@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.
Files changed (91) hide show
  1. package/dist/cjs/builder/FileField.js +10 -7
  2. package/dist/cjs/builder/components/AddSchemaFields.js +2 -1
  3. package/dist/cjs/builder/components/SchemaArrayForm.js +4 -4
  4. package/dist/cjs/builder/components/SchemaField.js +4 -4
  5. package/dist/cjs/form/Form.js +44 -22
  6. package/dist/cjs/hooks/useFileUploader.js +40 -28
  7. package/dist/cjs/hooks/useFormBuilder.js +10 -3
  8. package/dist/cjs/i18n/index.js +4 -4
  9. package/dist/cjs/input/ArrayInput.js +3 -3
  10. package/dist/cjs/input/AvatarInput.js +17 -12
  11. package/dist/cjs/input/Checkbox.js +2 -2
  12. package/dist/cjs/input/ColorInput.js +2 -2
  13. package/dist/cjs/input/File.js +1 -1
  14. package/dist/cjs/input/Hidden.js +1 -10
  15. package/dist/cjs/input/Password.js +1 -1
  16. package/dist/cjs/input/Radio.js +2 -2
  17. package/dist/cjs/input/RadioGroup.js +3 -1
  18. package/dist/cjs/input/Search.js +2 -3
  19. package/dist/cjs/internal/ErrorIcon.js +1 -1
  20. package/dist/cjs/internal/InputWrapper.js +3 -3
  21. package/dist/cjs/select/AutoComplete.js +1 -2
  22. package/dist/cjs/select/DualList.js +5 -5
  23. package/dist/cjs/select/List.js +8 -24
  24. package/dist/cjs/select/Select.js +9 -28
  25. package/dist/esm/builder/FileField.js +11 -8
  26. package/dist/esm/builder/components/AddSchemaFields.js +2 -1
  27. package/dist/esm/builder/components/SchemaArrayForm.js +5 -5
  28. package/dist/esm/builder/components/SchemaField.js +5 -5
  29. package/dist/esm/form/Form.js +44 -22
  30. package/dist/esm/hooks/useFileUploader.js +41 -29
  31. package/dist/esm/hooks/useFormBuilder.js +10 -3
  32. package/dist/esm/i18n/index.js +2 -2
  33. package/dist/esm/input/ArrayInput.js +4 -4
  34. package/dist/esm/input/AvatarInput.js +18 -13
  35. package/dist/esm/input/Checkbox.js +3 -3
  36. package/dist/esm/input/ColorInput.js +3 -3
  37. package/dist/esm/input/File.js +2 -2
  38. package/dist/esm/input/Hidden.js +2 -11
  39. package/dist/esm/input/Password.js +2 -2
  40. package/dist/esm/input/Radio.js +3 -3
  41. package/dist/esm/input/RadioGroup.js +3 -1
  42. package/dist/esm/input/Search.js +3 -4
  43. package/dist/esm/internal/ErrorIcon.js +2 -2
  44. package/dist/esm/internal/InputWrapper.js +4 -4
  45. package/dist/esm/select/AutoComplete.js +2 -3
  46. package/dist/esm/select/DualList.js +6 -6
  47. package/dist/esm/select/List.js +8 -24
  48. package/dist/esm/select/Select.js +10 -29
  49. package/dist/types/builder/FileField.d.ts +2 -1
  50. package/dist/types/form/Form.d.ts +11 -10
  51. package/dist/types/hooks/useFileUploader.d.ts +4 -2
  52. package/dist/types/hooks/useFormBuilder.d.ts +6 -0
  53. package/dist/types/input/AvatarInput.d.ts +2 -2
  54. package/dist/types/input/Hidden.d.ts +3 -11
  55. package/dist/types/input/RadioGroup.d.ts +5 -1
  56. package/dist/types/select/DualList.d.ts +5 -6
  57. package/dist/types/select/Options.d.ts +1 -1
  58. package/dist/types/types/index.d.ts +7 -8
  59. package/package.json +5 -5
  60. package/src/builder/FileField.tsx +8 -12
  61. package/src/builder/components/AddSchemaFields.tsx +2 -1
  62. package/src/builder/components/SchemaArrayForm.tsx +5 -11
  63. package/src/builder/components/SchemaField.tsx +4 -5
  64. package/src/form/Form.tsx +30 -24
  65. package/src/hooks/useFileUploader.ts +41 -29
  66. package/src/hooks/useFormBuilder.tsx +12 -4
  67. package/src/i18n/index.ts +2 -2
  68. package/src/input/ArrayInput.tsx +4 -10
  69. package/src/input/AvatarInput.tsx +16 -16
  70. package/src/input/Checkbox.tsx +6 -3
  71. package/src/input/ColorInput.tsx +3 -7
  72. package/src/input/File.tsx +2 -2
  73. package/src/input/Hidden.tsx +4 -22
  74. package/src/input/Password.tsx +4 -2
  75. package/src/input/Radio.tsx +3 -3
  76. package/src/input/RadioGroup.tsx +6 -0
  77. package/src/input/Search.tsx +3 -3
  78. package/src/internal/ErrorIcon.tsx +2 -2
  79. package/src/internal/InputWrapper.tsx +8 -4
  80. package/src/select/AutoComplete.tsx +2 -3
  81. package/src/select/DualList.tsx +15 -12
  82. package/src/select/List.tsx +3 -3
  83. package/src/select/Options.tsx +1 -1
  84. package/src/select/Select.tsx +7 -8
  85. package/src/types/index.ts +8 -7
  86. /package/dist/cjs/i18n/{ar.json.js → ar/form.json.js} +0 -0
  87. /package/dist/cjs/i18n/{en.json.js → en/form.json.js} +0 -0
  88. /package/dist/esm/i18n/{ar.json.js → ar/form.json.js} +0 -0
  89. /package/dist/esm/i18n/{en.json.js → en/form.json.js} +0 -0
  90. /package/src/i18n/{ar.json → ar/form.json} +0 -0
  91. /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, type yup } from "@react-fabric/utilities";
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 data schema
65
+ * react-hook-form resolver for validation
66
+ * @see {@link https://react-hook-form.com/ts#Resolver}
67
67
  */
68
- schema?: yup.ObjectSchema<K>;
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
- * schema={yup.object().shape({
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
- schema,
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: schema && (yupResolver(schema) as AnyObject),
129
- defaultValues: defaultValues as DefaultValues<K>,
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: AnyObject = {}) => {
143
- form.reset(reset);
144
- form.clearErrors();
145
- ref.current
146
- ?.querySelector<HTMLElement>("[auto-focus], input, textarea")
147
- ?.focus();
148
- },
149
- [defaultValues],
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
- multiple = true,
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 = yup.object(
139
- Object.fromEntries(
140
- filteredSchema.map((field) => [field.id, makeYupField(field)]),
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
@@ -22,7 +22,7 @@
22
22
  */
23
23
 
24
24
  import { addTranslationBundle } from "@react-fabric/core";
25
- import ar from "./ar.json";
26
- import en from "./en.json";
25
+ import ar from "./ar/form.json";
26
+ import en from "./en/form.json";
27
27
 
28
28
  addTranslationBundle("form", { en, ar });
@@ -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={CoreIcons.dragHandle}
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={CoreIcons.insert}
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={CoreIcons.remove}
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, CoreIcons, Icon, ProgressBar } from "@react-fabric/core";
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, list, upload, remove } = useFileUploader(
94
+ const { files, upload, remove } = useFileUploader(
94
95
  async (data, config) => await uploadHandler?.(data, config),
95
- value,
96
- false,
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 (list?.length) {
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, list, defaultValue]);
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={CoreIcons.stop}
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={CoreIcons.trash}
182
+ icon="icon-[mdi--trash-can-outline]"
183
183
  color="danger"
184
184
  size="sm"
185
185
  className="flex-content"
@@ -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 { CoreIcons, Icon } from "@react-fabric/core";
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 ?? CoreIcons.checkboxOn,
114
+ () => iconChecked ?? icon ?? "icon-[mdi--checkbox-marked]",
115
115
  [icon, iconChecked],
116
116
  );
117
- const iconOff = useMemo(() => icon ?? CoreIcons.checkboxOff, [icon]);
117
+ const iconOff = useMemo(
118
+ () => icon ?? "icon-[mdi--checkbox-blank-outline]",
119
+ [icon],
120
+ );
118
121
 
119
122
  useEffect(() => {
120
123
  setActualValue(deferred);
@@ -33,7 +33,7 @@ import {
33
33
  useFloating,
34
34
  useInteractions,
35
35
  } from "@floating-ui/react";
36
- import { CoreIcons, Icon } from "@react-fabric/core";
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={CoreIcons.colorPicker}
202
+ icon="icon-[mdi--eyedropper]"
207
203
  onClick={() =>
208
204
  (window as AnyObject).EyeDropper &&
209
205
  new (window as AnyObject).EyeDropper()
@@ -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 { CoreIcons, Icon } from "@react-fabric/core";
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={CoreIcons.close}
184
+ icon="icon-[mdi--close]"
185
185
  onClick={() => {
186
186
  removeFile(idx);
187
187
  }}
@@ -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, useEffect } from "react";
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 will fire change for form update
33
+ * hidden input value
34
34
  */
35
- hiddenValue?: AnyObject;
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" onChange={onChange} value={value} name={name} />
58
+ <input type="hidden" value={value} name={name} />
77
59
  <ErrorIcon invalid={invalid} error={error} />
78
60
  </Fragment>
79
61
  );
@@ -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, CoreIcons, Tooltip } from "@react-fabric/core";
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={show ? CoreIcons.eyeOff : CoreIcons.eye}
117
+ icon={
118
+ show ? "icon-[mdi--eye-off-outline]" : "icon-[mdi--eye-outline]"
119
+ }
118
120
  onClick={() => setShow(!show)}
119
121
  />
120
122
  </Tooltip>
@@ -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 { CoreIcons, Icon } from "@react-fabric/core";
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 ?? CoreIcons.radioOn,
96
+ () => iconChecked ?? icon ?? "icon-[mdi--radiobox-marked]",
97
97
  [icon, iconChecked],
98
98
  );
99
- const iconOff = useMemo(() => icon ?? CoreIcons.radioOff, [icon]);
99
+ const iconOff = useMemo(() => icon ?? "icon-[mdi--radiobox-blank]", [icon]);
100
100
 
101
101
  const handleChange = useCallback(
102
102
  (e?: ChangeEvent<HTMLInputElement>) => {
@@ -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
  }),
@@ -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, CoreIcons, Icon, useDebounce } from "@react-fabric/core";
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={CoreIcons.spinner} animate="spin" />
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={CoreIcons.search}
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 { CoreIcons, Icon, Tooltip } from "@react-fabric/core";
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={CoreIcons.alert}
56
+ icon="icon-[mdi--alert-circle-outline]"
57
57
  />
58
58
  </Tooltip>
59
59
  )