@golemui/core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +517 -0
  2. package/README.md +11 -0
  3. package/index.d.ts +18 -0
  4. package/index.js +1598 -0
  5. package/index.umd.cjs +8 -0
  6. package/lib/context/form.context.d.ts +21 -0
  7. package/lib/context/index.d.ts +3 -0
  8. package/lib/context/widget-registry.d.ts +13 -0
  9. package/lib/context/with-widget.type.d.ts +4 -0
  10. package/lib/form-store.d.ts +12 -0
  11. package/lib/form-validator.d.ts +10 -0
  12. package/lib/form-widget.d.ts +93 -0
  13. package/lib/form.d.ts +22 -0
  14. package/lib/i18n.d.ts +87 -0
  15. package/lib/item-renderer.d.ts +24 -0
  16. package/lib/middleware/index.d.ts +2 -0
  17. package/lib/middleware/json-schema/json-schema.d.ts +67 -0
  18. package/lib/middleware/json-schema/json-schema.middleware.d.ts +19 -0
  19. package/lib/shared.d.ts +143 -0
  20. package/lib/store/actions.d.ts +121 -0
  21. package/lib/store/model.d.ts +107 -0
  22. package/lib/store/reducer.d.ts +10 -0
  23. package/lib/store/reducers/add-widget.d.ts +3 -0
  24. package/lib/store/reducers/calculate-current-state.d.ts +2 -0
  25. package/lib/store/reducers/calculate-widget-flags.d.ts +2 -0
  26. package/lib/store/reducers/calculate-widget-props.d.ts +3 -0
  27. package/lib/store/reducers/index.d.ts +13 -0
  28. package/lib/store/reducers/initialize.d.ts +3 -0
  29. package/lib/store/reducers/inject-validation-issues.d.ts +3 -0
  30. package/lib/store/reducers/override-widget-prop.d.ts +3 -0
  31. package/lib/store/reducers/remove-widget.d.ts +3 -0
  32. package/lib/store/reducers/set-data.d.ts +3 -0
  33. package/lib/store/reducers/set-form-health.d.ts +8 -0
  34. package/lib/store/reducers/set-language.d.ts +3 -0
  35. package/lib/store/reducers/set-widget-data.d.ts +3 -0
  36. package/lib/store/reducers/utils.d.ts +32 -0
  37. package/lib/store/reducers/validate-all.d.ts +3 -0
  38. package/lib/store/selectors.d.ts +21 -0
  39. package/lib/utils/array.d.ts +61 -0
  40. package/lib/utils/assert-never.d.ts +5 -0
  41. package/lib/utils/debug.d.ts +3 -0
  42. package/lib/utils/decoder.d.ts +51 -0
  43. package/lib/utils/dot-path.d.ts +16 -0
  44. package/lib/utils/form.d.ts +20 -0
  45. package/lib/utils/function.d.ts +71 -0
  46. package/lib/utils/object.d.ts +140 -0
  47. package/lib/utils/random.d.ts +1 -0
  48. package/lib/utils/repeater.d.ts +2 -0
  49. package/lib/utils/suffixable.d.ts +16 -0
  50. package/lib/utils/types.d.ts +63 -0
  51. package/package.json +30 -0
@@ -0,0 +1,121 @@
1
+ import { FormWidget } from '../form-widget';
2
+ import { DotPath, Uid, ValidateOn } from '../shared';
3
+ import { FormHealth } from './model';
4
+ export type INITIALIZE = {
5
+ type: 'INITIALIZE';
6
+ payload: {
7
+ formDef: string | Record<string, any>;
8
+ formName: string;
9
+ };
10
+ };
11
+ /**
12
+ * Sets the data for the entire form.
13
+ */
14
+ export type SET_DATA = {
15
+ type: 'SET_DATA';
16
+ payload: {
17
+ data: Record<string, any>;
18
+ };
19
+ };
20
+ /**
21
+ * Sets the i18n language
22
+ */
23
+ export type SET_LANGUAGE = {
24
+ type: 'SET_LANGUAGE';
25
+ payload: {
26
+ /**
27
+ * The BCP 47 language tag of the current locale (e.g., 'en-US', 'es', 'fr-CA').
28
+ */
29
+ lang: string;
30
+ };
31
+ };
32
+ export type ADD_WIDGET = {
33
+ type: 'ADD_WIDGET';
34
+ payload: {
35
+ widget: FormWidget<string>;
36
+ };
37
+ };
38
+ export type REMOVE_WIDGET = {
39
+ type: 'REMOVE_WIDGET';
40
+ payload: {
41
+ uid: Uid;
42
+ };
43
+ };
44
+ /**
45
+ * Sets the default value for a single form widget.
46
+ */
47
+ export type SET_WIDGET_INITIAL_DATA = {
48
+ type: 'SET_WIDGET_INITIAL_DATA';
49
+ payload: {
50
+ path: DotPath;
51
+ data: any;
52
+ };
53
+ };
54
+ /**
55
+ * Sets the data for a single form widget.
56
+ */
57
+ export type SET_WIDGET_DATA = {
58
+ type: 'SET_WIDGET_DATA';
59
+ payload: {
60
+ path: DotPath;
61
+ data: any;
62
+ };
63
+ };
64
+ /**
65
+ * Overrides a property in a form widget's `props` object.
66
+ */
67
+ export type OVERRIDE_WIDGET_PROP = {
68
+ type: 'OVERRIDE_WIDGET_PROP';
69
+ payload: {
70
+ path: DotPath;
71
+ prop: string;
72
+ value: any;
73
+ };
74
+ };
75
+ export type SET_FORM_HEALTH = {
76
+ type: 'SET_FORM_HEALTH';
77
+ payload: {
78
+ formHealth: FormHealth;
79
+ };
80
+ };
81
+ /**
82
+ * Action type indicating an attempt to validate form data.
83
+ *
84
+ * When dispatched, this action triggers validation for the entire form based on
85
+ * the form's validation configuration. However, validation errors will only be
86
+ * displayed for the specific widget identified by the `path` property, which will
87
+ * be marked as _touched_.
88
+ *
89
+ * The actual validation behavior is determined by the form's configuration and
90
+ * may not execute immediately upon dispatch.
91
+ * ```
92
+ */
93
+ export type ATTEMPT_VALIDATION = {
94
+ type: 'ATTEMPT_VALIDATION';
95
+ payload: {
96
+ reason: Exclude<ValidateOn, any[] | 'eager' | 'submit'>;
97
+ path: DotPath;
98
+ uid: Uid;
99
+ };
100
+ };
101
+ /**
102
+ * Action type that validates all form widgets and marks them as _touched_.
103
+ *
104
+ * When dispatched, this action triggers validation for every widget in the form
105
+ * and marks all widgets as _touched_, causing validation errors to be displayed
106
+ * for all invalid widgets regardless of the form's validation configuration.
107
+ *
108
+ * This action is typically dispatched when the user attempts to submit the form,
109
+ * ensuring all validation errors are visible before submission proceeds.
110
+ */
111
+ export type VALIDATE_ALL = {
112
+ type: 'VALIDATE_ALL';
113
+ };
114
+ export type INJECT_VALIDATION_ISSUES = {
115
+ type: 'INJECT_VALIDATION_ISSUES';
116
+ payload: {
117
+ issues: string[] | null;
118
+ path: DotPath;
119
+ };
120
+ };
121
+ export type Action = INITIALIZE | SET_LANGUAGE | SET_DATA | ADD_WIDGET | REMOVE_WIDGET | SET_WIDGET_INITIAL_DATA | SET_WIDGET_DATA | OVERRIDE_WIDGET_PROP | SET_FORM_HEALTH | INJECT_VALIDATION_ISSUES | ATTEMPT_VALIDATION | VALIDATE_ALL;
@@ -0,0 +1,107 @@
1
+ import { DotPath, Uid, ValidationStatus } from '../shared';
2
+ import * as Form from '../form';
3
+ import * as Widget from '../form-widget';
4
+ export type State = {
5
+ formName: string;
6
+ /**
7
+ * The complete form definition.
8
+ */
9
+ formDef: Form.Form<string>;
10
+ /**
11
+ * Flattened representation of `formDef` as a map from UID to widget definition.
12
+ * Enables more efficient lookup and processing in downstream operations.
13
+ */
14
+ flatForm: Record<Uid, Widget.FormWidget<string>>;
15
+ /**
16
+ * List of states computed for the current form state.
17
+ */
18
+ currentStates: string[];
19
+ /**
20
+ * Tracks widgets whose components have been rendered.
21
+ * A widget is added when its component mounts and removed when it unmounts.
22
+ */
23
+ calculatedWidgets: Record<Uid, DerivedWidget<Widget.FormWidget<string>>>;
24
+ /**
25
+ * Validations statuses derived from the schema validators expressed declaratively.
26
+ *
27
+ * These validation statuses are produced automatically by the configured schema
28
+ * validators (e.g. zod), and are fully managed by the validation engine and should
29
+ * not be mutated directly.
30
+ */
31
+ validations: Record<DotPath, ValidationStatus>;
32
+ /**
33
+ * Tracks controls that have been _touched_ hence can display validation errors.
34
+ */
35
+ touchedControls: Record<DotPath, boolean>;
36
+ /**
37
+ * Validation statuses injected imperatively via the public API.
38
+ *
39
+ * These validation statuses are not derived from the schema validators and are intended
40
+ * for contextual validations that cannot be expressed declaratively.
41
+ */
42
+ injectedValidations: Record<DotPath, ValidationStatus>;
43
+ /**
44
+ * Tracks widgets with state expressions.
45
+ * When data changes, these widgets are updated and their flags recalculated.
46
+ */
47
+ widgetFlags: Record<Uid, {
48
+ hidden?: boolean;
49
+ readonly?: boolean;
50
+ disabled?: boolean;
51
+ }>;
52
+ /**
53
+ * Allows overriding a widget’s `prop` properties externally via its event handler mechanism.
54
+ * For example, this can be used to load options for a select widget asynchronously.
55
+ */
56
+ widgetPropOverrides: Record<Uid, Record<string, any>>;
57
+ data: Record<string, any>;
58
+ /**
59
+ * This reflects whether the form is currently functioning normally
60
+ * or is in an errored state.
61
+ */
62
+ formHealth: FormHealth;
63
+ /**
64
+ * Indicates whether the user has interacted with the form.
65
+ * Set to true when a validateOn-type event occurs on any form control.
66
+ */
67
+ touched: boolean;
68
+ /**
69
+ * The BCP 47 language tag of the current locale (e.g., 'en-US', 'es', 'fr-CA').
70
+ */
71
+ lang: string;
72
+ };
73
+ export declare const createInitialState: (lang: string) => State;
74
+ export type MiddlewareAPI<S, A> = {
75
+ getState: () => S;
76
+ dispatch: (action: A) => void;
77
+ };
78
+ export type Middleware<S, A> = (api: MiddlewareAPI<S, A>) => (next: (action: A) => void) => (action: A) => void;
79
+ /**
80
+ * Represents the current operational state of the form.
81
+ * When in an errored state, the form is considered non-operational
82
+ * until the error is cleared.
83
+ */
84
+ export type FormHealth = {
85
+ status: 'ok';
86
+ } | {
87
+ status: 'errored';
88
+ message: string;
89
+ };
90
+ /**
91
+ * Represents a form widget whose value is derived from a computation
92
+ * and evaluated against its previous derived state.
93
+ *
94
+ * A `DerivedWidget<T>` captures the source widget, the previous derived value,
95
+ * the newly derived value, and whether a structural change occurred between
96
+ * derivations.
97
+ */
98
+ export type DerivedWidget<F extends Widget.FormWidget<string>> = {
99
+ /** The source widget from which the derived value is computed */
100
+ source: F;
101
+ /** The previously derived value */
102
+ previous: Exclude<F, Widget.FunctionWidget<string>>;
103
+ /** The newly derived value */
104
+ current: Exclude<F, Widget.FunctionWidget<string>>;
105
+ /** Indicates whether the newly derived value changed structurally */
106
+ changed?: boolean;
107
+ };
@@ -0,0 +1,10 @@
1
+ import { ValidatorFn } from '../form-validator';
2
+ import { I18nTranslator } from '../i18n';
3
+ import { ValidateOn } from '../shared';
4
+ import { Action } from './actions';
5
+ import { State } from './model';
6
+ export declare const reducer: ({ validators, validateOn, localization, }: {
7
+ validators: ValidatorFn<any>;
8
+ validateOn: ValidateOn;
9
+ localization: I18nTranslator;
10
+ }) => (state: State, action: Action) => State;
@@ -0,0 +1,3 @@
1
+ import { ADD_WIDGET } from '../actions';
2
+ import { State } from '../model';
3
+ export declare function addWidget(state: State, action: ADD_WIDGET): State;
@@ -0,0 +1,2 @@
1
+ import { State } from '../model';
2
+ export declare const calculateCurrentState: (state: State) => State;
@@ -0,0 +1,2 @@
1
+ import { State } from '../model';
2
+ export declare const calculateWidgetFlags: (state: State) => State;
@@ -0,0 +1,3 @@
1
+ import { I18nTranslator } from '../../i18n';
2
+ import { State } from '../model';
3
+ export declare const calculateWidgetProps: (localization: I18nTranslator) => (state: State) => State;
@@ -0,0 +1,13 @@
1
+ export * from './add-widget';
2
+ export * from './calculate-current-state';
3
+ export * from './calculate-widget-flags';
4
+ export * from './calculate-widget-props';
5
+ export * from './initialize';
6
+ export * from './inject-validation-issues';
7
+ export * from './override-widget-prop';
8
+ export * from './remove-widget';
9
+ export * from './set-data';
10
+ export * from './set-widget-data';
11
+ export * from './set-form-health';
12
+ export * from './set-language';
13
+ export * from './validate-all';
@@ -0,0 +1,3 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ export declare const initialize: ({ lang }: State, action: Actions.INITIALIZE) => State;
@@ -0,0 +1,3 @@
1
+ import { INJECT_VALIDATION_ISSUES } from '../actions';
2
+ import { State } from '../model';
3
+ export declare function injectValidationIssues(state: State, action: INJECT_VALIDATION_ISSUES): State;
@@ -0,0 +1,3 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ export declare const overrideWidgetProp: (state: State, { payload }: Actions.OVERRIDE_WIDGET_PROP) => State;
@@ -0,0 +1,3 @@
1
+ import { REMOVE_WIDGET } from '../actions';
2
+ import { State } from '../model';
3
+ export declare function removeWidget(state: State, action: REMOVE_WIDGET): State;
@@ -0,0 +1,3 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ export declare const setData: (state: State, action: Actions.SET_DATA) => State;
@@ -0,0 +1,8 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ /**
4
+ * Updates the operational state of the form.
5
+ * This reflects whether the form is currently functioning normally
6
+ * or is in an errored state.
7
+ */
8
+ export declare const setFormHealth: (state: State, action: Actions.SET_FORM_HEALTH) => State;
@@ -0,0 +1,3 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ export declare const setLanguage: (state: State, action: Actions.SET_LANGUAGE) => State;
@@ -0,0 +1,3 @@
1
+ import { State } from '../model';
2
+ import * as Actions from '../actions';
3
+ export declare const setWidgetData: (state: State, action: Actions.SET_WIDGET_DATA | Actions.SET_WIDGET_INITIAL_DATA) => State;
@@ -0,0 +1,32 @@
1
+ import { DotPath } from '../../shared';
2
+ import { State } from '../model';
3
+ /**
4
+ * Conditionally applies a reducer function based on a predicate
5
+ *
6
+ * This higher-order reducer creates a new reducer that only applies the given
7
+ * reducer function when the predicate function returns true for the current state.
8
+ * If the predicate returns false, the state is returned unchanged.
9
+ *
10
+ * @param predicate - A function that takes the current state and returns a boolean
11
+ * indicating whether the reducer should be applied
12
+ * @param reducerFn - The reducer function to apply when the predicate returns true
13
+ *
14
+ * @returns A new reducer function that conditionally applies the given reducer
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // Only increment if count is less than 10
19
+ * const conditionalIncrement = reduceIf(
20
+ * (state: { count: number }) => state.count < 10,
21
+ * (state) => ({ ...state, count: state.count + 1 })
22
+ * );
23
+ *
24
+ * conditionalIncrement({ count: 5 }); // returns { count: 6 }
25
+ * conditionalIncrement({ count: 10 }); // returns { count: 10 } (unchanged)
26
+ * ```
27
+ */
28
+ export declare const reduceIf: (predicate: (state: State) => boolean, reducerFn: (state: State) => State) => (state: State) => State;
29
+ export declare const isControlTouched: (widgetPath: DotPath) => (state: State) => boolean;
30
+ export declare const hasWhen: (val: unknown) => val is {
31
+ when: string;
32
+ };
@@ -0,0 +1,3 @@
1
+ import { ValidatorFn } from '../../form-validator';
2
+ import { State } from '../model';
3
+ export declare const validateAll: (validators: ValidatorFn<any>) => (state: State) => State;
@@ -0,0 +1,21 @@
1
+ import { Observable } from 'rxjs';
2
+ import { LayoutWidget } from '../form-widget';
3
+ import { DotPath, Uid } from '../shared';
4
+ import { State } from './model';
5
+ export declare const dataByPath$: <T = any>(path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<T>>;
6
+ export declare const validationByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<import('../shared').ValidationStatus>>;
7
+ export declare const injectedValidationByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<import('../shared').ValidationStatus>>;
8
+ export declare const calculatedWidgetsByUid$: (uid: Uid) => import('rxjs').UnaryFunction<Observable<State>, Observable<import('../form-widget').NonFunctionWidget<string, any, any>>>;
9
+ export declare const calculatedLayoutChildrenByUid$: (uid: Uid) => import('rxjs').UnaryFunction<Observable<State>, Observable<(import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, (import('../form-widget').DisplayWidget<never, any, any> | import('../form-widget').InputWidget<any, never, any, any, any> | LayoutWidget<never, any, any, /*elided*/ any> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]> | import('../form-widget').ActionWidget<never, any, any> | import('../form-widget').FunctionWidget<never, any, any>)[]>>;
10
+ export declare const selectWidgetFlags: import('rxjs').UnaryFunction<Observable<State>, Observable<Record<string, {
11
+ hidden?: boolean;
12
+ readonly?: boolean;
13
+ disabled?: boolean;
14
+ }>>>;
15
+ export declare const widgetFlagsByUid$: (uid: Uid) => import('rxjs').UnaryFunction<Observable<State>, Observable<{
16
+ hidden?: boolean;
17
+ readonly?: boolean;
18
+ disabled?: boolean;
19
+ }>>;
20
+ export declare const touchedControlsByPath$: (path: DotPath) => import('rxjs').UnaryFunction<Observable<State>, Observable<boolean>>;
21
+ export declare const formHealth: (store: Observable<State>) => Observable<import('./model').FormHealth>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Unique marker value used to explicitly indicate that an element
3
+ * should be skipped by {@link filterMap}.
4
+ *
5
+ * This is a stable singleton and does not allocate per iteration.
6
+ */
7
+ export declare const SKIP: unique symbol;
8
+ /**
9
+ * Applies a mapping function to each element of an array and collects
10
+ * only the values that are not {@link SKIP}.
11
+ *
12
+ * This combines `map` and `filter` in a single pass without allocating
13
+ * intermediate arrays or sentinel objects.
14
+ *
15
+ * @typeParam T - The type of the input array elements.
16
+ * @typeParam U - The type of the mapped output elements.
17
+ *
18
+ * @param array - The source array to iterate over.
19
+ * @param fn - A function that maps each element to a value of type `U`,
20
+ * or returns {@link SKIP} to exclude the element from the result.
21
+ *
22
+ * @returns A new array containing only the mapped values.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const result = filterMap([1, 2, 3, 4], n =>
27
+ * n % 2 === 0 ? String(n) : SKIP
28
+ * );
29
+ * // result: ["2", "4"]
30
+ * ```
31
+ */
32
+ export declare function filterMap<T, U>(array: readonly T[], fn: (value: T, index: number, array: readonly T[]) => U | typeof SKIP): U[];
33
+ /**
34
+ * Compares two arrays for structural equality by applying a predicate
35
+ * to each pair of elements.
36
+ *
37
+ * The function:
38
+ * - Fails fast if array lengths differ
39
+ * - Iterates in a single pass
40
+ * - Short-circuits immediately when the predicate returns `false`
41
+ *
42
+ * @param a - First array.
43
+ * @param b - Second array.
44
+ * @param predicate - A function invoked for each pair of elements.
45
+ * It must return `true` if the elements are considered equal, or `false`
46
+ * to terminate early and indicate inequality.
47
+ *
48
+ * @returns `true` if arrays are structurally equal according to the
49
+ * predicate; otherwise `false`.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const equal = zipEvery(
54
+ * [1, 2, 3],
55
+ * [1, 2, 3],
56
+ * (a, b) => a === b
57
+ * );
58
+ * // true
59
+ * ```
60
+ */
61
+ export declare function zipEvery<A, B>(a: readonly A[], b: readonly B[], predicate: (aValue: A, bValue: B, index: number, a: readonly A[], b: readonly B[]) => boolean): boolean;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Ensures exhaustiveness in compile-time checks and throws at runtime
3
+ * if an unhandled case is encountered.
4
+ */
5
+ export declare const assertNever: (value: never) => never;
@@ -0,0 +1,3 @@
1
+ export declare const Debug: {
2
+ log: <T>(value: T, label?: string) => T;
3
+ };
@@ -0,0 +1,51 @@
1
+ import * as jd from 'ts.data.json';
2
+ export type KeySpec<A> = Record<string, {
3
+ suffixed?: boolean;
4
+ decoder: jd.Decoder<A>;
5
+ }>;
6
+ /**
7
+ * Creates a JSON decoder for objects whose keys are validated against a
8
+ * specification map.
9
+ *
10
+ * Each entry in `specs` defines:
11
+ * - the base key name
12
+ * - whether the key may appear with dot-suffixed variants
13
+ * - the decoder used to validate the corresponding values
14
+ *
15
+ * Matching rules:
16
+ * - If `suffixed` is `false`, only the exact key is accepted.
17
+ * - If `suffixed` is `true`, both the base key and any keys starting with
18
+ * `<key>.` are accepted.
19
+ * - Any object key that does not match one of the specifications causes
20
+ * decoding to fail.
21
+ *
22
+ * All values are decoded independently using the decoder associated with the
23
+ * matched key. Decoded values are returned under their original object keys
24
+ * (including suffixes).
25
+ *
26
+ * @typeParam T - The resulting object shape after successful decoding.
27
+ *
28
+ * @param specs - A map of base keys to their decoding specification.
29
+ * @param decoderName - Human-readable name used in error messages.
30
+ *
31
+ * @returns A `jd.Decoder` that validates and decodes objects according to the
32
+ * provided key specifications.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const decoder = objectWithSuffix<Record<string, string>>(
37
+ * {
38
+ * label: { suffixed: true, decoder: jd.string() },
39
+ * title: { suffixed: false, decoder: jd.string() },
40
+ * },
41
+ * 'MyObj',
42
+ * );
43
+ *
44
+ * decoder.decode({
45
+ * label: 'Submit',
46
+ * 'label.register': 'Register',
47
+ * title: 'Form',
48
+ * });
49
+ * ```
50
+ */
51
+ export declare function objectWithSuffix<T extends Record<string, any>>(specs: KeySpec<any>, decoderName: string): jd.Decoder<T>;
@@ -0,0 +1,16 @@
1
+ import { DotPath } from '../shared';
2
+ /**
3
+ * Heuristically checks if a value looks like a dot notation path
4
+ * rather than a standard string.
5
+ * To be considered a "potential" dot path, the value must:
6
+ * 1. Be a string.
7
+ * 2. Start with one of the allowed prefixes ($form.*, $error.* or $meta.*).
8
+ * 3. Not contain any spaces (distinguishing it from sentences).
9
+ *
10
+ * * @example
11
+ * isPotentialDotPath('$form.user.id'); // true
12
+ * isPotentialDotPath('name'); // false (No prefix)
13
+ * isPotentialDotPath('my file'); // false (Contains space)
14
+ * isPotentialDotPath(123); // false (Not a string)
15
+ */
16
+ export declare const isPotentialDotPath: (path: unknown) => path is DotPath;
@@ -0,0 +1,20 @@
1
+ import * as Widget from '../form-widget';
2
+ /**
3
+ * Flattens the hierarchical form structure into a single-level array of form widgets.
4
+ *
5
+ * @returns A flattened array of all form widgets, including nested ones from layout widgets
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const hierarchicalWidgets = [
10
+ * { type: 'text', name: 'firstName' },
11
+ * { type: 'layout', children: [
12
+ * { type: 'text', name: 'street' },
13
+ * { type: 'text', name: 'city' }
14
+ * ]}
15
+ * ];
16
+ * const flatWidgets = flattenForm(hierarchicalWidgets);
17
+ * // Result: [firstName, layout, street, city]
18
+ * ```
19
+ */
20
+ export declare function flattenForm(widgets: Widget.FormWidget[]): Widget.FormWidget[];
@@ -0,0 +1,71 @@
1
+ /**
2
+ * A function type that transforms a value of type A to type B
3
+ */
4
+ type Func<A, B> = (arg: A) => B;
5
+ /**
6
+ * Performs left-to-right function composition (pipeline).
7
+ * The output of each function is passed as input to the next function.
8
+ *
9
+ * @typeParam A - The initial value type
10
+ * @param value - The initial value to pipe through the functions
11
+ * @param fns - Functions to apply in sequence
12
+ * @returns The result after applying all functions
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const addOne = (x: number) => x + 1;
17
+ * const double = (x: number) => x * 2;
18
+ * const toString = (x: number) => `Result: ${x}`;
19
+ *
20
+ * const result = pipe(5, addOne, double, toString); // 5 -> 6 -> 12 -> "Result: 12"
21
+ * ```
22
+ */
23
+ declare function pipe<A>(value: A): A;
24
+ /** @see {@link pipe} */
25
+ declare function pipe<A, B>(value: A, fn1: Func<A, B>): B;
26
+ /** @see {@link pipe} */
27
+ declare function pipe<A, B, C>(value: A, fn1: Func<A, B>, fn2: Func<B, C>): C;
28
+ /** @see {@link pipe} */
29
+ declare function pipe<A, B, C, D>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>): D;
30
+ /** @see {@link pipe} */
31
+ declare function pipe<A, B, C, D, E>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>): E;
32
+ /** @see {@link pipe} */
33
+ declare function pipe<A, B, C, D, E, F>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>): F;
34
+ /** @see {@link pipe} */
35
+ declare function pipe<A, B, C, D, E, F, G>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>, fn6: Func<F, G>): G;
36
+ /** @see {@link pipe} */
37
+ declare function pipe<A, B, C, D, E, F, G, H>(value: A, fn1: Func<A, B>, fn2: Func<B, C>, fn3: Func<C, D>, fn4: Func<D, E>, fn5: Func<E, F>, fn6: Func<F, G>, fn7: Func<G, H>): H;
38
+ /**
39
+ * Performs right-to-left function composition.
40
+ * The output of each function is passed as input to the previous function.
41
+ *
42
+ * @typeParam A - The input type of the composed function
43
+ * @returns A new function that applies all the given functions from right to left
44
+ *
45
+ * @example
46
+ * Basic composition
47
+ * ```typescript
48
+ * const addOne = (x: number) => x + 1;
49
+ * const double = (x: number) => x * 2;
50
+ * const toString = (x: number) => `Result: ${x}`;
51
+ *
52
+ * const transform = compose(toString, double, addOne); // Applies: addOne -> double -> toString
53
+ * console.log(transform(5)); // "Result: 12"
54
+ * ```
55
+ */
56
+ declare function compose<A>(fn1: Func<A, A>): Func<A, A>;
57
+ /** @see {@link compose} */
58
+ declare function compose<A, B>(fn1: Func<A, B>, fn2: Func<B, A>): Func<B, B>;
59
+ /** @see {@link compose} */
60
+ declare function compose<A, B, C>(fn1: Func<B, C>, fn2: Func<A, B>): Func<A, C>;
61
+ /** @see {@link compose} */
62
+ declare function compose<A, B, C, D>(fn1: Func<C, D>, fn2: Func<B, C>, fn3: Func<A, B>): Func<A, D>;
63
+ /** @see {@link compose} */
64
+ declare function compose<A, B, C, D, E>(fn1: Func<D, E>, fn2: Func<C, D>, fn3: Func<B, C>, fn4: Func<A, B>): Func<A, E>;
65
+ /** @see {@link compose} */
66
+ declare function compose<A, B, C, D, E, F>(fn1: Func<E, F>, fn2: Func<D, E>, fn3: Func<C, D>, fn4: Func<B, C>, fn5: Func<A, B>): Func<A, F>;
67
+ /** @see {@link compose} */
68
+ declare function compose<A, B, C, D, E, F, G>(fn1: Func<F, G>, fn2: Func<E, F>, fn3: Func<D, E>, fn4: Func<C, D>, fn5: Func<B, C>, fn6: Func<A, B>): Func<A, G>;
69
+ /** @see {@link compose} */
70
+ declare function compose<A, B, C, D, E, F, G, H>(fn1: Func<G, H>, fn2: Func<F, G>, fn3: Func<E, F>, fn4: Func<D, E>, fn5: Func<C, D>, fn6: Func<B, C>, fn7: Func<A, B>): Func<A, H>;
71
+ export { compose, pipe };