@aws-amplify/ui-react-core 3.0.16 → 3.0.18
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/README.md +1 -1
- package/dist/elements.js +135 -0
- package/dist/esm/elements/ElementsContext.mjs +55 -0
- package/dist/esm/elements/defineBaseElement.mjs +34 -0
- package/dist/esm/elements/elements.mjs +3 -0
- package/dist/esm/elements/withBaseElementProps.mjs +43 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/types/elements/ElementsContext.d.ts +59 -0
- package/dist/types/elements/defineBaseElement.d.ts +31 -0
- package/dist/types/elements/index.d.ts +3 -0
- package/dist/types/elements/types.d.ts +53 -0
- package/dist/types/elements/withBaseElementProps.d.ts +34 -0
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/useDataState.d.ts +7 -0
- package/elements/package.json +6 -0
- package/package.json +9 -2
- package/src/elements/ElementsContext.tsx +69 -0
- package/src/elements/defineBaseElement.tsx +73 -0
- package/src/elements/index.ts +3 -0
- package/src/elements/types.ts +87 -0
- package/src/elements/withBaseElementProps.tsx +55 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useDataState.ts +50 -0
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# Amplify UI React Core
|
|
2
2
|
|
|
3
|
-
`@aws-amplify/ui-react-core` is a React platform agnostic utility library for Amplify UI internal usage in
|
|
3
|
+
`@aws-amplify/ui-react-core` is a React platform agnostic utility library for Amplify UI internal usage in `@aws-amplify/ui-react*` and `@aws-amplify/ui-react-native*` namespaced packages.
|
package/dist/elements.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var React = require('react');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
10
|
+
|
|
11
|
+
const ElementsContext = React__default["default"].createContext(undefined);
|
|
12
|
+
/**
|
|
13
|
+
* @internal @unstable
|
|
14
|
+
*
|
|
15
|
+
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
16
|
+
* to its `children`. `ElementsContext` lookup is handled directly
|
|
17
|
+
* by `BaseElement`components returned by `defineBaseElement`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
*
|
|
21
|
+
* Add `ElementsContext` aware `BaseElement` components to a Connected
|
|
22
|
+
* Component
|
|
23
|
+
*
|
|
24
|
+
* ```tsx
|
|
25
|
+
* // `BaseElement`, renders custom or default element defintion
|
|
26
|
+
* const ViewElement = defineBaseElement({
|
|
27
|
+
* displayName: "View",
|
|
28
|
+
* type: "div",
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // `BaseElement` components to be provided through `ElementsContext`
|
|
32
|
+
* interface ConnectedComponentElements {
|
|
33
|
+
* View: typeof ViewElement;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* function createConnectedComponent<T extends ConnectedComponentElements>(
|
|
37
|
+
* elements?: T
|
|
38
|
+
* ) {
|
|
39
|
+
* const Provider = ({ children }: { children?: React.ReactNode }) => (
|
|
40
|
+
* <ElementsProvider elements={elements}>
|
|
41
|
+
* <Children />
|
|
42
|
+
* </ElementsProvider>
|
|
43
|
+
* );
|
|
44
|
+
*
|
|
45
|
+
* function ConnectedComponent() {
|
|
46
|
+
* return (
|
|
47
|
+
* <Provider>
|
|
48
|
+
* <ConnectedComponentContent />
|
|
49
|
+
* </Provider>
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* ConnectedComponent.Provider = Provider;
|
|
54
|
+
*
|
|
55
|
+
* return ConnectedComponent;
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
function ElementsProvider({ elements, ...props }) {
|
|
60
|
+
return React__default["default"].createElement(ElementsContext.Provider, { ...props, value: elements });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @internal @unstable
|
|
65
|
+
*
|
|
66
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
67
|
+
* provided `type` with an assigned `displayName`.
|
|
68
|
+
*
|
|
69
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
70
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
71
|
+
*
|
|
72
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
73
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
74
|
+
* unstyled HTML element of the provided `type`.
|
|
75
|
+
*
|
|
76
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
77
|
+
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
78
|
+
*/
|
|
79
|
+
function defineBaseElement(input) {
|
|
80
|
+
const { displayName, type } = input;
|
|
81
|
+
const Element = React__default["default"].forwardRef(({ variant, ...props }, ref) => {
|
|
82
|
+
const Element = React__default["default"].useContext(ElementsContext)?.[displayName];
|
|
83
|
+
if (Element) {
|
|
84
|
+
// only pass `variant` to provided `Element` values
|
|
85
|
+
return React__default["default"].createElement(Element, { ...props, ref, variant });
|
|
86
|
+
}
|
|
87
|
+
return React__default["default"].createElement(type, { ...props, ref });
|
|
88
|
+
});
|
|
89
|
+
Element.displayName = displayName;
|
|
90
|
+
return Element;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @internal @unstable
|
|
95
|
+
*
|
|
96
|
+
* Extend target `BaseElement` with `defaultProps`. `defaultProps`
|
|
97
|
+
* are overidden by `props` provided to returned `BaseElement`.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
*
|
|
101
|
+
* Extend `InputElement` with default `className` and `type`
|
|
102
|
+
* ```tsx
|
|
103
|
+
*
|
|
104
|
+
* // define extended `props` on `BaseElement` interface
|
|
105
|
+
* type InputElementPropKey = 'onChange' | 'type';
|
|
106
|
+
*
|
|
107
|
+
* // create `InputElement` base with `type` generic and extended `props` key
|
|
108
|
+
* export const InputElement = defineBaseElement<"input", InputElementPropKey>({
|
|
109
|
+
* type: "input",
|
|
110
|
+
* displayName: "Input",
|
|
111
|
+
* });
|
|
112
|
+
*
|
|
113
|
+
* // extend base `InputElement` with default input `type` of `checkbox`
|
|
114
|
+
* const CheckboxElement = withBaseElementProps(Input, {
|
|
115
|
+
* className: 'submit-toggle__checkbox',
|
|
116
|
+
* type: 'checkbox',
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @param Target `BaseElement` to extend
|
|
121
|
+
* @param defaultProps `defaultProps` to apply to `Target`, accepts object or callback
|
|
122
|
+
* @returns extended `BaseElement` with `defaultProps`
|
|
123
|
+
*/
|
|
124
|
+
function withBaseElementProps(Target, defaultProps) {
|
|
125
|
+
const Component = React__default["default"].forwardRef((props, ref) => (React__default["default"].createElement(Target, { ...(typeof defaultProps === 'function'
|
|
126
|
+
? defaultProps(props)
|
|
127
|
+
: defaultProps),
|
|
128
|
+
...props, ref: ref })));
|
|
129
|
+
Component.displayName = Target.displayName;
|
|
130
|
+
return Component;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
exports.ElementsProvider = ElementsProvider;
|
|
134
|
+
exports.defineBaseElement = defineBaseElement;
|
|
135
|
+
exports.withBaseElementProps = withBaseElementProps;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
const ElementsContext = React__default.createContext(undefined);
|
|
4
|
+
/**
|
|
5
|
+
* @internal @unstable
|
|
6
|
+
*
|
|
7
|
+
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
8
|
+
* to its `children`. `ElementsContext` lookup is handled directly
|
|
9
|
+
* by `BaseElement`components returned by `defineBaseElement`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
*
|
|
13
|
+
* Add `ElementsContext` aware `BaseElement` components to a Connected
|
|
14
|
+
* Component
|
|
15
|
+
*
|
|
16
|
+
* ```tsx
|
|
17
|
+
* // `BaseElement`, renders custom or default element defintion
|
|
18
|
+
* const ViewElement = defineBaseElement({
|
|
19
|
+
* displayName: "View",
|
|
20
|
+
* type: "div",
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // `BaseElement` components to be provided through `ElementsContext`
|
|
24
|
+
* interface ConnectedComponentElements {
|
|
25
|
+
* View: typeof ViewElement;
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* function createConnectedComponent<T extends ConnectedComponentElements>(
|
|
29
|
+
* elements?: T
|
|
30
|
+
* ) {
|
|
31
|
+
* const Provider = ({ children }: { children?: React.ReactNode }) => (
|
|
32
|
+
* <ElementsProvider elements={elements}>
|
|
33
|
+
* <Children />
|
|
34
|
+
* </ElementsProvider>
|
|
35
|
+
* );
|
|
36
|
+
*
|
|
37
|
+
* function ConnectedComponent() {
|
|
38
|
+
* return (
|
|
39
|
+
* <Provider>
|
|
40
|
+
* <ConnectedComponentContent />
|
|
41
|
+
* </Provider>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* ConnectedComponent.Provider = Provider;
|
|
46
|
+
*
|
|
47
|
+
* return ConnectedComponent;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function ElementsProvider({ elements, ...props }) {
|
|
52
|
+
return React__default.createElement(ElementsContext.Provider, { ...props, value: elements });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { ElementsContext, ElementsProvider };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { ElementsContext } from './ElementsContext.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal @unstable
|
|
6
|
+
*
|
|
7
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
8
|
+
* provided `type` with an assigned `displayName`.
|
|
9
|
+
*
|
|
10
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
11
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
12
|
+
*
|
|
13
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
14
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
15
|
+
* unstyled HTML element of the provided `type`.
|
|
16
|
+
*
|
|
17
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
18
|
+
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
19
|
+
*/
|
|
20
|
+
function defineBaseElement(input) {
|
|
21
|
+
const { displayName, type } = input;
|
|
22
|
+
const Element = React__default.forwardRef(({ variant, ...props }, ref) => {
|
|
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, ref, variant });
|
|
27
|
+
}
|
|
28
|
+
return React__default.createElement(type, { ...props, ref });
|
|
29
|
+
});
|
|
30
|
+
Element.displayName = displayName;
|
|
31
|
+
return Element;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { defineBaseElement as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @internal @unstable
|
|
5
|
+
*
|
|
6
|
+
* Extend target `BaseElement` with `defaultProps`. `defaultProps`
|
|
7
|
+
* are overidden by `props` provided to returned `BaseElement`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
*
|
|
11
|
+
* Extend `InputElement` with default `className` and `type`
|
|
12
|
+
* ```tsx
|
|
13
|
+
*
|
|
14
|
+
* // define extended `props` on `BaseElement` interface
|
|
15
|
+
* type InputElementPropKey = 'onChange' | 'type';
|
|
16
|
+
*
|
|
17
|
+
* // create `InputElement` base with `type` generic and extended `props` key
|
|
18
|
+
* export const InputElement = defineBaseElement<"input", InputElementPropKey>({
|
|
19
|
+
* type: "input",
|
|
20
|
+
* displayName: "Input",
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // extend base `InputElement` with default input `type` of `checkbox`
|
|
24
|
+
* const CheckboxElement = withBaseElementProps(Input, {
|
|
25
|
+
* className: 'submit-toggle__checkbox',
|
|
26
|
+
* type: 'checkbox',
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param Target `BaseElement` to extend
|
|
31
|
+
* @param defaultProps `defaultProps` to apply to `Target`, accepts object or callback
|
|
32
|
+
* @returns extended `BaseElement` with `defaultProps`
|
|
33
|
+
*/
|
|
34
|
+
function withBaseElementProps(Target, defaultProps) {
|
|
35
|
+
const Component = React__default.forwardRef((props, ref) => (React__default.createElement(Target, { ...(typeof defaultProps === 'function'
|
|
36
|
+
? defaultProps(props)
|
|
37
|
+
: defaultProps),
|
|
38
|
+
...props, ref: ref })));
|
|
39
|
+
Component.displayName = Target.displayName;
|
|
40
|
+
return Component;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { withBaseElementProps as default };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -9,6 +9,7 @@ export { default as useForm } from './components/FormCore/useForm.mjs';
|
|
|
9
9
|
export { default as FormProvider } from './components/FormCore/FormProvider.mjs';
|
|
10
10
|
export { default as withFormProvider } from './components/FormCore/withFormProvider.mjs';
|
|
11
11
|
export { default as RenderNothing } from './components/RenderNothing/RenderNothing.mjs';
|
|
12
|
+
import 'react';
|
|
12
13
|
export { default as useDeprecationWarning } from './hooks/useDeprecationWarning.mjs';
|
|
13
14
|
export { default as useGetUrl } from './hooks/useGetUrl.mjs';
|
|
14
15
|
export { default as useHasValueUpdated } from './hooks/useHasValueUpdated.mjs';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ElementDisplayName } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* @internal @unstable
|
|
5
|
+
*/
|
|
6
|
+
export interface Elements extends Partial<Record<ElementDisplayName, React.ComponentType>> {
|
|
7
|
+
}
|
|
8
|
+
export declare const ElementsContext: React.Context<Elements | undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* @internal @unstable
|
|
11
|
+
*
|
|
12
|
+
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
13
|
+
* to its `children`. `ElementsContext` lookup is handled directly
|
|
14
|
+
* by `BaseElement`components returned by `defineBaseElement`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
*
|
|
18
|
+
* Add `ElementsContext` aware `BaseElement` components to a Connected
|
|
19
|
+
* Component
|
|
20
|
+
*
|
|
21
|
+
* ```tsx
|
|
22
|
+
* // `BaseElement`, renders custom or default element defintion
|
|
23
|
+
* const ViewElement = defineBaseElement({
|
|
24
|
+
* displayName: "View",
|
|
25
|
+
* type: "div",
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // `BaseElement` components to be provided through `ElementsContext`
|
|
29
|
+
* interface ConnectedComponentElements {
|
|
30
|
+
* View: typeof ViewElement;
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* function createConnectedComponent<T extends ConnectedComponentElements>(
|
|
34
|
+
* elements?: T
|
|
35
|
+
* ) {
|
|
36
|
+
* const Provider = ({ children }: { children?: React.ReactNode }) => (
|
|
37
|
+
* <ElementsProvider elements={elements}>
|
|
38
|
+
* <Children />
|
|
39
|
+
* </ElementsProvider>
|
|
40
|
+
* );
|
|
41
|
+
*
|
|
42
|
+
* function ConnectedComponent() {
|
|
43
|
+
* return (
|
|
44
|
+
* <Provider>
|
|
45
|
+
* <ConnectedComponentContent />
|
|
46
|
+
* </Provider>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* ConnectedComponent.Provider = Provider;
|
|
51
|
+
*
|
|
52
|
+
* return ConnectedComponent;
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function ElementsProvider<T extends Elements>({ elements, ...props }: {
|
|
57
|
+
children?: React.ReactNode;
|
|
58
|
+
elements?: T;
|
|
59
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BaseElement, BaseElementProps, ElementDisplayName, ElementRefType, ReactElementProps, ReactElementType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* @internal @unstable
|
|
4
|
+
*/
|
|
5
|
+
export interface DefineBaseElementInput<T> {
|
|
6
|
+
/**
|
|
7
|
+
* `BaseElement` display name in React dev tools and stack traces
|
|
8
|
+
*/
|
|
9
|
+
displayName: ElementDisplayName;
|
|
10
|
+
/**
|
|
11
|
+
* base HTML `element` type
|
|
12
|
+
*/
|
|
13
|
+
type: T;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @internal @unstable
|
|
17
|
+
*
|
|
18
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
19
|
+
* provided `type` with an assigned `displayName`.
|
|
20
|
+
*
|
|
21
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
22
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
23
|
+
*
|
|
24
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
25
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
26
|
+
* unstyled HTML element of the provided `type`.
|
|
27
|
+
*
|
|
28
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
29
|
+
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
30
|
+
*/
|
|
31
|
+
export default 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, ElementRefType<P>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @internal @unstable
|
|
4
|
+
*
|
|
5
|
+
* Base type definition of `BaseElement` components available through
|
|
6
|
+
* `ElementsContext`. The definitions define a contract between a
|
|
7
|
+
* Connected Component and the `elements` that can be provided as
|
|
8
|
+
* overrides.
|
|
9
|
+
*
|
|
10
|
+
* `BaseElement` interfaces surface a minimal set of HTML semantic `props`
|
|
11
|
+
* required to achieve the base functionality of consumers. `props`
|
|
12
|
+
* are always optional at the interface level, allowing for additional `props`
|
|
13
|
+
* to be added to existing `BaseElement` interfaces as needed.
|
|
14
|
+
*/
|
|
15
|
+
export type BaseElement<T = {}, K = {}> = React.ForwardRefExoticComponent<React.PropsWithoutRef<T> & React.RefAttributes<K>>;
|
|
16
|
+
type ListElementSubType = 'Ordered' | 'Unordered';
|
|
17
|
+
type ListElementDisplayName = 'List' | `${ListElementSubType}List`;
|
|
18
|
+
type TableElementSubType = 'Body' | 'Data' | 'Row' | 'Head' | 'Header';
|
|
19
|
+
type TableElementDisplayName = 'Table' | `Table${TableElementSubType}`;
|
|
20
|
+
/**
|
|
21
|
+
* @internal @unstable
|
|
22
|
+
*
|
|
23
|
+
* allowed values of `displayName` of `BaseElement` and `ElemebtsContext` keys
|
|
24
|
+
*/
|
|
25
|
+
export type ElementDisplayName = 'Button' | 'Divider' | 'Heading' | 'Icon' | 'Input' | 'Label' | 'ListItem' | 'Nav' | 'ProgressBar' | 'Span' | 'Text' | 'Title' | 'View' | ListElementDisplayName | TableElementDisplayName;
|
|
26
|
+
/**
|
|
27
|
+
* @internal @unstable
|
|
28
|
+
*/
|
|
29
|
+
export type ElementRefType<T> = T extends {
|
|
30
|
+
ref?: React.LegacyRef<infer K> | React.Ref<infer K> | React.ForwardedRef<infer K>;
|
|
31
|
+
} ? K : never;
|
|
32
|
+
/**
|
|
33
|
+
* @internal @unstable
|
|
34
|
+
*/
|
|
35
|
+
export type ReactElementType = keyof React.JSX.IntrinsicElements;
|
|
36
|
+
/**
|
|
37
|
+
* @internal @unstable
|
|
38
|
+
*/
|
|
39
|
+
export type ReactElementProps<T extends ReactElementType> = React.JSX.IntrinsicElements[T];
|
|
40
|
+
/**
|
|
41
|
+
* @internal @unstable
|
|
42
|
+
*
|
|
43
|
+
* key of `props` always available on `BaseElement` definitions
|
|
44
|
+
*/
|
|
45
|
+
type ElementPropKey<T> = T | 'children' | 'className' | 'style';
|
|
46
|
+
/**
|
|
47
|
+
* @internal @unstable
|
|
48
|
+
*/
|
|
49
|
+
export type BaseElementProps<T extends keyof K, V = string, K extends Record<ElementPropKey<keyof K>, any> = Record<string, any>> = React.AriaAttributes & React.RefAttributes<ElementRefType<K>> & Pick<K, ElementPropKey<T>> & {
|
|
50
|
+
testId?: string;
|
|
51
|
+
variant?: V;
|
|
52
|
+
};
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BaseElement, ElementRefType } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* @internal @unstable
|
|
5
|
+
*
|
|
6
|
+
* Extend target `BaseElement` with `defaultProps`. `defaultProps`
|
|
7
|
+
* are overidden by `props` provided to returned `BaseElement`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
*
|
|
11
|
+
* Extend `InputElement` with default `className` and `type`
|
|
12
|
+
* ```tsx
|
|
13
|
+
*
|
|
14
|
+
* // define extended `props` on `BaseElement` interface
|
|
15
|
+
* type InputElementPropKey = 'onChange' | 'type';
|
|
16
|
+
*
|
|
17
|
+
* // create `InputElement` base with `type` generic and extended `props` key
|
|
18
|
+
* export const InputElement = defineBaseElement<"input", InputElementPropKey>({
|
|
19
|
+
* type: "input",
|
|
20
|
+
* displayName: "Input",
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // extend base `InputElement` with default input `type` of `checkbox`
|
|
24
|
+
* const CheckboxElement = withBaseElementProps(Input, {
|
|
25
|
+
* className: 'submit-toggle__checkbox',
|
|
26
|
+
* type: 'checkbox',
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param Target `BaseElement` to extend
|
|
31
|
+
* @param defaultProps `defaultProps` to apply to `Target`, accepts object or callback
|
|
32
|
+
* @returns extended `BaseElement` with `defaultProps`
|
|
33
|
+
*/
|
|
34
|
+
export default function withBaseElementProps<T, K extends T | ((input: T) => T)>(Target: React.ForwardRefExoticComponent<T>, defaultProps: K): BaseElement<T, ElementRefType<T>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { default as useDataState, DataState } from './useDataState';
|
|
1
2
|
export { default as useDeprecationWarning, UseDeprecationWarning, } from './useDeprecationWarning';
|
|
2
3
|
export { default as useGetUrl } from './useGetUrl';
|
|
3
4
|
export { default as useHasValueUpdated } from './useHasValueUpdated';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface DataState<T> {
|
|
2
|
+
data: T;
|
|
3
|
+
hasError: boolean;
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
message: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export default function useDataState<T, K>(action: (prevData: T, ...input: K[]) => T | Promise<T>, initialData: T): [state: DataState<T>, handleAction: (...input: K[]) => void];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-amplify/ui-react-core",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.18",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/esm/index.mjs",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -10,12 +10,19 @@
|
|
|
10
10
|
"require": "./dist/index.js",
|
|
11
11
|
"types": "./dist/types/index.d.ts"
|
|
12
12
|
},
|
|
13
|
+
"./elements": {
|
|
14
|
+
"import": "./dist/esm/elements/elements.mjs",
|
|
15
|
+
"require": "./dist/elements.js",
|
|
16
|
+
"react-native": "./src/elements/index.ts",
|
|
17
|
+
"types": "./dist/types/elements/index.d.ts"
|
|
18
|
+
},
|
|
13
19
|
"./package.json": "./package.json"
|
|
14
20
|
},
|
|
15
21
|
"types": "dist/types/index.d.ts",
|
|
16
22
|
"license": "Apache-2.0",
|
|
17
23
|
"files": [
|
|
18
24
|
"dist",
|
|
25
|
+
"elements",
|
|
19
26
|
"LICENSE",
|
|
20
27
|
"src",
|
|
21
28
|
"!**/__mocks__",
|
|
@@ -33,7 +40,7 @@
|
|
|
33
40
|
"typecheck": "tsc --noEmit"
|
|
34
41
|
},
|
|
35
42
|
"dependencies": {
|
|
36
|
-
"@aws-amplify/ui": "6.0
|
|
43
|
+
"@aws-amplify/ui": "6.1.0",
|
|
37
44
|
"@xstate/react": "^3.2.2",
|
|
38
45
|
"lodash": "4.17.21",
|
|
39
46
|
"react-hook-form": "^7.43.5",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ElementDisplayName } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal @unstable
|
|
6
|
+
*/
|
|
7
|
+
export interface Elements
|
|
8
|
+
extends Partial<Record<ElementDisplayName, React.ComponentType>> {}
|
|
9
|
+
|
|
10
|
+
export const ElementsContext = React.createContext<Elements | undefined>(
|
|
11
|
+
undefined
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @internal @unstable
|
|
16
|
+
*
|
|
17
|
+
* `ElementsProvider` provides the values contained in `ElementsContext`
|
|
18
|
+
* to its `children`. `ElementsContext` lookup is handled directly
|
|
19
|
+
* by `BaseElement`components returned by `defineBaseElement`.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
*
|
|
23
|
+
* Add `ElementsContext` aware `BaseElement` components to a Connected
|
|
24
|
+
* Component
|
|
25
|
+
*
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // `BaseElement`, renders custom or default element defintion
|
|
28
|
+
* const ViewElement = defineBaseElement({
|
|
29
|
+
* displayName: "View",
|
|
30
|
+
* type: "div",
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // `BaseElement` components to be provided through `ElementsContext`
|
|
34
|
+
* interface ConnectedComponentElements {
|
|
35
|
+
* View: typeof ViewElement;
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* function createConnectedComponent<T extends ConnectedComponentElements>(
|
|
39
|
+
* elements?: T
|
|
40
|
+
* ) {
|
|
41
|
+
* const Provider = ({ children }: { children?: React.ReactNode }) => (
|
|
42
|
+
* <ElementsProvider elements={elements}>
|
|
43
|
+
* <Children />
|
|
44
|
+
* </ElementsProvider>
|
|
45
|
+
* );
|
|
46
|
+
*
|
|
47
|
+
* function ConnectedComponent() {
|
|
48
|
+
* return (
|
|
49
|
+
* <Provider>
|
|
50
|
+
* <ConnectedComponentContent />
|
|
51
|
+
* </Provider>
|
|
52
|
+
* );
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* ConnectedComponent.Provider = Provider;
|
|
56
|
+
*
|
|
57
|
+
* return ConnectedComponent;
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function ElementsProvider<T extends Elements>({
|
|
62
|
+
elements,
|
|
63
|
+
...props
|
|
64
|
+
}: {
|
|
65
|
+
children?: React.ReactNode;
|
|
66
|
+
elements?: T;
|
|
67
|
+
}): React.JSX.Element {
|
|
68
|
+
return <ElementsContext.Provider {...props} value={elements} />;
|
|
69
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ElementsContext } from './ElementsContext';
|
|
3
|
+
import {
|
|
4
|
+
BaseElement,
|
|
5
|
+
BaseElementProps,
|
|
6
|
+
ElementDisplayName,
|
|
7
|
+
ElementRefType,
|
|
8
|
+
ReactElementProps,
|
|
9
|
+
ReactElementType,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @internal @unstable
|
|
14
|
+
*/
|
|
15
|
+
export interface DefineBaseElementInput<T> {
|
|
16
|
+
/**
|
|
17
|
+
* `BaseElement` display name in React dev tools and stack traces
|
|
18
|
+
*/
|
|
19
|
+
displayName: ElementDisplayName;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* base HTML `element` type
|
|
23
|
+
*/
|
|
24
|
+
type: T;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @internal @unstable
|
|
29
|
+
*
|
|
30
|
+
* Defines a `ElementsContext` aware `BaseElement` UI component of the
|
|
31
|
+
* provided `type` with an assigned `displayName`.
|
|
32
|
+
*
|
|
33
|
+
* If `BaseElement` is used as a child of an `ElementsProvider`, returns the
|
|
34
|
+
* `BaseElement` value of the provided `displayName` of `ElementsContext`.
|
|
35
|
+
*
|
|
36
|
+
* When used outside of a parent `ElementsProvider` or no `BaseElement`
|
|
37
|
+
* of `displayName` is found in the `ElementsContext`, returns a stateless,
|
|
38
|
+
* unstyled HTML element of the provided `type`.
|
|
39
|
+
*
|
|
40
|
+
* @param {DefineBaseElementInput} input `BaseElement` parameters
|
|
41
|
+
* @returns {BaseElement} `ElementsContext` aware UI component
|
|
42
|
+
*/
|
|
43
|
+
export default function defineBaseElement<
|
|
44
|
+
// element type
|
|
45
|
+
T extends ReactElementType,
|
|
46
|
+
// string union of base element props to include
|
|
47
|
+
K extends keyof U = never,
|
|
48
|
+
// variant string union
|
|
49
|
+
V = string,
|
|
50
|
+
// available props of base element type
|
|
51
|
+
U extends ReactElementProps<T> = ReactElementProps<T>,
|
|
52
|
+
// control element props
|
|
53
|
+
P extends BaseElementProps<K, V, U> = BaseElementProps<K, V, U>,
|
|
54
|
+
>(input: DefineBaseElementInput<T>): BaseElement<P, ElementRefType<P>> {
|
|
55
|
+
const { displayName, type } = input;
|
|
56
|
+
|
|
57
|
+
const Element = React.forwardRef<ElementRefType<P>, P>(
|
|
58
|
+
({ variant, ...props }, ref) => {
|
|
59
|
+
const Element = React.useContext(ElementsContext)?.[displayName];
|
|
60
|
+
|
|
61
|
+
if (Element) {
|
|
62
|
+
// only pass `variant` to provided `Element` values
|
|
63
|
+
return <Element {...{ ...props, ref, variant }} />;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return React.createElement(type, { ...props, ref });
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
Element.displayName = displayName;
|
|
71
|
+
|
|
72
|
+
return Element;
|
|
73
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @internal @unstable
|
|
5
|
+
*
|
|
6
|
+
* Base type definition of `BaseElement` components available through
|
|
7
|
+
* `ElementsContext`. The definitions define a contract between a
|
|
8
|
+
* Connected Component and the `elements` that can be provided as
|
|
9
|
+
* overrides.
|
|
10
|
+
*
|
|
11
|
+
* `BaseElement` interfaces surface a minimal set of HTML semantic `props`
|
|
12
|
+
* required to achieve the base functionality of consumers. `props`
|
|
13
|
+
* are always optional at the interface level, allowing for additional `props`
|
|
14
|
+
* to be added to existing `BaseElement` interfaces as needed.
|
|
15
|
+
*/
|
|
16
|
+
export type BaseElement<T = {}, K = {}> = React.ForwardRefExoticComponent<
|
|
17
|
+
React.PropsWithoutRef<T> & React.RefAttributes<K>
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
type ListElementSubType = 'Ordered' | 'Unordered';
|
|
21
|
+
type ListElementDisplayName = 'List' | `${ListElementSubType}List`;
|
|
22
|
+
|
|
23
|
+
type TableElementSubType = 'Body' | 'Data' | 'Row' | 'Head' | 'Header';
|
|
24
|
+
type TableElementDisplayName = 'Table' | `Table${TableElementSubType}`;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @internal @unstable
|
|
28
|
+
*
|
|
29
|
+
* allowed values of `displayName` of `BaseElement` and `ElemebtsContext` keys
|
|
30
|
+
*/
|
|
31
|
+
export type ElementDisplayName =
|
|
32
|
+
| 'Button'
|
|
33
|
+
| 'Divider'
|
|
34
|
+
| 'Heading' // h1, h2, etc
|
|
35
|
+
| 'Icon'
|
|
36
|
+
| 'Input'
|
|
37
|
+
| 'Label'
|
|
38
|
+
| 'ListItem'
|
|
39
|
+
| 'Nav'
|
|
40
|
+
| 'ProgressBar'
|
|
41
|
+
| 'Span'
|
|
42
|
+
| 'Text'
|
|
43
|
+
| 'Title'
|
|
44
|
+
| 'View'
|
|
45
|
+
| ListElementDisplayName
|
|
46
|
+
| TableElementDisplayName;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @internal @unstable
|
|
50
|
+
*/
|
|
51
|
+
export type ElementRefType<T> = T extends {
|
|
52
|
+
ref?:
|
|
53
|
+
| React.LegacyRef<infer K>
|
|
54
|
+
| React.Ref<infer K>
|
|
55
|
+
| React.ForwardedRef<infer K>;
|
|
56
|
+
}
|
|
57
|
+
? K
|
|
58
|
+
: never;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @internal @unstable
|
|
62
|
+
*/
|
|
63
|
+
export type ReactElementType = keyof React.JSX.IntrinsicElements;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @internal @unstable
|
|
67
|
+
*/
|
|
68
|
+
export type ReactElementProps<T extends ReactElementType> =
|
|
69
|
+
React.JSX.IntrinsicElements[T];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @internal @unstable
|
|
73
|
+
*
|
|
74
|
+
* key of `props` always available on `BaseElement` definitions
|
|
75
|
+
*/
|
|
76
|
+
type ElementPropKey<T> = T | 'children' | 'className' | 'style';
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @internal @unstable
|
|
80
|
+
*/
|
|
81
|
+
export type BaseElementProps<
|
|
82
|
+
T extends keyof K,
|
|
83
|
+
V = string,
|
|
84
|
+
K extends Record<ElementPropKey<keyof K>, any> = Record<string, any>,
|
|
85
|
+
> = React.AriaAttributes &
|
|
86
|
+
React.RefAttributes<ElementRefType<K>> &
|
|
87
|
+
Pick<K, ElementPropKey<T>> & { testId?: string; variant?: V };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BaseElement, ElementRefType } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal @unstable
|
|
6
|
+
*
|
|
7
|
+
* Extend target `BaseElement` with `defaultProps`. `defaultProps`
|
|
8
|
+
* are overidden by `props` provided to returned `BaseElement`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
*
|
|
12
|
+
* Extend `InputElement` with default `className` and `type`
|
|
13
|
+
* ```tsx
|
|
14
|
+
*
|
|
15
|
+
* // define extended `props` on `BaseElement` interface
|
|
16
|
+
* type InputElementPropKey = 'onChange' | 'type';
|
|
17
|
+
*
|
|
18
|
+
* // create `InputElement` base with `type` generic and extended `props` key
|
|
19
|
+
* export const InputElement = defineBaseElement<"input", InputElementPropKey>({
|
|
20
|
+
* type: "input",
|
|
21
|
+
* displayName: "Input",
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // extend base `InputElement` with default input `type` of `checkbox`
|
|
25
|
+
* const CheckboxElement = withBaseElementProps(Input, {
|
|
26
|
+
* className: 'submit-toggle__checkbox',
|
|
27
|
+
* type: 'checkbox',
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param Target `BaseElement` to extend
|
|
32
|
+
* @param defaultProps `defaultProps` to apply to `Target`, accepts object or callback
|
|
33
|
+
* @returns extended `BaseElement` with `defaultProps`
|
|
34
|
+
*/
|
|
35
|
+
export default function withBaseElementProps<
|
|
36
|
+
T,
|
|
37
|
+
K extends T | ((input: T) => T),
|
|
38
|
+
>(
|
|
39
|
+
Target: React.ForwardRefExoticComponent<T>,
|
|
40
|
+
defaultProps: K
|
|
41
|
+
): BaseElement<T, ElementRefType<T>> {
|
|
42
|
+
const Component = React.forwardRef<ElementRefType<T>, T>((props, ref) => (
|
|
43
|
+
<Target
|
|
44
|
+
{...{
|
|
45
|
+
...(typeof defaultProps === 'function'
|
|
46
|
+
? defaultProps(props)
|
|
47
|
+
: defaultProps),
|
|
48
|
+
...props,
|
|
49
|
+
}}
|
|
50
|
+
ref={ref}
|
|
51
|
+
/>
|
|
52
|
+
));
|
|
53
|
+
Component.displayName = Target.displayName;
|
|
54
|
+
return Component;
|
|
55
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface DataState<T> {
|
|
4
|
+
data: T;
|
|
5
|
+
hasError: boolean;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
message: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// default state
|
|
11
|
+
const INITIAL_STATE = { hasError: false, isLoading: false, message: undefined };
|
|
12
|
+
const LOADING_STATE = { hasError: false, isLoading: true, message: undefined };
|
|
13
|
+
const ERROR_STATE = { hasError: true, isLoading: false };
|
|
14
|
+
|
|
15
|
+
const resolveMaybeAsync = async <T>(
|
|
16
|
+
value: T | Promise<T>
|
|
17
|
+
): Promise<Awaited<T>> => {
|
|
18
|
+
const awaited = await value;
|
|
19
|
+
return awaited;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function useDataState<T, K>(
|
|
23
|
+
action: (prevData: T, ...input: K[]) => T | Promise<T>,
|
|
24
|
+
initialData: T
|
|
25
|
+
): [state: DataState<T>, handleAction: (...input: K[]) => void] {
|
|
26
|
+
const [dataState, setDataState] = React.useState<DataState<T>>(() => ({
|
|
27
|
+
...INITIAL_STATE,
|
|
28
|
+
data: initialData,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const prevData = React.useRef(initialData);
|
|
32
|
+
|
|
33
|
+
const handleAction: (...input: K[]) => void = React.useCallback(
|
|
34
|
+
(...input) => {
|
|
35
|
+
setDataState(({ data }) => ({ ...LOADING_STATE, data }));
|
|
36
|
+
|
|
37
|
+
resolveMaybeAsync(action(prevData.current, ...input))
|
|
38
|
+
.then((data: T) => {
|
|
39
|
+
prevData.current = data;
|
|
40
|
+
setDataState({ ...INITIAL_STATE, data });
|
|
41
|
+
})
|
|
42
|
+
.catch(({ message }: Error) => {
|
|
43
|
+
setDataState(({ data }) => ({ ...ERROR_STATE, data, message }));
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
[action]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return [dataState, handleAction];
|
|
50
|
+
}
|