@fluentui-react-native/composition 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +601 -0
- package/CHANGELOG.md +173 -0
- package/README.md +1 -0
- package/babel.config.js +1 -0
- package/just.config.js +3 -0
- package/lib/composeFactory.d.ts +26 -0
- package/lib/composeFactory.d.ts.map +1 -0
- package/lib/composeFactory.js +52 -0
- package/lib/composeFactory.js.map +1 -0
- package/lib/composeFactory.test.d.ts +2 -0
- package/lib/composeFactory.test.d.ts.map +1 -0
- package/lib/composeFactory.test.js +72 -0
- package/lib/composeFactory.test.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib-commonjs/composeFactory.d.ts +26 -0
- package/lib-commonjs/composeFactory.d.ts.map +1 -0
- package/lib-commonjs/composeFactory.js +55 -0
- package/lib-commonjs/composeFactory.js.map +1 -0
- package/lib-commonjs/composeFactory.test.d.ts +2 -0
- package/lib-commonjs/composeFactory.test.d.ts.map +1 -0
- package/lib-commonjs/composeFactory.test.js +81 -0
- package/lib-commonjs/composeFactory.test.js.map +1 -0
- package/lib-commonjs/index.d.ts +2 -0
- package/lib-commonjs/index.d.ts.map +1 -0
- package/lib-commonjs/index.js +7 -0
- package/lib-commonjs/index.js.map +1 -0
- package/package.json +44 -0
- package/src/__snapshots__/composeFactory.test.tsx.snap +49 -0
- package/src/composeFactory.test.tsx +94 -0
- package/src/composeFactory.ts +90 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`composeFactory test suite Base component render 1`] = `
|
|
4
|
+
<View
|
|
5
|
+
style={
|
|
6
|
+
Object {
|
|
7
|
+
"backgroundColor": "black",
|
|
8
|
+
"borderColor": "green",
|
|
9
|
+
"borderWidth": 1,
|
|
10
|
+
"height": 20,
|
|
11
|
+
"width": 30,
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
>
|
|
15
|
+
<Text
|
|
16
|
+
style={
|
|
17
|
+
Object {
|
|
18
|
+
"color": "white",
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
>
|
|
22
|
+
Hello
|
|
23
|
+
</Text>
|
|
24
|
+
</View>
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
exports[`composeFactory test suite Base component render 2`] = `
|
|
28
|
+
<View
|
|
29
|
+
style={
|
|
30
|
+
Object {
|
|
31
|
+
"backgroundColor": "pink",
|
|
32
|
+
"borderColor": "green",
|
|
33
|
+
"borderWidth": 1,
|
|
34
|
+
"height": 20,
|
|
35
|
+
"width": 30,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
>
|
|
39
|
+
<Text
|
|
40
|
+
style={
|
|
41
|
+
Object {
|
|
42
|
+
"color": "white",
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
>
|
|
46
|
+
Hello
|
|
47
|
+
</Text>
|
|
48
|
+
</View>
|
|
49
|
+
`;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** @jsx withSlots */
|
|
2
|
+
import { withSlots } from '@fluentui-react-native/use-slot';
|
|
3
|
+
import * as renderer from 'react-test-renderer';
|
|
4
|
+
import { composeFactory, UseStyledSlots } from './composeFactory';
|
|
5
|
+
import { ViewProps, View, Text, TextProps, ColorValue } from 'react-native';
|
|
6
|
+
import { ThemeHelper } from '@fluentui-react-native/use-styling';
|
|
7
|
+
|
|
8
|
+
type Theme = {
|
|
9
|
+
values: {
|
|
10
|
+
backgroundColor?: ColorValue;
|
|
11
|
+
color?: ColorValue;
|
|
12
|
+
};
|
|
13
|
+
components: {
|
|
14
|
+
[key: string]: object;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const theme: Theme = {
|
|
19
|
+
values: {
|
|
20
|
+
backgroundColor: 'black',
|
|
21
|
+
color: 'white',
|
|
22
|
+
},
|
|
23
|
+
components: {},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type SlotProps = {
|
|
27
|
+
outer: ViewProps;
|
|
28
|
+
content: TextProps;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type Tokens = {
|
|
32
|
+
backgroundColor?: ColorValue;
|
|
33
|
+
color?: ColorValue;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const themeHelper: ThemeHelper<Theme> = {
|
|
37
|
+
useTheme: () => theme,
|
|
38
|
+
getComponentInfo: (theme: Theme, name: string) => {
|
|
39
|
+
return theme?.components ?? theme.components[name];
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
function mergeProps<T>(p1: T, p2: T): T {
|
|
44
|
+
return { ...p1, ...p2 };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const Base = composeFactory<ViewProps, SlotProps, Tokens, Theme>(
|
|
48
|
+
{
|
|
49
|
+
tokens: [
|
|
50
|
+
(t) => ({
|
|
51
|
+
backgroundColor: t.values.backgroundColor,
|
|
52
|
+
color: t.values.color,
|
|
53
|
+
}),
|
|
54
|
+
],
|
|
55
|
+
slotProps: {
|
|
56
|
+
outer: (tokens) => ({ style: { backgroundColor: tokens.backgroundColor } }),
|
|
57
|
+
content: (tokens) => ({ style: { color: tokens.color } }),
|
|
58
|
+
},
|
|
59
|
+
slots: {
|
|
60
|
+
outer: View,
|
|
61
|
+
content: Text,
|
|
62
|
+
},
|
|
63
|
+
render: (props: ViewProps, useSlots: UseStyledSlots<ViewProps, SlotProps>) => {
|
|
64
|
+
const Slots = useSlots(props);
|
|
65
|
+
return (extra: ViewProps) => (
|
|
66
|
+
<Slots.outer {...mergeProps(props, extra)}>
|
|
67
|
+
<Slots.content>Hello</Slots.content>
|
|
68
|
+
</Slots.outer>
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
themeHelper,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const Customized = Base.customize({ backgroundColor: 'pink' });
|
|
76
|
+
|
|
77
|
+
const mixinStyle = {
|
|
78
|
+
width: 30,
|
|
79
|
+
height: 20,
|
|
80
|
+
borderColor: 'green',
|
|
81
|
+
borderWidth: 1,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
describe('composeFactory test suite', () => {
|
|
85
|
+
it('Base component render', () => {
|
|
86
|
+
const tree = renderer.create(<Base style={mixinStyle} />).toJSON();
|
|
87
|
+
expect(tree).toMatchSnapshot();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('Base component render', () => {
|
|
91
|
+
const tree = renderer.create(<Customized style={mixinStyle} />).toJSON();
|
|
92
|
+
expect(tree).toMatchSnapshot();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { UseStylingOptions, TokenSettings, ThemeHelper, HasLayer, buildUseStyling } from '@fluentui-react-native/use-styling';
|
|
2
|
+
import { ComposableFunction, stagedComponent } from '@fluentui-react-native/use-slot';
|
|
3
|
+
import { UseSlotOptions, buildUseSlots, Slots } from '@fluentui-react-native/use-slots';
|
|
4
|
+
import { immutableMergeCore, MergeOptions } from '@fluentui-react-native/immutable-merge';
|
|
5
|
+
|
|
6
|
+
export type UseStyledSlots<TProps, TSlotProps> = (props: TProps, lookup?: HasLayer) => Slots<TSlotProps>;
|
|
7
|
+
|
|
8
|
+
export type ComposeFactoryOptions<TProps, TSlotProps, TTokens, TTheme, TStatics extends object = object> = UseStylingOptions<
|
|
9
|
+
TProps,
|
|
10
|
+
TSlotProps,
|
|
11
|
+
TTokens,
|
|
12
|
+
TTheme
|
|
13
|
+
> &
|
|
14
|
+
UseSlotOptions<TSlotProps> & {
|
|
15
|
+
/**
|
|
16
|
+
* Includes from UseStylingOptions:
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
displayName?: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* staged render function that takes props and a useSlots hook as an input
|
|
23
|
+
*/
|
|
24
|
+
render: (props: TProps, useSlots: UseStyledSlots<TProps, TSlotProps>) => React.FunctionComponent<TProps>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* optional statics to attach to the component
|
|
28
|
+
*/
|
|
29
|
+
statics?: TStatics;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics extends object = object> = ComposableFunction<TProps> & {
|
|
33
|
+
__options: ComposeFactoryOptions<TProps, TSlotProps, TTokens, TTheme, TStatics>;
|
|
34
|
+
customize: (...tokens: TokenSettings<TTokens, TTheme>[]) => ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics>;
|
|
35
|
+
compose: (
|
|
36
|
+
options: Partial<ComposeFactoryOptions<TProps, TSlotProps, TTokens, TTheme, TStatics>>,
|
|
37
|
+
) => ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics>;
|
|
38
|
+
} & TStatics;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* options get deep merged except the tokens array gets appended
|
|
42
|
+
*/
|
|
43
|
+
const mergeOptions: MergeOptions = {
|
|
44
|
+
tokens: 'appendArray',
|
|
45
|
+
object: true,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export function composeFactory<TProps, TSlotProps, TTokens, TTheme, TStatics extends object = object>(
|
|
49
|
+
options: ComposeFactoryOptions<TProps, TSlotProps, TTokens, TTheme, TStatics>,
|
|
50
|
+
themeHelper: ThemeHelper<TTheme>,
|
|
51
|
+
base?: ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics>,
|
|
52
|
+
): ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics> {
|
|
53
|
+
type LocalComponent = ComposeFactoryComponent<TProps, TSlotProps, TTokens, TTheme, TStatics>;
|
|
54
|
+
type LocalOptions = ComposeFactoryOptions<TProps, TSlotProps, TTokens, TTheme, TStatics>;
|
|
55
|
+
|
|
56
|
+
// merge options together if a base is specified
|
|
57
|
+
const baseOptions: LocalOptions = base?.__options as LocalOptions;
|
|
58
|
+
options = baseOptions ? immutableMergeCore<LocalOptions>(mergeOptions, baseOptions, options) : { ...options };
|
|
59
|
+
|
|
60
|
+
// build styling if styling options are specified
|
|
61
|
+
options.useStyling = options.slotProps || options.tokens ? buildUseStyling(options, themeHelper) : () => ({} as TSlotProps);
|
|
62
|
+
|
|
63
|
+
// build the slots hook, which will use the styling hook if it has been built
|
|
64
|
+
const useSlots = buildUseSlots(options) as UseStyledSlots<TProps, TSlotProps>;
|
|
65
|
+
|
|
66
|
+
// build the staged component
|
|
67
|
+
const component = stagedComponent<TProps>((props) => options.render(props, useSlots)) as LocalComponent;
|
|
68
|
+
|
|
69
|
+
// attach additional props to the returned component
|
|
70
|
+
component.displayName = options.displayName;
|
|
71
|
+
component.__options = options;
|
|
72
|
+
component.customize = (...tokens: LocalOptions['tokens']) =>
|
|
73
|
+
composeFactory<TProps, TSlotProps, TTokens, TTheme, TStatics>(
|
|
74
|
+
immutableMergeCore(mergeOptions, options, { tokens: tokens } as LocalOptions),
|
|
75
|
+
themeHelper,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
component.compose = (customOptions: Partial<LocalOptions>) =>
|
|
79
|
+
composeFactory<TProps, TSlotProps, TTokens, TTheme, TStatics>(
|
|
80
|
+
immutableMergeCore(mergeOptions, options, customOptions) as LocalOptions,
|
|
81
|
+
themeHelper,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// attach statics if specified
|
|
85
|
+
if (options.statics) {
|
|
86
|
+
Object.assign(component, options.statics);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return component;
|
|
90
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './composeFactory';
|