@mapples/form 1.1.2 → 1.2.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.
- package/dist/components/Form.d.ts +2 -1
- package/dist/components/Form.d.ts.map +1 -1
- package/dist/components/Form.js +7 -5
- package/dist/components/Form.js.map +1 -1
- package/dist/hooks/useBindFormField.d.ts.map +1 -1
- package/dist/hooks/useBindFormField.js +6 -1
- package/dist/hooks/useBindFormField.js.map +1 -1
- package/dist/hooks/useFormFieldToggle.d.ts +2 -0
- package/dist/hooks/useFormFieldToggle.d.ts.map +1 -1
- package/dist/hooks/useFormFieldToggle.js +13 -7
- package/dist/hooks/useFormFieldToggle.js.map +1 -1
- package/dist/state/index.d.ts +37 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +118 -29
- package/dist/state/index.js.map +1 -1
- package/dist/types/index.d.ts +13 -3
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ import { FormProps } from '../types';
|
|
|
13
13
|
* @param props.ref - Optional ref to access the FormState instance directly
|
|
14
14
|
* @param props.historyItems - Number of history states to keep for undo/redo (0 to disable)
|
|
15
15
|
* @param props.historyItemThrottle - Save a history entry every Nth change
|
|
16
|
+
* @param props.historyCoalesceMs - Coalesce write bursts into one history entry
|
|
16
17
|
* @param props.filterHistoryKeys - Field paths to exclude from history tracking
|
|
17
18
|
* @param props.onChange - Callback invoked whenever any form value changes
|
|
18
19
|
* @returns JSX element that provides form context to children
|
|
@@ -41,6 +42,6 @@ import { FormProps } from '../types';
|
|
|
41
42
|
*
|
|
42
43
|
* @public
|
|
43
44
|
*/
|
|
44
|
-
declare const Form: <T extends object>({ children, initialValues, validationSchema, onSubmit, ref, historyItems, filterHistoryKeys, historyItemThrottle, onChange, }: PropsWithChildren<FormProps<T>>) => import("react").JSX.Element;
|
|
45
|
+
declare const Form: <T extends object>({ children, initialValues, validationSchema, onSubmit, ref, historyItems, filterHistoryKeys, historyItemThrottle, historyCoalesceMs, onChange, }: PropsWithChildren<FormProps<T>>) => import("react").JSX.Element;
|
|
45
46
|
export default Form;
|
|
46
47
|
//# sourceMappingURL=Form.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAOf,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC
|
|
1
|
+
{"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAKlB,MAAM,OAAO,CAAC;AAOf,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,QAAA,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,kJAW7B,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,gCAuGjC,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
package/dist/components/Form.js
CHANGED
|
@@ -15,6 +15,7 @@ import FormState from '../state';
|
|
|
15
15
|
* @param props.ref - Optional ref to access the FormState instance directly
|
|
16
16
|
* @param props.historyItems - Number of history states to keep for undo/redo (0 to disable)
|
|
17
17
|
* @param props.historyItemThrottle - Save a history entry every Nth change
|
|
18
|
+
* @param props.historyCoalesceMs - Coalesce write bursts into one history entry
|
|
18
19
|
* @param props.filterHistoryKeys - Field paths to exclude from history tracking
|
|
19
20
|
* @param props.onChange - Callback invoked whenever any form value changes
|
|
20
21
|
* @returns JSX element that provides form context to children
|
|
@@ -43,7 +44,7 @@ import FormState from '../state';
|
|
|
43
44
|
*
|
|
44
45
|
* @public
|
|
45
46
|
*/
|
|
46
|
-
const Form = ({ children, initialValues, validationSchema, onSubmit, ref, historyItems, filterHistoryKeys, historyItemThrottle, onChange, }) => {
|
|
47
|
+
const Form = ({ children, initialValues, validationSchema, onSubmit, ref, historyItems, filterHistoryKeys, historyItemThrottle, historyCoalesceMs, onChange, }) => {
|
|
47
48
|
const [touched, setTouched] = useState({});
|
|
48
49
|
const [submitting, setSubmitting] = useState(false);
|
|
49
50
|
const [validationErrors, setValidationErrors] = useState(null);
|
|
@@ -52,7 +53,7 @@ const Form = ({ children, initialValues, validationSchema, onSubmit, ref, histor
|
|
|
52
53
|
// when initialValues/schema change identity (e.g. inline object literals on
|
|
53
54
|
// every parent render), which would otherwise wipe edited values back to the
|
|
54
55
|
// initial state. We never call the setter, so this never triggers a re-render.
|
|
55
|
-
const [form] = useState(() => new FormState(initialValues, validationSchema, historyItems, historyItemThrottle, filterHistoryKeys));
|
|
56
|
+
const [form] = useState(() => new FormState(initialValues, validationSchema, historyItems, historyItemThrottle, filterHistoryKeys, historyCoalesceMs));
|
|
56
57
|
useEffect(() => {
|
|
57
58
|
if (!onChange)
|
|
58
59
|
return;
|
|
@@ -81,12 +82,13 @@ const Form = ({ children, initialValues, validationSchema, onSubmit, ref, histor
|
|
|
81
82
|
setSubmitting(false);
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
85
|
+
// `onSubmit` belongs to the consumer: it is responsible for reporting its
|
|
86
|
+
// own failures. Anything that escapes it is a real fault and must reach the
|
|
87
|
+
// caller rather than being swallowed here — `finally` only clears the
|
|
88
|
+
// submitting flag.
|
|
84
89
|
try {
|
|
85
90
|
await onSubmit?.(form.getValues());
|
|
86
91
|
}
|
|
87
|
-
catch (e) {
|
|
88
|
-
console.error(e);
|
|
89
|
-
}
|
|
90
92
|
finally {
|
|
91
93
|
setSubmitting(false);
|
|
92
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.js","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,QAAQ,GACT,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,SAAS,MAAM,UAAU,CAAC;AAGjC
|
|
1
|
+
{"version":3,"file":"Form.js","sourceRoot":"","sources":["../../src/components/Form.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBindFormField.d.ts","sourceRoot":"","sources":["../../src/hooks/useBindFormField.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,gBAAgB,GAAI,CAAC,EAAE,WAAW,MAAM,EAAE,eAAe,MAAM;;;;;;;
|
|
1
|
+
{"version":3,"file":"useBindFormField.d.ts","sourceRoot":"","sources":["../../src/hooks/useBindFormField.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,gBAAgB,GAAI,CAAC,EAAE,WAAW,MAAM,EAAE,eAAe,MAAM;;;;;;;yBAyBtD,CAAC;CAef,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -34,7 +34,12 @@ const useBindFormField = (fieldPath, fallBackPath) => {
|
|
|
34
34
|
const [value, setValue] = useState();
|
|
35
35
|
useEffect(() => {
|
|
36
36
|
const unsubscribe = form?.subscribeOnChange((v) => {
|
|
37
|
-
|
|
37
|
+
// Every document change notifies this subscription, including changes
|
|
38
|
+
// that moved or removed the node `fieldPath` points at — the path is
|
|
39
|
+
// fixed at subscribe time and goes stale until the effect re-runs. A
|
|
40
|
+
// source that no longer resolves has nothing to mirror; propagating
|
|
41
|
+
// its `undefined` would only write at the stale location.
|
|
42
|
+
if (fallBackPath && v !== undefined) {
|
|
38
43
|
form?.setValue(fallBackPath, v);
|
|
39
44
|
}
|
|
40
45
|
setValue(v);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBindFormField.js","sourceRoot":"","sources":["../../src/hooks/useBindFormField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,gBAAgB,GAAG,CAAI,SAAiB,EAAE,YAAqB,EAAE,EAAE;IACvE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GACvD,aAAa,CAAC,SAAS,CAAC,CAAC;IAE3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAiB,CAAC;IAEpD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,IAAI,EAAE,iBAAiB,CAAI,CAAC,CAAC,EAAE,EAAE;YACnD,IAAI,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useBindFormField.js","sourceRoot":"","sources":["../../src/hooks/useBindFormField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAE5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,gBAAgB,GAAG,CAAI,SAAiB,EAAE,YAAqB,EAAE,EAAE;IACvE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GACvD,aAAa,CAAC,SAAS,CAAC,CAAC;IAE3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAiB,CAAC;IAEpD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,IAAI,EAAE,iBAAiB,CAAI,CAAC,CAAC,EAAE,EAAE;YACnD,sEAAsE;YACtE,qEAAqE;YACrE,qEAAqE;YACrE,oEAAoE;YACpE,0DAA0D;YAC1D,IAAI,YAAY,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBACpC,IAAI,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YAClC,CAAC;YACD,QAAQ,CAAC,CAAC,CAAC,CAAC;QACd,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,EAAE,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IAEpC,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,QAAW,EAAE,EAAE;QACd,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC,EACD,CAAC,SAAS,EAAE,IAAI,CAAC,CAClB,CAAC;IAEF,OAAO;QACL,KAAK;QACL,KAAK;QACL,MAAM;QACN,SAAS;QACT,QAAQ;QACR,KAAK;QACL,QAAQ,EAAE,cAAc;KACzB,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook to manage boolean toggle fields.
|
|
3
3
|
* This hook provides a simple way to handle boolean fields with toggle functionality.
|
|
4
|
+
* The value follows the stored field (an existing `true` renders as on), not
|
|
5
|
+
* only the toggles made through this hook.
|
|
4
6
|
*
|
|
5
7
|
* @param fieldPath - Dot notation path to the boolean field
|
|
6
8
|
* @returns Object containing current value and toggle function
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFieldToggle.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormFieldToggle.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"useFormFieldToggle.d.ts","sourceRoot":"","sources":["../../src/hooks/useFormFieldToggle.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,kBAAkB,GAAI,WAAW,MAAM;;;CA4B5C,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import useForm from './useForm';
|
|
3
3
|
/**
|
|
4
4
|
* Hook to manage boolean toggle fields.
|
|
5
5
|
* This hook provides a simple way to handle boolean fields with toggle functionality.
|
|
6
|
+
* The value follows the stored field (an existing `true` renders as on), not
|
|
7
|
+
* only the toggles made through this hook.
|
|
6
8
|
*
|
|
7
9
|
* @param fieldPath - Dot notation path to the boolean field
|
|
8
10
|
* @returns Object containing current value and toggle function
|
|
@@ -29,13 +31,17 @@ import useForm from './useForm';
|
|
|
29
31
|
*/
|
|
30
32
|
const useFormFieldToggle = (fieldPath) => {
|
|
31
33
|
const { form } = useForm();
|
|
32
|
-
const [value, setValue] = useState(
|
|
34
|
+
const [value, setValue] = useState(() => !!form?.getValue(fieldPath));
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const unsubscribe = form?.subscribeOnChange((next) => setValue(!!next), fieldPath);
|
|
37
|
+
return () => {
|
|
38
|
+
unsubscribe?.();
|
|
39
|
+
};
|
|
40
|
+
}, [fieldPath, form]);
|
|
33
41
|
const handleToggleValue = () => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return nextValue;
|
|
38
|
-
});
|
|
42
|
+
const nextValue = !value;
|
|
43
|
+
setValue(nextValue);
|
|
44
|
+
form?.setValue(fieldPath, nextValue);
|
|
39
45
|
};
|
|
40
46
|
return {
|
|
41
47
|
value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormFieldToggle.js","sourceRoot":"","sources":["../../src/hooks/useFormFieldToggle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useFormFieldToggle.js","sourceRoot":"","sources":["../../src/hooks/useFormFieldToggle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,OAAO,MAAM,WAAW,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAE,EAAE;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;IAE3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAChC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAsB,SAAS,CAAC,CACvD,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,WAAW,GAAG,IAAI,EAAE,iBAAiB,CACzC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAC1B,SAAS,CACV,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,WAAW,EAAE,EAAE,CAAC;QAClB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IAEtB,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC;QACzB,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpB,IAAI,EAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;QACL,WAAW,EAAE,iBAAiB;KAC/B,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
package/dist/state/index.d.ts
CHANGED
|
@@ -20,6 +20,10 @@ declare class FormState<T extends object> {
|
|
|
20
20
|
private readonly historyItemThrottle;
|
|
21
21
|
private saveCounter;
|
|
22
22
|
private readonly filterHistoryKeys;
|
|
23
|
+
private readonly historyCoalesceMs;
|
|
24
|
+
private lastHistoryWriteAt;
|
|
25
|
+
private historyDirty;
|
|
26
|
+
private listenerSeq;
|
|
23
27
|
/**
|
|
24
28
|
* Creates a new FormState instance.
|
|
25
29
|
*
|
|
@@ -28,8 +32,11 @@ declare class FormState<T extends object> {
|
|
|
28
32
|
* @param historyItems - Number of history items to keep for undo/redo (0 to disable)
|
|
29
33
|
* @param historyItemThrottle - Throttle for saving history items (every Nth change)
|
|
30
34
|
* @param filterHistoryKeys - Array of field paths to exclude from history tracking
|
|
35
|
+
* @param historyCoalesceMs - Coalesce writes closer together than this into
|
|
36
|
+
* one history entry (a typing or drag burst becomes a single undo step).
|
|
37
|
+
* 0 keeps the counter-throttle behavior.
|
|
31
38
|
*/
|
|
32
|
-
constructor(initialValues: T, validationSchema?: ObjectSchema<T>, historyItems?: number, historyItemThrottle?: number, filterHistoryKeys?: string[]);
|
|
39
|
+
constructor(initialValues: T, validationSchema?: ObjectSchema<T>, historyItems?: number, historyItemThrottle?: number, filterHistoryKeys?: string[], historyCoalesceMs?: number);
|
|
33
40
|
/**
|
|
34
41
|
* Gets a deep copy of all form values.
|
|
35
42
|
*
|
|
@@ -63,6 +70,14 @@ declare class FormState<T extends object> {
|
|
|
63
70
|
* @param value - The value to set at the specified path
|
|
64
71
|
*/
|
|
65
72
|
setValue<V>(path: string, value?: V): void;
|
|
73
|
+
/**
|
|
74
|
+
* Whether a write to `writePath` affects a subscriber at `subscriptionPath`.
|
|
75
|
+
* Segment-aware in both directions: a write below the subscription changes
|
|
76
|
+
* the subscribed value's contents; a write at or above it replaces the
|
|
77
|
+
* subscribed value outright. Root subscribers (no path) see every write.
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private pathsIntersect;
|
|
66
81
|
/**
|
|
67
82
|
* Subscribes to form value changes.
|
|
68
83
|
*
|
|
@@ -93,7 +108,16 @@ declare class FormState<T extends object> {
|
|
|
93
108
|
* @throws Throws validation errors if validation fails
|
|
94
109
|
*/
|
|
95
110
|
validate(): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Commits the end state of a coalescing burst that has gone quiet. MUST run
|
|
113
|
+
* before the next mutation lands in `this.values` — afterwards the burst's
|
|
114
|
+
* true end state is gone. Called at the top of `setValue`/`setValues`, and
|
|
115
|
+
* from `prev()` so an undo taken mid-burst leaves the burst redoable.
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
private finalizeStaleHistoryBurst;
|
|
96
119
|
private saveToHistory;
|
|
120
|
+
private pushHistoryEntry;
|
|
97
121
|
/**
|
|
98
122
|
* Moves to the previous state in the form history (undo operation).
|
|
99
123
|
*
|
|
@@ -118,6 +142,18 @@ declare class FormState<T extends object> {
|
|
|
118
142
|
* @returns True if redo operation is possible
|
|
119
143
|
*/
|
|
120
144
|
canNext(): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Delivers the current values to subscribers — all of them, or only those
|
|
147
|
+
* whose path intersects `changedPath` when one is given.
|
|
148
|
+
*
|
|
149
|
+
* Cost discipline: the editor holds hundreds of subscriptions on one large
|
|
150
|
+
* document, and this runs on every write. Pathed subscribers get a clone of
|
|
151
|
+
* just their subtree; root subscribers share ONE lazily-created full clone
|
|
152
|
+
* per pass. Subscribers must therefore treat delivered values as read-only.
|
|
153
|
+
* Fresh clones (not `this.values` references) are still required so React
|
|
154
|
+
* state setters see a new identity per delivery.
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
121
157
|
private notifySubscriptions;
|
|
122
158
|
private notifyHistorySubscriptions;
|
|
123
159
|
private remapValidationError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAEpD,OAAO,KAAK,EAEV,oBAAoB,EAErB,MAAM,UAAU,CAAC;AAElB;;;;;;;GAOG;AACH,cAAM,SAAS,CAAC,CAAC,SAAS,MAAM;IAC9B,OAAO,CAAC,MAAM,CAAI;IAElB,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,wBAAwB,CAAsC;IACtE,OAAO,CAAC,MAAM,CAAkD;IAEhE,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAW;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAEpD,OAAO,KAAK,EAEV,oBAAoB,EAErB,MAAM,UAAU,CAAC;AAElB;;;;;;;GAOG;AACH,cAAM,SAAS,CAAC,CAAC,SAAS,MAAM;IAC9B,OAAO,CAAC,MAAM,CAAI;IAElB,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,wBAAwB,CAAsC;IACtE,OAAO,CAAC,MAAM,CAAkD;IAEhE,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAW;IAC7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,WAAW,CAAa;IAEhC;;;;;;;;;;;OAWG;gBAED,aAAa,EAAE,CAAC,EAChB,gBAAgB,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAClC,YAAY,GAAE,MAAU,EACxB,mBAAmB,GAAE,MAAU,EAC/B,iBAAiB,GAAE,MAAM,EAAO,EAChC,iBAAiB,GAAE,MAAU;IAe/B;;;;OAIG;IACH,SAAS;IAIT;;;;OAIG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;IAInD;;;;OAIG;IACH,SAAS;IAIT;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;IAQpD;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;IA2BnC;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAQtB;;;;;;;OAOG;IACH,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;IAa/D;;;;;OAKG;IACH,wBAAwB,CAAC,EAAE,EAAE,MAAM,IAAI;IAQvC;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,CAAC;IAI7B;;;;OAIG;IACG,QAAQ;IAYd;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,gBAAgB;IAaxB;;;;OAIG;IACH,IAAI;IAgBJ;;;;OAIG;IACH,IAAI;IASJ;;;;OAIG;IACH,OAAO;IAIP;;;;OAIG;IACH,OAAO;IAIP;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,0BAA0B;IAMlC,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,0BAA0B;IAIlC,OAAO,CAAC,kBAAkB;CAK3B;AAED,eAAe,SAAS,CAAC"}
|
package/dist/state/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cloneDeep, get, set, groupBy, isEqual, some } from 'lodash';
|
|
1
|
+
import { cloneDeep, get, has, set, groupBy, isEqual, some } from 'lodash';
|
|
2
2
|
/**
|
|
3
3
|
* FormState manages the state of a form including values, validation, history, and subscriptions.
|
|
4
4
|
* It provides methods to get/set values, validate data, manage history for undo/redo functionality,
|
|
@@ -19,6 +19,10 @@ class FormState {
|
|
|
19
19
|
historyItemThrottle;
|
|
20
20
|
saveCounter = 0;
|
|
21
21
|
filterHistoryKeys;
|
|
22
|
+
historyCoalesceMs;
|
|
23
|
+
lastHistoryWriteAt = 0;
|
|
24
|
+
historyDirty = false;
|
|
25
|
+
listenerSeq = 0;
|
|
22
26
|
/**
|
|
23
27
|
* Creates a new FormState instance.
|
|
24
28
|
*
|
|
@@ -27,13 +31,17 @@ class FormState {
|
|
|
27
31
|
* @param historyItems - Number of history items to keep for undo/redo (0 to disable)
|
|
28
32
|
* @param historyItemThrottle - Throttle for saving history items (every Nth change)
|
|
29
33
|
* @param filterHistoryKeys - Array of field paths to exclude from history tracking
|
|
34
|
+
* @param historyCoalesceMs - Coalesce writes closer together than this into
|
|
35
|
+
* one history entry (a typing or drag burst becomes a single undo step).
|
|
36
|
+
* 0 keeps the counter-throttle behavior.
|
|
30
37
|
*/
|
|
31
|
-
constructor(initialValues, validationSchema, historyItems = 0, historyItemThrottle = 5, filterHistoryKeys = []) {
|
|
38
|
+
constructor(initialValues, validationSchema, historyItems = 0, historyItemThrottle = 5, filterHistoryKeys = [], historyCoalesceMs = 0) {
|
|
32
39
|
this.values = cloneDeep(initialValues);
|
|
33
40
|
this.validationSchema = validationSchema;
|
|
34
41
|
this.historyItems = historyItems;
|
|
35
42
|
this.historyItemThrottle = historyItemThrottle;
|
|
36
43
|
this.filterHistoryKeys = filterHistoryKeys;
|
|
44
|
+
this.historyCoalesceMs = historyCoalesceMs;
|
|
37
45
|
if (this.historyItems > 0) {
|
|
38
46
|
this.history = [cloneDeep(initialValues)];
|
|
39
47
|
this.historyIndex = 0;
|
|
@@ -70,13 +78,10 @@ class FormState {
|
|
|
70
78
|
* @param cb - Optional callback invoked with `true` after the values and subscriptions have been updated
|
|
71
79
|
*/
|
|
72
80
|
setValues(values, cb) {
|
|
81
|
+
this.finalizeStaleHistoryBurst();
|
|
73
82
|
this.values = cloneDeep(values);
|
|
74
83
|
this.saveToHistory();
|
|
75
|
-
this.
|
|
76
|
-
subscription.cb(subscription.path
|
|
77
|
-
? get(this.getValues(), subscription.path)
|
|
78
|
-
: this.getValues());
|
|
79
|
-
});
|
|
84
|
+
this.notifySubscriptions();
|
|
80
85
|
cb?.(true);
|
|
81
86
|
}
|
|
82
87
|
/**
|
|
@@ -87,20 +92,42 @@ class FormState {
|
|
|
87
92
|
* @param value - The value to set at the specified path
|
|
88
93
|
*/
|
|
89
94
|
setValue(path, value) {
|
|
95
|
+
// `set` builds every missing segment of the path. That is what makes
|
|
96
|
+
// writing a nested field work, but it also means a write to a path that
|
|
97
|
+
// no longer exists FABRICATES the structure it names. Field paths do go
|
|
98
|
+
// stale — a subscriber keeps the path it was created with, and the node
|
|
99
|
+
// it points at can move or be removed before the subscription is torn
|
|
100
|
+
// down. Writing `undefined` there has nothing to clear, so the only
|
|
101
|
+
// effect would be that fabricated structure: refuse it.
|
|
102
|
+
if (value === undefined && !has(this.values, path)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.finalizeStaleHistoryBurst();
|
|
90
106
|
set(this.values, path, value);
|
|
91
107
|
if (!some(this.filterHistoryKeys, (value) => {
|
|
92
108
|
return path.includes(value);
|
|
93
109
|
})) {
|
|
94
110
|
this.saveToHistory();
|
|
95
111
|
}
|
|
96
|
-
this.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
this.notifySubscriptions(path);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether a write to `writePath` affects a subscriber at `subscriptionPath`.
|
|
116
|
+
* Segment-aware in both directions: a write below the subscription changes
|
|
117
|
+
* the subscribed value's contents; a write at or above it replaces the
|
|
118
|
+
* subscribed value outright. Root subscribers (no path) see every write.
|
|
119
|
+
* @private
|
|
120
|
+
*/
|
|
121
|
+
pathsIntersect(writePath, subscriptionPath) {
|
|
122
|
+
if (!subscriptionPath)
|
|
123
|
+
return true;
|
|
124
|
+
if (writePath === subscriptionPath)
|
|
125
|
+
return true;
|
|
126
|
+
if (writePath.startsWith(subscriptionPath + '.'))
|
|
127
|
+
return true;
|
|
128
|
+
if (subscriptionPath.startsWith(writePath + '.'))
|
|
129
|
+
return true;
|
|
130
|
+
return false;
|
|
104
131
|
}
|
|
105
132
|
/**
|
|
106
133
|
* Subscribes to form value changes.
|
|
@@ -138,7 +165,7 @@ class FormState {
|
|
|
138
165
|
* @returns The value at the specified path or all form values
|
|
139
166
|
*/
|
|
140
167
|
getValue(path) {
|
|
141
|
-
return cloneDeep(path ? get(this.
|
|
168
|
+
return cloneDeep(path ? get(this.values, path) : this.values);
|
|
142
169
|
}
|
|
143
170
|
/**
|
|
144
171
|
* Validates the form using the provided validation schema.
|
|
@@ -157,9 +184,40 @@ class FormState {
|
|
|
157
184
|
throw errors;
|
|
158
185
|
}
|
|
159
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Commits the end state of a coalescing burst that has gone quiet. MUST run
|
|
189
|
+
* before the next mutation lands in `this.values` — afterwards the burst's
|
|
190
|
+
* true end state is gone. Called at the top of `setValue`/`setValues`, and
|
|
191
|
+
* from `prev()` so an undo taken mid-burst leaves the burst redoable.
|
|
192
|
+
* @private
|
|
193
|
+
*/
|
|
194
|
+
finalizeStaleHistoryBurst() {
|
|
195
|
+
if (!this.historyDirty)
|
|
196
|
+
return;
|
|
197
|
+
if (Date.now() - this.lastHistoryWriteAt <= this.historyCoalesceMs)
|
|
198
|
+
return;
|
|
199
|
+
this.history[this.historyIndex] = cloneDeep(this.values);
|
|
200
|
+
this.historyDirty = false;
|
|
201
|
+
}
|
|
160
202
|
saveToHistory() {
|
|
161
203
|
if (this.historyItems === 0)
|
|
162
204
|
return;
|
|
205
|
+
if (this.historyCoalesceMs > 0) {
|
|
206
|
+
this.lastHistoryWriteAt = Date.now();
|
|
207
|
+
// `finalizeStaleHistoryBurst` ran before this write landed, so a
|
|
208
|
+
// still-dirty entry means this write continues the current burst: its
|
|
209
|
+
// end state is captured when the burst finalizes. No clone, no compare.
|
|
210
|
+
if (this.historyDirty)
|
|
211
|
+
return;
|
|
212
|
+
const currentValues = cloneDeep(this.values);
|
|
213
|
+
if (this.history.length > 0 &&
|
|
214
|
+
isEqual(this.history[this.historyIndex], currentValues)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this.pushHistoryEntry(currentValues);
|
|
218
|
+
this.historyDirty = true;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
163
221
|
this.saveCounter++;
|
|
164
222
|
if (this.saveCounter % this.historyItemThrottle !== 0)
|
|
165
223
|
return;
|
|
@@ -168,17 +226,17 @@ class FormState {
|
|
|
168
226
|
if (this.history.length > 0 && diff) {
|
|
169
227
|
return;
|
|
170
228
|
}
|
|
229
|
+
this.pushHistoryEntry(currentValues);
|
|
230
|
+
}
|
|
231
|
+
pushHistoryEntry(currentValues) {
|
|
171
232
|
if (this.historyIndex < this.history.length - 1) {
|
|
172
233
|
this.history = this.history.slice(0, this.historyIndex + 1);
|
|
173
234
|
}
|
|
174
235
|
this.history.push(currentValues);
|
|
175
236
|
if (this.history.length > this.historyItems) {
|
|
176
237
|
this.history = this.history.slice(-this.historyItems);
|
|
177
|
-
this.historyIndex = this.history.length - 1;
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
this.historyIndex = this.history.length - 1;
|
|
181
238
|
}
|
|
239
|
+
this.historyIndex = this.history.length - 1;
|
|
182
240
|
}
|
|
183
241
|
/**
|
|
184
242
|
* Moves to the previous state in the form history (undo operation).
|
|
@@ -186,6 +244,12 @@ class FormState {
|
|
|
186
244
|
* @returns True if the operation was successful, false if no previous state exists
|
|
187
245
|
*/
|
|
188
246
|
prev() {
|
|
247
|
+
// An undo mid-burst first commits the burst's end state, so a redo can
|
|
248
|
+
// return to what the user actually last saw.
|
|
249
|
+
if (this.historyDirty) {
|
|
250
|
+
this.history[this.historyIndex] = cloneDeep(this.values);
|
|
251
|
+
this.historyDirty = false;
|
|
252
|
+
}
|
|
189
253
|
if (!this.canPrev())
|
|
190
254
|
return false;
|
|
191
255
|
this.historyIndex--;
|
|
@@ -224,12 +288,37 @@ class FormState {
|
|
|
224
288
|
canNext() {
|
|
225
289
|
return this.historyItems > 0 && this.historyIndex < this.history.length - 1;
|
|
226
290
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Delivers the current values to subscribers — all of them, or only those
|
|
293
|
+
* whose path intersects `changedPath` when one is given.
|
|
294
|
+
*
|
|
295
|
+
* Cost discipline: the editor holds hundreds of subscriptions on one large
|
|
296
|
+
* document, and this runs on every write. Pathed subscribers get a clone of
|
|
297
|
+
* just their subtree; root subscribers share ONE lazily-created full clone
|
|
298
|
+
* per pass. Subscribers must therefore treat delivered values as read-only.
|
|
299
|
+
* Fresh clones (not `this.values` references) are still required so React
|
|
300
|
+
* state setters see a new identity per delivery.
|
|
301
|
+
* @private
|
|
302
|
+
*/
|
|
303
|
+
notifySubscriptions(changedPath) {
|
|
304
|
+
// Snapshot: callbacks may (un)subscribe or write back into the form
|
|
305
|
+
// mid-pass; iterating the live map would tangle delivery with those
|
|
306
|
+
// mutations.
|
|
307
|
+
const subscribers = Array.from(this.subscriptions.values());
|
|
308
|
+
let fullClone;
|
|
309
|
+
for (const subscription of subscribers) {
|
|
310
|
+
if (changedPath !== undefined &&
|
|
311
|
+
!this.pathsIntersect(changedPath, subscription.path)) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (subscription.path) {
|
|
315
|
+
subscription.cb(cloneDeep(get(this.values, subscription.path)));
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
fullClone ??= cloneDeep(this.values);
|
|
319
|
+
subscription.cb(fullClone);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
233
322
|
}
|
|
234
323
|
notifyHistorySubscriptions() {
|
|
235
324
|
this.formHistorySubscriptions.forEach((callback) => {
|
|
@@ -246,9 +335,9 @@ class FormState {
|
|
|
246
335
|
return () => this.formHistorySubscriptions.delete(id);
|
|
247
336
|
}
|
|
248
337
|
generateListenerId() {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
return
|
|
338
|
+
// Monotonic — timestamp+random ids could collide, silently replacing a
|
|
339
|
+
// live subscription in the Map and orphaning its callback.
|
|
340
|
+
return `listener-${++this.listenerSeq}`;
|
|
252
341
|
}
|
|
253
342
|
}
|
|
254
343
|
export default FormState;
|
package/dist/state/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ref } from 'react';
|
|
2
2
|
import { ObjectSchema, ValidationError } from 'yup';
|
|
3
3
|
import FormState from '../state';
|
|
4
4
|
/**
|
|
@@ -57,12 +57,22 @@ export interface FormProps<T extends object> {
|
|
|
57
57
|
validationSchema?: ObjectSchema<T>;
|
|
58
58
|
/** Callback function called when the form is successfully submitted */
|
|
59
59
|
onSubmit?: (value: T) => void | Promise<void>;
|
|
60
|
-
/**
|
|
61
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Optional ref to access the FormState instance directly. Accepts either a
|
|
62
|
+
* ref object or a callback ref — a callback is the only way for a consumer
|
|
63
|
+
* to observe REMOUNTS of the form (a ref object mutates silently).
|
|
64
|
+
*/
|
|
65
|
+
ref?: Ref<FormState<T> | null>;
|
|
62
66
|
/** Number of history items to keep for undo/redo functionality (0 to disable) */
|
|
63
67
|
historyItems?: number;
|
|
64
68
|
/** Throttle for saving history items (every Nth change) */
|
|
65
69
|
historyItemThrottle?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Coalesce writes closer together than this into one history entry, so a
|
|
72
|
+
* typing or drag burst becomes a single undo step. 0 (default) keeps the
|
|
73
|
+
* counter-throttle behavior.
|
|
74
|
+
*/
|
|
75
|
+
historyCoalesceMs?: number;
|
|
66
76
|
/** Array of field paths to exclude from history tracking */
|
|
67
77
|
filterHistoryKeys?: string[];
|
|
68
78
|
/** Callback function called whenever form values change */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAEpD,OAAO,SAAS,MAAM,UAAU,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,QAAQ;IAC7C,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAC/C,mEAAmE;IACnE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACnB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAClC,+EAA+E;IAC/E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,kEAAkE;IAClE,UAAU,EAAE,OAAO,CAAC;IACpB,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,GAAG,IAAI,CAAC;IAC3D,uDAAuD;IACvD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mDAAmD;IACnD,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;IACzC,yCAAyC;IACzC,aAAa,EAAE,CAAC,CAAC;IACjB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C;;;;OAIG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/B,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC/B"}
|