@fluentui-react-native/use-slots 0.10.11 → 0.11.0
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 +15 -0
- package/CHANGELOG.md +46 -1
- package/babel.config.js +1 -1
- package/lib/buildUseSlots.d.ts +11 -10
- package/lib/buildUseSlots.d.ts.map +1 -1
- package/lib/buildUseSlots.js +16 -14
- package/lib/buildUseSlots.js.map +1 -1
- package/lib/buildUseSlots.test.d.ts +1 -1
- package/lib/buildUseSlots.test.js +27 -17
- package/lib/buildUseSlots.test.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/useSlots.samples.test.d.ts +1 -1
- package/lib/useSlots.samples.test.js +228 -187
- package/lib/useSlots.samples.test.js.map +1 -1
- package/lib-commonjs/buildUseSlots.d.ts +11 -10
- package/lib-commonjs/buildUseSlots.d.ts.map +1 -1
- package/lib-commonjs/buildUseSlots.js +20 -19
- package/lib-commonjs/buildUseSlots.js.map +1 -1
- package/lib-commonjs/buildUseSlots.test.d.ts +1 -1
- package/lib-commonjs/buildUseSlots.test.js +82 -45
- package/lib-commonjs/buildUseSlots.test.js.map +1 -1
- package/lib-commonjs/index.d.ts +1 -1
- package/lib-commonjs/index.js +10 -5
- package/lib-commonjs/index.js.map +1 -1
- package/lib-commonjs/useSlots.samples.test.d.ts +1 -1
- package/lib-commonjs/useSlots.samples.test.js +297 -215
- package/lib-commonjs/useSlots.samples.test.js.map +1 -1
- package/package.json +48 -41
- package/src/__snapshots__/useSlots.samples.test.tsx.snap +42 -42
- package/src/buildUseSlots.test.tsx +8 -5
- package/src/buildUseSlots.ts +8 -5
- package/src/useSlots.samples.test.tsx +42 -42
|
@@ -1,218 +1,259 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from '@fluentui-react-native/framework-base/jsx-runtime';
|
|
2
|
+
/** @jsxImportSource @fluentui-react-native/framework-base */
|
|
3
|
+
import { act } from 'react';
|
|
1
4
|
import { mergeProps } from '@fluentui-react-native/framework-base';
|
|
2
|
-
import {
|
|
5
|
+
import { phasedComponent } from '@fluentui-react-native/framework-base';
|
|
3
6
|
import * as renderer from 'react-test-renderer';
|
|
7
|
+
import { View, Text } from 'react-native';
|
|
4
8
|
import { buildUseSlots } from './buildUseSlots';
|
|
5
9
|
/**
|
|
6
10
|
* This file contains samples and description to help explain what the useSlots hook does and why it is useful
|
|
7
11
|
* for building components.
|
|
8
12
|
*/
|
|
9
13
|
describe('useSlots sample code test suite', () => {
|
|
14
|
+
/**
|
|
15
|
+
* The first mechanism to understand is the stagedComponent mechanic. This allows a component to be written, separating
|
|
16
|
+
* hook calls and component rendering. This allows it to be safely called as a function by a higher order component, even conditionally.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Example #1: Single level simple component ----------------------------------------
|
|
20
|
+
*
|
|
21
|
+
* First we are going to create a wrapped text component that bolds all text. One component will be authored as a staged
|
|
22
|
+
* component and one as a regular component.
|
|
23
|
+
*/
|
|
24
|
+
const boldBaseProps = { style: { fontWeight: 900 } };
|
|
25
|
+
/**
|
|
26
|
+
* First create the bold text in the standard way. This is just a function component.
|
|
27
|
+
*/
|
|
28
|
+
const BoldTextStandard = (props) => {
|
|
10
29
|
/**
|
|
11
|
-
*
|
|
12
|
-
* hook calls and component rendering. This allows it to be safely called as a function by a higher order component, even conditionally.
|
|
30
|
+
* Pick out the children to pass them on to the child Text element
|
|
13
31
|
*/
|
|
32
|
+
const { children, ...rest } = props;
|
|
14
33
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* First we are going to create a wrapped text component that bolds all text. One component will be authored as a staged
|
|
18
|
-
* component and one as a regular component.
|
|
34
|
+
* Now render the text, merging the baseProps with the style updates with the rest param. Note that this leverages the fact
|
|
35
|
+
* that mergeProps will reliably produce style objects with the same reference, given the same inputs.
|
|
19
36
|
*/
|
|
20
|
-
|
|
37
|
+
return _jsx(Text, { ...mergeProps(boldBaseProps, rest), children: children });
|
|
38
|
+
};
|
|
39
|
+
BoldTextStandard.displayName = 'BoldTextStandard';
|
|
40
|
+
/**
|
|
41
|
+
* To write the same component using the staged pattern is only slightly more complex. The pattern involves splitting the component rendering into
|
|
42
|
+
* two parts and executing any hooks in the first part.
|
|
43
|
+
*
|
|
44
|
+
* The phasedComponent function takes an input function of this form and wraps it in a function component that react knows how to render
|
|
45
|
+
*/
|
|
46
|
+
const BoldTextStaged = phasedComponent((props) => {
|
|
21
47
|
/**
|
|
22
|
-
*
|
|
48
|
+
* This section would be where hook/styling code would go, props here would include everything coming in from the base react tree with the
|
|
49
|
+
* exception of children, which will be passed in stage 2.
|
|
23
50
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* that mergeProps will reliably produce style objects with the same reference, given the same inputs.
|
|
32
|
-
*/
|
|
33
|
-
return withSlots("span", { ...mergeProps(boldBaseProps, rest) }, children);
|
|
51
|
+
return (extra) => {
|
|
52
|
+
/**
|
|
53
|
+
* extra are additional props that may be filled in by a higher order component. They should not include styling and are only props the
|
|
54
|
+
* enclosing component are passing to the JSX elements
|
|
55
|
+
*/
|
|
56
|
+
const { children, ...rest } = extra;
|
|
57
|
+
return _jsx(Text, { ...mergeProps(boldBaseProps, props, rest), children: children });
|
|
34
58
|
};
|
|
35
|
-
|
|
59
|
+
});
|
|
60
|
+
BoldTextStaged.displayName = 'BoldTextStaged';
|
|
61
|
+
it('renders sample 1 - the two types of basic bold text components', () => {
|
|
62
|
+
const styleToMerge = { color: 'black' };
|
|
36
63
|
/**
|
|
37
|
-
*
|
|
38
|
-
* two parts and executing any hooks in the first part.
|
|
39
|
-
*
|
|
40
|
-
* The stagedComponent function takes an input function of this form and wraps it in a function component that react knows how to render
|
|
64
|
+
* First render the staged component. This invokes the wrapper that was built by the stagedComponent function
|
|
41
65
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return withSlots("span", { ...mergeProps(boldBaseProps, props, extra) }, children);
|
|
53
|
-
};
|
|
54
|
-
});
|
|
55
|
-
BoldTextStaged.displayName = 'BoldTextStaged';
|
|
56
|
-
it('renders sample 1 - the two types of basic bold text components', () => {
|
|
57
|
-
const styleToMerge = { color: 'black' };
|
|
58
|
-
/**
|
|
59
|
-
* First render the staged component. This invokes the wrapper that was built by the stagedComponent function
|
|
60
|
-
*/
|
|
61
|
-
const wrapper = renderer
|
|
62
|
-
.create(withSlots("div", null,
|
|
63
|
-
withSlots(BoldTextStaged, { style: styleToMerge }, "Staged component at one level"),
|
|
64
|
-
withSlots(BoldTextStandard, { style: styleToMerge }, "Standard component of a single level")))
|
|
65
|
-
.toJSON();
|
|
66
|
-
expect(wrapper).toMatchSnapshot();
|
|
66
|
+
let component;
|
|
67
|
+
act(() => {
|
|
68
|
+
component = renderer.create(
|
|
69
|
+
_jsxs(View, {
|
|
70
|
+
children: [
|
|
71
|
+
_jsx(BoldTextStaged, { style: styleToMerge, children: 'Staged component at one level' }),
|
|
72
|
+
_jsx(BoldTextStandard, { style: styleToMerge, children: 'Standard component of a single level' }),
|
|
73
|
+
],
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
67
76
|
});
|
|
77
|
+
expect(component.toJSON()).toMatchSnapshot();
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* Example #2 - Simple component containing another simple component -------------------------------------
|
|
81
|
+
*
|
|
82
|
+
* Next we will build a layer on top of the previously authored components to turn the bold text components into header components. This is
|
|
83
|
+
* to illustrate the way in which components can be commonly built on top of other simpler components.
|
|
84
|
+
*/
|
|
85
|
+
const headerBaseProps = { style: { fontSize: 20 } };
|
|
86
|
+
/**
|
|
87
|
+
* The standard way of doing things is a repeat of what happens above. Grab the children, pass them on, merge the rest of the props with
|
|
88
|
+
* base props.
|
|
89
|
+
*
|
|
90
|
+
* This again leverages style merging via mergeProps to avoid changing the references of the style objects on every render
|
|
91
|
+
*/
|
|
92
|
+
const HeaderStandard = (props) => {
|
|
93
|
+
const { children, ...rest } = props;
|
|
94
|
+
return _jsx(BoldTextStandard, { ...mergeProps(headerBaseProps, rest), children: children });
|
|
95
|
+
};
|
|
96
|
+
HeaderStandard.displayName = 'HeaderStandard';
|
|
97
|
+
/**
|
|
98
|
+
* To consume the staged component we'll use the use slots hook builder. This allows easy consumption of staged components (or standard components)
|
|
99
|
+
* This will be described in more detail further on but in this case the component has a single child component, so it only has one slot that we
|
|
100
|
+
* will call 'text'
|
|
101
|
+
*
|
|
102
|
+
* This should be built once, and consumed by the component, not built on the fly inside
|
|
103
|
+
*/
|
|
104
|
+
const useHeaderSlots = buildUseSlots({ slots: { text: BoldTextStaged } });
|
|
105
|
+
/**
|
|
106
|
+
* Now author the staged component using the slot hook
|
|
107
|
+
*/
|
|
108
|
+
const HeaderStaged = phasedComponent((props) => {
|
|
68
109
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* to illustrate the way in which components can be commonly built on top of other simpler components.
|
|
73
|
-
*/
|
|
74
|
-
const headerBaseProps = { style: { fontSize: 20 } };
|
|
75
|
-
/**
|
|
76
|
-
* The standard way of doing things is a repeat of what happens above. Grab the children, pass them on, merge the rest of the props with
|
|
77
|
-
* base props.
|
|
110
|
+
* Call the slots hook (or any hook) outside of the inner closure. The useSlots hook will return an object with each slot as a renderable
|
|
111
|
+
* function. The hooks for sub-components will be called as part of this call. Props passed in at this point will be the props that appear
|
|
112
|
+
* in outer part of the staged component. (For this example `props`)
|
|
78
113
|
*
|
|
79
|
-
*
|
|
80
|
-
*/
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
114
|
+
* Note that while we are passing in props, in the simple usage case it isn't used and could be omitted if desired
|
|
115
|
+
* */
|
|
116
|
+
const BoldText = useHeaderSlots(props).text;
|
|
117
|
+
/** Now the inner closure, pretty much the same as before */
|
|
118
|
+
return (extra) => {
|
|
119
|
+
const { children, ...rest } = extra;
|
|
120
|
+
/**
|
|
121
|
+
* Instead of rendering the <BoldTextStageed> component directly we render using the slot. If this is a staged component it will call the
|
|
122
|
+
* inner closure directly, without going through createElement. Entries passed into the JSX, including children, are what appear in the
|
|
123
|
+
* props of the inner closure. (In this example `extra`)
|
|
124
|
+
*
|
|
125
|
+
* NOTE: this requires using the withSlots helper via the jsx directive. This knows how to pick apart the entries and just call the second
|
|
126
|
+
* part of the function
|
|
127
|
+
*/
|
|
128
|
+
return _jsx(BoldText, { ...mergeProps(headerBaseProps, props, rest), children: children });
|
|
84
129
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const useHeaderSlots = buildUseSlots({ slots: { text: BoldTextStaged } });
|
|
130
|
+
});
|
|
131
|
+
HeaderStaged.displayName = 'HeaderStaged';
|
|
132
|
+
/**
|
|
133
|
+
* Look at the snapshots to compare the rendered output. The staged component will skip the intermediate levels of the react hieararchy while
|
|
134
|
+
* still rendering to the correct primitives.
|
|
135
|
+
*/
|
|
136
|
+
it('renders sample 2 = the two types of two level header components', () => {
|
|
137
|
+
const styleToMerge = { color: 'black' };
|
|
94
138
|
/**
|
|
95
|
-
*
|
|
139
|
+
* First render the staged component. This invokes the wrapper that was built by the stagedComponent function
|
|
96
140
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return (extra, children) => {
|
|
108
|
-
/**
|
|
109
|
-
* Instead of rendering the <BoldTextStageed> component directly we render using the slot. If this is a staged component it will call the
|
|
110
|
-
* inner closure directly, without going through createElement. Entries passed into the JSX, including children, are what appear in the
|
|
111
|
-
* props of the inner closure. (In this example `extra`)
|
|
112
|
-
*
|
|
113
|
-
* NOTE: this requires using the withSlots helper via the jsx directive. This knows how to pick apart the entries and just call the second
|
|
114
|
-
* part of the function
|
|
115
|
-
*/
|
|
116
|
-
return withSlots(BoldText, { ...mergeProps(headerBaseProps, props, extra) }, children);
|
|
117
|
-
};
|
|
141
|
+
let component;
|
|
142
|
+
act(() => {
|
|
143
|
+
component = renderer.create(
|
|
144
|
+
_jsxs('div', {
|
|
145
|
+
children: [
|
|
146
|
+
_jsx(HeaderStaged, { style: styleToMerge, children: 'Staged component with two levels' }),
|
|
147
|
+
_jsx(HeaderStandard, { style: styleToMerge, children: 'Standard component with two levels' }),
|
|
148
|
+
],
|
|
149
|
+
}),
|
|
150
|
+
);
|
|
118
151
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
expect(component.toJSON()).toMatchSnapshot();
|
|
153
|
+
});
|
|
154
|
+
/** standard props for the container */
|
|
155
|
+
const containerProps = { style: { display: 'flex', flexDirection: 'column' } };
|
|
156
|
+
/**
|
|
157
|
+
* add a quick cache to ensure that we don't thrash the styles. This is a danger any time a value from a style is added as
|
|
158
|
+
* a prop on a component
|
|
159
|
+
*/
|
|
160
|
+
const colorProps = {};
|
|
161
|
+
const getColorProps = (value) => {
|
|
162
|
+
if (value !== undefined) {
|
|
163
|
+
colorProps[value] = colorProps[value] || { style: { color: value } };
|
|
164
|
+
return colorProps[value];
|
|
165
|
+
}
|
|
166
|
+
return {};
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* now just create the component like a standard react functional component
|
|
170
|
+
*/
|
|
171
|
+
const CaptionedHeaderStandard = (props) => {
|
|
172
|
+
const { headerColor, captionColor, captionText, children, ...rest } = props;
|
|
173
|
+
const headerColorProps = getColorProps(headerColor);
|
|
174
|
+
const captionColorProps = getColorProps(captionColor);
|
|
175
|
+
return _jsxs(View, {
|
|
176
|
+
...mergeProps(containerProps, rest),
|
|
177
|
+
children: [
|
|
178
|
+
_jsx(HeaderStandard, { ...headerColorProps, children: children }),
|
|
179
|
+
captionText && _jsx(BoldTextStandard, { ...captionColorProps, children: captionText }),
|
|
180
|
+
],
|
|
135
181
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
182
|
+
};
|
|
183
|
+
CaptionedHeaderStandard.displayName = `CaptionedHeaderStandard';`;
|
|
184
|
+
/**
|
|
185
|
+
* now build the same component using slots hook. This will also add use of the style injection pattern
|
|
186
|
+
*/
|
|
187
|
+
const useCaptionedHeaderSlots = buildUseSlots({
|
|
188
|
+
/** Slots are just like above, this component will have three sub-components */
|
|
189
|
+
slots: {
|
|
190
|
+
container: View,
|
|
191
|
+
header: HeaderStaged,
|
|
192
|
+
caption: BoldTextStaged,
|
|
193
|
+
},
|
|
194
|
+
/** useStyling is an optional function that turns props into props for the sub-components */
|
|
195
|
+
useStyling: (props) => ({
|
|
196
|
+
container: containerProps,
|
|
197
|
+
header: getColorProps(props.headerColor),
|
|
198
|
+
caption: getColorProps(props.captionColor),
|
|
199
|
+
}),
|
|
200
|
+
});
|
|
201
|
+
/** a mask to clear props that we don't want to pass to the inner view */
|
|
202
|
+
const clearCustomProps = { headerColor: undefined, captionColor: undefined };
|
|
203
|
+
/**
|
|
204
|
+
* now use the hook to implement it as a staged component
|
|
205
|
+
*/
|
|
206
|
+
const CaptionedHeaderStaged = phasedComponent((props) => {
|
|
207
|
+
// At the point where this is called the slots are initialized with the initial prop values from useStyling above
|
|
208
|
+
const Slots = useCaptionedHeaderSlots(props);
|
|
209
|
+
return (extra) => {
|
|
210
|
+
// merge the props together, picking out the caption text and clearing any custom values we don't want forwarded to the view
|
|
211
|
+
const { children, captionText, ...rest } = mergeProps(props, extra, clearCustomProps);
|
|
212
|
+
// now render using the slots. Any values passed in via JSX will be merged with values from the slot hook above
|
|
213
|
+
return _jsxs(Slots.container, {
|
|
214
|
+
...rest,
|
|
215
|
+
children: [_jsx(Slots.header, { children: children }), captionText && _jsx(Slots.caption, { children: captionText })],
|
|
216
|
+
});
|
|
149
217
|
};
|
|
218
|
+
});
|
|
219
|
+
CaptionedHeaderStaged.displayName = 'CaptionedHeaderStaged';
|
|
220
|
+
it('renders sample 3 - the two types of higher order header components', () => {
|
|
221
|
+
const styleToMerge = { backgroundColor: 'gray', borderColor: 'purple', borderWidth: 1 };
|
|
150
222
|
/**
|
|
151
|
-
*
|
|
223
|
+
* Render the two sets of components. Note in the snapshots how the render tree layers for the standard approach are starting
|
|
224
|
+
* to add up.
|
|
152
225
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
226
|
+
let component;
|
|
227
|
+
act(() => {
|
|
228
|
+
component = renderer.create(
|
|
229
|
+
_jsxs('div', {
|
|
230
|
+
children: [
|
|
231
|
+
_jsx('span', { children: '--- SIMPLE USAGE COMPARISON ---' }),
|
|
232
|
+
_jsx(CaptionedHeaderStandard, { style: styleToMerge, children: 'Standard HOC' }),
|
|
233
|
+
_jsx(CaptionedHeaderStaged, { style: styleToMerge, children: 'Staged HOC' }),
|
|
234
|
+
_jsx('span', { children: '--- COMPARISON WITH CAPTIONS ---' }),
|
|
235
|
+
_jsx(CaptionedHeaderStandard, { style: styleToMerge, captionText: 'Caption text', children: 'Standard HOC with Caption' }),
|
|
236
|
+
_jsx(CaptionedHeaderStaged, { style: styleToMerge, captionText: 'Caption text', children: 'Staged HOC with Caption' }),
|
|
237
|
+
_jsx('span', { children: '--- COMPARISON WITH CAPTIONS AND CUSTOMIZATIONS ---' }),
|
|
238
|
+
_jsx(CaptionedHeaderStandard, {
|
|
239
|
+
style: styleToMerge,
|
|
240
|
+
captionText: 'Caption text',
|
|
241
|
+
captionColor: 'yellow',
|
|
242
|
+
headerColor: 'red',
|
|
243
|
+
children: 'Standard HOC with caption and customizations',
|
|
244
|
+
}),
|
|
245
|
+
_jsx(CaptionedHeaderStaged, {
|
|
246
|
+
style: styleToMerge,
|
|
247
|
+
captionText: 'Caption text',
|
|
248
|
+
captionColor: 'yellow',
|
|
249
|
+
headerColor: 'red',
|
|
250
|
+
children: 'Staged HOC with caption and customizations',
|
|
251
|
+
}),
|
|
252
|
+
],
|
|
177
253
|
}),
|
|
254
|
+
);
|
|
178
255
|
});
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* now use the hook to implement it as a staged component
|
|
183
|
-
*/
|
|
184
|
-
const CaptionedHeaderStaged = stagedComponent((props) => {
|
|
185
|
-
// At the point where this is called the slots are initialized with the initial prop values from useStyling above
|
|
186
|
-
const Slots = useCaptionedHeaderSlots(props);
|
|
187
|
-
return (extra, children) => {
|
|
188
|
-
// merge the props together, picking out the caption text and clearing any custom values we don't want forwarded to the view
|
|
189
|
-
const { captionText, ...rest } = mergeProps(props, extra, clearCustomProps);
|
|
190
|
-
// now render using the slots. Any values passed in via JSX will be merged with values from the slot hook above
|
|
191
|
-
return (withSlots(Slots.container, { ...rest },
|
|
192
|
-
withSlots(Slots.header, null, children),
|
|
193
|
-
captionText && withSlots(Slots.caption, null, captionText)));
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
CaptionedHeaderStaged.displayName = 'CaptionedHeaderStaged';
|
|
197
|
-
it('renders sample 3 - the two types of higher order header components', () => {
|
|
198
|
-
const styleToMerge = { backgroundColor: 'gray', borderColor: 'purple', borderWidth: 1 };
|
|
199
|
-
/**
|
|
200
|
-
* Render the two sets of components. Note in the snapshots how the render tree layers for the standard approach are starting
|
|
201
|
-
* to add up.
|
|
202
|
-
*/
|
|
203
|
-
const wrapper = renderer
|
|
204
|
-
.create(withSlots("div", null,
|
|
205
|
-
withSlots("span", null, "--- SIMPLE USAGE COMPARISON ---"),
|
|
206
|
-
withSlots(CaptionedHeaderStandard, { style: styleToMerge }, "Standard HOC"),
|
|
207
|
-
withSlots(CaptionedHeaderStaged, { style: styleToMerge }, "Staged HOC"),
|
|
208
|
-
withSlots("span", null, "--- COMPARISON WITH CAPTIONS ---"),
|
|
209
|
-
withSlots(CaptionedHeaderStandard, { style: styleToMerge, captionText: "Caption text" }, "Standard HOC with Caption"),
|
|
210
|
-
withSlots(CaptionedHeaderStaged, { style: styleToMerge, captionText: "Caption text" }, "Staged HOC with Caption"),
|
|
211
|
-
withSlots("span", null, "--- COMPARISON WITH CAPTIONS AND CUSTOMIZATIONS ---"),
|
|
212
|
-
withSlots(CaptionedHeaderStandard, { style: styleToMerge, captionText: "Caption text", captionColor: "yellow", headerColor: "red" }, "Standard HOC with caption and customizations"),
|
|
213
|
-
withSlots(CaptionedHeaderStaged, { style: styleToMerge, captionText: "Caption text", captionColor: "yellow", headerColor: "red" }, "Staged HOC with caption and customizations")))
|
|
214
|
-
.toJSON();
|
|
215
|
-
expect(wrapper).toMatchSnapshot();
|
|
216
|
-
});
|
|
256
|
+
expect(component.toJSON()).toMatchSnapshot();
|
|
257
|
+
});
|
|
217
258
|
});
|
|
218
|
-
//# sourceMappingURL=useSlots.samples.test.js.map
|
|
259
|
+
//# sourceMappingURL=useSlots.samples.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlots.samples.test.js","sourceRoot":"","sources":["../src/useSlots.samples.test.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useSlots.samples.test.js","sourceRoot":"","sources":["../src/useSlots.samples.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type ComponentType } from '@fluentui-react-native/use-slot';
|
|
2
|
+
import type { FunctionComponent, PropsFilter } from '@fluentui-react-native/framework-base';
|
|
2
3
|
export type Slots<TSlotProps> = {
|
|
3
|
-
|
|
4
|
+
[K in keyof TSlotProps]: FunctionComponent<TSlotProps[K]>;
|
|
4
5
|
};
|
|
5
6
|
export type UseSlotOptions<TSlotProps> = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
slots: {
|
|
8
|
+
[K in keyof TSlotProps]: ComponentType<TSlotProps[K]>;
|
|
9
|
+
};
|
|
10
|
+
filters?: {
|
|
11
|
+
[K in keyof TSlotProps]?: PropsFilter;
|
|
12
|
+
};
|
|
13
|
+
useStyling?: TSlotProps | GetSlotProps<TSlotProps>;
|
|
13
14
|
};
|
|
14
15
|
export type GetSlotProps<TSlotProps> = (...args: any[]) => TSlotProps;
|
|
15
16
|
export type UseSlotsBase<TSlotProps> = (...args: any[]) => Slots<TSlotProps>;
|
|
16
17
|
export declare function buildUseSlots<TSlotProps>(options: UseSlotOptions<TSlotProps>): UseSlotsBase<TSlotProps>;
|
|
17
|
-
//# sourceMappingURL=buildUseSlots.d.ts.map
|
|
18
|
+
//# sourceMappingURL=buildUseSlots.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildUseSlots.d.ts","sourceRoot":"","sources":["../src/buildUseSlots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"buildUseSlots.d.ts","sourceRoot":"","sources":["../src/buildUseSlots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAS5F,MAAM,MAAM,KAAK,CAAC,UAAU,IAAI;KAAG,CAAC,IAAI,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAE9F,MAAM,MAAM,cAAc,CAAC,UAAU,IAAI;IACvC,KAAK,EAAE;SAAG,CAAC,IAAI,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IACjE,OAAO,CAAC,EAAE;SAAG,CAAC,IAAI,MAAM,UAAU,CAAC,CAAC,EAAE,WAAW;KAAE,CAAC;IACpD,UAAU,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,UAAU,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,UAAU,CAAC;AAEtE,MAAM,MAAM,YAAY,CAAC,UAAU,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;AAE7E,wBAAgB,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAqBvG"}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports,
|
|
3
|
-
exports.buildUseSlots =
|
|
4
|
-
const use_slot_1 = require(
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.buildUseSlots = buildUseSlots;
|
|
4
|
+
const use_slot_1 = require('@fluentui-react-native/use-slot');
|
|
5
5
|
function buildUseSlots(options) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
const { slots, filters = {}, useStyling } = options;
|
|
7
|
+
return (...args) => {
|
|
8
|
+
// get the baseline slot props to render with the slots
|
|
9
|
+
const slotProps = typeof useStyling === 'function' ? useStyling(...args) : useStyling || {};
|
|
10
|
+
// build up a set of slots closures and store them in props
|
|
11
|
+
const builtSlots = {};
|
|
12
|
+
// for each slot go through and either cache the slot props or call part one render if it is staged
|
|
13
|
+
// note: changing this to a for..in loop causes rule of hooks violations
|
|
14
|
+
// eslint-disable-next-line @rnx-kit/no-foreach-with-captured-variables
|
|
15
|
+
Object.keys(slots).forEach((slotName) => {
|
|
16
|
+
builtSlots[slotName] = (0, use_slot_1.useSlot)(slots[slotName], slotProps[slotName], filters[slotName]);
|
|
17
|
+
});
|
|
18
|
+
// return the prebuilt closures, these will have internal references to state.results
|
|
19
|
+
return builtSlots;
|
|
20
|
+
};
|
|
19
21
|
}
|
|
20
|
-
|
|
21
|
-
//# sourceMappingURL=buildUseSlots.js.map
|
|
22
|
+
//# sourceMappingURL=buildUseSlots.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildUseSlots.js","sourceRoot":"","sources":["../src/buildUseSlots.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"buildUseSlots.js","sourceRoot":"","sources":["../src/buildUseSlots.ts"],"names":[],"mappings":";;;AAAA,8DAA8E;AAsB9E,uBAA0C,OAAmC,EAA4B;IACvG,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IACpD,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE,CAAC;QACzB,uDAAuD;QACvD,MAAM,SAAS,GACb,OAAO,UAAU,KAAK,UAAU,CAAC,CAAC,CAAE,UAAqC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,UAAU,IAAI,EAAE,CAAgB,CAAC;QAE1H,2DAA2D;QAC3D,MAAM,UAAU,GAAsB,EAAuB,CAAC;QAE9D,mGAAmG;QAEnG,wEAAwE;QACxE,uEAAuE;QACvE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;YACvC,UAAU,CAAC,QAAQ,CAAC,GAAG,IAAA,kBAAO,EAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAA,CACzF,CAAC,CAAC;QAEH,qFAAqF;QACrF,OAAO,UAAU,CAAC;IAAA,CACnB,CAAC;AAAA,CACH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=buildUseSlots.test.d.ts.map
|
|
2
|
+
//# sourceMappingURL=buildUseSlots.test.d.ts.map
|