@aws-amplify/ui-react-core 3.0.29 → 3.1.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/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/hooks/useDropZone.mjs +13 -4
- package/dist/esm/utils/createContextUtilities.mjs +6 -3
- package/dist/esm/utils/processDroppedItems.mjs +66 -0
- package/dist/index.js +92 -11
- 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/dist/types/utils/processDroppedItems.d.ts +1 -0
- 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/hooks/useDropZone.ts +18 -7
- package/src/index.ts +2 -0
- package/src/utils/createContextUtilities.tsx +9 -6
- package/src/utils/processDroppedItems.ts +79 -0
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
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { isFunction } from '@aws-amplify/ui';
|
|
3
3
|
import { filterAllowedFiles } from '../utils/filterAllowedFiles.mjs';
|
|
4
|
+
import { processDroppedItems } from '../utils/processDroppedItems.mjs';
|
|
4
5
|
|
|
5
6
|
function useDropZone({ onDropComplete, onDragEnter: _onDragEnter, onDragLeave: _onDragLeave, onDragOver: _onDragOver, onDragStart: _onDragStart, onDrop: _onDrop, acceptedFileTypes = [], }) {
|
|
6
7
|
const [dragState, setDragState] = useState('inactive');
|
|
@@ -43,13 +44,21 @@ function useDropZone({ onDropComplete, onDragEnter: _onDragEnter, onDragLeave: _
|
|
|
43
44
|
event.preventDefault();
|
|
44
45
|
event.stopPropagation();
|
|
45
46
|
setDragState('inactive');
|
|
46
|
-
const files =
|
|
47
|
-
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(files, acceptedFileTypes);
|
|
47
|
+
const { files, items } = event.dataTransfer;
|
|
48
48
|
if (isFunction(_onDrop)) {
|
|
49
49
|
_onDrop(event);
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const completeDrop = (files) => {
|
|
52
|
+
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(files, acceptedFileTypes);
|
|
53
|
+
if (isFunction(onDropComplete)) {
|
|
54
|
+
onDropComplete({ acceptedFiles, rejectedFiles });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
if (!items) {
|
|
58
|
+
completeDrop(Array.from(files));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
processDroppedItems(Array.from(items)).then(completeDrop);
|
|
53
62
|
}
|
|
54
63
|
};
|
|
55
64
|
return {
|
|
@@ -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
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Helper function to convert FileSystemFileEntry to File
|
|
2
|
+
const getFileFromEntry = (fileEntry) => {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
fileEntry.file(resolve);
|
|
5
|
+
});
|
|
6
|
+
};
|
|
7
|
+
// Helper function to read all entries in a directory
|
|
8
|
+
const readAllDirectoryEntries = async (dirReader) => {
|
|
9
|
+
const entries = [];
|
|
10
|
+
let readBatch = [];
|
|
11
|
+
do {
|
|
12
|
+
readBatch = await new Promise((resolve, reject) => {
|
|
13
|
+
try {
|
|
14
|
+
dirReader.readEntries(resolve, reject);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
reject(error);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
entries.push(...readBatch);
|
|
21
|
+
} while (readBatch.length > 0);
|
|
22
|
+
return entries;
|
|
23
|
+
};
|
|
24
|
+
// Helper function to process files and folder contents
|
|
25
|
+
async function processDroppedItems(dataTransferItems) {
|
|
26
|
+
const files = [];
|
|
27
|
+
const processFileSystemEntry = async (entry) => {
|
|
28
|
+
if (entry.isFile) {
|
|
29
|
+
const file = await getFileFromEntry(entry);
|
|
30
|
+
// drag and dropped files do not have a webkitRelativePath property,
|
|
31
|
+
// but they do have a fullPath property which has the same information
|
|
32
|
+
// https://github.com/ant-design/ant-design/issues/16426
|
|
33
|
+
if (entry.fullPath && !file.webkitRelativePath) {
|
|
34
|
+
Object.defineProperties(file, {
|
|
35
|
+
webkitRelativePath: {
|
|
36
|
+
writable: true,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
// intentionally overwriting webkitRelativePath
|
|
40
|
+
// @ts-expect-error
|
|
41
|
+
file.webkitRelativePath = entry.fullPath.replace(/^\//, '');
|
|
42
|
+
Object.defineProperties(file, {
|
|
43
|
+
webkitRelativePath: {
|
|
44
|
+
writable: false,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
files.push(file);
|
|
49
|
+
}
|
|
50
|
+
else if (entry.isDirectory) {
|
|
51
|
+
const dirReader = entry.createReader();
|
|
52
|
+
const dirEntries = await readAllDirectoryEntries(dirReader);
|
|
53
|
+
await Promise.all(dirEntries.map(processFileSystemEntry));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// Filter out and process files from the data transfer items
|
|
57
|
+
await Promise.all(dataTransferItems
|
|
58
|
+
.reduce((acc, item) => {
|
|
59
|
+
const entry = item.webkitGetAsEntry();
|
|
60
|
+
return item.kind === 'file' && entry ? [...acc, entry] : acc;
|
|
61
|
+
}, [])
|
|
62
|
+
.map(processFileSystemEntry));
|
|
63
|
+
return files;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { processDroppedItems };
|
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
|
|
|
@@ -726,6 +731,71 @@ function filterAllowedFiles(files, acceptedFileTypes) {
|
|
|
726
731
|
return { acceptedFiles, rejectedFiles };
|
|
727
732
|
}
|
|
728
733
|
|
|
734
|
+
// Helper function to convert FileSystemFileEntry to File
|
|
735
|
+
const getFileFromEntry = (fileEntry) => {
|
|
736
|
+
return new Promise((resolve) => {
|
|
737
|
+
fileEntry.file(resolve);
|
|
738
|
+
});
|
|
739
|
+
};
|
|
740
|
+
// Helper function to read all entries in a directory
|
|
741
|
+
const readAllDirectoryEntries = async (dirReader) => {
|
|
742
|
+
const entries = [];
|
|
743
|
+
let readBatch = [];
|
|
744
|
+
do {
|
|
745
|
+
readBatch = await new Promise((resolve, reject) => {
|
|
746
|
+
try {
|
|
747
|
+
dirReader.readEntries(resolve, reject);
|
|
748
|
+
}
|
|
749
|
+
catch (error) {
|
|
750
|
+
reject(error);
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
entries.push(...readBatch);
|
|
754
|
+
} while (readBatch.length > 0);
|
|
755
|
+
return entries;
|
|
756
|
+
};
|
|
757
|
+
// Helper function to process files and folder contents
|
|
758
|
+
async function processDroppedItems(dataTransferItems) {
|
|
759
|
+
const files = [];
|
|
760
|
+
const processFileSystemEntry = async (entry) => {
|
|
761
|
+
if (entry.isFile) {
|
|
762
|
+
const file = await getFileFromEntry(entry);
|
|
763
|
+
// drag and dropped files do not have a webkitRelativePath property,
|
|
764
|
+
// but they do have a fullPath property which has the same information
|
|
765
|
+
// https://github.com/ant-design/ant-design/issues/16426
|
|
766
|
+
if (entry.fullPath && !file.webkitRelativePath) {
|
|
767
|
+
Object.defineProperties(file, {
|
|
768
|
+
webkitRelativePath: {
|
|
769
|
+
writable: true,
|
|
770
|
+
},
|
|
771
|
+
});
|
|
772
|
+
// intentionally overwriting webkitRelativePath
|
|
773
|
+
// @ts-expect-error
|
|
774
|
+
file.webkitRelativePath = entry.fullPath.replace(/^\//, '');
|
|
775
|
+
Object.defineProperties(file, {
|
|
776
|
+
webkitRelativePath: {
|
|
777
|
+
writable: false,
|
|
778
|
+
},
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
files.push(file);
|
|
782
|
+
}
|
|
783
|
+
else if (entry.isDirectory) {
|
|
784
|
+
const dirReader = entry.createReader();
|
|
785
|
+
const dirEntries = await readAllDirectoryEntries(dirReader);
|
|
786
|
+
await Promise.all(dirEntries.map(processFileSystemEntry));
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
// Filter out and process files from the data transfer items
|
|
790
|
+
await Promise.all(dataTransferItems
|
|
791
|
+
.reduce((acc, item) => {
|
|
792
|
+
const entry = item.webkitGetAsEntry();
|
|
793
|
+
return item.kind === 'file' && entry ? [...acc, entry] : acc;
|
|
794
|
+
}, [])
|
|
795
|
+
.map(processFileSystemEntry));
|
|
796
|
+
return files;
|
|
797
|
+
}
|
|
798
|
+
|
|
729
799
|
function useDropZone({ onDropComplete, onDragEnter: _onDragEnter, onDragLeave: _onDragLeave, onDragOver: _onDragOver, onDragStart: _onDragStart, onDrop: _onDrop, acceptedFileTypes = [], }) {
|
|
730
800
|
const [dragState, setDragState] = React.useState('inactive');
|
|
731
801
|
const onDragStart = (event) => {
|
|
@@ -767,13 +837,21 @@ function useDropZone({ onDropComplete, onDragEnter: _onDragEnter, onDragLeave: _
|
|
|
767
837
|
event.preventDefault();
|
|
768
838
|
event.stopPropagation();
|
|
769
839
|
setDragState('inactive');
|
|
770
|
-
const files =
|
|
771
|
-
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(files, acceptedFileTypes);
|
|
840
|
+
const { files, items } = event.dataTransfer;
|
|
772
841
|
if (ui.isFunction(_onDrop)) {
|
|
773
842
|
_onDrop(event);
|
|
774
843
|
}
|
|
775
|
-
|
|
776
|
-
|
|
844
|
+
const completeDrop = (files) => {
|
|
845
|
+
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(files, acceptedFileTypes);
|
|
846
|
+
if (ui.isFunction(onDropComplete)) {
|
|
847
|
+
onDropComplete({ acceptedFiles, rejectedFiles });
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
if (!items) {
|
|
851
|
+
completeDrop(Array.from(files));
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
processDroppedItems(Array.from(items)).then(completeDrop);
|
|
777
855
|
}
|
|
778
856
|
};
|
|
779
857
|
return {
|
|
@@ -838,7 +916,10 @@ function createContextUtilities(options) {
|
|
|
838
916
|
if (ui.isUndefined(defaultValue) && !ui.isString(errorMessage)) {
|
|
839
917
|
throw new Error(INVALID_OPTIONS_MESSAGE);
|
|
840
918
|
}
|
|
919
|
+
const contextDisplayName = `${contextName}Context`;
|
|
920
|
+
const providerDisplayName = `${contextName}Provider`;
|
|
841
921
|
const Context = React__namespace["default"].createContext(defaultValue);
|
|
922
|
+
Context.displayName = contextDisplayName;
|
|
842
923
|
function Provider(props) {
|
|
843
924
|
const { children, ...context } = props;
|
|
844
925
|
const value = React__namespace["default"].useMemo(() => context,
|
|
@@ -848,7 +929,7 @@ function createContextUtilities(options) {
|
|
|
848
929
|
Object.values(context));
|
|
849
930
|
return React__namespace["default"].createElement(Context.Provider, { value: value }, children);
|
|
850
931
|
}
|
|
851
|
-
Provider.displayName =
|
|
932
|
+
Provider.displayName = providerDisplayName;
|
|
852
933
|
return {
|
|
853
934
|
[`use${contextName}`]: function (params) {
|
|
854
935
|
const context = React__namespace["default"].useContext(Context);
|
|
@@ -857,8 +938,8 @@ function createContextUtilities(options) {
|
|
|
857
938
|
}
|
|
858
939
|
return context;
|
|
859
940
|
},
|
|
860
|
-
[
|
|
861
|
-
[
|
|
941
|
+
[providerDisplayName]: Provider,
|
|
942
|
+
[contextDisplayName]: Context,
|
|
862
943
|
};
|
|
863
944
|
}
|
|
864
945
|
|