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
@@ -0,0 +1,72 @@
1
+ /**
2
+ * An ArgStore over `window.localStorage` (Praeceptor's print options), items kept under
3
+ * `${prefix}.${key}`. Guarded for SSR/Node (`typeof window === 'undefined'`), so creating one
4
+ * outside a browser does not crash: reads then give `undefined` and writes are no-ops. A browser
5
+ * may block storage (a sandboxed frame, blocked site data) or refuse a write (quota), and then
6
+ * reaching or using `localStorage` throws: a read that fails reads as absent and a write that
7
+ * fails is skipped, with one warning per store rather than one per call.
8
+ *
9
+ * A write notifies this store's own subscribers; a `storage` event (another tab changed a key
10
+ * under the prefix) notifies them too. The store listens for that event on `window` only while
11
+ * it has subscribers, so a store that is dropped leaves no listener behind; still, create one
12
+ * once (outside render, or in `useMemo`) rather than on every render.
13
+ */
14
+ export function localStorageStore(prefix) {
15
+ const hasWindow = typeof window !== 'undefined';
16
+ const listeners = new Set();
17
+ const storageKey = (key) => `${prefix}.${key}`;
18
+ // `null` means "another tab cleared the whole storage" (localStorage.clear()): every key under
19
+ // the prefix may have changed, so this counts as ours too.
20
+ const isOwnStorageKey = (key) => key === null || key.startsWith(`${prefix}.`);
21
+ const onStorage = (event) => {
22
+ if (isOwnStorageKey(event.key))
23
+ listeners.forEach((listener) => listener());
24
+ };
25
+ let warned = false;
26
+ /** Runs a use of localStorage; if it throws, warns (the first time for this store) and gives `undefined`. */
27
+ const guarded = (what, use) => {
28
+ try {
29
+ return use(window.localStorage);
30
+ }
31
+ catch (error) {
32
+ if (!warned) {
33
+ warned = true;
34
+ console.warn(`localStorageStore('${prefix}'): cannot ${what} localStorage (${String(error)}); `
35
+ + 'failing reads read as absent and failing writes are skipped, without further warnings');
36
+ }
37
+ return undefined;
38
+ }
39
+ };
40
+ return {
41
+ read(key) {
42
+ if (!hasWindow)
43
+ return undefined;
44
+ return guarded('read', (storage) => storage.getItem(storageKey(key))) ?? undefined;
45
+ },
46
+ write(changes, _method) {
47
+ if (!hasWindow)
48
+ return;
49
+ for (const { key, raw } of changes) {
50
+ guarded('write', (storage) => {
51
+ if (raw === undefined)
52
+ storage.removeItem(storageKey(key));
53
+ else
54
+ storage.setItem(storageKey(key), raw);
55
+ });
56
+ }
57
+ listeners.forEach((listener) => listener());
58
+ },
59
+ subscribe(listener) {
60
+ if (hasWindow && listeners.size === 0)
61
+ window.addEventListener('storage', onStorage);
62
+ listeners.add(listener);
63
+ return () => {
64
+ if (!listeners.delete(listener))
65
+ return;
66
+ if (hasWindow && listeners.size === 0)
67
+ window.removeEventListener('storage', onStorage);
68
+ };
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=localStorageStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localStorageStore.js","sourceRoot":"","sources":["../src/localStorageStore.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC;IACvD,+FAA+F;IAC/F,2DAA2D;IAC3D,MAAM,eAAe,GAAG,CAAC,GAAkB,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAG,CAAC,KAAmB,EAAE,EAAE;QACxC,IAAI,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC;IAEF,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,6GAA6G;IAC7G,MAAM,OAAO,GAAG,CAAI,IAAY,EAAE,GAA4B,EAAiB,EAAE;QAC/E,IAAI,CAAC;YACH,OAAO,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,GAAG,IAAI,CAAC;gBACd,OAAO,CAAC,IAAI,CACV,sBAAsB,MAAM,cAAc,IAAI,kBAAkB,MAAM,CAAC,KAAK,CAAC,KAAK;sBAChF,uFAAuF,CAC1F,CAAC;YACJ,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,CAAC,GAAG;YACN,IAAI,CAAC,SAAS;gBAAE,OAAO,SAAS,CAAC;YACjC,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACrF,CAAC;QACD,KAAK,CAAC,OAAO,EAAE,OAAO;YACpB,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,KAAK,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC;gBACnC,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE;oBAC3B,IAAI,GAAG,KAAK,SAAS;wBAAE,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;;wBACtD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC7C,CAAC,CAAC,CAAC;YACL,CAAC;YACD,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,SAAS,CAAC,QAAQ;YAChB,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;gBAAE,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACrF,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE;gBACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;oBAAE,OAAO;gBACxC,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;oBAAE,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC1F,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A key for accent- and case-insensitive comparison of labels (the tree hook's search,
3
+ * Taskmaster's): decompose, strip the combining marks, lower-case. No quaesitor dependency.
4
+ */
5
+ export declare function normalizeText(text: string): string;
6
+ //# sourceMappingURL=normalizeText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeText.d.ts","sourceRoot":"","sources":["../src/normalizeText.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A key for accent- and case-insensitive comparison of labels (the tree hook's search,
3
+ * Taskmaster's): decompose, strip the combining marks, lower-case. No quaesitor dependency.
4
+ */
5
+ export function normalizeText(text) {
6
+ return text.normalize('NFD').replace(/\p{M}/gu, '').toLowerCase();
7
+ }
8
+ //# sourceMappingURL=normalizeText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeText.js","sourceRoot":"","sources":["../src/normalizeText.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACpE,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { type FieldCtx } from './FieldContext.js';
2
+ import type { ValueOrFn } from './types.js';
3
+ /**
4
+ * The bounds and formatting a numeric field has, shared with the range kind (whose two ends
5
+ * reuse the same bounds). Each may be a context function, resolved like any other field option.
6
+ * `format` is not itself a ValueOrFn — it always takes the number as its first argument — so it
7
+ * is resolved by its own rule, below.
8
+ */
9
+ export interface NumericBounds<Ctx = any> {
10
+ min?: ValueOrFn<number | undefined, Ctx>;
11
+ max?: ValueOrFn<number | undefined, Ctx>;
12
+ step?: ValueOrFn<number | undefined, Ctx>;
13
+ integer?: ValueOrFn<boolean, Ctx>;
14
+ unit?: ValueOrFn<string | undefined, Ctx>;
15
+ /** Formats a value for display; default: the number followed by the unit, if any. */
16
+ format?: (n: number, ctx: Ctx) => string;
17
+ }
18
+ /** A NumericBounds with every option resolved through the field context. */
19
+ export interface ResolvedNumeric {
20
+ min: number | undefined;
21
+ max: number | undefined;
22
+ step: number | undefined;
23
+ integer: boolean;
24
+ unit: string | undefined;
25
+ format(n: number): string;
26
+ }
27
+ /** Clamps `n` into [min, max]; either end left out leaves that side open. */
28
+ export declare function clamp(n: number, min?: number, max?: number): number;
29
+ /**
30
+ * Resolves a numeric field's bounds and formatter with the field context. `format` goes by its
31
+ * own rule, not resolveIn's, as it always receives the number first; otherwise it is treated
32
+ * the same way. With a provider above, it receives the context as its second argument, and a
33
+ * key it reads that no provider gave throws naming the field and the option `'format'`. With
34
+ * none, a `format` that declares the context parameter (`format.length >= 2`) throws the same
35
+ * message shape resolveIn uses, and one that does not is called with the number alone.
36
+ */
37
+ export declare function resolveNumeric(id: string, opts: NumericBounds, ctx: FieldCtx): ResolvedNumeric;
38
+ //# sourceMappingURL=numeric.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numeric.d.ts","sourceRoot":"","sources":["../src/numeric.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,aAAa,CAAC,GAAG,GAAG,GAAG;IACtC,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC;IAC1C,qFAAqF;IACrF,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;CAC1C;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,6EAA6E;AAC7E,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,GAAG,eAAe,CAqB9F"}
@@ -0,0 +1,43 @@
1
+ import { NO_FIELD_CONTEXT, readingContext } from './FieldContext.js';
2
+ import { resolveIn } from './resolve.js';
3
+ /** Clamps `n` into [min, max]; either end left out leaves that side open. */
4
+ export function clamp(n, min, max) {
5
+ let result = n;
6
+ if (min !== undefined)
7
+ result = Math.max(result, min);
8
+ if (max !== undefined)
9
+ result = Math.min(result, max);
10
+ return result;
11
+ }
12
+ /**
13
+ * Resolves a numeric field's bounds and formatter with the field context. `format` goes by its
14
+ * own rule, not resolveIn's, as it always receives the number first; otherwise it is treated
15
+ * the same way. With a provider above, it receives the context as its second argument, and a
16
+ * key it reads that no provider gave throws naming the field and the option `'format'`. With
17
+ * none, a `format` that declares the context parameter (`format.length >= 2`) throws the same
18
+ * message shape resolveIn uses, and one that does not is called with the number alone.
19
+ */
20
+ export function resolveNumeric(id, opts, ctx) {
21
+ const where = (name) => `Field '${id}': option '${name}'`;
22
+ const min = resolveIn(opts.min, undefined, ctx, where('min'));
23
+ const max = resolveIn(opts.max, undefined, ctx, where('max'));
24
+ const step = resolveIn(opts.step, undefined, ctx, where('step'));
25
+ const integer = resolveIn(opts.integer, false, ctx, where('integer'));
26
+ const unit = resolveIn(opts.unit, undefined, ctx, where('unit'));
27
+ const { format } = opts;
28
+ let resolvedFormat;
29
+ if (format === undefined) {
30
+ resolvedFormat = (n) => `${n}${unit ?? ''}`;
31
+ }
32
+ else if (ctx !== NO_FIELD_CONTEXT) {
33
+ resolvedFormat = (n) => readingContext(where('format'), () => format(n, ctx));
34
+ }
35
+ else if (format.length < 2) {
36
+ resolvedFormat = (n) => format(n, undefined);
37
+ }
38
+ else {
39
+ throw new Error(`${where('format')} is a function of the field context, but no FieldContextProvider is above it`);
40
+ }
41
+ return { min, max, step, integer, unit, format: resolvedFormat };
42
+ }
43
+ //# sourceMappingURL=numeric.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numeric.js","sourceRoot":"","sources":["../src/numeric.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAiB,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AA6BzC,6EAA6E;AAC7E,MAAM,UAAU,KAAK,CAAC,CAAS,EAAE,GAAY,EAAE,GAAY;IACzD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU,EAAE,IAAmB,EAAE,GAAa;IAC3E,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,UAAU,EAAE,cAAc,IAAI,GAAG,CAAC;IAClE,MAAM,GAAG,GAAG,SAAS,CAAqB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAClF,MAAM,GAAG,GAAG,SAAS,CAAqB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,SAAS,CAAqB,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,SAAS,CAAU,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,SAAS,CAAqB,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAErF,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,IAAI,cAAqC,CAAC;IAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,cAAc,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;IAC9C,CAAC;SAAM,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;QACpC,cAAc,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,GAAY,CAAC,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,cAAc,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,SAAkB,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,8EAA8E,CAAC,CAAC;IACpH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;AACnE,CAAC"}
package/dist/resolve.d.ts CHANGED
@@ -1,3 +1,16 @@
1
+ import { type FieldCtx } from './FieldContext.js';
1
2
  import type { ValueOrFn } from './types.js';
2
3
  export declare function resolve<T>(v: ValueOrFn<T> | undefined, fallback: T): T;
4
+ /**
5
+ * Resolves a field's option with its context. With a provider above, every function receives
6
+ * `ctx`, so one whose parameter has a default (`(ctx = {}) => ...`) gets it too. With none, a
7
+ * function without declared parameters is called with nothing, so it works without a provider,
8
+ * and one that declares a parameter throws, `where` (`Field '<id>': option '<name>'`) saying
9
+ * whose it is. A key the function reads that no provider gave throws with `where` in front, so
10
+ * that error names the field and the option too. A function that returns `undefined` counts as
11
+ * an absent option, and yields `fallback` — a context lookup that misses (e.g. `(ctx) =>
12
+ * ctx.items[id]`) should fall back exactly as leaving the option out would, not leave the field
13
+ * with no value at all.
14
+ */
15
+ export declare function resolveIn<T>(v: ValueOrFn<T> | undefined, fallback: T, ctx: FieldCtx, where: string): T;
3
16
  //# sourceMappingURL=resolve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAGtE"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAGtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAStG"}
package/dist/resolve.js CHANGED
@@ -1,6 +1,31 @@
1
+ import { NO_FIELD_CONTEXT, readingContext } from './FieldContext.js';
1
2
  export function resolve(v, fallback) {
2
3
  if (v === undefined)
3
4
  return fallback;
4
5
  return typeof v === 'function' ? v() : v;
5
6
  }
7
+ /**
8
+ * Resolves a field's option with its context. With a provider above, every function receives
9
+ * `ctx`, so one whose parameter has a default (`(ctx = {}) => ...`) gets it too. With none, a
10
+ * function without declared parameters is called with nothing, so it works without a provider,
11
+ * and one that declares a parameter throws, `where` (`Field '<id>': option '<name>'`) saying
12
+ * whose it is. A key the function reads that no provider gave throws with `where` in front, so
13
+ * that error names the field and the option too. A function that returns `undefined` counts as
14
+ * an absent option, and yields `fallback` — a context lookup that misses (e.g. `(ctx) =>
15
+ * ctx.items[id]`) should fall back exactly as leaving the option out would, not leave the field
16
+ * with no value at all.
17
+ */
18
+ export function resolveIn(v, fallback, ctx, where) {
19
+ if (v === undefined)
20
+ return fallback;
21
+ if (typeof v !== 'function')
22
+ return v;
23
+ const fn = v;
24
+ if (ctx !== NO_FIELD_CONTEXT)
25
+ return readingContext(where, () => fn(ctx)) ?? fallback;
26
+ if (fn.length > 0) {
27
+ throw new Error(`${where} is a function of the field context, but no FieldContextProvider is above it`);
28
+ }
29
+ return fn() ?? fallback;
30
+ }
6
31
  //# sourceMappingURL=resolve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,OAAO,CAAI,CAA2B,EAAE,QAAW;IACjE,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACrC,OAAO,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAE,CAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAiB,MAAM,mBAAmB,CAAC;AAGpF,MAAM,UAAU,OAAO,CAAI,CAA2B,EAAE,QAAW;IACjE,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACrC,OAAO,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAE,CAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAI,CAA2B,EAAE,QAAW,EAAE,GAAa,EAAE,KAAa;IACjG,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACrC,IAAI,OAAO,CAAC,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,CAAwB,CAAC;IACpC,IAAI,GAAG,KAAK,gBAAgB;QAAE,OAAO,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC;IACtF,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,8EAA8E,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,EAAE,EAAE,IAAI,QAAQ,CAAC;AAC1B,CAAC"}
package/dist/tree.d.ts ADDED
@@ -0,0 +1,69 @@
1
+ import type { OneOfChoice, OneOfChoiceControls } from './choices.js';
2
+ /** A node of a tree field (Praeceptor's categories): a choice with children. */
3
+ export interface TreeNode<T extends string = string> extends OneOfChoice<T> {
4
+ children?: TreeNode<T>[];
5
+ }
6
+ /** A node as the widgets get it: the resolved choice, its children likewise, and whether it shows checked. */
7
+ export interface TreeNodeControls<T extends string = string> extends OneOfChoiceControls<T> {
8
+ children: TreeNodeControls<T>[] | undefined;
9
+ /** Covered by the value (in the cascading selections), or in the value (`'independent'`). */
10
+ checked: boolean;
11
+ }
12
+ /**
13
+ * What a tree field's value lists, as antd TreeSelect's `showCheckedStrategy` and
14
+ * `checkStrictly` do. In the three cascading selections a node stands for its subtree, and
15
+ * a node all of whose children are covered is covered too; they differ only in which of the
16
+ * covered nodes the value names:
17
+ * - `'topmost'` (`SHOW_PARENT`, the default): the covered nodes whose parent is not covered;
18
+ * - `'all'` (`SHOW_ALL`): every covered node;
19
+ * - `'leaves'` (`SHOW_CHILD`): the covered leaves.
20
+ *
21
+ * `'independent'` (`checkStrictly`, moxb's `strictSelect`): each node is chosen on its own.
22
+ */
23
+ export type TreeSelection = 'topmost' | 'all' | 'leaves' | 'independent';
24
+ /**
25
+ * Which nodes a tree widget opens at first: `'top'` (the default), the roots with children;
26
+ * `'none'`; `'selected'` (moxb's `expandValues`), the ancestors of the value's nodes; `'all'`,
27
+ * every node with children.
28
+ */
29
+ export type TreeExpand = 'top' | 'none' | 'selected' | 'all';
30
+ /**
31
+ * A tree field's value in its canonical form under `selection` (see TreeSelection): the
32
+ * nodes it names in tree pre-order, followed by the values that name no node, without
33
+ * duplicates. With `'topmost'`, `['A1', 'A']` becomes `['A']`, and a node's children all
34
+ * listed become the node.
35
+ */
36
+ export declare function normalizeTreeValue<T extends string>(nodes: TreeNode<T>[], value: T[], selection: TreeSelection): T[];
37
+ /**
38
+ * Every node a tree field's value stands for, in pre-order (what an item filed under some
39
+ * node matches against): in the cascading selections the covered nodes (the value's nodes,
40
+ * their descendants, and every node all of whose children are covered); with
41
+ * `'independent'` the value's nodes themselves. Values that name no node follow, as in
42
+ * normalizeTreeValue.
43
+ */
44
+ export declare function coveredNodes<T extends string>(nodes: TreeNode<T>[], value: T[], selection?: TreeSelection): T[];
45
+ /**
46
+ * The value after flipping `node`, normalized. In the cascading selections a covered node
47
+ * is removed with its descendants and its ancestors (they no longer have all their
48
+ * children), and an uncovered one is added with its descendants; with `'independent'` the
49
+ * node alone is added or removed. A `node` that is not one of the nodes changes nothing.
50
+ */
51
+ export declare function toggleTreeValue<T extends string>(nodes: TreeNode<T>[], value: T[], node: T, selection: TreeSelection): T[];
52
+ /** The nodes a tree widget opens at first under `expand` (see TreeExpand), in pre-order. */
53
+ export declare function expandedTreeKeys<T extends string>(nodes: TreeNode<T>[], value: T[], expand: TreeExpand): T[];
54
+ /**
55
+ * The nodes matching a search (Taskmaster's category search), by antd TreeSelect's rule, so a
56
+ * dropdown and a drawer over the same nodes agree: a node matches if its label (else its
57
+ * value) contains the query, ignoring accents, case and the query's surrounding spaces. A
58
+ * matching node stays with its whole subtree; any other node stays if one of its descendants
59
+ * matches, keeping only the children that stay. A node that stays with no children has
60
+ * `children` undefined, not an empty list. Generic over the node's shape, so the widgets can
61
+ * filter resolved node controls; the nodes given are not changed. An empty query returns
62
+ * them as they are.
63
+ */
64
+ export declare function filterTree<N extends {
65
+ label?: string;
66
+ value: string;
67
+ children?: N[];
68
+ }>(nodes: N[], query: string): N[];
69
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGrE,gFAAgF;AAChF,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1B;AAED,8GAA8G;AAC9G,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IACzF,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;IAC5C,6FAA6F;IAC7F,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,CAAC;AAwD7D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,aAAa,GAAG,CAAC,EAAE,CAOpH;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,GAAE,aAAyB,GAAG,CAAC,EAAE,CAE1H;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,aAAa,GAAG,CAAC,EAAE,CAgB1H;AAED,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,EAAE,CAU5G;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,CAYtH"}
package/dist/tree.js ADDED
@@ -0,0 +1,151 @@
1
+ import { normalizeText } from './normalizeText.js';
2
+ function hasChildren(node) {
3
+ return (node.children?.length ?? 0) > 0;
4
+ }
5
+ /** The nodes in pre-order, and each node's parent. */
6
+ function indexTree(nodes) {
7
+ const order = [];
8
+ const parent = new Map();
9
+ const walk = (list, up) => {
10
+ for (const node of list) {
11
+ order.push(node);
12
+ if (up !== undefined)
13
+ parent.set(node.value, up);
14
+ if (node.children)
15
+ walk(node.children, node.value);
16
+ }
17
+ };
18
+ walk(nodes, undefined);
19
+ return { order, parent };
20
+ }
21
+ /** The values that name no node, in their order, without duplicates (kept, so a stale value is not silently dropped). */
22
+ function unknownValues(order, value) {
23
+ const known = new Set(order.map((n) => n.value));
24
+ return [...new Set(value.filter((v) => !known.has(v)))];
25
+ }
26
+ /** The nodes a value covers in the cascading selections: the value's nodes, their descendants, and every node all of whose children are covered. */
27
+ function cascade(nodes, value) {
28
+ const listed = new Set(value);
29
+ const covered = new Set();
30
+ const walk = (node, inherited) => {
31
+ const self = inherited || listed.has(node.value);
32
+ const children = (node.children ?? []).map((child) => walk(child, self));
33
+ const isCovered = self || (children.length > 0 && children.every(Boolean));
34
+ if (isCovered)
35
+ covered.add(node.value);
36
+ return isCovered;
37
+ };
38
+ for (const node of nodes)
39
+ walk(node, false);
40
+ return covered;
41
+ }
42
+ /** The covered nodes the value names under `selection` (see TreeSelection), in pre-order. */
43
+ function namedNodes(order, parent, covered, selection) {
44
+ const named = order.filter((node) => {
45
+ if (!covered.has(node.value))
46
+ return false;
47
+ if (selection === 'leaves')
48
+ return !hasChildren(node);
49
+ if (selection === 'topmost') {
50
+ const up = parent.get(node.value);
51
+ return up === undefined || !covered.has(up);
52
+ }
53
+ return true;
54
+ });
55
+ return named.map((node) => node.value);
56
+ }
57
+ /**
58
+ * A tree field's value in its canonical form under `selection` (see TreeSelection): the
59
+ * nodes it names in tree pre-order, followed by the values that name no node, without
60
+ * duplicates. With `'topmost'`, `['A1', 'A']` becomes `['A']`, and a node's children all
61
+ * listed become the node.
62
+ */
63
+ export function normalizeTreeValue(nodes, value, selection) {
64
+ const { order, parent } = indexTree(nodes);
65
+ const covered = selection === 'independent' ? new Set(value) : cascade(nodes, value);
66
+ const named = selection === 'independent'
67
+ ? order.filter((node) => covered.has(node.value)).map((node) => node.value)
68
+ : namedNodes(order, parent, covered, selection);
69
+ return [...named, ...unknownValues(order, value)];
70
+ }
71
+ /**
72
+ * Every node a tree field's value stands for, in pre-order (what an item filed under some
73
+ * node matches against): in the cascading selections the covered nodes (the value's nodes,
74
+ * their descendants, and every node all of whose children are covered); with
75
+ * `'independent'` the value's nodes themselves. Values that name no node follow, as in
76
+ * normalizeTreeValue.
77
+ */
78
+ export function coveredNodes(nodes, value, selection = 'topmost') {
79
+ return normalizeTreeValue(nodes, value, selection === 'independent' ? 'independent' : 'all');
80
+ }
81
+ /**
82
+ * The value after flipping `node`, normalized. In the cascading selections a covered node
83
+ * is removed with its descendants and its ancestors (they no longer have all their
84
+ * children), and an uncovered one is added with its descendants; with `'independent'` the
85
+ * node alone is added or removed. A `node` that is not one of the nodes changes nothing.
86
+ */
87
+ export function toggleTreeValue(nodes, value, node, selection) {
88
+ const { order, parent } = indexTree(nodes);
89
+ const target = order.find((n) => n.value === node);
90
+ if (!target)
91
+ return normalizeTreeValue(nodes, value, selection);
92
+ if (selection === 'independent') {
93
+ return normalizeTreeValue(nodes, value.includes(node) ? value.filter((v) => v !== node) : [...value, node], selection);
94
+ }
95
+ const covered = cascade(nodes, value);
96
+ const subtree = indexTree([target]).order.map((n) => n.value);
97
+ if (covered.has(node)) {
98
+ for (const v of subtree)
99
+ covered.delete(v);
100
+ for (let up = parent.get(node); up !== undefined; up = parent.get(up))
101
+ covered.delete(up);
102
+ }
103
+ else {
104
+ for (const v of subtree)
105
+ covered.add(v);
106
+ }
107
+ return normalizeTreeValue(nodes, [...covered, ...unknownValues(order, value)], selection);
108
+ }
109
+ /** The nodes a tree widget opens at first under `expand` (see TreeExpand), in pre-order. */
110
+ export function expandedTreeKeys(nodes, value, expand) {
111
+ if (expand === 'none')
112
+ return [];
113
+ if (expand === 'top')
114
+ return nodes.filter(hasChildren).map((node) => node.value);
115
+ const { order, parent } = indexTree(nodes);
116
+ if (expand === 'all')
117
+ return order.filter(hasChildren).map((node) => node.value);
118
+ const ancestors = new Set();
119
+ for (const v of value) {
120
+ for (let up = parent.get(v); up !== undefined; up = parent.get(up))
121
+ ancestors.add(up);
122
+ }
123
+ return order.filter((node) => ancestors.has(node.value)).map((node) => node.value);
124
+ }
125
+ /**
126
+ * The nodes matching a search (Taskmaster's category search), by antd TreeSelect's rule, so a
127
+ * dropdown and a drawer over the same nodes agree: a node matches if its label (else its
128
+ * value) contains the query, ignoring accents, case and the query's surrounding spaces. A
129
+ * matching node stays with its whole subtree; any other node stays if one of its descendants
130
+ * matches, keeping only the children that stay. A node that stays with no children has
131
+ * `children` undefined, not an empty list. Generic over the node's shape, so the widgets can
132
+ * filter resolved node controls; the nodes given are not changed. An empty query returns
133
+ * them as they are.
134
+ */
135
+ export function filterTree(nodes, query) {
136
+ const q = normalizeText(query.trim());
137
+ if (!q)
138
+ return nodes;
139
+ /** The nodes of `list` that stay; `all` when an ancestor matched, so every node does. */
140
+ const keep = (list, all) => list.flatMap((node) => {
141
+ const matches = all || normalizeText(node.label ?? node.value).includes(q);
142
+ const children = keep(node.children ?? [], matches);
143
+ if (!matches && children.length === 0)
144
+ return [];
145
+ if (node.children === undefined)
146
+ return [node];
147
+ return [{ ...node, children: children.length > 0 ? children : undefined }];
148
+ });
149
+ return keep(nodes, false);
150
+ }
151
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAkCnD,SAAS,WAAW,CAAC,IAA8B;IACjD,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,sDAAsD;AACtD,SAAS,SAAS,CAAmB,KAAoB;IACvD,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAQ,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,IAAmB,EAAE,EAAiB,EAAE,EAAE;QACtD,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,IAAI,EAAE,KAAK,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACvB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED,yHAAyH;AACzH,SAAS,aAAa,CAAmB,KAAoB,EAAE,KAAU;IACvE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,oJAAoJ;AACpJ,SAAS,OAAO,CAAmB,KAAoB,EAAE,KAAU;IACjE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAK,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,IAAiB,EAAE,SAAkB,EAAW,EAAE;QAC9D,MAAM,IAAI,GAAG,SAAS,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACzE,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,IAAI,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6FAA6F;AAC7F,SAAS,UAAU,CAAmB,KAAoB,EAAE,MAAiB,EAAE,OAAe,EAAE,SAAwB;IACtH,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,OAAO,EAAE,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAmB,KAAoB,EAAE,KAAU,EAAE,SAAwB;IAC7G,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,SAAS,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,SAAS,KAAK,aAAa;QACvC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QAC3E,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAmB,KAAoB,EAAE,KAAU,EAAE,YAA2B,SAAS;IACnH,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAmB,KAAoB,EAAE,KAAU,EAAE,IAAO,EAAE,SAAwB;IACnH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAChE,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;QAChC,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;IACzH,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3C,KAAK,IAAI,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,SAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,kBAAkB,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC5F,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAAmB,KAAoB,EAAE,KAAU,EAAE,MAAkB;IACrG,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjF,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAK,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,KAAK,IAAI,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,SAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAA8D,KAAU,EAAE,KAAa;IAC/G,MAAM,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,yFAAyF;IACzF,MAAM,IAAI,GAAG,CAAC,IAAS,EAAE,GAAY,EAAO,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACnE,MAAM,OAAO,GAAG,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC"}
package/dist/types.d.ts CHANGED
@@ -14,7 +14,15 @@ export type Decision = boolean | {
14
14
  verdict: boolean;
15
15
  reason?: string;
16
16
  };
17
- export type ValueOrFn<T> = T | (() => T);
17
+ /**
18
+ * A value, or a function giving it, as a field's options take them. With a FieldContextProvider
19
+ * above, a field calls every such function with its field context (the provider's value); with
20
+ * none, a function without parameters is called with nothing and one that declares a parameter
21
+ * throws.
22
+ */
23
+ export type ValueOrFn<T, Ctx = any> = T | ((ctx: Ctx) => T);
24
+ /** A value, or a function of no arguments giving it, as an action's options take them: an action calls its functions with nothing. */
25
+ export type Thunk<T> = T | (() => T);
18
26
  export type Severity = 'info' | 'warning' | 'error';
19
27
  /** Something an action (or, later, a field's validation) has to say, with its severity. */
20
28
  export interface Message {
@@ -56,12 +64,12 @@ export type ConfirmationSpec = {
56
64
  };
57
65
  export interface ActionOptions<TArgs = void, TResult = void, RouteId extends string = string> {
58
66
  id: string;
59
- label: ValueOrFn<string>;
60
- icon?: ValueOrFn<React.ReactNode>;
61
- variant?: ValueOrFn<'default' | 'primary' | 'danger'>;
62
- enabled?: ValueOrFn<Decision>;
63
- invisible?: ValueOrFn<boolean>;
64
- confirmation?: ValueOrFn<ConfirmationSpec | undefined>;
67
+ label: Thunk<string>;
68
+ icon?: Thunk<React.ReactNode>;
69
+ variant?: Thunk<'default' | 'primary' | 'danger'>;
70
+ enabled?: Thunk<Decision>;
71
+ invisible?: Thunk<boolean>;
72
+ confirmation?: Thunk<ConfirmationSpec | undefined>;
65
73
  errorRoute?: RouteId;
66
74
  fire: (args: TArgs, ctx: ExecutionContext) => Promise<TResult> | TResult;
67
75
  onSuccess?: (result: TResult) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { UpdateMethod } from './argStore.js';
2
+ import type { ValueOrFn } from './types.js';
3
+ import type { ValueType } from './valueTypes.js';
4
+ /** An argument's shape (moxb's url-arg definition, without a `permanent` flag — that is a router concern). */
5
+ export interface ArgDefinition<T, Ctx = any> {
6
+ key: string;
7
+ valueType: ValueType<T>;
8
+ default: ValueOrFn<T, Ctx>;
9
+ }
10
+ export interface ArgControls<T> {
11
+ value: T;
12
+ isDefault: boolean;
13
+ set(value: T, method?: UpdateMethod): void;
14
+ reset(method?: UpdateMethod): void;
15
+ /** The href `set(value)` would produce, where the store supports it (a URL store); `undefined` otherwise. */
16
+ hrefFor(value: T): string | undefined;
17
+ }
18
+ /**
19
+ * An argument read from and written to the nearest ArgStore. An absent key reads as the default;
20
+ * writing the default removes the key.
21
+ *
22
+ * `parse(raw)` is memoized on `[raw, key, valueType]` (not the default, which may be a context
23
+ * function with its own, independently changing inputs): re-rendering with the same raw value
24
+ * does not re-parse and does not re-warn; a raw value that does not parse warns once per such
25
+ * change and the default is used instead. `value` itself then keeps its previous identity
26
+ * whenever it is still `isEqual` to the freshly computed one (parsed-or-default), so a default
27
+ * that builds a fresh value every render (`() => []`) does not change `value`'s identity either —
28
+ * effects keyed on `value` do not re-run just because nothing meaningful changed.
29
+ */
30
+ export declare function useArg<T>(definition: ArgDefinition<T>): ArgControls<T>;
31
+ /** One argument's planned change in a batch (moxb's ArgChange): a new value, or a reset. */
32
+ export type ArgChange = {
33
+ definition: ArgDefinition<any>;
34
+ value?: unknown;
35
+ reset?: true;
36
+ };
37
+ export declare function setArg<T>(definition: ArgDefinition<T>, value: T): ArgChange;
38
+ export declare function resetArg(definition: ArgDefinition<any>): ArgChange;
39
+ /**
40
+ * Applies several argument changes as one store write (one history entry: "clear all", a chip
41
+ * that also closes a task). Each change's default is resolved at call time, from the field
42
+ * context captured when this hook rendered.
43
+ */
44
+ export declare function useArgWriter(): (changes: ArgChange[], method?: UpdateMethod) => void;
45
+ //# sourceMappingURL=useArg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useArg.d.ts","sourceRoot":"","sources":["../src/useArg.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,eAAe,CAAC;AAI7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,8GAA8G;AAC9G,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,6GAA6G;IAC7G,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;CACvC;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA8CtE;AAED,4FAA4F;AAC5F,MAAM,MAAM,SAAS,GAAG;IAAE,UAAU,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1F,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAE3E;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,SAAS,CAElE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,EAAE,YAAY,KAAK,IAAI,CAepF"}