@sonata-innovations/fiber-types 1.0.5 → 2.0.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/dist/component-accessors.d.ts +12 -0
- package/dist/component-accessors.d.ts.map +1 -0
- package/dist/component-accessors.js +39 -0
- package/dist/component-manifest.d.ts +39 -0
- package/dist/component-manifest.d.ts.map +1 -0
- package/dist/component-manifest.js +355 -0
- package/dist/component-variants.d.ts +51 -0
- package/dist/component-variants.d.ts.map +1 -0
- package/dist/component-variants.js +64 -0
- package/dist/flow.d.ts +21 -4
- package/dist/flow.d.ts.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/normalize-conditional-order.d.ts +8 -0
- package/dist/normalize-conditional-order.d.ts.map +1 -0
- package/dist/normalize-conditional-order.js +230 -0
- package/dist/uuid-regeneration.d.ts.map +1 -1
- package/dist/uuid-regeneration.js +7 -3
- package/dist/uuid.d.ts +2 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +5 -0
- package/package.json +4 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Component } from "./flow";
|
|
2
|
+
import type { FlowValidationConfig } from "./validation";
|
|
3
|
+
/** Returns the component's validation config if its property shape carries
|
|
4
|
+
* one. Returns `undefined` for display-only types (header/text/divider/
|
|
5
|
+
* callout/table/computed) and for `toggleSwitch`/`group`/`repeater`. */
|
|
6
|
+
export declare const getValidationConfig: (component: Component) => FlowValidationConfig | undefined;
|
|
7
|
+
/** Best human-readable identifier for a component, falling back from `label`
|
|
8
|
+
* to `title` to `value`. Returns `undefined` when no display string is set.
|
|
9
|
+
* Used by FBT/FBTL surfaces that need to name a component (stage cards, drag
|
|
10
|
+
* overlays, condition pickers, validation messages). */
|
|
11
|
+
export declare const getComponentDisplayLabel: (component: Component) => string | undefined;
|
|
12
|
+
//# sourceMappingURL=component-accessors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-accessors.d.ts","sourceRoot":"","sources":["../src/component-accessors.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD;;yEAEyE;AACzE,eAAO,MAAM,mBAAmB,GAC9B,WAAW,SAAS,KACnB,oBAAoB,GAAG,SAIzB,CAAC;AAEF;;;yDAGyD;AACzD,eAAO,MAAM,wBAAwB,GACnC,WAAW,SAAS,KACnB,MAAM,GAAG,SAYX,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Component accessors — narrow-access helpers across the discriminated union.
|
|
3
|
+
|
|
4
|
+
With `Component.properties` keyed on `type`, accessing a field that only
|
|
5
|
+
some variants carry (e.g. `validation`, `options`) requires narrowing. The
|
|
6
|
+
helpers here are the canonical narrowing patterns expressed once, so call
|
|
7
|
+
sites don't repeat the `"x" in props` boilerplate.
|
|
8
|
+
|
|
9
|
+
Add a new helper here only if the access pattern appears in multiple
|
|
10
|
+
packages and the narrowing rule is the same for every component type that
|
|
11
|
+
exposes the field. One-off accesses inside a single file should narrow
|
|
12
|
+
inline (`"options" in c.properties ? c.properties.options : undefined`)
|
|
13
|
+
rather than spawning a helper.
|
|
14
|
+
========================================================================== */
|
|
15
|
+
/** Returns the component's validation config if its property shape carries
|
|
16
|
+
* one. Returns `undefined` for display-only types (header/text/divider/
|
|
17
|
+
* callout/table/computed) and for `toggleSwitch`/`group`/`repeater`. */
|
|
18
|
+
export const getValidationConfig = (component) => {
|
|
19
|
+
return "validation" in component.properties
|
|
20
|
+
? component.properties.validation
|
|
21
|
+
: undefined;
|
|
22
|
+
};
|
|
23
|
+
/** Best human-readable identifier for a component, falling back from `label`
|
|
24
|
+
* to `title` to `value`. Returns `undefined` when no display string is set.
|
|
25
|
+
* Used by FBT/FBTL surfaces that need to name a component (stage cards, drag
|
|
26
|
+
* overlays, condition pickers, validation messages). */
|
|
27
|
+
export const getComponentDisplayLabel = (component) => {
|
|
28
|
+
const props = component.properties;
|
|
29
|
+
if ("label" in props && typeof props.label === "string" && props.label) {
|
|
30
|
+
return props.label;
|
|
31
|
+
}
|
|
32
|
+
if ("title" in props && typeof props.title === "string" && props.title) {
|
|
33
|
+
return props.title;
|
|
34
|
+
}
|
|
35
|
+
if ("value" in props && typeof props.value === "string" && props.value) {
|
|
36
|
+
return props.value;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ValidationRuleType } from "./validation";
|
|
2
|
+
export type ComponentCategory = "display" | "input" | "selection" | "datetime" | "interactive" | "container";
|
|
3
|
+
export type ComponentManifestEntry = {
|
|
4
|
+
/** Stable type id used everywhere — Flow JSON, registry keys, props.type. */
|
|
5
|
+
type: string;
|
|
6
|
+
/** Human-readable label shown in the palette and badges. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Icon key used by FBT (resolved via the FBT icon registry). */
|
|
9
|
+
iconKey: string;
|
|
10
|
+
/** UI grouping — drives the pool section and the category badge. */
|
|
11
|
+
category: ComponentCategory;
|
|
12
|
+
/** True for components that render content but never contribute to FlowData
|
|
13
|
+
* and cannot be condition sources or validation targets. */
|
|
14
|
+
displayOnly: boolean;
|
|
15
|
+
/** Validation rules the FBT editor offers for this type. An empty array
|
|
16
|
+
* means the editor surfaces no validation UI. */
|
|
17
|
+
validationRules: readonly ValidationRuleType[];
|
|
18
|
+
/** Doc-only pointer to the TS property type in `properties.ts`.
|
|
19
|
+
* Not used at runtime — exists so a reader can jump from manifest entry to
|
|
20
|
+
* shape definition without grep. */
|
|
21
|
+
propertiesTypeName: string;
|
|
22
|
+
};
|
|
23
|
+
/** Frozen, ordered list of every registered component type. The order is the
|
|
24
|
+
* canonical pool-section order (display → input → selection → datetime →
|
|
25
|
+
* interactive → container) and matches the FBT pool. */
|
|
26
|
+
export declare const COMPONENT_MANIFEST: readonly ComponentManifestEntry[];
|
|
27
|
+
/** Stable, immutable list of all registered component type ids. */
|
|
28
|
+
export declare const COMPONENT_TYPES: readonly string[];
|
|
29
|
+
/** Component types that render content but never contribute to FlowData. */
|
|
30
|
+
export declare const DISPLAY_ONLY_TYPES: ReadonlySet<string>;
|
|
31
|
+
/** Human-readable label for the category badge / pool section header. */
|
|
32
|
+
export declare const CATEGORY_LABELS: Record<ComponentCategory, string>;
|
|
33
|
+
/** Look up a manifest entry by component type id. Returns undefined for
|
|
34
|
+
* unrecognized types — callers decide whether that is an error. */
|
|
35
|
+
export declare function getComponentManifestEntry(type: string): ComponentManifestEntry | undefined;
|
|
36
|
+
/** Manifest entries grouped by category, preserving manifest order within
|
|
37
|
+
* each group. Drives the FBT pool layout. */
|
|
38
|
+
export declare function getManifestByCategory(): Record<ComponentCategory, readonly ComponentManifestEntry[]>;
|
|
39
|
+
//# sourceMappingURL=component-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-manifest.d.ts","sourceRoot":"","sources":["../src/component-manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,OAAO,GACP,WAAW,GACX,UAAU,GACV,aAAa,GACb,WAAW,CAAC;AAEhB,MAAM,MAAM,sBAAsB,GAAG;IACnC,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,EAAE,iBAAiB,CAAC;IAC5B;iEAC6D;IAC7D,WAAW,EAAE,OAAO,CAAC;IACrB;sDACkD;IAClD,eAAe,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC/C;;yCAEqC;IACrC,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAuTF;;yDAEyD;AACzD,eAAO,MAAM,kBAAkB,EAAE,SAAS,sBAAsB,EAAY,CAAC;AAE7E,mEAAmE;AACnE,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAA+B,CAAC;AAE7E,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAElD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAO7D,CAAC;AAEF;oEACoE;AACpE,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,GACX,sBAAsB,GAAG,SAAS,CAEpC;AAED;8CAC8C;AAC9C,wBAAgB,qBAAqB,IAAI,MAAM,CAC7C,iBAAiB,EACjB,SAAS,sBAAsB,EAAE,CAClC,CAaA"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Component Manifest — single source of truth for the registered component
|
|
3
|
+
types. Every package that needs per-type metadata (labels, icons,
|
|
4
|
+
categories, display-only behavior, allowed validation rules) derives that
|
|
5
|
+
knowledge from this file rather than restating it.
|
|
6
|
+
|
|
7
|
+
Adding a new component type means:
|
|
8
|
+
(1) add an entry here,
|
|
9
|
+
(2) add the property type in `properties.ts`,
|
|
10
|
+
(3) register a renderer in FBRE (`registerComponent`),
|
|
11
|
+
(4) add a field-map entry in FBT (`fbt/src/ui/editor/field-map.tsx`).
|
|
12
|
+
|
|
13
|
+
The parity guard in `fbre/src/__tests__/manifest-parity.test.ts` fails if
|
|
14
|
+
the renderer set drifts from the manifest, and the FBT-side guard fails if
|
|
15
|
+
the field-map drifts. Silent registry drift was the largest growth-friction
|
|
16
|
+
item in the 2026-05-19 core libs audit (HIGH-1); this file closes that gap.
|
|
17
|
+
========================================================================== */
|
|
18
|
+
const ENTRIES = [
|
|
19
|
+
// ---------- Display ----------
|
|
20
|
+
{
|
|
21
|
+
type: "header",
|
|
22
|
+
label: "Header",
|
|
23
|
+
iconKey: "header",
|
|
24
|
+
category: "display",
|
|
25
|
+
displayOnly: true,
|
|
26
|
+
validationRules: [],
|
|
27
|
+
propertiesTypeName: "ComponentDisplayProperties",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
label: "Description Text",
|
|
32
|
+
iconKey: "descriptionText",
|
|
33
|
+
category: "display",
|
|
34
|
+
displayOnly: true,
|
|
35
|
+
validationRules: [],
|
|
36
|
+
propertiesTypeName: "ComponentDisplayProperties",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: "divider",
|
|
40
|
+
label: "Divider",
|
|
41
|
+
iconKey: "divider",
|
|
42
|
+
category: "display",
|
|
43
|
+
displayOnly: true,
|
|
44
|
+
validationRules: [],
|
|
45
|
+
propertiesTypeName: "ComponentDividerProperties",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "callout",
|
|
49
|
+
label: "Callout",
|
|
50
|
+
iconKey: "callout",
|
|
51
|
+
category: "display",
|
|
52
|
+
displayOnly: true,
|
|
53
|
+
validationRules: [],
|
|
54
|
+
propertiesTypeName: "ComponentCalloutProperties",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "table",
|
|
58
|
+
label: "Table",
|
|
59
|
+
iconKey: "table",
|
|
60
|
+
category: "display",
|
|
61
|
+
displayOnly: true,
|
|
62
|
+
validationRules: [],
|
|
63
|
+
propertiesTypeName: "ComponentTableProperties",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: "computed",
|
|
67
|
+
label: "Calculated Field",
|
|
68
|
+
iconKey: "calculated",
|
|
69
|
+
category: "display",
|
|
70
|
+
displayOnly: false,
|
|
71
|
+
validationRules: [],
|
|
72
|
+
propertiesTypeName: "ComponentComputedProperties",
|
|
73
|
+
},
|
|
74
|
+
// ---------- Text & Number ----------
|
|
75
|
+
{
|
|
76
|
+
type: "inputText",
|
|
77
|
+
label: "Text Input",
|
|
78
|
+
iconKey: "textInput",
|
|
79
|
+
category: "input",
|
|
80
|
+
displayOnly: false,
|
|
81
|
+
validationRules: [
|
|
82
|
+
"required",
|
|
83
|
+
"email",
|
|
84
|
+
"phone",
|
|
85
|
+
"url",
|
|
86
|
+
"minLength",
|
|
87
|
+
"maxLength",
|
|
88
|
+
"exactLength",
|
|
89
|
+
"pattern",
|
|
90
|
+
"contains",
|
|
91
|
+
"excludes",
|
|
92
|
+
"matchesField",
|
|
93
|
+
],
|
|
94
|
+
propertiesTypeName: "ComponentInputProperties",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "inputTextArea",
|
|
98
|
+
label: "Text Area",
|
|
99
|
+
iconKey: "textArea",
|
|
100
|
+
category: "input",
|
|
101
|
+
displayOnly: false,
|
|
102
|
+
validationRules: [
|
|
103
|
+
"required",
|
|
104
|
+
"minLength",
|
|
105
|
+
"maxLength",
|
|
106
|
+
"exactLength",
|
|
107
|
+
"pattern",
|
|
108
|
+
"contains",
|
|
109
|
+
"excludes",
|
|
110
|
+
"matchesField",
|
|
111
|
+
],
|
|
112
|
+
propertiesTypeName: "ComponentInputProperties",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: "inputNumber",
|
|
116
|
+
label: "Number Input",
|
|
117
|
+
iconKey: "numberInput",
|
|
118
|
+
category: "input",
|
|
119
|
+
displayOnly: false,
|
|
120
|
+
validationRules: ["required", "minValue", "maxValue", "matchesField"],
|
|
121
|
+
propertiesTypeName: "ComponentInputProperties",
|
|
122
|
+
},
|
|
123
|
+
// ---------- Selection ----------
|
|
124
|
+
{
|
|
125
|
+
type: "dropDown",
|
|
126
|
+
label: "Select",
|
|
127
|
+
iconKey: "select",
|
|
128
|
+
category: "selection",
|
|
129
|
+
displayOnly: false,
|
|
130
|
+
validationRules: ["required"],
|
|
131
|
+
propertiesTypeName: "ComponentOptionProperties",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
type: "dropDownMulti",
|
|
135
|
+
label: "Multi-select",
|
|
136
|
+
iconKey: "multiSelect",
|
|
137
|
+
category: "selection",
|
|
138
|
+
displayOnly: false,
|
|
139
|
+
validationRules: ["required", "minSelected", "maxSelected"],
|
|
140
|
+
propertiesTypeName: "ComponentOptionProperties",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: "checkbox",
|
|
144
|
+
label: "Checkbox",
|
|
145
|
+
iconKey: "checkbox",
|
|
146
|
+
category: "selection",
|
|
147
|
+
displayOnly: false,
|
|
148
|
+
validationRules: ["required", "minSelected", "maxSelected"],
|
|
149
|
+
propertiesTypeName: "ComponentOptionProperties",
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
type: "radio",
|
|
153
|
+
label: "Radio",
|
|
154
|
+
iconKey: "radio",
|
|
155
|
+
category: "selection",
|
|
156
|
+
displayOnly: false,
|
|
157
|
+
validationRules: ["required"],
|
|
158
|
+
propertiesTypeName: "ComponentOptionProperties",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "toggleSwitch",
|
|
162
|
+
label: "Toggle Switch",
|
|
163
|
+
iconKey: "toggleSwitch",
|
|
164
|
+
category: "selection",
|
|
165
|
+
displayOnly: false,
|
|
166
|
+
validationRules: [],
|
|
167
|
+
propertiesTypeName: "ComponentSwitchProperties",
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: "yesNo",
|
|
171
|
+
label: "Yes / No",
|
|
172
|
+
iconKey: "yesNo",
|
|
173
|
+
category: "selection",
|
|
174
|
+
displayOnly: false,
|
|
175
|
+
validationRules: ["required"],
|
|
176
|
+
propertiesTypeName: "ComponentYesNoProperties",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
type: "confirm",
|
|
180
|
+
label: "Confirmation",
|
|
181
|
+
iconKey: "confirm",
|
|
182
|
+
category: "selection",
|
|
183
|
+
displayOnly: false,
|
|
184
|
+
validationRules: ["required"],
|
|
185
|
+
propertiesTypeName: "ComponentConfirmProperties",
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
type: "cardSelect",
|
|
189
|
+
label: "Card Select",
|
|
190
|
+
iconKey: "cardSelect",
|
|
191
|
+
category: "selection",
|
|
192
|
+
displayOnly: false,
|
|
193
|
+
validationRules: ["required"],
|
|
194
|
+
propertiesTypeName: "ComponentCardSelectProperties",
|
|
195
|
+
},
|
|
196
|
+
// ---------- Date & Time ----------
|
|
197
|
+
{
|
|
198
|
+
type: "date",
|
|
199
|
+
label: "Date",
|
|
200
|
+
iconKey: "date",
|
|
201
|
+
category: "datetime",
|
|
202
|
+
displayOnly: false,
|
|
203
|
+
validationRules: ["required"],
|
|
204
|
+
propertiesTypeName: "ComponentDateProperties",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
type: "time",
|
|
208
|
+
label: "Time",
|
|
209
|
+
iconKey: "time",
|
|
210
|
+
category: "datetime",
|
|
211
|
+
displayOnly: false,
|
|
212
|
+
validationRules: ["required"],
|
|
213
|
+
propertiesTypeName: "ComponentTimeProperties",
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: "dateTime",
|
|
217
|
+
label: "Date & Time",
|
|
218
|
+
iconKey: "dateTime",
|
|
219
|
+
category: "datetime",
|
|
220
|
+
displayOnly: false,
|
|
221
|
+
validationRules: ["required"],
|
|
222
|
+
propertiesTypeName: "ComponentDateTimeProperties",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
type: "dateRange",
|
|
226
|
+
label: "Date Range",
|
|
227
|
+
iconKey: "dateRange",
|
|
228
|
+
category: "datetime",
|
|
229
|
+
displayOnly: false,
|
|
230
|
+
validationRules: ["required"],
|
|
231
|
+
propertiesTypeName: "ComponentDateRangeProperties",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
type: "timeRange",
|
|
235
|
+
label: "Time Range",
|
|
236
|
+
iconKey: "timeRange",
|
|
237
|
+
category: "datetime",
|
|
238
|
+
displayOnly: false,
|
|
239
|
+
validationRules: ["required"],
|
|
240
|
+
propertiesTypeName: "ComponentTimeRangeProperties",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
type: "dateTimeRange",
|
|
244
|
+
label: "Date & Time Range",
|
|
245
|
+
iconKey: "dateTimeRange",
|
|
246
|
+
category: "datetime",
|
|
247
|
+
displayOnly: false,
|
|
248
|
+
validationRules: ["required"],
|
|
249
|
+
propertiesTypeName: "ComponentDateTimeRangeProperties",
|
|
250
|
+
},
|
|
251
|
+
// ---------- Interactive ----------
|
|
252
|
+
{
|
|
253
|
+
type: "fileUpload",
|
|
254
|
+
label: "File Upload",
|
|
255
|
+
iconKey: "fileUpload",
|
|
256
|
+
category: "interactive",
|
|
257
|
+
displayOnly: false,
|
|
258
|
+
validationRules: ["required", "fileType", "fileSize"],
|
|
259
|
+
propertiesTypeName: "ComponentFileUploadProperties",
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
type: "rating",
|
|
263
|
+
label: "Rating",
|
|
264
|
+
iconKey: "rating",
|
|
265
|
+
category: "interactive",
|
|
266
|
+
displayOnly: false,
|
|
267
|
+
validationRules: ["required"],
|
|
268
|
+
propertiesTypeName: "ComponentRatingProperties",
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: "slider",
|
|
272
|
+
label: "Slider",
|
|
273
|
+
iconKey: "slider",
|
|
274
|
+
category: "interactive",
|
|
275
|
+
displayOnly: false,
|
|
276
|
+
validationRules: [],
|
|
277
|
+
propertiesTypeName: "ComponentSliderProperties",
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
type: "colorPicker",
|
|
281
|
+
label: "Color Picker",
|
|
282
|
+
iconKey: "colorPicker",
|
|
283
|
+
category: "interactive",
|
|
284
|
+
displayOnly: false,
|
|
285
|
+
validationRules: ["required"],
|
|
286
|
+
propertiesTypeName: "ComponentColorPickerProperties",
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
type: "signature",
|
|
290
|
+
label: "Signature",
|
|
291
|
+
iconKey: "signature",
|
|
292
|
+
category: "interactive",
|
|
293
|
+
displayOnly: false,
|
|
294
|
+
validationRules: ["required"],
|
|
295
|
+
propertiesTypeName: "ComponentSignatureProperties",
|
|
296
|
+
},
|
|
297
|
+
// ---------- Containers ----------
|
|
298
|
+
{
|
|
299
|
+
type: "group",
|
|
300
|
+
label: "Group",
|
|
301
|
+
iconKey: "contactInfo",
|
|
302
|
+
category: "container",
|
|
303
|
+
displayOnly: false,
|
|
304
|
+
validationRules: [],
|
|
305
|
+
propertiesTypeName: "ComponentGroupProperties",
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
type: "repeater",
|
|
309
|
+
label: "Repeater",
|
|
310
|
+
iconKey: "repeater",
|
|
311
|
+
category: "container",
|
|
312
|
+
displayOnly: false,
|
|
313
|
+
validationRules: [],
|
|
314
|
+
propertiesTypeName: "ComponentRepeaterProperties",
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
const ENTRY_BY_TYPE = new Map(ENTRIES.map((e) => [e.type, e]));
|
|
318
|
+
/** Frozen, ordered list of every registered component type. The order is the
|
|
319
|
+
* canonical pool-section order (display → input → selection → datetime →
|
|
320
|
+
* interactive → container) and matches the FBT pool. */
|
|
321
|
+
export const COMPONENT_MANIFEST = ENTRIES;
|
|
322
|
+
/** Stable, immutable list of all registered component type ids. */
|
|
323
|
+
export const COMPONENT_TYPES = ENTRIES.map((e) => e.type);
|
|
324
|
+
/** Component types that render content but never contribute to FlowData. */
|
|
325
|
+
export const DISPLAY_ONLY_TYPES = new Set(ENTRIES.filter((e) => e.displayOnly).map((e) => e.type));
|
|
326
|
+
/** Human-readable label for the category badge / pool section header. */
|
|
327
|
+
export const CATEGORY_LABELS = {
|
|
328
|
+
display: "Display",
|
|
329
|
+
input: "Text & Number",
|
|
330
|
+
selection: "Selection",
|
|
331
|
+
datetime: "Date & Time",
|
|
332
|
+
interactive: "Interactive",
|
|
333
|
+
container: "Containers",
|
|
334
|
+
};
|
|
335
|
+
/** Look up a manifest entry by component type id. Returns undefined for
|
|
336
|
+
* unrecognized types — callers decide whether that is an error. */
|
|
337
|
+
export function getComponentManifestEntry(type) {
|
|
338
|
+
return ENTRY_BY_TYPE.get(type);
|
|
339
|
+
}
|
|
340
|
+
/** Manifest entries grouped by category, preserving manifest order within
|
|
341
|
+
* each group. Drives the FBT pool layout. */
|
|
342
|
+
export function getManifestByCategory() {
|
|
343
|
+
const out = {
|
|
344
|
+
display: [],
|
|
345
|
+
input: [],
|
|
346
|
+
selection: [],
|
|
347
|
+
datetime: [],
|
|
348
|
+
interactive: [],
|
|
349
|
+
container: [],
|
|
350
|
+
};
|
|
351
|
+
for (const entry of ENTRIES) {
|
|
352
|
+
out[entry.category].push(entry);
|
|
353
|
+
}
|
|
354
|
+
return out;
|
|
355
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ComponentCalloutProperties, ComponentCardSelectProperties, ComponentColorPickerProperties, ComponentComputedProperties, ComponentConfirmProperties, ComponentDateProperties, ComponentDateRangeProperties, ComponentDateTimeProperties, ComponentDateTimeRangeProperties, ComponentDisplayProperties, ComponentDividerProperties, ComponentFileUploadProperties, ComponentGroupProperties, ComponentInputProperties, ComponentOptionProperties, ComponentRatingProperties, ComponentRepeaterProperties, ComponentSignatureProperties, ComponentSliderProperties, ComponentSwitchProperties, ComponentTableProperties, ComponentTimeProperties, ComponentTimeRangeProperties, ComponentYesNoProperties } from "./properties";
|
|
2
|
+
/** Per-type property map. Keys here are the canonical `Component.type` ids;
|
|
3
|
+
* values are the corresponding property shapes from `properties.ts`. */
|
|
4
|
+
export interface ComponentPropertiesByType {
|
|
5
|
+
header: ComponentDisplayProperties;
|
|
6
|
+
text: ComponentDisplayProperties;
|
|
7
|
+
divider: ComponentDividerProperties;
|
|
8
|
+
callout: ComponentCalloutProperties;
|
|
9
|
+
table: ComponentTableProperties;
|
|
10
|
+
computed: ComponentComputedProperties;
|
|
11
|
+
inputText: ComponentInputProperties;
|
|
12
|
+
inputTextArea: ComponentInputProperties;
|
|
13
|
+
inputNumber: ComponentInputProperties;
|
|
14
|
+
dropDown: ComponentOptionProperties;
|
|
15
|
+
dropDownMulti: ComponentOptionProperties;
|
|
16
|
+
checkbox: ComponentOptionProperties;
|
|
17
|
+
radio: ComponentOptionProperties;
|
|
18
|
+
toggleSwitch: ComponentSwitchProperties;
|
|
19
|
+
yesNo: ComponentYesNoProperties;
|
|
20
|
+
confirm: ComponentConfirmProperties;
|
|
21
|
+
cardSelect: ComponentCardSelectProperties;
|
|
22
|
+
date: ComponentDateProperties;
|
|
23
|
+
time: ComponentTimeProperties;
|
|
24
|
+
dateTime: ComponentDateTimeProperties;
|
|
25
|
+
dateRange: ComponentDateRangeProperties;
|
|
26
|
+
timeRange: ComponentTimeRangeProperties;
|
|
27
|
+
dateTimeRange: ComponentDateTimeRangeProperties;
|
|
28
|
+
fileUpload: ComponentFileUploadProperties;
|
|
29
|
+
rating: ComponentRatingProperties;
|
|
30
|
+
slider: ComponentSliderProperties;
|
|
31
|
+
colorPicker: ComponentColorPickerProperties;
|
|
32
|
+
signature: ComponentSignatureProperties;
|
|
33
|
+
group: ComponentGroupProperties;
|
|
34
|
+
repeater: ComponentRepeaterProperties;
|
|
35
|
+
}
|
|
36
|
+
/** Union of every registered component `type` string. */
|
|
37
|
+
export type ComponentType = keyof ComponentPropertiesByType;
|
|
38
|
+
/** Runtime list of every registered component `type` — sourced from the type
|
|
39
|
+
* map so the parity check below can verify it matches the manifest. */
|
|
40
|
+
export declare const COMPONENT_VARIANT_TYPES: readonly ComponentType[];
|
|
41
|
+
/** Asserts at runtime that `ComponentPropertiesByType` keys match the
|
|
42
|
+
* COMPONENT_MANIFEST entry set. Pure-function check — call it from a unit
|
|
43
|
+
* test to fail the build when the two drift. */
|
|
44
|
+
export declare function assertManifestTypeMapParity(manifestTypes: readonly string[]): {
|
|
45
|
+
ok: true;
|
|
46
|
+
} | {
|
|
47
|
+
ok: false;
|
|
48
|
+
missingFromMap: string[];
|
|
49
|
+
missingFromManifest: string[];
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=component-variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-variants.d.ts","sourceRoot":"","sources":["../src/component-variants.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,0BAA0B,EAC1B,6BAA6B,EAC7B,8BAA8B,EAC9B,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,EACvB,4BAA4B,EAC5B,2BAA2B,EAC3B,gCAAgC,EAChC,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,EAC3B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,4BAA4B,EAC5B,wBAAwB,EACzB,MAAM,cAAc,CAAC;AAEtB;yEACyE;AACzE,MAAM,WAAW,yBAAyB;IAExC,MAAM,EAAE,0BAA0B,CAAC;IACnC,IAAI,EAAE,0BAA0B,CAAC;IACjC,OAAO,EAAE,0BAA0B,CAAC;IACpC,OAAO,EAAE,0BAA0B,CAAC;IACpC,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,2BAA2B,CAAC;IAGtC,SAAS,EAAE,wBAAwB,CAAC;IACpC,aAAa,EAAE,wBAAwB,CAAC;IACxC,WAAW,EAAE,wBAAwB,CAAC;IAGtC,QAAQ,EAAE,yBAAyB,CAAC;IACpC,aAAa,EAAE,yBAAyB,CAAC;IACzC,QAAQ,EAAE,yBAAyB,CAAC;IACpC,KAAK,EAAE,yBAAyB,CAAC;IACjC,YAAY,EAAE,yBAAyB,CAAC;IACxC,KAAK,EAAE,wBAAwB,CAAC;IAChC,OAAO,EAAE,0BAA0B,CAAC;IACpC,UAAU,EAAE,6BAA6B,CAAC;IAG1C,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE,uBAAuB,CAAC;IAC9B,QAAQ,EAAE,2BAA2B,CAAC;IACtC,SAAS,EAAE,4BAA4B,CAAC;IACxC,SAAS,EAAE,4BAA4B,CAAC;IACxC,aAAa,EAAE,gCAAgC,CAAC;IAGhD,UAAU,EAAE,6BAA6B,CAAC;IAC1C,MAAM,EAAE,yBAAyB,CAAC;IAClC,MAAM,EAAE,yBAAyB,CAAC;IAClC,WAAW,EAAE,8BAA8B,CAAC;IAC5C,SAAS,EAAE,4BAA4B,CAAC;IAGxC,KAAK,EAAE,wBAAwB,CAAC;IAChC,QAAQ,EAAE,2BAA2B,CAAC;CACvC;AAED,yDAAyD;AACzD,MAAM,MAAM,aAAa,GAAG,MAAM,yBAAyB,CAAC;AAE5D;wEACwE;AACxE,eAAO,MAAM,uBAAuB,EAAE,SAAS,aAAa,EA+BlD,CAAC;AAEX;;iDAEiD;AACjD,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAC;IAAC,mBAAmB,EAAE,MAAM,EAAE,CAAA;CAAE,CAWvF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Component variants — type-level mapping from each component `type` to the
|
|
3
|
+
shape of its `properties`. This is the type-level companion to
|
|
4
|
+
COMPONENT_MANIFEST: the manifest is runtime data (labels, icons, validation
|
|
5
|
+
rules), this file is types (per-type property shapes).
|
|
6
|
+
|
|
7
|
+
Adding a new component type means:
|
|
8
|
+
(1) add its property shape in `properties.ts`,
|
|
9
|
+
(2) add a key here mapping `type` → that shape,
|
|
10
|
+
(3) add a manifest entry in `component-manifest.ts`,
|
|
11
|
+
(4) add the renderer in FBRE and the field-map entry in FBT.
|
|
12
|
+
|
|
13
|
+
The runtime parity guard inside `assertManifestTypeMapParity` (called from
|
|
14
|
+
tests in fbre/fbt) fails if step (2) is missed against step (3). The casts
|
|
15
|
+
in fbre/fbt fall back to the loose union and start firing TS errors at the
|
|
16
|
+
read sites if step (1) is missed against step (2).
|
|
17
|
+
========================================================================== */
|
|
18
|
+
/** Runtime list of every registered component `type` — sourced from the type
|
|
19
|
+
* map so the parity check below can verify it matches the manifest. */
|
|
20
|
+
export const COMPONENT_VARIANT_TYPES = [
|
|
21
|
+
"header",
|
|
22
|
+
"text",
|
|
23
|
+
"divider",
|
|
24
|
+
"callout",
|
|
25
|
+
"table",
|
|
26
|
+
"computed",
|
|
27
|
+
"inputText",
|
|
28
|
+
"inputTextArea",
|
|
29
|
+
"inputNumber",
|
|
30
|
+
"dropDown",
|
|
31
|
+
"dropDownMulti",
|
|
32
|
+
"checkbox",
|
|
33
|
+
"radio",
|
|
34
|
+
"toggleSwitch",
|
|
35
|
+
"yesNo",
|
|
36
|
+
"confirm",
|
|
37
|
+
"cardSelect",
|
|
38
|
+
"date",
|
|
39
|
+
"time",
|
|
40
|
+
"dateTime",
|
|
41
|
+
"dateRange",
|
|
42
|
+
"timeRange",
|
|
43
|
+
"dateTimeRange",
|
|
44
|
+
"fileUpload",
|
|
45
|
+
"rating",
|
|
46
|
+
"slider",
|
|
47
|
+
"colorPicker",
|
|
48
|
+
"signature",
|
|
49
|
+
"group",
|
|
50
|
+
"repeater",
|
|
51
|
+
];
|
|
52
|
+
/** Asserts at runtime that `ComponentPropertiesByType` keys match the
|
|
53
|
+
* COMPONENT_MANIFEST entry set. Pure-function check — call it from a unit
|
|
54
|
+
* test to fail the build when the two drift. */
|
|
55
|
+
export function assertManifestTypeMapParity(manifestTypes) {
|
|
56
|
+
const mapSet = new Set(COMPONENT_VARIANT_TYPES);
|
|
57
|
+
const manifestSet = new Set(manifestTypes);
|
|
58
|
+
const missingFromMap = manifestTypes.filter((t) => !mapSet.has(t));
|
|
59
|
+
const missingFromManifest = COMPONENT_VARIANT_TYPES.filter((t) => !manifestSet.has(t));
|
|
60
|
+
if (missingFromMap.length === 0 && missingFromManifest.length === 0) {
|
|
61
|
+
return { ok: true };
|
|
62
|
+
}
|
|
63
|
+
return { ok: false, missingFromMap, missingFromManifest };
|
|
64
|
+
}
|
package/dist/flow.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FlowConditionConfig } from "./conditions";
|
|
2
2
|
import type { FlowCalculation } from "./calculation";
|
|
3
|
+
import type { ComponentPropertiesByType, ComponentType } from "./component-variants";
|
|
3
4
|
export type ScreenTransitionType = "none" | "slide" | "fade" | "slideFade" | "rise" | "scaleFade";
|
|
4
5
|
export type FlowStyleType = "clean" | "outlined" | "refined-clean" | "airy-clean" | "soft-outlined" | "defined-outlined" | "centered-minimal" | "stacked-cards" | "soft-float" | "bold-statement";
|
|
5
6
|
export type ControlsLayout = "default" | "centered" | "inline-full" | "stacked";
|
|
@@ -31,10 +32,9 @@ export type FlowConfiguration = {
|
|
|
31
32
|
controls?: ControlsConfig;
|
|
32
33
|
summary?: boolean;
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
+
/** Fields every component variant carries regardless of `type`. */
|
|
36
|
+
type ComponentCommon = {
|
|
35
37
|
uuid: string;
|
|
36
|
-
type: string;
|
|
37
|
-
properties: ComponentProperties;
|
|
38
38
|
conditions?: FlowConditionConfig;
|
|
39
39
|
components?: Component[];
|
|
40
40
|
value?: any;
|
|
@@ -42,6 +42,23 @@ export type Component = {
|
|
|
42
42
|
valid?: boolean;
|
|
43
43
|
display?: Record<string, any>;
|
|
44
44
|
};
|
|
45
|
+
/** A component with a specific known `type`. Useful for helpers that want to
|
|
46
|
+
* accept only the matching variant (e.g. `ComponentOfType<"inputText">`). */
|
|
47
|
+
export type ComponentOfType<K extends ComponentType> = ComponentCommon & {
|
|
48
|
+
type: K;
|
|
49
|
+
properties: ComponentPropertiesByType[K];
|
|
50
|
+
};
|
|
51
|
+
/** Component is a discriminated union keyed on `type`. Switching or guarding
|
|
52
|
+
* on `component.type === "..."` narrows `component.properties` to the
|
|
53
|
+
* matching `Component*Properties` shape from `properties.ts`. */
|
|
54
|
+
export type Component = {
|
|
55
|
+
[K in ComponentType]: ComponentOfType<K>;
|
|
56
|
+
}[ComponentType];
|
|
57
|
+
/** Union of every registered properties shape. Replaces the prior
|
|
58
|
+
* `Record<string, any>` alias — consumers that previously typed a value as
|
|
59
|
+
* `ComponentProperties` now get the union and must narrow (most often via
|
|
60
|
+
* `component.type` on the enclosing `Component`). */
|
|
61
|
+
export type ComponentProperties = ComponentPropertiesByType[ComponentType];
|
|
45
62
|
export type FlowScreen = {
|
|
46
63
|
uuid: string;
|
|
47
64
|
label?: string;
|
|
@@ -58,5 +75,5 @@ export type Flow = {
|
|
|
58
75
|
screens: FlowScreen[];
|
|
59
76
|
calculations?: FlowCalculation[];
|
|
60
77
|
};
|
|
61
|
-
export
|
|
78
|
+
export {};
|
|
62
79
|
//# sourceMappingURL=flow.d.ts.map
|
package/dist/flow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../src/flow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../src/flow.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
export type { Flow, FlowScreen, FlowConfiguration, ThemeConfig, NavigationConfig, ControlsConfig, FlowMetadata, Component, ComponentProperties, ScreenTransitionType, FlowStyleType, ControlsLayout, StepperStyle, FlowModeType, } from "./flow";
|
|
1
|
+
export type { Flow, FlowScreen, FlowConfiguration, ThemeConfig, NavigationConfig, ControlsConfig, FlowMetadata, Component, ComponentOfType, ComponentProperties, ScreenTransitionType, FlowStyleType, ControlsLayout, StepperStyle, FlowModeType, } from "./flow";
|
|
2
|
+
export type { ComponentType, ComponentPropertiesByType, } from "./component-variants";
|
|
3
|
+
export { COMPONENT_VARIANT_TYPES, assertManifestTypeMapParity, } from "./component-variants";
|
|
2
4
|
export type { ConditionAction, ConditionLogic, ConditionOperator, ConditionRule, ConditionRuleSource, ConditionGroup, FlowConditionConfig, } from "./conditions";
|
|
3
5
|
export type { ValidationRuleType, ValidationRule, FlowValidationConfig, } from "./validation";
|
|
6
|
+
export { generateUUID } from "./uuid";
|
|
4
7
|
export { normalizeOptions } from "./normalize-options";
|
|
5
8
|
export type { FlowData, ScreenData, ComponentData, CalculationData, FileUploadData, FileUploadBase64Data, FileUploadS3Data, RangeValue, } from "./flow-data";
|
|
6
9
|
export { regenerateComponentUUIDs, regenerateFlowUUIDs, } from "./uuid-regeneration";
|
|
10
|
+
export { normalizeConditionalOrder } from "./normalize-conditional-order";
|
|
11
|
+
export { getValidationConfig, getComponentDisplayLabel, } from "./component-accessors";
|
|
7
12
|
export type { PresetData, TemplateData } from "./preset-template-data";
|
|
8
13
|
export type { CalculationFormat, FlowCalculation, } from "./calculation";
|
|
9
|
-
export type {
|
|
14
|
+
export type { ComponentCategory, ComponentManifestEntry, } from "./component-manifest";
|
|
15
|
+
export { COMPONENT_MANIFEST, COMPONENT_TYPES, DISPLAY_ONLY_TYPES, CATEGORY_LABELS, getComponentManifestEntry, getManifestByCategory, } from "./component-manifest";
|
|
16
|
+
export type { ComponentWidth, DateFormat, ComponentDisplayProperties, ComponentDividerProperties, ComponentInputProperties, OptionItem, ComponentOptionProperties, ComponentSliderProperties, ComponentSwitchProperties, ComponentRatingProperties, ComponentFileUploadProperties, ComponentGroupProperties, ComponentRepeaterProperties, ComponentDateProperties, ComponentTimeProperties, ComponentDateTimeProperties, ComponentDateRangeProperties, ComponentTimeRangeProperties, ComponentDateTimeRangeProperties, ComponentYesNoProperties, ComponentConfirmProperties, ComponentColorPickerProperties, CardSelectOption, ComponentCardSelectProperties, ComponentCalloutVariant, ComponentCalloutProperties, TableColumn, TableRow, ComponentTableProperties, SignatureMode, ComponentSignatureProperties, ComponentComputedProperties, } from "./properties";
|
|
10
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,SAAS,EACT,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,GACb,MAAM,QAAQ,CAAC;AAEhB,YAAY,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEvE,YAAY,EACV,iBAAiB,EACjB,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,cAAc,EACd,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,GACb,MAAM,QAAQ,CAAC;AAEhB,YAAY,EACV,aAAa,EACb,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEvE,YAAY,EACV,iBAAiB,EACjB,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,cAAc,EACd,UAAU,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,wBAAwB,EACxB,UAAU,EACV,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,EAC5B,gCAAgC,EAChC,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,gBAAgB,EAChB,6BAA6B,EAC7B,uBAAuB,EACvB,0BAA0B,EAC1B,WAAW,EACX,QAAQ,EACR,wBAAwB,EACxB,aAAa,EACb,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
export { COMPONENT_VARIANT_TYPES, assertManifestTypeMapParity, } from "./component-variants";
|
|
2
|
+
export { generateUUID } from "./uuid";
|
|
1
3
|
export { normalizeOptions } from "./normalize-options";
|
|
2
4
|
export { regenerateComponentUUIDs, regenerateFlowUUIDs, } from "./uuid-regeneration";
|
|
5
|
+
export { normalizeConditionalOrder } from "./normalize-conditional-order";
|
|
6
|
+
export { getValidationConfig, getComponentDisplayLabel, } from "./component-accessors";
|
|
7
|
+
export { COMPONENT_MANIFEST, COMPONENT_TYPES, DISPLAY_ONLY_TYPES, CATEGORY_LABELS, getComponentManifestEntry, getManifestByCategory, } from "./component-manifest";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Flow } from "./flow";
|
|
2
|
+
/**
|
|
3
|
+
* Returns a new Flow in which every top-level conditional component is moved
|
|
4
|
+
* to immediately follow the component it depends on. Pure: the input Flow is
|
|
5
|
+
* not mutated and component objects are reused by reference.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeConditionalOrder(flow: Flow): Flow;
|
|
8
|
+
//# sourceMappingURL=normalize-conditional-order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-conditional-order.d.ts","sourceRoot":"","sources":["../src/normalize-conditional-order.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,IAAI,EAAyB,MAAM,QAAQ,CAAC;AAgB1D;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAqL1D"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
Conditional-order normalization — relocate each conditional component so it
|
|
3
|
+
sits immediately after the component it depends on.
|
|
4
|
+
|
|
5
|
+
Why: FBTL groups a conditional with its trigger ONLY when the conditional
|
|
6
|
+
immediately follows that trigger in document order. Generators (e.g. an AI
|
|
7
|
+
authoring step) often emit a conditional after an unrelated non-conditional
|
|
8
|
+
sibling, so FBTL can't group them and the conditional becomes a detached
|
|
9
|
+
downstream screen. Run a Flow through this BEFORE loading it into FBTL and
|
|
10
|
+
the adjacency FBTL expects is guaranteed.
|
|
11
|
+
|
|
12
|
+
Scope and guarantees:
|
|
13
|
+
- Operates on TOP-LEVEL screen components only. Nested children (inside
|
|
14
|
+
groups/repeaters) already share their parent's screen and are untouched.
|
|
15
|
+
- Only REORDERS. No condition, property, uuid, label, or screen-level
|
|
16
|
+
condition is ever rewritten. Component object references are preserved.
|
|
17
|
+
- A condition source pointing at a question nested inside a group/repeater
|
|
18
|
+
resolves to that nested question's top-level ancestor card, so the
|
|
19
|
+
conditional anchors on the card that actually carries the trigger.
|
|
20
|
+
- A conditional with multiple component sources is anchored after the
|
|
21
|
+
LATEST of its (resolved) sources, so every dependency precedes it.
|
|
22
|
+
- Dependency chains (A → C → D) are resolved trigger-before-dependent.
|
|
23
|
+
- Cycles and dangling sources are left in place (never relocated, never
|
|
24
|
+
loops).
|
|
25
|
+
- Every empty screen is dropped — both those emptied by relocation and any
|
|
26
|
+
the generator emitted empty. Original screen order, uuids, labels, and
|
|
27
|
+
screen-level conditions of surviving screens are preserved.
|
|
28
|
+
- First-screen identity is preserved: if relocation drops the original
|
|
29
|
+
first screen, its uuid is transplanted onto the new first screen so
|
|
30
|
+
FBTL's stable round-trip screenUUID does not shift.
|
|
31
|
+
========================================================================== */
|
|
32
|
+
/** All component-type source UUIDs referenced by a condition config.
|
|
33
|
+
* `sourceType` undefined is treated as "component" (matches FBTL). */
|
|
34
|
+
function conditionSourceUUIDs(config) {
|
|
35
|
+
const rules = config?.when?.rules;
|
|
36
|
+
if (!rules || rules.length === 0)
|
|
37
|
+
return [];
|
|
38
|
+
const out = [];
|
|
39
|
+
for (const rule of rules) {
|
|
40
|
+
if (rule.sourceType && rule.sourceType !== "component")
|
|
41
|
+
continue;
|
|
42
|
+
if (rule.source)
|
|
43
|
+
out.push(rule.source);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns a new Flow in which every top-level conditional component is moved
|
|
49
|
+
* to immediately follow the component it depends on. Pure: the input Flow is
|
|
50
|
+
* not mutated and component objects are reused by reference.
|
|
51
|
+
*/
|
|
52
|
+
export function normalizeConditionalOrder(flow) {
|
|
53
|
+
const screens = flow.screens ?? [];
|
|
54
|
+
const flat = [];
|
|
55
|
+
screens.forEach((screen, screenIndex) => {
|
|
56
|
+
for (const comp of screen.components ?? []) {
|
|
57
|
+
flat.push({ comp, screenIndex });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const byUUID = new Map();
|
|
61
|
+
for (const e of flat)
|
|
62
|
+
byUUID.set(e.comp.uuid, e);
|
|
63
|
+
const originalIndex = new Map();
|
|
64
|
+
flat.forEach((e, i) => originalIndex.set(e.comp.uuid, i));
|
|
65
|
+
// Map every component UUID — including ones nested inside group/repeater
|
|
66
|
+
// children — to its TOP-LEVEL ancestor. Lets a condition that points at a
|
|
67
|
+
// nested question anchor on the top-level card that contains it instead of
|
|
68
|
+
// being treated as dangling.
|
|
69
|
+
const topAncestor = new Map();
|
|
70
|
+
function indexSubtree(comp, rootUUID) {
|
|
71
|
+
topAncestor.set(comp.uuid, rootUUID);
|
|
72
|
+
for (const child of comp.components ?? []) {
|
|
73
|
+
indexSubtree(child, rootUUID);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
for (const e of flat)
|
|
77
|
+
indexSubtree(e.comp, e.comp.uuid);
|
|
78
|
+
// Resolve each component's anchor: the source it should follow. Each source
|
|
79
|
+
// UUID is mapped to its top-level ancestor; the anchor is the resolved
|
|
80
|
+
// ancestor that appears LAST in original document order, so every dependency
|
|
81
|
+
// of a multi-source condition ends up before it. Returns null when there is
|
|
82
|
+
// no condition, no component source, or the source resolves to nothing /
|
|
83
|
+
// back to this component itself.
|
|
84
|
+
function anchorUUID(comp) {
|
|
85
|
+
const resolved = conditionSourceUUIDs(comp.conditions)
|
|
86
|
+
.map((uuid) => topAncestor.get(uuid))
|
|
87
|
+
.filter((uuid) => uuid !== undefined && uuid !== comp.uuid && byUUID.has(uuid));
|
|
88
|
+
if (resolved.length === 0)
|
|
89
|
+
return null;
|
|
90
|
+
let best = null;
|
|
91
|
+
let bestIdx = -1;
|
|
92
|
+
for (const uuid of resolved) {
|
|
93
|
+
const idx = originalIndex.get(uuid) ?? -1;
|
|
94
|
+
if (idx > bestIdx) {
|
|
95
|
+
bestIdx = idx;
|
|
96
|
+
best = uuid;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return best;
|
|
100
|
+
}
|
|
101
|
+
// Dependency depth, with cycle detection. Cyclic components report depth 0
|
|
102
|
+
// so they are treated as un-anchored (left in place, never looped on).
|
|
103
|
+
const depthCache = new Map();
|
|
104
|
+
function depthOf(uuid, seen) {
|
|
105
|
+
const cached = depthCache.get(uuid);
|
|
106
|
+
if (cached !== undefined)
|
|
107
|
+
return cached;
|
|
108
|
+
if (seen.has(uuid))
|
|
109
|
+
return 0; // cycle — break
|
|
110
|
+
const entry = byUUID.get(uuid);
|
|
111
|
+
if (!entry)
|
|
112
|
+
return 0;
|
|
113
|
+
const anchor = anchorUUID(entry.comp);
|
|
114
|
+
if (!anchor) {
|
|
115
|
+
depthCache.set(uuid, 0);
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
seen.add(uuid);
|
|
119
|
+
const d = depthOf(anchor, seen) + 1;
|
|
120
|
+
seen.delete(uuid);
|
|
121
|
+
depthCache.set(uuid, d);
|
|
122
|
+
return d;
|
|
123
|
+
}
|
|
124
|
+
function isCyclic(uuid) {
|
|
125
|
+
// Walk anchors; if we revisit a node before hitting a root, it's a cycle.
|
|
126
|
+
const path = new Set();
|
|
127
|
+
let cur = uuid;
|
|
128
|
+
while (cur) {
|
|
129
|
+
if (path.has(cur))
|
|
130
|
+
return true;
|
|
131
|
+
path.add(cur);
|
|
132
|
+
const entry = byUUID.get(cur);
|
|
133
|
+
if (!entry)
|
|
134
|
+
return false;
|
|
135
|
+
cur = anchorUUID(entry.comp);
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
// Working order starts as original document order; relocations splice in.
|
|
140
|
+
const order = flat.map((e) => e.comp);
|
|
141
|
+
// Process relocatable conditionals trigger-before-dependent (depth asc),
|
|
142
|
+
// tie-broken by original index for stable sibling ordering.
|
|
143
|
+
const movable = flat
|
|
144
|
+
.map((e) => e.comp)
|
|
145
|
+
.filter((c) => anchorUUID(c) !== null && !isCyclic(c.uuid))
|
|
146
|
+
.sort((a, b) => {
|
|
147
|
+
const da = depthOf(a.uuid, new Set());
|
|
148
|
+
const db = depthOf(b.uuid, new Set());
|
|
149
|
+
if (da !== db)
|
|
150
|
+
return da - db;
|
|
151
|
+
return (originalIndex.get(a.uuid) ?? 0) - (originalIndex.get(b.uuid) ?? 0);
|
|
152
|
+
});
|
|
153
|
+
for (const comp of movable) {
|
|
154
|
+
const anchor = anchorUUID(comp);
|
|
155
|
+
if (!anchor)
|
|
156
|
+
continue;
|
|
157
|
+
const from = order.indexOf(comp);
|
|
158
|
+
if (from === -1)
|
|
159
|
+
continue;
|
|
160
|
+
order.splice(from, 1);
|
|
161
|
+
let at = order.findIndex((c) => c.uuid === anchor);
|
|
162
|
+
if (at === -1) {
|
|
163
|
+
// Anchor vanished (shouldn't happen) — restore original slot.
|
|
164
|
+
order.splice(Math.min(from, order.length), 0, comp);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
// Skip past any conditionals already attached to this anchor so multiple
|
|
168
|
+
// dependents of one trigger keep their original relative order.
|
|
169
|
+
let insertAt = at + 1;
|
|
170
|
+
while (insertAt < order.length && anchorUUID(order[insertAt]) === anchor) {
|
|
171
|
+
insertAt++;
|
|
172
|
+
}
|
|
173
|
+
order.splice(insertAt, 0, comp);
|
|
174
|
+
}
|
|
175
|
+
// Resolve the screen a component lands on: follow anchors to the root
|
|
176
|
+
// (non-conditional / cyclic) component and use that screen.
|
|
177
|
+
const screenCache = new Map();
|
|
178
|
+
function targetScreen(uuid, seen) {
|
|
179
|
+
const cached = screenCache.get(uuid);
|
|
180
|
+
if (cached !== undefined)
|
|
181
|
+
return cached;
|
|
182
|
+
const entry = byUUID.get(uuid);
|
|
183
|
+
if (!entry)
|
|
184
|
+
return 0;
|
|
185
|
+
if (seen.has(uuid))
|
|
186
|
+
return entry.screenIndex; // cycle — own screen
|
|
187
|
+
if (isCyclic(uuid))
|
|
188
|
+
return entry.screenIndex;
|
|
189
|
+
const anchor = anchorUUID(entry.comp);
|
|
190
|
+
if (!anchor) {
|
|
191
|
+
screenCache.set(uuid, entry.screenIndex);
|
|
192
|
+
return entry.screenIndex;
|
|
193
|
+
}
|
|
194
|
+
seen.add(uuid);
|
|
195
|
+
const s = targetScreen(anchor, seen);
|
|
196
|
+
seen.delete(uuid);
|
|
197
|
+
screenCache.set(uuid, s);
|
|
198
|
+
return s;
|
|
199
|
+
}
|
|
200
|
+
// Re-emit screens in original order; components in final relocated order
|
|
201
|
+
// filtered to their target screen. Drop every empty screen — both those
|
|
202
|
+
// emptied by relocation and any that arrived empty from the generator.
|
|
203
|
+
const buckets = screens.map(() => []);
|
|
204
|
+
for (const comp of order) {
|
|
205
|
+
buckets[targetScreen(comp.uuid, new Set())].push(comp);
|
|
206
|
+
}
|
|
207
|
+
const newScreens = [];
|
|
208
|
+
screens.forEach((screen, i) => {
|
|
209
|
+
const comps = buckets[i];
|
|
210
|
+
if (comps.length === 0)
|
|
211
|
+
return; // empty — drop
|
|
212
|
+
newScreens.push({ ...screen, components: comps });
|
|
213
|
+
});
|
|
214
|
+
// Preserve first-screen identity: FBTL pins screens[0]'s uuid as its stable
|
|
215
|
+
// round-trip screenUUID. If relocation dropped the original first screen,
|
|
216
|
+
// transplant its uuid onto the new first screen so that anchor doesn't
|
|
217
|
+
// shift. The surviving screen keeps its own label — it carries meaning the
|
|
218
|
+
// dropped screen's would not.
|
|
219
|
+
const originalFirst = screens[0];
|
|
220
|
+
if (originalFirst && newScreens.length > 0) {
|
|
221
|
+
if (newScreens[0].uuid !== originalFirst.uuid) {
|
|
222
|
+
newScreens[0] = { ...newScreens[0], uuid: originalFirst.uuid };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else if (originalFirst && newScreens.length === 0) {
|
|
226
|
+
// Whole flow had no components — keep one well-formed empty screen.
|
|
227
|
+
newScreens.push({ ...originalFirst, components: [] });
|
|
228
|
+
}
|
|
229
|
+
return { ...flow, screens: newScreens };
|
|
230
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uuid-regeneration.d.ts","sourceRoot":"","sources":["../src/uuid-regeneration.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"uuid-regeneration.d.ts","sourceRoot":"","sources":["../src/uuid-regeneration.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9C;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAkB7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAYpD"}
|
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
UUID regeneration — deep-clone components/flows and replace all UUIDs.
|
|
3
3
|
Used when dropping stored presets/templates onto the stage.
|
|
4
4
|
========================================================================== */
|
|
5
|
+
import { generateUUID } from "./uuid";
|
|
5
6
|
/**
|
|
6
7
|
* Deep-clones an array of components and replaces every `uuid`
|
|
7
8
|
* (including recursively within group `components`).
|
|
8
9
|
*/
|
|
9
10
|
export function regenerateComponentUUIDs(components) {
|
|
10
11
|
return components.map((comp) => {
|
|
12
|
+
// Cast through the union because the spread breaks TS's correlation
|
|
13
|
+
// between `type` and `properties`. At runtime the spread preserves both
|
|
14
|
+
// verbatim and structuredClone preserves the matching shape.
|
|
11
15
|
const cloned = {
|
|
12
16
|
...comp,
|
|
13
|
-
uuid:
|
|
17
|
+
uuid: generateUUID(),
|
|
14
18
|
properties: structuredClone(comp.properties),
|
|
15
19
|
};
|
|
16
20
|
// Recurse into group children
|
|
@@ -27,12 +31,12 @@ export function regenerateComponentUUIDs(components) {
|
|
|
27
31
|
export function regenerateFlowUUIDs(flow) {
|
|
28
32
|
return {
|
|
29
33
|
...flow,
|
|
30
|
-
uuid:
|
|
34
|
+
uuid: generateUUID(),
|
|
31
35
|
metadata: { ...flow.metadata },
|
|
32
36
|
config: flow.config ? { ...flow.config } : undefined,
|
|
33
37
|
screens: flow.screens.map((screen) => ({
|
|
34
38
|
...screen,
|
|
35
|
-
uuid:
|
|
39
|
+
uuid: generateUUID(),
|
|
36
40
|
components: regenerateComponentUUIDs(screen.components),
|
|
37
41
|
})),
|
|
38
42
|
};
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../src/uuid.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,QAAO,MAA6B,CAAC"}
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
UUID generator — thin wrapper around crypto.randomUUID.
|
|
3
|
+
Single source for fbt/fbtl (which re-export this) and uuid-regeneration.
|
|
4
|
+
========================================================================== */
|
|
5
|
+
export const generateUUID = () => crypto.randomUUID();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonata-innovations/fiber-types",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "TypeScript type definitions for the Fiber form builder system",
|
|
5
5
|
"keywords": ["fiber", "form-builder", "types", "typescript", "flow-json"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
],
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"scripts": {
|
|
28
|
-
"
|
|
28
|
+
"clean": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\"",
|
|
29
|
+
"prebuild": "node scripts/check-variant-parity.mjs",
|
|
30
|
+
"build": "npm run clean && tsc"
|
|
29
31
|
},
|
|
30
32
|
"publishConfig": {
|
|
31
33
|
"access": "public"
|