@sonata-innovations/fiber-types 2.3.0 → 2.5.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/AGENTS.md +1 -0
- package/CHANGELOG.md +17 -0
- package/README.md +8 -1
- package/dist/flow.d.ts +49 -2
- package/dist/flow.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/docs/features/custom-presets-and-templates.md +428 -0
- package/docs/fiber-concepts.md +9 -5
- package/docs/schema/flow-quick-reference.md +1 -1
- package/docs/schema/flow-schema.json +74 -4
- package/docs/schema/flow-schema.md +31 -2
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -40,6 +40,7 @@ npx ajv-cli validate --spec=draft2020 \
|
|
|
40
40
|
- **Options must be `{ label, value }` objects**, not bare strings. `value` may be a string or a number.
|
|
41
41
|
- **Option-bearing components do not default to their first option.** Initial value is `null` unless `properties.defaultValue` matches an option's `value`.
|
|
42
42
|
- **Never set runtime-only fields** (`value`, `valid`, `addedComponents`) in Flow JSON.
|
|
43
|
+
- **`theme.fontFamily` may be an object, not just a string.** `{ family, src }` names a font the renderer loads itself; a bare string assumes the host page already has it. Narrow before treating it as a stack.
|
|
43
44
|
- **`Component` is a discriminated union.** Narrow on `component.type` and `properties` narrows with it; use `ComponentOfType<"inputText">` to name one variant.
|
|
44
45
|
- **If an AI/LLM generated the flow**, run `normalizeConditionalOrder(flow)` before handing it to FBTL — it reorders conditionals to sit after their triggers, structurally only, and is idempotent.
|
|
45
46
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the Fiber schema types. Dates are release dates.
|
|
4
4
|
|
|
5
|
+
## 2.5.0 — 2026-08-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`ThemeConfig.fontFamily` now also accepts a loadable font config** — `{ family, src?, faces?, stack? }`, with the new `FontFamilyConfig`, `FontFaceConfig` and `FontSource` types exported. A plain family string still works and still means "the host page already loads this font"; the object form carries the sources a renderer needs to register the face itself. This is what makes a brand font work inside a shadow root, where an `@font-face` declared in the root's stylesheet is never registered at all. The schema (`flow-schema.json`) accepts either shape.
|
|
10
|
+
|
|
11
|
+
Widening the type is source-compatible for anything that *sets* `fontFamily`, but code that *reads* it as a `string` needs to narrow. `isFontFamilyConfig` and `fontFamilyStack` are exported from `@sonata-innovations/fiber-fbre` for that.
|
|
12
|
+
|
|
13
|
+
## 2.4.0 — 2026-07-11 (never published)
|
|
14
|
+
|
|
15
|
+
> The version bump landed in the repo but was never tagged, so npm went 2.3.0 → 2.5.0. The change below ships as part of 2.5.0.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- `ComponentInputType` (`"text" | "email" | "tel" | "url" | "password"`) is now exported from the package index. It is the declared type of the `inputText` component's `inputType` property and was the only property-level union not re-exported — every sibling (`ComponentWidth`, `DateFormat`, `ComponentCalloutVariant`, `SignatureMode`, …) already was. Consumers can now type a helper against it directly instead of restating the string union. No runtime or schema change: the `inputType` values are unchanged and were already documented in `flow-schema.json`.
|
|
21
|
+
|
|
5
22
|
## 2.3.0 — 2026-07-10
|
|
6
23
|
|
|
7
24
|
### Added
|
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ npx ajv-cli validate --spec=draft2020 \
|
|
|
46
46
|
import type {
|
|
47
47
|
Flow, FlowScreen, Component, ComponentProperties,
|
|
48
48
|
FlowMetadata, FlowConfiguration, ThemeConfig, NavigationConfig,
|
|
49
|
-
ControlsConfig, ConfirmationConfig,
|
|
49
|
+
ControlsConfig, ConfirmationConfig, FontFamilyConfig,
|
|
50
50
|
FlowData, ScreenData, ComponentData, CalculationData,
|
|
51
51
|
FileUploadData, RangeValue,
|
|
52
52
|
FlowConditionConfig, ConditionRule, ConditionOperator,
|
|
@@ -66,6 +66,12 @@ import {
|
|
|
66
66
|
} from "@sonata-innovations/fiber-types";
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
Those are the headline types. Every **per-component property shape**
|
|
70
|
+
(`ComponentInputProperties`, `ComponentOptionProperties`, `ComponentRepeaterProperties`, …)
|
|
71
|
+
and every **property-level union** (`ComponentWidth`, `DateFormat`, `ComponentInputType`,
|
|
72
|
+
`ComponentCalloutVariant`, `SignatureMode`, `OptionItem`, `TableColumn`, …) is exported too —
|
|
73
|
+
import them when you need to type a helper against a single property rather than a whole component.
|
|
74
|
+
|
|
69
75
|
`Component` is a **discriminated union keyed on `type`** — narrow on `component.type` and `component.properties` narrows with it:
|
|
70
76
|
|
|
71
77
|
```ts
|
|
@@ -76,6 +82,7 @@ if (component.type === "inputText") {
|
|
|
76
82
|
|
|
77
83
|
## Gotchas
|
|
78
84
|
|
|
85
|
+
- **`ThemeConfig.fontFamily` is `string | FontFamilyConfig`.** A plain string is a CSS stack and means "the host page already loads this font"; `{ family, src }` carries the sources a renderer registers itself. Code that reads the knob as a `string` has to narrow — `isFontFamilyConfig` / `fontFamilyStack` are exported from `@sonata-innovations/fiber-fbre` for that.
|
|
79
86
|
- **30 component types.** Display types (`header`, `text`, `divider`, `callout`, `table`) never appear in FlowData; `computed` does.
|
|
80
87
|
- **`pattern` validation rules take `params.regex`**, not `params.pattern`. A `pattern` key is silently ignored and the rule always passes.
|
|
81
88
|
- **Options must be `{ label, value }` objects**, not bare strings. `value` may be a string or a number.
|
package/dist/flow.d.ts
CHANGED
|
@@ -14,6 +14,49 @@ export type FlowMetadata = Record<string, string> & {
|
|
|
14
14
|
* `darkMode: boolean`. Light is the default. A future "auto" (follow the
|
|
15
15
|
* viewer's `prefers-color-scheme`) is an additive option, not yet supported. */
|
|
16
16
|
export type ColorScheme = "light" | "dark";
|
|
17
|
+
/** One `url(...)` entry inside a face's `src`. `format` is the CSS
|
|
18
|
+
* `format()` hint — "woff2", "woff", "truetype". */
|
|
19
|
+
export type FontSource = {
|
|
20
|
+
url: string;
|
|
21
|
+
format?: string;
|
|
22
|
+
};
|
|
23
|
+
/** A single `@font-face`: one weight/style of a family. */
|
|
24
|
+
export type FontFaceConfig = {
|
|
25
|
+
src: FontSource[];
|
|
26
|
+
/** CSS `font-weight` — "400", "700", or a variable range like "100 900". */
|
|
27
|
+
weight?: string;
|
|
28
|
+
style?: "normal" | "italic" | "oblique";
|
|
29
|
+
display?: "auto" | "block" | "swap" | "fallback" | "optional";
|
|
30
|
+
unicodeRange?: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A brand font the renderer can actually load, rather than a family name it
|
|
34
|
+
* can only hope the host page already has.
|
|
35
|
+
*
|
|
36
|
+
* Naming a family in a theme does nothing on its own: `fontFamily` maps to a
|
|
37
|
+
* CSS family *string*, and if no `@font-face` for it is registered in the
|
|
38
|
+
* owning document the form falls back to `system-ui` and looks approximately
|
|
39
|
+
* fine, so nobody reports it. It matters most exactly where the host cannot
|
|
40
|
+
* patch around it — a form mounted in a shadow root, since `@font-face`
|
|
41
|
+
* rules inside a shadow stylesheet are not registered at all.
|
|
42
|
+
*
|
|
43
|
+
* Give the family sources here and the renderer registers the faces in the
|
|
44
|
+
* owning document itself (`ensureFontLoaded` in `@sonata-innovations/fiber-fbre`),
|
|
45
|
+
* so the family string and the loaded face cannot drift apart.
|
|
46
|
+
*/
|
|
47
|
+
export type FontFamilyConfig = {
|
|
48
|
+
/** CSS family name. Used both for the `@font-face` and the token value. */
|
|
49
|
+
family: string;
|
|
50
|
+
/** Shorthand for a single regular face. Merged with `faces`. */
|
|
51
|
+
src?: FontSource[];
|
|
52
|
+
/** Additional faces — a second weight, an italic. */
|
|
53
|
+
faces?: FontFaceConfig[];
|
|
54
|
+
/**
|
|
55
|
+
* The full stack written to `--fbre-font`. Defaults to the family plus a
|
|
56
|
+
* system fallback, so a face that fails to load still renders sensibly.
|
|
57
|
+
*/
|
|
58
|
+
stack?: string;
|
|
59
|
+
};
|
|
17
60
|
/**
|
|
18
61
|
* Visual theme settings. Two layers:
|
|
19
62
|
* - `colorScheme` + `style` pick built-in presets (the seed palette + shape).
|
|
@@ -40,8 +83,12 @@ export type ThemeConfig = {
|
|
|
40
83
|
border?: string;
|
|
41
84
|
/** Corner radius, any CSS length (`--fbre-radius`), e.g. `"3px"`. */
|
|
42
85
|
radius?: string;
|
|
43
|
-
/**
|
|
44
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Font family (`--fbre-font`). A plain CSS stack string uses whatever the
|
|
88
|
+
* host page already provides; a `FontFamilyConfig` additionally carries the
|
|
89
|
+
* sources the renderer needs to register the face itself.
|
|
90
|
+
*/
|
|
91
|
+
fontFamily?: string | FontFamilyConfig;
|
|
45
92
|
/** Error state color (`--fbre-error`). */
|
|
46
93
|
error?: string;
|
|
47
94
|
/** Success state color (`--fbre-success`). */
|
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,iBAAiB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACd,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,OAAO,GACP,MAAM,GACN,WAAW,GACX,MAAM,GACN,WAAW,CAAC;AAEhB,MAAM,MAAM,aAAa,GACrB,OAAO,GACP,UAAU,GACV,eAAe,GACf,YAAY,GACZ,eAAe,GACf,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,YAAY,GACZ,gBAAgB,CAAC;AAErB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEjF,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEzD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;iFAEiF;AACjF,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB
|
|
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,4 +1,4 @@
|
|
|
1
|
-
export type { Flow, FlowScreen, FlowConfiguration, ThemeConfig, ColorScheme, NavigationConfig, ControlsConfig, ConfirmationConfig, FlowMetadata, Component, ComponentOfType, ComponentProperties, ScreenTransitionType, FlowStyleType, ControlsLayout, StepperStyle, FlowModeType, } from "./flow.js";
|
|
1
|
+
export type { Flow, FlowScreen, FlowConfiguration, ThemeConfig, ColorScheme, NavigationConfig, ControlsConfig, FontSource, FontFaceConfig, FontFamilyConfig, ConfirmationConfig, FlowMetadata, Component, ComponentOfType, ComponentProperties, ScreenTransitionType, FlowStyleType, ControlsLayout, StepperStyle, FlowModeType, } from "./flow.js";
|
|
2
2
|
export type { ComponentType, ComponentPropertiesByType, } from "./component-variants.js";
|
|
3
3
|
export { COMPONENT_VARIANT_TYPES, assertManifestTypeMapParity, } from "./component-variants.js";
|
|
4
4
|
export type { ConditionAction, ConditionLogic, ConditionOperator, ConditionRule, ConditionRuleSource, ConditionGroup, FlowConditionConfig, } from "./conditions.js";
|
|
@@ -13,5 +13,5 @@ export type { PresetData, TemplateData } from "./preset-template-data.js";
|
|
|
13
13
|
export type { CalculationFormat, FlowCalculation, } from "./calculation.js";
|
|
14
14
|
export type { ComponentCategory, ComponentManifestEntry, } from "./component-manifest.js";
|
|
15
15
|
export { COMPONENT_MANIFEST, COMPONENT_TYPES, DISPLAY_ONLY_TYPES, CATEGORY_LABELS, getComponentManifestEntry, getManifestByCategory, } from "./component-manifest.js";
|
|
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.js";
|
|
16
|
+
export type { ComponentWidth, DateFormat, ComponentDisplayProperties, ComponentDividerProperties, ComponentInputType, 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.js";
|
|
17
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,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,aAAa,EACb,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,YAAY,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE1E,YAAY,EACV,iBAAiB,EACjB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAEjC,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,iBAAiB,CAAC"}
|
|
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,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,YAAY,GACb,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,aAAa,EACb,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,YAAY,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,OAAO,EACL,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE1E,YAAY,EACV,iBAAiB,EACjB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,cAAc,EACd,UAAU,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,kBAAkB,EAClB,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,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Custom Presets & Templates (FBT)
|
|
3
|
+
applies-to:
|
|
4
|
+
- "@sonata-innovations/fiber-fbt@^2.2"
|
|
5
|
+
- "@sonata-innovations/fiber-types@^2.2"
|
|
6
|
+
read-when: "Extending FBT's pool with custom presets/templates: data-based vs factory definitions, icon catalog, collision rules, server-stored definitions."
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Generated from the Fiber repo's docs/ tree by project/scripts/sync-package-docs.mjs. Do not edit here. -->
|
|
10
|
+
# Custom Presets & Templates
|
|
11
|
+
|
|
12
|
+
Parent applications extend FBT's pool with custom **presets** and **templates** via the optional `customPresets` and `customTemplates` props. This is the deep-dive companion to the short "Custom Presets & Templates" section in `docs/integration/fbt.md`.
|
|
13
|
+
|
|
14
|
+
## Concepts
|
|
15
|
+
|
|
16
|
+
- A **preset** is one or more pre-configured components. Dropping it onto the stage batch-adds those components to the **current screen** (at the drop position if dropped over an existing component, otherwise appended).
|
|
17
|
+
- A **template** is a complete `Flow`. Dropping it **merges** into the current flow: its screens are **appended** to the existing screen list via `mergeFlow`, and the first appended screen becomes the active screen. Nothing is replaced — the existing screens, metadata, and config are untouched, and the template's own `metadata`/`config` are ignored by the merge (only its screens are ingested).
|
|
18
|
+
|
|
19
|
+
Whether a definition is treated as a preset or a template is determined by **which prop array it arrives in** (`customPresets` vs `customTemplates`), not by its `type` string.
|
|
20
|
+
|
|
21
|
+
## Two definition kinds, one set of props
|
|
22
|
+
|
|
23
|
+
Both props accept a union type:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// fbt/src/types/custom.ts
|
|
27
|
+
export type AnyPresetDefinition = CustomPresetDefinition | PresetData;
|
|
28
|
+
export type AnyTemplateDefinition = CustomTemplateDefinition | TemplateData;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- **Data-based** (`PresetData` / `TemplateData`, exported from `@sonata-innovations/fiber-types`) — plain serializable JSON. **Preferred**: it can be stored in a database, sent over the wire, and edited without code. FBT regenerates UUIDs automatically on every drop.
|
|
32
|
+
- **Factory-based** (`CustomPresetDefinition` / `CustomTemplateDefinition`, exported from `@sonata-innovations/fiber-fbt`) — a `factory()` function called on every drop. Kept for backward compatibility.
|
|
33
|
+
|
|
34
|
+
FBT distinguishes the two kinds structurally (`"factory" in definition`), so you can mix both kinds in the same array.
|
|
35
|
+
|
|
36
|
+
## Data-based definitions (primary)
|
|
37
|
+
|
|
38
|
+
### Shapes
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// @sonata-innovations/fiber-types
|
|
42
|
+
export type PresetData = {
|
|
43
|
+
type: string; // unique identifier (see collision rules below)
|
|
44
|
+
label: string; // display name in the pool
|
|
45
|
+
icon: string; // key into FBT's ICON_MAP (see icon catalog below)
|
|
46
|
+
components: Component[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type TemplateData = {
|
|
50
|
+
type: string;
|
|
51
|
+
label: string;
|
|
52
|
+
icon: string;
|
|
53
|
+
flow: Flow;
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### UUID regeneration semantics
|
|
58
|
+
|
|
59
|
+
The UUIDs you write into a data-based definition are **placeholders**. On every drop, FBT calls `regenerateComponentUUIDs` (presets) or `regenerateFlowUUIDs` (templates) from `@sonata-innovations/fiber-types`:
|
|
60
|
+
|
|
61
|
+
- Every component gets a fresh UUID; `properties` are deep-cloned (`structuredClone`), and nested `components` arrays (groups) are regenerated recursively.
|
|
62
|
+
- For templates, the flow UUID and every screen UUID are also replaced.
|
|
63
|
+
- The original definition object is never mutated, so the same definition can be dropped any number of times without duplicate-UUID bugs.
|
|
64
|
+
|
|
65
|
+
This means placeholder UUIDs only need to be unique **within** the definition (so group nesting is unambiguous); any string works.
|
|
66
|
+
|
|
67
|
+
### Full preset example
|
|
68
|
+
|
|
69
|
+
`Component` is a discriminated union keyed on `type` — `properties` is checked against the shape for that `type` (e.g. `label` is required for `"inputText"`, `value` for `"header"`, `options` for `"dropDown"`). Group children live on the component's top-level `components` field, not inside `properties`.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import type { PresetData } from "@sonata-innovations/fiber-types";
|
|
73
|
+
|
|
74
|
+
const ssnPreset: PresetData = {
|
|
75
|
+
type: "custom-ssn",
|
|
76
|
+
label: "SSN",
|
|
77
|
+
icon: "ssn",
|
|
78
|
+
components: [
|
|
79
|
+
{
|
|
80
|
+
uuid: "ssn-field",
|
|
81
|
+
type: "inputText",
|
|
82
|
+
properties: {
|
|
83
|
+
label: "Social Security Number",
|
|
84
|
+
placeholder: "XXX-XX-XXXX",
|
|
85
|
+
validation: {
|
|
86
|
+
rules: [
|
|
87
|
+
{ type: "required" },
|
|
88
|
+
// NOTE: the param key is `regex`, not `pattern`
|
|
89
|
+
{ type: "pattern", params: { regex: "^\\d{3}-\\d{2}-\\d{4}$" } },
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const emergencyContactPreset: PresetData = {
|
|
98
|
+
type: "custom-emergencyContact",
|
|
99
|
+
label: "Emergency Contact",
|
|
100
|
+
icon: "emergencyContact",
|
|
101
|
+
components: [
|
|
102
|
+
{
|
|
103
|
+
uuid: "ec-group",
|
|
104
|
+
type: "group",
|
|
105
|
+
properties: { label: "Emergency Contact", showLabel: true },
|
|
106
|
+
components: [
|
|
107
|
+
{
|
|
108
|
+
uuid: "ec-name",
|
|
109
|
+
type: "inputText",
|
|
110
|
+
properties: {
|
|
111
|
+
label: "Contact Name",
|
|
112
|
+
width: "half",
|
|
113
|
+
validation: { rules: [{ type: "required" }] },
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
uuid: "ec-phone",
|
|
118
|
+
type: "inputText",
|
|
119
|
+
properties: {
|
|
120
|
+
label: "Contact Phone",
|
|
121
|
+
placeholder: "(555) 555-5555",
|
|
122
|
+
inputType: "tel",
|
|
123
|
+
width: "half",
|
|
124
|
+
validation: { rules: [{ type: "required" }, { type: "phone" }] },
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
uuid: "ec-relationship",
|
|
129
|
+
type: "dropDown",
|
|
130
|
+
properties: {
|
|
131
|
+
label: "Relationship",
|
|
132
|
+
options: [
|
|
133
|
+
{ label: "Spouse", value: "spouse" },
|
|
134
|
+
{ label: "Parent", value: "parent" },
|
|
135
|
+
{ label: "Sibling", value: "sibling" },
|
|
136
|
+
{ label: "Friend", value: "friend" },
|
|
137
|
+
{ label: "Other", value: "other" },
|
|
138
|
+
],
|
|
139
|
+
validation: { rules: [{ type: "required" }] },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Full template example
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import type { TemplateData } from "@sonata-innovations/fiber-types";
|
|
152
|
+
|
|
153
|
+
const onboardingTemplate: TemplateData = {
|
|
154
|
+
type: "custom-employeeOnboarding",
|
|
155
|
+
label: "Employee Onboarding",
|
|
156
|
+
icon: "employeeOnboarding",
|
|
157
|
+
flow: {
|
|
158
|
+
uuid: "onboarding-flow",
|
|
159
|
+
metadata: { name: "Employee Onboarding" },
|
|
160
|
+
config: {},
|
|
161
|
+
screens: [
|
|
162
|
+
{
|
|
163
|
+
uuid: "onboarding-screen-1",
|
|
164
|
+
label: "Personal Info",
|
|
165
|
+
components: [
|
|
166
|
+
{
|
|
167
|
+
uuid: "ob-header-1",
|
|
168
|
+
type: "header",
|
|
169
|
+
properties: { value: "Employee Information" },
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
uuid: "ob-first-name",
|
|
173
|
+
type: "inputText",
|
|
174
|
+
properties: {
|
|
175
|
+
label: "First Name",
|
|
176
|
+
width: "half",
|
|
177
|
+
validation: { rules: [{ type: "required" }] },
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
uuid: "ob-last-name",
|
|
182
|
+
type: "inputText",
|
|
183
|
+
properties: {
|
|
184
|
+
label: "Last Name",
|
|
185
|
+
width: "half",
|
|
186
|
+
validation: { rules: [{ type: "required" }] },
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
uuid: "ob-email",
|
|
191
|
+
type: "inputText",
|
|
192
|
+
properties: {
|
|
193
|
+
label: "Email Address",
|
|
194
|
+
placeholder: "name@company.com",
|
|
195
|
+
inputType: "email",
|
|
196
|
+
validation: { rules: [{ type: "required" }, { type: "email" }] },
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
uuid: "onboarding-screen-2",
|
|
203
|
+
label: "Employment Details",
|
|
204
|
+
components: [
|
|
205
|
+
{
|
|
206
|
+
uuid: "ob-header-2",
|
|
207
|
+
type: "header",
|
|
208
|
+
properties: { value: "Employment Details" },
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
uuid: "ob-job-title",
|
|
212
|
+
type: "inputText",
|
|
213
|
+
properties: {
|
|
214
|
+
label: "Job Title",
|
|
215
|
+
validation: { rules: [{ type: "required" }] },
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
uuid: "ob-employment-type",
|
|
220
|
+
type: "dropDown",
|
|
221
|
+
properties: {
|
|
222
|
+
label: "Employment Type",
|
|
223
|
+
options: [
|
|
224
|
+
{ label: "Full-Time", value: "full-time" },
|
|
225
|
+
{ label: "Part-Time", value: "part-time" },
|
|
226
|
+
{ label: "Contract", value: "contract" },
|
|
227
|
+
{ label: "Intern", value: "intern" },
|
|
228
|
+
],
|
|
229
|
+
validation: { rules: [{ type: "required" }] },
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Remember: dropping this template does **not** overwrite the builder's current flow — its two screens are appended after the existing ones, and "Personal Info" becomes the active screen. The `metadata.name` above documents the template but is not merged into the current flow.
|
|
240
|
+
|
|
241
|
+
### Passing to FBT
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
import { FBT } from "@sonata-innovations/fiber-fbt";
|
|
245
|
+
import "@sonata-innovations/fiber-fbt/styles";
|
|
246
|
+
import type { AnyPresetDefinition, AnyTemplateDefinition } from "@sonata-innovations/fiber-fbt";
|
|
247
|
+
|
|
248
|
+
const MY_PRESETS: AnyPresetDefinition[] = [ssnPreset, emergencyContactPreset];
|
|
249
|
+
const MY_TEMPLATES: AnyTemplateDefinition[] = [onboardingTemplate];
|
|
250
|
+
|
|
251
|
+
function App() {
|
|
252
|
+
return (
|
|
253
|
+
<FBT
|
|
254
|
+
flow={existingFlow}
|
|
255
|
+
onFlowChange={handleFlowChange}
|
|
256
|
+
customPresets={MY_PRESETS}
|
|
257
|
+
customTemplates={MY_TEMPLATES}
|
|
258
|
+
/>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Both props are optional; if omitted, FBT shows only its built-in items. Keep the arrays referentially stable (module constants or memoized) — the context memoizes its lookup maps on the array identities.
|
|
264
|
+
|
|
265
|
+
## Factory-based definitions (back-compat)
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
// @sonata-innovations/fiber-fbt
|
|
269
|
+
export type CustomPresetDefinition = {
|
|
270
|
+
type: string;
|
|
271
|
+
label: string;
|
|
272
|
+
icon: string;
|
|
273
|
+
factory: () => Component[];
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export type CustomTemplateDefinition = {
|
|
277
|
+
type: string;
|
|
278
|
+
label: string;
|
|
279
|
+
icon: string;
|
|
280
|
+
factory: () => Flow;
|
|
281
|
+
};
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
With a factory, **you** are responsible for returning fresh UUIDs on every call — FBT does not regenerate UUIDs for factory-based definitions. You would still use a factory when the definition must be computed at drop time (e.g. injecting the current date, user data, or environment-dependent options):
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import type { CustomPresetDefinition } from "@sonata-innovations/fiber-fbt";
|
|
288
|
+
|
|
289
|
+
const visitDatePreset: CustomPresetDefinition = {
|
|
290
|
+
type: "custom-visitDate",
|
|
291
|
+
label: "Visit Date",
|
|
292
|
+
icon: "date",
|
|
293
|
+
factory: () => [
|
|
294
|
+
{
|
|
295
|
+
uuid: crypto.randomUUID(),
|
|
296
|
+
type: "date",
|
|
297
|
+
properties: {
|
|
298
|
+
label: "Visit Date",
|
|
299
|
+
min: new Date().toISOString().slice(0, 10), // today, computed at drop
|
|
300
|
+
validation: { rules: [{ type: "required" }] },
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
};
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
For anything static, prefer `PresetData`/`TemplateData`.
|
|
308
|
+
|
|
309
|
+
## How resolution works
|
|
310
|
+
|
|
311
|
+
1. **Context injection** — the FBT provider builds `presetMap` / `templateMap` (`Map<string, () => Component[] | Flow>`) from the prop arrays, keyed by `type`. Factory definitions map to their `factory`; data definitions map to a wrapper that regenerates UUIDs. If two custom definitions share a `type`, the later one in the array wins (plain `Map.set` overwrite).
|
|
312
|
+
2. **Kind by prop array** — items from `customPresets` are tagged `kind: "preset"`, items from `customTemplates` are tagged `kind: "template"` when the pool renders them. The `type` string plays no part in this.
|
|
313
|
+
3. **Built-in-first lookup at drop** — the DnD handler resolves the dropped `type` against the **built-in** definitions first, and only falls back to the custom map if that returns nothing:
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
// fbt/src/ui/dnd/dnd-wrapper.tsx
|
|
317
|
+
const flow = createTemplate(item.type) ?? templateMap.get(item.type)?.();
|
|
318
|
+
const components = createPreset(item.type) ?? presetMap.get(item.type)?.();
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Collision rules
|
|
322
|
+
|
|
323
|
+
There is **no required prefix** on custom `type` strings — FBT accepts any string. But because built-in lookup runs first, a custom definition whose `type` equals a built-in key is **silently shadowed**: your pool entry shows your label and icon, but dropping it produces the built-in content.
|
|
324
|
+
|
|
325
|
+
Built-in keys to avoid — presets: `preset-phone`, `preset-email`, `preset-date`, `preset-url`, `preset-fullName`, `preset-dollarAmount`, `preset-password`, `preset-addressBlock`, `preset-contactInfo`, `preset-nameFields`, `preset-agreement`; templates: `template-contactForm`, `template-signUp`, `template-patientIntake`, `template-feedbackSurvey`.
|
|
326
|
+
|
|
327
|
+
**Recommendation:** use a distinct namespace such as `custom-*`. No built-in uses it, and it matches what the Fiber server enforces for stored definitions (see below).
|
|
328
|
+
|
|
329
|
+
## Icon catalog
|
|
330
|
+
|
|
331
|
+
`icon` is a key into FBT's `ICON_MAP` (`fbt/src/lib/icons.tsx`) — 46 built-in SVG icons. Icon keys are their own namespace: they often mirror component types but are not the same set (e.g. the paragraph-text icon is `descriptionText` while the component type is `text`; `select` is the dropdown icon). If the key is unknown, the item renders with an empty icon slot — no error, graceful fallback.
|
|
332
|
+
|
|
333
|
+
### Display & structure
|
|
334
|
+
|
|
335
|
+
| Key | Glyph |
|
|
336
|
+
|-----|-------|
|
|
337
|
+
| `header` | Heading lines |
|
|
338
|
+
| `descriptionText` | Paragraph lines |
|
|
339
|
+
| `divider` | Horizontal rule |
|
|
340
|
+
| `callout` | Info box |
|
|
341
|
+
| `table` | Grid |
|
|
342
|
+
|
|
343
|
+
### Text & number inputs
|
|
344
|
+
|
|
345
|
+
| Key | Glyph |
|
|
346
|
+
|-----|-------|
|
|
347
|
+
| `textInput` | Single-line field |
|
|
348
|
+
| `textArea` | Multi-line field |
|
|
349
|
+
| `numberInput` | Field with `#` |
|
|
350
|
+
| `dollarAmount` | Field with `$` |
|
|
351
|
+
| `phone` | Phone handset/device |
|
|
352
|
+
| `email` | Envelope |
|
|
353
|
+
| `url` | Chain link |
|
|
354
|
+
| `password` | Padlock |
|
|
355
|
+
|
|
356
|
+
### Selection
|
|
357
|
+
|
|
358
|
+
| Key | Glyph |
|
|
359
|
+
|-----|-------|
|
|
360
|
+
| `select` | Dropdown |
|
|
361
|
+
| `multiSelect` | Checked list |
|
|
362
|
+
| `checkbox` | Checked box |
|
|
363
|
+
| `radio` | Radio dot |
|
|
364
|
+
| `toggleSwitch` | Switch |
|
|
365
|
+
| `yesNo` | Check/cross pair |
|
|
366
|
+
| `confirm` | Checked box (shares the `checkbox` glyph) |
|
|
367
|
+
| `cardSelect` | Card grid |
|
|
368
|
+
|
|
369
|
+
### Date & time
|
|
370
|
+
|
|
371
|
+
| Key | Glyph |
|
|
372
|
+
|-----|-------|
|
|
373
|
+
| `date` | Calendar |
|
|
374
|
+
| `time` | Clock |
|
|
375
|
+
| `dateTime` | Calendar + clock |
|
|
376
|
+
| `dateRange` | Two calendars |
|
|
377
|
+
| `timeRange` | Two clocks |
|
|
378
|
+
| `dateTimeRange` | Two calendar+clock pairs |
|
|
379
|
+
|
|
380
|
+
### Interactive & special
|
|
381
|
+
|
|
382
|
+
| Key | Glyph |
|
|
383
|
+
|-----|-------|
|
|
384
|
+
| `fileUpload` | Upload arrow |
|
|
385
|
+
| `rating` | Star |
|
|
386
|
+
| `slider` | Slider track |
|
|
387
|
+
| `colorPicker` | Color wheel |
|
|
388
|
+
| `signature` | Signature stroke |
|
|
389
|
+
| `repeater` | Stacked dashed rows |
|
|
390
|
+
| `calculated` | `fx` in a box |
|
|
391
|
+
|
|
392
|
+
### People & preset-flavored
|
|
393
|
+
|
|
394
|
+
| Key | Glyph |
|
|
395
|
+
|-----|-------|
|
|
396
|
+
| `fullName` | Person |
|
|
397
|
+
| `addressBlock` | Map pin |
|
|
398
|
+
| `contactInfo` | Contact card |
|
|
399
|
+
| `nameFields` | Paired fields |
|
|
400
|
+
| `agreement` | Document with check |
|
|
401
|
+
| `ssn` | Masked field (`***`) |
|
|
402
|
+
| `emergencyContact` | Person with plus |
|
|
403
|
+
|
|
404
|
+
### Template-flavored
|
|
405
|
+
|
|
406
|
+
| Key | Glyph |
|
|
407
|
+
|-----|-------|
|
|
408
|
+
| `signUpForm` | Form with avatar |
|
|
409
|
+
| `patientIntake` | Bulleted form |
|
|
410
|
+
| `feedbackSurvey` | Form with star |
|
|
411
|
+
| `contactForm` | Form lines |
|
|
412
|
+
| `employeeOnboarding` | Document lines |
|
|
413
|
+
|
|
414
|
+
## Server-stored definitions
|
|
415
|
+
|
|
416
|
+
The Fiber server (private package, not published) provides tenant-scoped storage for data-based definitions:
|
|
417
|
+
|
|
418
|
+
- CRUD endpoints at `/api/v1/presets` and `/api/v1/templates`, storing `PresetData` / `TemplateData` JSON per tenant.
|
|
419
|
+
- The server **rejects** any stored definition whose `type` does not start with `custom-` — this prefix guarantees no collision with built-in keys.
|
|
420
|
+
- The portal provides management pages for presets and templates, and its flow editor fetches the tenant's custom definitions on mount.
|
|
421
|
+
|
|
422
|
+
From FBT's perspective there is nothing special about server-stored definitions: the parent app fetches them and passes them through the same `customPresets` / `customTemplates` props as data-based definitions.
|
|
423
|
+
|
|
424
|
+
## UI behavior
|
|
425
|
+
|
|
426
|
+
- When either prop array is non-empty, the corresponding pool tab (Presets or Templates) appends a **CUSTOM** section after the built-in sections, containing one item per definition.
|
|
427
|
+
- Custom items carry a **star badge** in place of the colored accent that built-in preset/template items get; search results label them with a "Custom" badge.
|
|
428
|
+
- Items are drag-and-drop onto the stage. Icon resolution is `ICON_MAP[item.icon]` guarded by `{Icon && <Icon />}` — an unknown key renders nothing.
|
package/docs/fiber-concepts.md
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
title: Fiber Concepts
|
|
3
3
|
applies-to:
|
|
4
4
|
- "@sonata-innovations/fiber-types@^2.2"
|
|
5
|
+
- "@sonata-innovations/fiber-shared@^1.0"
|
|
5
6
|
- "@sonata-innovations/fiber-fbre@^3.3"
|
|
6
7
|
- "@sonata-innovations/fiber-fbt@^2.2"
|
|
7
8
|
- "@sonata-innovations/fiber-fbtl@^2.2"
|
|
9
|
+
- "@sonata-innovations/fiber-theme-editor@^1.0"
|
|
8
10
|
read-when: "First contact with Fiber: the Flow/Screen/Component model, FlowData, builders vs render engine, conditions/validation/calculations concepts."
|
|
9
11
|
---
|
|
10
12
|
|
|
@@ -22,7 +24,7 @@ read-when: "First contact with Fiber: the Flow/Screen/Component model, FlowData,
|
|
|
22
24
|
Fiber is a system for building and rendering data-collection forms. It splits authoring from rendering and offers two authoring surfaces targeted at different audiences:
|
|
23
25
|
|
|
24
26
|
- **FBT (Fiber Tool)** — A visual drag-and-drop builder for power users / form designers. Full feature surface: screens, multi-rule conditions, validation, calculations, reference markup, the complete 30-type component palette. See the [FBT integration guide](@sonata-innovations/fiber-fbt/docs/integration/fbt.md).
|
|
25
|
-
- **FBTL (Fiber Tool Lite)** — A stripped-down, end-user-friendly builder designed to be embedded in parent apps so non-technical end users (clinicians, teachers, etc.) can author their own forms.
|
|
27
|
+
- **FBTL (Fiber Tool Lite)** — A stripped-down, end-user-friendly builder designed to be embedded in parent apps so non-technical end users (clinicians, teachers, etc.) can author their own forms. Seven question types + Information Screens + single-rule conditions. Preserves advanced properties from loaded flows without editing them. See the [FBTL integration guide](@sonata-innovations/fiber-fbtl/docs/integration/fbtl.md).
|
|
26
28
|
- **FBRE (Fiber Render Engine)** — A render engine that consumes Flow JSON, renders the interactive form for end users, and outputs collected data ("FlowData") back to the parent application. See the [FBRE integration guide](@sonata-innovations/fiber-fbre/docs/integration/fbre.md).
|
|
27
29
|
|
|
28
30
|
A fourth library, the **Theme Editor**, is a plug-and-play widget that lets end users visually customize a flow's theme (color scheme, style, palette knobs) and emits the resulting `ThemeConfig`. See the [Theme Editor integration guide](@sonata-innovations/fiber-theme-editor/docs/integration/theme-editor.md).
|
|
@@ -92,7 +94,7 @@ The optional `config` object controls runtime behavior, organized into semantic
|
|
|
92
94
|
| `theme` | `colorScheme` | Built-in palette preset: `"light"` (default) or `"dark"` (replaces the former `darkMode` boolean) |
|
|
93
95
|
| `theme` | `style` | Visual style (`"clean"`, `"outlined"`, …) |
|
|
94
96
|
| `theme` | `background` / `surface` / `text` / `border` | Palette knobs overriding the preset tokens |
|
|
95
|
-
| `theme` | `radius` / `fontFamily` | Corner radius and font family knobs |
|
|
97
|
+
| `theme` | `radius` / `fontFamily` | Corner radius and font family knobs. `fontFamily` also accepts `{ family, src }`, which FBRE loads itself rather than assuming the host page already has the font |
|
|
96
98
|
| `theme` | `error` / `success` / `warning` | Semantic state color knobs |
|
|
97
99
|
| `navigation` | `transition` | Screen transition animation type |
|
|
98
100
|
| `navigation` | `allowInvalidTransition` | Allow navigating past screens with validation errors |
|
|
@@ -291,11 +293,11 @@ The formula engine lives in `@sonata-innovations/fiber-shared`, so calculations
|
|
|
291
293
|
### Authoring Phase (FBT or FBTL)
|
|
292
294
|
|
|
293
295
|
1. A form author opens **FBT** (power users) or **FBTL** (non-technical end users) in a parent application
|
|
294
|
-
2. They assemble the flow — FBT via multi-screen drag-and-drop with the full component palette; FBTL via a flat, one-question-per-screen list limited to
|
|
296
|
+
2. They assemble the flow — FBT via multi-screen drag-and-drop with the full component palette; FBTL via a flat, one-question-per-screen list limited to seven question types plus Information Screens
|
|
295
297
|
3. The builder produces a Flow JSON object via the `onFlowChange` callback (FBT also exposes `exportFlow()` on the store)
|
|
296
298
|
4. The parent application saves the Flow JSON (to a database, file, API, etc.)
|
|
297
299
|
|
|
298
|
-
FBTL
|
|
300
|
+
FBTL uses a **page-break model**: each stage card carries a break-after flag, so a freshly authored flow is one question per screen until the author merges cards onto a shared screen. Screen structure round-trips — a loaded multi-screen flow's boundaries become break flags rather than being flattened away — and the host can switch the builder to a single-screen model entirely (`options.screenModel`). A component-level condition is promoted to a screen-level condition only when its screen ends up holding exactly one component; otherwise it stays on the component as an in-place show/hide. Advanced properties FBTL cannot edit (calculations, reference markup, multi-rule conditions, and so on) are preserved untouched, and the resulting JSON remains fully interoperable with FBT.
|
|
299
301
|
|
|
300
302
|
### Rendering Phase (FBRE)
|
|
301
303
|
|
|
@@ -386,6 +388,8 @@ The markup → HTML converter lives in `@sonata-innovations/fiber-shared`, share
|
|
|
386
388
|
|
|
387
389
|
`${...}` tokens interpolate live values into text. A token is resolved in order against: **calculations** (by UUID) → **component values** (by UUID) → **context** (by key, from FBRE's `context` prop). Unresolvable references render as empty. This powers dynamic text like "Your total is ${calc-uuid}" or "Welcome back, ${userName}".
|
|
388
390
|
|
|
391
|
+
Writing one means knowing a UUID, so builders offer a picker. `resolvableReferences(flow)` from `@sonata-innovations/fiber-shared` returns every reference a flow can resolve, in that same order — use it rather than re-walking the flow, so a picker cannot drift from what the renderer will actually resolve. See [Confirmation Screen → Building your own picker](@sonata-innovations/fiber-fbre/docs/features/confirmation-screen.md#building-your-own-picker).
|
|
392
|
+
|
|
389
393
|
---
|
|
390
394
|
|
|
391
395
|
## 11. Extension Points
|
|
@@ -406,7 +410,7 @@ A template is likewise data — a `TemplateData` object (`{ type, label, icon, f
|
|
|
406
410
|
|
|
407
411
|
Presets and templates being plain data (rather than code) is what enables server-side storage: the hosted platform stores tenant-scoped custom presets and templates in the database and serves them to FBT at load time. Older factory-function definitions (functions returning fresh `Component`/`Flow` objects) are still accepted for back-compat, but data-based definitions are the current model.
|
|
408
412
|
|
|
409
|
-
See [`custom-presets-and-templates.md`](
|
|
413
|
+
See [`custom-presets-and-templates.md`](features/custom-presets-and-templates.md) for the full authoring guide.
|
|
410
414
|
|
|
411
415
|
---
|
|
412
416
|
|
|
@@ -37,7 +37,7 @@ Flow
|
|
|
37
37
|
| Field | Type | Default | Description |
|
|
38
38
|
|-------|------|---------|-------------|
|
|
39
39
|
| `mode` | `FlowModeType` | `"standard"` | `"standard"` or `"conversational"` — conversational mode centers content, auto-advances on selection, and Enter-advances on text inputs |
|
|
40
|
-
| `theme` | `ThemeConfig` | — | `{ color?, colorScheme?, style?, background?, surface?, text?, border?, radius?, fontFamily?, error?, success?, warning? }` — visual theme settings (palette knobs + preset) |
|
|
40
|
+
| `theme` | `ThemeConfig` | — | `{ color?, colorScheme?, style?, background?, surface?, text?, border?, radius?, fontFamily?, error?, success?, warning? }` — visual theme settings (palette knobs + preset). `fontFamily` is a CSS stack string **or** `{ family, src }` for a font FBRE loads itself |
|
|
41
41
|
| `navigation` | `NavigationConfig` | — | `{ transition?, allowInvalidTransition? }` — screen navigation settings |
|
|
42
42
|
| `controls` | `ControlsConfig` | — | `{ show?, layout?, showStepper?, stepperStyle? }` — navigation controls settings |
|
|
43
43
|
| `confirmation` | `ConfirmationConfig` | — | `{ show?, title?, body? }` — terminal thank-you screen (see [Confirmation Screen](@sonata-innovations/fiber-fbre/docs/integration/fbre.md#confirmation-screen)) |
|
|
@@ -70,8 +70,11 @@
|
|
|
70
70
|
"description": "Corner radius as a CSS length (--fbre-radius), e.g. '3px'."
|
|
71
71
|
},
|
|
72
72
|
"fontFamily": {
|
|
73
|
-
"
|
|
74
|
-
"
|
|
73
|
+
"description": "Font family (--fbre-font). A plain CSS stack string uses whatever font the host page already provides; an object additionally carries the sources FBRE registers itself via ensureFontLoaded, which is what makes a brand font work inside a shadow root.",
|
|
74
|
+
"oneOf": [
|
|
75
|
+
{ "type": "string" },
|
|
76
|
+
{ "$ref": "#/$defs/FontFamilyConfig" }
|
|
77
|
+
]
|
|
75
78
|
},
|
|
76
79
|
"error": {
|
|
77
80
|
"type": "string",
|
|
@@ -93,6 +96,73 @@
|
|
|
93
96
|
}
|
|
94
97
|
},
|
|
95
98
|
|
|
99
|
+
"FontSource": {
|
|
100
|
+
"type": "object",
|
|
101
|
+
"additionalProperties": false,
|
|
102
|
+
"required": ["url"],
|
|
103
|
+
"properties": {
|
|
104
|
+
"url": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "Where the font file is served from."
|
|
107
|
+
},
|
|
108
|
+
"format": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "CSS format() hint, e.g. 'woff2'."
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"FontFaceConfig": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"description": "One @font-face — a single weight/style of the family.",
|
|
117
|
+
"additionalProperties": false,
|
|
118
|
+
"required": ["src"],
|
|
119
|
+
"properties": {
|
|
120
|
+
"src": {
|
|
121
|
+
"type": "array",
|
|
122
|
+
"items": { "$ref": "#/$defs/FontSource" },
|
|
123
|
+
"minItems": 1
|
|
124
|
+
},
|
|
125
|
+
"weight": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "CSS font-weight: '400', '700', or a variable range like '100 900'."
|
|
128
|
+
},
|
|
129
|
+
"style": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"enum": ["normal", "italic", "oblique"]
|
|
132
|
+
},
|
|
133
|
+
"display": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"enum": ["auto", "block", "swap", "fallback", "optional"]
|
|
136
|
+
},
|
|
137
|
+
"unicodeRange": { "type": "string" }
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"FontFamilyConfig": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"description": "A brand font the renderer can load, rather than a family name it can only hope the host page already has.",
|
|
143
|
+
"additionalProperties": false,
|
|
144
|
+
"required": ["family"],
|
|
145
|
+
"properties": {
|
|
146
|
+
"family": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"description": "CSS family name, used for both the @font-face and the token value."
|
|
149
|
+
},
|
|
150
|
+
"src": {
|
|
151
|
+
"type": "array",
|
|
152
|
+
"items": { "$ref": "#/$defs/FontSource" },
|
|
153
|
+
"description": "Shorthand for a single regular face. Merged with faces."
|
|
154
|
+
},
|
|
155
|
+
"faces": {
|
|
156
|
+
"type": "array",
|
|
157
|
+
"items": { "$ref": "#/$defs/FontFaceConfig" },
|
|
158
|
+
"description": "Additional faces — a second weight, an italic."
|
|
159
|
+
},
|
|
160
|
+
"stack": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"description": "Full CSS stack written to --fbre-font. Defaults to the family plus a system fallback."
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
},
|
|
96
166
|
"NavigationConfig": {
|
|
97
167
|
"type": "object",
|
|
98
168
|
"description": "Screen navigation settings.",
|
|
@@ -136,7 +206,7 @@
|
|
|
136
206
|
|
|
137
207
|
"ConfirmationConfig": {
|
|
138
208
|
"type": "object",
|
|
139
|
-
"description": "Terminal 'thank you' / confirmation screen shown after the flow is submitted. Presentation-only, so it lives on the config rather than as a Screen.
|
|
209
|
+
"description": "Terminal 'thank you' / confirmation screen shown after the flow is submitted. Presentation-only, so it lives on the config rather than as a Screen. In local and remote modes it renders only when 'show' is not false and 'title' or 'body' has content (or the parent supplies an override via the onFlowComplete return value); server-driven mode falls back to a generic 'Thank you' when nothing is configured. An explicit 'show': false renders nothing in every mode.",
|
|
140
210
|
"properties": {
|
|
141
211
|
"show": {
|
|
142
212
|
"type": "boolean",
|
|
@@ -250,7 +320,7 @@
|
|
|
250
320
|
]
|
|
251
321
|
},
|
|
252
322
|
"properties": {
|
|
253
|
-
"description": "Type-specific properties. JSON schema is the open ComponentProperties shape below; TypeScript narrows it per-type via the variant map in
|
|
323
|
+
"description": "Type-specific properties. JSON schema is the open ComponentProperties shape below; TypeScript narrows it per-type via the variant map in types/src/component-variants.ts.",
|
|
254
324
|
"$ref": "#/$defs/ComponentProperties"
|
|
255
325
|
},
|
|
256
326
|
"conditions": { "$ref": "#/$defs/FlowConditionConfig" },
|
|
@@ -66,11 +66,40 @@ The theme has two layers: `colorScheme` + `style` pick built-in presets (the see
|
|
|
66
66
|
| `text` | `string` | No | Primary text color (`--fbre-text`); derives secondary/placeholder/label |
|
|
67
67
|
| `border` | `string` | No | Border/rule color (`--fbre-border`); derives hover/light/subtle |
|
|
68
68
|
| `radius` | `string` | No | Corner radius, any CSS length (`--fbre-radius`), e.g. `"3px"` |
|
|
69
|
-
| `fontFamily` | `string`
|
|
69
|
+
| `fontFamily` | `string \| FontFamilyConfig` | No | Font family (`--fbre-font`). See [FontFamilyConfig](#fontfamilyconfig) |
|
|
70
70
|
| `error` | `string` | No | Error state color (`--fbre-error`) |
|
|
71
71
|
| `success` | `string` | No | Success state color (`--fbre-success`) |
|
|
72
72
|
| `warning` | `string` | No | Warning state color (`--fbre-warning`) |
|
|
73
73
|
|
|
74
|
+
#### FontFamilyConfig
|
|
75
|
+
|
|
76
|
+
A plain string is a CSS stack and nothing more: the form renders in that family only if the host page already loaded it, and falls back to `system-ui` otherwise — silently, and to something that looks approximately fine. Passing an object instead gives the renderer the sources, and FBRE registers the faces in the owning document itself.
|
|
77
|
+
|
|
78
|
+
That matters most where the host cannot patch around it. FBRE is designed to mount inside a shadow root, and `@font-face` rules declared inside a shadow root's stylesheet are never registered — faces resolve at document level only.
|
|
79
|
+
|
|
80
|
+
| Field | Type | Required | Description |
|
|
81
|
+
| -------- | ------------------ | -------- | ------------------------------------------------------------------ |
|
|
82
|
+
| `family` | `string` | Yes | CSS family name, used for both the `@font-face` and the token value |
|
|
83
|
+
| `src` | `FontSource[]` | No | Shorthand for a single regular face. Merged with `faces` |
|
|
84
|
+
| `faces` | `FontFaceConfig[]` | No | Additional faces — a second weight, an italic |
|
|
85
|
+
| `stack` | `string` | No | Full stack written to `--fbre-font`. Defaults to the family plus a system fallback |
|
|
86
|
+
|
|
87
|
+
`FontSource` is `{ url, format? }`; `FontFaceConfig` is `{ src, weight?, style?, display?, unicodeRange? }`.
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"fontFamily": {
|
|
92
|
+
"family": "Brand Sans",
|
|
93
|
+
"src": [{ "url": "https://cdn.example.com/brand.woff2", "format": "woff2" }],
|
|
94
|
+
"faces": [
|
|
95
|
+
{ "src": [{ "url": "https://cdn.example.com/brand-bold.woff2", "format": "woff2" }], "weight": "700" }
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
See [FBRE Theming Guide → Loading a brand font](@sonata-innovations/fiber-fbre/docs/features/fbre-theming.md#loading-a-brand-font).
|
|
102
|
+
|
|
74
103
|
#### Style Types
|
|
75
104
|
|
|
76
105
|
**Standard mode styles** (6):
|
|
@@ -113,7 +142,7 @@ Each style has a default stepper visual (see `stepperStyle`). When switching for
|
|
|
113
142
|
|
|
114
143
|
### ConfirmationConfig
|
|
115
144
|
|
|
116
|
-
A terminal "thank you" screen shown after the flow is submitted (once `onFlowComplete` resolves). It is presentation-only — not a data-collection `Screen` — so it lives on the config.
|
|
145
|
+
A terminal "thank you" screen shown after the flow is submitted (once `onFlowComplete` resolves). It is presentation-only — not a data-collection `Screen` — so it lives on the config. In local and remote modes the screen renders only when `show` is not `false` **and** `title` or `body` has content; server-driven mode falls back to a generic "Thank you" when nothing is configured, and renders nothing on an explicit `show: false` (see [Per-mode behavior](@sonata-innovations/fiber-fbre/docs/features/confirmation-screen.md#per-mode-behavior)). When shown, it replaces the final screen and the navigation controls/stepper are hidden.
|
|
117
146
|
|
|
118
147
|
`title` and `body` support the same `${...}` reference markup as display components — references resolve against collected field values, calculations, and external `context` values (by name). A parent application can also override the configured message at runtime by returning (or resolving with) a `{ title?, body? }` object from `onFlowComplete` — useful for post-submit data such as a server-generated reference number.
|
|
119
148
|
|