@sonata-innovations/fiber-fbre 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/README.md ADDED
@@ -0,0 +1,508 @@
1
+ # @sonata-innovations/fiber-fbre v2
2
+
3
+ Fiber Render Engine — consumes Flow JSON and renders data collection forms. Handles conditional logic, validation, screen transitions, and outputs collected FlowData back to the parent application.
4
+
5
+ ## Quick Start
6
+
7
+ ### Local Mode
8
+
9
+ Pass a Flow object directly:
10
+
11
+ ```tsx
12
+ import { FBRE } from "@sonata-innovations/fiber-fbre";
13
+ import "@sonata-innovations/fiber-fbre/styles";
14
+
15
+ function App() {
16
+ return (
17
+ <FBRE
18
+ flow={myFlow}
19
+ screenIndex={0}
20
+ onFlowComplete={(data) => console.log(data)}
21
+ />
22
+ );
23
+ }
24
+ ```
25
+
26
+ ### Remote Mode
27
+
28
+ Fetch a published flow from a Fiber API:
29
+
30
+ ```tsx
31
+ import { FBRE } from "@sonata-innovations/fiber-fbre";
32
+ import "@sonata-innovations/fiber-fbre/styles";
33
+
34
+ function App() {
35
+ return (
36
+ <FBRE
37
+ flowId="your-flow-id"
38
+ apiEndpoint="https://your-api.example.com/api/v1"
39
+ apiKey="your-api-key"
40
+ onFlowComplete={(data) => console.log(data)}
41
+ />
42
+ );
43
+ }
44
+ ```
45
+
46
+ ### Server-Driven Mode
47
+
48
+ Session-based rendering where the server evaluates conditions and validation:
49
+
50
+ ```tsx
51
+ import { FBRE } from "@sonata-innovations/fiber-fbre";
52
+ import "@sonata-innovations/fiber-fbre/styles";
53
+
54
+ function App() {
55
+ return (
56
+ <FBRE
57
+ sessionEndpoint="https://your-api.example.com/api/v1/public/sessions"
58
+ flowId="your-flow-id"
59
+ onFlowComplete={(data) => console.log(data)}
60
+ />
61
+ );
62
+ }
63
+ ```
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ npm install @sonata-innovations/fiber-fbre
69
+ ```
70
+
71
+ Then import the CSS in your app entry point:
72
+
73
+ ```ts
74
+ import "@sonata-innovations/fiber-fbre/styles";
75
+ ```
76
+
77
+ **Peer dependencies:** `react ^18.0.0 || ^19.0.0`, `react-dom ^18.0.0 || ^19.0.0`
78
+
79
+ **Runtime dependencies:** `zustand`, `@sonata-innovations/fiber-types`, `@sonata-innovations/fiber-shared`
80
+
81
+ ## API
82
+
83
+ ### `<FBRE />` Props
84
+
85
+ FBRE supports three rendering modes, selected by which props you pass. The modes are mutually exclusive.
86
+
87
+ #### Local Mode
88
+
89
+ Render a Flow object you already have in memory.
90
+
91
+ | Prop | Type | Required | Description |
92
+ |------|------|----------|-------------|
93
+ | `flow` | `Flow` | Yes | Flow JSON object |
94
+ | `data` | `FlowData` | No | Pre-populated form data |
95
+ | `screenIndex` | `number` | No | Initial screen index (default `0`) |
96
+ | `theme` | `ThemeConfig` | No | Override theme settings (merged over `flow.config.theme`) |
97
+ | `navigation` | `NavigationConfig` | No | Override navigation settings (merged over `flow.config.navigation`) |
98
+ | `controls` | `ControlsConfig` | No | Override controls settings (merged over `flow.config.controls`) |
99
+ | `context` | `Record<string, string \| boolean \| number>` | No | External context values for condition evaluation and calculations |
100
+ | `storeRef` | `MutableRefObject<StoreApi<FBREStoreState> \| null>` | No | Ref to access the Zustand store |
101
+ | `onFlowComplete` | `(data: FlowData) => void` | Yes | Called when the user completes the flow |
102
+ | `onScreenChange` | `(index: number, data: FlowData) => void` | No | Called on screen navigation |
103
+ | `onScreenValidationChange` | `(index: number, data: any) => void` | No | Called when screen validity changes |
104
+
105
+ #### Remote Mode
106
+
107
+ Fetch a published flow from a Fiber API by ID.
108
+
109
+ | Prop | Type | Required | Description |
110
+ |------|------|----------|-------------|
111
+ | `flowId` | `string` | Yes | ID of the published flow |
112
+ | `apiEndpoint` | `string` | Yes | Base URL of the Fiber API |
113
+ | `apiKey` | `string` | No | API key for authentication |
114
+ | `data` | `FlowData` | No | Pre-populated form data |
115
+ | `screenIndex` | `number` | No | Initial screen index (default `0`) |
116
+ | `theme` | `ThemeConfig` | No | Override theme settings |
117
+ | `navigation` | `NavigationConfig` | No | Override navigation settings |
118
+ | `controls` | `ControlsConfig` | No | Override controls settings |
119
+ | `context` | `Record<string, string \| boolean \| number>` | No | External context values for condition evaluation and calculations |
120
+ | `storeRef` | `MutableRefObject<StoreApi<FBREStoreState> \| null>` | No | Ref to access the Zustand store |
121
+ | `onFlowComplete` | `(data: FlowData) => void` | Yes | Called when the user completes the flow |
122
+ | `onScreenChange` | `(index: number, data: FlowData) => void` | No | Called on screen navigation |
123
+ | `onScreenValidationChange` | `(index: number, data: any) => void` | No | Called when screen validity changes |
124
+
125
+ #### Server-Driven Mode
126
+
127
+ Session-based rendering. The server evaluates conditions and validation; the client renders one screen at a time.
128
+
129
+ | Prop | Type | Required | Description |
130
+ |------|------|----------|-------------|
131
+ | `sessionEndpoint` | `string` | Yes | Session API base URL |
132
+ | `flowId` | `string` | Yes | ID of the flow to start a session for |
133
+ | `apiKey` | `string` | No | API key for authentication |
134
+ | `theme` | `ThemeConfig` | No | Override theme settings |
135
+ | `context` | `Record<string, string \| boolean \| number>` | No | External context values for condition evaluation and calculations |
136
+ | `onFlowComplete` | `(data: FlowData) => void` | Yes | Called when the user completes the flow |
137
+ | `onScreenChange` | `(screenNumber: number) => void` | No | Called on screen navigation (note: receives screen number, not index + data) |
138
+
139
+ ### Imperative Access
140
+
141
+ Access the store directly for programmatic control:
142
+
143
+ ```tsx
144
+ import { useFBREStore, useFBREStoreApi, useFBREApi } from "@sonata-innovations/fiber-fbre";
145
+
146
+ // Inside a child of <FBRE />
147
+ const flowData = useFBREStore((s) => s.getFlowData());
148
+ const storeApi = useFBREStoreApi();
149
+ const data = storeApi.getState().getFlowData();
150
+
151
+ // In remote mode — access API config, flowId, tenantId
152
+ const apiContext = useFBREApi();
153
+ ```
154
+
155
+ ### Events
156
+
157
+ ```tsx
158
+ import { addFBREEventListener, removeFBREEventListener } from "@sonata-innovations/fiber-fbre";
159
+
160
+ const handler = (id, data) => console.log("file uploaded:", id, data);
161
+ addFBREEventListener("file-upload", handler);
162
+ removeFBREEventListener("file-upload", handler);
163
+ ```
164
+
165
+ ### Exports
166
+
167
+ ```ts
168
+ // Components
169
+ import { FBRE } from "@sonata-innovations/fiber-fbre";
170
+
171
+ // Store hooks
172
+ import { useFBREStore, useFBREStoreApi, useFBREApi } from "@sonata-innovations/fiber-fbre";
173
+
174
+ // Event system
175
+ import { addFBREEventListener, removeFBREEventListener } from "@sonata-innovations/fiber-fbre";
176
+
177
+ // Error classes
178
+ import { ApiError, TimeoutError } from "@sonata-innovations/fiber-fbre";
179
+
180
+ // Types
181
+ import type {
182
+ FBREProps,
183
+ FBRELocalProps,
184
+ FBRERemoteProps,
185
+ FBREServerDrivenModeProps,
186
+ FBREStoreState,
187
+ FBREApiConfig,
188
+ Flow,
189
+ FlowScreen,
190
+ FlowConfiguration,
191
+ ThemeConfig,
192
+ NavigationConfig,
193
+ ControlsConfig,
194
+ FlowMetadata,
195
+ Component,
196
+ ComponentProperties,
197
+ ComponentDisplayProperties,
198
+ ComponentDividerProperties,
199
+ ComponentInputProperties,
200
+ ComponentOptionProperties,
201
+ ComponentSliderProperties,
202
+ ComponentSwitchProperties,
203
+ ComponentRatingProperties,
204
+ ComponentFileUploadProperties,
205
+ ComponentGroupProperties,
206
+ FlowData,
207
+ ScreenData,
208
+ ComponentData,
209
+ FileUploadData,
210
+ FileUploadBase64Data,
211
+ FileUploadS3Data,
212
+ FlowConditionConfig,
213
+ ConditionOperator,
214
+ ConditionRule,
215
+ ConditionGroup,
216
+ ConditionDependency,
217
+ } from "@sonata-innovations/fiber-fbre";
218
+ ```
219
+
220
+ ## Flow JSON Schema
221
+
222
+ ```
223
+ Flow
224
+ ├── uuid: string
225
+ ├── metadata: { name?, description?, ...}
226
+ ├── config?: { theme?: { color?, darkMode?, style? }, navigation?: { transition?, allowInvalidTransition? }, controls?: { show?, layout?, showStepper? }, summary? }
227
+ └── screens: FlowScreen[]
228
+ ├── uuid: string
229
+ ├── label?: string
230
+ ├── conditions?: FlowConditionConfig
231
+ └── components: Component[]
232
+ ├── uuid: string
233
+ ├── type: string
234
+ ├── properties: { ... }
235
+ ├── conditions?: FlowConditionConfig
236
+ └── components?: Component[] (groups and repeaters)
237
+ ```
238
+
239
+ ### Component Types
240
+
241
+ | Type | Category | Description |
242
+ |------|----------|-------------|
243
+ | `header` | Display | Heading text |
244
+ | `text` | Display | Rich text with markup support |
245
+ | `divider` | Display | Horizontal rule with optional label |
246
+ | `callout` | Display | Styled alert/info box with variant coloring (info, success, warning, neutral) |
247
+ | `table` | Display | Static comparison/data table with optional column highlighting |
248
+ | `inputText` | Input | Single-line text field |
249
+ | `inputTextArea` | Input | Multi-line text field |
250
+ | `inputNumber` | Input | Numeric input (supports decimal restriction and start adornment) |
251
+ | `dropDown` | Selection | Native select dropdown |
252
+ | `dropDownMulti` | Selection | Multi-select with tag chips |
253
+ | `checkbox` | Selection | Checkbox group |
254
+ | `radio` | Selection | Radio button group |
255
+ | `toggleSwitch` | Selection | On/off toggle |
256
+ | `yesNo` | Selection | Two large tappable buttons for binary yes/no |
257
+ | `cardSelect` | Selection | Card-based visual selection with image/icon support |
258
+ | `date` | Date & Time | Calendar popup date picker |
259
+ | `time` | Date & Time | Hour/minute time selector |
260
+ | `dateTime` | Date & Time | Combined date + time picker |
261
+ | `dateRange` | Date & Time | Two date pickers for start/end |
262
+ | `timeRange` | Date & Time | Two time pickers for start/end |
263
+ | `dateTimeRange` | Date & Time | Two datetime pickers for start/end |
264
+ | `fileUpload` | Interactive | File picker with size validation |
265
+ | `rating` | Interactive | Star rating with half-star precision |
266
+ | `slider` | Interactive | Range slider with value label |
267
+ | `colorPicker` | Interactive | Saturation/hue picker with hex input |
268
+ | `computed` | Display | Calculated field with formula-based computed values |
269
+ | `signature` | Interactive | Signature pad — draw on canvas, type name, or both |
270
+ | `group` | Container | Component container with layout grid, collapsible |
271
+ | `repeater` | Container | Iterable component container (add/remove iterations, pre-populated rows) |
272
+
273
+ ### Conditions
274
+
275
+ Components and screens can be conditionally shown/hidden using `FlowConditionConfig`:
276
+
277
+ ```json
278
+ {
279
+ "action": "show",
280
+ "when": {
281
+ "logic": "and",
282
+ "rules": [
283
+ {
284
+ "source": "other-component-uuid",
285
+ "operator": "equals",
286
+ "value": "yes"
287
+ }
288
+ ]
289
+ }
290
+ }
291
+ ```
292
+
293
+ **Logic:** `"and"` (all rules must match) or `"or"` (any rule matches).
294
+
295
+ **Context rules:** Set `sourceType: "context"` on a rule to reference an external context value instead of a component. In this case, `source` is a context key (not a component UUID).
296
+
297
+ **Operators:**
298
+
299
+ | Category | Operators |
300
+ |----------|-----------|
301
+ | Equality | `equals`, `notEquals` |
302
+ | String | `contains`, `notContains`, `startsWith`, `endsWith` |
303
+ | Presence | `isEmpty`, `isNotEmpty` |
304
+ | Numeric | `greaterThan`, `greaterThanOrEqual`, `lessThan`, `lessThanOrEqual` |
305
+ | Set (single) | `isOneOf`, `isNotOneOf` |
306
+ | Set (multi) | `includesAny`, `includesAll`, `includesNone` |
307
+ | Boolean | `isTrue`, `isFalse` |
308
+
309
+ Condition results are stored separately from the Flow JSON in a `conditionResults` map (keyed by target UUID). Hidden components are excluded from FlowData output.
310
+
311
+ ### Validation
312
+
313
+ Components support a rules-based validation system via `properties.validation`:
314
+
315
+ ```json
316
+ {
317
+ "validation": {
318
+ "rules": [
319
+ { "type": "required" },
320
+ { "type": "email" },
321
+ { "type": "minLength", "params": { "min": 5 } }
322
+ ]
323
+ }
324
+ }
325
+ ```
326
+
327
+ **17 built-in validators:** `required`, `email`, `phone`, `url`, `minLength`, `maxLength`, `exactLength`, `minValue`, `maxValue`, `pattern`, `minSelected`, `maxSelected`, `fileType`, `fileSize`, `contains`, `excludes`, `matchesField`
328
+
329
+ Each validator has a default error message. Custom messages can be set per rule via the `message` field.
330
+
331
+ **Error display:** The first failing message is shown below the field with an "(and N more)" count when multiple rules fail.
332
+
333
+ **Cross-field validation:** `matchesField` enables bidirectional re-evaluation — changing either field re-validates the other.
334
+
335
+ **Migration:** Legacy `required` and `regex` flat properties are automatically converted to validation rules on load.
336
+
337
+ Validation errors are stored in `validationErrors: Record<string, string[]>` on the store (keyed by component UUID). Hidden components (by conditions) do not block screen validity.
338
+
339
+ ### Calculations
340
+
341
+ Flows can include formula-based computed values via `FlowCalculation`:
342
+
343
+ ```json
344
+ {
345
+ "calculations": [
346
+ {
347
+ "uuid": "calc-uuid",
348
+ "formula": "{{comp-a-uuid}} + {{comp-b-uuid}} * 0.1",
349
+ "label": "Total"
350
+ }
351
+ ]
352
+ }
353
+ ```
354
+
355
+ - Formulas reference component values via `{uuid}` tokens and support standard arithmetic (`+`, `-`, `*`, `/`)
356
+ - Aggregation functions: `SUM()`, `COUNT()`, `AVG()`, `MIN()`, `MAX()` over repeater iterations
357
+ - Scalar `MIN(expr, ...)` / `MAX(expr, ...)` for capping values (e.g. `MIN({discount}, 25)`)
358
+ - `IF(condition, then, else)` for conditional formulas (e.g. tiered pricing)
359
+ - Comparison operators: `>`, `<`, `>=`, `<=`, `==`, `!=` (return 1/0)
360
+ - Option metadata is accessible for option-based components
361
+ - Results update reactively when source values change
362
+ - Access results via `getCalculationResult(uuid)` on the store
363
+
364
+ ### Markup
365
+
366
+ Text components and `detail` fields support inline markup:
367
+
368
+ - `[b]bold[/b]` → **bold**
369
+ - `[i]italic[/i]` → *italic*
370
+ - `[l href="url"]link[/l]` → [link](url)
371
+
372
+ ## Theming
373
+
374
+ FBRE uses CSS custom properties. Override on the container:
375
+
376
+ ```css
377
+ .fbre-container {
378
+ --fbre-theme-color: #1976d2;
379
+ --fbre-theme-light: #e3f2fd;
380
+ --fbre-theme-dark: #1565c0;
381
+ --fbre-error: #d32f2f;
382
+ --fbre-text: #212121;
383
+ --fbre-text-secondary: #666;
384
+ --fbre-border: #ccc;
385
+ --fbre-bg: #fff;
386
+ --fbre-radius: 4px;
387
+ --fbre-font: "Segoe UI", system-ui, sans-serif;
388
+ }
389
+ ```
390
+
391
+ `theme.color` from `flow.config.theme.color` is applied automatically via inline style.
392
+
393
+ ### Dark Mode
394
+
395
+ Enable dark mode via the `theme` prop or config:
396
+
397
+ ```tsx
398
+ // Via theme prop (takes precedence)
399
+ <FBRE flow={myFlow} theme={{ darkMode: true }} onFlowComplete={handleComplete} />
400
+
401
+ // Via flow config
402
+ const flow = {
403
+ ...myFlow,
404
+ config: { ...myFlow.config, theme: { darkMode: true } }
405
+ };
406
+ <FBRE flow={flow} onFlowComplete={handleComplete} />
407
+ ```
408
+
409
+ Dark mode applies `data-mode="dark"` on the container and overrides all CSS custom properties with a dark palette. Custom `theme.color` values are preserved — the inline style takes precedence over the dark mode default.
410
+
411
+ ### Screen Transitions
412
+
413
+ Animate screen changes by setting `navigation.transition` in the flow config:
414
+
415
+ ```json
416
+ {
417
+ "config": {
418
+ "navigation": { "transition": "slideFade" }
419
+ }
420
+ }
421
+ ```
422
+
423
+ | Type | Effect | Direction-aware? |
424
+ |------|--------|-----------------|
425
+ | `"none"` | Instant swap (default) | — |
426
+ | `"slide"` | Full horizontal slide | Yes |
427
+ | `"fade"` | Crossfade | No |
428
+ | `"slideFade"` | 30px slide + opacity | Yes |
429
+ | `"rise"` | Vertical rise/sink | Yes |
430
+ | `"scaleFade"` | Scale + opacity | No |
431
+
432
+ Direction-aware transitions reverse when navigating backward. Buttons are disabled during animation to prevent overlapping transitions.
433
+
434
+ Customize timing via CSS custom properties:
435
+
436
+ ```css
437
+ .fbre-container {
438
+ --fbre-transition-duration: 250ms;
439
+ --fbre-transition-easing: cubic-bezier(0.4, 0, 0.2, 1);
440
+ }
441
+ ```
442
+
443
+ `@media (prefers-reduced-motion: reduce)` sets duration to `0ms` automatically.
444
+
445
+ ## Architecture
446
+
447
+ | Concern | Implementation |
448
+ |---------|---------------|
449
+ | UI framework | Zero-dependency custom CSS |
450
+ | Styling | CSS custom properties + BEM (`fbre-` prefix) |
451
+ | Display detection | `isDisplayComponent()` checks type against constant set (`header`, `text`, `divider`, `callout`, `table`) |
452
+ | State | Zustand store factory, one store per `<FBRE />` instance via React Context |
453
+ | Re-renders | Zustand selectors — granular, automatic |
454
+ | Build | Vite library mode |
455
+ | Components | Registry pattern (`Map<string, FC>`), one file per type |
456
+ | Dependencies | react, zustand, @sonata-innovations/fiber-types, @sonata-innovations/fiber-shared |
457
+
458
+ ## FlowData Output
459
+
460
+ `getFlowData()` returns collected form data. Display-only components (`header`, `text`, `divider`, `callout`, `table`) are excluded automatically based on their type.
461
+
462
+ ```
463
+ FlowData
464
+ ├── uuid: string
465
+ ├── metadata: Record<string, string>
466
+ └── screens: ScreenData[]
467
+ ├── uuid: string
468
+ ├── label?: string
469
+ └── components: ComponentData[]
470
+ ├── uuid: string
471
+ ├── type: string
472
+ ├── label?: string (omitted when empty)
473
+ ├── value: string | string[] | number | number[] | boolean | null | FileUploadData
474
+ └── components?: ComponentData[][] (groups and repeaters)
475
+ ```
476
+
477
+ ## Build
478
+
479
+ ```bash
480
+ npm run build
481
+ ```
482
+
483
+ Output:
484
+
485
+ ```
486
+ dist/
487
+ ├── index.d.ts # Bundled type declarations
488
+ ├── fiber-fbre.js # ES module
489
+ ├── fiber-fbre.cjs # CommonJS
490
+ └── fiber-fbre.css # All styles
491
+ ```
492
+
493
+ ## Responsive Sizing
494
+
495
+ FBRE uses CSS container queries to automatically scale controls in narrow containers (under 400px). Buttons, stepper dots, and toggle switches shrink proportionally. No configuration needed — just embed in a smaller container and the compact sizing kicks in.
496
+
497
+ ## Multiple Instances
498
+
499
+ Each `<FBRE />` creates its own isolated Zustand store. Multiple instances can run simultaneously on the same page without state conflicts.
500
+
501
+ ```tsx
502
+ <FBRE flow={flowA} onFlowComplete={handleA} />
503
+ <FBRE flow={flowB} onFlowComplete={handleB} />
504
+ ```
505
+
506
+ ## AI-Assisted Development
507
+
508
+ For AI integration reference, see [AI Integration Guide](../documentation/ai-integration-guide.md) and [llms.txt](./llms.txt).
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("react/jsx-runtime"),w=require("react"),G=require("zustand"),Je=require("@sonata-innovations/fiber-types"),U=require("@sonata-innovations/fiber-shared"),Ye=new Map,We=e=>Ye.get(e),Xe=new Set(["header","text","divider","callout","table"]),ue=e=>Xe.has(e),Ke=(e,s)=>{var o,t,n,r;if(s.includes(":")){const i=s.split(":"),a=e.components[i[0]];return(n=(t=(o=a==null?void 0:a.addedComponents)==null?void 0:o[parseInt(i[1])])==null?void 0:t[parseInt(i[2])])==null?void 0:n.value}return(r=e.components[s])==null?void 0:r.value},T=(e,s)=>{var t;const o=(t=e.properties)==null?void 0:t.validation;return!o||!o.rules||o.rules.length===0?[]:U.validateValue(e.value,o,s?n=>Ke(s,n):void 0)},Qe=e=>{var o;const s=(o=e.properties)==null?void 0:o.validation;return!s||!s.rules?!1:s.rules.some(t=>t.type==="required")},z=e=>{var o,t;const s={...e};return Array.isArray((o=s.properties)==null?void 0:o.options)&&(s.properties={...s.properties,options:Je.normalizeOptions(s.properties.options)}),e.type==="computed"?(s.value=null,s.valid=!0):!ue(e.type)&&e.type!=="group"&&e.type!=="repeater"&&(s.value=null,s.valid=!Qe(e)),(e.type==="checkbox"||e.type==="dropDownMulti")&&(s.value=[]),e.type==="radio"&&"options"in e.properties&&e.properties.options.length>0&&(s.value=e.properties.options[0].value),e.type==="toggleSwitch"&&(s.value=!1),e.type==="colorPicker"&&((t=e.properties)!=null&&t.defaultValue)&&(s.value=e.properties.defaultValue),e.type==="slider"&&(s.value="initValue"in e.properties?e.properties.initValue:"min"in e.properties?e.properties.min:0),s},oe=(e,s,o)=>{var t;for(const n of o.rules)if(n.type==="matchesField"&&((t=n.params)!=null&&t.field)){const r=n.params.field;e[r]||(e[r]=[]),e[r].push({target:s,config:o})}},X=(e,s)=>{const o=e.screens[s];return o?!o.components.some(n=>{var a;const r=e.components[n.uuid];if(!r)return!1;if(r.type==="group"||r.type==="repeater")return(a=r.addedComponents)==null?void 0:a.some(c=>c.some(u=>{const l=u.conditions&&"when"in u.conditions?u.conditions:void 0;return l&&U.isHiddenByCondition(l,e.conditionResults[u.uuid])?!1:!u.valid}));const i=r.conditions&&"when"in r.conditions?r.conditions:void 0;return U.isHiddenByCondition(i,e.conditionResults[r.uuid])?!1:r&&"valid"in r&&!r.valid}):!0};function Ze(e){const s={};for(const o of e){const t=U.extractFormulaReferences(o.formula);for(const n of t)s[n]||(s[n]=[]),s[n].includes(o.uuid)||s[n].push(o.uuid)}return s}function Ue(e){const s=new Map(e.map(i=>[i.uuid,i])),o=new Set(e.map(i=>i.uuid)),t=new Set,n=[];function r(i,a){if(t.has(i)||a.has(i))return;a.add(i);const c=s.get(i);if(!c)return;const u=U.extractFormulaReferences(c.formula);for(const l of u)o.has(l)&&r(l,a);a.delete(i),t.add(i),n.push(c)}for(const i of e)r(i.uuid,new Set);return n}function Ae(e,s){return{resolveValue:o=>{if(o in s)return s[o];const t=J(e,o);if(!t)return null;const n=t.value;if(n==null||n==="")return null;const r=Number(n);return isNaN(r)?null:r},resolveOptionMetadata:(o,t)=>{var l;const n=J(e,o);if(!n)return null;const r=n.value;if(!r)return null;const i=(l=n.properties)==null?void 0:l.options;if(!Array.isArray(i))return null;const a=i.find(d=>d.value===r||d.label===r);if(!(a!=null&&a.metadata))return null;const c=a.metadata[t];if(c==null)return null;const u=Number(c);return isNaN(u)?null:u},resolveRepeaterValues:o=>{for(const t of Object.keys(e.components)){const n=e.components[t];if(n.type!=="repeater"||!n.addedComponents||!n.components)continue;const r=n.components.findIndex(a=>a.uuid===o);if(r===-1)continue;const i=[];for(const a of n.addedComponents){const c=a[r];if(!c)continue;const u=c.value;if(u==null||u==="")continue;const l=Number(u);isNaN(l)||i.push(l)}return i.length>0?i:null}return null}}}function ye(e){const s=e.calculations??[];if(s.length===0)return{};const o=Ue(s),t={},n=Ae(e,t);for(const r of o)t[r.uuid]=U.evaluateFormula(r.formula,n);return t}function me(e,s){const o=e.calculationsByDependency,t=e.calculations??[];if(t.length===0||!o)return null;const n=new Set,r=[s];for(;r.length>0;){const l=r.shift(),d=o[l];if(d)for(const f of d)n.has(f)||(n.add(f),r.push(f))}if(n.size===0)return null;const i=Ue(t),a={...e.calculationResults},c=Ae(e,a);let u=!1;for(const l of i)if(n.has(l.uuid)){const d=U.evaluateFormula(l.formula,c);a[l.uuid]!==d&&(a[l.uuid]=d,u=!0)}return u?a:null}function en(e){const s={},o=t=>{var r;if(t.type!=="computed"||!((r=t.properties)!=null&&r.formula))return;const n=U.extractFormulaReferences(t.properties.formula);for(const i of n)s[i]||(s[i]=[]),s[i].includes(t.uuid)||s[i].push(t.uuid)};for(const t of Object.values(e))if(o(t),(t.type==="repeater"||t.type==="group")&&t.components)for(const n of t.components)o(n);return s}function Le(e,s,o,t){var c,u;const n=e.components[o],r=((c=n==null?void 0:n.components)==null?void 0:c.map(l=>l.uuid))??[],i=(u=n==null?void 0:n.addedComponents)==null?void 0:u[t],a=new Map;if(i)for(let l=0;l<i.length;l++){const d=r[l];d&&a.set(d,i[l])}return{resolveValue:l=>{if(l in s)return s[l];const d=a.get(l);if(d){const g=d.value;if(g==null||g==="")return null;const h=Number(g);return isNaN(h)?null:h}const f=J(e,l);if(!f)return null;const m=f.value;if(m==null||m==="")return null;const y=Number(m);return isNaN(y)?null:y},resolveOptionMetadata:(l,d)=>{var x;const m=a.get(l)??J(e,l);if(!m)return null;const y=m.value;if(!y)return null;const g=(x=m.properties)==null?void 0:x.options;if(!Array.isArray(g))return null;const h=g.find(b=>b.value===y||b.label===y);if(!(h!=null&&h.metadata))return null;const v=h.metadata[d];if(v==null)return null;const C=Number(v);return isNaN(C)?null:C},resolveRepeaterValues:l=>{for(const d of Object.keys(e.components)){const f=e.components[d];if(f.type!=="repeater"||!f.addedComponents||!f.components)continue;const m=f.components.findIndex(g=>g.uuid===l);if(m===-1)continue;const y=[];for(const g of f.addedComponents){const h=g[m];if(!h)continue;const v=h.value;if(v==null||v==="")continue;const C=Number(v);isNaN(C)||y.push(C)}return y.length>0?y:null}return null}}}function de(e,s){return{resolveValue:o=>{if(o in s)return s[o];const t=J(e,o);if(!t)return null;const n=t.value;if(n==null||n==="")return null;const r=Number(n);return isNaN(r)?null:r},resolveOptionMetadata:(o,t)=>{var l;const n=J(e,o);if(!n)return null;const r=n.value;if(!r)return null;const i=(l=n.properties)==null?void 0:l.options;if(!Array.isArray(i))return null;const a=i.find(d=>d.value===r||d.label===r);if(!(a!=null&&a.metadata))return null;const c=a.metadata[t];if(c==null)return null;const u=Number(c);return isNaN(u)?null:u},resolveRepeaterValues:o=>{for(const t of Object.keys(e.components)){const n=e.components[t];if(n.type!=="repeater"||!n.addedComponents||!n.components)continue;const r=n.components.findIndex(a=>a.uuid===o);if(r===-1)continue;const i=[];for(const a of n.addedComponents){const c=a[r];if(!c)continue;const u=c.value;if(u==null||u==="")continue;const l=Number(u);isNaN(l)||i.push(l)}return i.length>0?i:null}return null}}}function ge(e){var o,t;const s=e.calculationResults??{};for(const n of Object.values(e.components))if(n.type==="computed"&&((o=n.properties)!=null&&o.formula)){const r=de(e,s),i=U.evaluateFormula(n.properties.formula,r);n.value=i}for(const n of Object.values(e.components))if((n.type==="repeater"||n.type==="group")&&n.addedComponents&&n.components)for(let r=0;r<n.addedComponents.length;r++){const i=n.addedComponents[r];for(let a=0;a<i.length;a++){const c=i[a],u=n.components[a];if((u==null?void 0:u.type)==="computed"&&((t=u.properties)!=null&&t.formula)){const l=n.type==="repeater"?Le(e,s,n.uuid,r):de(e,s),d=U.evaluateFormula(u.properties.formula,l);c.value=d}}}}function nn(e,s){var i,a;const o=e.computedByDependency;if(!o)return!1;const t=o[s];if(!t||t.length===0)return!1;const n=e.calculationResults??{};let r=!1;for(const c of t){const u=e.components[c];if(u&&u.type==="computed"&&((i=u.properties)!=null&&i.formula)){const l=de(e,n),d=U.evaluateFormula(u.properties.formula,l);u.value!==d&&(e.components[c]={...u,value:d},r=!0);continue}for(const l of Object.values(e.components))if((l.type==="repeater"||l.type==="group")&&l.components&&l.addedComponents){const d=l.components.findIndex(m=>m.uuid===c);if(d===-1)continue;const f=l.components[d];if((f==null?void 0:f.type)!=="computed"||!((a=f.properties)!=null&&a.formula))continue;for(let m=0;m<l.addedComponents.length;m++){const y=l.addedComponents[m][d];if(!y)continue;const g=l.type==="repeater"?Le(e,n,l.uuid,m):de(e,n),h=U.evaluateFormula(f.properties.formula,g);y.value!==h&&(l.addedComponents[m][d]={...y,value:h},r=!0)}}}return r}const Pe=(e,s)=>{var o,t;if(s.includes(":")){const n=s.split(":"),r=e[n[0]];return(t=(o=r==null?void 0:r.addedComponents)==null?void 0:o[parseInt(n[1])])==null?void 0:t[parseInt(n[2])]}return e[s]},ae=(e,s)=>{for(const o of e.screenOrder)if(e.screens[o].components.some(n=>n.uuid===s))return o;return null},tn=(e,s)=>{if(!s.includes(":"))return null;const o=s.split(":");if(o.length!==3)return null;const t=o[0],n=parseInt(o[2]),r=e.components[t];if(!r||r.type!=="repeater"||!r.components)return null;const i=r.components[n];return(i==null?void 0:i.uuid)??null},ke=(e,s,o,t,n)=>{const r=s(),i=r.groupComponentMap[o]??o,a=rn(e,s,i),c={components:r.components,groupComponentMap:r.groupComponentMap},u=T(t,c);t.valid=u.length===0;const l={...r.validationErrors,[o]:u},d=r.validationsByDependency[o];if(d)for(const x of d){const b=J(r,x.target);if(b){const R=T(b,c);b.valid=R.length===0,l[x.target]=R}}const f=ae(r,n),m={components:{...r.components},validationErrors:l};if(a&&(m.conditionResults=a),f){const x={...r,...m};m.screenValidity={...r.screenValidity,[f]:X(x,f)}}const y={...r,...m},g=o.includes(":")?tn(y,o):null,h=[],v=x=>{if(nn(y,x)){const b=y.computedByDependency[x]??[];for(const R of b)h.includes(R)||(h.push(R),v(R))}};v(i),g&&g!==i&&v(g);let C=me(y,i);if(g&&g!==i){const x=C?{...y,calculationResults:C}:y,b=me(x,g);b&&(C=b)}for(const x of h){const b=C?{...y,calculationResults:C}:y,R=me(b,x);R&&(C=R)}C&&(m.calculationResults=C),e(m)},on=(e,s)=>({updateComponentValue:(o,t)=>{var i,a;const n=s();if(o.includes(":")){const c=o.split(":"),u=c[0],l=parseInt(c[1]),d=parseInt(c[2]),f=n.components[u];if(!((a=(i=f==null?void 0:f.addedComponents)==null?void 0:i[l])!=null&&a[d]))return;const m=f.addedComponents[l][d].value!==t;if(f.addedComponents[l][d]={...f.addedComponents[l][d],value:t},m){ke(e,s,o,f.addedComponents[l][d],u);return}e({components:{...n.components}});return}const r=n.components[o];if(r){if(r.type==="group"||r.type==="repeater"){e({components:{...n.components}});return}t!==r.value&&(r.value=t,ke(e,s,o,r,o))}},addGroupIteration:o=>{const t=s(),n=t.components[o];if(!n||n.type!=="group"||!n.components)return;n.addedComponents||(n.addedComponents=[]);const r={...t.conditionsByDependency},i=n.components.map((u,l)=>{const d=z(u);if(d.uuid=[o,n.addedComponents.length,l].join(":"),t.groupComponentMap[d.uuid]=u.uuid,d.conditions&&Object.keys(d.conditions).length>0){const m="when"in d.conditions?d.conditions:null;m&&(d.conditions=m,W(r,d.uuid,m,"component"))}const f=T(d);return d.valid=f.length===0,d});n.addedComponents.push(i);const a=ae(t,o),c={...t.screenValidity};return a&&(c[a]=X({...t},a)),e({components:{...t.components},groupComponentMap:{...t.groupComponentMap},conditionsByDependency:r,screenValidity:c}),n.addedComponents},addRepeaterIteration:o=>{const t=s(),n=t.components[o];if(!n||n.type!=="repeater"||!n.components)return;n.addedComponents||(n.addedComponents=[]);const r={...t.conditionsByDependency},i=n.components.map((d,f)=>{const m=z(d);if(m.uuid=[o,n.addedComponents.length,f].join(":"),m.conditions&&Object.keys(m.conditions).length>0){const g="when"in m.conditions?m.conditions:null;g&&(m.conditions=g,W(r,m.uuid,g,"component"))}const y=T(m);return m.valid=y.length===0,m});n.addedComponents.push(i);const a=ae(t,o),c={...t.screenValidity};a&&(c[a]=X({...t},a));const u={...t,components:{...t.components}};ge(u);const l=ye(u);return e({components:{...t.components},conditionsByDependency:r,screenValidity:c,calculationResults:l}),n.addedComponents},removeRepeaterIteration:(o,t)=>{var g;const n=s(),r=n.components[o];if(!r||r.type!=="repeater"||!r.addedComponents)return;const i=((g=r.properties)==null?void 0:g.minIterations)??1;if(r.addedComponents.length<=i)return;const a=r.addedComponents[t],c=new Set(a.map(h=>h.uuid));r.addedComponents.splice(t,1);const u={...n.conditionsByDependency},l={...n.validationErrors};for(const h of c)delete l[h],delete u[h];for(const h of Object.keys(u)){const v=u[h],C=v.filter(x=>!c.has(x.target));C.length===0?delete u[h]:C.length!==v.length&&(u[h]=C)}for(let h=t;h<r.addedComponents.length;h++)r.addedComponents[h].forEach((v,C)=>{const x=v.uuid,b=[o,h,C].join(":");if(x!==b){v.uuid=b,x in l&&(l[b]=l[x],delete l[x]),x in u&&(u[b]=u[x],delete u[x]);for(const R of Object.values(u))for(const _ of R)_.target===x&&(_.target=b)}});const d=ae(n,o),f={...n.screenValidity};d&&(f[d]=X({...n},d));const m={...n,components:{...n.components}};ge(m);const y=ye(m);e({components:{...n.components},conditionsByDependency:u,validationErrors:l,screenValidity:f,calculationResults:y})}}),J=(e,s)=>Pe(e.components,s),W=(e,s,o,t)=>{const n=new Set;for(const i of o.when.rules)n.add(i.source);const r={target:s,type:t,config:o};for(const i of n)e[i]||(e[i]=[]),e[i].push(r)},sn=(e,s)=>{var o,t;return s.includes(":")?(o=J(e,s))==null?void 0:o.value:(t=e.components[s])==null?void 0:t.value},Q=(e,s)=>U.evaluateConditionConfig(s,(o,t)=>(t==null?void 0:t.sourceType)==="context"?e.externalContext[t.source]:sn(e,o)),rn=(e,s,o)=>{const t=s(),n=t.conditionsByDependency[o];if(!n||n.length===0)return null;let r=!1;const i={...t.conditionResults};for(const a of n){const c=Q(t,a.config);i[a.target]!==c&&(i[a.target]=c,r=!0)}return r?i:null},cn=e=>{const s={},o=new Set;for(const t of Object.values(e.conditionsByDependency))for(const n of t)o.has(n.target)||(o.add(n.target),s[n.target]=Q(e,n.config));return s},ve=e=>{if(!e||ue(e.type))return null;const s="label"in e.properties?e.properties.label:"",o={uuid:e.uuid,type:e.type,value:e.value};return s&&(o.label=s),o},Ve=e=>{if(e.conditions&&"when"in e.conditions)return e.conditions},an=e=>{const s={uuid:e.flowUUID,metadata:e.metadata,screens:[]},o=t=>{const n=e.screens[t];if(!n)return!1;const r=n.conditions&&"when"in n.conditions?n.conditions:void 0;return U.isHiddenByCondition(r,e.conditionResults[t])};return s.screens=e.screenOrder.filter(t=>!o(t)).map(t=>{const n=e.screens[t],r={uuid:t,components:n.components.map(i=>{const a=e.components[i.uuid];if(!a)return null;const c=Ve(a);if(U.isHiddenByCondition(c,e.conditionResults[i.uuid]))return null;if((a.type==="group"||a.type==="repeater")&&a.addedComponents){const u=ve(a);return u?{...u,components:a.addedComponents.map(l=>l.filter(d=>{const f=Ve(d);return!U.isHiddenByCondition(f,e.conditionResults[d.uuid])}).map(d=>ve(d)).filter(d=>d!==null))}:null}return ve(a)}).filter(i=>i!==null)};return n.label&&(r.label=n.label),r}),s},pe=w.createContext(null);function P(e){const s=w.useContext(pe);if(!s)throw new Error("useFBREStore must be used within an FBRE provider");return G.useStore(s,e)}const be=()=>{const e=w.useContext(pe);if(!e)throw new Error("useFBREStoreApi must be used within an FBRE provider");return e},re=e=>!e||Object.keys(e).length===0?null:"when"in e?e:null,ln=[],un=()=>G.createStore((e,s)=>({flowUUID:"",metadata:{},config:{},externalContext:{},screenOrder:[],screens:{},screenValidity:{},components:{},groupComponentMap:{},templateComponentMap:{},conditionsByDependency:{},conditionResults:{},validationErrors:{},validationsByDependency:{},calculations:[],calculationResults:{},calculationsByDependency:{},computedByDependency:{},loadFlow:(o,t,n)=>{var _;const r={},i=[],a={},c={},u={},l={},d={},f={},m={};o.screens.forEach(E=>{const O=re(E.conditions),F=O?{...E,conditions:O}:{...E};r[E.uuid]=F,i.push(E.uuid),O&&W(l,E.uuid,O,"screen"),E.components.forEach(S=>{var k;const D=re(S.conditions),B=z(S);if(D&&(B.conditions=D),a[S.uuid]=B,D&&W(l,S.uuid,D,"component"),(k=B.properties)!=null&&k.validation&&oe(d,S.uuid,B.properties.validation),(S.type==="group"||S.type==="repeater")&&S.components){const $=a[S.uuid];$.addedComponents||($.addedComponents=[]);const q=S.properties??{},j=S.type==="repeater"?q.initialData:void 0,N=S.type==="repeater"?q.minIterations:void 0,M=j?j.length:S.type==="repeater"&&N&&N>1?N:1;for(let V=0;V<M;V++){const K=S.components.map((Y,fe)=>{var te;const A=z(Y);A.uuid=[S.uuid,$.addedComponents.length,fe].join(":"),j&&j[V]&&Y.uuid in j[V]&&(A.value=j[V][Y.uuid]),S.type==="group"&&(c[A.uuid]=Y.uuid),V===0&&(u[Y.uuid]=A.uuid);const ee=re(A.conditions);ee&&(A.conditions=ee,W(l,A.uuid,ee,"component")),(te=A.properties)!=null&&te.validation&&oe(d,A.uuid,A.properties.validation);const ne=T(A);return A.valid=ne.length===0,ne.length>0&&(f[A.uuid]=ne),A});$.addedComponents.push(K)}}})}),t&&t.screens.forEach(E=>{const O=i.indexOf(E.uuid);O<0||E.components.forEach(F=>{const S=a[F.uuid];if(S)if((S.type==="group"||S.type==="repeater")&&F.components&&S.addedComponents){if(F.components.length>1){const D=S.addedComponents.length,B=F.components.length-D,H=o.screens[O].components.find(k=>k.uuid===S.uuid);for(let k=0;k<B;k++)if(H!=null&&H.components){const $=H.components.map((q,j)=>{var K;const N=z(q);N.uuid=[S.uuid,S.addedComponents.length,j].join(":"),S.type==="group"&&(c[N.uuid]=q.uuid),u[q.uuid]||(u[q.uuid]=N.uuid);const M=re(N.conditions);M&&(N.conditions=M,W(l,N.uuid,M,"component")),(K=N.properties)!=null&&K.validation&&oe(d,N.uuid,N.properties.validation);const V=T(N);return N.valid=V.length===0,V.length>0&&(f[N.uuid]=V),N});S.addedComponents.push($)}}F.components.forEach(D=>{D.forEach(B=>{for(const H of S.addedComponents){const k=H.find($=>$.uuid===B.uuid);if(k){k.value=B.value;const $=T(k);k.valid=$.length===0,f[k.uuid]=$;break}}})})}else{S.value=F.value;const D=T(S);S.valid=D.length===0,f[S.uuid]=D}})});for(const E of Object.keys(a)){const O=a[E];if(!(O.type==="group"||O.type==="repeater"||!((_=O.properties)!=null&&_.validation))&&!(E in f)){const F=T(O);O.valid=F.length===0,F.length>0&&(f[E]=F)}}const y={...s(),externalContext:n??{},screens:r,screenOrder:i,components:a,groupComponentMap:c,templateComponentMap:u,conditionsByDependency:l,conditionResults:{},validationErrors:f,validationsByDependency:d},g=cn(y);y.conditionResults=g,i.forEach(E=>{m[E]=X(y,E)});const h=en(a),v={...y,computedByDependency:h,calculationResults:{},screenValidity:m};ge(v);const C=o.calculations??[],x=Ze(C),b={...v,calculations:C},R=ye(b);e({flowUUID:o.uuid,metadata:o.metadata,config:o.config??{},externalContext:n??{},screens:r,screenOrder:i,components:a,groupComponentMap:c,templateComponentMap:u,conditionsByDependency:l,conditionResults:g,screenValidity:m,validationErrors:f,validationsByDependency:d,calculations:C,calculationResults:R,calculationsByDependency:x,computedByDependency:h})},updateContext:o=>{const t=s(),n=t.externalContext,r=[];for(const u of Object.keys(o))n[u]!==o[u]&&r.push(u);for(const u of Object.keys(n))!(u in o)&&!r.includes(u)&&r.push(u);if(r.length===0)return;const i={...t.conditionResults};let a=!1;const c=new Set;for(const u of r){const l=t.conditionsByDependency[u];if(!(!l||l.length===0))for(const d of l){if(c.has(d.target))continue;c.add(d.target);const f={...t,externalContext:o},m=Q(f,d.config);i[d.target]!==m&&(i[d.target]=m,a=!0)}}if(a){const u={...t,conditionResults:i},l={};for(const d of t.screenOrder)l[d]=X(u,d);e({externalContext:o,conditionResults:i,screenValidity:l})}else e({externalContext:o})},...on(e,s),getFlowData:()=>an(s()),getScreenByIndex:o=>{const t=s();return o<0||o>=t.screenOrder.length?null:t.screens[t.screenOrder[o]]},getScreenValidity:o=>{const t=s();return o<0||o>=t.screenOrder.length?!0:t.screenValidity[t.screenOrder[o]]??!0},getValidationErrors:o=>s().validationErrors[o]??ln,evaluateFlowValidation:()=>{const o=s(),t={};let n=!0;return o.screenOrder.forEach(r=>{const i=X(o,r);t[r]=i,i||(n=!1)}),e({screenValidity:t}),n},getMaxScreenCount:()=>s().screenOrder.length-1,getCalculationResult:o=>s().calculationResults[o]??null})),dn=({uuid:e})=>{var a;const s=P(c=>c.components[e]),o=P(c=>c.conditionResults[e]);if(!s)return null;const t=s.conditions&&"when"in s.conditions?s.conditions:void 0;if(U.isHiddenByCondition(t,o))return null;const n=We(s.type);if(!n)return console.warn(`FBRE: No renderer for component type "${s.type}"`),null;const r=(a=s.properties)==null?void 0:a.width,i=r&&r!=="full"?`fbre-component fbre-width-${r}`:"fbre-component";return p.jsx("div",{className:i,"data-uuid":e,children:p.jsx(n,{uuid:e})})},Ce=({screenIndex:e})=>{const s=P(o=>{const t=o.screenOrder[e];return t?o.screens[t]:null});return s?p.jsx("div",{className:"fbre-screen",children:s.components.map(o=>p.jsx(dn,{uuid:o.uuid},o.uuid))}):null},Oe=({size:e=14})=>p.jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:p.jsx("polyline",{points:"4,12 9.5,17.5 20,7"})}),pn=({size:e=12})=>p.jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"currentColor",children:p.jsx("path",{d:"M7 10l5 5 5-5z"})}),fn=({size:e=16})=>p.jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"currentColor",children:p.jsx("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})}),mn=({size:e=16})=>p.jsx("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"currentColor",children:p.jsx("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})}),Me=({position:e,screenIndex:s,maxScreenIndex:o,allowInvalidTransition:t,screenValidity:n,summaryEnabled:r,summaryActive:i,atMaxScreen:a,nextButtonLabel:c,backButtonLabel:u,completionLoading:l,nextScreen:d,prevScreen:f,onFlowComplete:m})=>{const y=l??!1;if(e==="back"){const x=s===0&&!i||y;return p.jsxs("button",{type:"button",className:"fbre-btn fbre-btn--secondary",disabled:x,onClick:f,children:[p.jsx(fn,{}),u||"Back"]})}const g=r?a&&i:a,h=r?a?i?"Done":"Review":"Next":a?"Done":"Next";if(o===0){const x=r?i?"Complete":"Review":"Complete",b=y||!n;return p.jsxs("button",{type:"button",className:"fbre-btn fbre-btn--primary",disabled:b,onClick:()=>{r&&!i?d():m()},children:[c||x,y?p.jsx("span",{className:"fbre-btn__spinner"}):p.jsx(Oe,{size:16})]})}const v=y||!t&&!n||h==="Done"&&!n,C=()=>{g?m():d()};return p.jsxs("button",{type:"button",className:"fbre-btn fbre-btn--primary",disabled:v,onClick:C,children:[c||h,y?p.jsx("span",{className:"fbre-btn__spinner"}):g?p.jsx(Oe,{size:16}):p.jsx(mn,{})]})},vn=({current:e,total:s})=>{if(s<=1)return null;const o=(e+1)/s*100;return s<=6?p.jsx("div",{className:"fbre-stepper fbre-stepper--dots",children:Array.from({length:s},(t,n)=>p.jsx("div",{className:`fbre-stepper__dot${n===e?" active":n<e?" completed":""}`},n))}):p.jsx("div",{className:"fbre-stepper fbre-stepper--bar",children:p.jsx("div",{className:"fbre-stepper__fill",style:{width:`${o}%`}})})},hn=({current:e,total:s})=>s<=1?null:p.jsxs("div",{className:"fbre-stepper-text",children:["Step ",e+1," of ",s]}),yn=e=>{const s=e.controlsLayout==="stacked",o=e.showStepper!==!1&&(e.stepperStyle??"default")==="default";return p.jsxs("div",{className:s?"fbre-controls fbre-controls--stacked":"fbre-controls",children:[e.screenIndex>0||e.summaryActive?p.jsx(Me,{position:"back",...e}):p.jsx("div",{}),o&&e.maxScreenIndex>0&&p.jsx(vn,{current:e.screenIndex,total:e.maxScreenIndex+1}),p.jsx(Me,{position:"next",...e})]})},$e=({component:e})=>{const{uuid:s,label:o,type:t,value:n,components:r}=e,i=()=>{if(n!=null)switch(t){case"fileUpload":return n.name;case"inputText":case"inputTextArea":case"inputNumber":case"dropDown":case"radio":case"rating":case"slider":return n.toString();case"computed":return typeof n=="number"?n.toString():"—";case"toggleSwitch":return n?"Yes":"No";case"checkbox":case"dropDownMulti":return n.length===0?"No options selected":n.join(", ")}return"No response given"};if(t==="signature"&&n){const u=typeof n=="string"&&n.startsWith("data:");return p.jsxs("div",{className:"fbre-summary__item",children:[p.jsx("div",{className:"fbre-summary__item-label",children:o}),p.jsx("div",{className:"fbre-summary__item-value",children:u?p.jsx("img",{src:n,alt:"Signature",style:{maxWidth:"100%",maxHeight:80}}):p.jsx("span",{style:{fontFamily:'"Brush Script MT", "Segoe Script", "Dancing Script", cursive',fontSize:24},children:n})})]})}const a=()=>r?r.map((u,l)=>p.jsx("div",{children:u.map(d=>p.jsx($e,{component:d},d.uuid))},`${s}-${l}`)):null,c=n==null||typeof n=="string"&&n.length===0||Array.isArray(n)&&n.length===0;return p.jsxs("div",{className:`fbre-summary__item${t==="group"||t==="repeater"?" fbre-summary__item--group":""}`,children:[p.jsx("div",{className:"fbre-summary__item-label",children:o}),t!=="group"&&t!=="repeater"&&p.jsx("div",{className:`fbre-summary__item-value${c?" fbre-summary__item-value--empty":""}`,children:i()}),(t==="group"||t==="repeater")&&a()]})},gn=/\$\{([^}]+)\}/g,Cn=(e,s)=>e.replace(gn,(o,t)=>{const n=s.resolveCalculation(t);if(n!==null)return n;const r=s.resolveComponentValue(t);return r!==null?r:""});function bn(){const e=P(n=>n.components),s=P(n=>n.templateComponentMap),o=P(n=>n.calculations),t=P(n=>n.calculationResults);return w.useMemo(()=>{const n=new Map(o.map(i=>[i.uuid,i])),r=i=>{var d,f;const a=e[i];if(a)return a;const c=s[i];if(!c)return;const u=c.split(":"),l=e[u[0]];return(f=(d=l==null?void 0:l.addedComponents)==null?void 0:d[parseInt(u[1])])==null?void 0:f[parseInt(u[2])]};return{resolveComponentValue:i=>{const a=r(i);if(!a)return null;const c=a.value;return c==null||c===""?null:Array.isArray(c)?c.join(", "):String(c)},resolveCalculation:i=>{const a=n.get(i);if(!a)return null;const c=t[i]??null;return U.formatCalculationResult(c,a.format,a.decimalPlaces,a.currencySymbol)}}},[e,s,o,t])}const xn=({screen:e,showToggle:s})=>{const o=bn(),[t,n]=w.useState(!0);return p.jsxs("div",{children:[p.jsxs("div",{className:"fbre-summary__screen-header",onClick:()=>s&&n(!t),children:[e.label&&p.jsx("span",{className:"fbre-summary__screen-label",children:Cn(e.label,o)}),s&&p.jsx("span",{className:`fbre-summary__screen-toggle${t?"":" collapsed"}`,children:p.jsx(pn,{size:20})})]}),p.jsx("div",{className:`fbre-summary__screen-body${t?"":" collapsed"}`,children:e.components.map(r=>p.jsx($e,{component:r},r.uuid))})]})},_e=()=>{const e=be(),s=P(n=>n.components),o=w.useMemo(()=>e.getState().getFlowData(),[e,s]),t=o.screens.length;return p.jsxs("div",{className:"fbre-summary",children:[p.jsx("h2",{className:"fbre-summary__title",children:"Review"}),p.jsx("div",{className:"fbre-summary__body",children:o.screens.map(n=>p.jsx(xn,{screen:n,showToggle:t>1},n.uuid))})]})},He=(e,s,o)=>s?!U.isHiddenByCondition(s,o[e]):!0,Fe=(e,s)=>{const o=e.screenOrder.length-1;let t=s+1;for(;t<=o;){const n=e.screenOrder[t],r=e.screens[n],i=r!=null&&r.conditions&&"when"in r.conditions?r.conditions:void 0;if(He(n,i,e.conditionResults))return t;t++}return null},Sn=(e,s)=>{let o=s-1;for(;o>=0;){const t=e.screenOrder[o],n=e.screens[t],r=n!=null&&n.conditions&&"when"in n.conditions?n.conditions:void 0;if(He(t,r,e.conditionResults))return o;o--}return 0},le=new Map,wn=(e,s)=>{le.has(e)||le.set(e,new Set),le.get(e).add(s)},jn=(e,s)=>{var o;(o=le.get(e))==null||o.delete(s)},qe=w.createContext(null);function Rn(){return w.useContext(qe)}class se extends Error{constructor(s,o,t,n){super(s),this.name="ApiError",this.status=o,this.code=t,this.validationErrors=n}}class Ge extends se{constructor(s,o){super(`Request timed out after ${o}ms: ${s}`,0,"TIMEOUT"),this.name="TimeoutError"}}const En=new Set([502,503,504]),ie=2,Nn=[500,1500];function In(e){return new Promise(s=>setTimeout(s,e))}async function Z(e,s,o={}){const n=`${e.apiEndpoint||""}${s}`,r=e.timeout??3e4,i={...o.body?{"Content-Type":"application/json"}:{},...o.headers};e.apiKey&&(i.Authorization=`Bearer ${e.apiKey}`);let a;for(let c=0;c<=ie;c++){c>0&&await In(Nn[c-1]);try{const u=new AbortController,l=setTimeout(()=>u.abort(),r);let d;try{d=await fetch(n,{...o,headers:i,signal:u.signal})}finally{clearTimeout(l)}if(!d.ok){const f=await d.json().catch(()=>({})),m=new se(f.error||`HTTP ${d.status}`,d.status,f.code,f.validationErrors);if(c<ie&&En.has(d.status)){a=m;continue}throw m}return d.json()}catch(u){if(u instanceof se)throw u;if(u instanceof DOMException&&u.name==="AbortError"){const l=new Ge(n,r);if(c<ie){a=l;continue}throw l}if(u instanceof TypeError&&c<ie){a=u;continue}throw u}}throw a}async function Dn(e,s){return Z(e,`/api/v1/public/flows/${s}`)}async function Bn(e,s,o){const t={flowId:s};return o&&Object.keys(o).length>0&&(t.context=o),Z(e,"/api/v1/public/sessions",{method:"POST",body:JSON.stringify(t)})}async function kn(e,s,o){return Z(e,`/api/v1/public/sessions/${s}/next`,{method:"POST",body:JSON.stringify({data:o})})}async function Vn(e,s,o){return Z(e,`/api/v1/public/sessions/${s}/prev`,{method:"POST",body:JSON.stringify({data:o})})}async function On(e,s,o){return Z(e,`/api/v1/public/sessions/${s}/complete`,{method:"POST",body:JSON.stringify({data:o})})}async function Mn(e,s){return Z(e,`/api/v1/public/sessions/${s}`)}const _n=({screenIndex:e,onFlowComplete:s,onScreenChange:o})=>{var te,xe,Se,we,je,Re,Ee,Ne,Ie,De,Be;const t=P(I=>I.config),n=P(I=>I.screenOrder.length),r=P(I=>Object.keys(I.components).length>0),i=be(),a=Math.max(0,Math.min(e,n-1)),[c,u]=w.useState(a),[l,d]=w.useState(!!(t!=null&&t.summary&&e>=n)),f=((te=t==null?void 0:t.navigation)==null?void 0:te.transition)??"none",m=f!=="none",[y,g]=w.useState(null),[h,v]=w.useState(!1),[C,x]=w.useState("forward"),[b,R]=w.useState(!1),_=w.useRef(null);w.useEffect(()=>{const I=Math.max(0,Math.min(e,n-1));u(I)},[e]);const E=P(I=>I.screenOrder[c]),O=P(I=>E?I.screenValidity[E]??!0:!0),F=P(I=>{var L;return E?(L=I.screens[E])==null?void 0:L.nextButtonLabel:void 0}),S=P(I=>{var L;return E?(L=I.screens[E])==null?void 0:L.backButtonLabel:void 0}),D=w.useCallback(I=>{o&&o(I,i.getState().getFlowData())},[o,i]),B=w.useCallback(I=>{g(c),v(l),x(I),R(!0),_.current&&(_.current.scrollTop=0)},[c,l]),H=w.useCallback(()=>{R(!1),g(null)},[]),k=w.useCallback(()=>{if(!b)if(l)m&&B("back"),d(!1),D(c);else{const I=i.getState(),L=Sn(I,c);L!==c&&(m&&B("back"),u(L),D(L))}},[b,l,c,m,B,D,i]),$=w.useCallback(()=>{if(b)return;const I=i.getState(),L=Fe(I,c);L!==null?(m&&B("forward"),u(L),D(L)):t!=null&&t.summary&&(m&&B("forward"),d(!0),D(c+1))},[b,c,t,m,B,D,i]),[q,j]=w.useState(!1),[N,M]=w.useState(null),V=w.useCallback(()=>{M(null);const I=s(i.getState().getFlowData());I&&typeof I.then=="function"&&(j(!0),I.then(()=>{j(!1)}).catch(L=>{j(!1),M(L instanceof Error?L.message:String(L))}))},[s,i]),K=P(I=>Fe(I,c)===null),Y=((xe=t==null?void 0:t.theme)==null?void 0:xe.darkMode)??!1,fe=((Se=t==null?void 0:t.controls)==null?void 0:Se.showStepper)!==!1&&((we=t==null?void 0:t.controls)==null?void 0:we.stepperStyle)==="text",A={};(je=t==null?void 0:t.theme)!=null&&je.color&&(A["--fbre-theme-color"]=t.theme.color);const ee=()=>h?p.jsx(_e,{}):y!==null?p.jsx(Ce,{screenIndex:y}):null,ne=b?"fbre-screen-wrapper fbre-screen-wrapper--transitioning":"fbre-screen-wrapper";return p.jsxs("div",{className:"fbre-container","data-style":((Re=t==null?void 0:t.theme)==null?void 0:Re.style)??"clean","data-mode":Y?"dark":"light","data-transition":m?f:void 0,style:Object.keys(A).length>0?A:void 0,children:[fe&&p.jsx(hn,{current:c,total:n}),p.jsxs("div",{className:ne,ref:_,children:[b&&p.jsx("div",{className:"fbre-screen--exiting","data-direction":C,onAnimationEnd:H,children:ee()}),p.jsxs("div",{className:b?"fbre-screen--entering":void 0,"data-direction":b?C:void 0,children:[!l&&p.jsx(Ce,{screenIndex:c}),l&&p.jsx(_e,{})]})]}),N&&p.jsx("div",{className:"fbre-completion-error",children:N}),((Ee=t==null?void 0:t.controls)==null?void 0:Ee.show)!==!1&&r&&p.jsx(yn,{screenIndex:c,maxScreenIndex:n-1,allowInvalidTransition:(Ne=t==null?void 0:t.navigation)==null?void 0:Ne.allowInvalidTransition,screenValidity:O,summaryEnabled:(t==null?void 0:t.summary)??!1,summaryActive:l,atMaxScreen:K,nextButtonLabel:F,backButtonLabel:S,completionLoading:q,showStepper:(Ie=t==null?void 0:t.controls)==null?void 0:Ie.showStepper,stepperStyle:(De=t==null?void 0:t.controls)==null?void 0:De.stepperStyle,controlsLayout:(Be=t==null?void 0:t.controls)==null?void 0:Be.layout,nextScreen:$,prevScreen:k,onFlowComplete:V})]})},Fn=[],Tn=()=>G.createStore((e,s)=>({flowUUID:"",metadata:{},config:{},externalContext:{},screenOrder:[],screens:{},screenValidity:{},components:{},groupComponentMap:{},templateComponentMap:{},conditionsByDependency:{},conditionResults:{},validationErrors:{},validationsByDependency:{},calculations:[],calculationResults:{},calculationsByDependency:{},computedByDependency:{},sessionId:"",navigation:{canGoBack:!1,canGoForward:!1,screenNumber:1,totalScreens:1,progress:0,isLastScreen:!0},loading:!1,error:"",clearError:()=>{e({error:""})},loadFlow:()=>{},updateContext:o=>{e({externalContext:o})},updateComponentValue:(o,t)=>{var f,m;const n=s();if(o.includes(":")){const y=o.split(":"),g=y[0],h=parseInt(y[1]),v=parseInt(y[2]),C=n.components[g];if(!((m=(f=C==null?void 0:C.addedComponents)==null?void 0:f[h])!=null&&m[v]))return;C.addedComponents[h][v]={...C.addedComponents[h][v],value:t};const x=n.groupComponentMap[o]??o,b=n.conditionsByDependency[x];let R=n.conditionResults;if(b&&b.length>0){R={...n.conditionResults};for(const S of b)R[S.target]=Q({...n},S.config)}const _={components:n.components,groupComponentMap:n.groupComponentMap},E=T(C.addedComponents[h][v],_);C.addedComponents[h][v].valid=E.length===0;const O={...n.validationErrors,[o]:E},F=n.validationsByDependency[o];if(F)for(const S of F){const D=Te(n,S.target);if(D){const B=T(D,_);D.valid=B.length===0,O[S.target]=B}}e({components:{...n.components},conditionResults:R,validationErrors:O});return}const r=n.components[o];if(!r)return;if(r.type==="group"||r.type==="repeater"){e({components:{...n.components}});return}if(t===r.value)return;r.value=t;const i=n.conditionsByDependency[o];let a=n.conditionResults;if(i&&i.length>0){a={...n.conditionResults};for(const y of i)a[y.target]=Q({...n},y.config)}const c={components:n.components,groupComponentMap:n.groupComponentMap},u=T(r,c);r.valid=u.length===0;const l={...n.validationErrors,[o]:u},d=n.validationsByDependency[o];if(d)for(const y of d){const g=Te(n,y.target);if(g){const h=T(g,c);g.valid=h.length===0,l[y.target]=h}}e({components:{...n.components},conditionResults:a,validationErrors:l})},addGroupIteration:o=>{const t=s(),n=t.components[o];if(!n||n.type!=="group"||!n.components)return;n.addedComponents||(n.addedComponents=[]);const r=n.components.map((i,a)=>{const c=z(i);c.uuid=[o,n.addedComponents.length,a].join(":"),t.groupComponentMap[c.uuid]=i.uuid;const u=T(c);return c.valid=u.length===0,c});return n.addedComponents.push(r),e({components:{...t.components},groupComponentMap:{...t.groupComponentMap}}),n.addedComponents},addRepeaterIteration:o=>{const t=s(),n=t.components[o];if(!n||n.type!=="repeater"||!n.components)return;n.addedComponents||(n.addedComponents=[]);const r=n.components.map((i,a)=>{const c=z(i);c.uuid=[o,n.addedComponents.length,a].join(":");const u=T(c);return c.valid=u.length===0,c});return n.addedComponents.push(r),e({components:{...t.components}}),n.addedComponents},removeRepeaterIteration:(o,t)=>{const n=s(),r=n.components[o];if(!(!r||r.type!=="repeater"||!r.addedComponents||r.addedComponents.length<=1)){r.addedComponents.splice(t,1);for(let i=t;i<r.addedComponents.length;i++)r.addedComponents[i].forEach((a,c)=>{a.uuid=[o,i,c].join(":")});e({components:{...n.components}})}},getFlowData:()=>({uuid:"",metadata:{},screens:[]}),getScreenByIndex:o=>{const t=s();if(o!==0)return null;const n=t.screenOrder[0];return n?t.screens[n]:null},getScreenValidity:o=>{const t=s();if(o!==0)return!0;const n=t.screenOrder[0];return n?t.screenValidity[n]??!0:!0},getValidationErrors:o=>s().validationErrors[o]??Fn,evaluateFlowValidation:()=>{const o=s(),t=o.screenOrder[0];if(!t)return!0;const n=o.screens[t];if(!n)return!0;let r=!0;const i={components:o.components,groupComponentMap:o.groupComponentMap},a={...o.validationErrors};for(const u of n.components){const l=o.components[u.uuid];if(!l)continue;if((l.type==="group"||l.type==="repeater")&&l.addedComponents){for(const m of l.addedComponents)for(const y of m){const g=y.conditions&&"when"in y.conditions?y.conditions:void 0;if(g){const v=o.conditionResults[y.uuid]??!1;if(g.action==="show"&&!v||g.action==="hide"&&v)continue}const h=T(y,i);y.valid=h.length===0,a[y.uuid]=h,h.length>0&&(r=!1)}continue}const d=l.conditions&&"when"in l.conditions?l.conditions:void 0;if(d){const m=o.conditionResults[l.uuid]??!1;if(d.action==="show"&&!m||d.action==="hide"&&m)continue}const f=T(l,i);l.valid=f.length===0,a[l.uuid]=f,f.length>0&&(r=!1)}const c={...o.screenValidity,[t]:r};return e({components:{...o.components},validationErrors:a,screenValidity:c}),r},getMaxScreenCount:()=>0,getCalculationResult:o=>s().calculationResults[o]??null})),ce=(e,s)=>{var y,g;const o={},t={},n={},r={},i={},a={},c=s.screen.uuid;for(const h of s.screen.components){const v=z(h);if(o[v.uuid]=v,(v.type==="group"||v.type==="repeater")&&h.components){v.addedComponents||(v.addedComponents=[]);const C=h.components.map((x,b)=>{var _;const R=z(x);if(R.uuid=[v.uuid,0,b].join(":"),v.type==="group"&&(t[R.uuid]=x.uuid),n[x.uuid]=R.uuid,(_=R.properties)!=null&&_.validation){const E=R.properties.validation;E.rules&&E.rules.length>0&&oe(i,R.uuid,E)}return R});v.addedComponents.push(C)}if((y=v.properties)!=null&&y.validation){const C=v.properties.validation;C.rules&&C.rules.length>0&&oe(i,v.uuid,C)}}for(const{targetUUID:h,config:v}of s.conditions)W(r,h,v,h===c?"screen":"component");if(s.previousData)for(const h of s.previousData){const v=o[h.uuid];v&&(v.value=h.value)}const u={components:o};for(const h of Object.keys(o)){const v=o[h];if(v.type==="group"||v.type==="repeater"){if(v.addedComponents)for(const x of v.addedComponents)for(const b of x){const R=T(b,u);b.valid=R.length===0,R.length>0&&(a[b.uuid]=R)}continue}if(!((g=v.properties)!=null&&g.validation))continue;const C=T(v,u);v.valid=C.length===0,C.length>0&&(a[h]=C)}const l={},d={components:o},f=new Set;for(const h of Object.values(r))for(const v of h)f.has(v.target)||(f.add(v.target),l[v.target]=Q(d,v.config));let m=!0;for(const h of s.screen.components){const v=o[h.uuid];if(v)if((v.type==="group"||v.type==="repeater")&&v.addedComponents)for(const C of v.addedComponents){for(const x of C)if(!x.valid){m=!1;break}if(!m)break}else v.valid===!1&&(m=!1)}e.setState({screenOrder:[c],screens:{[c]:{uuid:c,label:s.screen.label,components:s.screen.components,nextButtonLabel:s.screen.nextButtonLabel,backButtonLabel:s.screen.backButtonLabel}},screenValidity:{[c]:m},components:o,groupComponentMap:t,templateComponentMap:n,conditionsByDependency:r,conditionResults:l,validationErrors:a,validationsByDependency:i,calculations:[],calculationResults:{},calculationsByDependency:{},computedByDependency:{},sessionId:s.sessionId,navigation:s.navigation,loading:!1,error:"",externalContext:s.context??{},config:s.config??{}})},he=e=>{var r;const s=e.getState(),o=s.screenOrder[0];if(!o)return[];const t=s.screens[o];if(!t)return[];const n=[];for(const i of t.components){const a=s.components[i.uuid];if(!a||ue(a.type))continue;const c={uuid:a.uuid,type:a.type,value:a.value};(r=a.properties)!=null&&r.label&&(c.label=a.properties.label),(a.type==="group"||a.type==="repeater")&&a.addedComponents&&(c.components=a.addedComponents.map(u=>u.filter(l=>!ue(l.type)).map(l=>({uuid:l.uuid,type:l.type,value:l.value})))),n.push(c)}return n},Te=(e,s)=>Pe(e.components,s),Un=6e4,An=({sessionEndpoint:e,flowId:s,apiKey:o,theme:t,context:n,onFlowComplete:r,onScreenChange:i})=>{const a=w.useRef(null);a.current||(a.current=Tn());const c=a.current,u=G.useStore(c,j=>j.loading),l=G.useStore(c,j=>j.error),d=G.useStore(c,j=>j.navigation),f=G.useStore(c,j=>j.config),m=G.useStore(c,j=>j.screenOrder),y=G.useStore(c,j=>j.screens),[g,h]=w.useState(""),v=w.useRef(null),C=w.useRef(Date.now()),x=w.useMemo(()=>({apiEndpoint:e,apiKey:o}),[e,o]),b=w.useCallback(j=>{h(j),v.current&&clearTimeout(v.current),v.current=setTimeout(()=>h(""),8e3)},[]),R=w.useCallback(()=>{h(""),v.current&&(clearTimeout(v.current),v.current=null)},[]),_=w.useCallback(async()=>{c.setState({loading:!0,error:""});try{const j=await Bn(x,s,n);ce(c,j)}catch(j){c.setState({loading:!1,error:j.message})}},[s,e,o,n]);w.useEffect(()=>{_()},[_]),w.useEffect(()=>{const j=async()=>{if(document.visibilityState!=="visible")return;const N=c.getState();if(!(!N.sessionId||Date.now()-C.current<Un))try{const V=await Mn(x,N.sessionId);ce(c,V)}catch(V){V instanceof se&&V.status===404&&c.setState({loading:!1,error:"Session expired. Please start over.",screenOrder:[],screens:{}})}};return document.addEventListener("visibilitychange",j),()=>document.removeEventListener("visibilitychange",j)},[e,o]);const E=w.useCallback(async()=>{const j=c.getState();if(!(j.loading||!j.evaluateFlowValidation())){c.setState({loading:!0}),c.getState().clearError(),R();try{const M=he(c),V=await kn(x,j.sessionId,M);ce(c,V),C.current=Date.now(),i==null||i(V.navigation.screenNumber)}catch(M){c.setState({loading:!1}),b(M.message)}}},[x,c,i,b,R]),O=w.useCallback(async()=>{const j=c.getState();if(!j.loading){c.setState({loading:!0}),c.getState().clearError(),R();try{const N=he(c),M=await Vn(x,j.sessionId,N);ce(c,M),C.current=Date.now(),i==null||i(M.navigation.screenNumber)}catch(N){c.setState({loading:!1}),b(N.message)}}},[x,c,i,b,R]),F=w.useCallback(async()=>{const j=c.getState();if(!(j.loading||!j.evaluateFlowValidation())){c.setState({loading:!0}),c.getState().clearError(),R();try{const M=he(c),V=await On(x,j.sessionId,M);C.current=Date.now(),r(V)}catch(M){c.setState({loading:!1}),b(M.message)}}},[x,c,r,b,R]),S={...f==null?void 0:f.theme,...t},D=S.darkMode??!1,B={};S.color&&(B["--fbre-theme-color"]=S.color);const H=m[0],k=H?y[H]:void 0,$=k==null?void 0:k.nextButtonLabel,q=k==null?void 0:k.backButtonLabel;return u&&m.length===0?p.jsx("div",{className:"fbre-container",children:p.jsxs("div",{className:"fbre-remote-loading",children:[p.jsx("div",{className:"fbre-spinner"}),p.jsx("p",{children:"Loading form..."})]})}):l&&m.length===0?p.jsx("div",{className:"fbre-container",children:p.jsxs("div",{className:"fbre-remote-error",children:[p.jsx("p",{children:"Failed to load form"}),p.jsx("p",{className:"fbre-remote-error__detail",children:l}),p.jsx("button",{type:"button",className:"fbre-btn fbre-btn--next",onClick:_,style:{marginTop:12},children:"Retry"})]})}):m.length===0?null:p.jsx(pe.Provider,{value:c,children:p.jsxs("div",{className:"fbre-container","data-style":S.style??"clean","data-mode":D?"dark":"light",style:Object.keys(B).length>0?B:void 0,children:[p.jsx("div",{className:"fbre-screen-wrapper",children:p.jsx(Ce,{screenIndex:0})}),p.jsx(Ln,{navigation:d,loading:u,onPrev:O,onNext:E,onComplete:F,nextButtonLabel:$,backButtonLabel:q}),p.jsxs("div",{className:`fbre-toast${g?" visible":""}`,children:[p.jsx("span",{children:g}),p.jsx("button",{type:"button",className:"fbre-toast__close",onClick:R,"aria-label":"Dismiss",children:"×"})]})]})})},Ln=({navigation:e,loading:s,onPrev:o,onNext:t,onComplete:n,nextButtonLabel:r,backButtonLabel:i})=>p.jsxs("div",{className:"fbre-controls",children:[p.jsx("div",{className:"fbre-controls__left",children:e.canGoBack&&p.jsx("button",{type:"button",className:"fbre-btn fbre-btn--back",onClick:o,disabled:s,children:i||"Back"})}),p.jsx("div",{className:"fbre-controls__center",children:p.jsxs("span",{className:"fbre-controls__progress",children:[e.screenNumber," / ",e.totalScreens]})}),p.jsx("div",{className:"fbre-controls__right",children:e.isLastScreen?p.jsx("button",{type:"button",className:"fbre-btn fbre-btn--complete",onClick:n,disabled:s,children:s?"Submitting...":r||"Complete"}):p.jsx("button",{type:"button",className:"fbre-btn fbre-btn--next",onClick:t,disabled:s,children:s?"Loading...":r||"Next"})})]});function Pn(e,s,o,t){return!s&&!o&&!t?e:{...e,...s&&{theme:{...e.theme,...s}},...o&&{navigation:{...e.navigation,...o}},...t&&{controls:{...e.controls,...t}}}}const ze=({flow:e,data:s,theme:o,navigation:t,controls:n,screenIndex:r,context:i,storeRef:a,onFlowComplete:c,onScreenChange:u,onScreenValidationChange:l,apiCtx:d})=>{const f=w.useRef(null);f.current||(f.current=un(),f.current.getState().loadFlow(e,s,i)),a&&(a.current=f.current),w.useEffect(()=>{f.current&&f.current.getState().loadFlow(e,s,i)},[e.uuid]),w.useEffect(()=>{if(f.current){const g=f.current.getState(),h=Pn(g.config,o,t,n);h!==g.config&&f.current.setState({config:h})}},[o,t,n]);const m=i?JSON.stringify(i):"";w.useEffect(()=>{f.current&&i&&f.current.getState().updateContext(i)},[m]);const y=p.jsx(pe.Provider,{value:f.current,children:p.jsx(_n,{screenIndex:r??0,onFlowComplete:c,onScreenChange:u,onScreenValidationChange:l})});return d?p.jsx(qe.Provider,{value:d,children:y}):y},$n=({flowId:e,apiEndpoint:s,apiKey:o,data:t,theme:n,navigation:r,controls:i,screenIndex:a,context:c,storeRef:u,onFlowComplete:l,onScreenChange:d,onScreenValidationChange:f})=>{const[m,y]=w.useState(null),[g,h]=w.useState(""),[v,C]=w.useState(null);return w.useEffect(()=>{y(null),h("");const x={apiEndpoint:s,apiKey:o};Dn(x,e).then(b=>{y(b.data),C({config:x,flowId:b.id,flowVersionId:b.versionId,tenantId:b.tenantId})}).catch(b=>h(b.message))},[e,s,o]),g?p.jsx("div",{className:"fbre-container",children:p.jsxs("div",{className:"fbre-remote-error",children:[p.jsx("p",{children:"Failed to load form"}),p.jsx("p",{className:"fbre-remote-error__detail",children:g})]})}):!m||!v?p.jsx("div",{className:"fbre-container",children:p.jsxs("div",{className:"fbre-remote-loading",children:[p.jsx("div",{className:"fbre-spinner"}),p.jsx("p",{children:"Loading form..."})]})}):p.jsx(ze,{flow:m,data:t,theme:n,navigation:r,controls:i,screenIndex:a,context:c,storeRef:u,onFlowComplete:l,onScreenChange:d,onScreenValidationChange:f,apiCtx:v})},Hn=e=>"sessionEndpoint"in e?p.jsx(An,{...e}):"flowId"in e&&e.flowId?p.jsx($n,{...e}):p.jsx(ze,{...e});exports.ApiError=se;exports.FBRE=Hn;exports.TimeoutError=Ge;exports.addFBREEventListener=wn;exports.removeFBREEventListener=jn;exports.useFBREApi=Rn;exports.useFBREStore=P;exports.useFBREStoreApi=be;