@stapel/forms-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/MODULE.md +172 -0
- package/README.md +207 -0
- package/dist/api/export.d.ts +66 -0
- package/dist/api/export.d.ts.map +1 -0
- package/dist/api/export.js +138 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/extensions.d.ts +8 -0
- package/dist/api/extensions.d.ts.map +1 -0
- package/dist/api/extensions.js +8 -0
- package/dist/api/extensions.js.map +1 -0
- package/dist/api/formsApi.d.ts +113 -0
- package/dist/api/formsApi.d.ts.map +1 -0
- package/dist/api/formsApi.js +81 -0
- package/dist/api/formsApi.js.map +1 -0
- package/dist/api/generated/schema.d.ts +987 -0
- package/dist/api/generated/schema.d.ts.map +1 -0
- package/dist/api/generated/schema.js +2 -0
- package/dist/api/generated/schema.js.map +1 -0
- package/dist/api/types.d.ts +222 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +14 -0
- package/dist/api/types.js.map +1 -0
- package/dist/default/ConfigField.d.ts +32 -0
- package/dist/default/ConfigField.d.ts.map +1 -0
- package/dist/default/ConfigField.js +101 -0
- package/dist/default/ConfigField.js.map +1 -0
- package/dist/default/ErrorAlert.d.ts +9 -0
- package/dist/default/ErrorAlert.d.ts.map +1 -0
- package/dist/default/ErrorAlert.js +27 -0
- package/dist/default/ErrorAlert.js.map +1 -0
- package/dist/default/FormBuilderPane.d.ts +36 -0
- package/dist/default/FormBuilderPane.d.ts.map +1 -0
- package/dist/default/FormBuilderPane.js +70 -0
- package/dist/default/FormBuilderPane.js.map +1 -0
- package/dist/default/FormsListPane.d.ts +18 -0
- package/dist/default/FormsListPane.d.ts.map +1 -0
- package/dist/default/FormsListPane.js +28 -0
- package/dist/default/FormsListPane.js.map +1 -0
- package/dist/default/ResponsesPane.d.ts +21 -0
- package/dist/default/ResponsesPane.d.ts.map +1 -0
- package/dist/default/ResponsesPane.js +118 -0
- package/dist/default/ResponsesPane.js.map +1 -0
- package/dist/default/StapelForm.d.ts +76 -0
- package/dist/default/StapelForm.d.ts.map +1 -0
- package/dist/default/StapelForm.js +118 -0
- package/dist/default/StapelForm.js.map +1 -0
- package/dist/default/fields.d.ts +11 -0
- package/dist/default/fields.d.ts.map +1 -0
- package/dist/default/fields.js +273 -0
- package/dist/default/fields.js.map +1 -0
- package/dist/default/index.d.ts +42 -0
- package/dist/default/index.d.ts.map +1 -0
- package/dist/default/index.js +37 -0
- package/dist/default/index.js.map +1 -0
- package/dist/default/slots.d.ts +59 -0
- package/dist/default/slots.d.ts.map +1 -0
- package/dist/default/slots.js +25 -0
- package/dist/default/slots.js.map +1 -0
- package/dist/default/theme.d.ts +23 -0
- package/dist/default/theme.d.ts.map +1 -0
- package/dist/default/theme.js +38 -0
- package/dist/default/theme.js.map +1 -0
- package/dist/default/types.d.ts +12 -0
- package/dist/default/types.d.ts.map +1 -0
- package/dist/default/types.js +2 -0
- package/dist/default/types.js.map +1 -0
- package/dist/flows/errors.d.ts +12 -0
- package/dist/flows/errors.d.ts.map +1 -0
- package/dist/flows/errors.js +13 -0
- package/dist/flows/errors.js.map +1 -0
- package/dist/flows/registry.d.ts +22 -0
- package/dist/flows/registry.d.ts.map +1 -0
- package/dist/flows/registry.js +20 -0
- package/dist/flows/registry.js.map +1 -0
- package/dist/headless/FormBuilder.d.ts +100 -0
- package/dist/headless/FormBuilder.d.ts.map +1 -0
- package/dist/headless/FormBuilder.js +278 -0
- package/dist/headless/FormBuilder.js.map +1 -0
- package/dist/headless/FormFill.d.ts +88 -0
- package/dist/headless/FormFill.d.ts.map +1 -0
- package/dist/headless/FormFill.js +279 -0
- package/dist/headless/FormFill.js.map +1 -0
- package/dist/headless/FormList.d.ts +34 -0
- package/dist/headless/FormList.d.ts.map +1 -0
- package/dist/headless/FormList.js +37 -0
- package/dist/headless/FormList.js.map +1 -0
- package/dist/headless/FormsProvider.d.ts +19 -0
- package/dist/headless/FormsProvider.d.ts.map +1 -0
- package/dist/headless/FormsProvider.js +15 -0
- package/dist/headless/FormsProvider.js.map +1 -0
- package/dist/headless/ResponsesTable.d.ts +82 -0
- package/dist/headless/ResponsesTable.d.ts.map +1 -0
- package/dist/headless/ResponsesTable.js +195 -0
- package/dist/headless/ResponsesTable.js.map +1 -0
- package/dist/i18n/errorsMap.d.ts +10 -0
- package/dist/i18n/errorsMap.d.ts.map +1 -0
- package/dist/i18n/errorsMap.js +20 -0
- package/dist/i18n/errorsMap.js.map +1 -0
- package/dist/i18n/es.d.ts +7 -0
- package/dist/i18n/es.d.ts.map +1 -0
- package/dist/i18n/es.js +118 -0
- package/dist/i18n/es.js.map +1 -0
- package/dist/i18n/generated/errors.es.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.es.gen.js +79 -0
- package/dist/i18n/generated/errors.es.gen.js.map +1 -0
- package/dist/i18n/generated/errors.gen.d.ts +485 -0
- package/dist/i18n/generated/errors.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.gen.js +246 -0
- package/dist/i18n/generated/errors.gen.js.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts +16 -0
- package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -0
- package/dist/i18n/generated/errors.ru.gen.js +79 -0
- package/dist/i18n/generated/errors.ru.gen.js.map +1 -0
- package/dist/i18n/keys.d.ts +141 -0
- package/dist/i18n/keys.d.ts.map +1 -0
- package/dist/i18n/keys.js +233 -0
- package/dist/i18n/keys.js.map +1 -0
- package/dist/i18n/ru.d.ts +7 -0
- package/dist/i18n/ru.d.ts.map +1 -0
- package/dist/i18n/ru.js +127 -0
- package/dist/i18n/ru.js.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/model/context.d.ts +11 -0
- package/dist/model/context.d.ts.map +1 -0
- package/dist/model/context.js +16 -0
- package/dist/model/context.js.map +1 -0
- package/dist/model/mutations.d.ts +135 -0
- package/dist/model/mutations.d.ts.map +1 -0
- package/dist/model/mutations.js +223 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/queries.d.ts +59 -0
- package/dist/model/queries.d.ts.map +1 -0
- package/dist/model/queries.js +117 -0
- package/dist/model/queries.js.map +1 -0
- package/dist/model/queryKeys.d.ts +28 -0
- package/dist/model/queryKeys.d.ts.map +1 -0
- package/dist/model/queryKeys.js +23 -0
- package/dist/model/queryKeys.js.map +1 -0
- package/dist/model/runtime.d.ts +28 -0
- package/dist/model/runtime.d.ts.map +1 -0
- package/dist/model/runtime.js +14 -0
- package/dist/model/runtime.js.map +1 -0
- package/dist/widgets/configForms.d.ts +112 -0
- package/dist/widgets/configForms.d.ts.map +1 -0
- package/dist/widgets/configForms.js +211 -0
- package/dist/widgets/configForms.js.map +1 -0
- package/dist/widgets/registry.d.ts +83 -0
- package/dist/widgets/registry.d.ts.map +1 -0
- package/dist/widgets/registry.js +27 -0
- package/dist/widgets/registry.js.map +1 -0
- package/dist/widgets/validate.d.ts +57 -0
- package/dist/widgets/validate.d.ts.map +1 -0
- package/dist/widgets/validate.js +173 -0
- package/dist/widgets/validate.js.map +1 -0
- package/llms.txt +124 -0
- package/manifest.json +1038 -0
- package/package.json +108 -0
- package/src/analytics/generated/events.json +7 -0
- package/src/api/export.ts +195 -0
- package/src/api/extensions.ts +7 -0
- package/src/api/formsApi.ts +329 -0
- package/src/api/generated/schema.ts +989 -0
- package/src/api/types.ts +276 -0
- package/src/default/ConfigField.tsx +227 -0
- package/src/default/ErrorAlert.tsx +46 -0
- package/src/default/FormBuilderPane.tsx +414 -0
- package/src/default/FormsListPane.tsx +144 -0
- package/src/default/ResponsesPane.tsx +332 -0
- package/src/default/StapelForm.tsx +377 -0
- package/src/default/fields.tsx +454 -0
- package/src/default/index.ts +71 -0
- package/src/default/slots.ts +78 -0
- package/src/default/theme.tsx +65 -0
- package/src/default/types.ts +12 -0
- package/src/flows/errors.ts +16 -0
- package/src/flows/registry.ts +32 -0
- package/src/headless/FormBuilder.tsx +453 -0
- package/src/headless/FormFill.tsx +396 -0
- package/src/headless/FormList.tsx +74 -0
- package/src/headless/FormsProvider.tsx +20 -0
- package/src/headless/ResponsesTable.tsx +341 -0
- package/src/i18n/errorsMap.ts +31 -0
- package/src/i18n/es.ts +140 -0
- package/src/i18n/generated/errors.es.gen.ts +85 -0
- package/src/i18n/generated/errors.gen.ts +277 -0
- package/src/i18n/generated/errors.json +583 -0
- package/src/i18n/generated/errors.ru.gen.ts +85 -0
- package/src/i18n/keys.ts +264 -0
- package/src/i18n/ru.ts +150 -0
- package/src/index.ts +184 -0
- package/src/model/context.tsx +28 -0
- package/src/model/mutations.ts +387 -0
- package/src/model/queries.ts +154 -0
- package/src/model/queryKeys.ts +61 -0
- package/src/model/runtime.ts +48 -0
- package/src/widgets/registry.ts +101 -0
- package/src/widgets/validate.ts +224 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;AAEnD,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEnE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,yBAAyB,GACjC,YAAY,CAcd"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createModuleRuntime } from "@stapel/core";
|
|
2
|
+
import { createFormsApi } from "../api/formsApi.js";
|
|
3
|
+
export function createFormsRuntime(options) {
|
|
4
|
+
return createModuleRuntime((client) => createFormsApi(client, {
|
|
5
|
+
...(options.fetch !== undefined ? { fetch: options.fetch } : {}),
|
|
6
|
+
...(options.credentials !== undefined
|
|
7
|
+
? { credentials: options.credentials }
|
|
8
|
+
: {}),
|
|
9
|
+
...(options.defaultHeaders !== undefined
|
|
10
|
+
? { defaultHeaders: options.defaultHeaders }
|
|
11
|
+
: {}),
|
|
12
|
+
}), options);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/model/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA6BpD,MAAM,UAAU,kBAAkB,CAChC,OAAkC;IAElC,OAAO,mBAAmB,CACxB,CAAC,MAAM,EAAE,EAAE,CACT,cAAc,CAAC,MAAM,EAAE;QACrB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS;YACnC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;YACtC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,cAAc,KAAK,SAAS;YACtC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE;YAC5C,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,EACJ,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The field-kind CONFIG CONTRACT — what `<FormBuilder>` is data-driven off.
|
|
3
|
+
*
|
|
4
|
+
* ── Why this table exists in TypeScript at all ─────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* `stapel_attributes.config_form` declares every feature type's admin config
|
|
7
|
+
* form as DATA (`FormField(name, kind, label_key, required, default, params)`)
|
|
8
|
+
* precisely so a builder needs no per-type UI. Its own docstring, however,
|
|
9
|
+
* records how that data reaches a client: *"Emitted server-side onto the admin
|
|
10
|
+
* page via the widget (**no endpoint**)."* There is no REST surface serving
|
|
11
|
+
* `form_declarations()` — not in stapel-attributes, and not among
|
|
12
|
+
* stapel-forms' 13 paths (verified against `docs/schema.json`).
|
|
13
|
+
*
|
|
14
|
+
* So this module MIRRORS the upstream declarations rather than fetching them.
|
|
15
|
+
* That is a real, named cost, not a design preference — see the spec delta
|
|
16
|
+
* filed for it. What the mirror buys is the property §8 actually asked for:
|
|
17
|
+
* the builder iterates a table, so a kind is configured by DATA and no kind
|
|
18
|
+
* gets a bespoke hand-written form. What it costs is that the table can drift
|
|
19
|
+
* from upstream until the endpoint exists; the drift is bounded by
|
|
20
|
+
* `test/configForms.test.ts`, which pins every entry against the values quoted
|
|
21
|
+
* from `config_form.py` here.
|
|
22
|
+
*
|
|
23
|
+
* Source: `stapel_attributes/config_form.py::BUILTIN_FORMS` (attributes 0.4.6).
|
|
24
|
+
*
|
|
25
|
+
* ── v1 scope, and the two kinds that ship builder-less ─────────────────────
|
|
26
|
+
*
|
|
27
|
+
* Spec §12 risk 5: *"if a kind's config form turns out unrepresentable, that
|
|
28
|
+
* kind ships builder-less (authorable via draft PUT) rather than growing
|
|
29
|
+
* bespoke UI."* Applying it honestly:
|
|
30
|
+
*
|
|
31
|
+
* - **`convertible_unit`** declares NO config form upstream (it is absent
|
|
32
|
+
* from `BUILTIN_FORMS`). Nothing to render → builder-less.
|
|
33
|
+
* - **`hierarchical_select`** declares exactly one field, of kind
|
|
34
|
+
* `hierarchical_options` — a tree editor. Its whole form is the
|
|
35
|
+
* unrepresentable part → builder-less.
|
|
36
|
+
*
|
|
37
|
+
* Both remain fully RENDERABLE (they have widgets) and fully authorable
|
|
38
|
+
* through `PUT /forms/<id>/draft`. The builder says so instead of pretending.
|
|
39
|
+
*
|
|
40
|
+
* Two individual config FIELDS are also v1-unrepresentable and are marked
|
|
41
|
+
* {@link ConfigFieldSpec.unsupported}: `date.options` (`timestamp_array`) and
|
|
42
|
+
* anything else using `hierarchical_options`. The builder renders the rest of
|
|
43
|
+
* that kind's form and states which options it cannot edit — dropping them
|
|
44
|
+
* silently would present a partial form as a complete one.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* The config-widget vocabulary — `stapel_attributes.config_form.FIELD_KINDS`.
|
|
48
|
+
* A kind here is a WIDGET, not a feature type: this is why the builder scales
|
|
49
|
+
* to a host-registered type for free, exactly as the upstream docstring
|
|
50
|
+
* promises ("a newly registered type gets an admin form with zero JS as long
|
|
51
|
+
* as it uses the standard field-kinds").
|
|
52
|
+
*/
|
|
53
|
+
export type ConfigFieldKind = "number" | "text" | "checkbox" | "translatable_text" | "number_options" | "string_options" | "color_options" | "select" | "select_options_with_default" | "max_selected_dropdown" | "hierarchical_options" | "timestamp" | "timestamp_array";
|
|
54
|
+
/** One inline choice of a `select` config widget. */
|
|
55
|
+
export interface ConfigSelectOption {
|
|
56
|
+
readonly value: string;
|
|
57
|
+
readonly label: string;
|
|
58
|
+
}
|
|
59
|
+
/** One declared config-form field (upstream `FormField.to_dict()`). */
|
|
60
|
+
export interface ConfigFieldSpec {
|
|
61
|
+
/** The config key this field edits. Order is significant. */
|
|
62
|
+
readonly name: string;
|
|
63
|
+
readonly kind: ConfigFieldKind;
|
|
64
|
+
/** Upstream i18n key, `admin.attributes.form.<type>.<field>`. The builder
|
|
65
|
+
* renders `t(labelKey)` and falls back to a humanized `name`. */
|
|
66
|
+
readonly labelKey: string;
|
|
67
|
+
/** Cosmetic `*` marker only — real validation is server-side. */
|
|
68
|
+
readonly required?: boolean;
|
|
69
|
+
/** Applied when the config key is absent. */
|
|
70
|
+
readonly default?: unknown;
|
|
71
|
+
/** Inline choices, for `kind: "select"`. */
|
|
72
|
+
readonly options?: readonly ConfigSelectOption[];
|
|
73
|
+
/** Numeric step, for `kind: "number"`. */
|
|
74
|
+
readonly step?: number;
|
|
75
|
+
/** Placeholder, for the text-ish kinds. */
|
|
76
|
+
readonly placeholder?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Set when v1 has no widget for this config kind. The builder shows the row
|
|
79
|
+
* disabled with an explanation rather than omitting it — a config form that
|
|
80
|
+
* silently hides an option looks complete when it is not.
|
|
81
|
+
*/
|
|
82
|
+
readonly unsupported?: true;
|
|
83
|
+
}
|
|
84
|
+
/** A field kind's full config declaration. */
|
|
85
|
+
export interface KindConfigForm {
|
|
86
|
+
/** Upstream i18n key, `admin.attributes.type.<slug>`. */
|
|
87
|
+
readonly labelKey: string;
|
|
88
|
+
readonly fields: readonly ConfigFieldSpec[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Field kind → its config form. A kind ABSENT from this table ships
|
|
92
|
+
* builder-less (see the module header): `convertible_unit` (no upstream
|
|
93
|
+
* declaration) and `hierarchical_select` (its only field is a tree editor).
|
|
94
|
+
*/
|
|
95
|
+
export declare const FIELD_KIND_CONFIG_FORMS: Readonly<Record<string, KindConfigForm>>;
|
|
96
|
+
/**
|
|
97
|
+
* The kinds the builder can configure, in offer order. Anything in
|
|
98
|
+
* `BUILTIN_FIELD_KINDS` but not here is builder-less by the §12 risk-5 rule.
|
|
99
|
+
*/
|
|
100
|
+
export declare const BUILDER_KINDS: readonly string[];
|
|
101
|
+
/** Can `<FormBuilder>` configure this kind? */
|
|
102
|
+
export declare function isBuilderSupportedKind(kind: string): boolean;
|
|
103
|
+
/** The kind's config declaration, or `undefined` when it ships builder-less. */
|
|
104
|
+
export declare function configFormFor(kind: string): KindConfigForm | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* The config defaults a freshly-added field of this kind starts with — every
|
|
107
|
+
* declared `default`, and nothing else. Keys with no upstream default stay
|
|
108
|
+
* ABSENT rather than being written as `null`: the engine's dataclass reads an
|
|
109
|
+
* absent key as "use my own default", and writing one changes behaviour.
|
|
110
|
+
*/
|
|
111
|
+
export declare function defaultConfigFor(kind: string): Record<string, unknown>;
|
|
112
|
+
//# sourceMappingURL=configForms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configForms.d.ts","sourceRoot":"","sources":["../../src/widgets/configForms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,MAAM,GACN,UAAU,GACV,mBAAmB,GACnB,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,QAAQ,GACR,6BAA6B,GAC7B,uBAAuB,GACvB,sBAAsB,GACtB,WAAW,GACX,iBAAiB,CAAC;AAEtB,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B;qEACiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;CAC7B;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CAC7C;AA0HD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAS5E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAS1C,CAAC;AAEF,+CAA+C;AAC/C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQtE"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The field-kind CONFIG CONTRACT — what `<FormBuilder>` is data-driven off.
|
|
3
|
+
*
|
|
4
|
+
* ── Why this table exists in TypeScript at all ─────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* `stapel_attributes.config_form` declares every feature type's admin config
|
|
7
|
+
* form as DATA (`FormField(name, kind, label_key, required, default, params)`)
|
|
8
|
+
* precisely so a builder needs no per-type UI. Its own docstring, however,
|
|
9
|
+
* records how that data reaches a client: *"Emitted server-side onto the admin
|
|
10
|
+
* page via the widget (**no endpoint**)."* There is no REST surface serving
|
|
11
|
+
* `form_declarations()` — not in stapel-attributes, and not among
|
|
12
|
+
* stapel-forms' 13 paths (verified against `docs/schema.json`).
|
|
13
|
+
*
|
|
14
|
+
* So this module MIRRORS the upstream declarations rather than fetching them.
|
|
15
|
+
* That is a real, named cost, not a design preference — see the spec delta
|
|
16
|
+
* filed for it. What the mirror buys is the property §8 actually asked for:
|
|
17
|
+
* the builder iterates a table, so a kind is configured by DATA and no kind
|
|
18
|
+
* gets a bespoke hand-written form. What it costs is that the table can drift
|
|
19
|
+
* from upstream until the endpoint exists; the drift is bounded by
|
|
20
|
+
* `test/configForms.test.ts`, which pins every entry against the values quoted
|
|
21
|
+
* from `config_form.py` here.
|
|
22
|
+
*
|
|
23
|
+
* Source: `stapel_attributes/config_form.py::BUILTIN_FORMS` (attributes 0.4.6).
|
|
24
|
+
*
|
|
25
|
+
* ── v1 scope, and the two kinds that ship builder-less ─────────────────────
|
|
26
|
+
*
|
|
27
|
+
* Spec §12 risk 5: *"if a kind's config form turns out unrepresentable, that
|
|
28
|
+
* kind ships builder-less (authorable via draft PUT) rather than growing
|
|
29
|
+
* bespoke UI."* Applying it honestly:
|
|
30
|
+
*
|
|
31
|
+
* - **`convertible_unit`** declares NO config form upstream (it is absent
|
|
32
|
+
* from `BUILTIN_FORMS`). Nothing to render → builder-less.
|
|
33
|
+
* - **`hierarchical_select`** declares exactly one field, of kind
|
|
34
|
+
* `hierarchical_options` — a tree editor. Its whole form is the
|
|
35
|
+
* unrepresentable part → builder-less.
|
|
36
|
+
*
|
|
37
|
+
* Both remain fully RENDERABLE (they have widgets) and fully authorable
|
|
38
|
+
* through `PUT /forms/<id>/draft`. The builder says so instead of pretending.
|
|
39
|
+
*
|
|
40
|
+
* Two individual config FIELDS are also v1-unrepresentable and are marked
|
|
41
|
+
* {@link ConfigFieldSpec.unsupported}: `date.options` (`timestamp_array`) and
|
|
42
|
+
* anything else using `hierarchical_options`. The builder renders the rest of
|
|
43
|
+
* that kind's form and states which options it cannot edit — dropping them
|
|
44
|
+
* silently would present a partial form as a complete one.
|
|
45
|
+
*/
|
|
46
|
+
function lk(type, field) {
|
|
47
|
+
return `admin.attributes.form.${type}.${field}`;
|
|
48
|
+
}
|
|
49
|
+
const INT_FIELDS = [
|
|
50
|
+
{ name: "min", kind: "number", labelKey: lk("int", "min"), step: 1 },
|
|
51
|
+
{ name: "max", kind: "number", labelKey: lk("int", "max"), step: 1 },
|
|
52
|
+
{ name: "options", kind: "number_options", labelKey: lk("int", "options") },
|
|
53
|
+
{ name: "allowCustom", kind: "checkbox", labelKey: lk("int", "allowCustom"), default: true },
|
|
54
|
+
{ name: "prefix", kind: "translatable_text", labelKey: lk("int", "prefix"), placeholder: "$" },
|
|
55
|
+
{ name: "postfix", kind: "translatable_text", labelKey: lk("int", "postfix"), placeholder: "km" },
|
|
56
|
+
{ name: "postfix1000", kind: "translatable_text", labelKey: lk("int", "postfix1000"), placeholder: "k" },
|
|
57
|
+
{ name: "placeholder", kind: "translatable_text", labelKey: lk("int", "placeholder") },
|
|
58
|
+
];
|
|
59
|
+
const FLOAT_FIELDS = [
|
|
60
|
+
{ name: "min", kind: "number", labelKey: lk("float", "min"), step: 0.01 },
|
|
61
|
+
{ name: "max", kind: "number", labelKey: lk("float", "max"), step: 0.01 },
|
|
62
|
+
{ name: "precision", kind: "number", labelKey: lk("float", "precision"), default: 2, step: 1 },
|
|
63
|
+
{ name: "options", kind: "number_options", labelKey: lk("float", "options") },
|
|
64
|
+
{ name: "allowCustom", kind: "checkbox", labelKey: lk("float", "allowCustom"), default: true },
|
|
65
|
+
{ name: "prefix", kind: "translatable_text", labelKey: lk("float", "prefix"), placeholder: "$" },
|
|
66
|
+
{ name: "postfix", kind: "translatable_text", labelKey: lk("float", "postfix"), placeholder: "m²" },
|
|
67
|
+
{ name: "postfix1000", kind: "translatable_text", labelKey: lk("float", "postfix1000"), placeholder: "k" },
|
|
68
|
+
{ name: "placeholder", kind: "translatable_text", labelKey: lk("float", "placeholder") },
|
|
69
|
+
];
|
|
70
|
+
const STRING_FIELDS = [
|
|
71
|
+
{ name: "minLength", kind: "number", labelKey: lk("string", "minLength"), step: 1 },
|
|
72
|
+
{ name: "maxLength", kind: "number", labelKey: lk("string", "maxLength"), step: 1 },
|
|
73
|
+
// stapel-attributes 0.4.6. Rendering metadata only — the string widget draws
|
|
74
|
+
// a textarea instead of an input. Absent means false, which is what every
|
|
75
|
+
// schema published against 0.4.5 (including stapel-forms 0.1.0's own tests)
|
|
76
|
+
// carries, so nothing stored needs a migration.
|
|
77
|
+
{ name: "multiline", kind: "checkbox", labelKey: lk("string", "multiline"), default: false },
|
|
78
|
+
{ name: "pattern", kind: "text", labelKey: lk("string", "pattern") },
|
|
79
|
+
{ name: "options", kind: "string_options", labelKey: lk("string", "options") },
|
|
80
|
+
{ name: "allowCustom", kind: "checkbox", labelKey: lk("string", "allowCustom"), default: true },
|
|
81
|
+
{ name: "prefix", kind: "translatable_text", labelKey: lk("string", "prefix"), placeholder: "$" },
|
|
82
|
+
{ name: "postfix", kind: "translatable_text", labelKey: lk("string", "postfix"), placeholder: "m²" },
|
|
83
|
+
{ name: "placeholder", kind: "translatable_text", labelKey: lk("string", "placeholder") },
|
|
84
|
+
];
|
|
85
|
+
const BOOL_FIELDS = [
|
|
86
|
+
{ name: "trueLabel", kind: "translatable_text", labelKey: lk("bool", "trueLabel"), placeholder: "yes" },
|
|
87
|
+
{ name: "falseLabel", kind: "translatable_text", labelKey: lk("bool", "falseLabel"), placeholder: "no" },
|
|
88
|
+
];
|
|
89
|
+
const HEX_COLOR_FIELDS = [
|
|
90
|
+
{ name: "options", kind: "color_options", labelKey: lk("hex_color", "options") },
|
|
91
|
+
// LN-B15: hex_color's allowCustom defaults FALSE, unlike int/float/string.
|
|
92
|
+
{ name: "allowCustom", kind: "checkbox", labelKey: lk("hex_color", "allowCustom"), default: false },
|
|
93
|
+
];
|
|
94
|
+
const SELECT_FIELDS = [
|
|
95
|
+
{ name: "options", kind: "select_options_with_default", labelKey: lk("select", "options") },
|
|
96
|
+
{
|
|
97
|
+
name: "uiStyle",
|
|
98
|
+
kind: "select",
|
|
99
|
+
labelKey: lk("select", "uiStyle"),
|
|
100
|
+
required: true,
|
|
101
|
+
// B2 canon: the untouched-form default MUST equal the engine dataclass
|
|
102
|
+
// default (SelectConfig.uiStyle = "dropdown"), so a select saved without
|
|
103
|
+
// touching this round-trips to what the UI displayed.
|
|
104
|
+
default: "dropdown",
|
|
105
|
+
options: [
|
|
106
|
+
{ value: "chips", label: "Chips/Tags" },
|
|
107
|
+
{ value: "checkboxes", label: "Checkboxes (like checklist)" },
|
|
108
|
+
{ value: "dropdown", label: "Dropdown" },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{ name: "minSelected", kind: "number", labelKey: lk("select", "minSelected"), default: 0, step: 1 },
|
|
112
|
+
// No default: SelectConfig.maxSelected is None = unlimited, and the widget
|
|
113
|
+
// shows "Unlimited" for an absent value.
|
|
114
|
+
{ name: "maxSelected", kind: "max_selected_dropdown", labelKey: lk("select", "maxSelected") },
|
|
115
|
+
{ name: "lockUserInput", kind: "checkbox", labelKey: lk("select", "lockUserInput") },
|
|
116
|
+
];
|
|
117
|
+
const DATE_FIELDS = [
|
|
118
|
+
{
|
|
119
|
+
name: "precision",
|
|
120
|
+
kind: "select",
|
|
121
|
+
labelKey: lk("date", "precision"),
|
|
122
|
+
required: true,
|
|
123
|
+
default: "date",
|
|
124
|
+
options: [
|
|
125
|
+
{ value: "year", label: "Year only" },
|
|
126
|
+
{ value: "month", label: "Month (year + month)" },
|
|
127
|
+
{ value: "date", label: "Date (year + month + day)" },
|
|
128
|
+
{ value: "datetime", label: "Date & Time" },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{ name: "minDate", kind: "timestamp", labelKey: lk("date", "minDate") },
|
|
132
|
+
{ name: "maxDate", kind: "timestamp", labelKey: lk("date", "maxDate") },
|
|
133
|
+
{ name: "allowFuture", kind: "checkbox", labelKey: lk("date", "allowFuture"), default: true },
|
|
134
|
+
{ name: "allowPast", kind: "checkbox", labelKey: lk("date", "allowPast"), default: true },
|
|
135
|
+
// Upstream names this field literally "default".
|
|
136
|
+
{ name: "default", kind: "timestamp", labelKey: lk("date", "default") },
|
|
137
|
+
{ name: "options", kind: "timestamp_array", labelKey: lk("date", "options"), unsupported: true },
|
|
138
|
+
{ name: "lockInput", kind: "checkbox", labelKey: lk("date", "lockInput") },
|
|
139
|
+
{ name: "placeholder", kind: "text", labelKey: lk("date", "placeholder") },
|
|
140
|
+
];
|
|
141
|
+
const HEADER_FIELDS = [
|
|
142
|
+
{
|
|
143
|
+
name: "style",
|
|
144
|
+
kind: "select",
|
|
145
|
+
labelKey: lk("header", "style"),
|
|
146
|
+
required: true,
|
|
147
|
+
// LN-B01, preserved deliberately: the upstream default "h2" matches
|
|
148
|
+
// NEITHER option value. Mirrored rather than "fixed" — silently changing
|
|
149
|
+
// it here would make the builder disagree with the engine.
|
|
150
|
+
default: "h2",
|
|
151
|
+
options: [
|
|
152
|
+
{ value: "l", label: "H1 - Large" },
|
|
153
|
+
{ value: "m", label: "H2 - Medium" },
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
/**
|
|
158
|
+
* Field kind → its config form. A kind ABSENT from this table ships
|
|
159
|
+
* builder-less (see the module header): `convertible_unit` (no upstream
|
|
160
|
+
* declaration) and `hierarchical_select` (its only field is a tree editor).
|
|
161
|
+
*/
|
|
162
|
+
export const FIELD_KIND_CONFIG_FORMS = {
|
|
163
|
+
int: { labelKey: "admin.attributes.type.int", fields: INT_FIELDS },
|
|
164
|
+
float: { labelKey: "admin.attributes.type.float", fields: FLOAT_FIELDS },
|
|
165
|
+
string: { labelKey: "admin.attributes.type.string", fields: STRING_FIELDS },
|
|
166
|
+
bool: { labelKey: "admin.attributes.type.bool", fields: BOOL_FIELDS },
|
|
167
|
+
hex_color: { labelKey: "admin.attributes.type.hex_color", fields: HEX_COLOR_FIELDS },
|
|
168
|
+
select: { labelKey: "admin.attributes.type.select", fields: SELECT_FIELDS },
|
|
169
|
+
date: { labelKey: "admin.attributes.type.date", fields: DATE_FIELDS },
|
|
170
|
+
header: { labelKey: "admin.attributes.type.header", fields: HEADER_FIELDS },
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* The kinds the builder can configure, in offer order. Anything in
|
|
174
|
+
* `BUILTIN_FIELD_KINDS` but not here is builder-less by the §12 risk-5 rule.
|
|
175
|
+
*/
|
|
176
|
+
export const BUILDER_KINDS = [
|
|
177
|
+
"string",
|
|
178
|
+
"int",
|
|
179
|
+
"float",
|
|
180
|
+
"bool",
|
|
181
|
+
"select",
|
|
182
|
+
"date",
|
|
183
|
+
"header",
|
|
184
|
+
"hex_color",
|
|
185
|
+
];
|
|
186
|
+
/** Can `<FormBuilder>` configure this kind? */
|
|
187
|
+
export function isBuilderSupportedKind(kind) {
|
|
188
|
+
return Object.prototype.hasOwnProperty.call(FIELD_KIND_CONFIG_FORMS, kind);
|
|
189
|
+
}
|
|
190
|
+
/** The kind's config declaration, or `undefined` when it ships builder-less. */
|
|
191
|
+
export function configFormFor(kind) {
|
|
192
|
+
return FIELD_KIND_CONFIG_FORMS[kind];
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The config defaults a freshly-added field of this kind starts with — every
|
|
196
|
+
* declared `default`, and nothing else. Keys with no upstream default stay
|
|
197
|
+
* ABSENT rather than being written as `null`: the engine's dataclass reads an
|
|
198
|
+
* absent key as "use my own default", and writing one changes behaviour.
|
|
199
|
+
*/
|
|
200
|
+
export function defaultConfigFor(kind) {
|
|
201
|
+
const form = configFormFor(kind);
|
|
202
|
+
if (form === undefined)
|
|
203
|
+
return {};
|
|
204
|
+
const config = {};
|
|
205
|
+
for (const field of form.fields) {
|
|
206
|
+
if (field.default !== undefined)
|
|
207
|
+
config[field.name] = field.default;
|
|
208
|
+
}
|
|
209
|
+
return config;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=configForms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configForms.js","sourceRoot":"","sources":["../../src/widgets/configForms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AA+DH,SAAS,EAAE,CAAC,IAAY,EAAE,KAAa;IACrC,OAAO,yBAAyB,IAAI,IAAI,KAAK,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,GAA+B;IAC7C,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IACpE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IACpE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE;IAC3E,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;IAC5F,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;IAC9F,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;IACjG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;IACxG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE;CACvF,CAAC;AAEF,MAAM,YAAY,GAA+B;IAC/C,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;IACzE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;IACzE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IAC9F,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE;IAC7E,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;IAC9F,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;IAChG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;IACnG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;IAC1G,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE;CACzF,CAAC;AAEF,MAAM,aAAa,GAA+B;IAChD,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IACnF,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IACnF,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,gDAAgD;IAChD,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;IAC5F,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;IACpE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;IAC9E,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;IAC/F,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;IACjG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;IACpG,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE;CAC1F,CAAC;AAEF,MAAM,WAAW,GAA+B;IAC9C,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE;IACvG,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;CACzG,CAAC;AAEF,MAAM,gBAAgB,GAA+B;IACnD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE;IAChF,2EAA2E;IAC3E,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;CACpG,CAAC;AAEF,MAAM,aAAa,GAA+B;IAChD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,6BAA6B,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;IAC3F;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;QACjC,QAAQ,EAAE,IAAI;QACd,uEAAuE;QACvE,yEAAyE;QACzE,sDAAsD;QACtD,OAAO,EAAE,UAAU;QACnB,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE;YACvC,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,6BAA6B,EAAE;YAC7D,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;SACzC;KACF;IACD,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;IACnG,2EAA2E;IAC3E,yCAAyC;IACzC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,uBAAuB,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE;IAC7F,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE;CACrF,CAAC;AAEF,MAAM,WAAW,GAA+B;IAC9C;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC;QACjC,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,MAAM;QACf,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE;YACrC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE;YACjD,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,2BAA2B,EAAE;YACrD,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE;SAC5C;KACF;IACD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;IACvE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;IACvE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;IAC7F,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;IACzF,iDAAiD;IACjD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE;IACvE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;IAChG,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;IAC1E,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE;CAC3E,CAAC;AAEF,MAAM,aAAa,GAA+B;IAChD;QACE,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC/B,QAAQ,EAAE,IAAI;QACd,oEAAoE;QACpE,yEAAyE;QACzE,2DAA2D;QAC3D,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE;YACnC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE;SACrC;KACF;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAA6C;IAC/E,GAAG,EAAE,EAAE,QAAQ,EAAE,2BAA2B,EAAE,MAAM,EAAE,UAAU,EAAE;IAClE,KAAK,EAAE,EAAE,QAAQ,EAAE,6BAA6B,EAAE,MAAM,EAAE,YAAY,EAAE;IACxE,MAAM,EAAE,EAAE,QAAQ,EAAE,8BAA8B,EAAE,MAAM,EAAE,aAAa,EAAE;IAC3E,IAAI,EAAE,EAAE,QAAQ,EAAE,4BAA4B,EAAE,MAAM,EAAE,WAAW,EAAE;IACrE,SAAS,EAAE,EAAE,QAAQ,EAAE,iCAAiC,EAAE,MAAM,EAAE,gBAAgB,EAAE;IACpF,MAAM,EAAE,EAAE,QAAQ,EAAE,8BAA8B,EAAE,MAAM,EAAE,aAAa,EAAE;IAC3E,IAAI,EAAE,EAAE,QAAQ,EAAE,4BAA4B,EAAE,MAAM,EAAE,WAAW,EAAE;IACrE,MAAM,EAAE,EAAE,QAAQ,EAAE,8BAA8B,EAAE,MAAM,EAAE,aAAa,EAAE;CAC5E,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC9C,QAAQ;IACR,KAAK;IACL,OAAO;IACP,MAAM;IACN,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,WAAW;CACZ,CAAC;AAEF,+CAA+C;AAC/C,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The field-widget registry — THE customer seam of this pair, and the direct
|
|
3
|
+
* descendant of docs-react's editor registry.
|
|
4
|
+
*
|
|
5
|
+
* A form schema's fields are `stapel_attributes` `FeatureDef`s, and that type
|
|
6
|
+
* vocabulary is an OPEN registry server-side (builtins →
|
|
7
|
+
* `STAPEL_ATTRIBUTES["EXTRA_TYPES"]` → runtime `register_feature_type`). A
|
|
8
|
+
* host that adds a type on the backend must be able to render it on the front
|
|
9
|
+
* without forking the skin:
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* registerFormFieldWidget("signature", SignaturePad); // at startup
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* ── Resolution, and what happens when nothing matches ──────────────────────
|
|
16
|
+
*
|
|
17
|
+
* This module answers only the FIRST rung: an explicit registration, or
|
|
18
|
+
* `null`. The `/default` skin completes the ladder — explicit registration >
|
|
19
|
+
* skin builtin (antd) > **unsupported-field notice** — mirroring
|
|
20
|
+
* docs-react's `DocSurface`, where an explicit `registerDocEditor` outranks
|
|
21
|
+
* the skin's own styled default so a host's swap is never shadowed.
|
|
22
|
+
*
|
|
23
|
+
* The last rung is a notice, deliberately, and never a skipped field. A
|
|
24
|
+
* schema can legally contain a kind this build has no widget for; rendering
|
|
25
|
+
* nothing would silently drop a field that may be REQUIRED, and the person
|
|
26
|
+
* would submit a form they could not complete and be told, by the server,
|
|
27
|
+
* that a field they never saw is missing. `<FormFill>` therefore also blocks
|
|
28
|
+
* the submit with `forms.unsupported_kind` while such a field is present —
|
|
29
|
+
* degrade loudly (spec §7.2).
|
|
30
|
+
*
|
|
31
|
+
* The registry lives in the main entry, not in `/default`, so a host building
|
|
32
|
+
* its own renderer over `<FormFill>` uses the same seam as the skin does
|
|
33
|
+
* rather than a parallel one.
|
|
34
|
+
*/
|
|
35
|
+
import type { ComponentType } from "react";
|
|
36
|
+
import type { FlowError } from "@stapel/core";
|
|
37
|
+
import type { FormFieldDef } from "../api/types.js";
|
|
38
|
+
/**
|
|
39
|
+
* What every field widget receives. One field, one value, one setter, one
|
|
40
|
+
* error — the widget never touches the API layer or the rest of the form.
|
|
41
|
+
*/
|
|
42
|
+
export interface FormFieldWidgetProps {
|
|
43
|
+
/** The field's `FeatureDef`. `field.config` carries the kind's camelCase
|
|
44
|
+
* options (`maxLength`, `minSelected`, `precision`, `multiline`, …). */
|
|
45
|
+
readonly field: FormFieldDef;
|
|
46
|
+
/** The current answer, or `undefined` while unanswered. */
|
|
47
|
+
readonly value: unknown;
|
|
48
|
+
/** Report a new answer. Pass the bare scalar — `select` normalizes to a
|
|
49
|
+
* list server-side, so a single choice need not be wrapped. */
|
|
50
|
+
onChange(value: unknown): void;
|
|
51
|
+
/** The field's current refusal (client mirror or server verdict), or
|
|
52
|
+
* `undefined`. */
|
|
53
|
+
readonly error: FlowError | undefined;
|
|
54
|
+
/** True while a submit is in flight — widgets should go read-only. */
|
|
55
|
+
readonly disabled: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* DOM id the widget MUST put on its primary control. The skin's field row
|
|
58
|
+
* points its `<label for>` at this, so the label actually names the input
|
|
59
|
+
* for a screen reader (and for a click). A widget that drops it renders an
|
|
60
|
+
* unlabelled control — which antd's `Form.Item` cannot detect and will
|
|
61
|
+
* happily draw a label beside.
|
|
62
|
+
*/
|
|
63
|
+
readonly id: string;
|
|
64
|
+
}
|
|
65
|
+
export type FormFieldWidget = ComponentType<FormFieldWidgetProps>;
|
|
66
|
+
/**
|
|
67
|
+
* Register (or override) the widget for a field kind. Call at startup, before
|
|
68
|
+
* the first render — the registry is module-global, like the i18n bundle
|
|
69
|
+
* registration and docs-react's editor registry.
|
|
70
|
+
*/
|
|
71
|
+
export declare function registerFormFieldWidget(kind: string, widget: FormFieldWidget): void;
|
|
72
|
+
/** Remove an explicit registration (the skin's builtin, if any, resolves
|
|
73
|
+
* again). */
|
|
74
|
+
export declare function unregisterFormFieldWidget(kind: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* The EXPLICIT registration for a kind, or `null`. Named for what it is: the
|
|
77
|
+
* skin calls this FIRST and only falls back to its own builtin when it
|
|
78
|
+
* returns `null`, so a host registration always wins.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resolveFormFieldWidget(kind: string): FormFieldWidget | null;
|
|
81
|
+
/** Every kind with an explicit registration, sorted. */
|
|
82
|
+
export declare function registeredFormFieldKinds(): readonly string[];
|
|
83
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/widgets/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;4EACwE;IACxE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;mEAC+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B;sBACkB;IAClB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC,oBAAoB,CAAC,CAAC;AAIlE;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,GACtB,IAAI,CAEN;AAED;aACa;AACb,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAE3E;AAED,wDAAwD;AACxD,wBAAgB,wBAAwB,IAAI,SAAS,MAAM,EAAE,CAE5D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const registered = new Map();
|
|
2
|
+
/**
|
|
3
|
+
* Register (or override) the widget for a field kind. Call at startup, before
|
|
4
|
+
* the first render — the registry is module-global, like the i18n bundle
|
|
5
|
+
* registration and docs-react's editor registry.
|
|
6
|
+
*/
|
|
7
|
+
export function registerFormFieldWidget(kind, widget) {
|
|
8
|
+
registered.set(kind, widget);
|
|
9
|
+
}
|
|
10
|
+
/** Remove an explicit registration (the skin's builtin, if any, resolves
|
|
11
|
+
* again). */
|
|
12
|
+
export function unregisterFormFieldWidget(kind) {
|
|
13
|
+
registered.delete(kind);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The EXPLICIT registration for a kind, or `null`. Named for what it is: the
|
|
17
|
+
* skin calls this FIRST and only falls back to its own builtin when it
|
|
18
|
+
* returns `null`, so a host registration always wins.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveFormFieldWidget(kind) {
|
|
21
|
+
return registered.get(kind) ?? null;
|
|
22
|
+
}
|
|
23
|
+
/** Every kind with an explicit registration, sorted. */
|
|
24
|
+
export function registeredFormFieldKinds() {
|
|
25
|
+
return [...registered.keys()].sort();
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/widgets/registry.ts"],"names":[],"mappings":"AAoEA,MAAM,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEtD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAY,EACZ,MAAuB;IAEvB,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;aACa;AACb,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,wBAAwB;IACtC,OAAO,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The client-side validation MIRROR — instant feedback, never a verdict.
|
|
3
|
+
*
|
|
4
|
+
* "Client-side validation mirrors, server decides" (spec §7.2). Every rule
|
|
5
|
+
* here is derived from the schema's own `config` so the person sees a problem
|
|
6
|
+
* as they type instead of after a round trip; none of it is trusted. The
|
|
7
|
+
* server re-runs `stapel_attributes.validate_dto_structured` on every submit
|
|
8
|
+
* and its answer is the one that counts.
|
|
9
|
+
*
|
|
10
|
+
* ── Why the mirror emits the SERVER's error keys ───────────────────────────
|
|
11
|
+
*
|
|
12
|
+
* Each rule below reports the exact `error.400.feature_*` key
|
|
13
|
+
* (`stapel_attributes.errors.ERROR_CODE_TO_KEY`) the backend would have
|
|
14
|
+
* returned for the same input, with the same `{feature}`/`{field}` params. So
|
|
15
|
+
* a "too long" caught locally and a "too long" caught by the server render
|
|
16
|
+
* the SAME sentence in the SAME language. The alternative — pair-invented
|
|
17
|
+
* copy for the local half — gives the person two different wordings for one
|
|
18
|
+
* problem and makes the local one a lie the moment the backend's rule moves.
|
|
19
|
+
*
|
|
20
|
+
* ── camelCase, and the cap that does not exist ─────────────────────────────
|
|
21
|
+
*
|
|
22
|
+
* Config keys are camelCase (`maxLength`, not `max_length`) — backend delta
|
|
23
|
+
* note 1. A type's dataclass parser drops keys it does not know, so a
|
|
24
|
+
* snake_case typo is a constraint that silently does not exist. `publish`
|
|
25
|
+
* refuses those server-side; this mirror simply reads the camelCase names and
|
|
26
|
+
* therefore agrees with the engine by construction.
|
|
27
|
+
*/
|
|
28
|
+
import type { FlowError } from "@stapel/core";
|
|
29
|
+
import type { FormFieldDef } from "../api/types.js";
|
|
30
|
+
/** The `error.400.feature_*` keys this mirror can raise — a subset of
|
|
31
|
+
* `stapel_attributes.errors.ATTRIBUTES_ERRORS`, listed so the i18n bundle can
|
|
32
|
+
* be checked against it. */
|
|
33
|
+
export declare const FEATURE_ERROR_CODES: readonly string[];
|
|
34
|
+
/** The declared choice values of an options-bearing config, or `undefined`
|
|
35
|
+
* when the kind has none. Accepts both the bare-scalar and the
|
|
36
|
+
* `{value, label}` option shapes the attributes types allow. */
|
|
37
|
+
export declare function optionValues(field: FormFieldDef): readonly unknown[] | undefined;
|
|
38
|
+
/** True when the answer is "nothing was entered" — the one shape the
|
|
39
|
+
* mandatory rule fires on. An explicit `false` is an ANSWER for a `bool`, not
|
|
40
|
+
* an absence, which is why this is not a falsiness check. */
|
|
41
|
+
export declare function isBlank(value: unknown): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Validate one answer against its field's config. Returns the mirrored
|
|
44
|
+
* refusal, or `undefined` when this side of the wire is satisfied.
|
|
45
|
+
*
|
|
46
|
+
* `header` fields are skipped outright: the engine regenerates a header's DAO
|
|
47
|
+
* from its config and REJECTS an answer to one (backend delta note 1), so a
|
|
48
|
+
* header has nothing to validate and must never be given a value.
|
|
49
|
+
*/
|
|
50
|
+
export declare function validateFieldValue(field: FormFieldDef, value: unknown): FlowError | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Validate a whole answer set. Returns `{slug: FlowError}` for the fields that
|
|
53
|
+
* failed — the exact shape `FormFillBag.fieldErrors` carries, so a server
|
|
54
|
+
* response can be merged into it without a translation step.
|
|
55
|
+
*/
|
|
56
|
+
export declare function validateAnswers(fields: readonly FormFieldDef[], values: Readonly<Record<string, unknown>>): Readonly<Record<string, FlowError>>;
|
|
57
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/widgets/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;4BAE4B;AAC5B,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOhD,CAAC;AA8BF;;gEAEgE;AAChE,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,GAClB,SAAS,OAAO,EAAE,GAAG,SAAS,CAQhC;AAED;;6DAE6D;AAC7D,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAK/C;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,OAAO,GACb,SAAS,GAAG,SAAS,CAoGvB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAOrC"}
|