react-luna-form 0.0.86 → 0.0.88
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 +15 -10
- package/dist/client/cjs/index.js +2 -1
- package/dist/client/esm/index.js +2 -1
- package/dist/config/cjs/index.js +1 -1
- package/dist/config/esm/index.js +1 -1
- package/dist/schema/cjs/index.js +1 -1
- package/dist/schema/esm/index.js +1 -1
- package/dist/server/cjs/index.js +1 -1
- package/dist/server/esm/index.js +1 -1
- package/dist/types/luna-core/handle/source-event.d.ts +2 -1
- package/dist/types/luna-core/handle/value-event.d.ts +2 -1
- package/dist/types/luna-core/helper/input.d.ts +16 -7
- package/dist/types/luna-core/type.d.ts +15 -4
- package/dist/types/luna-core/util/constant.d.ts +4 -0
- package/dist/types/luna-core/util/date.d.ts +132 -6
- package/dist/types/luna-core/util/extract.d.ts +21 -0
- package/dist/types/luna-core/util/format.d.ts +11 -0
- package/dist/types/luna-core/util/is-input.d.ts +3 -2
- package/dist/types/luna-core/util/pattern.d.ts +28 -0
- package/dist/types/luna-core/util/prepare.d.ts +3 -2
- package/dist/types/luna-core/util/schema.d.ts +2 -1
- package/dist/types/luna-core/util/string.d.ts +7 -0
- package/dist/types/luna-react/src/client/component/field/field-list-preview-item.d.ts +3 -3
- package/dist/types/luna-react/src/client/component/field/field-preview-item.d.ts +4 -2
- package/dist/types/luna-react/src/client/component/field/field-preview-value.d.ts +4 -1
- package/dist/types/luna-react/src/client/component/field/field-preview.d.ts +6 -4
- package/dist/types/luna-react/src/{component → client/component}/field/field-set-advanced.d.ts +1 -1
- package/dist/types/luna-react/src/client/component/field/field-set.d.ts +11 -0
- package/dist/types/luna-react/src/client/component/field/field.d.ts +20 -11
- package/dist/types/luna-react/src/client/component/field-description.d.ts +2 -0
- package/dist/types/luna-react/src/{component → client/component}/formatted-description.d.ts +3 -3
- package/dist/types/luna-react/src/client/component/guard/list-guard.d.ts +1 -1
- package/dist/types/luna-react/src/client/component/input-strategies.d.ts +10 -2
- package/dist/types/luna-react/src/client/component/slot/slot.d.ts +1 -2
- package/dist/types/luna-react/src/client/hook/use-entry-atom.d.ts +18 -0
- package/dist/types/luna-react/src/client/hook/use-input-core.d.ts +4 -4
- package/dist/types/luna-react/src/client/hook/use-latest.d.ts +22 -0
- package/dist/types/luna-react/src/client/hook/use-live-item-value.d.ts +17 -3
- package/dist/types/luna-react/src/client/hook/use-value.d.ts +1 -1
- package/dist/types/luna-react/src/client/lib/error-store.d.ts +3 -4
- package/dist/types/luna-react/src/client/lib/host-value-store.d.ts +13 -15
- package/dist/types/luna-react/src/client/lib/list-store.d.ts +0 -2
- package/dist/types/luna-react/src/client/lib/resolve-value.d.ts +0 -5
- package/dist/types/luna-react/src/client/lib/source-store.d.ts +7 -4
- package/dist/types/luna-react/src/client/lib/state-store.d.ts +0 -4
- package/dist/types/luna-react/src/client/lib/store-helper.d.ts +5 -15
- package/dist/types/luna-react/src/client/lib/value-store.d.ts +0 -4
- package/dist/types/luna-react/src/component/column.d.ts +4 -2
- package/dist/types/luna-react/src/component/description.d.ts +9 -0
- package/dist/types/luna-react/src/component/field/field-list.d.ts +2 -3
- package/dist/types/luna-react/src/component/field/{field-set.d.ts → field-set-static.d.ts} +1 -1
- package/dist/types/luna-react/src/component/field/field.d.ts +4 -4
- package/dist/types/luna-react/src/component/field-description.d.ts +5 -4
- package/dist/types/luna-react/src/component/form.d.ts +10 -0
- package/dist/types/luna-react/src/component/input/input-base.d.ts +3 -3
- package/dist/types/luna-react/src/component/input-group.d.ts +4 -2
- package/dist/types/luna-react/src/component/input-label.d.ts +4 -2
- package/dist/types/luna-react/src/component/slot/list-slot.d.ts +1 -1
- package/dist/types/luna-react/src/component/slot/slot-base.d.ts +4 -3
- package/dist/types/luna-react/src/component/slot/slot-create.d.ts +2 -3
- package/dist/types/luna-react/src/component/slot/slot-list.d.ts +2 -3
- package/dist/types/luna-react/src/component/slot/slot.d.ts +1 -2
- package/dist/types/luna-react/src/config/index.d.ts +1 -0
- package/dist/types/luna-react/src/lib/visibility.d.ts +3 -0
- package/dist/types/luna-react/src/server/component/field.d.ts +2 -0
- package/dist/types/luna-react/src/server/component/input.d.ts +2 -2
- package/dist/types/luna-react/src/server/component/list-slot.d.ts +2 -0
- package/dist/types/luna-react/src/server/component/slot.d.ts +14 -0
- package/dist/types/luna-react/src/type.d.ts +2 -1
- package/docs/events/change.md +4 -1
- package/docs/fields/custom-inputs.md +153 -4
- package/docs/fields/data-source.md +5 -3
- package/docs/fields/input.md +175 -3
- package/docs/fields/list.md +1 -1
- package/docs/fields/specialized-selectors.md +51 -12
- package/docs/forms/submit.md +13 -14
- package/docs/index.md +2 -1
- package/docs/interpolation/format-filters.md +28 -29
- package/docs/interpolation/overview.md +44 -14
- package/docs/setup.md +56 -35
- package/docs/structure/definition.md +45 -6
- package/docs/validation/overview.md +15 -12
- package/package.json +5 -5
- package/dist/types/luna-react/src/client/component/field/field-with-state.d.ts +0 -13
- package/dist/types/luna-react/src/client/hook/use-format.d.ts +0 -5
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DATA_FORMAT, DATA_MODE, DATA_RESERVED, MAX, MIN } from './constant';
|
|
2
|
+
import type { Locale } from 'date-fns';
|
|
3
|
+
import type { Date as DateField, DateFormat, Input, Select, Time, TimeFormat, TimezoneGroup } from '../type';
|
|
4
|
+
/**
|
|
5
|
+
* The language a form writes its months, days, numbers, dates and dictionary
|
|
6
|
+
* in: its `lang`, as a canonical tag, and English without one, for one that is
|
|
7
|
+
* no tag, or for one the runtime knows no language for. It is the one reading
|
|
8
|
+
* of the language, so everything the form writes agrees on it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function toLocale(locale?: string): string;
|
|
11
|
+
/** The base language of a form's language: `es` for `es-CO`. */
|
|
12
|
+
export declare function baseLanguage(locale?: string): string;
|
|
2
13
|
export declare function getMonth(locale?: string): {
|
|
3
14
|
value: string;
|
|
4
15
|
label: string;
|
|
@@ -11,13 +22,128 @@ export declare function getYear(min: number, max: number): Array<{
|
|
|
11
22
|
value: string;
|
|
12
23
|
label: string;
|
|
13
24
|
}>;
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
export type YearLimits = Readonly<{
|
|
26
|
+
max?: number;
|
|
27
|
+
min?: number;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* The first and the last year a year select offers, both included: whole
|
|
31
|
+
* numbers, the way an `input/number` takes its bounds, or a `$ref` the host
|
|
32
|
+
* resolved to one. The library keeps no clock, so "this year" is the host's to
|
|
33
|
+
* say, through `context`, and a field without both bounds offers no year.
|
|
34
|
+
*
|
|
35
|
+
* Read once for the options the component is handed and for the schema that
|
|
36
|
+
* checks a year, so the two cannot disagree. It takes an `Input` as well,
|
|
37
|
+
* which is what the schema sees every field as.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildYearLimits(field: Input | Select): YearLimits;
|
|
40
|
+
/**
|
|
41
|
+
* The zone a timezone select suggests, as its definition gives it in
|
|
42
|
+
* `advanced.suggested`: the host knows it -- a profile, a cookie, a header --
|
|
43
|
+
* and passes it through `context`, so the server and the browser suggest the
|
|
44
|
+
* same one. It is read as the name the runtime gives it, and a value that is no
|
|
45
|
+
* zone suggests nothing, which a development build names.
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildSuggestedZone(field: Select): string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* An instant as the host gives it in `context.now`: an ISO date, time and
|
|
50
|
+
* offset, such as `2026-10-05T19:30:00-05:00` or `2026-10-06T00:30:00Z`.
|
|
51
|
+
* Without its offset a time would be read in this machine's zone, which is the
|
|
52
|
+
* clock the form keeps no more, so anything else is no instant.
|
|
53
|
+
*/
|
|
54
|
+
export declare function readInstant(text?: string): Date | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Every zone this engine knows, grouped by region, with the one the host
|
|
57
|
+
* suggests first. Labelled for the instant the host gives, `context.now`: the
|
|
58
|
+
* offset a zone has, and the name it goes by, both depend on it, so without one
|
|
59
|
+
* a zone goes by its city. Nothing here reads this machine's clock or zone.
|
|
60
|
+
*
|
|
61
|
+
* Built once while the zone and the instant hold: a timezone select builds its
|
|
62
|
+
* options on every render, and there are hundreds of zones. Frozen, since every
|
|
63
|
+
* form that asks shares it, on a server every request. `suggested` is a zone's
|
|
64
|
+
* name as the runtime gives it, as `buildSuggestedZone` reads it. Sorted in
|
|
65
|
+
* English, the language of the labels, so no machine's collation orders it.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getTimezones(suggested?: string, now?: string): readonly TimezoneGroup[];
|
|
18
68
|
export declare function toNativeDate(value: string, fromFormat: DateFormat): string;
|
|
19
69
|
export declare function toNativeTime(value: string, fromFormat: TimeFormat): string;
|
|
20
70
|
export declare function fromNativeTime(native: string, toFormat?: TimeFormat): string;
|
|
21
|
-
export declare function
|
|
71
|
+
export declare function displayDate(value: string, format: DateFormat, lang?: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* The date-fns locale for a language, by its base: `es-CO` writes Spanish
|
|
74
|
+
* names. English for a language the library does not ship.
|
|
75
|
+
*/
|
|
76
|
+
export declare function dateFnsLocale(lang?: string): Locale | undefined;
|
|
22
77
|
export declare function getTimeFormat(field: Time): TimeFormat;
|
|
23
78
|
export declare function getDateFormat(field: DateField): DateFormat;
|
|
79
|
+
export type DateLimits = Readonly<{
|
|
80
|
+
max?: string;
|
|
81
|
+
min?: string;
|
|
82
|
+
reserved: readonly string[];
|
|
83
|
+
unreadable: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
type DateBound = 'max' | 'min';
|
|
86
|
+
export type DateIssue = Readonly<{
|
|
87
|
+
issue: DateBound;
|
|
88
|
+
limit: string;
|
|
89
|
+
}> | Readonly<{
|
|
90
|
+
issue: 'range';
|
|
91
|
+
}> | Readonly<{
|
|
92
|
+
issue: 'reserved';
|
|
93
|
+
}> | Readonly<{
|
|
94
|
+
issue: 'unreadable';
|
|
95
|
+
}>;
|
|
96
|
+
/**
|
|
97
|
+
* The days a date field allows: the first and the last, both included, and
|
|
98
|
+
* the ones nobody may pick. Read once for the props its component is handed and
|
|
99
|
+
* for the schema that checks it, so the two cannot disagree.
|
|
100
|
+
*
|
|
101
|
+
* It is the one place the limits are read, on the server and in the browser, so
|
|
102
|
+
* it is where one that limits nothing is named for whoever wrote the form.
|
|
103
|
+
*/
|
|
104
|
+
export declare function buildDateLimits(field: DateField): DateLimits;
|
|
105
|
+
export declare function checkDay(day: string, limits: DateLimits): DateIssue | null;
|
|
106
|
+
/**
|
|
107
|
+
* A range as the form holds it, `[from, to]`, with `''` for an end nobody
|
|
108
|
+
* picked: the pair a calendar emits or the two hidden inputs a form submits,
|
|
109
|
+
* and one text alone as the first end. Anything else -- numbers, an object, a
|
|
110
|
+
* list of more than two -- is no range, and comes back `undefined`, so it is
|
|
111
|
+
* held back for what it is instead of being taken for a range nobody picked.
|
|
112
|
+
*/
|
|
113
|
+
export declare function toRange(value: unknown): [string, string] | undefined;
|
|
114
|
+
export declare function checkRange(from: string, to: string, limits: DateLimits): DateIssue | null;
|
|
115
|
+
export type DateProps = Readonly<{
|
|
116
|
+
format: DateFormat;
|
|
117
|
+
lang: string;
|
|
118
|
+
max?: string;
|
|
119
|
+
min?: string;
|
|
120
|
+
mode: 'range' | 'single';
|
|
121
|
+
reserved: readonly string[];
|
|
122
|
+
}>;
|
|
123
|
+
/**
|
|
124
|
+
* What a date component reads back from the props the form gave it: the format
|
|
125
|
+
* to show a day in, whether it picks one day or a range, the first and the last
|
|
126
|
+
* day it may offer, and the days it may not, all as `yyyy-MM-dd`.
|
|
127
|
+
*
|
|
128
|
+
* The form writes a date field's rules as attributes, so a native input and a
|
|
129
|
+
* calendar from any library can both carry them; this is the other half, and
|
|
130
|
+
* it lives here so an adapter never decodes an attribute the form chose how
|
|
131
|
+
* to encode.
|
|
132
|
+
*/
|
|
133
|
+
export declare function readDateProps(props: Readonly<{
|
|
134
|
+
[DATA_FORMAT]?: string;
|
|
135
|
+
[DATA_MODE]?: string;
|
|
136
|
+
[DATA_RESERVED]?: string;
|
|
137
|
+
[MAX]?: string;
|
|
138
|
+
[MIN]?: string;
|
|
139
|
+
lang?: string;
|
|
140
|
+
}>): DateProps;
|
|
141
|
+
/**
|
|
142
|
+
* What a reader worked out for a key, kept while it is among the last `limit`
|
|
143
|
+
* keys read, the one read longest ago dropped first: what a component reads on
|
|
144
|
+
* every render is worked out once while its input holds, whatever other forms
|
|
145
|
+
* read between, and a server that sees a new input on every request holds no
|
|
146
|
+
* more than that.
|
|
147
|
+
*/
|
|
148
|
+
export declare function remember<T>(cache: Map<string, T>, key: string, compute: () => T, limit: number): T;
|
|
149
|
+
export {};
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import type { Nullable, Option, Value } from '../type';
|
|
2
2
|
export declare function hasOwn(value: object, key: string): boolean;
|
|
3
|
+
export type Entry = {
|
|
4
|
+
found: boolean;
|
|
5
|
+
value: unknown;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The one walk of a dotted path, for every reader of one.
|
|
9
|
+
*
|
|
10
|
+
* A flat key that is literally the path wins, because that is how the form
|
|
11
|
+
* keeps a list's leaves -- `items.0.name` is a key, not a route -- and a
|
|
12
|
+
* definition is free to name a field the same way. Then objects by key and
|
|
13
|
+
* arrays by numeric index.
|
|
14
|
+
*
|
|
15
|
+
* There were two of these, one per package, and they disagreed about that first
|
|
16
|
+
* step: a list named `config.items` was found by the reader in luna-react and
|
|
17
|
+
* not by the one here, so whether a form hydrated depended on which one the
|
|
18
|
+
* caller happened to use. `extract` and `resolveValue` are both this now.
|
|
19
|
+
*
|
|
20
|
+
* Every step asks `hasOwn`, so an inherited member is not a value and a name
|
|
21
|
+
* that reaches a prototype resolves to nothing. See SEG-2.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveEntry(name: string, currentValue: Record<string, unknown> | unknown[]): Entry;
|
|
3
24
|
export declare function getEntity<T>(selected: Value, collection?: Nullable<T[]>, entity?: string): NonNullable<T> | {
|
|
4
25
|
value: import("..").Multiple;
|
|
5
26
|
} | {
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
export type FormatContext = {
|
|
2
2
|
locale?: string;
|
|
3
|
+
now?: string;
|
|
3
4
|
};
|
|
4
5
|
export type FormatFilter = (value: unknown, args: string[], ctx: FormatContext) => string;
|
|
6
|
+
/**
|
|
7
|
+
* `context.now`, the one key of the host's `context` the library reads on its
|
|
8
|
+
* own: the instant a relative date is measured from and a time zone's offset is
|
|
9
|
+
* given for. The library keeps no clock, so without it there is no "now".
|
|
10
|
+
*
|
|
11
|
+
* Only an ISO date, time and offset is an instant. A `Date`, a timestamp or a
|
|
12
|
+
* time without its offset is none, and a development build names it once for
|
|
13
|
+
* the context that carries it, since nothing on the form says so otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readNow(context?: Record<string, unknown>): string | undefined;
|
|
5
16
|
export declare const formatFilters: Record<string, FormatFilter>;
|
|
6
17
|
export declare function applyFormatFilter(value: unknown, expression: string, ctx: FormatContext): string | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Chips, Column, Field, Input, List, Nullable, Select, Time } from '../type';
|
|
1
|
+
import type { Chips, Column, Date as DateField, Field, Input, List, Nullable, Select, Time } from '../type';
|
|
2
2
|
export declare const isSelectActive: (field: Field) => boolean;
|
|
3
3
|
export declare const isSelectDay: (field: Field) => boolean;
|
|
4
4
|
export declare const isSelectMonth: (field: Field) => boolean;
|
|
@@ -6,8 +6,9 @@ export declare const isSelectYear: (field: Field) => boolean;
|
|
|
6
6
|
export declare const isSelectTimezone: (field: Field) => boolean;
|
|
7
7
|
export declare const isChipsDays: (field: Field) => boolean;
|
|
8
8
|
export declare const isChipsMonths: (field: Field) => boolean;
|
|
9
|
-
export declare const isDate: (field: Field) => field is
|
|
9
|
+
export declare const isDate: (field: Field) => field is DateField;
|
|
10
10
|
export declare const isTime: (field: Field) => field is Time;
|
|
11
|
+
export declare function isDateRange(field: Field): boolean;
|
|
11
12
|
export declare const isCheckbox: (field: Field) => field is Input;
|
|
12
13
|
export declare const isChips: (field: Field) => field is Chips;
|
|
13
14
|
export declare const isRadio: (field: Field) => field is Select;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an authored pattern can do to the thread that runs it.
|
|
3
|
+
*
|
|
4
|
+
* A pattern that can split the same text between its repetitions in more than
|
|
5
|
+
* one way backtracks exponentially on a value that almost matches: `^(a+)+$`
|
|
6
|
+
* holds the thread for seconds on thirty characters, a tab's or a server's.
|
|
7
|
+
* Only the ambiguity is dangerous. `^[a-z]+(-[a-z]+)*$` repeats a group with a
|
|
8
|
+
* quantifier inside it as well, and runs in linear time, because every
|
|
9
|
+
* repetition opens with a `-` that the one before cannot close with.
|
|
10
|
+
*
|
|
11
|
+
* So the question asked of each repeated group is not whether it nests a
|
|
12
|
+
* quantifier but whether its repetitions can overlap: whether the group can
|
|
13
|
+
* open with a character it can also close with, and then either holds an
|
|
14
|
+
* unbounded quantifier or offers alternatives that open alike. That is
|
|
15
|
+
* `(a+)+`, `(\w+\s?)+` and `(a|a)+`, and not `(-[a-z]+)*`, `(,\d+)*` or
|
|
16
|
+
* `(ab+c)+`.
|
|
17
|
+
*
|
|
18
|
+
* It is a reading of the source, not a proof. Characters are reasoned about as
|
|
19
|
+
* ASCII, with everything beyond it counted as one more symbol, and what the
|
|
20
|
+
* reader cannot tell apart it reads as any character: it would rather refuse
|
|
21
|
+
* a safe pattern than run a catastrophic one. Quadratic patterns are not its
|
|
22
|
+
* concern; they need very long values to hurt.
|
|
23
|
+
*
|
|
24
|
+
* Every term works out what it can open and close with as it is read, once,
|
|
25
|
+
* so reading a pattern costs time in proportion to its length, however it
|
|
26
|
+
* nests.
|
|
27
|
+
*/
|
|
28
|
+
export declare function backtracksCatastrophically(source: string, flags?: string): boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Definition, Filterable, Nullable } from '../type';
|
|
2
|
-
export declare function prepare<T extends Filterable>(base?: readonly T[], definition?: Definition):
|
|
3
|
-
export declare function resolveRefs(base: unknown, definition?: Definition,
|
|
2
|
+
export declare function prepare<T extends Filterable>(base?: readonly T[], definition?: Definition, context?: Record<string, unknown>): T[];
|
|
3
|
+
export declare function resolveRefs(base: unknown, definition?: Definition, context?: Record<string, unknown>): unknown;
|
|
4
|
+
export declare function refOf(value: unknown): string | undefined;
|
|
4
5
|
export declare function entries<T>(values?: Nullable<Record<string, T>>): [key: string, value: T][];
|
|
@@ -8,9 +8,10 @@ export declare function getText(input: Input, translations?: Record<string, stri
|
|
|
8
8
|
export declare function getNumber(input: Input, translations?: Record<string, string>): z.ZodPreprocess<z.ZodOptional<z.ZodNullable<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>>, unknown> | z.ZodPreprocess<z.ZodPipe<z.ZodUnknown, z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>, unknown>;
|
|
9
9
|
export declare function getYearSchema(input: Input, translations?: Record<string, string>): z.ZodPreprocess<z.ZodOptional<z.ZodNullable<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>>, unknown> | z.ZodPreprocess<z.ZodPipe<z.ZodUnknown, z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>, unknown>;
|
|
10
10
|
export declare function getMonthSchema(input: Input, translations?: Record<string, string>): z.ZodPreprocess<z.ZodOptional<z.ZodNullable<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>>, unknown> | z.ZodPreprocess<z.ZodPipe<z.ZodUnknown, z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>>, unknown>;
|
|
11
|
+
export declare function getDateSchema(field: Field, translations?: Record<string, string>): z.ZodPreprocess<z.ZodOptional<z.ZodNullable<z.ZodType<[string, string], unknown, z.core.$ZodTypeInternals<[string, string], unknown>>>>, unknown> | z.ZodPreprocess<z.ZodPipe<z.ZodUnknown, z.ZodType<[string, string], unknown, z.core.$ZodTypeInternals<[string, string], unknown>>>, unknown> | z.ZodPreprocess<z.ZodOptional<z.ZodNullable<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>>, unknown> | z.ZodPreprocess<z.ZodPipe<z.ZodUnknown, z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>, unknown>;
|
|
11
12
|
export declare function applyCustomValidation(schema: ZodSchema, fields?: Field[], translations?: Record<string, string>): ZodSchema;
|
|
12
13
|
export declare function validateCustom(value: unknown, rules: CustomValidation | Array<CustomValidation>, getValue: (name: string) => unknown, translations?: Record<string, string>): string[];
|
|
13
|
-
export declare function buildFormSchema(sections: Sections, translations?: Record<string, string>, definition?: Definition): z.ZodType;
|
|
14
|
+
export declare function buildFormSchema(sections: Sections, translations?: Record<string, string>, definition?: Definition, context?: Record<string, unknown>): z.ZodType;
|
|
14
15
|
export declare function collectIssues(error: z.ZodError): Array<{
|
|
15
16
|
path: string;
|
|
16
17
|
message: string;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
export type InterpolateOptions = {
|
|
2
2
|
locale?: string;
|
|
3
|
+
now?: string;
|
|
3
4
|
};
|
|
5
|
+
/**
|
|
6
|
+
* What text the form renders is formatted with: the form's language, its
|
|
7
|
+
* `lang`, and the instant the host gave in `context`. A label and a
|
|
8
|
+
* description format the same value the same way because they ask here.
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderOptions(lang?: string, context?: Record<string, unknown>): InterpolateOptions;
|
|
4
11
|
/**
|
|
5
12
|
* Replaces placeholders in the format {key} with values from the provided object.
|
|
6
13
|
* Supports nested objects using dot notation (e.g., {user.id}) and pipe filters
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type Localization } from '../../../../../luna-core/index';
|
|
1
2
|
import type { List, Nullable, PreviewItem } from '../../../../../luna-core/index';
|
|
2
3
|
import type { ReactNode } from 'react';
|
|
3
|
-
export declare function FieldListPreviewItem({ canRemove, children, field, index, isMultiField, itemKey, label,
|
|
4
|
+
export declare function FieldListPreviewItem({ canRemove, children, field, index, isMultiField, itemKey, label, localization, onRemove, previewBadge, previewLabel, previewTags, value, }: {
|
|
4
5
|
canRemove: boolean;
|
|
5
6
|
children: ReactNode;
|
|
6
7
|
field: List;
|
|
@@ -8,11 +9,10 @@ export declare function FieldListPreviewItem({ canRemove, children, field, index
|
|
|
8
9
|
isMultiField: boolean;
|
|
9
10
|
itemKey: string | number;
|
|
10
11
|
label: string;
|
|
11
|
-
|
|
12
|
+
localization?: Localization;
|
|
12
13
|
onRemove: (index: number) => void;
|
|
13
14
|
previewBadge?: PreviewItem;
|
|
14
15
|
previewLabel?: PreviewItem;
|
|
15
16
|
previewTags?: PreviewItem[];
|
|
16
|
-
translations?: Record<string, string>;
|
|
17
17
|
value?: Nullable<Record<string, unknown> | unknown[]>;
|
|
18
18
|
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { type Option } from '../../../../../luna-core/index';
|
|
2
|
-
export declare function FieldPreviewItem({ className, initialValue, name, options, separator, staticLabel, }: Readonly<{
|
|
1
|
+
import { type DateFormat, type Option } from '../../../../../luna-core/index';
|
|
2
|
+
export declare function FieldPreviewItem({ className, dateFormat, initialValue, lang, name, options, separator, staticLabel, }: Readonly<{
|
|
3
3
|
className?: string;
|
|
4
|
+
dateFormat?: DateFormat;
|
|
4
5
|
initialValue?: unknown;
|
|
6
|
+
lang?: string;
|
|
5
7
|
name?: string;
|
|
6
8
|
options?: Array<Option | string>;
|
|
7
9
|
separator?: boolean;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { type DateFormat } from '../../../../../luna-core/index';
|
|
2
|
+
export declare function FieldPreviewValue({ children, dateFormat, initialValue, lang, name, }: Readonly<{
|
|
2
3
|
children: (value: string) => React.ReactNode;
|
|
4
|
+
dateFormat?: DateFormat;
|
|
3
5
|
initialValue?: unknown;
|
|
6
|
+
lang?: string;
|
|
4
7
|
name: string;
|
|
5
8
|
}>): import("react").JSX.Element;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import { type Localization } from '../../../../../luna-core/index';
|
|
1
2
|
import type { Fields, PreviewItem } from '../../../../../luna-core/index';
|
|
2
|
-
|
|
3
|
+
type PreviewProps = Readonly<{
|
|
3
4
|
className?: string;
|
|
4
5
|
fields?: Fields;
|
|
5
6
|
label?: string;
|
|
6
|
-
|
|
7
|
+
localization?: Localization;
|
|
7
8
|
name: string;
|
|
8
9
|
previews: PreviewItem | PreviewItem[];
|
|
9
|
-
translations?: Record<string, string>;
|
|
10
10
|
value?: Record<string, unknown> | unknown[] | null;
|
|
11
|
-
}
|
|
11
|
+
}>;
|
|
12
|
+
export declare function FieldPreview(props: PreviewProps): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Section, type Style } from '../../../../../luna-core/index';
|
|
2
|
+
export declare function FieldSet(props: Readonly<{
|
|
3
|
+
advanced?: {
|
|
4
|
+
step?: boolean;
|
|
5
|
+
};
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
section: Section;
|
|
8
|
+
step?: number;
|
|
9
|
+
style?: Style;
|
|
10
|
+
translations?: Record<string, string>;
|
|
11
|
+
}>): import("react").JSX.Element;
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
import type { FieldProps } from '../../../component/field/field';
|
|
2
|
+
/**
|
|
3
|
+
* Everything a field reads from the store, in one component, with the memo
|
|
4
|
+
* around it rather than inside.
|
|
5
|
+
*
|
|
6
|
+
* Two wrappers used to sit outside that memo, one per atom, and both of them
|
|
7
|
+
* ran on every render of the form: a hundred fields cost two hundred renders a
|
|
8
|
+
* keystroke on a controlled host, for the memo underneath to then find every
|
|
9
|
+
* prop unchanged. Outside, the same comparison stops the field whole, the two
|
|
10
|
+
* reads included.
|
|
11
|
+
*
|
|
12
|
+
* Stopping there does not cut a field off from the store. What it reads are
|
|
13
|
+
* subscriptions, so its own state and its own errors render it whatever its
|
|
14
|
+
* props do -- which is the only way either of them changes.
|
|
15
|
+
*/
|
|
16
|
+
declare function FieldWithMeta(props: FieldProps): import("react").JSX.Element | null;
|
|
1
17
|
/**
|
|
2
18
|
* A field renders when something it can see has changed, and not because a
|
|
3
19
|
* field elsewhere in the form did.
|
|
@@ -14,15 +30,8 @@
|
|
|
14
30
|
* prop, so `children` is a stable callback rather than a closure rebuilt
|
|
15
31
|
* whenever that value moved; a field reads its own entry from the store, and
|
|
16
32
|
* the one thing that has to be read while rendering comes through a context
|
|
17
|
-
* whose identity never changes.
|
|
18
|
-
*
|
|
33
|
+
* whose identity never changes. What used to move, `errors`, is read from the
|
|
34
|
+
* store now, on the inside of this comparison.
|
|
19
35
|
*/
|
|
20
|
-
export declare const Field: (
|
|
21
|
-
|
|
22
|
-
disabled?: boolean;
|
|
23
|
-
errors?: Record<string, string[]>;
|
|
24
|
-
field: import('../../../../../luna-core/index').Field;
|
|
25
|
-
lang?: string;
|
|
26
|
-
style?: import('../../../../../luna-core/index').Style;
|
|
27
|
-
translations?: Record<string, string>;
|
|
28
|
-
}>>>) => import("react").JSX.Element | null;
|
|
36
|
+
export declare const Field: import("react").MemoExoticComponent<typeof FieldWithMeta>;
|
|
37
|
+
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type Description as DescriptionType } from '
|
|
2
|
-
import type { Config } from '
|
|
1
|
+
import { type Description as DescriptionType, type Localization } from '../../../../luna-core/index';
|
|
2
|
+
import type { Config } from '../../type';
|
|
3
3
|
export declare function FormattedDescription(props: Readonly<{
|
|
4
4
|
config?: Config;
|
|
5
5
|
context?: Record<string, unknown>;
|
|
6
|
+
localization?: Localization;
|
|
6
7
|
text?: DescriptionType;
|
|
7
|
-
translations?: Record<string, string>;
|
|
8
8
|
value?: unknown;
|
|
9
9
|
}>): import("react").JSX.Element | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ListProps } from '../../../component/field/field-list';
|
|
2
|
-
export declare function ListGuard({ children, field,
|
|
2
|
+
export declare function ListGuard({ children, field, onValueChange, localization, value, }: ListProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { Config } from '../../type';
|
|
2
2
|
import type { DataSource, Field, Nullable, Value } from '../../../../luna-core/index';
|
|
3
|
+
/**
|
|
4
|
+
* What a held value is when the change events run at mount, which has to be
|
|
5
|
+
* what a change hands them later: a form reopened on saved data reveals what it
|
|
6
|
+
* revealed when it was filled in. An array travels as one -- a `chips` field's
|
|
7
|
+
* selections, the two days of a range -- since `String()` on it joins them into
|
|
8
|
+
* "a,b", which answers to no option, no `when` and no day. Anything else is the
|
|
9
|
+
* text it would have been typed as.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toChangeValue(value: unknown): Value;
|
|
3
12
|
/**
|
|
4
13
|
* What the input pipeline reads off a change, and all it reads: the new value.
|
|
5
14
|
*
|
|
@@ -30,7 +39,7 @@ export type InputStrategies = Readonly<{
|
|
|
30
39
|
valueRef: React.RefObject<unknown>;
|
|
31
40
|
}>) => boolean;
|
|
32
41
|
dispatchChange: (ctx: Readonly<{
|
|
33
|
-
applyChangeEventsRef: React.RefObject<(
|
|
42
|
+
applyChangeEventsRef: React.RefObject<(s: unknown) => void>;
|
|
34
43
|
data: Nullable<unknown[]>;
|
|
35
44
|
entity?: string;
|
|
36
45
|
inputValue: Value;
|
|
@@ -38,5 +47,4 @@ export type InputStrategies = Readonly<{
|
|
|
38
47
|
}>) => void;
|
|
39
48
|
buildInitialSelected: (defaultValue: unknown, data: Nullable<unknown[]>, entity: string | undefined) => unknown;
|
|
40
49
|
isInitialReady: (field: Field, defaultValue: unknown, data: Nullable<unknown[]>) => boolean;
|
|
41
|
-
useExtraProps?: (field: Field) => Record<string, unknown> | undefined;
|
|
42
50
|
}>;
|
|
@@ -4,12 +4,11 @@ export declare const Slot: (props: Readonly<{
|
|
|
4
4
|
context?: Record<string, unknown>;
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
fields?: import('../../../../../luna-core/index').Fields;
|
|
7
|
-
lang?: string;
|
|
8
7
|
onValueChange?: (input: {
|
|
9
8
|
name: string;
|
|
10
9
|
value: unknown;
|
|
11
10
|
}) => void;
|
|
12
11
|
style?: import('../../../../../luna-core/index').Style;
|
|
13
|
-
|
|
12
|
+
localization?: import('../../../../../luna-core/index').Localization;
|
|
14
13
|
value?: import('../../../../../luna-core/index').Nullable<Record<string, unknown>>;
|
|
15
14
|
}>) => import("react").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PrimitiveAtom } from 'jotai';
|
|
2
|
+
/**
|
|
3
|
+
* One entry of a record the whole form shares, as an atom of the component that
|
|
4
|
+
* reads it.
|
|
5
|
+
*
|
|
6
|
+
* A family did this before: one atom per name, kept in a module-level cache for
|
|
7
|
+
* the life of the page. That cache never let go on its own, so it had to be
|
|
8
|
+
* emptied by hand -- release atoms, a call in `useStore`, and a comment on the
|
|
9
|
+
* loop to avoid -- and two of the three families grew anyway, a key per row ever
|
|
10
|
+
* added and a key per name ever shown. Made here, the atom goes when the
|
|
11
|
+
* component does, and there is nothing left to release.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useEntryAtom<T>(base: PrimitiveAtom<Record<string, T>>, name: string): import("jotai").WritableAtom<NonNullable<T> | undefined, [next: T | undefined], void>;
|
|
14
|
+
/** The same for a record of contributions. See `createContributionAtom`. */
|
|
15
|
+
export declare function useContributionAtom<T>(base: PrimitiveAtom<Record<string, Record<string, T>>>, name: string, options: Readonly<{
|
|
16
|
+
merge: (values: T[]) => T | undefined;
|
|
17
|
+
validateTarget: (target: string) => boolean;
|
|
18
|
+
}>): import("jotai").WritableAtom<T | undefined, [target: string, value: T | undefined], void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AriaAttributes, type CommonProps, type DataAttributes, type DataSource, type Field, type Schema, type Value } from '../../../../luna-core/index';
|
|
1
|
+
import { type AriaAttributes, type CommonProps, type DataAttributes, type DataSource, type Field, type Schema, type Value, type Localization } from '../../../../luna-core/index';
|
|
2
2
|
import type { Config, InputChange } from '../../type';
|
|
3
3
|
export type InputCoreProps = Readonly<{
|
|
4
4
|
ariaAttributes?: AriaAttributes;
|
|
@@ -9,20 +9,20 @@ export type InputCoreProps = Readonly<{
|
|
|
9
9
|
field: Field;
|
|
10
10
|
getField: (name: string) => Field | undefined;
|
|
11
11
|
horizontal?: boolean;
|
|
12
|
+
localization?: Localization;
|
|
12
13
|
onRegister: (name: string, schema: Schema, field: Field) => void;
|
|
13
14
|
onUnmount: (name: string, options?: {
|
|
14
15
|
keepValue?: boolean;
|
|
15
16
|
}) => void;
|
|
16
17
|
onValueChange?: (input: InputChange) => void;
|
|
17
18
|
readOnly?: boolean;
|
|
18
|
-
translations?: Record<string, string>;
|
|
19
19
|
}>;
|
|
20
20
|
export declare function useInputCore(props: InputCoreProps, deps: Readonly<{
|
|
21
21
|
setSource: (target: string, source?: DataSource) => void;
|
|
22
22
|
setValue: (value: unknown) => void;
|
|
23
23
|
value: unknown;
|
|
24
24
|
}>): {
|
|
25
|
-
readonly applyChangeEventsRef: import("react").RefObject<(
|
|
25
|
+
readonly applyChangeEventsRef: import("react").RefObject<(selected: unknown) => void>;
|
|
26
26
|
readonly commonProps: {
|
|
27
27
|
placeholder: string;
|
|
28
28
|
disabled?: boolean;
|
|
@@ -33,7 +33,7 @@ export declare function useInputCore(props: InputCoreProps, deps: Readonly<{
|
|
|
33
33
|
readonly entity: string | undefined;
|
|
34
34
|
readonly hasClickable: boolean;
|
|
35
35
|
readonly onBlur: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
36
|
-
readonly onValueChangeRef: import("react").RefObject<(
|
|
36
|
+
readonly onValueChangeRef: import("react").RefObject<(value: Value) => void>;
|
|
37
37
|
readonly setTimeoutRef: (callback: () => void, delay: number) => void;
|
|
38
38
|
readonly validated: (value: Value) => void;
|
|
39
39
|
readonly valueRef: import("react").RefObject<unknown>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The latest value a commit left, for the code that runs after it: an event
|
|
3
|
+
* handler, an effect, a callback whose identity has to stay steady across
|
|
4
|
+
* renders.
|
|
5
|
+
*
|
|
6
|
+
* Written from a layout effect and not from the render body, which is the whole
|
|
7
|
+
* point. A render is not a promise that anything reached the screen -- React
|
|
8
|
+
* throws one away when a transition is interrupted or a boundary retries -- and
|
|
9
|
+
* a ref assigned while rendering keeps whatever that discarded render held,
|
|
10
|
+
* which is props nobody ever saw. A commit is the moment a value becomes real,
|
|
11
|
+
* so that is when this writes it. It is also what the React Compiler asks of a
|
|
12
|
+
* component before it will optimize it.
|
|
13
|
+
*
|
|
14
|
+
* Layout and not `useEffect`: every effect of a commit runs after every layout
|
|
15
|
+
* effect of that same commit, so an effect reading this ref reads the value of
|
|
16
|
+
* the render it belongs to, whatever order the hooks were declared in.
|
|
17
|
+
*
|
|
18
|
+
* Reading it while rendering is still wrong, and still reported by
|
|
19
|
+
* `react-hooks/refs`: there the value is one commit old. What a render needs is
|
|
20
|
+
* the value itself.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useLatest<T>(value: T): import("react").RefObject<T>;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* What a row holds right now: the form's own state over the initial value tree,
|
|
3
|
+
* for a `when` that has to follow what the user types.
|
|
4
|
+
*
|
|
5
|
+
* Subscribed to the row's keys and not to the record. Every field in the form
|
|
6
|
+
* writes into that one record, so a row that read it woke up on every keystroke
|
|
7
|
+
* anywhere and walked every key in the form to find its own. The selection is
|
|
8
|
+
* compared shallowly, so a keystroke outside the row recomputes the pick, finds
|
|
9
|
+
* the same keys, and renders nothing.
|
|
10
|
+
*
|
|
11
|
+
* Only a condition needs this, and only a condition asks for it: the components
|
|
12
|
+
* that own one render the child that calls this hook, so a row with no
|
|
13
|
+
* condition to answer never subscribes at all.
|
|
14
|
+
*
|
|
15
|
+
* The atom is made with the component that reads it and goes with it: jotai
|
|
16
|
+
* caches a selection under the selector function, `pickRow` makes a new one per
|
|
17
|
+
* row, and both are held weakly, so nothing is kept by name for the life of the
|
|
18
|
+
* page.
|
|
5
19
|
*/
|
|
6
20
|
export declare function useLiveItemValue(name: string, initialValue?: Record<string, unknown> | unknown[] | null): unknown;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Field } from '../../../../luna-core/index';
|
|
2
2
|
export declare function useValue(field: Field): {
|
|
3
|
-
readonly setValue: (
|
|
3
|
+
readonly setValue: (next: unknown) => void;
|
|
4
4
|
readonly shouldSkipOnChange: () => boolean;
|
|
5
5
|
readonly value: {} | undefined;
|
|
6
6
|
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
init:
|
|
1
|
+
export declare const inputErrorAtom: import("jotai").PrimitiveAtom<Record<string, string[]>> & {
|
|
2
|
+
init: Record<string, string[]>;
|
|
3
3
|
};
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const clearInputErrorAtom: import("jotai").WritableAtom<null, [names: string[]], void> & {
|
|
5
5
|
init: null;
|
|
6
6
|
};
|
|
7
7
|
export declare const reportErrorAtom: import("jotai").WritableAtom<null, [newValue: Record<string, string[]>], void> & {
|
|
8
8
|
init: null;
|
|
9
9
|
};
|
|
10
|
-
export declare const reportInputErrorAtom: import("jotai-family").AtomFamily<string, import("jotai").WritableAtom<string[] | undefined, [newValue: string[] | undefined], void>>;
|