@marktiderman/genesis-forms 0.5.0 → 0.6.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.
@@ -0,0 +1,322 @@
1
+ import { J as Json, g as Operator, a as FieldBlock, B as Block, O as OptionsSource, F as FormDefinition, e as FormEvent } from './types-oAckGR_Z.js';
2
+
3
+ /**
4
+ * A field type, without any UI. Renderers are registered separately per
5
+ * platform (`genesis-forms-react`), so a manifest runs anywhere.
6
+ */
7
+ interface FieldTypeManifest {
8
+ type: string;
9
+ label: string;
10
+ category: "text" | "choice" | "scale" | "date" | "media" | "advanced";
11
+ /** `json: false` types must convert, so drafts and server replay never lose an answer. */
12
+ value: {
13
+ json: true;
14
+ } | {
15
+ json: false;
16
+ serialize: (value: unknown) => Json;
17
+ deserialize: (json: Json) => unknown;
18
+ };
19
+ operators: Operator[];
20
+ a11y: {
21
+ semantics: "control" | "group";
22
+ /** The HTML `autocomplete` token, such as `"email"` or `"tel"`. */
23
+ autocomplete?: string;
24
+ /** The HTML `inputmode` hint for on-screen keyboards, such as `"email"` or `"tel"`. */
25
+ inputMode?: "text" | "email" | "tel" | "numeric" | "decimal" | "url" | "search";
26
+ };
27
+ isEmpty?: (value: Json | undefined) => boolean;
28
+ /** Return an error message, or null when the (non-empty) value is valid. */
29
+ validate?: (value: Json, field: FieldBlock) => string | null;
30
+ /** Plain text for recall, exports and emails. */
31
+ summarize?: (value: Json, field: FieldBlock) => string;
32
+ /**
33
+ * The form a (valid, non-empty) value is stored in, such as an email
34
+ * without surrounding spaces. Applied by `engine.answers()` and the server.
35
+ */
36
+ normalize?: (value: Json, field: FieldBlock) => Json;
37
+ /** Valid example answers, used by `coverage()` and other test tools to explore a path. */
38
+ samples?: (field: FieldBlock) => Json[];
39
+ }
40
+ declare function registerFieldType(manifest: FieldTypeManifest): void;
41
+ declare function getFieldType(type: string): FieldTypeManifest | undefined;
42
+ declare function listFieldTypes(): FieldTypeManifest[];
43
+ declare function isEmptyValue(value: Json | undefined, field?: FieldBlock): boolean;
44
+ /** A value in its stored form (see `FieldTypeManifest.normalize`). */
45
+ declare function normalizeValue(value: Json, field: FieldBlock): Json;
46
+ /** Whether a block holds personal or secret data: `sensitive: true`, or the `props.sensitive: true` alias. */
47
+ declare function isSensitive(block: Block): boolean;
48
+ declare function summarizeValue(value: Json | undefined, field: FieldBlock): string;
49
+ interface ChoiceOption {
50
+ value: string;
51
+ label?: string;
52
+ /** A muted line under the label, such as a location's address. At most `OPTION_LIMITS.description` characters. */
53
+ description?: string;
54
+ /** A small picture beside the label: an `https://` URL, at most `OPTION_LIMITS.image` characters. */
55
+ image?: string;
56
+ /**
57
+ * Facts about the option for filtering and recall, such as `{ location: ["cff", "cornerstone"] }`
58
+ * for a coach who works at two locations (see `props.optionsFrom.filter`). Names and values are
59
+ * text; a value is one text or a list of them.
60
+ */
61
+ attributes?: Record<string, string | string[]>;
62
+ }
63
+ /** Bounds on an option's extra details. A longer or malformed detail is dropped when options are read. */
64
+ declare const OPTION_LIMITS: {
65
+ /** Characters in a description. */
66
+ readonly description: 500;
67
+ /** Characters in an image URL. */
68
+ readonly image: 2048;
69
+ /** Attributes on one option. */
70
+ readonly attributes: 20;
71
+ /** Characters in an attribute's name. */
72
+ readonly attributeName: 64;
73
+ /** Characters in one attribute value. */
74
+ readonly attributeValue: 200;
75
+ /** Values in one attribute's list. */
76
+ readonly attributeItems: 50;
77
+ };
78
+ /**
79
+ * Whether `url` is an `https://` link with a host and no spaces or control characters, within
80
+ * `OPTION_LIMITS.image`. A pattern rather than `new URL`, so it behaves the same in React Native.
81
+ */
82
+ declare function isHttpsUrl(url: unknown): url is string;
83
+ /**
84
+ * An option from untrusted JSON (a definition, the host's list): its string `value`, and its
85
+ * `label`, `description`, `image` and `attributes` when each is well formed and within
86
+ * `OPTION_LIMITS`; anything else is left out. Null when there is no string value.
87
+ */
88
+ declare function readOption(raw: unknown): ChoiceOption | null;
89
+ /** An option as JSON, with only the details it has. */
90
+ declare function optionJson(option: ChoiceOption): Json;
91
+ /** The longest answer an "Other" option takes. */
92
+ declare const OTHER_MAX_LENGTH = 200;
93
+ /**
94
+ * A choice question's "Other" option (`props.other: true` or `{ label }`): the respondent types
95
+ * their own answer, stored as the answer's value itself (single choice, dropdown) or as one more
96
+ * item (multiple choice). Null when the question has none.
97
+ */
98
+ declare function otherOption(field: FieldBlock): {
99
+ label: string;
100
+ } | null;
101
+ /** Whether a value is a typed "Other" answer: text that isn't one of the question's options. */
102
+ declare function isOtherValue(field: FieldBlock, value: unknown): value is string;
103
+ declare function choiceOptions(field: FieldBlock): ChoiceOption[];
104
+ /**
105
+ * Option lists the app showing a form supplies, by key (`OptionsSource.key`):
106
+ * `{ coaches: [{ value: "8c1…", label: "Ada Lovelace" }] }`.
107
+ */
108
+ type HostOptions = Readonly<Record<string, readonly ChoiceOption[]>>;
109
+ /**
110
+ * A choice field's `props.optionsFrom`, when it is a well-formed `{ source: "host", key }`, with its
111
+ * `filter` when that is well formed too (`{ attribute, field }`, both non-empty text).
112
+ */
113
+ declare function optionsSource(field: FieldBlock): OptionsSource | undefined;
114
+ /**
115
+ * The definition with each `optionsFrom: { source: "host" }` field's options
116
+ * filled in from `hostOptions`: its own `props.options` first, then the host's
117
+ * list for its key (a value the field already has is not added twice). A key
118
+ * the host does not supply adds nothing, so the field offers its own options
119
+ * only. `createForm` and `validateSubmission` call it with their `hostOptions`,
120
+ * so a respondent sees, and a submit accepts, exactly these. Returns
121
+ * `definition` itself when no field takes options from the host.
122
+ */
123
+ declare function withHostOptions(definition: FormDefinition, hostOptions: HostOptions | undefined): FormDefinition;
124
+ /** The optional words under the ends of a rating or NPS scale ("Poor", "Great"). */
125
+ declare function scaleLabels(field: FieldBlock): {
126
+ low?: string;
127
+ high?: string;
128
+ };
129
+ /** How a rating is drawn: `"numbers"` (default) or `"stars"`. */
130
+ declare function ratingDisplay(field: FieldBlock): "numbers" | "stars";
131
+ /** A `number` field's limits: `min`, `max` and `step` (each optional; `step` is above 0). */
132
+ declare function numberLimits(field: FieldBlock): {
133
+ min?: number;
134
+ max?: number;
135
+ step?: number;
136
+ };
137
+ /** `YYYY-MM-DD`, a real calendar day (no 2026-02-30), years 0001 to 9999. */
138
+ declare function isIsoDate(value: string): boolean;
139
+ /** A `date` field's earliest and latest days (`YYYY-MM-DD`), when set. */
140
+ declare function dateLimits(field: FieldBlock): {
141
+ min?: string;
142
+ max?: string;
143
+ };
144
+
145
+ /**
146
+ * Which options a choice question shows, and how they are picked: lists filtered by another
147
+ * answer, search for long lists, preselecting from a link, and snapshots of what was picked.
148
+ * Pure and renderer-agnostic, so the engine, the server and every renderer (web and native)
149
+ * decide the same way.
150
+ */
151
+
152
+ /** Field types whose answer is one or more of their options. */
153
+ declare const CHOICE_FIELD_TYPES: ReadonlySet<string>;
154
+ /** A choice field's `props.optionsFrom.filter` (`{ attribute, field }`), when it is well formed. */
155
+ declare function optionFilter(field: FieldBlock): {
156
+ attribute: string;
157
+ field: string;
158
+ } | undefined;
159
+ /**
160
+ * Whether an option matches an answer on one attribute: its `attributes[attribute]` (a text or a
161
+ * list) shares a value with the answer (a text, or a list from a multiple choice). An option
162
+ * without the attribute matches nothing.
163
+ */
164
+ declare function optionMatches(option: ChoiceOption, attribute: string, answer: Json | undefined): boolean;
165
+ /**
166
+ * The options a choice question shows given the answers so far (`values`, keyed by field id, as
167
+ * in `FormState.values`): all of `choiceOptions(field)`, or, with `props.optionsFrom.filter`,
168
+ * only those matching the filtered-by question's answer (`optionMatches`). While that question is
169
+ * unanswered (or isn't in the form) every option shows. Pass the definition with the host's lists
170
+ * filled in (`engine.definition`, or `withHostOptions`).
171
+ */
172
+ declare function visibleOptions(definition: FormDefinition, field: FieldBlock, values: Readonly<Record<string, Json | undefined>>): ChoiceOption[];
173
+ /**
174
+ * The answers on the respondent's path, by field id: what a filter reads. An answer to a question
175
+ * off the path (hidden by logic, jumped over) counts as none, as it does for logic. Pass these to
176
+ * `visibleOptions` from a renderer, so it shows exactly what the engine accepts.
177
+ */
178
+ declare function answersOnPath(state: {
179
+ path: readonly string[];
180
+ values: Readonly<Record<string, Json | undefined>>;
181
+ }): Record<string, Json | undefined>;
182
+ /**
183
+ * Null, or the error for a (non-empty) choice answer that is one of the question's options but
184
+ * not one it shows now because of its filter (`visibleOptions`). A typed "Other" answer is left
185
+ * to the field type's own check. The engine and `validateSubmission` both call it, so a value
186
+ * outside the filtered list is refused on the server too.
187
+ */
188
+ declare function filteredChoiceError(definition: FormDefinition, field: FieldBlock, value: Json | undefined, values: Readonly<Record<string, Json | undefined>>): string | null;
189
+ /** Whether any choice question in the definition filters its options by another answer. */
190
+ declare function hasOptionFilters(definition: FormDefinition): boolean;
191
+ /**
192
+ * `values` after the answer to `changedId` changed, with every choice its filter no longer
193
+ * shows taken out: a single choice or dropdown is cleared, a multiple choice keeps the options
194
+ * that still show (and a typed "Other" answer). It follows on: clearing one question clears what
195
+ * was filtered by it. Returns `values` itself when nothing is cleared. The engine calls it on
196
+ * every answer, so a pick never outlives the answer it depended on.
197
+ */
198
+ declare function clearFilteredAnswers(definition: FormDefinition, values: Record<string, Json | undefined>, changedId: string): Record<string, Json | undefined>;
199
+ /** A choice question with more options than this gets a search box, unless `props.searchable` says otherwise. */
200
+ declare const SEARCHABLE_OPTION_COUNT = 10;
201
+ /**
202
+ * Whether a choice question shows a search box over its options: `props.searchable` when it is
203
+ * true or false, otherwise when it has more than `SEARCHABLE_OPTION_COUNT` options. The default
204
+ * counts all its options (`choiceOptions(field)`, with the host's lists filled in), so a list a
205
+ * filter narrows keeps its search box while the respondent answers.
206
+ */
207
+ declare function isSearchable(field: FieldBlock, optionCount?: number): boolean;
208
+ /**
209
+ * The options that match what the respondent typed, in their order: every word of `query` is
210
+ * found (ignoring case and accents) in the option's label, value or description. A blank query
211
+ * matches every option.
212
+ */
213
+ declare function searchOptions(options: readonly ChoiceOption[], query: string): ChoiceOption[];
214
+ /** Characters in a link parameter's name. */
215
+ declare const MAX_PREFILL_PARAM_LENGTH = 64;
216
+ /** A choice question's `props.prefill`: the link parameter that preselects it, and whether it is then hidden. */
217
+ interface PrefillSetting {
218
+ /** The query parameter, as in `?location=cornerstone`. */
219
+ param: string;
220
+ /** Skip the question while the link has filled it in. */
221
+ hideWhenPrefilled: boolean;
222
+ }
223
+ /** A well-formed parameter name: letters, digits, `_`, `-` and `.`, at most `MAX_PREFILL_PARAM_LENGTH`. */
224
+ declare function isPrefillParam(param: unknown): param is string;
225
+ /** A choice field's `props.prefill` (`{ param, hideWhenPrefilled? }`), when it is well formed. */
226
+ declare function prefillSetting(field: FieldBlock): PrefillSetting | undefined;
227
+ /**
228
+ * A link's query parameters: a `URLSearchParams` (or anything with `getAll`), or a plain record
229
+ * of a text or a list of texts per name.
230
+ */
231
+ type LinkParams = {
232
+ getAll(name: string): string[];
233
+ } | Readonly<Record<string, string | readonly string[] | undefined>>;
234
+ /**
235
+ * Answers a link preselects, by field id, for `createForm`'s `initialValues` (its `linkParams`
236
+ * option calls this). Each choice question with `props.prefill: { param }` takes the parameter's
237
+ * value when it is one of the options the question shows (`visibleOptions`, so a filtered list is
238
+ * respected); anything else is ignored. A multiple choice takes every matching value, from
239
+ * repeated parameters (`?coach=a&coach=b`) or one comma-separated value. Questions are filled in
240
+ * form order, so a filtered question sees what the link picked before it. A question `values`
241
+ * already answers (the host's own prefill) is left alone. The server checks these like any answer.
242
+ */
243
+ declare function prefillFromLink(definition: FormDefinition, params: LinkParams | undefined, values?: Readonly<Record<string, Json | undefined>>): Record<string, Json>;
244
+ /** The parts of a form's state `hiddenByPrefill` reads (a `FormState` has them all). */
245
+ interface PrefillState {
246
+ path: readonly string[];
247
+ values: Readonly<Record<string, Json | undefined>>;
248
+ errors: Readonly<Record<string, string>>;
249
+ events: readonly FormEvent[];
250
+ }
251
+ /**
252
+ * Questions on the path the respondent skips because a prefill answered them: those with
253
+ * `props.prefill.hideWhenPrefilled` whose answer is still the prefilled one (the last answer
254
+ * event for them came from `initialValues` or a link) and has no error. The engine steps over
255
+ * them and renderers leave them out; their answers are stored like any other. A question shows
256
+ * again once its answer is cleared or changed (by a filter, say).
257
+ */
258
+ declare function hiddenByPrefill(definition: FormDefinition, state: PrefillState): string[];
259
+ /** The blocks the respondent steps through: the path without the questions a prefill hides (`hiddenByPrefill`). */
260
+ declare function respondentPath(definition: FormDefinition, state: PrefillState): string[];
261
+ /** One picked option as it was when the response was stored: its value (an id) and its label then. */
262
+ interface OptionSnapshot {
263
+ value: string;
264
+ label: string;
265
+ /** A typed "Other" answer rather than one of the options. */
266
+ other?: true;
267
+ }
268
+ /** A choice answer's snapshot: one pick (single choice, dropdown) or a list (multiple choice). */
269
+ type AnswerSnapshot = OptionSnapshot | OptionSnapshot[];
270
+ /**
271
+ * Each answer to a choice question that takes options from the app (`props.optionsFrom`), as
272
+ * `{ value, label }` pairs as of now, by field id: store them beside the answers so reports
273
+ * group by the value (an id) while history keeps the name it had then. Pass the definition with
274
+ * the host's lists filled in (`withHostOptions`, or `engine.definition`) and the checked
275
+ * answers (`validateSubmission`'s `submission.answers`). A value that isn't one of the options
276
+ * keeps itself as its label, marked `other` (a typed "Other" answer).
277
+ */
278
+ declare function answerSnapshots(definition: FormDefinition, answers: Readonly<Record<string, Json | undefined>>): Record<string, AnswerSnapshot>;
279
+ /** What `answersFromSnapshots` found again. */
280
+ interface RestoredAnswers {
281
+ /** Answers by field id, for `initialValues`: each pick's current value. */
282
+ answers: Record<string, Json>;
283
+ /** Picks no longer offered, by field id: the option was removed and no option has its label now. */
284
+ missing: Record<string, OptionSnapshot[]>;
285
+ }
286
+ /**
287
+ * The reverse of `answerSnapshots`, for an edit link: the answers to prefill from stored
288
+ * snapshots. A pick whose value is still an option keeps it; otherwise an option with the same
289
+ * label (ignoring case and accents) stands in, such as a location deleted and added again; a
290
+ * typed "Other" answer stays one when the question still allows it. Anything else is reported
291
+ * in `missing` and left out. Pass the definition with the host's current lists filled in.
292
+ */
293
+ declare function answersFromSnapshots(definition: FormDefinition, snapshots: Readonly<Record<string, unknown>>): RestoredAnswers;
294
+
295
+ /** The Standard Schema interface (standardschema.dev), as far as validation needs it. */
296
+ interface StandardSchemaV1<T = unknown> {
297
+ readonly "~standard": {
298
+ readonly version: 1;
299
+ readonly vendor: string;
300
+ readonly validate: (value: unknown) => {
301
+ value: T;
302
+ issues?: undefined;
303
+ } | {
304
+ issues: ReadonlyArray<{
305
+ message: string;
306
+ }>;
307
+ } | Promise<unknown>;
308
+ };
309
+ }
310
+ /** A custom check for one field: a function, or any Standard Schema (Zod, Valibot, ArkType…). */
311
+ type FieldValidator = ((value: Json) => string | null) | StandardSchemaV1;
312
+ declare const REQUIRED_MESSAGE = "This question needs an answer.";
313
+ /**
314
+ * Validate one field's value. `requireAnswers: false` (drafts) checks the
315
+ * format of what was answered without requiring the rest.
316
+ */
317
+ declare function validateField(field: FieldBlock, value: Json | undefined, options?: {
318
+ requireAnswers?: boolean;
319
+ custom?: FieldValidator;
320
+ }): string | null;
321
+
322
+ export { withHostOptions as $, type AnswerSnapshot as A, numberLimits as B, CHOICE_FIELD_TYPES as C, optionFilter as D, optionJson as E, type FieldValidator as F, optionMatches as G, type HostOptions as H, optionsSource as I, otherOption as J, prefillFromLink as K, type LinkParams as L, MAX_PREFILL_PARAM_LENGTH as M, prefillSetting as N, OPTION_LIMITS as O, type PrefillSetting as P, ratingDisplay as Q, REQUIRED_MESSAGE as R, SEARCHABLE_OPTION_COUNT as S, readOption as T, registerFieldType as U, respondentPath as V, scaleLabels as W, searchOptions as X, summarizeValue as Y, validateField as Z, visibleOptions as _, type ChoiceOption as a, type FieldTypeManifest as b, OTHER_MAX_LENGTH as c, type OptionSnapshot as d, type PrefillState as e, type RestoredAnswers as f, type StandardSchemaV1 as g, answerSnapshots as h, answersFromSnapshots as i, answersOnPath as j, choiceOptions as k, clearFilteredAnswers as l, dateLimits as m, filteredChoiceError as n, getFieldType as o, hasOptionFilters as p, hiddenByPrefill as q, isEmptyValue as r, isHttpsUrl as s, isIsoDate as t, isOtherValue as u, isPrefillParam as v, isSearchable as w, isSensitive as x, listFieldTypes as y, normalizeValue as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marktiderman/genesis-forms",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1,131 +0,0 @@
1
- import { J as Json, g as Operator, a as FieldBlock, B as Block, O as OptionsSource, F as FormDefinition } from './types-BhYUbLJ-.js';
2
-
3
- /**
4
- * A field type, without any UI. Renderers are registered separately per
5
- * platform (`genesis-forms-react`), so a manifest runs anywhere.
6
- */
7
- interface FieldTypeManifest {
8
- type: string;
9
- label: string;
10
- category: "text" | "choice" | "scale" | "date" | "media" | "advanced";
11
- /** `json: false` types must convert, so drafts and server replay never lose an answer. */
12
- value: {
13
- json: true;
14
- } | {
15
- json: false;
16
- serialize: (value: unknown) => Json;
17
- deserialize: (json: Json) => unknown;
18
- };
19
- operators: Operator[];
20
- a11y: {
21
- semantics: "control" | "group";
22
- /** The HTML `autocomplete` token, such as `"email"` or `"tel"`. */
23
- autocomplete?: string;
24
- /** The HTML `inputmode` hint for on-screen keyboards, such as `"email"` or `"tel"`. */
25
- inputMode?: "text" | "email" | "tel" | "numeric" | "decimal" | "url" | "search";
26
- };
27
- isEmpty?: (value: Json | undefined) => boolean;
28
- /** Return an error message, or null when the (non-empty) value is valid. */
29
- validate?: (value: Json, field: FieldBlock) => string | null;
30
- /** Plain text for recall, exports and emails. */
31
- summarize?: (value: Json, field: FieldBlock) => string;
32
- /**
33
- * The form a (valid, non-empty) value is stored in, such as an email
34
- * without surrounding spaces. Applied by `engine.answers()` and the server.
35
- */
36
- normalize?: (value: Json, field: FieldBlock) => Json;
37
- /** Valid example answers, used by `coverage()` and other test tools to explore a path. */
38
- samples?: (field: FieldBlock) => Json[];
39
- }
40
- declare function registerFieldType(manifest: FieldTypeManifest): void;
41
- declare function getFieldType(type: string): FieldTypeManifest | undefined;
42
- declare function listFieldTypes(): FieldTypeManifest[];
43
- declare function isEmptyValue(value: Json | undefined, field?: FieldBlock): boolean;
44
- /** A value in its stored form (see `FieldTypeManifest.normalize`). */
45
- declare function normalizeValue(value: Json, field: FieldBlock): Json;
46
- /** Whether a block holds personal or secret data: `sensitive: true`, or the `props.sensitive: true` alias. */
47
- declare function isSensitive(block: Block): boolean;
48
- declare function summarizeValue(value: Json | undefined, field: FieldBlock): string;
49
- interface ChoiceOption {
50
- value: string;
51
- label?: string;
52
- }
53
- /** The longest answer an "Other" option takes. */
54
- declare const OTHER_MAX_LENGTH = 200;
55
- /**
56
- * A choice question's "Other" option (`props.other: true` or `{ label }`): the respondent types
57
- * their own answer, stored as the answer's value itself (single choice, dropdown) or as one more
58
- * item (multiple choice). Null when the question has none.
59
- */
60
- declare function otherOption(field: FieldBlock): {
61
- label: string;
62
- } | null;
63
- /** Whether a value is a typed "Other" answer: text that isn't one of the question's options. */
64
- declare function isOtherValue(field: FieldBlock, value: unknown): value is string;
65
- declare function choiceOptions(field: FieldBlock): ChoiceOption[];
66
- /**
67
- * Option lists the app showing a form supplies, by key (`OptionsSource.key`):
68
- * `{ coaches: [{ value: "8c1…", label: "Ada Lovelace" }] }`.
69
- */
70
- type HostOptions = Readonly<Record<string, readonly ChoiceOption[]>>;
71
- /** A choice field's `props.optionsFrom`, when it is a well-formed `{ source: "host", key }`. */
72
- declare function optionsSource(field: FieldBlock): OptionsSource | undefined;
73
- /**
74
- * The definition with each `optionsFrom: { source: "host" }` field's options
75
- * filled in from `hostOptions`: its own `props.options` first, then the host's
76
- * list for its key (a value the field already has is not added twice). A key
77
- * the host does not supply adds nothing, so the field offers its own options
78
- * only. `createForm` and `validateSubmission` call it with their `hostOptions`,
79
- * so a respondent sees, and a submit accepts, exactly these. Returns
80
- * `definition` itself when no field takes options from the host.
81
- */
82
- declare function withHostOptions(definition: FormDefinition, hostOptions: HostOptions | undefined): FormDefinition;
83
- /** The optional words under the ends of a rating or NPS scale ("Poor", "Great"). */
84
- declare function scaleLabels(field: FieldBlock): {
85
- low?: string;
86
- high?: string;
87
- };
88
- /** How a rating is drawn: `"numbers"` (default) or `"stars"`. */
89
- declare function ratingDisplay(field: FieldBlock): "numbers" | "stars";
90
- /** A `number` field's limits: `min`, `max` and `step` (each optional; `step` is above 0). */
91
- declare function numberLimits(field: FieldBlock): {
92
- min?: number;
93
- max?: number;
94
- step?: number;
95
- };
96
- /** `YYYY-MM-DD`, a real calendar day (no 2026-02-30), years 0001 to 9999. */
97
- declare function isIsoDate(value: string): boolean;
98
- /** A `date` field's earliest and latest days (`YYYY-MM-DD`), when set. */
99
- declare function dateLimits(field: FieldBlock): {
100
- min?: string;
101
- max?: string;
102
- };
103
-
104
- /** The Standard Schema interface (standardschema.dev), as far as validation needs it. */
105
- interface StandardSchemaV1<T = unknown> {
106
- readonly "~standard": {
107
- readonly version: 1;
108
- readonly vendor: string;
109
- readonly validate: (value: unknown) => {
110
- value: T;
111
- issues?: undefined;
112
- } | {
113
- issues: ReadonlyArray<{
114
- message: string;
115
- }>;
116
- } | Promise<unknown>;
117
- };
118
- }
119
- /** A custom check for one field: a function, or any Standard Schema (Zod, Valibot, ArkType…). */
120
- type FieldValidator = ((value: Json) => string | null) | StandardSchemaV1;
121
- declare const REQUIRED_MESSAGE = "This question needs an answer.";
122
- /**
123
- * Validate one field's value. `requireAnswers: false` (drafts) checks the
124
- * format of what was answered without requiring the rest.
125
- */
126
- declare function validateField(field: FieldBlock, value: Json | undefined, options?: {
127
- requireAnswers?: boolean;
128
- custom?: FieldValidator;
129
- }): string | null;
130
-
131
- export { type ChoiceOption as C, type FieldValidator as F, type HostOptions as H, OTHER_MAX_LENGTH as O, REQUIRED_MESSAGE as R, type StandardSchemaV1 as S, type FieldTypeManifest as a, isIsoDate as b, choiceOptions as c, dateLimits as d, isOtherValue as e, isSensitive as f, getFieldType as g, numberLimits as h, isEmptyValue as i, otherOption as j, registerFieldType as k, listFieldTypes as l, summarizeValue as m, normalizeValue as n, optionsSource as o, ratingDisplay as r, scaleLabels as s, validateField as v, withHostOptions as w };
@@ -1,131 +0,0 @@
1
- import { J as Json, g as Operator, a as FieldBlock, B as Block, O as OptionsSource, F as FormDefinition } from './types-BhYUbLJ-.cjs';
2
-
3
- /**
4
- * A field type, without any UI. Renderers are registered separately per
5
- * platform (`genesis-forms-react`), so a manifest runs anywhere.
6
- */
7
- interface FieldTypeManifest {
8
- type: string;
9
- label: string;
10
- category: "text" | "choice" | "scale" | "date" | "media" | "advanced";
11
- /** `json: false` types must convert, so drafts and server replay never lose an answer. */
12
- value: {
13
- json: true;
14
- } | {
15
- json: false;
16
- serialize: (value: unknown) => Json;
17
- deserialize: (json: Json) => unknown;
18
- };
19
- operators: Operator[];
20
- a11y: {
21
- semantics: "control" | "group";
22
- /** The HTML `autocomplete` token, such as `"email"` or `"tel"`. */
23
- autocomplete?: string;
24
- /** The HTML `inputmode` hint for on-screen keyboards, such as `"email"` or `"tel"`. */
25
- inputMode?: "text" | "email" | "tel" | "numeric" | "decimal" | "url" | "search";
26
- };
27
- isEmpty?: (value: Json | undefined) => boolean;
28
- /** Return an error message, or null when the (non-empty) value is valid. */
29
- validate?: (value: Json, field: FieldBlock) => string | null;
30
- /** Plain text for recall, exports and emails. */
31
- summarize?: (value: Json, field: FieldBlock) => string;
32
- /**
33
- * The form a (valid, non-empty) value is stored in, such as an email
34
- * without surrounding spaces. Applied by `engine.answers()` and the server.
35
- */
36
- normalize?: (value: Json, field: FieldBlock) => Json;
37
- /** Valid example answers, used by `coverage()` and other test tools to explore a path. */
38
- samples?: (field: FieldBlock) => Json[];
39
- }
40
- declare function registerFieldType(manifest: FieldTypeManifest): void;
41
- declare function getFieldType(type: string): FieldTypeManifest | undefined;
42
- declare function listFieldTypes(): FieldTypeManifest[];
43
- declare function isEmptyValue(value: Json | undefined, field?: FieldBlock): boolean;
44
- /** A value in its stored form (see `FieldTypeManifest.normalize`). */
45
- declare function normalizeValue(value: Json, field: FieldBlock): Json;
46
- /** Whether a block holds personal or secret data: `sensitive: true`, or the `props.sensitive: true` alias. */
47
- declare function isSensitive(block: Block): boolean;
48
- declare function summarizeValue(value: Json | undefined, field: FieldBlock): string;
49
- interface ChoiceOption {
50
- value: string;
51
- label?: string;
52
- }
53
- /** The longest answer an "Other" option takes. */
54
- declare const OTHER_MAX_LENGTH = 200;
55
- /**
56
- * A choice question's "Other" option (`props.other: true` or `{ label }`): the respondent types
57
- * their own answer, stored as the answer's value itself (single choice, dropdown) or as one more
58
- * item (multiple choice). Null when the question has none.
59
- */
60
- declare function otherOption(field: FieldBlock): {
61
- label: string;
62
- } | null;
63
- /** Whether a value is a typed "Other" answer: text that isn't one of the question's options. */
64
- declare function isOtherValue(field: FieldBlock, value: unknown): value is string;
65
- declare function choiceOptions(field: FieldBlock): ChoiceOption[];
66
- /**
67
- * Option lists the app showing a form supplies, by key (`OptionsSource.key`):
68
- * `{ coaches: [{ value: "8c1…", label: "Ada Lovelace" }] }`.
69
- */
70
- type HostOptions = Readonly<Record<string, readonly ChoiceOption[]>>;
71
- /** A choice field's `props.optionsFrom`, when it is a well-formed `{ source: "host", key }`. */
72
- declare function optionsSource(field: FieldBlock): OptionsSource | undefined;
73
- /**
74
- * The definition with each `optionsFrom: { source: "host" }` field's options
75
- * filled in from `hostOptions`: its own `props.options` first, then the host's
76
- * list for its key (a value the field already has is not added twice). A key
77
- * the host does not supply adds nothing, so the field offers its own options
78
- * only. `createForm` and `validateSubmission` call it with their `hostOptions`,
79
- * so a respondent sees, and a submit accepts, exactly these. Returns
80
- * `definition` itself when no field takes options from the host.
81
- */
82
- declare function withHostOptions(definition: FormDefinition, hostOptions: HostOptions | undefined): FormDefinition;
83
- /** The optional words under the ends of a rating or NPS scale ("Poor", "Great"). */
84
- declare function scaleLabels(field: FieldBlock): {
85
- low?: string;
86
- high?: string;
87
- };
88
- /** How a rating is drawn: `"numbers"` (default) or `"stars"`. */
89
- declare function ratingDisplay(field: FieldBlock): "numbers" | "stars";
90
- /** A `number` field's limits: `min`, `max` and `step` (each optional; `step` is above 0). */
91
- declare function numberLimits(field: FieldBlock): {
92
- min?: number;
93
- max?: number;
94
- step?: number;
95
- };
96
- /** `YYYY-MM-DD`, a real calendar day (no 2026-02-30), years 0001 to 9999. */
97
- declare function isIsoDate(value: string): boolean;
98
- /** A `date` field's earliest and latest days (`YYYY-MM-DD`), when set. */
99
- declare function dateLimits(field: FieldBlock): {
100
- min?: string;
101
- max?: string;
102
- };
103
-
104
- /** The Standard Schema interface (standardschema.dev), as far as validation needs it. */
105
- interface StandardSchemaV1<T = unknown> {
106
- readonly "~standard": {
107
- readonly version: 1;
108
- readonly vendor: string;
109
- readonly validate: (value: unknown) => {
110
- value: T;
111
- issues?: undefined;
112
- } | {
113
- issues: ReadonlyArray<{
114
- message: string;
115
- }>;
116
- } | Promise<unknown>;
117
- };
118
- }
119
- /** A custom check for one field: a function, or any Standard Schema (Zod, Valibot, ArkType…). */
120
- type FieldValidator = ((value: Json) => string | null) | StandardSchemaV1;
121
- declare const REQUIRED_MESSAGE = "This question needs an answer.";
122
- /**
123
- * Validate one field's value. `requireAnswers: false` (drafts) checks the
124
- * format of what was answered without requiring the rest.
125
- */
126
- declare function validateField(field: FieldBlock, value: Json | undefined, options?: {
127
- requireAnswers?: boolean;
128
- custom?: FieldValidator;
129
- }): string | null;
130
-
131
- export { type ChoiceOption as C, type FieldValidator as F, type HostOptions as H, OTHER_MAX_LENGTH as O, REQUIRED_MESSAGE as R, type StandardSchemaV1 as S, type FieldTypeManifest as a, isIsoDate as b, choiceOptions as c, dateLimits as d, isOtherValue as e, isSensitive as f, getFieldType as g, numberLimits as h, isEmptyValue as i, otherOption as j, registerFieldType as k, listFieldTypes as l, summarizeValue as m, normalizeValue as n, optionsSource as o, ratingDisplay as r, scaleLabels as s, validateField as v, withHostOptions as w };