Skip to content

Commit 57c12f4

Browse files
authored
Fixed TS errors and created "withDefaultProps" HOC for class components (#65)
* withDefaultProps HOC for class components Fab and Mention components were updated to get theme defaultProps working * Fixed TS errors
1 parent 1c4053d commit 57c12f4

11 files changed

+91
-46
lines changed

example/src/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const theme: Partial<ThemeType> = {
2727
fontSize: 'lg',
2828
textTransform: 'uppercase',
2929
},
30+
Fab: {
31+
bg: 'red500',
32+
},
3033
},
3134

3235
colors: {

src/ui/checkbox/group.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CheckboxGroupProps } from './checkbox.type';
88
const CheckboxGroup: React.FunctionComponent<CheckboxGroupProps> = (
99
incomingProps
1010
) => {
11-
const props = useDefaultProps('CheckboxGroup', incomingProps);
11+
const props = useDefaultProps('CheckboxGroup', incomingProps, {});
1212

1313
const [value, setValue] = useState(props.value || props.defaultValue || []);
1414
const {

src/ui/collapse/collapse.component.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { CollapseGroup } from './group.component';
1212
const Collapse: CompoundedCollapse<CollapseProps> = (incomingProps) => {
1313
const props = useDefaultProps('Collapse', incomingProps, {
1414
bg: 'white',
15+
active: false,
1516
flexDir: 'column',
1617
flexWrap: 'nowrap',
1718
rounded: 'md',

src/ui/collapse/group.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CollapseGroupProps } from './collapse.type';
88
const CollapseGroup: React.FunctionComponent<CollapseGroupProps> = (
99
incomingProps
1010
) => {
11-
const props = useDefaultProps('CollapseGroup', incomingProps);
11+
const props = useDefaultProps('CollapseGroup', incomingProps, {});
1212

1313
const [activeId, setActiveId] = useState(props.defaultActive || null);
1414
const { children, onChange: onChangeProp, ...rest } = props;

src/ui/fab/fab.component.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,45 @@ import { ThemeContext, ThemeType } from '../../theme';
1313
import { Button } from '../button/button.component';
1414
import { Icon } from '../icon/icon.component';
1515
import { FabProps } from './fab.type';
16+
import { withDefaultProps } from '../../utilities/withDefaultProps';
1617

1718
interface FabState {
1819
active: boolean;
1920
}
2021

21-
class Fab extends React.Component<FabProps, FabState> {
22-
static defaultProps: Partial<FabProps> = {
23-
color: 'white',
24-
fontSize: '4xl',
25-
p: 18,
26-
overlayColor: 'gray900',
27-
overlayOpacity: 0.5,
28-
position: 'absolute',
29-
openOnMount: false,
30-
showBackground: true,
31-
animated: true,
32-
bottom: 30,
33-
right: 30,
34-
icon: 'plus',
35-
activeIcon: 'close',
36-
rounded: 'circle',
37-
bg: 'blue500',
38-
useNativeDriver: false,
39-
shadow: 'lg',
40-
shadowColor: 'gray900',
41-
};
42-
22+
const defaultProps = {
23+
color: 'white',
24+
fontSize: '4xl',
25+
p: 18,
26+
overlayColor: 'gray900',
27+
overlayOpacity: 0.5,
28+
position: 'absolute',
29+
openOnMount: false,
30+
showBackground: true,
31+
animated: true,
32+
bottom: 30,
33+
right: 30,
34+
icon: 'plus',
35+
activeIcon: 'close',
36+
rounded: 'circle',
37+
bg: 'blue500',
38+
useNativeDriver: false,
39+
shadow: 'lg',
40+
shadowColor: 'gray900',
41+
} as const;
42+
43+
class FabBase extends React.Component<
44+
FabProps & typeof defaultProps,
45+
FabState
46+
> {
4347
animation: any;
4448
fadeAnimation: any;
4549
visibleAnimation: any;
4650
actionsAnimation: any;
4751
mainBottomAnimation: any;
4852
actionsBottomAnimation: any;
4953

50-
constructor(props: FabProps) {
54+
constructor(props: FabProps & typeof defaultProps) {
5155
super(props);
5256

5357
this.state = {
@@ -363,4 +367,6 @@ class Fab extends React.Component<FabProps, FabState> {
363367
}
364368
}
365369

370+
const Fab = withDefaultProps<FabProps>(FabBase, 'Fab')(defaultProps);
371+
366372
export { Fab };

src/ui/image/image.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ThemeContext } from '../../theme';
88
import { useDefaultProps } from '../../utilities/useDefaultProps';
99

1010
const Image: React.FunctionComponent<ImageProps> = (incomingProps) => {
11-
const props = useDefaultProps('Image', incomingProps);
11+
const props = useDefaultProps('Image', incomingProps, {});
1212

1313
const {
1414
h,

src/ui/mention/mention.component.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,25 @@ import { View, FlatList, ActivityIndicator } from 'react-native';
55
import { MentionProps } from './mention.type';
66
import { getStyle } from './mention.style';
77
import { ThemeContext } from '../../theme';
8-
9-
class Mention extends React.Component<MentionProps> {
10-
static defaultProps = {
11-
bg: 'white',
12-
rounded: 'md',
13-
borderColor: 'gray200',
14-
borderWidth: 1,
15-
horizontal: false,
16-
loading: false,
17-
shadow: 1,
18-
shadowColor: 'gray900',
19-
keyboardShouldPersistTaps: 'always',
20-
trigger: '@',
21-
position: 'absolute',
22-
bottom: '100%',
23-
onHide: () => {},
24-
};
25-
8+
import { withDefaultProps } from '../../utilities/withDefaultProps';
9+
10+
const defaultProps = {
11+
bg: 'white',
12+
rounded: 'md',
13+
borderColor: 'gray200',
14+
borderWidth: 1,
15+
horizontal: false,
16+
loading: false,
17+
shadow: 1,
18+
shadowColor: 'gray900',
19+
keyboardShouldPersistTaps: 'always',
20+
trigger: '@',
21+
position: 'absolute',
22+
bottom: '100%',
23+
onHide: () => {},
24+
} as const;
25+
26+
class MentionBase extends React.Component<MentionProps & typeof defaultProps> {
2627
previousChar = ' ';
2728

2829
isTrackingStarted = false;
@@ -183,4 +184,6 @@ class Mention extends React.Component<MentionProps> {
183184
}
184185
}
185186

187+
const Mention = withDefaultProps(MentionBase, 'Mention')(defaultProps);
188+
186189
export { Mention };

src/ui/radio/group.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useDefaultProps } from '../../utilities/useDefaultProps';
88
const RadioGroup: React.FunctionComponent<RadioGroupProps> = (
99
incomingProps
1010
) => {
11-
const props = useDefaultProps('RadioGroup', incomingProps);
11+
const props = useDefaultProps('RadioGroup', incomingProps, {});
1212

1313
const [value, setValue] = useState(props.value || props.defaultValue || null);
1414
const {

src/ui/radio/radio.component.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const Radio: CompoundedRadio<RadioProps> = (incomingProps) => {
2525
highlightBg: 'gray300',
2626
bg: 'transparent',
2727
p: 'none',
28+
checked: false,
2829
color: 'white',
2930
rounded: 'circle',
3031
loading: false,

src/utilities/withDefaultProps.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
import deepmerge from 'deepmerge';
3+
import { ThemeContext, ThemeType } from '../theme';
4+
5+
export function withDefaultProps<T>(
6+
WrappedComponent: unknown,
7+
componentName: keyof NonNullable<ThemeType['components']>
8+
) {
9+
return function wrapWithStyledComponent(defaultProps: Partial<T>) {
10+
return class extends React.PureComponent {
11+
static contextType = ThemeContext;
12+
context!: React.ContextType<typeof ThemeContext>;
13+
14+
render() {
15+
const theme = this.context.theme;
16+
// @ts-ignore
17+
const propsFromTheme: Partial<T> =
18+
(theme.components && theme.components[componentName]) ?? {};
19+
20+
// @ts-ignore
21+
const mergedProps: T & Required<typeof defaultProps> = deepmerge(
22+
deepmerge(defaultProps, propsFromTheme),
23+
this.props
24+
);
25+
// @ts-ignore
26+
return <WrappedComponent {...mergedProps} />;
27+
}
28+
};
29+
};
30+
}

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"resolveJsonModule": true,
2222
"skipLibCheck": true,
2323
"strict": true,
24-
"target": "esnext"
24+
"target": "esnext",
25+
"types": ["react-native"]
2526
}
2627
}

0 commit comments

Comments
 (0)