@react-fabric/form 1.0.0-beta.60 → 1.0.0-beta.62
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/cjs/builder/FileField.js +10 -7
- package/dist/cjs/builder/components/AddSchemaFields.js +2 -1
- package/dist/cjs/builder/components/SchemaArrayForm.js +4 -4
- package/dist/cjs/builder/components/SchemaField.js +4 -4
- package/dist/cjs/form/Form.js +44 -22
- package/dist/cjs/hooks/useFileUploader.js +40 -28
- package/dist/cjs/hooks/useFormBuilder.js +10 -3
- package/dist/cjs/i18n/index.js +4 -4
- package/dist/cjs/input/ArrayInput.js +3 -3
- package/dist/cjs/input/AvatarInput.js +17 -12
- package/dist/cjs/input/Checkbox.js +2 -2
- package/dist/cjs/input/ColorInput.js +2 -2
- package/dist/cjs/input/File.js +1 -1
- package/dist/cjs/input/Hidden.js +1 -10
- package/dist/cjs/input/Password.js +1 -1
- package/dist/cjs/input/Radio.js +2 -2
- package/dist/cjs/input/RadioGroup.js +3 -1
- package/dist/cjs/input/Search.js +2 -3
- package/dist/cjs/internal/ErrorIcon.js +1 -1
- package/dist/cjs/internal/InputWrapper.js +3 -3
- package/dist/cjs/select/AutoComplete.js +1 -2
- package/dist/cjs/select/DualList.js +5 -5
- package/dist/cjs/select/List.js +8 -24
- package/dist/cjs/select/Select.js +9 -28
- package/dist/esm/builder/FileField.js +11 -8
- package/dist/esm/builder/components/AddSchemaFields.js +2 -1
- package/dist/esm/builder/components/SchemaArrayForm.js +5 -5
- package/dist/esm/builder/components/SchemaField.js +5 -5
- package/dist/esm/form/Form.js +44 -22
- package/dist/esm/hooks/useFileUploader.js +41 -29
- package/dist/esm/hooks/useFormBuilder.js +10 -3
- package/dist/esm/i18n/index.js +2 -2
- package/dist/esm/input/ArrayInput.js +4 -4
- package/dist/esm/input/AvatarInput.js +18 -13
- package/dist/esm/input/Checkbox.js +3 -3
- package/dist/esm/input/ColorInput.js +3 -3
- package/dist/esm/input/File.js +2 -2
- package/dist/esm/input/Hidden.js +2 -11
- package/dist/esm/input/Password.js +2 -2
- package/dist/esm/input/Radio.js +3 -3
- package/dist/esm/input/RadioGroup.js +3 -1
- package/dist/esm/input/Search.js +3 -4
- package/dist/esm/internal/ErrorIcon.js +2 -2
- package/dist/esm/internal/InputWrapper.js +4 -4
- package/dist/esm/select/AutoComplete.js +2 -3
- package/dist/esm/select/DualList.js +6 -6
- package/dist/esm/select/List.js +8 -24
- package/dist/esm/select/Select.js +10 -29
- package/dist/types/builder/FileField.d.ts +2 -1
- package/dist/types/form/Form.d.ts +11 -10
- package/dist/types/hooks/useFileUploader.d.ts +4 -2
- package/dist/types/hooks/useFormBuilder.d.ts +6 -0
- package/dist/types/input/AvatarInput.d.ts +2 -2
- package/dist/types/input/Hidden.d.ts +3 -11
- package/dist/types/input/RadioGroup.d.ts +5 -1
- package/dist/types/select/DualList.d.ts +5 -6
- package/dist/types/select/Options.d.ts +1 -1
- package/dist/types/types/index.d.ts +7 -8
- package/package.json +5 -5
- package/src/builder/FileField.tsx +8 -12
- package/src/builder/components/AddSchemaFields.tsx +2 -1
- package/src/builder/components/SchemaArrayForm.tsx +5 -11
- package/src/builder/components/SchemaField.tsx +4 -5
- package/src/form/Form.tsx +30 -24
- package/src/hooks/useFileUploader.ts +41 -29
- package/src/hooks/useFormBuilder.tsx +12 -4
- package/src/i18n/index.ts +2 -2
- package/src/input/ArrayInput.tsx +4 -10
- package/src/input/AvatarInput.tsx +16 -16
- package/src/input/Checkbox.tsx +6 -3
- package/src/input/ColorInput.tsx +3 -7
- package/src/input/File.tsx +2 -2
- package/src/input/Hidden.tsx +4 -22
- package/src/input/Password.tsx +4 -2
- package/src/input/Radio.tsx +3 -3
- package/src/input/RadioGroup.tsx +6 -0
- package/src/input/Search.tsx +3 -3
- package/src/internal/ErrorIcon.tsx +2 -2
- package/src/internal/InputWrapper.tsx +8 -4
- package/src/select/AutoComplete.tsx +2 -3
- package/src/select/DualList.tsx +15 -12
- package/src/select/List.tsx +3 -3
- package/src/select/Options.tsx +1 -1
- package/src/select/Select.tsx +7 -8
- package/src/types/index.ts +8 -7
- /package/dist/cjs/i18n/{ar.json.js → ar/form.json.js} +0 -0
- /package/dist/cjs/i18n/{en.json.js → en/form.json.js} +0 -0
- /package/dist/esm/i18n/{ar.json.js → ar/form.json.js} +0 -0
- /package/dist/esm/i18n/{en.json.js → en/form.json.js} +0 -0
- /package/src/i18n/{ar.json → ar/form.json} +0 -0
- /package/src/i18n/{en.json → en/form.json} +0 -0
package/src/form/Form.tsx
CHANGED
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { yupResolver } from "@hookform/resolvers/yup";
|
|
25
24
|
import { useDebounce } from "@react-fabric/core";
|
|
26
|
-
import { EMPTY_OBJECT
|
|
25
|
+
import { EMPTY_OBJECT } from "@react-fabric/utilities";
|
|
27
26
|
import {
|
|
28
27
|
useCallback,
|
|
29
28
|
useEffect,
|
|
@@ -35,12 +34,12 @@ import {
|
|
|
35
34
|
} from "react";
|
|
36
35
|
import {
|
|
37
36
|
FormProvider,
|
|
38
|
-
type Path,
|
|
39
37
|
useFormContext,
|
|
40
38
|
useForm as useFormHook,
|
|
41
39
|
useWatch,
|
|
42
|
-
type DefaultValues,
|
|
43
40
|
type FormState,
|
|
41
|
+
type Path,
|
|
42
|
+
type Resolver,
|
|
44
43
|
} from "react-hook-form";
|
|
45
44
|
|
|
46
45
|
type NestedKeyOf<T extends object> = {
|
|
@@ -63,13 +62,18 @@ export interface FormRef<K extends KeyValue> {
|
|
|
63
62
|
export interface FormProps<K extends KeyValue = KeyValue> {
|
|
64
63
|
formRef?: Ref<FormRef<K>>;
|
|
65
64
|
/**
|
|
66
|
-
* form
|
|
65
|
+
* react-hook-form resolver for validation
|
|
66
|
+
* @see {@link https://react-hook-form.com/ts#Resolver}
|
|
67
67
|
*/
|
|
68
|
-
|
|
68
|
+
resolver?: Resolver<K>;
|
|
69
69
|
/**
|
|
70
70
|
* default data values
|
|
71
71
|
*/
|
|
72
|
-
defaultValues?: K
|
|
72
|
+
defaultValues?: K | Promise<K>;
|
|
73
|
+
/**
|
|
74
|
+
* reset values on defaultValues change (workaround for using fetch result)
|
|
75
|
+
*/
|
|
76
|
+
resetOnChange?: boolean;
|
|
73
77
|
/**
|
|
74
78
|
* change callback
|
|
75
79
|
*/
|
|
@@ -94,10 +98,7 @@ const DEFAULT_SUBMIT = () => undefined;
|
|
|
94
98
|
* ```jsx
|
|
95
99
|
* <Form
|
|
96
100
|
* formRef={formRef}
|
|
97
|
-
*
|
|
98
|
-
* name: yup.string().required("Name is required"),
|
|
99
|
-
* email: yup.string().email("Invalid email").required("Email is required"),
|
|
100
|
-
* })}
|
|
101
|
+
* resolver={hookformResolver(schema)}
|
|
101
102
|
* defaultValues={{ name: "", email: "" }}
|
|
102
103
|
* onSubmit={(values) => {
|
|
103
104
|
* console.log("Form submitted with values:", values);
|
|
@@ -115,8 +116,9 @@ const DEFAULT_SUBMIT = () => undefined;
|
|
|
115
116
|
*/
|
|
116
117
|
export const Form = <K extends KeyValue>({
|
|
117
118
|
formRef,
|
|
118
|
-
|
|
119
|
+
resolver,
|
|
119
120
|
children,
|
|
121
|
+
resetOnChange,
|
|
120
122
|
defaultValues = EMPTY_OBJECT as K,
|
|
121
123
|
onSubmit = DEFAULT_SUBMIT,
|
|
122
124
|
onChange,
|
|
@@ -125,8 +127,8 @@ export const Form = <K extends KeyValue>({
|
|
|
125
127
|
const ref = useRef<HTMLFormElement>(null);
|
|
126
128
|
const form = useFormHook<K>({
|
|
127
129
|
shouldFocusError: true,
|
|
128
|
-
resolver
|
|
129
|
-
defaultValues:
|
|
130
|
+
resolver,
|
|
131
|
+
defaultValues: async () => await Promise.resolve(defaultValues),
|
|
130
132
|
});
|
|
131
133
|
|
|
132
134
|
const [, startTransition] = useTransition();
|
|
@@ -138,16 +140,19 @@ export const Form = <K extends KeyValue>({
|
|
|
138
140
|
return () => subscription.unsubscribe();
|
|
139
141
|
}, [form.watch, changeHandler]);
|
|
140
142
|
|
|
141
|
-
const handleReset = useCallback(
|
|
142
|
-
(reset
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
const handleReset = useCallback((reset: AnyObject = {}) => {
|
|
144
|
+
form.reset(reset);
|
|
145
|
+
form.clearErrors();
|
|
146
|
+
ref.current
|
|
147
|
+
?.querySelector<HTMLElement>("[auto-focus], input, textarea")
|
|
148
|
+
?.focus();
|
|
149
|
+
}, []);
|
|
150
|
+
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (resetOnChange) {
|
|
153
|
+
handleReset(defaultValues);
|
|
154
|
+
}
|
|
155
|
+
}, [defaultValues, resetOnChange]);
|
|
151
156
|
|
|
152
157
|
useImperativeHandle(
|
|
153
158
|
formRef,
|
|
@@ -174,6 +179,7 @@ export const Form = <K extends KeyValue>({
|
|
|
174
179
|
|
|
175
180
|
const onInvalid = useCallback((_: AnyObject, e: AnyObject) => {
|
|
176
181
|
const el = e.target;
|
|
182
|
+
console.log("Invalid:", _, e);
|
|
177
183
|
setTimeout(
|
|
178
184
|
() =>
|
|
179
185
|
el
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { isArray, isObject, isString, uuid } from "@react-fabric/utilities";
|
|
25
25
|
import { type AxiosRequestConfig } from "axios";
|
|
26
|
-
import { useCallback, useReducer } from "react";
|
|
26
|
+
import { useCallback, useEffect, useReducer } from "react";
|
|
27
27
|
|
|
28
28
|
export type UploadHandler = (
|
|
29
29
|
data: FormData,
|
|
@@ -54,6 +54,7 @@ type UploaderActions =
|
|
|
54
54
|
| { type: "stop"; key: string; path: string }
|
|
55
55
|
| { type: "error"; key: string; error: string }
|
|
56
56
|
| { type: "progress"; key: string; progress: number }
|
|
57
|
+
| { type: "init"; initialList?: string | FileInfo | FileInfo[] }
|
|
57
58
|
| { type: "remove"; key: string }
|
|
58
59
|
| { type: "abort"; key: string };
|
|
59
60
|
|
|
@@ -76,7 +77,13 @@ type UploaderActions =
|
|
|
76
77
|
export const useFileUploader = (
|
|
77
78
|
uploader: UploadHandler,
|
|
78
79
|
initialList?: string | FileInfo | FileInfo[],
|
|
79
|
-
|
|
80
|
+
{
|
|
81
|
+
multiple = true,
|
|
82
|
+
onChange,
|
|
83
|
+
}: {
|
|
84
|
+
multiple?: boolean;
|
|
85
|
+
onChange?: (files: FileInfo[] | FileInfo | null) => void;
|
|
86
|
+
} = {},
|
|
80
87
|
) => {
|
|
81
88
|
const [state, dispatch] = useReducer(
|
|
82
89
|
(state: UploaderState, action: UploaderActions) => {
|
|
@@ -119,6 +126,29 @@ export const useFileUploader = (
|
|
|
119
126
|
if (action.type === "remove") {
|
|
120
127
|
state.files.delete(action.key);
|
|
121
128
|
}
|
|
129
|
+
if (action.type === "init") {
|
|
130
|
+
state.files = new Map();
|
|
131
|
+
if (isString(action.initialList)) {
|
|
132
|
+
const key = uuid();
|
|
133
|
+
state.files.set(key, {
|
|
134
|
+
key,
|
|
135
|
+
path: action.initialList,
|
|
136
|
+
filename: "",
|
|
137
|
+
size: 0,
|
|
138
|
+
mime: "",
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (isObject(action.initialList)) {
|
|
142
|
+
const key = uuid();
|
|
143
|
+
state.files.set(key, { ...(action.initialList as AnyObject), key });
|
|
144
|
+
}
|
|
145
|
+
if (isArray(action.initialList)) {
|
|
146
|
+
action.initialList.forEach((file) => {
|
|
147
|
+
const key = uuid();
|
|
148
|
+
state.files.set(key, { ...file, key });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
122
152
|
state.list = Array.from(state.files.values())
|
|
123
153
|
.map((file) => {
|
|
124
154
|
return (
|
|
@@ -134,40 +164,23 @@ export const useFileUploader = (
|
|
|
134
164
|
);
|
|
135
165
|
})
|
|
136
166
|
.filter(Boolean) as FileInfo[];
|
|
167
|
+
if (action.type === "remove" || action.type === "stop") {
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
onChange?.(multiple ? state.list : state.list[0] ?? null);
|
|
170
|
+
}, 100);
|
|
171
|
+
}
|
|
137
172
|
return { ...state };
|
|
138
173
|
},
|
|
139
174
|
{
|
|
140
175
|
files: new Map(),
|
|
141
176
|
count: 0,
|
|
142
177
|
} as UploaderState,
|
|
143
|
-
(state: UploaderState) => {
|
|
144
|
-
if (initialList) {
|
|
145
|
-
if (isString(initialList)) {
|
|
146
|
-
const key = uuid();
|
|
147
|
-
state.files.set(key, {
|
|
148
|
-
key,
|
|
149
|
-
path: initialList,
|
|
150
|
-
filename: "",
|
|
151
|
-
size: 0,
|
|
152
|
-
mime: "",
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
if (isObject(initialList)) {
|
|
156
|
-
const key = uuid();
|
|
157
|
-
state.files.set(key, { ...(initialList as AnyObject), key });
|
|
158
|
-
}
|
|
159
|
-
if (isArray(initialList)) {
|
|
160
|
-
initialList.forEach((file) => {
|
|
161
|
-
const key = uuid();
|
|
162
|
-
state.files.set(key, { ...file, key });
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
state.list = Array.from(state.files.values());
|
|
167
|
-
return state;
|
|
168
|
-
},
|
|
169
178
|
);
|
|
170
179
|
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
dispatch({ type: "init", initialList });
|
|
182
|
+
}, [initialList]);
|
|
183
|
+
|
|
171
184
|
const doUpload = useCallback(async (key: string, file: File) => {
|
|
172
185
|
const data = new FormData();
|
|
173
186
|
data.append("file", file);
|
|
@@ -244,7 +257,6 @@ export const useFileUploader = (
|
|
|
244
257
|
remove,
|
|
245
258
|
retry,
|
|
246
259
|
pending: state.count,
|
|
247
|
-
list: state.list,
|
|
248
260
|
files: Array.from(state.files.values()),
|
|
249
261
|
};
|
|
250
262
|
};
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
+
import { yupResolver } from "@hookform/resolvers/yup";
|
|
24
25
|
import { EmptyContent } from "@react-fabric/core";
|
|
25
26
|
import { isEmpty, isNil, yup } from "@react-fabric/utilities";
|
|
26
27
|
import { Fragment, useMemo } from "react";
|
|
@@ -135,12 +136,18 @@ export const useFormBuilder = <T extends AnyObject = string>(
|
|
|
135
136
|
() => schema.filter?.((schm) => !!schm.id) ?? [],
|
|
136
137
|
[schema],
|
|
137
138
|
);
|
|
138
|
-
const schemaDef =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
const schemaDef = useMemo(
|
|
140
|
+
() =>
|
|
141
|
+
yup.object(
|
|
142
|
+
Object.fromEntries(
|
|
143
|
+
filteredSchema.map((field) => [field.id, makeYupField(field)]),
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
[filteredSchema],
|
|
142
147
|
);
|
|
143
148
|
|
|
149
|
+
const resolver = useMemo(() => yupResolver(schemaDef), [schemaDef]);
|
|
150
|
+
|
|
144
151
|
const formDef = (
|
|
145
152
|
<Fragment>
|
|
146
153
|
{filteredSchema.map((field, idx) => (
|
|
@@ -166,6 +173,7 @@ export const useFormBuilder = <T extends AnyObject = string>(
|
|
|
166
173
|
|
|
167
174
|
return {
|
|
168
175
|
formDef,
|
|
176
|
+
resolver,
|
|
169
177
|
schemaDef,
|
|
170
178
|
};
|
|
171
179
|
};
|
package/src/i18n/index.ts
CHANGED
package/src/input/ArrayInput.tsx
CHANGED
|
@@ -23,13 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { DndContext, type DragEndEvent } from "@dnd-kit/core";
|
|
25
25
|
import { SortableContext, useSortable } from "@dnd-kit/sortable";
|
|
26
|
-
import {
|
|
27
|
-
Button,
|
|
28
|
-
cloneChildren,
|
|
29
|
-
CoreIcons,
|
|
30
|
-
Icon,
|
|
31
|
-
Tooltip,
|
|
32
|
-
} from "@react-fabric/core";
|
|
26
|
+
import { Button, cloneChildren, Icon, Tooltip } from "@react-fabric/core";
|
|
33
27
|
import { isFalse, isString } from "@react-fabric/utilities";
|
|
34
28
|
import classNames from "classnames";
|
|
35
29
|
import {
|
|
@@ -328,7 +322,7 @@ export const ArrayInput = <T extends AnyObject = string>({
|
|
|
328
322
|
>
|
|
329
323
|
<Icon
|
|
330
324
|
className={isDragging ? "cursor-grabbing" : "cursor-grab"}
|
|
331
|
-
icon=
|
|
325
|
+
icon="icon-[mdi--drag-vertical]"
|
|
332
326
|
{...attributes}
|
|
333
327
|
{...listeners}
|
|
334
328
|
/>
|
|
@@ -369,7 +363,7 @@ export const ArrayInput = <T extends AnyObject = string>({
|
|
|
369
363
|
<Button
|
|
370
364
|
size="sm"
|
|
371
365
|
aria-label="Add item"
|
|
372
|
-
icon=
|
|
366
|
+
icon="icon-[mdi--plus-circle-outline]"
|
|
373
367
|
onClick={() => handleAdd(onAdd?.())}
|
|
374
368
|
data-invalid={!!error}
|
|
375
369
|
disabled={!!disabled || readOnly || fields.length > maxItems}
|
|
@@ -443,7 +437,7 @@ export const ArrayInput = <T extends AnyObject = string>({
|
|
|
443
437
|
{canRemove !== false && (
|
|
444
438
|
<Button
|
|
445
439
|
aria-label="Remove item"
|
|
446
|
-
icon=
|
|
440
|
+
icon="icon-[mdi--minus-circle-outline]"
|
|
447
441
|
color="danger"
|
|
448
442
|
variant="link"
|
|
449
443
|
className="self-end"
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { Avatar,
|
|
24
|
+
import { Avatar, Icon, ProgressBar } from "@react-fabric/core";
|
|
25
|
+
import { type AvatarProps } from "@react-fabric/core/dist/types/components/avatar/Avatar";
|
|
25
26
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
27
|
+
import classNames from "classnames";
|
|
26
28
|
import { useEffect, useState } from "react";
|
|
27
29
|
import { useFileUploader, type UploadHandler } from "../hooks/useFileUploader";
|
|
28
30
|
import { HiddenInput } from "./Hidden";
|
|
29
|
-
import { type AvatarProps } from "@react-fabric/core/dist/types/components/avatar/Avatar";
|
|
30
|
-
import classNames from "classnames";
|
|
31
31
|
|
|
32
32
|
export interface Props extends RefProp {
|
|
33
33
|
/**
|
|
@@ -88,17 +88,21 @@ export const AvatarInput = ({
|
|
|
88
88
|
variant,
|
|
89
89
|
fileUrl,
|
|
90
90
|
uploadHandler,
|
|
91
|
+
onChange,
|
|
91
92
|
...rest
|
|
92
93
|
}: Props) => {
|
|
93
|
-
const { files,
|
|
94
|
+
const { files, upload, remove } = useFileUploader(
|
|
94
95
|
async (data, config) => await uploadHandler?.(data, config),
|
|
95
|
-
value,
|
|
96
|
-
|
|
96
|
+
value ?? defaultValue,
|
|
97
|
+
{
|
|
98
|
+
multiple: false,
|
|
99
|
+
onChange: (files: AnyObject) => onChange?.(files?.path ?? null),
|
|
100
|
+
},
|
|
97
101
|
);
|
|
98
102
|
|
|
99
103
|
const [base64, setBase64] = useState("");
|
|
100
104
|
useEffect(() => {
|
|
101
|
-
if (
|
|
105
|
+
if (files?.length) {
|
|
102
106
|
const file = files?.[0]?.file;
|
|
103
107
|
void (
|
|
104
108
|
file &&
|
|
@@ -116,7 +120,7 @@ export const AvatarInput = ({
|
|
|
116
120
|
} else {
|
|
117
121
|
setBase64(fileUrl?.(defaultValue ?? "") ?? defaultValue ?? "");
|
|
118
122
|
}
|
|
119
|
-
}, [files,
|
|
123
|
+
}, [files, defaultValue]);
|
|
120
124
|
|
|
121
125
|
useEffect(() => {
|
|
122
126
|
!value &&
|
|
@@ -126,7 +130,7 @@ export const AvatarInput = ({
|
|
|
126
130
|
}, [value, defaultValue]);
|
|
127
131
|
|
|
128
132
|
return (
|
|
129
|
-
<div className="flex flex-nowrap items-end overflow-hidden">
|
|
133
|
+
<div className="flex flex-nowrap items-end overflow-hidden p-px">
|
|
130
134
|
<div
|
|
131
135
|
className={classNames(
|
|
132
136
|
"inline-block leading-none relative outline overflow-hidden",
|
|
@@ -153,11 +157,7 @@ export const AvatarInput = ({
|
|
|
153
157
|
/>
|
|
154
158
|
</div>
|
|
155
159
|
</div>
|
|
156
|
-
<HiddenInput
|
|
157
|
-
hiddenValue={list?.[0]?.path}
|
|
158
|
-
defaultValue={defaultValue}
|
|
159
|
-
{...rest}
|
|
160
|
-
/>
|
|
160
|
+
<HiddenInput value={files?.[0]?.path} {...rest} />
|
|
161
161
|
{files.map((file, idx) => (
|
|
162
162
|
<div key={idx} className="px-2 py-1 flex-1 overflow-hidden">
|
|
163
163
|
<div className="flex flex-nowrap gap-1 items-center">
|
|
@@ -168,7 +168,7 @@ export const AvatarInput = ({
|
|
|
168
168
|
)}
|
|
169
169
|
{file.progress && (
|
|
170
170
|
<Icon
|
|
171
|
-
icon=
|
|
171
|
+
icon="icon-[mdi--stop]"
|
|
172
172
|
bg="danger"
|
|
173
173
|
color="white"
|
|
174
174
|
size="sm"
|
|
@@ -179,7 +179,7 @@ export const AvatarInput = ({
|
|
|
179
179
|
)}
|
|
180
180
|
{!file.progress && (
|
|
181
181
|
<Icon
|
|
182
|
-
icon=
|
|
182
|
+
icon="icon-[mdi--trash-can-outline]"
|
|
183
183
|
color="danger"
|
|
184
184
|
size="sm"
|
|
185
185
|
className="flex-content"
|
package/src/input/Checkbox.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { Icon } from "@react-fabric/core";
|
|
25
25
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
26
26
|
import classNames from "classnames";
|
|
27
27
|
import {
|
|
@@ -111,10 +111,13 @@ export const Checkbox = ({
|
|
|
111
111
|
const deferred = useDeferredValue(!!checked);
|
|
112
112
|
|
|
113
113
|
const iconOn = useMemo(
|
|
114
|
-
() => iconChecked ?? icon ??
|
|
114
|
+
() => iconChecked ?? icon ?? "icon-[mdi--checkbox-marked]",
|
|
115
115
|
[icon, iconChecked],
|
|
116
116
|
);
|
|
117
|
-
const iconOff = useMemo(
|
|
117
|
+
const iconOff = useMemo(
|
|
118
|
+
() => icon ?? "icon-[mdi--checkbox-blank-outline]",
|
|
119
|
+
[icon],
|
|
120
|
+
);
|
|
118
121
|
|
|
119
122
|
useEffect(() => {
|
|
120
123
|
setActualValue(deferred);
|
package/src/input/ColorInput.tsx
CHANGED
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
useFloating,
|
|
34
34
|
useInteractions,
|
|
35
35
|
} from "@floating-ui/react";
|
|
36
|
-
import {
|
|
36
|
+
import { Icon } from "@react-fabric/core";
|
|
37
37
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
38
38
|
import {
|
|
39
39
|
startTransition,
|
|
@@ -168,11 +168,7 @@ export const ColorInput = ({
|
|
|
168
168
|
}}
|
|
169
169
|
>
|
|
170
170
|
{!actualValue && (
|
|
171
|
-
<Icon
|
|
172
|
-
size="md"
|
|
173
|
-
className="text-muted"
|
|
174
|
-
icon={CoreIcons.colorSwatch}
|
|
175
|
-
/>
|
|
171
|
+
<Icon size="md" className="text-muted" icon="icon-[mdi--palette]" />
|
|
176
172
|
)}
|
|
177
173
|
</div>
|
|
178
174
|
</button>
|
|
@@ -203,7 +199,7 @@ export const ColorInput = ({
|
|
|
203
199
|
{!disabled && showPicker && (
|
|
204
200
|
<Icon
|
|
205
201
|
className="flex-content p-1"
|
|
206
|
-
icon=
|
|
202
|
+
icon="icon-[mdi--eyedropper]"
|
|
207
203
|
onClick={() =>
|
|
208
204
|
(window as AnyObject).EyeDropper &&
|
|
209
205
|
new (window as AnyObject).EyeDropper()
|
package/src/input/File.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { Icon } from "@react-fabric/core";
|
|
25
25
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
26
26
|
import {
|
|
27
27
|
FileUtil,
|
|
@@ -181,7 +181,7 @@ export const FileInput = ({
|
|
|
181
181
|
</span>
|
|
182
182
|
<Icon
|
|
183
183
|
className="cursor-pointer opacity-30 hover:opacity-80"
|
|
184
|
-
icon=
|
|
184
|
+
icon="icon-[mdi--close]"
|
|
185
185
|
onClick={() => {
|
|
186
186
|
removeFile(idx);
|
|
187
187
|
}}
|
package/src/input/Hidden.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { Fragment
|
|
24
|
+
import { Fragment } from "react";
|
|
25
25
|
import { ErrorIcon } from "../internal/ErrorIcon";
|
|
26
26
|
|
|
27
27
|
interface Props {
|
|
@@ -30,17 +30,9 @@ interface Props {
|
|
|
30
30
|
*/
|
|
31
31
|
name?: string;
|
|
32
32
|
/**
|
|
33
|
-
* hidden value
|
|
33
|
+
* hidden input value
|
|
34
34
|
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* default avatar image
|
|
38
|
-
*/
|
|
39
|
-
defaultValue?: string;
|
|
40
|
-
/**
|
|
41
|
-
* form onChange handler
|
|
42
|
-
*/
|
|
43
|
-
onChange?: (value: AnyObject) => void;
|
|
35
|
+
value?: AnyObject;
|
|
44
36
|
}
|
|
45
37
|
|
|
46
38
|
/**
|
|
@@ -52,28 +44,18 @@ interface Props {
|
|
|
52
44
|
* @returns {JSX.Element} The rendered hidden input field and error icon.
|
|
53
45
|
*/
|
|
54
46
|
export const HiddenInput = ({
|
|
55
|
-
hiddenValue,
|
|
56
|
-
defaultValue,
|
|
57
|
-
onChange,
|
|
58
47
|
// @ts-expect-error ignore
|
|
59
48
|
// eslint-disable-next-line react/prop-types
|
|
60
49
|
invalid,
|
|
61
50
|
// @ts-expect-error ignore
|
|
62
51
|
// eslint-disable-next-line react/prop-types
|
|
63
52
|
error,
|
|
64
|
-
// @ts-expect-error ignore
|
|
65
|
-
// eslint-disable-next-line react/prop-types
|
|
66
53
|
value = "",
|
|
67
54
|
name,
|
|
68
55
|
}: Props) => {
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
setTimeout(() => {
|
|
71
|
-
onChange?.(hiddenValue ?? defaultValue);
|
|
72
|
-
}, 50);
|
|
73
|
-
}, [hiddenValue, defaultValue]);
|
|
74
56
|
return (
|
|
75
57
|
<Fragment>
|
|
76
|
-
<input type="hidden"
|
|
58
|
+
<input type="hidden" value={value} name={name} />
|
|
77
59
|
<ErrorIcon invalid={invalid} error={error} />
|
|
78
60
|
</Fragment>
|
|
79
61
|
);
|
package/src/input/Password.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { Button,
|
|
24
|
+
import { Button, Tooltip } from "@react-fabric/core";
|
|
25
25
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
26
26
|
import classNames from "classnames";
|
|
27
27
|
import {
|
|
@@ -114,7 +114,9 @@ export const Password = ({
|
|
|
114
114
|
color="warning"
|
|
115
115
|
variant="link"
|
|
116
116
|
aria-label={t(show ? "password.hide" : "password.show")}
|
|
117
|
-
icon={
|
|
117
|
+
icon={
|
|
118
|
+
show ? "icon-[mdi--eye-off-outline]" : "icon-[mdi--eye-outline]"
|
|
119
|
+
}
|
|
118
120
|
onClick={() => setShow(!show)}
|
|
119
121
|
/>
|
|
120
122
|
</Tooltip>
|
package/src/input/Radio.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { Icon } from "@react-fabric/core";
|
|
25
25
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
26
26
|
import classNames from "classnames";
|
|
27
27
|
import { useCallback, useMemo, type ChangeEvent } from "react";
|
|
@@ -93,10 +93,10 @@ export const Radio = ({
|
|
|
93
93
|
...rest
|
|
94
94
|
}: RadioProps) => {
|
|
95
95
|
const iconOn = useMemo(
|
|
96
|
-
() => iconChecked ?? icon ??
|
|
96
|
+
() => iconChecked ?? icon ?? "icon-[mdi--radiobox-marked]",
|
|
97
97
|
[icon, iconChecked],
|
|
98
98
|
);
|
|
99
|
-
const iconOff = useMemo(() => icon ??
|
|
99
|
+
const iconOff = useMemo(() => icon ?? "icon-[mdi--radiobox-blank]", [icon]);
|
|
100
100
|
|
|
101
101
|
const handleChange = useCallback(
|
|
102
102
|
(e?: ChangeEvent<HTMLInputElement>) => {
|
package/src/input/RadioGroup.tsx
CHANGED
|
@@ -68,6 +68,10 @@ export interface RadioGroupProps extends ChildrenProp<typeof Radio>, CssProp {
|
|
|
68
68
|
* vertical orientation
|
|
69
69
|
*/
|
|
70
70
|
vertical?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* value
|
|
73
|
+
*/
|
|
74
|
+
value?: string | number;
|
|
71
75
|
/**
|
|
72
76
|
* change handler
|
|
73
77
|
*/
|
|
@@ -87,6 +91,7 @@ export const RadioGroup = ({
|
|
|
87
91
|
name,
|
|
88
92
|
className,
|
|
89
93
|
optionWidth,
|
|
94
|
+
value,
|
|
90
95
|
onChange,
|
|
91
96
|
...rest
|
|
92
97
|
}: RadioGroupProps) => {
|
|
@@ -96,6 +101,7 @@ export const RadioGroup = ({
|
|
|
96
101
|
{cloneChildren(children, (child: AnyObject) =>
|
|
97
102
|
cloneElement(child, {
|
|
98
103
|
name,
|
|
104
|
+
checked: child.props.value === value,
|
|
99
105
|
onChange,
|
|
100
106
|
width: optionWidth,
|
|
101
107
|
}),
|
package/src/input/Search.tsx
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { Button,
|
|
24
|
+
import { Button, Icon, useDebounce } from "@react-fabric/core";
|
|
25
25
|
import { type RefProp } from "@react-fabric/core/dist/types/types";
|
|
26
26
|
import {
|
|
27
27
|
Fragment,
|
|
@@ -129,7 +129,7 @@ export const Search = ({
|
|
|
129
129
|
actionButton={
|
|
130
130
|
<Fragment>
|
|
131
131
|
{searching && (
|
|
132
|
-
<Icon className="p-2" icon=
|
|
132
|
+
<Icon className="p-2" icon="icon-[svg-spinners--eclipse]" />
|
|
133
133
|
)}
|
|
134
134
|
{!searching && !hideHandle && (
|
|
135
135
|
<Button
|
|
@@ -137,7 +137,7 @@ export const Search = ({
|
|
|
137
137
|
variant="link"
|
|
138
138
|
aria-label="search"
|
|
139
139
|
disabled={!actualValue}
|
|
140
|
-
icon=
|
|
140
|
+
icon="icon-[mdi--magnify]"
|
|
141
141
|
onClick={handleSearch}
|
|
142
142
|
/>
|
|
143
143
|
)}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { Icon, Tooltip } from "@react-fabric/core";
|
|
25
25
|
import { isString } from "@react-fabric/utilities";
|
|
26
26
|
import { useTranslation } from "react-i18next";
|
|
27
27
|
|
|
@@ -53,7 +53,7 @@ export const ErrorIcon = ({ error = "", invalid }: KeyValue) => {
|
|
|
53
53
|
<Icon
|
|
54
54
|
className="flex-content first:ms-2 self-center"
|
|
55
55
|
color="danger"
|
|
56
|
-
icon=
|
|
56
|
+
icon="icon-[mdi--alert-circle-outline]"
|
|
57
57
|
/>
|
|
58
58
|
</Tooltip>
|
|
59
59
|
)
|