vultus-core 0.3.0 → 0.5.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.
Files changed (125) hide show
  1. package/README.md +319 -4
  2. package/dist/ArgStoreContext.d.ts +10 -0
  3. package/dist/ArgStoreContext.d.ts.map +1 -0
  4. package/dist/ArgStoreContext.js +15 -0
  5. package/dist/ArgStoreContext.js.map +1 -0
  6. package/dist/Components.d.ts +30 -0
  7. package/dist/Components.d.ts.map +1 -0
  8. package/dist/Components.js +28 -0
  9. package/dist/Components.js.map +1 -0
  10. package/dist/FieldContext.d.ts +38 -0
  11. package/dist/FieldContext.d.ts.map +1 -0
  12. package/dist/FieldContext.js +82 -0
  13. package/dist/FieldContext.js.map +1 -0
  14. package/dist/argStore.d.ts +26 -0
  15. package/dist/argStore.d.ts.map +1 -0
  16. package/dist/argStore.js +27 -0
  17. package/dist/argStore.js.map +1 -0
  18. package/dist/choices.d.ts +43 -0
  19. package/dist/choices.d.ts.map +1 -0
  20. package/dist/choices.js +20 -0
  21. package/dist/choices.js.map +1 -0
  22. package/dist/field.d.ts +42 -15
  23. package/dist/field.d.ts.map +1 -1
  24. package/dist/field.js +20 -7
  25. package/dist/field.js.map +1 -1
  26. package/dist/index.d.ts +22 -4
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +21 -3
  29. package/dist/index.js.map +1 -1
  30. package/dist/kinds.d.ts +51 -0
  31. package/dist/kinds.d.ts.map +1 -0
  32. package/dist/kinds.js +143 -0
  33. package/dist/kinds.js.map +1 -0
  34. package/dist/localStorageStore.d.ts +16 -0
  35. package/dist/localStorageStore.d.ts.map +1 -0
  36. package/dist/localStorageStore.js +72 -0
  37. package/dist/localStorageStore.js.map +1 -0
  38. package/dist/normalizeText.d.ts +6 -0
  39. package/dist/normalizeText.d.ts.map +1 -0
  40. package/dist/normalizeText.js +8 -0
  41. package/dist/normalizeText.js.map +1 -0
  42. package/dist/numeric.d.ts +38 -0
  43. package/dist/numeric.d.ts.map +1 -0
  44. package/dist/numeric.js +43 -0
  45. package/dist/numeric.js.map +1 -0
  46. package/dist/resolve.d.ts +13 -0
  47. package/dist/resolve.d.ts.map +1 -1
  48. package/dist/resolve.js +25 -0
  49. package/dist/resolve.js.map +1 -1
  50. package/dist/tree.d.ts +69 -0
  51. package/dist/tree.d.ts.map +1 -0
  52. package/dist/tree.js +151 -0
  53. package/dist/tree.js.map +1 -0
  54. package/dist/types.d.ts +15 -7
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/useArg.d.ts +45 -0
  57. package/dist/useArg.d.ts.map +1 -0
  58. package/dist/useArg.js +83 -0
  59. package/dist/useArg.js.map +1 -0
  60. package/dist/useBoolField.d.ts +8 -3
  61. package/dist/useBoolField.d.ts.map +1 -1
  62. package/dist/useBoolField.js +9 -1
  63. package/dist/useBoolField.js.map +1 -1
  64. package/dist/useManyOfField.d.ts +35 -0
  65. package/dist/useManyOfField.d.ts.map +1 -0
  66. package/dist/useManyOfField.js +74 -0
  67. package/dist/useManyOfField.js.map +1 -0
  68. package/dist/useMixedBoolField.d.ts +8 -3
  69. package/dist/useMixedBoolField.d.ts.map +1 -1
  70. package/dist/useMixedBoolField.js +9 -1
  71. package/dist/useMixedBoolField.js.map +1 -1
  72. package/dist/useNumericField.d.ts +25 -0
  73. package/dist/useNumericField.d.ts.map +1 -0
  74. package/dist/useNumericField.js +52 -0
  75. package/dist/useNumericField.js.map +1 -0
  76. package/dist/useOneOfField.d.ts +18 -34
  77. package/dist/useOneOfField.d.ts.map +1 -1
  78. package/dist/useOneOfField.js +18 -18
  79. package/dist/useOneOfField.js.map +1 -1
  80. package/dist/useRangeField.d.ts +34 -0
  81. package/dist/useRangeField.d.ts.map +1 -0
  82. package/dist/useRangeField.js +63 -0
  83. package/dist/useRangeField.js.map +1 -0
  84. package/dist/useStoredField.d.ts +61 -0
  85. package/dist/useStoredField.d.ts.map +1 -0
  86. package/dist/useStoredField.js +151 -0
  87. package/dist/useStoredField.js.map +1 -0
  88. package/dist/useTextField.d.ts +22 -0
  89. package/dist/useTextField.d.ts.map +1 -0
  90. package/dist/useTextField.js +21 -0
  91. package/dist/useTextField.js.map +1 -0
  92. package/dist/useTreeField.d.ts +39 -0
  93. package/dist/useTreeField.d.ts.map +1 -0
  94. package/dist/useTreeField.js +66 -0
  95. package/dist/useTreeField.js.map +1 -0
  96. package/dist/valueTypes.d.ts +28 -0
  97. package/dist/valueTypes.d.ts.map +1 -0
  98. package/dist/valueTypes.js +65 -0
  99. package/dist/valueTypes.js.map +1 -0
  100. package/package.json +1 -1
  101. package/src/ArgStoreContext.tsx +16 -0
  102. package/src/Components.tsx +47 -0
  103. package/src/FieldContext.tsx +98 -0
  104. package/src/argStore.ts +49 -0
  105. package/src/choices.ts +62 -0
  106. package/src/field.ts +64 -25
  107. package/src/index.ts +54 -4
  108. package/src/kinds.ts +197 -0
  109. package/src/localStorageStore.ts +68 -0
  110. package/src/normalizeText.ts +7 -0
  111. package/src/numeric.ts +68 -0
  112. package/src/resolve.ts +23 -0
  113. package/src/tree.ts +175 -0
  114. package/src/types.ts +28 -7
  115. package/src/useArg.ts +121 -0
  116. package/src/useBoolField.ts +19 -6
  117. package/src/useManyOfField.ts +107 -0
  118. package/src/useMixedBoolField.ts +19 -6
  119. package/src/useNumericField.ts +69 -0
  120. package/src/useOneOfField.ts +38 -58
  121. package/src/useRangeField.ts +86 -0
  122. package/src/useStoredField.ts +205 -0
  123. package/src/useTextField.ts +39 -0
  124. package/src/useTreeField.ts +108 -0
  125. package/src/valueTypes.ts +77 -0
package/dist/useArg.js ADDED
@@ -0,0 +1,83 @@
1
+ import { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';
2
+ import { useArgStore } from './ArgStoreContext.js';
3
+ import { useFieldContext } from './FieldContext.js';
4
+ import { resolveIn } from './resolve.js';
5
+ /** The raw value a write needs for `value`: `undefined` (removes the key) when it equals the default, else its formatted form. */
6
+ function rawFor(value, defaultValue, valueType) {
7
+ return valueType.isEqual(value, defaultValue) ? undefined : valueType.format(value);
8
+ }
9
+ /**
10
+ * An argument read from and written to the nearest ArgStore. An absent key reads as the default;
11
+ * writing the default removes the key.
12
+ *
13
+ * `parse(raw)` is memoized on `[raw, key, valueType]` (not the default, which may be a context
14
+ * function with its own, independently changing inputs): re-rendering with the same raw value
15
+ * does not re-parse and does not re-warn; a raw value that does not parse warns once per such
16
+ * change and the default is used instead. `value` itself then keeps its previous identity
17
+ * whenever it is still `isEqual` to the freshly computed one (parsed-or-default), so a default
18
+ * that builds a fresh value every render (`() => []`) does not change `value`'s identity either —
19
+ * effects keyed on `value` do not re-run just because nothing meaningful changed.
20
+ */
21
+ export function useArg(definition) {
22
+ const { key, valueType, default: defaultOrFn } = definition;
23
+ const store = useArgStore();
24
+ const ctx = useFieldContext();
25
+ // Called on the store, not passed detached: a store written as a class uses `this`.
26
+ const subscribe = useCallback((listener) => store.subscribe(listener), [store]);
27
+ const read = useCallback(() => store.read(key), [store, key]);
28
+ const raw = useSyncExternalStore(subscribe, read);
29
+ const defaultValue = resolveIn(defaultOrFn, undefined, ctx, `Argument '${key}': option 'default'`);
30
+ const parsed = useMemo(() => {
31
+ if (raw === undefined)
32
+ return undefined;
33
+ const p = valueType.parse(raw);
34
+ if (p === undefined)
35
+ console.warn(`Argument '${key}': cannot read '${raw}', using the default`);
36
+ return p;
37
+ // eslint-disable-next-line react-hooks/exhaustive-deps
38
+ }, [raw, key, valueType]);
39
+ const candidate = parsed ?? defaultValue;
40
+ const previousRef = useRef(undefined);
41
+ const value = previousRef.current !== undefined && valueType.isEqual(previousRef.current.value, candidate)
42
+ ? previousRef.current.value
43
+ : candidate;
44
+ previousRef.current = { value };
45
+ const set = useCallback((next, method = 'replace') => {
46
+ store.write([{ key, raw: rawFor(next, defaultValue, valueType) }], method);
47
+ }, [store, key, valueType, defaultValue]);
48
+ const reset = useCallback((method = 'replace') => {
49
+ store.write([{ key, raw: undefined }], method);
50
+ }, [store, key]);
51
+ const hrefFor = useCallback((next) => {
52
+ if (!store.hrefFor)
53
+ return undefined;
54
+ return store.hrefFor([{ key, raw: rawFor(next, defaultValue, valueType) }]);
55
+ }, [store, key, valueType, defaultValue]);
56
+ return { value, isDefault: valueType.isEqual(value, defaultValue), set, reset, hrefFor };
57
+ }
58
+ export function setArg(definition, value) {
59
+ return { definition, value };
60
+ }
61
+ export function resetArg(definition) {
62
+ return { definition, reset: true };
63
+ }
64
+ /**
65
+ * Applies several argument changes as one store write (one history entry: "clear all", a chip
66
+ * that also closes a task). Each change's default is resolved at call time, from the field
67
+ * context captured when this hook rendered.
68
+ */
69
+ export function useArgWriter() {
70
+ const store = useArgStore();
71
+ const ctx = useFieldContext();
72
+ return useCallback((changes, method = 'replace') => {
73
+ const rawChanges = changes.map((change) => {
74
+ const { key, valueType, default: defaultOrFn } = change.definition;
75
+ if (change.reset)
76
+ return { key, raw: undefined };
77
+ const defaultValue = resolveIn(defaultOrFn, undefined, ctx, `Argument '${key}': option 'default'`);
78
+ return { key, raw: rawFor(change.value, defaultValue, valueType) };
79
+ });
80
+ store.write(rawChanges, method);
81
+ }, [store, ctx]);
82
+ }
83
+ //# sourceMappingURL=useArg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useArg.js","sourceRoot":"","sources":["../src/useArg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAoBzC,kIAAkI;AAClI,SAAS,MAAM,CAAI,KAAQ,EAAE,YAAe,EAAE,SAAuB;IACnE,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,MAAM,CAAI,UAA4B;IACpD,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC;IAC5D,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,oFAAoF;IACpF,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,QAAoB,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,oBAAoB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,SAAS,CAAI,WAAW,EAAE,SAAc,EAAE,GAAG,EAAE,aAAa,GAAG,qBAAqB,CAAC,CAAC;IAE3G,MAAM,MAAM,GAAG,OAAO,CAAgB,GAAG,EAAE;QACzC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACxC,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,GAAG,mBAAmB,GAAG,sBAAsB,CAAC,CAAC;QAChG,OAAO,CAAC,CAAC;QACT,uDAAuD;IACzD,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1B,MAAM,SAAS,GAAG,MAAM,IAAI,YAAY,CAAC;IAEzC,MAAM,WAAW,GAAG,MAAM,CAA2B,SAAS,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,KAAK,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC;QACxG,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK;QAC3B,CAAC,CAAC,SAAS,CAAC;IACd,WAAW,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC;IAEhC,MAAM,GAAG,GAAG,WAAW,CACrB,CAAC,IAAO,EAAE,SAAuB,SAAS,EAAE,EAAE;QAC5C,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC,EACD,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,CAAC,CACtC,CAAC;IACF,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,SAAuB,SAAS,EAAE,EAAE;QACnC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC,EACD,CAAC,KAAK,EAAE,GAAG,CAAC,CACb,CAAC;IACF,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,IAAO,EAAsB,EAAE;QAC9B,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QACrC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC,EACD,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,CAAC,CACtC,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC3F,CAAC;AAKD,MAAM,UAAU,MAAM,CAAI,UAA4B,EAAE,KAAQ;IAC9D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAA8B;IACrD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,OAAO,WAAW,CAChB,CAAC,OAAoB,EAAE,SAAuB,SAAS,EAAE,EAAE;QACzD,MAAM,UAAU,GAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACrD,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;YACnE,IAAI,MAAM,CAAC,KAAK;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;YACjD,MAAM,YAAY,GAAG,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,qBAAqB,CAAC,CAAC;YACnG,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;QACrE,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC,EACD,CAAC,KAAK,EAAE,GAAG,CAAC,CACb,CAAC;AACJ,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { type FieldControls, type FieldOptions } from './field.js';
2
- import type { ErrorRoutesRegistry } from './types.js';
3
- export type BoolFieldOptions<RouteId extends string = string> = FieldOptions<boolean, boolean, RouteId>;
2
+ import { type FieldCtx } from './FieldContext.js';
3
+ import type { ErrorRoutesRegistry, ValueOrFn } from './types.js';
4
+ export type BoolFieldOptions<RouteId extends string = string, Ctx = any> = FieldOptions<boolean, boolean, RouteId, Ctx>;
4
5
  export interface BoolFieldControls extends FieldControls<boolean, boolean> {
5
6
  /**
6
7
  * Request the opposite value. Programmatic use; widgets obtain the field's
@@ -8,10 +9,14 @@ export interface BoolFieldControls extends FieldControls<boolean, boolean> {
8
9
  */
9
10
  toggle(): void;
10
11
  }
12
+ /** The implicit initial value for a boolean field: `initialValue` resolved, else false. */
13
+ export declare function boolInitialValue(opts: {
14
+ initialValue?: ValueOrFn<boolean>;
15
+ }, ctx: FieldCtx, id: string): boolean;
11
16
  /**
12
17
  * A boolean field (moxb's Bool, the sidedao boolean field). Rendered by
13
18
  * vultus-antd's BoolCheckbox and BoolSwitch, which take the same controls.
14
19
  * Inside the field the value starts at `initialValue` (default false).
15
20
  */
16
- export declare function useBoolField<RouteId extends string = string>(opts: BoolFieldOptions<RouteId>, registry?: ErrorRoutesRegistry<RouteId>): BoolFieldControls;
21
+ export declare function useBoolField<RouteId extends string = string, Ctx = any>(opts: BoolFieldOptions<RouteId, Ctx>, registry?: ErrorRoutesRegistry<RouteId>): BoolFieldControls;
17
22
  //# sourceMappingURL=useBoolField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBoolField.d.ts","sourceRoot":"","sources":["../src/useBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAExG,MAAM,WAAW,iBAAkB,SAAQ,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;IACxE;;;OAGG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAC1D,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAC/B,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,iBAAiB,CAQnB"}
1
+ {"version":3,"file":"useBoolField.d.ts","sourceRoot":"","sources":["../src/useBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAExH,MAAM,WAAW,iBAAkB,SAAQ,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;IACxE;;;OAGG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAAE,EAC3C,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,MAAM,GACT,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,EACrE,IAAI,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,EACpC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,iBAAiB,CAUnB"}
@@ -1,12 +1,20 @@
1
1
  import { useFieldCore } from './field.js';
2
+ import { useFieldContext } from './FieldContext.js';
3
+ import { resolveIn } from './resolve.js';
4
+ /** The implicit initial value for a boolean field: `initialValue` resolved, else false. */
5
+ export function boolInitialValue(opts, ctx, id) {
6
+ return resolveIn(opts.initialValue, false, ctx, `Field '${id}': option 'initialValue'`);
7
+ }
2
8
  /**
3
9
  * A boolean field (moxb's Bool, the sidedao boolean field). Rendered by
4
10
  * vultus-antd's BoolCheckbox and BoolSwitch, which take the same controls.
5
11
  * Inside the field the value starts at `initialValue` (default false).
6
12
  */
7
13
  export function useBoolField(opts, registry) {
14
+ const ctx = useFieldContext();
8
15
  const inside = !opts.onChange && !opts.commit;
9
- const field = useFieldCore('boolean', inside ? { ...opts, initialValue: opts.initialValue ?? false } : opts, registry);
16
+ const initialValue = () => boolInitialValue(opts, ctx, opts.id);
17
+ const field = useFieldCore('boolean', inside ? { ...opts, initialValue } : opts, registry);
10
18
  return { ...field, toggle: () => field.setValue(!field.value) };
11
19
  }
12
20
  //# sourceMappingURL=useBoolField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBoolField.js","sourceRoot":"","sources":["../src/useBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AAajF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,IAA+B,EAC/B,QAAuC;IAEvC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,YAAY,CACxB,SAAS,EACT,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EACrE,QAAQ,CACT,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"useBoolField.js","sourceRoot":"","sources":["../src/useBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAC9B,IAA2C,EAC3C,GAAa,EACb,EAAU;IAEV,OAAO,SAAS,CAAU,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;AACnG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAoC,EACpC,QAAuC;IAEvC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,YAAY,CACxB,SAAS,EACT,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EACzC,QAAQ,CACT,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AAClE,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { type FieldControls, type FieldOptions } from './field.js';
2
+ import { type OneOfChoice, type OneOfChoiceControls } from './choices.js';
3
+ import { type FieldCtx } from './FieldContext.js';
4
+ import type { ErrorRoutesRegistry, ValueOrFn } from './types.js';
5
+ export type ManyOfOwnOptions<T extends string = string, Ctx = any> = {
6
+ /** The choices, in order; static or derived (a function, of the field context if it declares a parameter). */
7
+ choices: ValueOrFn<OneOfChoice<T>[], Ctx>;
8
+ };
9
+ export type ManyOfFieldOptions<T extends string = string, RouteId extends string = string, Ctx = any> = FieldOptions<T[], T[], RouteId, Ctx> & ManyOfOwnOptions<T, Ctx>;
10
+ export interface ManyOfChoiceControls<T extends string = string> extends OneOfChoiceControls<T> {
11
+ selected: boolean;
12
+ }
13
+ export interface ManyOfFieldControls<T extends string = string> extends FieldControls<T[], T[]> {
14
+ choices: ManyOfChoiceControls<T>[];
15
+ isSelected(value: T): boolean;
16
+ /** Flips a choice's membership in the value; ignored (with a warning) for an unknown or disabled choice. */
17
+ toggle(value: T): void;
18
+ }
19
+ /** The implicit initial value for a many-of field: `initialValue` resolved, else the empty list. */
20
+ export declare function manyOfInitialValue<T extends string>(opts: {
21
+ initialValue?: ValueOrFn<T[]>;
22
+ }, ctx: FieldCtx, id: string): T[];
23
+ /**
24
+ * A field whose value is a set of choices (moxb's ManyOf). A request (to
25
+ * `setValue` or `toggle`) is normalized to the known choices in their order,
26
+ * without duplicates, followed by the values the field already holds that are
27
+ * no longer among the choices and that the request keeps (in their current
28
+ * order: `toggle` keeps them, so a stored value naming a choice that was
29
+ * removed is not silently dropped, while `setValue([])` clears it). A request
30
+ * naming a value that is neither a choice nor already held, or that changes a
31
+ * disabled choice's membership, is ignored with a warning — as useOneOfField
32
+ * refuses a disabled or unknown choice.
33
+ */
34
+ export declare function useManyOfField<T extends string = string, RouteId extends string = string, Ctx = any>(opts: ManyOfFieldOptions<T, RouteId, Ctx>, registry?: ErrorRoutesRegistry<RouteId>): ManyOfFieldControls<T>;
35
+ //# sourceMappingURL=useManyOfField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useManyOfField.d.ts","sourceRoot":"","sources":["../src/useManyOfField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI;IACnE,8GAA8G;IAC9G,OAAO,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IAClG,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAElE,MAAM,WAAW,oBAAoB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IAC7F,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC7F,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,UAAU,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;IAC9B,4GAA4G;IAC5G,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACxB;AAED,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EACjD,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAA;CAAE,EACvC,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,MAAM,GACT,CAAC,EAAE,CAEL;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,EAClG,IAAI,EAAE,kBAAkB,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EACzC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,mBAAmB,CAAC,CAAC,CAAC,CA0DxB"}
@@ -0,0 +1,74 @@
1
+ import { useFieldCore } from './field.js';
2
+ import { resolveChoice } from './choices.js';
3
+ import { useFieldContext } from './FieldContext.js';
4
+ import { resolveIn } from './resolve.js';
5
+ /** The implicit initial value for a many-of field: `initialValue` resolved, else the empty list. */
6
+ export function manyOfInitialValue(opts, ctx, id) {
7
+ return resolveIn(opts.initialValue, [], ctx, `Field '${id}': option 'initialValue'`);
8
+ }
9
+ /**
10
+ * A field whose value is a set of choices (moxb's ManyOf). A request (to
11
+ * `setValue` or `toggle`) is normalized to the known choices in their order,
12
+ * without duplicates, followed by the values the field already holds that are
13
+ * no longer among the choices and that the request keeps (in their current
14
+ * order: `toggle` keeps them, so a stored value naming a choice that was
15
+ * removed is not silently dropped, while `setValue([])` clears it). A request
16
+ * naming a value that is neither a choice nor already held, or that changes a
17
+ * disabled choice's membership, is ignored with a warning — as useOneOfField
18
+ * refuses a disabled or unknown choice.
19
+ */
20
+ export function useManyOfField(opts, registry) {
21
+ const ctx = useFieldContext();
22
+ const resolvedChoices = resolveIn(opts.choices, [], ctx, `Field '${opts.id}': option 'choices'`)
23
+ .map((c) => resolveChoice(opts.id, c));
24
+ const byValue = new Map(resolvedChoices.map((c) => [c.value, c]));
25
+ const choiceOrder = resolvedChoices.map((c) => c.value);
26
+ const inside = !opts.onChange && !opts.commit;
27
+ const initialValue = () => manyOfInitialValue(opts, ctx, opts.id);
28
+ const field = useFieldCore('manyOf', inside ? { ...opts, initialValue } : opts, registry);
29
+ /** The normalized list a request becomes, or undefined when the request is refused (with a warning already issued). */
30
+ const normalize = (request, current) => {
31
+ const requestSet = new Set(request);
32
+ const currentSet = new Set(current);
33
+ const heldUnknown = current.filter((v) => !byValue.has(v));
34
+ const heldUnknownSet = new Set(heldUnknown);
35
+ for (const v of request) {
36
+ if (!byValue.has(v) && !heldUnknownSet.has(v)) {
37
+ console.warn(`Field '${opts.id}': '${v}' is not one of its choices`);
38
+ return undefined;
39
+ }
40
+ }
41
+ for (const choice of resolvedChoices) {
42
+ if (choice.enabled)
43
+ continue;
44
+ if (currentSet.has(choice.value) !== requestSet.has(choice.value)) {
45
+ console.warn(`Field '${opts.id}': choice '${choice.value}' is disabled — ${choice.whyDisabled ?? '(no reason)'}`);
46
+ return undefined;
47
+ }
48
+ }
49
+ return [...choiceOrder.filter((v) => requestSet.has(v)), ...heldUnknown.filter((v) => requestSet.has(v))];
50
+ };
51
+ const setValue = (next) => {
52
+ const normalized = normalize(next, field.value);
53
+ if (normalized === undefined)
54
+ return;
55
+ field.setValue(normalized);
56
+ };
57
+ const isSelected = (value) => field.value.includes(value);
58
+ const toggle = (value) => {
59
+ const choice = byValue.get(value);
60
+ if (!choice) {
61
+ console.warn(`Field '${opts.id}': '${value}' is not one of its choices`);
62
+ return;
63
+ }
64
+ if (!choice.enabled) {
65
+ console.warn(`Field '${opts.id}': choice '${value}' is disabled — ${choice.whyDisabled ?? '(no reason)'}`);
66
+ return;
67
+ }
68
+ const current = field.value;
69
+ setValue(current.includes(value) ? current.filter((v) => v !== value) : [...current, value]);
70
+ };
71
+ const choices = resolvedChoices.map((c) => ({ ...c, selected: field.value.includes(c.value) }));
72
+ return { ...field, setValue, choices, isSelected, toggle };
73
+ }
74
+ //# sourceMappingURL=useManyOfField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useManyOfField.js","sourceRoot":"","sources":["../src/useManyOfField.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,17 @@
1
1
  import { type FieldControls, type FieldOptions } from './field.js';
2
- import type { ErrorRoutesRegistry } from './types.js';
2
+ import { type FieldCtx } from './FieldContext.js';
3
+ import type { ErrorRoutesRegistry, ValueOrFn } from './types.js';
3
4
  /** What a mixed boolean field shows: on, off, or some of its items on and some off. */
4
5
  export type MixedBool = boolean | 'mixed';
5
- export type MixedBoolFieldOptions<RouteId extends string = string> = FieldOptions<MixedBool, boolean, RouteId>;
6
+ export type MixedBoolFieldOptions<RouteId extends string = string, Ctx = any> = FieldOptions<MixedBool, boolean, RouteId, Ctx>;
6
7
  export interface MixedBoolFieldControls extends FieldControls<MixedBool, boolean> {
7
8
  /** Request the opposite: off when on, on when off or mixed. Programmatic use, as in BoolFieldControls. */
8
9
  toggle(): void;
9
10
  }
11
+ /** The implicit initial value for a mixed-boolean field: `initialValue` resolved, else false. */
12
+ export declare function mixedBoolInitialValue(opts: {
13
+ initialValue?: ValueOrFn<MixedBool>;
14
+ }, ctx: FieldCtx, id: string): MixedBool;
10
15
  /**
11
16
  * A boolean field over an aggregate (moxb's indeterminate Bool, ARIA's
12
17
  * "mixed"): it shows true, false or 'mixed', and can be asked for true or
@@ -14,7 +19,7 @@ export interface MixedBoolFieldControls extends FieldControls<MixedBool, boolean
14
19
  * its knob in the middle, BoolCheckbox is indeterminate. Derive the value with
15
20
  * `aggregateBool`; with no items at all, disable the field with a reason.
16
21
  */
17
- export declare function useMixedBoolField<RouteId extends string = string>(opts: MixedBoolFieldOptions<RouteId>, registry?: ErrorRoutesRegistry<RouteId>): MixedBoolFieldControls;
22
+ export declare function useMixedBoolField<RouteId extends string = string, Ctx = any>(opts: MixedBoolFieldOptions<RouteId, Ctx>, registry?: ErrorRoutesRegistry<RouteId>): MixedBoolFieldControls;
18
23
  /**
19
24
  * The aggregate of several booleans: true when all are on, false when none is,
20
25
  * 'mixed' otherwise; `undefined` when there are none (a case for disabling the
@@ -1 +1 @@
1
- {"version":3,"file":"useMixedBoolField.d.ts","sourceRoot":"","sources":["../src/useMixedBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,IAAI,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAE/G,MAAM,WAAW,sBAAuB,SAAQ,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC;IAC/E,0GAA0G;IAC1G,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/D,IAAI,EAAE,qBAAqB,CAAC,OAAO,CAAC,EACpC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,sBAAsB,CAQxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GAAG,SAAS,CAI/E"}
1
+ {"version":3,"file":"useMixedBoolField.d.ts","sourceRoot":"","sources":["../src/useMixedBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjE,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI,YAAY,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAE/H,MAAM,WAAW,sBAAuB,SAAQ,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC;IAC/E,0GAA0G;IAC1G,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,iGAAiG;AACjG,wBAAgB,qBAAqB,CACnC,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,EAC7C,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,MAAM,GACT,SAAS,CAEX;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1E,IAAI,EAAE,qBAAqB,CAAC,OAAO,EAAE,GAAG,CAAC,EACzC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,sBAAsB,CAUxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GAAG,SAAS,CAI/E"}
@@ -1,4 +1,10 @@
1
1
  import { useFieldCore } from './field.js';
2
+ import { useFieldContext } from './FieldContext.js';
3
+ import { resolveIn } from './resolve.js';
4
+ /** The implicit initial value for a mixed-boolean field: `initialValue` resolved, else false. */
5
+ export function mixedBoolInitialValue(opts, ctx, id) {
6
+ return resolveIn(opts.initialValue, false, ctx, `Field '${id}': option 'initialValue'`);
7
+ }
2
8
  /**
3
9
  * A boolean field over an aggregate (moxb's indeterminate Bool, ARIA's
4
10
  * "mixed"): it shows true, false or 'mixed', and can be asked for true or
@@ -7,8 +13,10 @@ import { useFieldCore } from './field.js';
7
13
  * `aggregateBool`; with no items at all, disable the field with a reason.
8
14
  */
9
15
  export function useMixedBoolField(opts, registry) {
16
+ const ctx = useFieldContext();
10
17
  const inside = !opts.onChange && !opts.commit;
11
- const field = useFieldCore('mixed-boolean', inside ? { ...opts, initialValue: opts.initialValue ?? false } : opts, registry);
18
+ const initialValue = () => mixedBoolInitialValue(opts, ctx, opts.id);
19
+ const field = useFieldCore('mixed-boolean', inside ? { ...opts, initialValue } : opts, registry);
12
20
  return { ...field, toggle: () => field.setValue(field.value !== true) };
13
21
  }
14
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useMixedBoolField.js","sourceRoot":"","sources":["../src/useMixedBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AAajF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAoC,EACpC,QAAuC;IAEvC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,YAAY,CACxB,eAAe,EACf,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EACrE,QAAQ,CACT,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAA0B;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"useMixedBoolField.js","sourceRoot":"","sources":["../src/useMixedBoolField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC,iGAAiG;AACjG,MAAM,UAAU,qBAAqB,CACnC,IAA6C,EAC7C,GAAa,EACb,EAAU;IAEV,OAAO,SAAS,CAAY,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;AACrG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAyC,EACzC,QAAuC;IAEvC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,YAAY,CACxB,eAAe,EACf,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EACzC,QAAQ,CACT,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAA0B;IACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type FieldControls, type FieldOptions } from './field.js';
2
+ import { type FieldCtx } from './FieldContext.js';
3
+ import { type NumericBounds, type ResolvedNumeric } from './numeric.js';
4
+ import type { ErrorRoutesRegistry } from './types.js';
5
+ export type NumericOwnOptions<Ctx = any> = NumericBounds<Ctx>;
6
+ export type NumericFieldOptions<RouteId extends string = string, Ctx = any> = FieldOptions<number, number, RouteId, Ctx> & NumericOwnOptions<Ctx>;
7
+ export interface NumericFieldControls extends FieldControls<number, number>, ResolvedNumeric {
8
+ /** The value, formatted (default: the number and the unit; `format` overrides it). */
9
+ valueText: string;
10
+ }
11
+ /**
12
+ * The implicit initial value for a numeric field: `initialValue` resolved, else `min` (or 0),
13
+ * clamped into the bounds. Only those options are resolved, not `format`, so a `format` of the
14
+ * field context needs no provider here.
15
+ */
16
+ export declare function numericInitialValue(opts: NumericFieldOptions, ctx: FieldCtx, id: string): number;
17
+ /**
18
+ * A field whose value is a single number (moxb's Numeric). The shown value is always clamped
19
+ * into the bounds, then rounded when `integer`, since a value from outside (a stored or
20
+ * passed-in one) may fall outside them or be fractional even when every request this hook makes
21
+ * fits. A request is clamped and rounded the same way; a non-finite request (e.g. a widget
22
+ * parsing `''`) is refused with a warning, as a disabled field refuses any request.
23
+ */
24
+ export declare function useNumericField<RouteId extends string = string, Ctx = any>(opts: NumericFieldOptions<RouteId, Ctx>, registry?: ErrorRoutesRegistry<RouteId>): NumericFieldControls;
25
+ //# sourceMappingURL=useNumericField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNumericField.d.ts","sourceRoot":"","sources":["../src/useNumericField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAyB,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,iBAAiB,CAAC,GAAG,GAAG,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;AAE9D,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IACxE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAEtE,MAAM,WAAW,oBAAqB,SAAQ,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe;IAC1F,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,EACxE,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,EACvC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,oBAAoB,CA6BtB"}
@@ -0,0 +1,52 @@
1
+ import { useFieldCore } from './field.js';
2
+ import { useFieldContext } from './FieldContext.js';
3
+ import { resolveIn } from './resolve.js';
4
+ import { clamp, resolveNumeric } from './numeric.js';
5
+ /**
6
+ * The implicit initial value for a numeric field: `initialValue` resolved, else `min` (or 0),
7
+ * clamped into the bounds. Only those options are resolved, not `format`, so a `format` of the
8
+ * field context needs no provider here.
9
+ */
10
+ export function numericInitialValue(opts, ctx, id) {
11
+ const resolved = resolveIn(opts.initialValue, undefined, ctx, `Field '${id}': option 'initialValue'`);
12
+ if (resolved !== undefined)
13
+ return resolved;
14
+ const min = resolveIn(opts.min, undefined, ctx, `Field '${id}': option 'min'`);
15
+ const max = resolveIn(opts.max, undefined, ctx, `Field '${id}': option 'max'`);
16
+ return clamp(min ?? 0, min, max);
17
+ }
18
+ /**
19
+ * A field whose value is a single number (moxb's Numeric). The shown value is always clamped
20
+ * into the bounds, then rounded when `integer`, since a value from outside (a stored or
21
+ * passed-in one) may fall outside them or be fractional even when every request this hook makes
22
+ * fits. A request is clamped and rounded the same way; a non-finite request (e.g. a widget
23
+ * parsing `''`) is refused with a warning, as a disabled field refuses any request.
24
+ */
25
+ export function useNumericField(opts, registry) {
26
+ const ctx = useFieldContext();
27
+ const resolved = resolveNumeric(opts.id, opts, ctx);
28
+ const inside = !opts.onChange && !opts.commit;
29
+ const initialValue = () => numericInitialValue(opts, ctx, opts.id);
30
+ const field = useFieldCore('numeric', inside ? { ...opts, initialValue } : opts, registry);
31
+ /** A number clamped into the bounds, then rounded when `integer`. */
32
+ const fit = (n) => {
33
+ const clamped = clamp(n, resolved.min, resolved.max);
34
+ return resolved.integer ? Math.round(clamped) : clamped;
35
+ };
36
+ const value = fit(field.value);
37
+ const setValue = (next) => {
38
+ if (!Number.isFinite(next)) {
39
+ console.warn(`Field '${opts.id}': '${next}' is not a finite number`);
40
+ return;
41
+ }
42
+ field.setValue(fit(next));
43
+ };
44
+ return {
45
+ ...field,
46
+ ...resolved,
47
+ value,
48
+ setValue,
49
+ valueText: resolved.format(value),
50
+ };
51
+ }
52
+ //# sourceMappingURL=useNumericField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNumericField.js","sourceRoot":"","sources":["../src/useNumericField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,cAAc,EAA4C,MAAM,cAAc,CAAC;AAa/F;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAyB,EAAE,GAAa,EAAE,EAAU;IACtF,MAAM,QAAQ,GAAG,SAAS,CAAqB,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;IAC1H,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,GAAG,GAAG,SAAS,CAAqB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACnG,MAAM,GAAG,GAAG,SAAS,CAAqB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACnG,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAuC,EACvC,QAAuC;IAEvC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,YAAY,CAA+B,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEzH,qEAAqE;IACrE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrD,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1D,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,OAAO,IAAI,0BAA0B,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,OAAO;QACL,GAAG,KAAK;QACR,GAAG,QAAQ;QACX,KAAK;QACL,QAAQ;QACR,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;KAClC,CAAC;AACJ,CAAC"}
@@ -1,38 +1,22 @@
1
- import type { ReactNode } from 'react';
2
1
  import { type FieldControls, type FieldOptions } from './field.js';
3
- import type { Decision, ErrorRoutesRegistry, ValueOrFn } from './types.js';
4
- /** One choice of a one-of field (moxb's BindOneOfChoice). */
5
- export interface OneOfChoice<T extends string = string> {
6
- value: T;
7
- /** Shown for the choice; default: the value. */
8
- label?: string;
9
- /** What choosing it does (moxb's `help`), markdown; also the field's current state when it is chosen. */
10
- description?: string;
11
- /** Shown before the label (or instead of it, for an icon-only widget), like an action's icon. */
12
- icon?: ReactNode;
13
- /** Choosable? Default true, optionally with a reason. Use `enabled` or `disabled`, not contradicting each other. */
14
- enabled?: Decision;
15
- disabled?: Decision;
16
- /** Shown as the main or a dangerous choice, like an action's variant. Default 'default'. */
17
- variant?: 'default' | 'primary' | 'danger';
18
- /** A heading the choice is listed under, after the choices without one (OneOfSelect); default none. */
19
- group?: string;
20
- }
21
- /** A choice as the widgets get it. */
22
- export interface OneOfChoiceControls<T extends string = string> {
23
- value: T;
24
- label: string;
25
- description: string | undefined;
26
- icon: ReactNode | undefined;
27
- enabled: boolean;
28
- whyDisabled: string | undefined;
29
- variant: 'default' | 'primary' | 'danger';
30
- group: string | undefined;
31
- }
32
- export type OneOfFieldOptions<T extends string = string, RouteId extends string = string> = FieldOptions<T, T, RouteId> & {
33
- /** The choices, in order; static or derived. */
34
- choices: ValueOrFn<OneOfChoice<T>[]>;
2
+ import { type OneOfChoice, type OneOfChoiceControls } from './choices.js';
3
+ import { type FieldCtx } from './FieldContext.js';
4
+ import type { ErrorRoutesRegistry, ValueOrFn } from './types.js';
5
+ export type { OneOfChoice, OneOfChoiceControls };
6
+ export type OneOfOwnOptions<T extends string = string, Ctx = any> = {
7
+ /** The choices, in order; static or derived (a function, of the field context if it declares a parameter). */
8
+ choices: ValueOrFn<OneOfChoice<T>[], Ctx>;
35
9
  };
10
+ export type OneOfFieldOptions<T extends string = string, RouteId extends string = string, Ctx = any> = FieldOptions<T, T, RouteId, Ctx> & OneOfOwnOptions<T, Ctx>;
11
+ /**
12
+ * The implicit initial value for a one-of field: `initialValue` resolved through the field
13
+ * context, else the first enabled choice. Resolving first (rather than `opts.initialValue ??
14
+ * ...`) matters when `initialValue` is a context function that returns undefined: `??` would
15
+ * see the function, not its result, and never fall back.
16
+ */
17
+ export declare function oneOfInitialValue<T extends string>(opts: {
18
+ initialValue?: ValueOrFn<T>;
19
+ }, ctx: FieldCtx, id: string, choices: OneOfChoiceControls<T>[]): T | undefined;
36
20
  export interface OneOfFieldControls<T extends string = string> extends FieldControls<T, T> {
37
21
  choices: OneOfChoiceControls<T>[];
38
22
  /** The choice the value is, if it is one of them. */
@@ -47,5 +31,5 @@ export interface OneOfFieldControls<T extends string = string> extends FieldCont
47
31
  * warning, as a disabled field ignores any request. Inside the field the value
48
32
  * starts at `initialValue`, else at the first enabled choice.
49
33
  */
50
- export declare function useOneOfField<T extends string = string, RouteId extends string = string>(opts: OneOfFieldOptions<T, RouteId>, registry?: ErrorRoutesRegistry<RouteId>): OneOfFieldControls<T>;
34
+ export declare function useOneOfField<T extends string = string, RouteId extends string = string, Ctx = any>(opts: OneOfFieldOptions<T, RouteId, Ctx>, registry?: ErrorRoutesRegistry<RouteId>): OneOfFieldControls<T>;
51
35
  //# sourceMappingURL=useOneOfField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useOneOfField.d.ts","sourceRoot":"","sources":["../src/useOneOfField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAkC,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAGnG,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3E,6DAA6D;AAC7D,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACpD,KAAK,EAAE,CAAC,CAAC;IACT,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,oHAAoH;IACpH,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3C,uGAAuG;IACvG,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,sCAAsC;AACtC,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC5D,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1C,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,IACtF,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,GAAG;IAC5B,gDAAgD;IAChD,OAAO,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACtC,CAAC;AAEJ,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,qDAAqD;IACrD,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC7C;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EACtF,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,EACnC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,kBAAkB,CAAC,CAAC,CAAC,CA2BvB"}
1
+ {"version":3,"file":"useOneOfField.d.ts","sourceRoot":"","sources":["../src/useOneOfField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAiB,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIjE,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC;AAEjD,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI;IAClE,8GAA8G;IAC9G,OAAO,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,IACjG,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,IAAI,EAAE;IAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;CAAE,EACrC,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,GAChC,CAAC,GAAG,SAAS,CAGf;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;IAClC,qDAAqD;IACrD,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,GAAG,GAAG,GAAG,EACjG,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EACxC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,GACtC,kBAAkB,CAAC,CAAC,CAAC,CA8BvB"}
@@ -1,19 +1,16 @@
1
- import { calculateEnabled, useFieldCore } from './field.js';
2
- import { getReason, getVerdict } from './decision.js';
3
- import { resolve } from './resolve.js';
4
- function resolveChoice(fieldId, choice) {
5
- const decision = calculateEnabled(`${fieldId}.${choice.value}`, choice.enabled, choice.disabled);
6
- const enabled = getVerdict(decision, true);
7
- return {
8
- value: choice.value,
9
- label: choice.label ?? choice.value,
10
- description: choice.description,
11
- icon: choice.icon,
12
- enabled,
13
- whyDisabled: enabled ? undefined : getReason(decision),
14
- variant: choice.variant ?? 'default',
15
- group: choice.group,
16
- };
1
+ import { useFieldCore } from './field.js';
2
+ import { resolveChoice } from './choices.js';
3
+ import { useFieldContext } from './FieldContext.js';
4
+ import { resolveIn } from './resolve.js';
5
+ /**
6
+ * The implicit initial value for a one-of field: `initialValue` resolved through the field
7
+ * context, else the first enabled choice. Resolving first (rather than `opts.initialValue ??
8
+ * ...`) matters when `initialValue` is a context function that returns undefined: `??` would
9
+ * see the function, not its result, and never fall back.
10
+ */
11
+ export function oneOfInitialValue(opts, ctx, id, choices) {
12
+ const resolved = resolveIn(opts.initialValue, undefined, ctx, `Field '${id}': option 'initialValue'`);
13
+ return resolved ?? choices.find((c) => c.enabled)?.value;
17
14
  }
18
15
  /**
19
16
  * A field whose value is one of a list of choices (moxb's OneOf). Rendered by
@@ -25,9 +22,12 @@ function resolveChoice(fieldId, choice) {
25
22
  * starts at `initialValue`, else at the first enabled choice.
26
23
  */
27
24
  export function useOneOfField(opts, registry) {
28
- const choices = resolve(opts.choices, []).map((c) => resolveChoice(opts.id, c));
25
+ const ctx = useFieldContext();
26
+ const choices = resolveIn(opts.choices, [], ctx, `Field '${opts.id}': option 'choices'`)
27
+ .map((c) => resolveChoice(opts.id, c));
29
28
  const inside = !opts.onChange && !opts.commit;
30
- const initialValue = opts.initialValue ?? choices.find((c) => c.enabled)?.value;
29
+ // Undefined when no choice is enabled, and then so is the value.
30
+ const initialValue = () => oneOfInitialValue(opts, ctx, opts.id, choices);
31
31
  const field = useFieldCore('oneOf', inside ? { ...opts, initialValue } : opts, registry);
32
32
  const current = choices.find((c) => c.value === field.value);
33
33
  const setValue = (next) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useOneOfField.js","sourceRoot":"","sources":["../src/useOneOfField.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACnG,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA6CvC,SAAS,aAAa,CAAmB,OAAe,EAAE,MAAsB;IAC9E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjG,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3C,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;QACnC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO;QACP,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC;QACtD,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,SAAS;QACpC,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAmC,EACnC,QAAuC;IAEvC,MAAM,OAAO,GAAG,OAAO,CAAmB,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAClG,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;IAChF,MAAM,KAAK,GAAG,YAAY,CAAgB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxG,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,CAAC,IAAO,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,OAAO,IAAI,6BAA6B,CAAC,CAAC;YACxE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,cAAc,IAAI,mBAAmB,MAAM,CAAC,WAAW,IAAI,aAAa,EAAE,CAAC,CAAC;YAC1G,OAAO;QACT,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO;QACL,GAAG,KAAK;QACR,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,OAAO,EAAE,WAAW;QAChE,QAAQ;QACR,OAAO;QACP,OAAO;KACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"useOneOfField.js","sourceRoot":"","sources":["../src/useOneOfField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAyC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,aAAa,EAA8C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAezC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAqC,EACrC,GAAa,EACb,EAAU,EACV,OAAiC;IAEjC,MAAM,QAAQ,GAAG,SAAS,CAAgB,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,0BAA0B,CAAC,CAAC;IACrH,OAAO,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;AAC3D,CAAC;AAQD;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAwC,EACxC,QAAuC;IAEvC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAG,SAAS,CAAmB,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,UAAU,IAAI,CAAC,EAAE,qBAAqB,CAAC;SACvG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC9C,iEAAiE;IACjE,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAM,CAAC;IAC/E,MAAM,KAAK,GAAG,YAAY,CAAqB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7G,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,CAAC,IAAO,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,OAAO,IAAI,6BAA6B,CAAC,CAAC;YACxE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,cAAc,IAAI,mBAAmB,MAAM,CAAC,WAAW,IAAI,aAAa,EAAE,CAAC,CAAC;YAC1G,OAAO;QACT,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO;QACL,GAAG,KAAK;QACR,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,IAAI,OAAO,EAAE,WAAW;QAChE,QAAQ;QACR,OAAO;QACP,OAAO;KACR,CAAC;AACJ,CAAC"}