treege 3.0.0-beta.61 → 3.0.0-beta.63

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 CHANGED
@@ -45,8 +45,9 @@ Treege is a modern React library for creating and rendering interactive decision
45
45
  - **Security**: Built-in input sanitization to prevent XSS attacks
46
46
  - **Enhanced Error Messages**: Clear, user-friendly error messages for HTTP inputs and validation
47
47
  - **Conditional Logic**: Dynamic field visibility based on user input and conditional edges
48
- - **Multi-Step Forms**: Group nodes are automatically turned into navigable steps with Back/Continue controls
49
- - **Loading State**: Built-in `isLoading` prop renders a customizable skeleton while the flow is being fetched
48
+ - **Multi-Step Forms**: Group nodes are automatically turned into navigable steps with Back/Continue controls, an `onBack` bridge to outer flows, and external-button submission via `formId`
49
+ - **Edit Mode**: Pre-fill with `initialValues` (accepts name keys, reactive) to round-trip and edit previously submitted records
50
+ - **Loading State**: Built-in `isLoading` prop renders a customizable skeleton while the flow is being fetched, plus `isSubmitting` to drive the button's loading state from async submits
50
51
  - **Fully Customizable**: Override any component (form, inputs, ui, step, submitButton, submitButtonWrapper, loadingSkeleton)
51
52
  - **Optional Dependencies**: Graceful degradation when optional packages like `react-native-document-picker` aren't installed
52
53
  - **Theme Support**: Dark/light mode out of the box
@@ -335,22 +336,24 @@ You can implement these inputs using popular React Native libraries:
335
336
 
336
337
  The React Native renderer shares the same API as the web renderer, with some platform-specific props:
337
338
 
338
- | Prop | Type | Default | Description |
339
- |-------------------------|---------------------------------------------|--------------|--------------------------------------------------------------------------------|
340
- | `flow` | `Flow \| null` | - | Decision tree to render |
341
- | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
342
- | `onChange` | `(values: FormValues) => void` | - | Form change handler |
343
- | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
344
- | `initialValues` | `FormValues` | `{}` | Initial form values |
345
- | `components` | `TreegeRendererComponents` | - | Custom component overrides |
346
- | `language` | `string` | `"en"` | UI language |
347
- | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
348
- | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
349
- | `googleApiKey` | `string` | - | API key for address input |
350
- | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
351
- | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form |
352
- | `style` | `ViewStyle` | - | ScrollView style (RN only) |
353
- | `contentContainerStyle` | `ViewStyle` | - | Content container style (RN) |
339
+ | Prop | Type | Default | Description |
340
+ |-------------------------|---------------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------|
341
+ | `flow` | `Flow \| null` | - | Decision tree to render |
342
+ | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
343
+ | `onChange` | `(values: FormValues) => void` | - | Form change handler |
344
+ | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
345
+ | `initialValues` | `FormValues` | `{}` | Pre-fill values to edit a record. Accepts `node.id` or name keys; reactive (re-seeds if it changes after mount) |
346
+ | `components` | `TreegeRendererComponents` | - | Custom component overrides |
347
+ | `language` | `string` | `"en"` | UI language |
348
+ | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
349
+ | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
350
+ | `googleApiKey` | `string` | - | API key for address input |
351
+ | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
352
+ | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form |
353
+ | `isSubmitting` | `boolean` | `false` | Force the submit/continue button into its loading state (OR-ed with internal state) |
354
+ | `onBack` | `() => void` | - | Called when Back is clicked on the first step; bridges to an outer flow |
355
+ | `style` | `ViewStyle` | - | ScrollView style (RN only) |
356
+ | `contentContainerStyle` | `ViewStyle` | - | Content container style (RN) |
354
357
 
355
358
  ## Node Types
356
359
 
@@ -586,6 +589,32 @@ Customize the skeleton via `components.loadingSkeleton`:
586
589
  />
587
590
  ```
588
591
 
592
+ ### Editing an Existing Submission
593
+
594
+ To edit a record that was already filled in, pass it to `initialValues`. The keys can be either `node.id` **or** the same name-based keys you receive from `onSubmit`/`onChange`, so you can round-trip the submitted object directly — no remapping needed:
595
+
596
+ ```tsx
597
+ const handleSubmit = (values) => save(values); // e.g. { firstName: "Alice", email: "a@b.com" }
598
+
599
+ // later, to edit the saved record:
600
+ <TreegeRenderer flow={flow} initialValues={savedRecord} onSubmit={handleSubmit} />
601
+ ```
602
+
603
+ `initialValues` is **reactive**: if it changes after mount (e.g. an async-fetched record resolves later), the form is re-seeded automatically — no `key` prop or `isLoading` gate required. Passing a new object of identical content does not reset the form, so in-progress edits are preserved.
604
+
605
+ ```tsx
606
+ const { data } = useQuery(/* ... */);
607
+ <TreegeRenderer flow={flow} initialValues={data ?? {}} onSubmit={handleSubmit} />
608
+ ```
609
+
610
+ ### Submitting State
611
+
612
+ Pass `isSubmitting` to keep the submit/continue button in its loading state (spinner + disabled) while an async `onSubmit` resolves on your side. It's OR-ed with the renderer's own internal submitting state (e.g. during an HTTP `submitConfig` call):
613
+
614
+ ```tsx
615
+ <TreegeRenderer flow={flow} isSubmitting={mutation.isPending} onSubmit={handleSubmit} />
616
+ ```
617
+
589
618
  ### Multi-Step Forms
590
619
 
591
620
  When a flow contains **Group** nodes, the renderer automatically splits the form into navigable steps — each contiguous slice of visible nodes sharing the same group becomes one step, with built-in Back/Continue controls (Continue turns into Submit on the last step). Branching via conditional edges recomputes the steps on the fly.
@@ -596,13 +625,13 @@ Override the default step layout via `components.step`:
596
625
  <TreegeRenderer
597
626
  flow={flow}
598
627
  components={{
599
- step: ({ label, children, isFirstStep, isLastStep, canContinue, onBack, onContinue }) => (
628
+ step: ({ label, children, canGoBack, isLastStep, canContinue, isSubmitting, onBack, onContinue }) => (
600
629
  <section>
601
630
  <h2>{label}</h2>
602
631
  {children}
603
- {!isFirstStep && <button onClick={onBack}>Back</button>}
604
- <button disabled={!canContinue} onClick={onContinue}>
605
- {isLastStep ? "Submit" : "Continue"}
632
+ {canGoBack && <button onClick={onBack}>Back</button>}
633
+ <button disabled={!canContinue || isSubmitting} onClick={onContinue}>
634
+ {isSubmitting ? "Submitting…" : isLastStep ? "Submit" : "Continue"}
606
635
  </button>
607
636
  </section>
608
637
  ),
@@ -610,6 +639,25 @@ Override the default step layout via `components.step`:
610
639
  />
611
640
  ```
612
641
 
642
+ Use **`canGoBack`** (not `!isFirstStep`) to decide whether to show the Back control: it's `true` on any step past the first, and also on the first step when an `onBack` prop is provided.
643
+
644
+ #### Bridging navigation to an outer flow
645
+
646
+ When the renderer is embedded in a surrounding wizard (e.g. a modal with its own steps), use `onBack` to step back out of the renderer's first step, and `formId` to drive submission from an external button:
647
+
648
+ ```tsx
649
+ <TreegeRenderer
650
+ flow={flow}
651
+ formId="treege-form"
652
+ onBack={() => modal.goToPreviousStep()} // Back on step 0 → previous modal step
653
+ onSubmit={handleSubmit}
654
+ />
655
+
656
+ // A submit button living outside the renderer (web): only submits on the last
657
+ // step — on earlier steps it advances, like the built-in Continue button.
658
+ <button type="submit" form="treege-form">Save</button>
659
+ ```
660
+
613
661
  ### Headless / Programmatic Control
614
662
 
615
663
  Use the `useTreegeRenderer` hook to drive the form yourself (headless mode). It takes the same configuration as `TreegeRenderer` and returns the full form state and control methods:
@@ -701,21 +749,24 @@ Once the development server is running, you can access these examples:
701
749
 
702
750
  ### TreegeRenderer Props
703
751
 
704
- | Prop | Type | Default | Description |
705
- |------------------|---------------------------------------------|--------------|--------------------------------------------------------------------------------|
706
- | `flow` | `Flow \| null` | - | Decision tree to render |
707
- | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
708
- | `onChange` | `(values: FormValues) => void` | - | Form change handler |
709
- | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
710
- | `initialValues` | `FormValues` | `{}` | Initial form values |
711
- | `components` | `TreegeRendererComponents` | - | Custom component overrides |
712
- | `language` | `string` | `"en"` | UI language |
713
- | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
714
- | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
715
- | `googleApiKey` | `string` | - | API key for address input |
716
- | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
717
- | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form (see below) |
718
- | `className` | `string` | - | Additional CSS class names for custom styling |
752
+ | Prop | Type | Default | Description |
753
+ |------------------|---------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
754
+ | `flow` | `Flow \| null` | - | Decision tree to render |
755
+ | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
756
+ | `onChange` | `(values: FormValues) => void` | - | Form change handler |
757
+ | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
758
+ | `initialValues` | `FormValues` | `{}` | Pre-fill values to edit a submitted record. Accepts `node.id` **or** name keys (same shape as `onSubmit`); reactive — re-seeds if it changes after mount (see below) |
759
+ | `components` | `TreegeRendererComponents` | - | Custom component overrides |
760
+ | `language` | `string` | `"en"` | UI language |
761
+ | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
762
+ | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
763
+ | `googleApiKey` | `string` | - | API key for address input |
764
+ | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
765
+ | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form (see below) |
766
+ | `isSubmitting` | `boolean` | `false` | Force the submit/continue button into its loading state (spinner + disabled). OR-ed with the internal submitting state — useful with an async `onSubmit` |
767
+ | `onBack` | `() => void` | - | Called when Back is clicked on the **first step**; bridges back-navigation to an outer flow (e.g. a parent modal). Shows a Back button on step 0 when provided |
768
+ | `formId` | `string` | - | Sets the `<form>` `id` so a submit button outside the renderer can target it via the native `form` attribute. Web only; submits only on the last step in multi-step flows |
769
+ | `className` | `string` | - | Additional CSS class names for custom styling |
719
770
 
720
771
  ## Development
721
772