@povio/ui 3.3.0 → 3.4.0-rc.2

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 (82) hide show
  1. package/dist/components/inputs/Checkbox/Checkbox.d.ts +1 -2
  2. package/dist/components/inputs/Checkbox/Checkbox.js +93 -100
  3. package/dist/components/inputs/Checkbox/CheckboxGroup.d.ts +1 -2
  4. package/dist/components/inputs/Checkbox/CheckboxGroup.js +109 -113
  5. package/dist/components/inputs/DateTime/DatePicker/DatePicker.d.ts +1 -2
  6. package/dist/components/inputs/DateTime/DatePicker/DatePicker.js +15 -21
  7. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.d.ts +1 -2
  8. package/dist/components/inputs/DateTime/DateRangePicker/DateRangePicker.js +15 -22
  9. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.d.ts +1 -2
  10. package/dist/components/inputs/DateTime/DateTimePicker/DateTimePicker.js +19 -24
  11. package/dist/components/inputs/DateTime/TimePicker/TimePicker.d.ts +1 -2
  12. package/dist/components/inputs/DateTime/TimePicker/TimePicker.js +276 -294
  13. package/dist/components/inputs/DateTime/shared/DateField.d.ts +2 -1
  14. package/dist/components/inputs/DateTime/shared/DateField.js +2 -2
  15. package/dist/components/inputs/DateTime/shared/DatePickerInput.d.ts +1 -2
  16. package/dist/components/inputs/DateTime/shared/DatePickerInput.js +4 -12
  17. package/dist/components/inputs/DateTime/shared/TimePickerInput.d.ts +1 -2
  18. package/dist/components/inputs/DateTime/shared/TimePickerInput.js +45 -48
  19. package/dist/components/inputs/File/FileUpload.d.ts +1 -1
  20. package/dist/components/inputs/File/FileUpload.js +17 -17
  21. package/dist/components/inputs/File/InputUpload.d.ts +1 -1
  22. package/dist/components/inputs/File/InputUpload.js +17 -17
  23. package/dist/components/inputs/File/fileUpload.types.d.ts +1 -1
  24. package/dist/components/inputs/File/inputUpload.types.d.ts +1 -1
  25. package/dist/components/inputs/Input/NumberInput/NumberInput.d.ts +1 -1
  26. package/dist/components/inputs/Input/NumberInput/NumberInput.js +19 -19
  27. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeInput.d.ts +1 -1
  28. package/dist/components/inputs/Input/NumberRangeInput/NumberRangeInput.js +18 -18
  29. package/dist/components/inputs/Input/PasswordInput/PasswordInput.d.ts +1 -1
  30. package/dist/components/inputs/Input/TextArea/TextArea.d.ts +1 -1
  31. package/dist/components/inputs/Input/TextArea/TextArea.js +18 -18
  32. package/dist/components/inputs/Input/TextInput/TextInput.d.ts +2 -2
  33. package/dist/components/inputs/Input/TextInput/TextInput.js +36 -38
  34. package/dist/components/inputs/Inputs/Form.d.ts +4 -4
  35. package/dist/components/inputs/Inputs/InputItem.d.ts +22 -22
  36. package/dist/components/inputs/Inputs/InputItem.js +35 -36
  37. package/dist/components/inputs/Inputs/Inputs.d.ts +2 -2
  38. package/dist/components/inputs/RadioGroup/RadioGroup.d.ts +1 -2
  39. package/dist/components/inputs/RadioGroup/RadioGroup.js +107 -111
  40. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.d.ts +1 -1
  41. package/dist/components/inputs/Selection/Autocomplete/Autocomplete.js +13 -13
  42. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.d.ts +1 -1
  43. package/dist/components/inputs/Selection/Autocomplete/QueryAutocomplete.js +19 -19
  44. package/dist/components/inputs/Selection/Autocomplete/queryAutocomplete.types.d.ts +1 -1
  45. package/dist/components/inputs/Selection/Select/QuerySelect.d.ts +1 -1
  46. package/dist/components/inputs/Selection/Select/QuerySelect.js +19 -19
  47. package/dist/components/inputs/Selection/Select/Select.d.ts +1 -1
  48. package/dist/components/inputs/Selection/Select/Select.js +19 -19
  49. package/dist/components/inputs/Selection/shared/SelectBase.d.ts +0 -1
  50. package/dist/components/inputs/Selection/shared/SelectBase.js +34 -37
  51. package/dist/components/inputs/Selection/shared/select.context.d.ts +2 -2
  52. package/dist/components/inputs/Selection/shared/select.context.js +4 -8
  53. package/dist/components/inputs/Selection/shared/select.types.d.ts +1 -1
  54. package/dist/components/inputs/Skeleton/InputFrame.js +5 -2
  55. package/dist/components/inputs/Slider/Slider.d.ts +1 -1
  56. package/dist/components/inputs/Slider/Slider.js +18 -18
  57. package/dist/components/inputs/TextEditor/TextEditor.d.ts +1 -1
  58. package/dist/components/inputs/TextEditor/TextEditor.js +18 -18
  59. package/dist/components/inputs/Toggle/Toggle.d.ts +1 -2
  60. package/dist/components/inputs/Toggle/Toggle.js +59 -63
  61. package/dist/components/inputs/shared/InputClear.js +40 -25
  62. package/dist/components/inputs/shared/form.binding.d.ts +27 -0
  63. package/dist/components/inputs/shared/form.binding.js +57 -0
  64. package/dist/components/inputs/shared/form.types.d.ts +9 -8
  65. package/dist/components/inputs/shared/form.types.js +8 -0
  66. package/dist/components/segment/Segment.d.ts +1 -1
  67. package/dist/components/segment/Segment.js +17 -17
  68. package/dist/components/segment/segment.types.d.ts +1 -1
  69. package/dist/config/uiConfig.context.d.ts +5 -5
  70. package/dist/config/uiConfig.context.js +3 -12
  71. package/dist/helpers/dynamicColumns.d.ts +1 -1
  72. package/dist/helpers/dynamicInputs.d.ts +7 -7
  73. package/dist/hooks/useAutosave.d.ts +4 -4
  74. package/dist/hooks/useAutosave.js +64 -49
  75. package/dist/hooks/useForm.d.ts +39 -15
  76. package/dist/hooks/useForm.js +96 -43
  77. package/dist/hooks/useFormAutosave.d.ts +8 -9
  78. package/dist/hooks/useFormAutosave.js +23 -9
  79. package/dist/index.d.ts +2 -2
  80. package/dist/index.js +3 -3
  81. package/package.json +2 -3
  82. package/dist/hooks/useAutosave.spec.d.ts +0 -1
@@ -1,10 +1,10 @@
1
- import { FieldValues, UseFormReturn } from 'react-hook-form';
2
- export interface UseAutosaveProps<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues, TResponse = unknown> {
3
- form: UseFormReturn<TFieldValues, TContext, TTransformedValues>;
1
+ import { UIForm } from './useForm';
2
+ export interface UseAutosaveProps<TFieldValues extends Record<string, unknown>, TTransformedValues = TFieldValues, TResponse = unknown> {
3
+ form: UIForm<TFieldValues>;
4
4
  delay?: number;
5
5
  enabled?: boolean;
6
6
  trigger?: "change" | "blur";
7
7
  onSave: (data: Partial<TTransformedValues>) => Promise<TResponse>;
8
8
  onSaveSuccess?: () => void;
9
9
  }
10
- export declare function useAutosave<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues, TResponse = unknown>({ form, delay, enabled, trigger, onSave, onSaveSuccess, }: UseAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>): void;
10
+ export declare function useAutosave<TFieldValues extends Record<string, unknown>, TTransformedValues = TFieldValues, TResponse = unknown>({ form, delay, enabled, trigger, onSave, onSaveSuccess, }: UseAutosaveProps<TFieldValues, TTransformedValues, TResponse>): void;
@@ -1,70 +1,85 @@
1
1
  import { ObjectUtils } from "../utils/object.utils.js";
2
2
  import { isEqual } from "../utils/isEqual.js";
3
3
  import { useEffect, useRef } from "react";
4
- import { useFormState, useWatch } from "react-hook-form";
5
4
  //#region src/hooks/useAutosave.ts
6
- function isNilOrEqual(left, right) {
7
- if (ObjectUtils.isNil(left) && ObjectUtils.isNil(right)) return true;
8
- return isEqual(left, right);
9
- }
10
- function diffLeftOnly(left, right, shallowKeys) {
11
- if (!ObjectUtils.isObject(left) || ObjectUtils.isDate(left) || ObjectUtils.isRegExp(left)) return !isNilOrEqual(left, right) ? left : void 0;
12
- if (Array.isArray(left)) return !isNilOrEqual(left, right) ? left : void 0;
5
+ function diffLeftOnly(left, right) {
6
+ if (!ObjectUtils.isObject(left) || ObjectUtils.isDate(left) || ObjectUtils.isRegExp(left)) return isEqual(left, right) ? void 0 : left;
7
+ if (Array.isArray(left)) return isEqual(left, right) ? void 0 : left;
13
8
  const result = Object.entries(left).reduce((acc, [key, value]) => {
14
- const shallowSubtree = shallowKeys?.[key];
15
- if (shallowSubtree === true) {
16
- if (!isNilOrEqual(value, right?.[key])) acc[key] = value;
17
- return acc;
18
- }
19
- const diff = diffLeftOnly(value, right?.[key], shallowSubtree);
9
+ const diff = diffLeftOnly(value, right?.[key]);
20
10
  if (diff !== void 0 && (!ObjectUtils.isObject(diff) || !ObjectUtils.isEmpty(diff))) acc[key] = diff;
21
11
  return acc;
22
12
  }, {});
23
13
  return ObjectUtils.isEmpty(result) ? void 0 : result;
24
14
  }
15
+ var snapshot = (value) => structuredClone(value);
16
+ function pickChangedValues(source, changes) {
17
+ if (!ObjectUtils.isObject(changes) || Array.isArray(changes)) return source;
18
+ return Object.entries(changes).reduce((result, [key, value]) => {
19
+ result[key] = pickChangedValues(source?.[key], value);
20
+ return result;
21
+ }, {});
22
+ }
25
23
  function useAutosave({ form, delay = 500, enabled = true, trigger = "change", onSave, onSaveSuccess }) {
26
24
  const timeoutRef = useRef(void 0);
27
- const previousBlurTriggerFieldsRef = useRef(void 0);
28
- const { control, reset, handleSubmit } = form;
29
- const { dirtyFields, touchedFields, defaultValues } = useFormState({ control });
30
- const formData = useWatch({ control });
25
+ const savedSnapshotRef = useRef(snapshot(form.state.values));
26
+ const saveQueueRef = useRef(Promise.resolve());
27
+ const latestSaveRef = useRef({
28
+ onSave,
29
+ onSaveSuccess
30
+ });
31
+ latestSaveRef.current = {
32
+ onSave,
33
+ onSaveSuccess
34
+ };
31
35
  useEffect(() => {
32
- if (!enabled || Object.keys(dirtyFields).length === 0) return;
33
- if (trigger === "blur") {
34
- const blurTriggerFields = JSON.stringify(touchedFields);
35
- if (Object.keys(touchedFields).length === 0 || previousBlurTriggerFieldsRef.current === blurTriggerFields) return;
36
- previousBlurTriggerFieldsRef.current = blurTriggerFields;
37
- }
38
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
39
- timeoutRef.current = setTimeout(() => {
40
- handleSubmit(async (data) => {
41
- const changedData = diffLeftOnly(Object.entries(dirtyFields).filter(([, value]) => value).reduce((acc, [key]) => {
42
- acc[key] = data[key];
43
- return acc;
44
- }, {}), defaultValues, dirtyFields) ?? {};
45
- if (Object.keys(changedData).length === 0) return;
46
- try {
47
- reset(void 0, { keepValues: true });
48
- await onSave(changedData);
49
- onSaveSuccess?.();
50
- } catch {
51
- reset(defaultValues);
52
- return;
53
- }
54
- })();
55
- }, delay);
36
+ const clearPending = () => {
37
+ if (timeoutRef.current) {
38
+ clearTimeout(timeoutRef.current);
39
+ timeoutRef.current = void 0;
40
+ }
41
+ };
42
+ const queueSave = () => {
43
+ if (!enabled) return;
44
+ clearPending();
45
+ timeoutRef.current = setTimeout(() => {
46
+ saveQueueRef.current = saveQueueRef.current.then(async () => {
47
+ const valuesAtSaveTime = snapshot(form.state.values);
48
+ const changedValues = diffLeftOnly(valuesAtSaveTime, savedSnapshotRef.current);
49
+ if (!changedValues) return;
50
+ let transformedValues;
51
+ try {
52
+ transformedValues = form.parseValues(valuesAtSaveTime);
53
+ } catch {
54
+ return;
55
+ }
56
+ const payload = pickChangedValues(transformedValues, changedValues);
57
+ if (ObjectUtils.isEmpty(payload)) return;
58
+ try {
59
+ await latestSaveRef.current.onSave(payload);
60
+ savedSnapshotRef.current = valuesAtSaveTime;
61
+ for (const name of Object.keys(payload)) form.setFieldMeta(name, (meta) => ({
62
+ ...meta,
63
+ isDirty: false
64
+ }));
65
+ latestSaveRef.current.onSaveSuccess?.();
66
+ } catch {}
67
+ });
68
+ }, delay);
69
+ };
70
+ const unsubscribeStore = trigger === "change" ? form.store.subscribe(() => {
71
+ if (!isEqual(form.state.values, savedSnapshotRef.current)) queueSave();
72
+ }) : void 0;
73
+ const unsubscribeBlur = trigger === "blur" ? form.subscribeBlur(queueSave) : void 0;
56
74
  return () => {
57
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
75
+ clearPending();
76
+ unsubscribeStore?.unsubscribe();
77
+ unsubscribeBlur?.();
58
78
  };
59
79
  }, [
60
- defaultValues,
61
- dirtyFields,
62
- trigger === "change" ? formData : touchedFields,
63
80
  delay,
64
- onSave,
65
- handleSubmit,
66
81
  enabled,
67
- reset,
82
+ form,
68
83
  trigger
69
84
  ]);
70
85
  }
@@ -1,18 +1,42 @@
1
- import { BrowserNativeObject, ExtractObjects, FieldValues, NestedValue, UseFormProps as UseReactHookFormProps } from 'react-hook-form';
1
+ import { AnyFormApi, DeepKeys, DeepValue, ReactFormExtendedApi } from '@tanstack/react-form';
2
2
  import { z } from 'zod';
3
- type DeepNullablePartial<T> = T extends BrowserNativeObject | NestedValue ? T : {
4
- [K in keyof T]?: ExtractObjects<T[K]> extends never ? T[K] | null : DeepNullablePartial<T[K]>;
3
+ type FormMode = "all" | "onBlur" | "onChange" | "onSubmit" | "onTouched";
4
+ type FieldValidators = {
5
+ onBlur?: ({ value }: {
6
+ value: unknown;
7
+ }) => string | undefined;
8
+ onChange?: ({ value }: {
9
+ value: unknown;
10
+ }) => string | undefined;
5
11
  };
6
- type AsyncDefaultValues<TFieldValues> = (payload?: unknown) => Promise<TFieldValues>;
7
- type NullableDefaultValues<TFieldValues> = TFieldValues extends AsyncDefaultValues<TFieldValues> ? DeepNullablePartial<Awaited<TFieldValues>> : DeepNullablePartial<TFieldValues>;
8
- export type UseFormResolverProps<TFieldValues extends FieldValues, TTransformedValues = TFieldValues> = {
9
- zodSchema: z.ZodType<TTransformedValues, TFieldValues>;
10
- resolver?: never;
11
- } | {
12
- zodSchema?: never;
13
- };
14
- export type UseFormProps<TFieldValues extends FieldValues, TContext, TTransformedValues = TFieldValues> = Omit<UseReactHookFormProps<TFieldValues, TContext, TTransformedValues>, "defaultValues"> & {
15
- defaultValues?: NullableDefaultValues<TFieldValues> | AsyncDefaultValues<TFieldValues>;
12
+ export type FormSubmitHandler<TValues> = (values: TValues) => void | Promise<void>;
13
+ export type FormSubmitErrorHandler<TValues> = (errors: unknown, values: TValues) => unknown;
14
+ type TanStackForm<TFieldValues> = ReactFormExtendedApi<TFieldValues, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, never>;
15
+ export type UIForm<TFieldValues extends Record<string, unknown> = Record<string, unknown>> = Omit<TanStackForm<TFieldValues>, "handleSubmit"> & {
16
+ readonly disabled: boolean;
17
+ getFieldValidators: (name: DeepKeys<TFieldValues>) => FieldValidators | undefined;
18
+ notifyBlur: (name: DeepKeys<TFieldValues>) => void;
19
+ parseValues: (values: TFieldValues) => unknown;
20
+ subscribeBlur: (listener: (name: DeepKeys<TFieldValues>) => void) => () => void;
21
+ handleSubmit: (onValid: FormSubmitHandler<any>, onInvalid?: FormSubmitErrorHandler<TFieldValues>) => (event?: {
22
+ preventDefault?: () => void;
23
+ stopPropagation?: () => void;
24
+ }) => Promise<void>;
16
25
  };
17
- export declare function useForm<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues>({ resolver, zodSchema, defaultValues, ...props }: UseFormProps<TFieldValues, TContext, TTransformedValues> & UseFormResolverProps<TFieldValues, TTransformedValues>): import('react-hook-form').UseFormReturn<TFieldValues, TContext, TTransformedValues>;
18
- export {};
26
+ type AsyncDefaultValues<TFieldValues> = (payload?: unknown) => Promise<TFieldValues>;
27
+ type NullableDefaults<T> = T extends Date | File | Blob ? T : T extends Array<infer TItem> ? Array<NullableDefaults<TItem>> : T extends object ? {
28
+ [K in keyof T]?: NullableDefaults<T[K]> | null;
29
+ } : T | null;
30
+ export interface UseFormProps<TFieldValues, TTransformedValues = TFieldValues> {
31
+ defaultValues?: NullableDefaults<TFieldValues> | AsyncDefaultValues<TFieldValues>;
32
+ disabled?: boolean;
33
+ mode?: FormMode;
34
+ onSubmitAsync?: (props: {
35
+ value: TFieldValues;
36
+ }) => Promise<unknown>;
37
+ zodSchema?: z.ZodType<TTransformedValues, TFieldValues>;
38
+ }
39
+ export declare function useForm<TFieldValues extends Record<string, unknown> = Record<string, unknown>, _TContext = unknown, TTransformedValues = TFieldValues>({ defaultValues, disabled, mode, onSubmitAsync, zodSchema, }?: UseFormProps<TFieldValues, TTransformedValues>): UIForm<TFieldValues>;
40
+ export declare const useFormValue: <TFieldValues extends Record<string, unknown>, TSelected>(form: UIForm<TFieldValues>, selector: (values: TFieldValues) => TSelected) => TSelected;
41
+ export declare const useFormState: <TFieldValues extends Record<string, unknown>, TSelected>(form: UIForm<TFieldValues>, selector: (state: UIForm<TFieldValues>["state"]) => TSelected) => TSelected;
42
+ export type { AnyFormApi, DeepKeys, DeepValue };
@@ -1,48 +1,101 @@
1
1
  import { c } from "react/compiler-runtime";
2
- import { useForm } from "react-hook-form";
3
- import { zodResolver } from "@hookform/resolvers/zod";
2
+ import { useEffect, useMemo, useRef } from "react";
3
+ import { useForm, useStore } from "@tanstack/react-form";
4
4
  //#region src/hooks/useForm.ts
5
- function useForm$1(t0) {
6
- const $ = c(12);
7
- let defaultValues;
8
- let props;
9
- let resolver;
10
- let zodSchema;
11
- if ($[0] !== t0) {
12
- ({resolver, zodSchema, defaultValues, ...props} = t0);
13
- $[0] = t0;
14
- $[1] = defaultValues;
15
- $[2] = props;
16
- $[3] = resolver;
17
- $[4] = zodSchema;
18
- } else {
19
- defaultValues = $[1];
20
- props = $[2];
21
- resolver = $[3];
22
- zodSchema = $[4];
23
- }
24
- let t1;
25
- if ($[5] !== resolver || $[6] !== zodSchema) {
26
- t1 = resolver ?? (zodSchema ? zodResolver(zodSchema) : void 0);
27
- $[5] = resolver;
28
- $[6] = zodSchema;
29
- $[7] = t1;
30
- } else t1 = $[7];
31
- const formResolver = t1;
32
- const t2 = defaultValues;
33
- let t3;
34
- if ($[8] !== formResolver || $[9] !== props || $[10] !== t2) {
35
- t3 = {
36
- ...props,
37
- resolver: formResolver,
38
- defaultValues: t2
5
+ function useForm$1({ defaultValues, disabled = false, mode = "onSubmit", onSubmitAsync, zodSchema } = {}) {
6
+ const submitHandlerRef = useRef(() => void 0);
7
+ const submitErrorHandlerRef = useRef(void 0);
8
+ const blurListenersRef = useRef(/* @__PURE__ */ new Set());
9
+ const fieldValidators = useMemo(() => {
10
+ return /* @__PURE__ */ new Map();
11
+ }, [mode, zodSchema]);
12
+ const formValidator = useMemo(() => {
13
+ if (!zodSchema) return;
14
+ return ({ value }) => {
15
+ const result = zodSchema.safeParse(value);
16
+ if (result.success) return;
17
+ return { fields: Object.fromEntries(result.error.issues.map((issue) => [pathToString(issue.path), issue.message])) };
18
+ };
19
+ }, [zodSchema]);
20
+ const form = useForm({
21
+ defaultValues: (typeof defaultValues === "function" ? {} : defaultValues) ?? {},
22
+ validators: formValidator || onSubmitAsync ? {
23
+ onSubmit: formValidator,
24
+ onSubmitAsync
25
+ } : void 0,
26
+ onSubmit: async ({ value: value_0 }) => {
27
+ const transformed = zodSchema ? zodSchema.parse(value_0) : value_0;
28
+ await submitHandlerRef.current(transformed);
29
+ },
30
+ onSubmitInvalid: ({ value: value_1, formApi }) => {
31
+ submitErrorHandlerRef.current?.(formApi.state.errors, value_1);
32
+ }
33
+ });
34
+ const originalHandleSubmit = useMemo(() => form.handleSubmit.bind(form), [form]);
35
+ const uiForm = form;
36
+ Object.defineProperties(uiForm, { disabled: {
37
+ configurable: true,
38
+ get: () => disabled
39
+ } });
40
+ uiForm.getFieldValidators = (name) => {
41
+ const cached = fieldValidators.get(name);
42
+ if (cached || fieldValidators.has(name)) return cached;
43
+ const schema = zodSchema ? getSchemaAtPath(zodSchema, name) : void 0;
44
+ if (!schema || mode === "onSubmit") {
45
+ fieldValidators.set(name, void 0);
46
+ return;
47
+ }
48
+ const validate = ({ value: value_2 }) => {
49
+ const result_0 = schema.safeParse(value_2);
50
+ return result_0.success ? void 0 : result_0.error.issues[0]?.message;
39
51
  };
40
- $[8] = formResolver;
41
- $[9] = props;
42
- $[10] = t2;
43
- $[11] = t3;
44
- } else t3 = $[11];
45
- return useForm(t3);
52
+ const validators = mode === "onChange" || mode === "all" ? { onChange: validate } : { onBlur: validate };
53
+ fieldValidators.set(name, validators);
54
+ return validators;
55
+ };
56
+ uiForm.notifyBlur = (name_0) => {
57
+ for (const listener of blurListenersRef.current) listener(name_0);
58
+ };
59
+ uiForm.parseValues = (values) => zodSchema ? zodSchema.parse(values) : values;
60
+ uiForm.subscribeBlur = (listener_0) => {
61
+ blurListenersRef.current.add(listener_0);
62
+ return () => blurListenersRef.current.delete(listener_0);
63
+ };
64
+ uiForm.handleSubmit = (onValid, onInvalid) => async (event) => {
65
+ event?.preventDefault?.();
66
+ event?.stopPropagation?.();
67
+ submitHandlerRef.current = onValid;
68
+ submitErrorHandlerRef.current = onInvalid;
69
+ await originalHandleSubmit();
70
+ };
71
+ useEffect(() => {
72
+ if (typeof defaultValues === "function") defaultValues().then((values_0) => form.reset(values_0));
73
+ }, [defaultValues, form]);
74
+ return uiForm;
46
75
  }
76
+ var useFormValue = (form, selector) => {
77
+ const $ = c(2);
78
+ let t0;
79
+ if ($[0] !== selector) {
80
+ t0 = (state) => selector(state.values);
81
+ $[0] = selector;
82
+ $[1] = t0;
83
+ } else t0 = $[1];
84
+ return useStore(form.store, t0);
85
+ };
86
+ var useFormState = (form, selector) => {
87
+ return useStore(form.store, selector);
88
+ };
89
+ var getSchemaAtPath = (rootSchema, path) => {
90
+ let schema = rootSchema;
91
+ for (const segment of parsePath(path)) {
92
+ while (schema?.unwrap && !schema.shape && !schema.element && !schema.items) schema = schema.unwrap();
93
+ schema = typeof segment === "number" ? schema?.element ?? schema?.items?.[segment] : schema?.shape?.[segment];
94
+ if (!schema) return;
95
+ }
96
+ return schema;
97
+ };
98
+ var parsePath = (path) => path.replaceAll("[", ".").replaceAll("]", "").split(".").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
99
+ var pathToString = (path) => path.reduce((result, segment) => typeof segment === "number" ? `${result}[${segment}]` : result ? `${result}.${String(segment)}` : String(segment), "");
47
100
  //#endregion
48
- export { useForm$1 as useForm };
101
+ export { useForm$1 as useForm, useFormState, useFormValue };
@@ -1,15 +1,14 @@
1
1
  import { DependencyList } from 'react';
2
- import { FieldValues } from 'react-hook-form';
3
2
  import { UseAutosaveProps } from './useAutosave';
4
- import { UseFormProps, UseFormResolverProps } from './useForm';
5
- export type UseFormAutosaveProps<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues, TResponse = unknown> = Omit<UseFormProps<TFieldValues, TContext, TTransformedValues>, "defaultValues"> & UseFormResolverProps<TFieldValues, TTransformedValues> & {
6
- autosaveDelay?: UseAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>["delay"];
7
- enableAutosave?: UseAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>["enabled"];
8
- autosaveOn?: UseAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>["trigger"];
3
+ import { UseFormProps } from './useForm';
4
+ export type UseFormAutosaveProps<TFieldValues extends Record<string, unknown> = Record<string, unknown>, _TContext = any, TTransformedValues = TFieldValues, TResponse = unknown> = Omit<UseFormProps<TFieldValues, TTransformedValues>, "defaultValues"> & {
5
+ autosaveDelay?: UseAutosaveProps<TFieldValues, TTransformedValues, TResponse>["delay"];
6
+ enableAutosave?: UseAutosaveProps<TFieldValues, TTransformedValues, TResponse>["enabled"];
7
+ autosaveOn?: UseAutosaveProps<TFieldValues, TTransformedValues, TResponse>["trigger"];
9
8
  normalizeAutosaveData?: (data: Partial<TTransformedValues>) => Partial<TTransformedValues> | undefined;
10
- onAutosave: UseAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>["onSave"];
11
- getResetValues: () => UseFormProps<TFieldValues, TContext, TTransformedValues>["defaultValues"];
9
+ onAutosave: UseAutosaveProps<TFieldValues, TTransformedValues, TResponse>["onSave"];
10
+ getResetValues: () => UseFormProps<TFieldValues, TTransformedValues>["defaultValues"];
12
11
  resetDeps: DependencyList;
13
12
  resetTimeout?: number;
14
13
  };
15
- export declare function useFormAutosave<TFieldValues extends FieldValues = FieldValues, TContext = any, TTransformedValues = TFieldValues, TResponse = any>({ autosaveDelay, enableAutosave, autosaveOn, normalizeAutosaveData, onAutosave, getResetValues, resetDeps, resetTimeout, ...props }: UseFormAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>): import('react-hook-form').UseFormReturn<TFieldValues, TContext, TTransformedValues>;
14
+ export declare function useFormAutosave<TFieldValues extends Record<string, unknown> = Record<string, unknown>, TContext = any, TTransformedValues = TFieldValues, TResponse = any>({ autosaveDelay, enableAutosave, autosaveOn, normalizeAutosaveData, onAutosave, getResetValues, resetDeps, resetTimeout, ...props }: UseFormAutosaveProps<TFieldValues, TContext, TTransformedValues, TResponse>): import('./useForm').UIForm<TFieldValues>;
@@ -26,15 +26,19 @@ function useFormAutosave({ autosaveDelay, enableAutosave, autosaveOn = "change",
26
26
  const resetValues = getResetValues();
27
27
  if (resetValues === void 0) return;
28
28
  const resetFormValues = async () => {
29
- const keepStateOptions = shouldResetFormValuesRef.current ? { keepDirtyValues: true } : void 0;
29
+ const keepCurrentValues = shouldResetFormValuesRef.current;
30
30
  shouldResetFormValuesRef.current = false;
31
- let values = resetValues;
31
+ let values;
32
32
  if (ObjectUtils.isFunction(resetValues)) values = await resetValues();
33
- form.reset(values, keepStateOptions);
33
+ else values = resetValues;
34
+ form.reset(keepCurrentValues ? {
35
+ ...values,
36
+ ...form.state.values
37
+ } : values);
34
38
  };
35
39
  resetFormValues();
36
40
  }, [...resetDeps]);
37
- const onSaveSuccess = () => {
41
+ const prepareForSaveReset = () => {
38
42
  shouldResetFormValuesRef.current = true;
39
43
  if (resetFormValuesTimeoutRef.current) clearTimeout(resetFormValuesTimeoutRef.current);
40
44
  resetFormValuesTimeoutRef.current = setTimeout(() => {
@@ -46,12 +50,22 @@ function useFormAutosave({ autosaveDelay, enableAutosave, autosaveOn = "change",
46
50
  delay: autosaveDelay,
47
51
  enabled: enableAutosave,
48
52
  trigger: autosaveOn,
49
- onSave: useCallback((data) => {
53
+ onSave: useCallback(async (data) => {
50
54
  const normalizedData = normalizeAutosaveData ? normalizeAutosaveData(data) : data;
51
- if (!normalizedData || ObjectUtils.isEmpty(normalizedData)) return Promise.resolve(void 0);
52
- return onAutosave(normalizedData);
53
- }, [normalizeAutosaveData, onAutosave]),
54
- onSaveSuccess
55
+ if (!normalizedData || ObjectUtils.isEmpty(normalizedData)) return;
56
+ prepareForSaveReset();
57
+ try {
58
+ return await onAutosave(normalizedData);
59
+ } catch (error) {
60
+ shouldResetFormValuesRef.current = false;
61
+ if (resetFormValuesTimeoutRef.current) clearTimeout(resetFormValuesTimeoutRef.current);
62
+ throw error;
63
+ }
64
+ }, [
65
+ normalizeAutosaveData,
66
+ onAutosave,
67
+ resetTimeout
68
+ ])
55
69
  });
56
70
  return form;
57
71
  }
package/dist/index.d.ts CHANGED
@@ -230,8 +230,8 @@ export { useDebounceCallback } from './hooks/useDebounceCallback';
230
230
  export { useDeepCompareEffect, useDeepCompareLayoutEffect, useDeepCompareMemo } from './hooks/useDeepCompare';
231
231
  export type { FilterStore } from './hooks/useFilters';
232
232
  export { useFilters } from './hooks/useFilters';
233
- export type { UseFormProps, UseFormResolverProps } from './hooks/useForm';
234
- export { useForm } from './hooks/useForm';
233
+ export type { DeepKeys, DeepValue, FormSubmitErrorHandler, FormSubmitHandler, UIForm, UseFormProps, } from './hooks/useForm';
234
+ export { useForm, useFormState, useFormValue } from './hooks/useForm';
235
235
  export type { UseFormAutosaveProps } from './hooks/useFormAutosave';
236
236
  export { useFormAutosave } from './hooks/useFormAutosave';
237
237
  export { useIntersectionObserver } from './hooks/useIntersectionObserver';
package/dist/index.js CHANGED
@@ -87,10 +87,10 @@ import { DateTimeUtils } from "./utils/date-time.utils.js";
87
87
  import { datePickerInputContentRowDefinition } from "./components/inputs/DateTime/shared/datePickerInput.cva.js";
88
88
  import { popoverDefinition } from "./components/shared/popover.cva.js";
89
89
  import { tooltipWrapperTriggerDefinition } from "./components/inputs/shared/tooltipWrapper.cva.js";
90
- import { useDebounceCallback } from "./hooks/useDebounceCallback.js";
91
90
  import { DatePicker } from "./components/inputs/DateTime/DatePicker/DatePicker.js";
92
91
  import { tagDefinition } from "./components/text/Tag/tag.cva.js";
93
92
  import { Tag } from "./components/text/Tag/Tag.js";
93
+ import { useDebounceCallback } from "./hooks/useDebounceCallback.js";
94
94
  import { selectInputTagsContentWrapperDefinition } from "./components/inputs/Selection/shared/selectInput.cva.js";
95
95
  import { createKeyInteractionsHandler, getKeyInteractionAction, useKeyInteractions } from "./hooks/useKeyInteractions.js";
96
96
  import { selectListBoxItemDefinition } from "./components/inputs/Selection/shared/selectItem.cva.js";
@@ -170,11 +170,11 @@ import { dynamicColumns } from "./helpers/dynamicColumns.js";
170
170
  import { useAutosave } from "./hooks/useAutosave.js";
171
171
  import { RoutingUtils } from "./utils/routing.utils.js";
172
172
  import { useFilters } from "./hooks/useFilters.js";
173
- import { useForm } from "./hooks/useForm.js";
173
+ import { useForm, useFormState, useFormValue } from "./hooks/useForm.js";
174
174
  import { useFormAutosave } from "./hooks/useFormAutosave.js";
175
175
  import { usePagination } from "./hooks/usePagination.js";
176
176
  import { useSorting } from "./hooks/useSorting.js";
177
177
  import { useTableColumnConfig } from "./hooks/useTableColumnConfig.js";
178
178
  import { ArrayUtils } from "./utils/array.utils.js";
179
179
  import { QueriesUtils } from "./utils/queries.utils.js";
180
- export { Accordion, ActionModal, Alert, AlignCenterIcon, AlignLeftIcon, AlignLeftRightIcon, AlignRightIcon, ArrayUtils, ArrowDropDownIcon, ArrowDropUpIcon, ArrowLeftIcon, ArrowRightIcon, Autocomplete, BoldIcon, BottomSheet, Breadcrumbs, BulletedListIcon, Button, CalendarIcon, CellText, CheckIcon, Checkbox, CheckboxCheckmarkIcon, CheckboxGroup, CheckboxIndeterminateIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ClockIcon, CloseIcon, ColumnConfigModal, Confirmation, DatePicker, DateRangePicker, DateTimeIcon, DateTimePicker, DateTimeUtils, DateUtils, DomUtils, Drawer, FileUpload, FileUploadContainer, FileUtils, Form, FormField, HeaderText, HighlightIcon, HighlightOnIcon, HomeIcon, IconButton, InfiniteTable, InfoIcon, InlineIconButton, InputUpload, Inputs, IntlUtils, ItalicIcon, Link, LinkContext, LinkIcon, Loader, Menu, MenuIcon, MenuItem, MenuPopover, Modal, NumberInput, NumberRangeInput, NumberedListIcon, ObjectUtils, PaginatedTable, Pagination, PaginationList, PasswordInput, Pill, PillButton, PointerHorizontalIcon, PointerVerticalIcon, ProgressBar, QueriesUtils, QueryAutocomplete, QuerySelect, RadioGroup, ResponsivePopover, RestUtils, RoutingUtils, Segment, Select, SendIcon, Slider, SplitButton, Stepper, StrikethroughIcon, StringUtils, Table, Tag, TextArea, TextButton, TextColorIcon, TextInput, ThemeContext, TimePicker, Toast, ToastContainer, Toggle, ToggleButton, Tooltip, TooltipEllipsis, Typography, UIConfig, UIOverrides, UIRouter, UnderlinedIcon, VisibilityIcon, VisibilityOffIcon, ZodUtils, accordionChevronDefinition, accordionDefinition, accordionHeadingDefinition, accordionHeadingSubtitleDefinition, accordionHeadingTitleDefinition, accordionIconDefinition, accordionItemDefinition, accordionPanelContentDefinition, accordionPanelDefinition, accordionTriggerDefinition, alertDefinition, breadcrumbChevronDefinition, breadcrumbIconDefinition, breadcrumbItemDefinition, breadcrumbSegmentDefinition, breadcrumbsDefinition, buttonContentDefinition, buttonDefinition, buttonIconSizeDefinition, buttonSizeDefinition, checkboxContentRowDefinition, checkboxContentWrapperDefinition, checkboxDefinition, checkboxGroupLabelDefinition, checkboxIconDefinition, compoundMapper, createKeyInteractionsHandler, datePickerInputContentRowDefinition, dynamicColumns, dynamicInputs, fileUploadDropZoneDefinition, formFieldErrorDefinition, formFieldHeaderDefinition, formFieldHelperDefinition, getKeyInteractionAction, inputBaseDefinition, inputClearClassDefinition, inputContentWrapperDefinition, inputSideDefinition, inputSizeDefinition, inputUploadButtonDefinition, inputUploadDropZoneDefinition, isEqual, labelDefinition, linkDefinition, loaderDefinition, loaderWrapperDefinition, logger, menuDefinition, menuItemDefinition, menuPopoverDefinition, menuPopoverWrapperDefinition, modalContentDefinition, modalMainDefinition, modalOverlayDefinition, ns, pillButtonContentDefinition, pillButtonDefinition, popoverDefinition, progressBarDefinition, progressBarFillDefinition, progressBarTrackDefinition, progressBarTrackWrapperDefinition, progressBarValueDefinition, radioContentRowDefinition, radioContentWrapperDefinition, radioDefinition, resources, segmentDefinition, segmentItemDefinition, selectInputTagsContentWrapperDefinition, selectListBoxItemDefinition, selectPopoverDefinition, statusIconDefinition, statusSeparatorDefinition, stepperDefinition, stepperIconDefinition, stepperItemDefinition, stepperNumberDefinition, stepperSeparatorDefinition, stepperSubtextDefinition, stepperTitleDefinition, tableCellTextDefinition, tableDataDefinition, tableHeadDataDefinition, tableHeadRowDefinition, tableHeaderTextDefinition, tableRowDefinition, tagDefinition, textAreaWrapperDefinition, toastDefinition, statusIconDefinition$1 as toastStatusIconDefinition, statusSeparatorDefinition$1 as toastStatusSeparatorDefinition, toggleDefinition, tooltipDefinition, tooltipPointerHorizontalDefinition, tooltipPointerVerticalDefinition, tooltipTextDefinition, tooltipWrapperTriggerDefinition, typographyDefinition, uiOutlineClass, useAutosave, useBreakpoint, useDebounceCallback, useDeepCompareEffect, useDeepCompareLayoutEffect, useDeepCompareMemo, useFilters, useForm, useFormAutosave, useIntersectionObserver, useKeyInteractions, useLocalStorage, useLongPressRepeat, usePagination, useScrollableListBox, useSorting, useStateAndRef, useTableColumnConfig, useTableNav, useToast, useTranslationMemo };
180
+ export { Accordion, ActionModal, Alert, AlignCenterIcon, AlignLeftIcon, AlignLeftRightIcon, AlignRightIcon, ArrayUtils, ArrowDropDownIcon, ArrowDropUpIcon, ArrowLeftIcon, ArrowRightIcon, Autocomplete, BoldIcon, BottomSheet, Breadcrumbs, BulletedListIcon, Button, CalendarIcon, CellText, CheckIcon, Checkbox, CheckboxCheckmarkIcon, CheckboxGroup, CheckboxIndeterminateIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ClockIcon, CloseIcon, ColumnConfigModal, Confirmation, DatePicker, DateRangePicker, DateTimeIcon, DateTimePicker, DateTimeUtils, DateUtils, DomUtils, Drawer, FileUpload, FileUploadContainer, FileUtils, Form, FormField, HeaderText, HighlightIcon, HighlightOnIcon, HomeIcon, IconButton, InfiniteTable, InfoIcon, InlineIconButton, InputUpload, Inputs, IntlUtils, ItalicIcon, Link, LinkContext, LinkIcon, Loader, Menu, MenuIcon, MenuItem, MenuPopover, Modal, NumberInput, NumberRangeInput, NumberedListIcon, ObjectUtils, PaginatedTable, Pagination, PaginationList, PasswordInput, Pill, PillButton, PointerHorizontalIcon, PointerVerticalIcon, ProgressBar, QueriesUtils, QueryAutocomplete, QuerySelect, RadioGroup, ResponsivePopover, RestUtils, RoutingUtils, Segment, Select, SendIcon, Slider, SplitButton, Stepper, StrikethroughIcon, StringUtils, Table, Tag, TextArea, TextButton, TextColorIcon, TextInput, ThemeContext, TimePicker, Toast, ToastContainer, Toggle, ToggleButton, Tooltip, TooltipEllipsis, Typography, UIConfig, UIOverrides, UIRouter, UnderlinedIcon, VisibilityIcon, VisibilityOffIcon, ZodUtils, accordionChevronDefinition, accordionDefinition, accordionHeadingDefinition, accordionHeadingSubtitleDefinition, accordionHeadingTitleDefinition, accordionIconDefinition, accordionItemDefinition, accordionPanelContentDefinition, accordionPanelDefinition, accordionTriggerDefinition, alertDefinition, breadcrumbChevronDefinition, breadcrumbIconDefinition, breadcrumbItemDefinition, breadcrumbSegmentDefinition, breadcrumbsDefinition, buttonContentDefinition, buttonDefinition, buttonIconSizeDefinition, buttonSizeDefinition, checkboxContentRowDefinition, checkboxContentWrapperDefinition, checkboxDefinition, checkboxGroupLabelDefinition, checkboxIconDefinition, compoundMapper, createKeyInteractionsHandler, datePickerInputContentRowDefinition, dynamicColumns, dynamicInputs, fileUploadDropZoneDefinition, formFieldErrorDefinition, formFieldHeaderDefinition, formFieldHelperDefinition, getKeyInteractionAction, inputBaseDefinition, inputClearClassDefinition, inputContentWrapperDefinition, inputSideDefinition, inputSizeDefinition, inputUploadButtonDefinition, inputUploadDropZoneDefinition, isEqual, labelDefinition, linkDefinition, loaderDefinition, loaderWrapperDefinition, logger, menuDefinition, menuItemDefinition, menuPopoverDefinition, menuPopoverWrapperDefinition, modalContentDefinition, modalMainDefinition, modalOverlayDefinition, ns, pillButtonContentDefinition, pillButtonDefinition, popoverDefinition, progressBarDefinition, progressBarFillDefinition, progressBarTrackDefinition, progressBarTrackWrapperDefinition, progressBarValueDefinition, radioContentRowDefinition, radioContentWrapperDefinition, radioDefinition, resources, segmentDefinition, segmentItemDefinition, selectInputTagsContentWrapperDefinition, selectListBoxItemDefinition, selectPopoverDefinition, statusIconDefinition, statusSeparatorDefinition, stepperDefinition, stepperIconDefinition, stepperItemDefinition, stepperNumberDefinition, stepperSeparatorDefinition, stepperSubtextDefinition, stepperTitleDefinition, tableCellTextDefinition, tableDataDefinition, tableHeadDataDefinition, tableHeadRowDefinition, tableHeaderTextDefinition, tableRowDefinition, tagDefinition, textAreaWrapperDefinition, toastDefinition, statusIconDefinition$1 as toastStatusIconDefinition, statusSeparatorDefinition$1 as toastStatusSeparatorDefinition, toggleDefinition, tooltipDefinition, tooltipPointerHorizontalDefinition, tooltipPointerVerticalDefinition, tooltipTextDefinition, tooltipWrapperTriggerDefinition, typographyDefinition, uiOutlineClass, useAutosave, useBreakpoint, useDebounceCallback, useDeepCompareEffect, useDeepCompareLayoutEffect, useDeepCompareMemo, useFilters, useForm, useFormAutosave, useFormState, useFormValue, useIntersectionObserver, useKeyInteractions, useLocalStorage, useLongPressRepeat, usePagination, useScrollableListBox, useSorting, useStateAndRef, useTableColumnConfig, useTableNav, useToast, useTranslationMemo };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@povio/ui",
3
- "version": "3.3.0",
3
+ "version": "3.4.0-rc.2",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,7 +20,6 @@
20
20
  "@dnd-kit/modifiers": "^9.0.0",
21
21
  "@dnd-kit/sortable": "^10.0.0",
22
22
  "@dnd-kit/utilities": "^3.2.2",
23
- "@hookform/resolvers": "^5.2.2",
24
23
  "@internationalized/date": "^3.11.0",
25
24
  "@react-aria/button": "^3.14.4",
26
25
  "@react-aria/calendar": "^3.9.4",
@@ -30,6 +29,7 @@
30
29
  "@react-stately/calendar": "^3.9.2",
31
30
  "@react-stately/datepicker": "^3.16.0",
32
31
  "@react-types/shared": "^3.33.0",
32
+ "@tanstack/react-form": "^1.33.2",
33
33
  "@tanstack/react-table": "^8.21.3",
34
34
  "axios": "^1.13.2",
35
35
  "class-variance-authority": "^0.7.1",
@@ -40,7 +40,6 @@
40
40
  "motion": "~12.23.24",
41
41
  "react-aria": "^3.46.0",
42
42
  "react-aria-components": "^1.15.1",
43
- "react-hook-form": "^7.65.0",
44
43
  "react-responsive": "^10.0.1",
45
44
  "react-stately": "^3.44.0",
46
45
  "react-toastify": "^11.0.5",
@@ -1 +0,0 @@
1
- export {};