@victorylabs/params 0.1.0 → 0.3.0
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/{chunk-NUO3GOXV.js → chunk-5UKBDZTP.js} +37 -2
- package/dist/chunk-5UKBDZTP.js.map +1 -0
- package/dist/{chunk-43PUAYQP.js → chunk-DSAHBEAQ.js} +44 -18
- package/dist/chunk-DSAHBEAQ.js.map +1 -0
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/index.cjs +79 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -11
- package/dist/index.d.ts +47 -11
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/integrations/forms-reverse.cjs +71 -17
- package/dist/integrations/forms-reverse.cjs.map +1 -1
- package/dist/integrations/forms-reverse.js +2 -2
- package/dist/integrations/forms.cjs +71 -17
- package/dist/integrations/forms.cjs.map +1 -1
- package/dist/integrations/forms.js +2 -2
- package/dist/{params-store-Cgbtn53j.d.cts → params-store-4Lcb1M_X.d.cts} +29 -1
- package/dist/{params-store-CguA9-yr.d.ts → params-store-f3pmPdw3.d.ts} +29 -1
- package/dist/react.cjs +127 -54
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +42 -4
- package/dist/react.d.ts +42 -4
- package/dist/react.js +38 -20
- package/dist/react.js.map +1 -1
- package/dist/storage/idb.cjs +56 -3
- package/dist/storage/idb.cjs.map +1 -1
- package/dist/storage/idb.d.cts +40 -8
- package/dist/storage/idb.d.ts +40 -8
- package/dist/storage/idb.js +56 -3
- package/dist/storage/idb.js.map +1 -1
- package/dist/storage/url.cjs.map +1 -1
- package/dist/storage/url.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-43PUAYQP.js.map +0 -1
- package/dist/chunk-NUO3GOXV.js.map +0 -1
package/dist/react.cjs
CHANGED
|
@@ -20,14 +20,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/react/index.ts
|
|
21
21
|
var react_exports = {};
|
|
22
22
|
__export(react_exports, {
|
|
23
|
+
useDebouncedValue: () => useDebouncedValue,
|
|
23
24
|
useFieldInput: () => useFieldInput,
|
|
24
25
|
useFieldValue: () => useFieldValue,
|
|
25
26
|
useParams: () => useParams
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(react_exports);
|
|
28
29
|
|
|
30
|
+
// src/react/use-debounced-value.ts
|
|
31
|
+
var import_react = require("react");
|
|
32
|
+
function useDebouncedValue(value, ms) {
|
|
33
|
+
const [debounced, setDebounced] = (0, import_react.useState)(value);
|
|
34
|
+
(0, import_react.useEffect)(() => {
|
|
35
|
+
if (ms <= 0) {
|
|
36
|
+
setDebounced(value);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const id = setTimeout(() => setDebounced(value), ms);
|
|
40
|
+
return () => clearTimeout(id);
|
|
41
|
+
}, [value, ms]);
|
|
42
|
+
return debounced;
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
// src/react/use-field-input.tsx
|
|
30
|
-
var
|
|
46
|
+
var import_react3 = require("react");
|
|
31
47
|
|
|
32
48
|
// src/schema.ts
|
|
33
49
|
function isStandardSchema(spec) {
|
|
@@ -72,7 +88,8 @@ function defaultSerialize(value) {
|
|
|
72
88
|
if (typeof value === "number") return Number.isFinite(value) ? String(value) : "";
|
|
73
89
|
return JSON.stringify(value);
|
|
74
90
|
}
|
|
75
|
-
|
|
91
|
+
var customExtractors = /* @__PURE__ */ new Set();
|
|
92
|
+
var extractZodEnum = (spec) => {
|
|
76
93
|
let current = spec;
|
|
77
94
|
for (let i = 0; i < 8 && current !== null && typeof current === "object"; i++) {
|
|
78
95
|
const def = current._def;
|
|
@@ -90,13 +107,40 @@ function extractEnumValues(spec) {
|
|
|
90
107
|
return void 0;
|
|
91
108
|
}
|
|
92
109
|
return void 0;
|
|
110
|
+
};
|
|
111
|
+
var extractValibotEnum = (spec) => {
|
|
112
|
+
let current = spec;
|
|
113
|
+
for (let i = 0; i < 8 && current !== null && typeof current === "object"; i++) {
|
|
114
|
+
if (current.kind !== "schema" || typeof current.type !== "string") return void 0;
|
|
115
|
+
if (current.type === "picklist" || current.type === "enum") {
|
|
116
|
+
return Array.isArray(current.options) ? current.options : void 0;
|
|
117
|
+
}
|
|
118
|
+
if (current.wrapped) {
|
|
119
|
+
current = current.wrapped;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
return void 0;
|
|
125
|
+
};
|
|
126
|
+
var builtInExtractors = [extractZodEnum, extractValibotEnum];
|
|
127
|
+
function extractEnumValues(spec) {
|
|
128
|
+
for (const extractor of customExtractors) {
|
|
129
|
+
const result = extractor(spec);
|
|
130
|
+
if (result !== void 0) return result;
|
|
131
|
+
}
|
|
132
|
+
for (const extractor of builtInExtractors) {
|
|
133
|
+
const result = extractor(spec);
|
|
134
|
+
if (result !== void 0) return result;
|
|
135
|
+
}
|
|
136
|
+
return void 0;
|
|
93
137
|
}
|
|
94
138
|
|
|
95
139
|
// src/react/use-field-value.ts
|
|
96
|
-
var
|
|
140
|
+
var import_react2 = require("react");
|
|
97
141
|
function useFieldValue(store, path) {
|
|
98
|
-
const [, forceRender] = (0,
|
|
99
|
-
(0,
|
|
142
|
+
const [, forceRender] = (0, import_react2.useReducer)((tick) => tick + 1, 0);
|
|
143
|
+
(0, import_react2.useEffect)(() => store.subscribe(path, forceRender), [store, path]);
|
|
100
144
|
return store.getValue(path);
|
|
101
145
|
}
|
|
102
146
|
|
|
@@ -105,10 +149,10 @@ function useFieldInput(store, path) {
|
|
|
105
149
|
const storeValue = useFieldValue(store, path);
|
|
106
150
|
const config = store.getFieldConfig(path);
|
|
107
151
|
const debounceMs = config?.debounce ?? 0;
|
|
108
|
-
const [shadow, setShadow] = (0,
|
|
109
|
-
const debouncerRef = (0,
|
|
110
|
-
const lastStoreValueRef = (0,
|
|
111
|
-
(0,
|
|
152
|
+
const [shadow, setShadow] = (0, import_react3.useState)(null);
|
|
153
|
+
const debouncerRef = (0, import_react3.useRef)(null);
|
|
154
|
+
const lastStoreValueRef = (0, import_react3.useRef)(storeValue);
|
|
155
|
+
(0, import_react3.useEffect)(() => {
|
|
112
156
|
if (Object.is(lastStoreValueRef.current, storeValue)) return;
|
|
113
157
|
lastStoreValueRef.current = storeValue;
|
|
114
158
|
if (shadow !== null && shadow !== defaultSerialize(storeValue)) {
|
|
@@ -119,19 +163,19 @@ function useFieldInput(store, path) {
|
|
|
119
163
|
if (debounceMs > 0 && debouncerRef.current === null) {
|
|
120
164
|
debouncerRef.current = createDebouncer(store, path, debounceMs, () => setShadow(null));
|
|
121
165
|
}
|
|
122
|
-
const onChange = (0,
|
|
166
|
+
const onChange = (0, import_react3.useCallback)(
|
|
123
167
|
(event) => {
|
|
124
168
|
const next = event.target.value;
|
|
125
169
|
if (debounceMs > 0) {
|
|
126
170
|
setShadow(next);
|
|
127
171
|
debouncerRef.current?.trigger(next);
|
|
128
172
|
} else {
|
|
129
|
-
store.
|
|
173
|
+
store.setField(path, next);
|
|
130
174
|
}
|
|
131
175
|
},
|
|
132
176
|
[store, path, debounceMs]
|
|
133
177
|
);
|
|
134
|
-
const onBlur = (0,
|
|
178
|
+
const onBlur = (0, import_react3.useCallback)(() => {
|
|
135
179
|
debouncerRef.current?.flush();
|
|
136
180
|
}, []);
|
|
137
181
|
return {
|
|
@@ -146,7 +190,7 @@ function createDebouncer(store, path, ms, onCommit) {
|
|
|
146
190
|
let pendingValue = null;
|
|
147
191
|
const commit = () => {
|
|
148
192
|
if (pendingValue !== null) {
|
|
149
|
-
store.
|
|
193
|
+
store.setField(path, pendingValue);
|
|
150
194
|
pendingValue = null;
|
|
151
195
|
onCommit();
|
|
152
196
|
}
|
|
@@ -174,10 +218,10 @@ function createDebouncer(store, path, ms, onCommit) {
|
|
|
174
218
|
}
|
|
175
219
|
|
|
176
220
|
// src/react/use-params.tsx
|
|
177
|
-
var
|
|
221
|
+
var import_react5 = require("react");
|
|
178
222
|
|
|
179
223
|
// src/react/use-shared-store.ts
|
|
180
|
-
var
|
|
224
|
+
var import_react4 = require("react");
|
|
181
225
|
|
|
182
226
|
// src/dev.ts
|
|
183
227
|
var isDev = (() => {
|
|
@@ -457,17 +501,43 @@ var ParamsStore = class {
|
|
|
457
501
|
getFieldConfig(path) {
|
|
458
502
|
return this.fieldConfigs[path];
|
|
459
503
|
}
|
|
460
|
-
|
|
504
|
+
// ─── Writes ───────────────────────────────────────────────────────────
|
|
505
|
+
/**
|
|
506
|
+
* Apply a partial update — write multiple fields at once.
|
|
507
|
+
*
|
|
508
|
+
* `set(partial)` is the canonical write form. The path-and-value form
|
|
509
|
+
* (`set(path, value)` historically) is now `setField(path, value)` —
|
|
510
|
+
* see {@link setField}. The split keeps `set`'s single-signature
|
|
511
|
+
* inference clean for the common `set({ [key]: value })` pattern, which
|
|
512
|
+
* previously required `as Partial<T>` casts because TypeScript couldn't
|
|
513
|
+
* resolve the overload from a generic-keyed object literal.
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* ```ts
|
|
517
|
+
* p.set({ page: 1, sort: 'updated' })
|
|
518
|
+
* p.set({ [key]: value }) // works without a cast now
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
set(partial, options) {
|
|
461
522
|
if (this.disposed) return;
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
523
|
+
this.applyUpdates(partial, options);
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Write a single field by path. Equivalent to `set({ [path]: value })`
|
|
527
|
+
* but skips the object-literal allocation and avoids the inference issue
|
|
528
|
+
* that motivated splitting the API.
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* p.setField('query', 'react')
|
|
533
|
+
* p.setField('filters.tags', ['ts', 'react'])
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
setField(path, value, options) {
|
|
537
|
+
if (this.disposed) return;
|
|
538
|
+
this.applyUpdates({ [path]: value }, options);
|
|
539
|
+
}
|
|
540
|
+
applyUpdates(updates, options) {
|
|
471
541
|
const initialChanges = {};
|
|
472
542
|
for (const [path, v] of Object.entries(updates)) {
|
|
473
543
|
const old = deepGet(this.values, path);
|
|
@@ -499,13 +569,13 @@ var ParamsStore = class {
|
|
|
499
569
|
/** Boolean-flip helper. */
|
|
500
570
|
toggle(path, options) {
|
|
501
571
|
const current = this.getValue(path);
|
|
502
|
-
this.
|
|
572
|
+
this.setField(path, !current, options);
|
|
503
573
|
}
|
|
504
574
|
/** Push a value onto an array field. */
|
|
505
575
|
append(path, value, options) {
|
|
506
576
|
const current = this.getValue(path);
|
|
507
577
|
if (!Array.isArray(current)) return;
|
|
508
|
-
this.
|
|
578
|
+
this.setField(path, [...current, value], options);
|
|
509
579
|
}
|
|
510
580
|
/** Remove the first array element matching `value` by deepEqual. */
|
|
511
581
|
remove(path, value, options) {
|
|
@@ -513,14 +583,14 @@ var ParamsStore = class {
|
|
|
513
583
|
if (!Array.isArray(current)) return;
|
|
514
584
|
const idx = current.findIndex((item) => deepEqual(item, value));
|
|
515
585
|
if (idx === -1) return;
|
|
516
|
-
this.
|
|
586
|
+
this.setField(path, [...current.slice(0, idx), ...current.slice(idx + 1)], options);
|
|
517
587
|
}
|
|
518
588
|
/** Remove the array element at the given index. */
|
|
519
589
|
removeAt(path, index, options) {
|
|
520
590
|
const current = this.getValue(path);
|
|
521
591
|
if (!Array.isArray(current)) return;
|
|
522
592
|
if (index < 0 || index >= current.length) return;
|
|
523
|
-
this.
|
|
593
|
+
this.setField(path, [...current.slice(0, index), ...current.slice(index + 1)], options);
|
|
524
594
|
}
|
|
525
595
|
cycle(path, valuesOrOptions, maybeOptions) {
|
|
526
596
|
let resolved;
|
|
@@ -546,12 +616,12 @@ var ParamsStore = class {
|
|
|
546
616
|
const current = this.getValue(path);
|
|
547
617
|
const idx = resolved.findIndex((o) => deepEqual(o, current));
|
|
548
618
|
const next = idx === -1 ? resolved[0] : resolved[(idx + 1) % resolved.length];
|
|
549
|
-
this.
|
|
619
|
+
this.setField(path, next, setOpts);
|
|
550
620
|
}
|
|
551
621
|
/** Reset a single field to its default. */
|
|
552
622
|
clear(path, options) {
|
|
553
623
|
const def = deepGet(this.defaults, path);
|
|
554
|
-
this.
|
|
624
|
+
this.setField(path, def, options);
|
|
555
625
|
}
|
|
556
626
|
/** Reset all fields to defaults; optional partial overrides + SetOptions. */
|
|
557
627
|
reset(values, options) {
|
|
@@ -805,11 +875,11 @@ function warnOnDuplicateName(def) {
|
|
|
805
875
|
|
|
806
876
|
// src/react/use-shared-store.ts
|
|
807
877
|
function useSharedStore(def) {
|
|
808
|
-
const storeRef = (0,
|
|
878
|
+
const storeRef = (0, import_react4.useRef)(null);
|
|
809
879
|
if (storeRef.current === null) {
|
|
810
880
|
storeRef.current = acquire(def);
|
|
811
881
|
}
|
|
812
|
-
(0,
|
|
882
|
+
(0, import_react4.useEffect)(
|
|
813
883
|
() => () => {
|
|
814
884
|
release(def);
|
|
815
885
|
storeRef.current = null;
|
|
@@ -822,35 +892,33 @@ function useSharedStore(def) {
|
|
|
822
892
|
// src/react/use-params.tsx
|
|
823
893
|
function useParams(def) {
|
|
824
894
|
const store = useSharedStore(def);
|
|
825
|
-
const [, forceRender] = (0,
|
|
826
|
-
(0,
|
|
827
|
-
const set = (0,
|
|
828
|
-
(
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
}
|
|
834
|
-
}),
|
|
895
|
+
const [, forceRender] = (0, import_react5.useReducer)((tick) => tick + 1, 0);
|
|
896
|
+
(0, import_react5.useEffect)(() => store.subscribe("", forceRender), [store]);
|
|
897
|
+
const set = (0, import_react5.useCallback)(
|
|
898
|
+
(partial, options) => store.set(partial, options),
|
|
899
|
+
[store]
|
|
900
|
+
);
|
|
901
|
+
const setField = (0, import_react5.useCallback)(
|
|
902
|
+
(path, value2, options) => store.setField(path, value2, options),
|
|
835
903
|
[store]
|
|
836
904
|
);
|
|
837
|
-
const toggle = (0,
|
|
905
|
+
const toggle = (0, import_react5.useCallback)(
|
|
838
906
|
(path, options) => store.toggle(path, options),
|
|
839
907
|
[store]
|
|
840
908
|
);
|
|
841
|
-
const append = (0,
|
|
909
|
+
const append = (0, import_react5.useCallback)(
|
|
842
910
|
(path, value2, options) => store.append(path, value2, options),
|
|
843
911
|
[store]
|
|
844
912
|
);
|
|
845
|
-
const removeFn = (0,
|
|
913
|
+
const removeFn = (0, import_react5.useCallback)(
|
|
846
914
|
(path, value2, options) => store.remove(path, value2, options),
|
|
847
915
|
[store]
|
|
848
916
|
);
|
|
849
|
-
const removeAt = (0,
|
|
917
|
+
const removeAt = (0, import_react5.useCallback)(
|
|
850
918
|
(path, index, options) => store.removeAt(path, index, options),
|
|
851
919
|
[store]
|
|
852
920
|
);
|
|
853
|
-
const cycle = (0,
|
|
921
|
+
const cycle = (0, import_react5.useCallback)(
|
|
854
922
|
((path, valuesOrOptions, maybeOptions) => {
|
|
855
923
|
if (Array.isArray(valuesOrOptions)) {
|
|
856
924
|
store.cycle(path, valuesOrOptions, maybeOptions);
|
|
@@ -862,32 +930,36 @@ function useParams(def) {
|
|
|
862
930
|
}),
|
|
863
931
|
[store]
|
|
864
932
|
);
|
|
865
|
-
const clear = (0,
|
|
933
|
+
const clear = (0, import_react5.useCallback)(
|
|
866
934
|
(path, options) => store.clear(path, options),
|
|
867
935
|
[store]
|
|
868
936
|
);
|
|
869
|
-
const reset = (0,
|
|
937
|
+
const reset = (0, import_react5.useCallback)(
|
|
870
938
|
(values, options) => store.reset(values, options),
|
|
871
939
|
[store]
|
|
872
940
|
);
|
|
873
|
-
const subscribe = (0,
|
|
941
|
+
const subscribe = (0, import_react5.useCallback)(
|
|
874
942
|
(path, listener) => store.subscribe(path, listener),
|
|
875
943
|
[store]
|
|
876
944
|
);
|
|
877
|
-
const toQuery = (0,
|
|
945
|
+
const toQuery = (0, import_react5.useCallback)(
|
|
878
946
|
(overrides) => store.toQuery(overrides),
|
|
879
947
|
[store]
|
|
880
948
|
);
|
|
881
|
-
const href = (0,
|
|
949
|
+
const href = (0, import_react5.useCallback)((overrides) => store.href(overrides), [store]);
|
|
882
950
|
const value = (path) => useFieldValue(store, path);
|
|
883
|
-
const deferred = (path) => (0,
|
|
951
|
+
const deferred = (path) => (0, import_react5.useDeferredValue)(useFieldValue(store, path));
|
|
884
952
|
const input = (path) => useFieldInput(store, path);
|
|
885
953
|
return {
|
|
954
|
+
// Cast: store.getValues() returns Partial<T> for the storage layer's
|
|
955
|
+
// sake, but every field in ParamsDefinition declares a default so the
|
|
956
|
+
// hydrated view is structurally complete. See ParamsController.values.
|
|
886
957
|
values: store.getValues(),
|
|
887
958
|
value,
|
|
888
959
|
deferred,
|
|
889
960
|
input,
|
|
890
961
|
set,
|
|
962
|
+
setField,
|
|
891
963
|
toggle,
|
|
892
964
|
append,
|
|
893
965
|
remove: removeFn,
|
|
@@ -903,6 +975,7 @@ function useParams(def) {
|
|
|
903
975
|
}
|
|
904
976
|
// Annotate the CommonJS export names for ESM import in node:
|
|
905
977
|
0 && (module.exports = {
|
|
978
|
+
useDebouncedValue,
|
|
906
979
|
useFieldInput,
|
|
907
980
|
useFieldValue,
|
|
908
981
|
useParams
|