@react-fabric/form 1.0.0-beta.56 → 1.0.0-beta.58

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 (52) hide show
  1. package/css/_field.css +2 -1
  2. package/dist/cjs/form/Form.js +24 -0
  3. package/dist/cjs/index.js +1 -0
  4. package/dist/cjs/input/ArrayInput.js +34 -13
  5. package/dist/cjs/input/AvatarInput.js +17 -10
  6. package/dist/cjs/input/ColorInput.js +1 -0
  7. package/dist/cjs/input/Hidden.js +4 -3
  8. package/dist/cjs/input/Slider.js +2 -2
  9. package/dist/cjs/input/Textarea.js +1 -1
  10. package/dist/cjs/select/DualList.js +16 -8
  11. package/dist/cjs/select/List.js +5 -2
  12. package/dist/cjs/select/Options.js +49 -42
  13. package/dist/cjs/select/Select.js +4 -2
  14. package/dist/cjs/select/useSelect.js +14 -7
  15. package/dist/esm/form/Form.js +26 -3
  16. package/dist/esm/index.js +1 -1
  17. package/dist/esm/input/ArrayInput.js +35 -14
  18. package/dist/esm/input/AvatarInput.js +17 -10
  19. package/dist/esm/input/ColorInput.js +1 -0
  20. package/dist/esm/input/Hidden.js +4 -3
  21. package/dist/esm/input/Slider.js +2 -2
  22. package/dist/esm/input/Textarea.js +1 -1
  23. package/dist/esm/select/DualList.js +16 -8
  24. package/dist/esm/select/List.js +5 -2
  25. package/dist/esm/select/Options.js +49 -42
  26. package/dist/esm/select/Select.js +4 -2
  27. package/dist/esm/select/useSelect.js +14 -7
  28. package/dist/types/form/Form.d.ts +11 -0
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/input/ArrayInput.d.ts +5 -8
  31. package/dist/types/input/AvatarInput.d.ts +6 -1
  32. package/dist/types/input/Hidden.d.ts +5 -1
  33. package/dist/types/select/List.d.ts +1 -1
  34. package/dist/types/select/Options.d.ts +2 -1
  35. package/dist/types/select/Select.d.ts +1 -1
  36. package/dist/types/select/useSelect.d.ts +4 -1
  37. package/dist/types/types/index.d.ts +4 -0
  38. package/package.json +20 -21
  39. package/src/form/Form.tsx +34 -2
  40. package/src/index.ts +1 -1
  41. package/src/input/ArrayInput.tsx +55 -21
  42. package/src/input/AvatarInput.tsx +32 -5
  43. package/src/input/ColorInput.tsx +1 -0
  44. package/src/input/Hidden.tsx +9 -5
  45. package/src/input/Slider.tsx +4 -4
  46. package/src/input/Textarea.tsx +1 -1
  47. package/src/select/DualList.tsx +4 -8
  48. package/src/select/List.tsx +3 -0
  49. package/src/select/Options.tsx +47 -43
  50. package/src/select/Select.tsx +2 -0
  51. package/src/select/useSelect.tsx +15 -6
  52. package/src/types/index.ts +4 -0
@@ -65,4 +65,15 @@ export interface FormProps<K extends KeyValue = KeyValue> {
65
65
  * @see {@link https://github.com/jquense/yup} for more details on the Yup validation schema.
66
66
  */
67
67
  export declare const Form: <K extends KeyValue>({ formRef, schema, children, defaultValues, onSubmit, onChange, ...rest }: PropsWithChildren<FormProps<K>>) => import("react/jsx-runtime").JSX.Element;
68
+ export declare const useForm: <K extends KeyValue = KeyValue>() => {
69
+ values: import("react-hook-form").DeepPartialSkipArrayKey<K> & K;
70
+ formState: FormState<K>;
71
+ getValues: import("react-hook-form").UseFormGetValues<K>;
72
+ setValue: import("react-hook-form").UseFormSetValue<K>;
73
+ watch: import("react-hook-form").UseFormWatch<K>;
74
+ reset: import("react-hook-form").UseFormReset<K>;
75
+ resetField: import("react-hook-form").UseFormResetField<K>;
76
+ setError: import("react-hook-form").UseFormSetError<K>;
77
+ setFocus: import("react-hook-form").UseFormSetFocus<K>;
78
+ };
68
79
  export {};
@@ -1,6 +1,6 @@
1
1
  import "./i18n";
2
2
  export { Controller } from "./form/Controller";
3
- export { Form, type FormRef } from "./form/Form";
3
+ export { Form, useForm, type FormRef } from "./form/Form";
4
4
  export { SchemaEditor } from "./builder/SchemaEditor";
5
5
  export { useFileUploader } from "./hooks/useFileUploader";
6
6
  export { useFormBuilder } from "./hooks/useFormBuilder";
@@ -47,16 +47,13 @@ export interface ArrayInputProps<T extends AnyObject = string> {
47
47
  children: React.ReactNode | ((props: {
48
48
  index: number;
49
49
  name: string;
50
+ item: T;
50
51
  }) => ReactNode);
51
52
  /**
52
53
  * add item button label
53
54
  */
54
55
  addLabel?: string;
55
56
  buttonPosition?: "top" | "bottom" | "both";
56
- /**
57
- * fixed length list
58
- */
59
- fixedList?: boolean;
60
57
  arrayRef?: Ref<{
61
58
  addItem: (item: T) => void;
62
59
  removeItem: (idx: number) => void;
@@ -64,7 +61,7 @@ export interface ArrayInputProps<T extends AnyObject = string> {
64
61
  /**
65
62
  * add new item
66
63
  */
67
- onAdd?: () => AnyObject;
64
+ onAdd?: () => T;
68
65
  /**
69
66
  * on item remove
70
67
  */
@@ -76,11 +73,11 @@ export interface ArrayInputProps<T extends AnyObject = string> {
76
73
  /**
77
74
  * can remove item
78
75
  */
79
- canRemove?: (props: {
76
+ canRemove?: false | "newonly" | ((props: {
80
77
  item: T;
81
78
  index: number;
82
79
  lastItem: boolean;
83
- }) => boolean;
80
+ }) => boolean);
84
81
  /**
85
82
  * field width
86
83
  */
@@ -133,4 +130,4 @@ export interface ArrayInputProps<T extends AnyObject = string> {
133
130
  * @see {@link https://react-hook-form.com/api/usefieldarray} for more details on `useFieldArray`.
134
131
  * @see {@link https://react-dnd.github.io/react-dnd/about} for more details on DnD context and sorting.
135
132
  */
136
- export declare const ArrayInput: <T extends AnyObject = string>({ name, children, addLabel, fixedList, focusName, buttonPosition, onAdd, onRemove, onBeforeRemove, canRemove, arrayRef, enableSorting, disabled, readOnly, minItems, maxItems, ...rest }: ArrayInputProps<T>) => import("react/jsx-runtime").JSX.Element;
133
+ export declare const ArrayInput: <T extends AnyObject = string>({ name, children, addLabel, focusName, buttonPosition, onAdd, onRemove, onBeforeRemove, canRemove, arrayRef, enableSorting, disabled, readOnly, minItems, maxItems, ...rest }: ArrayInputProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { type RefProp } from "@react-fabric/core/dist/types/types";
2
2
  import { type UploadHandler } from "../hooks/useFileUploader";
3
+ import { AvatarProps } from "@react-fabric/core/dist/types/components/avatar/Avatar";
3
4
  export interface Props extends RefProp {
4
5
  /**
5
6
  * field name
@@ -17,6 +18,10 @@ export interface Props extends RefProp {
17
18
  * avatar name
18
19
  */
19
20
  avatarName?: string;
21
+ rounded?: boolean;
22
+ variant?: AvatarProps["variant"];
23
+ fallbackIcon?: AvatarProps["fallbackIcon"];
24
+ avatarClassName?: AvatarProps["className"];
20
25
  size?: string | number;
21
26
  /**
22
27
  * upload handler to store file in temp storage
@@ -43,4 +48,4 @@ export interface Props extends RefProp {
43
48
  * @param {Props} props - The properties for the AvatarInput component.
44
49
  * @returns {JSX.Element} - The rendered AvatarInput component.
45
50
  */
46
- export declare const AvatarInput: ({ size, avatarName, value, defaultValue, fileUrl, uploadHandler, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
51
+ export declare const AvatarInput: ({ size, avatarName, avatarClassName, value, rounded, defaultValue, fallbackIcon, variant, fileUrl, uploadHandler, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
@@ -7,6 +7,10 @@ interface Props {
7
7
  * hidden value will fire change for form update
8
8
  */
9
9
  hiddenValue?: AnyObject;
10
+ /**
11
+ * default avatar image
12
+ */
13
+ defaultValue?: string;
10
14
  /**
11
15
  * form onChange handler
12
16
  */
@@ -20,5 +24,5 @@ interface Props {
20
24
  * @param {Object} props - Component properties.
21
25
  * @returns {JSX.Element} The rendered hidden input field and error icon.
22
26
  */
23
- export declare const HiddenInput: ({ hiddenValue, onChange, invalid, error, value, name, }: Props) => import("react/jsx-runtime").JSX.Element;
27
+ export declare const HiddenInput: ({ hiddenValue, defaultValue, onChange, invalid, error, value, name, }: Props) => import("react/jsx-runtime").JSX.Element;
24
28
  export {};
@@ -7,6 +7,6 @@ import { type SelectProps } from "../types";
7
7
  * @param {SelectProps<T>} props - The properties for the List component.
8
8
  * @returns {JSX.Element} The rendered List component.
9
9
  */
10
- export declare const List: <T extends AnyObject = string>({ ref, name, value, readOnly, disabled, required, placeholder, autoFocus, options, height, groupProperty, labelProperty, valueProperty, sortProperty, multiple, allowCreate, searchable, createOption, matcher, renderer, onQuery, onChange, onSelect, onEnterPressed, emptyDisplay, invalid, error, allowClear, decorateStart, decorateEnd, "data-inner": isInner, "data-hide-selected": hideSelected, ...rest }: Omit<SelectProps<T>, "defaultOpen" | "hideHandle"> & {
10
+ export declare const List: <T extends AnyObject = string>({ ref, name, value, readOnly, disabled, required, placeholder, autoFocus, options, height, groupProperty, labelProperty, valueProperty, infoProperty, sortProperty, multiple, allowCreate, searchable, createOption, matcher, renderer, onQuery, onChange, onSelect, onEnterPressed, emptyDisplay, invalid, error, allowClear, decorateStart, decorateEnd, "data-inner": isInner, "data-hide-selected": hideSelected, ...rest }: Omit<SelectProps<T>, "defaultOpen" | "hideHandle"> & {
11
11
  height?: string | number;
12
12
  }) => import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,7 @@
1
1
  import { type ReactElement, type ReactNode } from "react";
2
- export declare const Options: ({ ref, style, items, active, className, itemRef, empty, valueProperty, labelProperty, itemProps, children, ...rest }: {
2
+ export declare const Options: ({ ref, style, items, active, className, itemRef, empty, info, valueProperty, labelProperty, itemProps, children, ...rest }: {
3
3
  ref: AnyObject;
4
+ info?: AnyObject;
4
5
  itemRef: AnyObject;
5
6
  style?: AnyObject;
6
7
  items: AnyObject[];
@@ -7,4 +7,4 @@ import { type SelectProps } from "../types";
7
7
  * @param {SelectProps<T>} props - The properties for the Select component.
8
8
  * @returns {JSX.Element} The rendered Select component.
9
9
  */
10
- export declare const Select: <T extends AnyObject = string>({ ref, name, value, invalid, readOnly, disabled, required, placeholder, autoFocus, error, options, defaultOpen, hideHandle, groupProperty, labelProperty, valueProperty, sortProperty, multiple, searchable, allowCreate, emptyDisplay, createOption, matcher, renderer, onQuery, onChange, onSelect, onEnterPressed, ...rest }: SelectProps<T>) => import("react/jsx-runtime").JSX.Element;
10
+ export declare const Select: <T extends AnyObject = string>({ ref, name, value, invalid, readOnly, disabled, required, placeholder, autoFocus, error, options, defaultOpen, hideHandle, groupProperty, labelProperty, valueProperty, sortProperty, infoProperty, multiple, searchable, allowCreate, emptyDisplay, createOption, matcher, renderer, onQuery, onChange, onSelect, onEnterPressed, ...rest }: SelectProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -4,15 +4,17 @@ interface State {
4
4
  open: boolean;
5
5
  loading: boolean;
6
6
  activeIndex: number | null;
7
+ activeItem: AnyObject;
7
8
  selectedIndex: number | null;
8
9
  value: AnyObject;
9
10
  query?: string;
10
11
  items: AnyObject[];
11
12
  }
12
- export declare const useSelect: ({ options, value, defaultOpen, autoComplete, multiple, allowCreate, groupProperty, valueProperty, labelProperty, sortProperty, createOption, matcher, onQuery, onChange, onSelect, }: {
13
+ export declare const useSelect: ({ options, value, autoComplete, alwaysOpen, defaultOpen, multiple, allowCreate, groupProperty, valueProperty, labelProperty, sortProperty, createOption, matcher, onQuery, onChange, onSelect, }: {
13
14
  value?: AnyObject;
14
15
  options?: AnyObject[];
15
16
  multiple?: boolean;
17
+ alwaysOpen?: boolean;
16
18
  defaultOpen?: boolean;
17
19
  allowCreate?: boolean;
18
20
  groupProperty?: AnyObject;
@@ -29,6 +31,7 @@ export declare const useSelect: ({ options, value, defaultOpen, autoComplete, mu
29
31
  state: State | {
30
32
  value: any;
31
33
  activeIndex: null;
34
+ activeItem: null;
32
35
  selectedIndex: any;
33
36
  multiple: boolean;
34
37
  emptyValue: AnyObject;
@@ -122,6 +122,10 @@ export interface BaseSelectProps<T extends AnyObject = string> {
122
122
  * value property name
123
123
  */
124
124
  valueProperty?: keyof T;
125
+ /**
126
+ * value property name
127
+ */
128
+ infoProperty?: keyof T;
125
129
  /**
126
130
  * value property name
127
131
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-fabric/form",
3
- "version": "1.0.0-beta.56",
3
+ "version": "1.0.0-beta.58",
4
4
  "description": "RUF: Form package",
5
5
  "author": "Adarsh Pastakia <adarshpastakia@outlook.com>",
6
6
  "license": "MIT",
@@ -35,33 +35,32 @@
35
35
  "watch": "npm-run-all -p watch:rollup watch:dts"
36
36
  },
37
37
  "dependencies": {
38
- "@dnd-kit/core": "^6.3.1",
39
- "@dnd-kit/modifiers": "^9.0.0",
40
- "@dnd-kit/sortable": "^10.0.0",
41
- "@dnd-kit/utilities": "^3.2.2",
42
- "@floating-ui/react": "^0.27.9",
43
- "@hookform/resolvers": "^3.9.0",
44
- "@react-fabric/core": "^1.0.0-beta.55",
45
- "@react-fabric/date": "^1.0.0-beta.55",
46
- "@react-fabric/utilities": "^1.0.0-beta.52",
47
- "classnames": "^2.5.1",
48
- "color": "^4.2.3",
49
- "react-color": "^2.19.3",
50
- "react-hook-form": "^7.52.1"
38
+ "@dnd-kit/core": "~6.3.1",
39
+ "@dnd-kit/modifiers": "~9.0.0",
40
+ "@dnd-kit/sortable": "~10.0.0",
41
+ "@dnd-kit/utilities": "~3.2.2",
42
+ "@floating-ui/react": "~0.27.16",
43
+ "@hookform/resolvers": "~5.2.2",
44
+ "@react-fabric/core": "^1.0.0-beta.58",
45
+ "@react-fabric/date": "^1.0.0-beta.58",
46
+ "@react-fabric/utilities": "^1.0.0-beta.58",
47
+ "classnames": "~2.5.1",
48
+ "color": "~5.0.2",
49
+ "react-color": "~2.19.3",
50
+ "react-hook-form": "~7.65.0"
51
51
  },
52
52
  "peerDependencies": {
53
- "i18next": "^25.2.1",
54
- "react": "^19.0.0",
55
- "react-dom": "^19.0.0",
56
- "react-i18next": "^15.5.2"
53
+ "i18next": "~25.6.0",
54
+ "react": "~19.2.0",
55
+ "react-dom": "~19.2.0",
56
+ "react-i18next": "~16.2.1"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/axios": "^0.14.0",
60
- "@types/react-color": "^3.0.12"
59
+ "@types/react-color": "~3.0.13"
61
60
  },
62
61
  "engines": {
63
62
  "node": ">=18.12.0",
64
63
  "npm": ">=8.19.0"
65
64
  },
66
- "gitHead": "fd9dd6cfd1a58efb5c4bfb6446928a78cb4f4266"
65
+ "gitHead": "7e66f8c498e37a40e410ecafff2ea6b31505dc1a"
67
66
  }
package/src/form/Form.tsx CHANGED
@@ -29,13 +29,16 @@ import {
29
29
  useEffect,
30
30
  useImperativeHandle,
31
31
  useRef,
32
+ useState,
32
33
  useTransition,
33
34
  type PropsWithChildren,
34
35
  type Ref,
35
36
  } from "react";
36
37
  import {
37
38
  FormProvider,
38
- useForm,
39
+ useFormContext,
40
+ useForm as useFormHook,
41
+ useWatch,
39
42
  type DefaultValues,
40
43
  type FormState,
41
44
  } from "react-hook-form";
@@ -120,7 +123,7 @@ export const Form = <K extends KeyValue>({
120
123
  ...rest
121
124
  }: PropsWithChildren<FormProps<K>>) => {
122
125
  const ref = useRef<HTMLFormElement>(null);
123
- const form = useForm<K>({
126
+ const form = useFormHook<K>({
124
127
  shouldFocusError: true,
125
128
  resolver: schema && (yupResolver(schema) as AnyObject),
126
129
  defaultValues: defaultValues as DefaultValues<K>,
@@ -202,3 +205,32 @@ export const Form = <K extends KeyValue>({
202
205
  </FormProvider>
203
206
  );
204
207
  };
208
+
209
+ export const useForm = <K extends KeyValue = KeyValue>() => {
210
+ const {
211
+ formState,
212
+ getValues,
213
+ setValue,
214
+ watch,
215
+ reset,
216
+ resetField,
217
+ setError,
218
+ setFocus,
219
+ } = useFormContext<K>();
220
+ const values = useWatch<K>();
221
+
222
+ return {
223
+ values: {
224
+ ...values,
225
+ ...getValues(),
226
+ },
227
+ formState,
228
+ getValues,
229
+ setValue,
230
+ watch,
231
+ reset,
232
+ resetField,
233
+ setError,
234
+ setFocus,
235
+ };
236
+ };
package/src/index.ts CHANGED
@@ -24,7 +24,7 @@
24
24
  import "./i18n";
25
25
 
26
26
  export { Controller } from "./form/Controller";
27
- export { Form, type FormRef } from "./form/Form";
27
+ export { Form, useForm, type FormRef } from "./form/Form";
28
28
 
29
29
  export { SchemaEditor } from "./builder/SchemaEditor";
30
30
 
@@ -34,9 +34,12 @@ import { isFalse, isString } from "@react-fabric/utilities";
34
34
  import classNames from "classnames";
35
35
  import {
36
36
  cloneElement,
37
+ use,
37
38
  useCallback,
39
+ useEffect,
38
40
  useImperativeHandle,
39
41
  useMemo,
42
+ useState,
40
43
  type PropsWithChildren,
41
44
  type ReactNode,
42
45
  type Ref,
@@ -96,16 +99,12 @@ export interface ArrayInputProps<T extends AnyObject = string> {
96
99
  enableSorting?: boolean;
97
100
  children:
98
101
  | React.ReactNode
99
- | ((props: { index: number; name: string }) => ReactNode);
102
+ | ((props: { index: number; name: string; item: T }) => ReactNode);
100
103
  /**
101
104
  * add item button label
102
105
  */
103
106
  addLabel?: string;
104
107
  buttonPosition?: "top" | "bottom" | "both";
105
- /**
106
- * fixed length list
107
- */
108
- fixedList?: boolean;
109
108
  arrayRef?: Ref<{
110
109
  addItem: (item: T) => void;
111
110
  removeItem: (idx: number) => void;
@@ -113,7 +112,7 @@ export interface ArrayInputProps<T extends AnyObject = string> {
113
112
  /**
114
113
  * add new item
115
114
  */
116
- onAdd?: () => AnyObject;
115
+ onAdd?: () => T;
117
116
  /**
118
117
  * on item remove
119
118
  */
@@ -125,7 +124,10 @@ export interface ArrayInputProps<T extends AnyObject = string> {
125
124
  /**
126
125
  * can remove item
127
126
  */
128
- canRemove?: (props: { item: T; index: number; lastItem: boolean }) => boolean;
127
+ canRemove?:
128
+ | false
129
+ | "newonly"
130
+ | ((props: { item: T; index: number; lastItem: boolean }) => boolean);
129
131
 
130
132
  /**
131
133
  * field width
@@ -184,7 +186,6 @@ export const ArrayInput = <T extends AnyObject = string>({
184
186
  name,
185
187
  children,
186
188
  addLabel,
187
- fixedList,
188
189
  focusName = "",
189
190
  buttonPosition = "bottom",
190
191
  onAdd,
@@ -211,6 +212,11 @@ export const ArrayInput = <T extends AnyObject = string>({
211
212
  control: form.control,
212
213
  });
213
214
 
215
+ const [initialList, setInitialList] = useState<string[]>([]);
216
+ useEffect(() => {
217
+ setInitialList(fields.map((f) => f.__ID__));
218
+ }, []);
219
+
214
220
  const error = useMemo<AnyObject>(
215
221
  () =>
216
222
  form.formState.errors[name]?.message ??
@@ -218,8 +224,27 @@ export const ArrayInput = <T extends AnyObject = string>({
218
224
  [form.formState.errors],
219
225
  );
220
226
 
227
+ const removeCheck = useCallback(
228
+ (item: T, index: number) => {
229
+ if (canRemove === false) return false;
230
+ if (canRemove === "newonly") {
231
+ return initialList.includes((item as any).__ID__) ? false : true;
232
+ }
233
+ if (typeof canRemove === "function") {
234
+ return canRemove({
235
+ item,
236
+ index,
237
+ lastItem: index + 1 === fields.length,
238
+ });
239
+ }
240
+ return true;
241
+ },
242
+ [canRemove, initialList, fields],
243
+ );
244
+
221
245
  const handleAdd = useCallback(
222
- (item: T) => {
246
+ (item?: T) => {
247
+ if (!item) return;
223
248
  append(item);
224
249
  setTimeout(() => {
225
250
  form.setFocus(
@@ -349,14 +374,26 @@ export const ArrayInput = <T extends AnyObject = string>({
349
374
  onClick={() => handleAdd(onAdd?.())}
350
375
  data-invalid={!!error}
351
376
  disabled={!!disabled || readOnly || fields.length > maxItems}
352
- className={classNames("fabric-addButton", "me-10")}
377
+ className={classNames(
378
+ "fabric-addButton",
379
+ canRemove !== false && "me-10",
380
+ )}
353
381
  >
354
- {addLabel ?? t("addArray")}
382
+ {addLabel ?? t("form:addArray")}
355
383
  </Button>
356
384
  </Tooltip>
357
385
  </div>
358
386
  ),
359
- [error, fields, handleAdd, disabled, readOnly, addLabel, maxItems],
387
+ [
388
+ error,
389
+ fields,
390
+ handleAdd,
391
+ canRemove,
392
+ disabled,
393
+ readOnly,
394
+ addLabel,
395
+ maxItems,
396
+ ],
360
397
  );
361
398
 
362
399
  return (
@@ -365,7 +402,7 @@ export const ArrayInput = <T extends AnyObject = string>({
365
402
  {...rest}
366
403
  appendLabel={
367
404
  <div className="-me-2">
368
- {!fixedList && onAdd && buttonPosition !== "bottom" && addButton}
405
+ {onAdd && buttonPosition !== "bottom" && addButton}
369
406
  </div>
370
407
  }
371
408
  >
@@ -379,6 +416,7 @@ export const ArrayInput = <T extends AnyObject = string>({
379
416
  {typeof children === "function"
380
417
  ? children({
381
418
  index,
419
+ item: item as any,
382
420
  name: `${name}.${index}`,
383
421
  })
384
422
  : cloneChildren(children, (child: AnyObject) =>
@@ -403,7 +441,7 @@ export const ArrayInput = <T extends AnyObject = string>({
403
441
  ),
404
442
  ),
405
443
  )}
406
- {!fixedList && (
444
+ {canRemove !== false && (
407
445
  <Button
408
446
  aria-label="Remove item"
409
447
  icon={CoreIcons.remove}
@@ -414,20 +452,16 @@ export const ArrayInput = <T extends AnyObject = string>({
414
452
  disabled ||
415
453
  readOnly ||
416
454
  fields.length <= minItems ||
417
- canRemove?.({
418
- item: item as T,
419
- index,
420
- lastItem: index + 1 === fields.length,
421
- }) !== false
455
+ removeCheck(item as any, index) === false
422
456
  }
423
- onClick={() => handleRemove(item as T, index)}
457
+ onClick={() => handleRemove(item as any, index)}
424
458
  />
425
459
  )}
426
460
  </SortableItem>
427
461
  ))}
428
462
  </Wrapper>
429
463
  </FieldWrapper>
430
- {!fixedList && onAdd && buttonPosition !== "top" && addButton}
464
+ {onAdd && buttonPosition !== "top" && addButton}
431
465
  </div>
432
466
  );
433
467
  };
@@ -26,6 +26,8 @@ import { type RefProp } from "@react-fabric/core/dist/types/types";
26
26
  import { useEffect, useState } from "react";
27
27
  import { useFileUploader, type UploadHandler } from "../hooks/useFileUploader";
28
28
  import { HiddenInput } from "./Hidden";
29
+ import { AvatarProps } from "@react-fabric/core/dist/types/components/avatar/Avatar";
30
+ import classNames from "classnames";
29
31
 
30
32
  export interface Props extends RefProp {
31
33
  /**
@@ -44,6 +46,10 @@ export interface Props extends RefProp {
44
46
  * avatar name
45
47
  */
46
48
  avatarName?: string;
49
+ rounded?: boolean;
50
+ variant?: AvatarProps["variant"];
51
+ fallbackIcon?: AvatarProps["fallbackIcon"];
52
+ avatarClassName?: AvatarProps["className"];
47
53
  size?: string | number;
48
54
  /**
49
55
  * upload handler to store file in temp storage
@@ -74,8 +80,12 @@ export interface Props extends RefProp {
74
80
  export const AvatarInput = ({
75
81
  size = "6rem",
76
82
  avatarName,
83
+ avatarClassName,
77
84
  value,
85
+ rounded,
78
86
  defaultValue,
87
+ fallbackIcon,
88
+ variant,
79
89
  fileUrl,
80
90
  uploadHandler,
81
91
  ...rest
@@ -117,9 +127,23 @@ export const AvatarInput = ({
117
127
 
118
128
  return (
119
129
  <div className="flex flex-nowrap items-end overflow-hidden">
120
- <div className="inline-block leading-none rounded-full relative outline overflow-hidden">
121
- <Avatar name={avatarName ?? "temp"} size={size} avatar={base64} />
122
- <div className="absolute inset-x-0 bottom-0 cursor-pointer bg-black/20 hover:bg-black/50 text-white text-xs text-center py-1">
130
+ <div
131
+ className={classNames(
132
+ "inline-block leading-none relative outline overflow-hidden",
133
+ rounded && "rounded-full",
134
+ !rounded && "rounded",
135
+ )}
136
+ >
137
+ <Avatar
138
+ name={avatarName ?? "temp"}
139
+ size={size}
140
+ avatar={base64}
141
+ rounded={rounded}
142
+ variant={variant}
143
+ fallbackIcon={fallbackIcon}
144
+ className={avatarClassName}
145
+ />
146
+ <div className="absolute inset-x-0 bottom-0 cursor-pointer opacity-50 bg-black/50 hover:opacity-90 text-white text-xs text-center py-1">
123
147
  <span>Edit</span>
124
148
  <input
125
149
  type="file"
@@ -129,11 +153,14 @@ export const AvatarInput = ({
129
153
  />
130
154
  </div>
131
155
  </div>
132
- <HiddenInput hiddenValue={list?.[0]?.path ?? defaultValue} {...rest} />
156
+ <HiddenInput
157
+ hiddenValue={list?.[0]?.path}
158
+ defaultValue={defaultValue}
159
+ {...rest}
160
+ />
133
161
  {files.map((file, idx) => (
134
162
  <div key={idx} className="px-2 py-1 flex-1 overflow-hidden">
135
163
  <div className="flex flex-nowrap gap-1 items-center">
136
- <div className="flex-initial truncate pe-2">{file.filename}</div>
137
164
  {file.error && (
138
165
  <div className="flex-1 truncate px-2">
139
166
  <span className="text-danger-600">{file.error}</span>
@@ -148,6 +148,7 @@ export const ColorInput = ({
148
148
  >
149
149
  <button
150
150
  data-ref="button"
151
+ type="button"
151
152
  className="flex-1 flex items-center"
152
153
  ref={refs.setReference}
153
154
  {...getReferenceProps({
@@ -33,6 +33,10 @@ interface Props {
33
33
  * hidden value will fire change for form update
34
34
  */
35
35
  hiddenValue?: AnyObject;
36
+ /**
37
+ * default avatar image
38
+ */
39
+ defaultValue?: string;
36
40
  /**
37
41
  * form onChange handler
38
42
  */
@@ -49,6 +53,7 @@ interface Props {
49
53
  */
50
54
  export const HiddenInput = ({
51
55
  hiddenValue,
56
+ defaultValue,
52
57
  onChange,
53
58
  // @ts-expect-error ignore
54
59
  // eslint-disable-next-line react/prop-types
@@ -62,11 +67,10 @@ export const HiddenInput = ({
62
67
  name,
63
68
  }: Props) => {
64
69
  useEffect(() => {
65
- hiddenValue &&
66
- setTimeout(() => {
67
- onChange?.(hiddenValue);
68
- }, 50);
69
- }, [hiddenValue]);
70
+ setTimeout(() => {
71
+ onChange?.(hiddenValue ?? defaultValue);
72
+ }, 50);
73
+ }, [hiddenValue, defaultValue]);
70
74
  return (
71
75
  <Fragment>
72
76
  <input type="hidden" onChange={onChange} value={value} name={name} />
@@ -214,8 +214,8 @@ export const Slider = ({
214
214
  <div
215
215
  ref={rangerInstance.trackElRef}
216
216
  className={classNames(
217
- "flex-1 relative flex items-center",
218
- vertical ? "my-2 w-8" : "mx-2 h-8",
217
+ "relative flex items-center",
218
+ vertical ? "my-2 w-8" : "flex-1 mx-2 h-8",
219
219
  )}
220
220
  style={{ height: vertical ? height : undefined }}
221
221
  >
@@ -262,10 +262,10 @@ export const Slider = ({
262
262
  {displayValue && (
263
263
  <div
264
264
  className={classNames(
265
- "bg-invert text-invert py-px px-2 text-xs absolute rounded z-[5] whitespace-nowrap",
265
+ "bg-invert text-invert py-px px-2 text-xs absolute rounded z-[5] whitespace-nowrap pointer-events-none",
266
266
  "before:absolute before:h-1.5 before:w-1.5 before:z-[-1] before:bg-invert before:top-1/2 before:-translate-y-1/2 before:rotate-45",
267
267
  vertical
268
- ? "end-0 ltr:translate-x-full rtl:-translate-x-full translate-y-2"
268
+ ? "end-0 ltr:translate-x-full rtl:-translate-x-full translate-y-2 ltr:before:-translate-x-[0.125rem] rtl:before:translate-x-[0.125rem] before:start-0"
269
269
  : "top-1/2 -translate-y-1/2",
270
270
  !vertical &&
271
271
  (percentage > 50
@@ -131,7 +131,7 @@ export const Textarea = ({
131
131
  {...rest}
132
132
  >
133
133
  <textarea
134
- className="appearance-none self-stretch bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 min-h-20 resize-none"
134
+ className="appearance-none self-stretch bg-transparent py-1 px-2 flex-1 border-none outline-none ring-0 min-h-12 resize-none"
135
135
  aria-invalid={invalid}
136
136
  aria-disabled={disabled}
137
137
  aria-readonly={readOnly}