@aws-amplify/ui-react-core 3.0.30 → 3.1.1
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/dist/elements.js +116 -3
- package/dist/esm/elements/ControlsContext.mjs +71 -0
- package/dist/esm/elements/ElementsContext.mjs +3 -2
- package/dist/esm/elements/defineBaseElement.mjs +30 -1
- package/dist/esm/elements/utils.mjs +11 -0
- package/dist/esm/elements/withBaseElementProps.mjs +1 -1
- package/dist/esm/elements.mjs +3 -1
- package/dist/esm/hooks/useDataState.mjs +10 -4
- package/dist/esm/utils/createContextUtilities.mjs +6 -3
- package/dist/index.js +15 -7
- package/dist/types/elements/ControlsContext.d.ts +63 -0
- package/dist/types/elements/ElementsContext.d.ts +3 -2
- package/dist/types/elements/defineBaseElement.d.ts +19 -2
- package/dist/types/elements/index.d.ts +4 -1
- package/dist/types/elements/types.d.ts +88 -6
- package/dist/types/elements/utils.d.ts +3 -0
- package/dist/types/elements/withBaseElementProps.d.ts +3 -3
- package/dist/types/hooks/index.d.ts +1 -1
- package/dist/types/hooks/useDataState.d.ts +6 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/utils/createContextUtilities.d.ts +1 -1
- package/package.json +3 -3
- package/src/elements/ControlsContext.tsx +89 -0
- package/src/elements/ElementsContext.tsx +3 -2
- package/src/elements/defineBaseElement.tsx +50 -2
- package/src/elements/index.ts +7 -1
- package/src/elements/types.ts +114 -6
- package/src/elements/utils.ts +20 -0
- package/src/elements/withBaseElementProps.tsx +3 -3
- package/src/hooks/index.ts +6 -1
- package/src/hooks/useDataState.ts +25 -7
- package/src/index.ts +2 -0
- package/src/utils/createContextUtilities.tsx +9 -6
package/dist/elements.js
CHANGED
|
@@ -8,13 +8,91 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
8
8
|
|
|
9
9
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
10
|
|
|
11
|
+
function isComponent(component) {
|
|
12
|
+
return typeof component === 'function';
|
|
13
|
+
}
|
|
14
|
+
function isForwardRefExoticComponent(component) {
|
|
15
|
+
return (typeof component === 'object' &&
|
|
16
|
+
typeof component.$$typeof ===
|
|
17
|
+
'symbol' &&
|
|
18
|
+
['react.memo', 'react.forward_ref'].includes(component.$$typeof.description));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @internal @unstable
|
|
23
|
+
*/
|
|
24
|
+
const ControlsContext = React__default["default"].createContext(undefined);
|
|
25
|
+
/**
|
|
26
|
+
* @internal @unstable
|
|
27
|
+
*
|
|
28
|
+
* `ControlsProvider` provides the values contained in `ControlsContext`
|
|
29
|
+
* to consumers. `ControlsContext` lookup is handled directly
|
|
30
|
+
* by `Control` components returned by `withControls`.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
*
|
|
34
|
+
* Add `ControlsContext` aware `Controls` components to a Connected
|
|
35
|
+
* Component:
|
|
36
|
+
*
|
|
37
|
+
* ```tsx
|
|
38
|
+
* const DataList = withControls(function DataList<T>(data: T[]) {
|
|
39
|
+
* return <ScrollView>data.map(ListItem)</ScrollView>;
|
|
40
|
+
* }, 'DataList');
|
|
41
|
+
*
|
|
42
|
+
* const DataListControl = () => {
|
|
43
|
+
* const data = useData();
|
|
44
|
+
* return <DataList data={data} />;
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* interface ComponentControls {
|
|
48
|
+
* DataList: typeof DataListControl;
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* function Component<T extends ComponentControls>(
|
|
52
|
+
* controls?: T
|
|
53
|
+
* ) {
|
|
54
|
+
* function ConnectedComponent({
|
|
55
|
+
* children,
|
|
56
|
+
* }: { children?: React.ReactNode }) {
|
|
57
|
+
* return (
|
|
58
|
+
* <ControlsProvider controls={controls}>
|
|
59
|
+
* {children}
|
|
60
|
+
* </ControlsProvider>
|
|
61
|
+
* );
|
|
62
|
+
* }
|
|
63
|
+
*
|
|
64
|
+
* return ConnectedComponent;
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
function ControlsProvider({ controls, ...props }) {
|
|
69
|
+
return React__default["default"].createElement(ControlsContext.Provider, { ...props, value: controls });
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* @internal @unstable
|
|
73
|
+
*
|
|
74
|
+
* @note reference `ControlsProvider` for example usage
|
|
75
|
+
*/
|
|
76
|
+
function withControls(Default, name) {
|
|
77
|
+
const Component = (props) => {
|
|
78
|
+
const Override = React__default["default"].useContext(ControlsContext)?.[name];
|
|
79
|
+
if (isComponent(Override)) {
|
|
80
|
+
return React__default["default"].createElement(Override, { ...props });
|
|
81
|
+
}
|
|
82
|
+
return React__default["default"].createElement(Default, { ...props });
|
|
83
|
+
};
|
|
84
|
+
Component.displayName = name;
|
|
85
|
+
return Component;
|
|
86
|
+
}
|
|
87
|
+
|
|
11
88
|
const ElementsContext = React__default["default"].createContext(undefined);
|
|
12
89
|
/**
|
|
13
90
|
* @internal @unstable
|
|
14
91
|
*
|
|
15
92
|
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
16
93
|
* to its `children`. `ElementsContext` lookup is handled directly
|
|
17
|
-
* by `BaseElement`components returned by `defineBaseElement
|
|
94
|
+
* by `BaseElement`components returned by `defineBaseElement` and
|
|
95
|
+
* `defineBaseElementWithRef`.
|
|
18
96
|
*
|
|
19
97
|
* @example
|
|
20
98
|
*
|
|
@@ -23,7 +101,7 @@ const ElementsContext = React__default["default"].createContext(undefined);
|
|
|
23
101
|
*
|
|
24
102
|
* ```tsx
|
|
25
103
|
* // `BaseElement`, renders custom or default element defintion
|
|
26
|
-
* const ViewElement =
|
|
104
|
+
* const ViewElement = defineBaseElementWithRef({
|
|
27
105
|
* displayName: "View",
|
|
28
106
|
* type: "div",
|
|
29
107
|
* });
|
|
@@ -77,6 +155,35 @@ function ElementsProvider({ elements, ...props }) {
|
|
|
77
155
|
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
78
156
|
*/
|
|
79
157
|
function defineBaseElement(input) {
|
|
158
|
+
const { displayName, type } = input;
|
|
159
|
+
const Element = ({ variant, ...props }) => {
|
|
160
|
+
const Element = React__default["default"].useContext(ElementsContext)?.[displayName];
|
|
161
|
+
if (Element) {
|
|
162
|
+
// only pass `variant` to provided `Element` values
|
|
163
|
+
return React__default["default"].createElement(Element, { ...props, variant });
|
|
164
|
+
}
|
|
165
|
+
return React__default["default"].createElement(type, props);
|
|
166
|
+
};
|
|
167
|
+
Element.displayName = displayName;
|
|
168
|
+
return Element;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @internal @unstable
|
|
172
|
+
*
|
|
173
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
174
|
+
* provided `type` with an assigned `displayName` and element `ref`.
|
|
175
|
+
*
|
|
176
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
177
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
178
|
+
*
|
|
179
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
180
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
181
|
+
* unstyled HTML element of the provided `type`.
|
|
182
|
+
*
|
|
183
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
184
|
+
* @returns {BaseElementWithRefProps} `ElementsContext` aware UI component
|
|
185
|
+
*/
|
|
186
|
+
function defineBaseElementWithRef(input) {
|
|
80
187
|
const { displayName, type } = input;
|
|
81
188
|
const Element = React__default["default"].forwardRef(({ variant, ...props }, ref) => {
|
|
82
189
|
const Element = React__default["default"].useContext(ElementsContext)?.[displayName];
|
|
@@ -105,7 +212,7 @@ function defineBaseElement(input) {
|
|
|
105
212
|
* type InputElementPropKey = 'onChange' | 'type';
|
|
106
213
|
*
|
|
107
214
|
* // create `InputElement` base with `type` generic and extended `props` key
|
|
108
|
-
* export const InputElement =
|
|
215
|
+
* export const InputElement = defineBaseElementWithRef<"input", InputElementPropKey>({
|
|
109
216
|
* type: "input",
|
|
110
217
|
* displayName: "Input",
|
|
111
218
|
* });
|
|
@@ -130,6 +237,12 @@ function withBaseElementProps(Target, defaultProps) {
|
|
|
130
237
|
return Component;
|
|
131
238
|
}
|
|
132
239
|
|
|
240
|
+
exports.ControlsContext = ControlsContext;
|
|
241
|
+
exports.ControlsProvider = ControlsProvider;
|
|
133
242
|
exports.ElementsProvider = ElementsProvider;
|
|
134
243
|
exports.defineBaseElement = defineBaseElement;
|
|
244
|
+
exports.defineBaseElementWithRef = defineBaseElementWithRef;
|
|
245
|
+
exports.isComponent = isComponent;
|
|
246
|
+
exports.isForwardRefExoticComponent = isForwardRefExoticComponent;
|
|
135
247
|
exports.withBaseElementProps = withBaseElementProps;
|
|
248
|
+
exports.withControls = withControls;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { isComponent } from './utils.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal @unstable
|
|
6
|
+
*/
|
|
7
|
+
const ControlsContext = React__default.createContext(undefined);
|
|
8
|
+
/**
|
|
9
|
+
* @internal @unstable
|
|
10
|
+
*
|
|
11
|
+
* `ControlsProvider` provides the values contained in `ControlsContext`
|
|
12
|
+
* to consumers. `ControlsContext` lookup is handled directly
|
|
13
|
+
* by `Control` components returned by `withControls`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
*
|
|
17
|
+
* Add `ControlsContext` aware `Controls` components to a Connected
|
|
18
|
+
* Component:
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const DataList = withControls(function DataList<T>(data: T[]) {
|
|
22
|
+
* return <ScrollView>data.map(ListItem)</ScrollView>;
|
|
23
|
+
* }, 'DataList');
|
|
24
|
+
*
|
|
25
|
+
* const DataListControl = () => {
|
|
26
|
+
* const data = useData();
|
|
27
|
+
* return <DataList data={data} />;
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* interface ComponentControls {
|
|
31
|
+
* DataList: typeof DataListControl;
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* function Component<T extends ComponentControls>(
|
|
35
|
+
* controls?: T
|
|
36
|
+
* ) {
|
|
37
|
+
* function ConnectedComponent({
|
|
38
|
+
* children,
|
|
39
|
+
* }: { children?: React.ReactNode }) {
|
|
40
|
+
* return (
|
|
41
|
+
* <ControlsProvider controls={controls}>
|
|
42
|
+
* {children}
|
|
43
|
+
* </ControlsProvider>
|
|
44
|
+
* );
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* return ConnectedComponent;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function ControlsProvider({ controls, ...props }) {
|
|
52
|
+
return React__default.createElement(ControlsContext.Provider, { ...props, value: controls });
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* @internal @unstable
|
|
56
|
+
*
|
|
57
|
+
* @note reference `ControlsProvider` for example usage
|
|
58
|
+
*/
|
|
59
|
+
function withControls(Default, name) {
|
|
60
|
+
const Component = (props) => {
|
|
61
|
+
const Override = React__default.useContext(ControlsContext)?.[name];
|
|
62
|
+
if (isComponent(Override)) {
|
|
63
|
+
return React__default.createElement(Override, { ...props });
|
|
64
|
+
}
|
|
65
|
+
return React__default.createElement(Default, { ...props });
|
|
66
|
+
};
|
|
67
|
+
Component.displayName = name;
|
|
68
|
+
return Component;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { ControlsContext, ControlsProvider, withControls };
|
|
@@ -6,7 +6,8 @@ const ElementsContext = React__default.createContext(undefined);
|
|
|
6
6
|
*
|
|
7
7
|
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
8
8
|
* to its `children`. `ElementsContext` lookup is handled directly
|
|
9
|
-
* by `BaseElement`components returned by `defineBaseElement
|
|
9
|
+
* by `BaseElement`components returned by `defineBaseElement` and
|
|
10
|
+
* `defineBaseElementWithRef`.
|
|
10
11
|
*
|
|
11
12
|
* @example
|
|
12
13
|
*
|
|
@@ -15,7 +16,7 @@ const ElementsContext = React__default.createContext(undefined);
|
|
|
15
16
|
*
|
|
16
17
|
* ```tsx
|
|
17
18
|
* // `BaseElement`, renders custom or default element defintion
|
|
18
|
-
* const ViewElement =
|
|
19
|
+
* const ViewElement = defineBaseElementWithRef({
|
|
19
20
|
* displayName: "View",
|
|
20
21
|
* type: "div",
|
|
21
22
|
* });
|
|
@@ -18,6 +18,35 @@ import { ElementsContext } from './ElementsContext.mjs';
|
|
|
18
18
|
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
19
19
|
*/
|
|
20
20
|
function defineBaseElement(input) {
|
|
21
|
+
const { displayName, type } = input;
|
|
22
|
+
const Element = ({ variant, ...props }) => {
|
|
23
|
+
const Element = React__default.useContext(ElementsContext)?.[displayName];
|
|
24
|
+
if (Element) {
|
|
25
|
+
// only pass `variant` to provided `Element` values
|
|
26
|
+
return React__default.createElement(Element, { ...props, variant });
|
|
27
|
+
}
|
|
28
|
+
return React__default.createElement(type, props);
|
|
29
|
+
};
|
|
30
|
+
Element.displayName = displayName;
|
|
31
|
+
return Element;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @internal @unstable
|
|
35
|
+
*
|
|
36
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
37
|
+
* provided `type` with an assigned `displayName` and element `ref`.
|
|
38
|
+
*
|
|
39
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
40
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
41
|
+
*
|
|
42
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
43
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
44
|
+
* unstyled HTML element of the provided `type`.
|
|
45
|
+
*
|
|
46
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
47
|
+
* @returns {BaseElementWithRefProps} `ElementsContext` aware UI component
|
|
48
|
+
*/
|
|
49
|
+
function defineBaseElementWithRef(input) {
|
|
21
50
|
const { displayName, type } = input;
|
|
22
51
|
const Element = React__default.forwardRef(({ variant, ...props }, ref) => {
|
|
23
52
|
const Element = React__default.useContext(ElementsContext)?.[displayName];
|
|
@@ -31,4 +60,4 @@ function defineBaseElement(input) {
|
|
|
31
60
|
return Element;
|
|
32
61
|
}
|
|
33
62
|
|
|
34
|
-
export { defineBaseElement
|
|
63
|
+
export { defineBaseElement, defineBaseElementWithRef };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function isComponent(component) {
|
|
2
|
+
return typeof component === 'function';
|
|
3
|
+
}
|
|
4
|
+
function isForwardRefExoticComponent(component) {
|
|
5
|
+
return (typeof component === 'object' &&
|
|
6
|
+
typeof component.$$typeof ===
|
|
7
|
+
'symbol' &&
|
|
8
|
+
['react.memo', 'react.forward_ref'].includes(component.$$typeof.description));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { isComponent, isForwardRefExoticComponent };
|
|
@@ -15,7 +15,7 @@ import React__default from 'react';
|
|
|
15
15
|
* type InputElementPropKey = 'onChange' | 'type';
|
|
16
16
|
*
|
|
17
17
|
* // create `InputElement` base with `type` generic and extended `props` key
|
|
18
|
-
* export const InputElement =
|
|
18
|
+
* export const InputElement = defineBaseElementWithRef<"input", InputElementPropKey>({
|
|
19
19
|
* type: "input",
|
|
20
20
|
* displayName: "Input",
|
|
21
21
|
* });
|
package/dist/esm/elements.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { ControlsContext, ControlsProvider, withControls } from './elements/ControlsContext.mjs';
|
|
2
|
+
export { defineBaseElement, defineBaseElementWithRef } from './elements/defineBaseElement.mjs';
|
|
2
3
|
export { default as withBaseElementProps } from './elements/withBaseElementProps.mjs';
|
|
3
4
|
export { ElementsProvider } from './elements/ElementsContext.mjs';
|
|
5
|
+
export { isComponent, isForwardRefExoticComponent } from './elements/utils.mjs';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isFunction } from '@aws-amplify/ui';
|
|
1
2
|
import React__default from 'react';
|
|
2
3
|
|
|
3
4
|
// default state
|
|
@@ -8,23 +9,28 @@ const resolveMaybeAsync = async (value) => {
|
|
|
8
9
|
const awaited = await value;
|
|
9
10
|
return awaited;
|
|
10
11
|
};
|
|
11
|
-
function useDataState(action, initialData) {
|
|
12
|
+
function useDataState(action, initialData, options) {
|
|
12
13
|
const [dataState, setDataState] = React__default.useState(() => ({
|
|
13
14
|
...INITIAL_STATE,
|
|
14
15
|
data: initialData,
|
|
15
16
|
}));
|
|
16
17
|
const prevData = React__default.useRef(initialData);
|
|
17
|
-
const
|
|
18
|
+
const { onSuccess, onError } = options ?? {};
|
|
19
|
+
const handleAction = React__default.useCallback((input) => {
|
|
18
20
|
setDataState(({ data }) => ({ ...LOADING_STATE, data }));
|
|
19
|
-
resolveMaybeAsync(action(prevData.current,
|
|
21
|
+
resolveMaybeAsync(action(prevData.current, input))
|
|
20
22
|
.then((data) => {
|
|
23
|
+
if (isFunction(onSuccess))
|
|
24
|
+
onSuccess(data);
|
|
21
25
|
prevData.current = data;
|
|
22
26
|
setDataState({ ...INITIAL_STATE, data });
|
|
23
27
|
})
|
|
24
28
|
.catch(({ message }) => {
|
|
29
|
+
if (isFunction(onError))
|
|
30
|
+
onError(message);
|
|
25
31
|
setDataState(({ data }) => ({ ...ERROR_STATE, data, message }));
|
|
26
32
|
});
|
|
27
|
-
}, [action]);
|
|
33
|
+
}, [action, onError, onSuccess]);
|
|
28
34
|
return [dataState, handleAction];
|
|
29
35
|
}
|
|
30
36
|
|
|
@@ -53,7 +53,10 @@ function createContextUtilities(options) {
|
|
|
53
53
|
if (isUndefined(defaultValue) && !isString(errorMessage)) {
|
|
54
54
|
throw new Error(INVALID_OPTIONS_MESSAGE);
|
|
55
55
|
}
|
|
56
|
+
const contextDisplayName = `${contextName}Context`;
|
|
57
|
+
const providerDisplayName = `${contextName}Provider`;
|
|
56
58
|
const Context = React__default.createContext(defaultValue);
|
|
59
|
+
Context.displayName = contextDisplayName;
|
|
57
60
|
function Provider(props) {
|
|
58
61
|
const { children, ...context } = props;
|
|
59
62
|
const value = React__default.useMemo(() => context,
|
|
@@ -63,7 +66,7 @@ function createContextUtilities(options) {
|
|
|
63
66
|
Object.values(context));
|
|
64
67
|
return React__default.createElement(Context.Provider, { value: value }, children);
|
|
65
68
|
}
|
|
66
|
-
Provider.displayName =
|
|
69
|
+
Provider.displayName = providerDisplayName;
|
|
67
70
|
return {
|
|
68
71
|
[`use${contextName}`]: function (params) {
|
|
69
72
|
const context = React__default.useContext(Context);
|
|
@@ -72,8 +75,8 @@ function createContextUtilities(options) {
|
|
|
72
75
|
}
|
|
73
76
|
return context;
|
|
74
77
|
},
|
|
75
|
-
[
|
|
76
|
-
[
|
|
78
|
+
[providerDisplayName]: Provider,
|
|
79
|
+
[contextDisplayName]: Context,
|
|
77
80
|
};
|
|
78
81
|
}
|
|
79
82
|
|
package/dist/index.js
CHANGED
|
@@ -563,23 +563,28 @@ const resolveMaybeAsync = async (value) => {
|
|
|
563
563
|
const awaited = await value;
|
|
564
564
|
return awaited;
|
|
565
565
|
};
|
|
566
|
-
function useDataState(action, initialData) {
|
|
566
|
+
function useDataState(action, initialData, options) {
|
|
567
567
|
const [dataState, setDataState] = React__namespace["default"].useState(() => ({
|
|
568
568
|
...INITIAL_STATE,
|
|
569
569
|
data: initialData,
|
|
570
570
|
}));
|
|
571
571
|
const prevData = React__namespace["default"].useRef(initialData);
|
|
572
|
-
const
|
|
572
|
+
const { onSuccess, onError } = options ?? {};
|
|
573
|
+
const handleAction = React__namespace["default"].useCallback((input) => {
|
|
573
574
|
setDataState(({ data }) => ({ ...LOADING_STATE, data }));
|
|
574
|
-
resolveMaybeAsync(action(prevData.current,
|
|
575
|
+
resolveMaybeAsync(action(prevData.current, input))
|
|
575
576
|
.then((data) => {
|
|
577
|
+
if (ui.isFunction(onSuccess))
|
|
578
|
+
onSuccess(data);
|
|
576
579
|
prevData.current = data;
|
|
577
580
|
setDataState({ ...INITIAL_STATE, data });
|
|
578
581
|
})
|
|
579
582
|
.catch(({ message }) => {
|
|
583
|
+
if (ui.isFunction(onError))
|
|
584
|
+
onError(message);
|
|
580
585
|
setDataState(({ data }) => ({ ...ERROR_STATE, data, message }));
|
|
581
586
|
});
|
|
582
|
-
}, [action]);
|
|
587
|
+
}, [action, onError, onSuccess]);
|
|
583
588
|
return [dataState, handleAction];
|
|
584
589
|
}
|
|
585
590
|
|
|
@@ -911,7 +916,10 @@ function createContextUtilities(options) {
|
|
|
911
916
|
if (ui.isUndefined(defaultValue) && !ui.isString(errorMessage)) {
|
|
912
917
|
throw new Error(INVALID_OPTIONS_MESSAGE);
|
|
913
918
|
}
|
|
919
|
+
const contextDisplayName = `${contextName}Context`;
|
|
920
|
+
const providerDisplayName = `${contextName}Provider`;
|
|
914
921
|
const Context = React__namespace["default"].createContext(defaultValue);
|
|
922
|
+
Context.displayName = contextDisplayName;
|
|
915
923
|
function Provider(props) {
|
|
916
924
|
const { children, ...context } = props;
|
|
917
925
|
const value = React__namespace["default"].useMemo(() => context,
|
|
@@ -921,7 +929,7 @@ function createContextUtilities(options) {
|
|
|
921
929
|
Object.values(context));
|
|
922
930
|
return React__namespace["default"].createElement(Context.Provider, { value: value }, children);
|
|
923
931
|
}
|
|
924
|
-
Provider.displayName =
|
|
932
|
+
Provider.displayName = providerDisplayName;
|
|
925
933
|
return {
|
|
926
934
|
[`use${contextName}`]: function (params) {
|
|
927
935
|
const context = React__namespace["default"].useContext(Context);
|
|
@@ -930,8 +938,8 @@ function createContextUtilities(options) {
|
|
|
930
938
|
}
|
|
931
939
|
return context;
|
|
932
940
|
},
|
|
933
|
-
[
|
|
934
|
-
[
|
|
941
|
+
[providerDisplayName]: Provider,
|
|
942
|
+
[contextDisplayName]: Context,
|
|
935
943
|
};
|
|
936
944
|
}
|
|
937
945
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @internal @unstable
|
|
4
|
+
*/
|
|
5
|
+
export interface Controls extends Partial<Record<string, React.ComponentType>> {
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* @internal @unstable
|
|
9
|
+
*/
|
|
10
|
+
export declare const ControlsContext: React.Context<Controls | undefined>;
|
|
11
|
+
/**
|
|
12
|
+
* @internal @unstable
|
|
13
|
+
*
|
|
14
|
+
* `ControlsProvider` provides the values contained in `ControlsContext`
|
|
15
|
+
* to consumers. `ControlsContext` lookup is handled directly
|
|
16
|
+
* by `Control` components returned by `withControls`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
*
|
|
20
|
+
* Add `ControlsContext` aware `Controls` components to a Connected
|
|
21
|
+
* Component:
|
|
22
|
+
*
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const DataList = withControls(function DataList<T>(data: T[]) {
|
|
25
|
+
* return <ScrollView>data.map(ListItem)</ScrollView>;
|
|
26
|
+
* }, 'DataList');
|
|
27
|
+
*
|
|
28
|
+
* const DataListControl = () => {
|
|
29
|
+
* const data = useData();
|
|
30
|
+
* return <DataList data={data} />;
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* interface ComponentControls {
|
|
34
|
+
* DataList: typeof DataListControl;
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* function Component<T extends ComponentControls>(
|
|
38
|
+
* controls?: T
|
|
39
|
+
* ) {
|
|
40
|
+
* function ConnectedComponent({
|
|
41
|
+
* children,
|
|
42
|
+
* }: { children?: React.ReactNode }) {
|
|
43
|
+
* return (
|
|
44
|
+
* <ControlsProvider controls={controls}>
|
|
45
|
+
* {children}
|
|
46
|
+
* </ControlsProvider>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* return ConnectedComponent;
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function ControlsProvider<T extends Controls>({ controls, ...props }: {
|
|
55
|
+
children?: React.ReactNode;
|
|
56
|
+
controls?: T;
|
|
57
|
+
}): React.JSX.Element;
|
|
58
|
+
/**
|
|
59
|
+
* @internal @unstable
|
|
60
|
+
*
|
|
61
|
+
* @note reference `ControlsProvider` for example usage
|
|
62
|
+
*/
|
|
63
|
+
export declare function withControls<T extends React.ComponentType<any>, K extends keyof Controls>(Default: T, name: K): (props: React.ComponentProps<T>) => React.JSX.Element;
|
|
@@ -11,7 +11,8 @@ export declare const ElementsContext: React.Context<Elements | undefined>;
|
|
|
11
11
|
*
|
|
12
12
|
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
13
13
|
* to its `children`. `ElementsContext` lookup is handled directly
|
|
14
|
-
* by `BaseElement`components returned by `defineBaseElement
|
|
14
|
+
* by `BaseElement`components returned by `defineBaseElement` and
|
|
15
|
+
* `defineBaseElementWithRef`.
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
*
|
|
@@ -20,7 +21,7 @@ export declare const ElementsContext: React.Context<Elements | undefined>;
|
|
|
20
21
|
*
|
|
21
22
|
* ```tsx
|
|
22
23
|
* // `BaseElement`, renders custom or default element defintion
|
|
23
|
-
* const ViewElement =
|
|
24
|
+
* const ViewElement = defineBaseElementWithRef({
|
|
24
25
|
* displayName: "View",
|
|
25
26
|
* type: "div",
|
|
26
27
|
* });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseElement, BaseElementProps, ElementDisplayName, ElementRefType, ReactElementProps, ReactElementType } from './types';
|
|
1
|
+
import { BaseElement, BaseElementProps, BaseElementWithRef, BaseElementWithRefProps, ElementDisplayName, ElementRefType, ReactElementProps, ReactElementType } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* @internal @unstable
|
|
4
4
|
*/
|
|
@@ -28,4 +28,21 @@ export interface DefineBaseElementInput<T> {
|
|
|
28
28
|
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
29
29
|
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
30
30
|
*/
|
|
31
|
-
export
|
|
31
|
+
export declare function defineBaseElement<T extends ReactElementType, K extends keyof U = never, V = string, U extends ReactElementProps<T> = ReactElementProps<T>, P extends BaseElementProps<K, V, U> = BaseElementProps<K, V, U>>(input: DefineBaseElementInput<T>): BaseElement<P>;
|
|
32
|
+
/**
|
|
33
|
+
* @internal @unstable
|
|
34
|
+
*
|
|
35
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
36
|
+
* provided `type` with an assigned `displayName` and element `ref`.
|
|
37
|
+
*
|
|
38
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
39
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
40
|
+
*
|
|
41
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
42
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
43
|
+
* unstyled HTML element of the provided `type`.
|
|
44
|
+
*
|
|
45
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
46
|
+
* @returns {BaseElementWithRefProps} `ElementsContext` aware UI component
|
|
47
|
+
*/
|
|
48
|
+
export declare function defineBaseElementWithRef<T extends ReactElementType, K extends keyof U = never, V = string, U extends ReactElementProps<T> = ReactElementProps<T>, P extends BaseElementWithRefProps<K, V, U> = BaseElementWithRefProps<K, V, U>>(input: DefineBaseElementInput<T>): BaseElementWithRef<P, ElementRefType<P>>;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './ControlsContext';
|
|
2
|
+
export { defineBaseElement, defineBaseElementWithRef, } from './defineBaseElement';
|
|
2
3
|
export { default as withBaseElementProps } from './withBaseElementProps';
|
|
3
4
|
export { ElementsProvider } from './ElementsContext';
|
|
5
|
+
export { isComponent, isForwardRefExoticComponent } from './utils';
|
|
6
|
+
export * from './types';
|