vultus-core 0.4.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.
- package/README.md +304 -6
- package/dist/ArgStoreContext.d.ts +10 -0
- package/dist/ArgStoreContext.d.ts.map +1 -0
- package/dist/ArgStoreContext.js +15 -0
- package/dist/ArgStoreContext.js.map +1 -0
- package/dist/FieldContext.d.ts +38 -0
- package/dist/FieldContext.d.ts.map +1 -0
- package/dist/FieldContext.js +82 -0
- package/dist/FieldContext.js.map +1 -0
- package/dist/argStore.d.ts +26 -0
- package/dist/argStore.d.ts.map +1 -0
- package/dist/argStore.js +27 -0
- package/dist/argStore.js.map +1 -0
- package/dist/choices.d.ts +43 -0
- package/dist/choices.d.ts.map +1 -0
- package/dist/choices.js +20 -0
- package/dist/choices.js.map +1 -0
- package/dist/field.d.ts +42 -15
- package/dist/field.d.ts.map +1 -1
- package/dist/field.js +20 -7
- package/dist/field.js.map +1 -1
- package/dist/index.d.ts +21 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -3
- package/dist/index.js.map +1 -1
- package/dist/kinds.d.ts +51 -0
- package/dist/kinds.d.ts.map +1 -0
- package/dist/kinds.js +143 -0
- package/dist/kinds.js.map +1 -0
- package/dist/localStorageStore.d.ts +16 -0
- package/dist/localStorageStore.d.ts.map +1 -0
- package/dist/localStorageStore.js +72 -0
- package/dist/localStorageStore.js.map +1 -0
- package/dist/normalizeText.d.ts +6 -0
- package/dist/normalizeText.d.ts.map +1 -0
- package/dist/normalizeText.js +8 -0
- package/dist/normalizeText.js.map +1 -0
- package/dist/numeric.d.ts +38 -0
- package/dist/numeric.d.ts.map +1 -0
- package/dist/numeric.js +43 -0
- package/dist/numeric.js.map +1 -0
- package/dist/resolve.d.ts +13 -0
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +25 -0
- package/dist/resolve.js.map +1 -1
- package/dist/tree.d.ts +69 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +151 -0
- package/dist/tree.js.map +1 -0
- package/dist/types.d.ts +15 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/useArg.d.ts +45 -0
- package/dist/useArg.d.ts.map +1 -0
- package/dist/useArg.js +83 -0
- package/dist/useArg.js.map +1 -0
- package/dist/useBoolField.d.ts +8 -3
- package/dist/useBoolField.d.ts.map +1 -1
- package/dist/useBoolField.js +9 -1
- package/dist/useBoolField.js.map +1 -1
- package/dist/useManyOfField.d.ts +35 -0
- package/dist/useManyOfField.d.ts.map +1 -0
- package/dist/useManyOfField.js +74 -0
- package/dist/useManyOfField.js.map +1 -0
- package/dist/useMixedBoolField.d.ts +8 -3
- package/dist/useMixedBoolField.d.ts.map +1 -1
- package/dist/useMixedBoolField.js +9 -1
- package/dist/useMixedBoolField.js.map +1 -1
- package/dist/useNumericField.d.ts +25 -0
- package/dist/useNumericField.d.ts.map +1 -0
- package/dist/useNumericField.js +52 -0
- package/dist/useNumericField.js.map +1 -0
- package/dist/useOneOfField.d.ts +18 -34
- package/dist/useOneOfField.d.ts.map +1 -1
- package/dist/useOneOfField.js +18 -18
- package/dist/useOneOfField.js.map +1 -1
- package/dist/useRangeField.d.ts +34 -0
- package/dist/useRangeField.d.ts.map +1 -0
- package/dist/useRangeField.js +63 -0
- package/dist/useRangeField.js.map +1 -0
- package/dist/useStoredField.d.ts +61 -0
- package/dist/useStoredField.d.ts.map +1 -0
- package/dist/useStoredField.js +151 -0
- package/dist/useStoredField.js.map +1 -0
- package/dist/useTextField.d.ts +22 -0
- package/dist/useTextField.d.ts.map +1 -0
- package/dist/useTextField.js +21 -0
- package/dist/useTextField.js.map +1 -0
- package/dist/useTreeField.d.ts +39 -0
- package/dist/useTreeField.d.ts.map +1 -0
- package/dist/useTreeField.js +66 -0
- package/dist/useTreeField.js.map +1 -0
- package/dist/valueTypes.d.ts +28 -0
- package/dist/valueTypes.d.ts.map +1 -0
- package/dist/valueTypes.js +65 -0
- package/dist/valueTypes.js.map +1 -0
- package/package.json +1 -1
- package/src/ArgStoreContext.tsx +16 -0
- package/src/FieldContext.tsx +98 -0
- package/src/argStore.ts +49 -0
- package/src/choices.ts +62 -0
- package/src/field.ts +64 -25
- package/src/index.ts +50 -4
- package/src/kinds.ts +197 -0
- package/src/localStorageStore.ts +68 -0
- package/src/normalizeText.ts +7 -0
- package/src/numeric.ts +68 -0
- package/src/resolve.ts +23 -0
- package/src/tree.ts +175 -0
- package/src/types.ts +28 -7
- package/src/useArg.ts +121 -0
- package/src/useBoolField.ts +19 -6
- package/src/useManyOfField.ts +107 -0
- package/src/useMixedBoolField.ts +19 -6
- package/src/useNumericField.ts +69 -0
- package/src/useOneOfField.ts +38 -58
- package/src/useRangeField.ts +86 -0
- package/src/useStoredField.ts +205 -0
- package/src/useTextField.ts +39 -0
- package/src/useTreeField.ts +108 -0
- package/src/valueTypes.ts +77 -0
|
@@ -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"}
|
package/dist/numeric.js
ADDED
|
@@ -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
|
package/dist/resolve.d.ts.map
CHANGED
|
@@ -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
|
package/dist/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"
|
|
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
|
package/dist/tree.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
|
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
|
-
|
|
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:
|
|
60
|
-
icon?:
|
|
61
|
-
variant?:
|
|
62
|
-
enabled?:
|
|
63
|
-
invisible?:
|
|
64
|
-
confirmation?:
|
|
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;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;CAC9F;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/useArg.d.ts
ADDED
|
@@ -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"}
|
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":"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"}
|