treege 3.0.0-beta.9 → 3.0.0-beta.91

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.
Files changed (225) hide show
  1. package/LICENSE +18 -12
  2. package/README.md +598 -79
  3. package/dist/DefaultSubmitButton-NeSDqyzv.js +1909 -0
  4. package/dist/ThemeContext-CPsC8QIP.js +1008 -0
  5. package/dist/editor/components/input/ComboboxWithCreate.d.ts +2 -1
  6. package/dist/editor/components/styles/EditorStyles.d.ts +2 -0
  7. package/dist/editor/constants/defaultNode.d.ts +1 -1
  8. package/dist/editor/constants/edgeTypes.d.ts +3 -2
  9. package/dist/editor/constants/inputTypeIcons.d.ts +3 -0
  10. package/dist/editor/constants/nodeSpacing.d.ts +25 -0
  11. package/dist/editor/constants/nodeTypes.d.ts +4 -5
  12. package/dist/editor/context/OpenApiContext.d.ts +79 -0
  13. package/dist/editor/context/TreegeEditorRuntimeProvider.d.ts +78 -0
  14. package/dist/editor/features/TreegeEditor/TreegeEditor.d.ts +1 -1
  15. package/dist/editor/features/TreegeEditor/controls/MiniMapControl.d.ts +6 -0
  16. package/dist/editor/features/TreegeEditor/dialogs/AuthorizeDialog.d.ts +20 -0
  17. package/dist/editor/features/TreegeEditor/dialogs/ChangeNodeTypeDialog.d.ts +2 -0
  18. package/dist/editor/features/TreegeEditor/dialogs/DeleteNodeDialog.d.ts +2 -0
  19. package/dist/editor/features/TreegeEditor/dialogs/HeadersDialog.d.ts +19 -0
  20. package/dist/editor/features/TreegeEditor/dialogs/OpenApiDialog.d.ts +6 -0
  21. package/dist/editor/features/TreegeEditor/edges/ConditionalEdge.d.ts +2 -2
  22. package/dist/editor/features/TreegeEditor/edges/DefaultEdge.d.ts +3 -0
  23. package/dist/editor/features/TreegeEditor/forms/HttpConfigForm.d.ts +4 -1
  24. package/dist/editor/features/TreegeEditor/forms/JsonTemplateEditor.d.ts +13 -0
  25. package/dist/editor/features/TreegeEditor/forms/OptionsMappingFields.d.ts +34 -0
  26. package/dist/editor/features/TreegeEditor/forms/OptionsSourceForm.d.ts +7 -0
  27. package/dist/editor/features/TreegeEditor/forms/SensitiveHeaderWarning.d.ts +13 -0
  28. package/dist/editor/features/TreegeEditor/forms/SubmitConfigForm.d.ts +7 -0
  29. package/dist/editor/features/TreegeEditor/inputs/ApiUrlCombobox.d.ts +20 -0
  30. package/dist/editor/features/TreegeEditor/inputs/ComboboxPattern.d.ts +2 -1
  31. package/dist/editor/features/TreegeEditor/inputs/DefaultFileValueField.d.ts +14 -0
  32. package/dist/editor/features/TreegeEditor/inputs/OptionImageField.d.ts +6 -0
  33. package/dist/editor/features/TreegeEditor/inputs/SelectNodeGroup.d.ts +22 -1
  34. package/dist/editor/features/TreegeEditor/inputs/TranslatableInput.d.ts +20 -0
  35. package/dist/editor/features/TreegeEditor/layout/AutoLayout.d.ts +15 -0
  36. package/dist/editor/features/TreegeEditor/listeners/FlowChangeEmitter.d.ts +19 -0
  37. package/dist/editor/features/TreegeEditor/nodes/TreegeNode.d.ts +5 -0
  38. package/dist/editor/features/TreegeEditor/nodes/components/BottomHandleDropdown.d.ts +25 -0
  39. package/dist/editor/features/TreegeEditor/nodes/components/NodeGroupBadge.d.ts +6 -0
  40. package/dist/editor/features/TreegeEditor/nodes/components/NodeImage.d.ts +5 -0
  41. package/dist/editor/features/TreegeEditor/nodes/components/NodeImageButton.d.ts +6 -0
  42. package/dist/editor/features/TreegeEditor/nodes/components/NodeInputPreview.d.ts +12 -0
  43. package/dist/editor/features/TreegeEditor/nodes/components/NodeLabelInput.d.ts +10 -0
  44. package/dist/editor/features/TreegeEditor/nodes/components/NodeMoreMenu.d.ts +6 -0
  45. package/dist/editor/features/TreegeEditor/nodes/components/NodeRequiredButton.d.ts +6 -0
  46. package/dist/editor/features/TreegeEditor/nodes/components/NodeStackOrderButtons.d.ts +6 -0
  47. package/dist/editor/features/TreegeEditor/nodes/components/NodeTypeBadge.d.ts +7 -0
  48. package/dist/editor/features/TreegeEditor/nodes/components/NodeTypePickerMenuContent.d.ts +12 -0
  49. package/dist/editor/features/TreegeEditor/nodes/layout/NodeWrapper.d.ts +4 -2
  50. package/dist/editor/features/TreegeEditor/panel/AIGeneratorDialog.d.ts +16 -0
  51. package/dist/editor/features/TreegeEditor/panel/ActionsPanel.d.ts +7 -2
  52. package/dist/editor/features/TreegeEditor/panel/MultiSelectionPanel.d.ts +7 -0
  53. package/dist/editor/hooks/useAvailableParentFields.d.ts +13 -0
  54. package/dist/editor/hooks/useFlowActions.d.ts +6 -2
  55. package/dist/editor/hooks/useFlowConnections.d.ts +14 -0
  56. package/dist/editor/hooks/useFlowContent.d.ts +16 -0
  57. package/dist/editor/hooks/useHistoryStore.d.ts +26 -0
  58. package/dist/editor/hooks/useIsStackedEdge.d.ts +8 -0
  59. package/dist/editor/hooks/useKeyValueRows.d.ts +15 -0
  60. package/dist/editor/hooks/useNodesSelection.d.ts +5 -5
  61. package/dist/editor/hooks/useStackPosition.d.ts +14 -0
  62. package/dist/editor/hooks/useTranslate.d.ts +1 -1
  63. package/dist/editor/hooks/useUndoRedo.d.ts +31 -0
  64. package/dist/editor/types/ai.d.ts +65 -0
  65. package/dist/editor/types/editor.d.ts +106 -10
  66. package/dist/editor/types/openapi.d.ts +106 -0
  67. package/dist/editor/utils/aiFlowGenerator.d.ts +5 -0
  68. package/dist/editor/utils/cleanEmptyData.d.ts +18 -0
  69. package/dist/editor/utils/cleanNodeConfig.d.ts +5 -0
  70. package/dist/editor/utils/dagreLayout.d.ts +8 -0
  71. package/dist/editor/utils/edge.d.ts +50 -0
  72. package/dist/editor/utils/groupColor.d.ts +14 -0
  73. package/dist/editor/utils/image.d.ts +7 -0
  74. package/dist/editor/utils/inputTypeIcon.d.ts +6 -0
  75. package/dist/editor/utils/jsonBindTarget.d.ts +15 -0
  76. package/dist/editor/utils/openApiPayload.d.ts +12 -0
  77. package/dist/editor/utils/openapi.d.ts +35 -0
  78. package/dist/editor/utils/sensitiveHeaders.d.ts +20 -0
  79. package/dist/editor/utils/stackPositionIndex.d.ts +9 -0
  80. package/dist/editor-DJbNgLSF.js +6485 -0
  81. package/dist/editor.js +3 -7
  82. package/dist/main.js +6 -52
  83. package/dist/renderer/context/TreegeRenderRuntimeProvider.d.ts +135 -0
  84. package/dist/renderer/context/TreegeRendererProvider.d.ts +15 -0
  85. package/dist/renderer/context/TreegeViewerProvider.d.ts +28 -0
  86. package/dist/renderer/features/TreegeRenderer/native/TreegeRenderer.d.ts +19 -11
  87. package/dist/renderer/features/TreegeRenderer/native/components/DefaultFormWrapper.d.ts +7 -7
  88. package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputLabel.d.ts +10 -0
  89. package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputWrapper.d.ts +9 -0
  90. package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputs.d.ts +20 -15
  91. package/dist/renderer/features/TreegeRenderer/native/components/DefaultLoadingSkeleton.d.ts +8 -0
  92. package/dist/renderer/features/TreegeRenderer/native/components/DefaultStep.d.ts +3 -0
  93. package/dist/renderer/features/TreegeRenderer/native/components/DefaultSubmitButton.d.ts +9 -7
  94. package/dist/renderer/features/TreegeRenderer/native/components/DefaultSubmitButtonWrapper.d.ts +11 -0
  95. package/dist/renderer/features/TreegeRenderer/native/components/DefaultUI.d.ts +8 -7
  96. package/dist/renderer/features/TreegeRenderer/native/components/DependencyHint.d.ts +15 -0
  97. package/dist/renderer/features/TreegeRenderer/native/components/OptionItemContent.d.ts +17 -0
  98. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultAddressInput.d.ts +3 -0
  99. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultAutocompleteInput.d.ts +3 -0
  100. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultCheckboxInput.d.ts +3 -0
  101. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultDateInput.d.ts +3 -0
  102. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultDateRangeInput.d.ts +3 -0
  103. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultFileInput.d.ts +3 -0
  104. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultHiddenInput.d.ts +3 -0
  105. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultHttpInput.d.ts +3 -0
  106. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultNumberInput.d.ts +3 -0
  107. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultPasswordInput.d.ts +3 -0
  108. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultRadioInput.d.ts +3 -0
  109. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSelectInput.d.ts +3 -0
  110. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSubmitInput.d.ts +11 -0
  111. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSwitchInput.d.ts +3 -0
  112. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTextInput.d.ts +3 -0
  113. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTextareaInput.d.ts +3 -0
  114. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTimeInput.d.ts +3 -0
  115. package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTimeRangeInput.d.ts +3 -0
  116. package/dist/renderer/features/TreegeRenderer/useTreegeRenderer.d.ts +97 -24
  117. package/dist/renderer/features/TreegeRenderer/web/TreegeRenderer.d.ts +1 -1
  118. package/dist/renderer/features/TreegeRenderer/web/components/DefaultFormWrapper.d.ts +3 -2
  119. package/dist/renderer/features/TreegeRenderer/web/components/DefaultInputLabel.d.ts +9 -0
  120. package/dist/renderer/features/TreegeRenderer/web/components/DefaultInputWrapper.d.ts +9 -0
  121. package/dist/renderer/features/TreegeRenderer/web/components/DefaultLoadingSkeleton.d.ts +7 -0
  122. package/dist/renderer/features/TreegeRenderer/web/components/DefaultStep.d.ts +3 -0
  123. package/dist/renderer/features/TreegeRenderer/web/components/DefaultSubmitButton.d.ts +5 -1
  124. package/dist/renderer/features/TreegeRenderer/web/components/DependencyHint.d.ts +22 -0
  125. package/dist/renderer/features/TreegeRenderer/web/components/OptionItemContent.d.ts +17 -0
  126. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultAddressInput.d.ts +1 -1
  127. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultAutocompleteInput.d.ts +1 -1
  128. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultCheckboxInput.d.ts +1 -1
  129. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultDateInput.d.ts +1 -1
  130. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultDateRangeInput.d.ts +1 -1
  131. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultFileInput.d.ts +1 -1
  132. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultHiddenInput.d.ts +1 -1
  133. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultHttpInput.d.ts +1 -1
  134. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultNumberInput.d.ts +1 -1
  135. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultPasswordInput.d.ts +1 -1
  136. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultRadioInput.d.ts +1 -1
  137. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSelectInput.d.ts +1 -1
  138. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSubmitInput.d.ts +11 -0
  139. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSwitchInput.d.ts +1 -1
  140. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTextAreaInput.d.ts +1 -1
  141. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTextInput.d.ts +1 -1
  142. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTimeInput.d.ts +1 -1
  143. package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTimeRangeInput.d.ts +1 -1
  144. package/dist/renderer/features/TreegeRenderer/web/components/styles/RendererStyles.d.ts +2 -0
  145. package/dist/renderer/features/TreegeViewer/utils/viewerFields.d.ts +102 -0
  146. package/dist/renderer/features/TreegeViewer/web/TreegeViewer.d.ts +94 -0
  147. package/dist/renderer/hooks/useInputOptions.d.ts +28 -0
  148. package/dist/renderer/hooks/useRenderNode.d.ts +62 -0
  149. package/dist/renderer/hooks/useSubmitHandler.d.ts +37 -0
  150. package/dist/renderer/hooks/useTranslate.d.ts +7 -5
  151. package/dist/renderer/index.d.ts +10 -2
  152. package/dist/renderer/index.native.d.ts +20 -0
  153. package/dist/renderer/types/renderer.d.ts +332 -49
  154. package/dist/renderer/utils/extraPayload.d.ts +21 -0
  155. package/dist/renderer/utils/file.d.ts +24 -10
  156. package/dist/renderer/utils/flow.d.ts +1 -18
  157. package/dist/renderer/utils/form.d.ts +54 -2
  158. package/dist/renderer/utils/http.d.ts +177 -0
  159. package/dist/renderer/utils/jsonTemplate.d.ts +30 -0
  160. package/dist/renderer/utils/node.d.ts +29 -1
  161. package/dist/renderer/utils/sanitize.d.ts +85 -0
  162. package/dist/renderer/utils/sanitize.native.d.ts +69 -0
  163. package/dist/renderer/utils/step.d.ts +27 -0
  164. package/dist/renderer/utils/submit.d.ts +50 -0
  165. package/dist/renderer/utils/templateDependencies.d.ts +17 -0
  166. package/dist/renderer-CNbSt_QW.js +446 -0
  167. package/dist/renderer-native.d.ts +2 -0
  168. package/dist/renderer-native.js +3696 -0
  169. package/dist/renderer.js +5 -45
  170. package/dist/shared/components/ui/badge.d.ts +2 -2
  171. package/dist/shared/components/ui/button.d.ts +3 -3
  172. package/dist/shared/components/ui/collapsible.d.ts +1 -1
  173. package/dist/shared/components/ui/command.d.ts +1 -1
  174. package/dist/shared/components/ui/dropdown-menu.d.ts +1 -1
  175. package/dist/shared/components/ui/field.d.ts +24 -0
  176. package/dist/shared/components/ui/form.d.ts +1 -1
  177. package/dist/shared/components/ui/item.d.ts +23 -0
  178. package/dist/shared/components/ui/popover.d.ts +10 -2
  179. package/dist/shared/components/ui/select.d.ts +3 -1
  180. package/dist/shared/components/ui/sheet.d.ts +1 -1
  181. package/dist/shared/components/ui/skeleton.d.ts +3 -0
  182. package/dist/shared/components/ui/toggle-group.d.ts +7 -0
  183. package/dist/shared/components/ui/toggle.d.ts +9 -0
  184. package/dist/shared/components/ui/tooltip.d.ts +1 -1
  185. package/dist/shared/constants/colors.d.ts +45 -0
  186. package/dist/shared/constants/inputType.d.ts +6 -0
  187. package/dist/shared/constants/node.d.ts +0 -1
  188. package/dist/shared/context/PortalContainerContext.d.ts +5 -0
  189. package/dist/shared/context/ThemeContext.d.ts +2 -0
  190. package/dist/shared/context/ThemeContext.native.d.ts +22 -0
  191. package/dist/shared/hooks/useMediaQuery.d.ts +12 -0
  192. package/dist/shared/hooks/useThemeColors.d.ts +37 -0
  193. package/dist/shared/locales/ar.json.d.ts +259 -19
  194. package/dist/shared/locales/de.json.d.ts +260 -20
  195. package/dist/shared/locales/en.json.d.ts +261 -21
  196. package/dist/shared/locales/es.json.d.ts +260 -20
  197. package/dist/shared/locales/fr.json.d.ts +260 -20
  198. package/dist/shared/locales/it.json.d.ts +260 -20
  199. package/dist/shared/locales/pt.json.d.ts +260 -20
  200. package/dist/shared/types/edge.d.ts +6 -0
  201. package/dist/shared/types/file.d.ts +14 -0
  202. package/dist/shared/types/node.d.ts +155 -19
  203. package/dist/shared/utils/httpRecord.d.ts +20 -0
  204. package/dist/shared/utils/inputTypeGuards.d.ts +7 -0
  205. package/dist/shared/utils/nodeTypeGuards.d.ts +1 -6
  206. package/dist/shared/utils/normalizeLabel.d.ts +22 -0
  207. package/dist/shared/utils/translations.d.ts +21 -1
  208. package/dist/useRenderNode-CG466pNk.js +538 -0
  209. package/package.json +54 -22
  210. package/dist/ThemeContext-BIvs8Kw-.js +0 -758
  211. package/dist/TreegeEditor-Lv5Tn9_F.js +0 -2152
  212. package/dist/TreegeRenderer-BVaqgInZ.js +0 -1405
  213. package/dist/editor/context/TreegeEditorContext.d.ts +0 -12
  214. package/dist/editor/features/TreegeEditor/forms/FlowNodeForm.d.ts +0 -2
  215. package/dist/editor/features/TreegeEditor/inputs/SelectInputType.d.ts +0 -7
  216. package/dist/editor/features/TreegeEditor/nodes/FlowNode.d.ts +0 -6
  217. package/dist/editor/features/TreegeEditor/nodes/GroupNode.d.ts +0 -6
  218. package/dist/editor/features/TreegeEditor/nodes/InputNode.d.ts +0 -6
  219. package/dist/editor/features/TreegeEditor/nodes/UINode.d.ts +0 -6
  220. package/dist/editor/hooks/useEdgesSelection.d.ts +0 -11
  221. package/dist/renderer/context/TreegeConfigContext.d.ts +0 -39
  222. package/dist/renderer/context/TreegeRendererContext.d.ts +0 -25
  223. package/dist/renderer/features/TreegeRenderer/native/components/DefaultGroup.d.ts +0 -7
  224. package/dist/renderer/features/TreegeRenderer/web/components/DefaultGroup.d.ts +0 -6
  225. /package/dist/editor/components/{data-display/logo.d.ts → branding/Logo.d.ts} +0 -0
package/README.md CHANGED
@@ -2,10 +2,10 @@
2
2
  <img alt="Treege" src="https://user-images.githubusercontent.com/108873902/189673125-5d1fdaf3-82d1-486f-bb16-01b0554bd4f1.png" style="padding: 20px;" width="auto" height="100" />
3
3
 
4
4
  <h1>Treege</h1>
5
- <p><strong>Build powerful decision trees with a visual node-based editor</strong></p>
5
+ <p><strong>Building complex, dynamic forms has never been this simple</strong></p>
6
6
 
7
7
  [![npm version](https://badge.fury.io/js/treege.svg)](https://badge.fury.io/js/treege)
8
- [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
9
9
 
10
10
  <p>
11
11
  <a href="https://treege.io/">🌐 Website</a> •
@@ -13,7 +13,8 @@
13
13
  <a href="#features">Features</a> •
14
14
  <a href="#installation">Installation</a> •
15
15
  <a href="#quick-start">Quick Start</a> •
16
- <a href="#examples">Examples</a>
16
+ <a href="#examples">Examples</a>
17
+ <a href="./AI_GENERATION.md">🪄 AI Generation</a>
17
18
  </p>
18
19
  </div>
19
20
 
@@ -21,14 +22,15 @@
21
22
 
22
23
  ## Overview
23
24
 
24
- Treege is a modern React library for creating and rendering interactive decision trees. Built on top of ReactFlow, it provides a complete solution for building complex form flows, decision logic, and conditional workflows with an intuitive visual editor.
25
+ Treege is a modern React library for creating and rendering interactive decision trees. Built on top of ReactFlow, it provides a complete solution for building complex form flow, decision logic, and conditional workflows with an intuitive visual editor.
25
26
 
26
27
  ## Features
27
28
 
28
29
  ### Visual Editor (`treege/editor`)
29
30
  - **Node-based Interface**: Drag-and-drop editor powered by ReactFlow
30
- - **4 Node Types**: Flow, Group, Input, and UI nodes
31
+ - **3 Node Types**: Input, UI, and Group nodes
31
32
  - **Conditional Edges**: Advanced logic with AND/OR operators (`===`, `!==`, `>`, `<`, `>=`, `<=`)
33
+ - **AI-Powered Generation**: Generate decision trees from natural language descriptions using Gemini, OpenAI, DeepSeek, or Claude ([Learn more](./AI_GENERATION.md))
32
34
  - **Multi-language Support**: Built-in translation system for all labels
33
35
  - **Type-safe**: Full TypeScript support
34
36
  - **Mini-map & Controls**: Navigation tools for complex trees
@@ -37,13 +39,21 @@ Treege is a modern React library for creating and rendering interactive decision
37
39
  ### Runtime Renderer (`treege/renderer`)
38
40
  - **Production Ready**: Full-featured form generation and validation system
39
41
  - **16 Input Types**: text, number, select, checkbox, radio, date, daterange, time, timerange, file, address, http, textarea, password, switch, autocomplete, and hidden
42
+ - **Cross-Platform**: Full support for both React Web and React Native with dedicated implementations
40
43
  - **HTTP Integration**: Built-in API integration with response mapping and search functionality
41
44
  - **Advanced Validation**: Required fields, pattern matching, custom validation functions
45
+ - **Security**: Built-in input sanitization to prevent XSS attacks
46
+ - **Enhanced Error Messages**: Clear, user-friendly error messages for HTTP inputs and validation
42
47
  - **Conditional Logic**: Dynamic field visibility based on user input and conditional edges
43
- - **Web & Native**: Both web (React) and React Native renderer implementations
44
- - **Fully Customizable**: Override any component (FormWrapper, Group, Inputs, SubmitButton, UI elements)
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
+ - **Host Data Injection**: Attach app-owned fields (e.g. a user id) to every submission with `extraPayload` — merged into both the `onSubmit` payload and the HTTP submit body
51
+ - **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
52
+ - **Fully Customizable**: Override any component (form, inputs, inputLabel, ui, step, submitButton, submitButtonWrapper, loadingSkeleton)
53
+ - **Optional Dependencies**: Graceful degradation when optional packages like `react-native-document-picker` aren't installed
45
54
  - **Theme Support**: Dark/light mode out of the box
46
55
  - **Google API Integration**: Address autocomplete support
56
+ - **Read-Only Viewer**: `TreegeViewer` renders a submitted flow as a label/value recap — same branch-visibility and formatting as the form, works with or without a flow (self-describing values), supports collapse, with a headless `getViewerFields` core for custom layouts
47
57
 
48
58
  ### Developer Experience
49
59
  - **Modular**: Import only what you need (editor, renderer, or both)
@@ -54,6 +64,9 @@ Treege is a modern React library for creating and rendering interactive decision
54
64
  ## Installation
55
65
 
56
66
  ```bash
67
+ # bun
68
+ bun add treege
69
+
57
70
  # npm
58
71
  npm install treege
59
72
 
@@ -62,9 +75,6 @@ pnpm add treege
62
75
 
63
76
  # yarn
64
77
  yarn add treege
65
-
66
- # bun
67
- bun add treege
68
78
  ```
69
79
 
70
80
  ## Quick Start
@@ -125,7 +135,7 @@ function App() {
125
135
 
126
136
  return (
127
137
  <TreegeRenderer
128
- flows={flow}
138
+ flow={flow}
129
139
  onSubmit={handleSubmit}
130
140
  />
131
141
  );
@@ -152,16 +162,136 @@ function App() {
152
162
  {mode === "edit" ? (
153
163
  <TreegeEditor flow={flow} onSave={setFlow} />
154
164
  ) : (
155
- <TreegeRenderer flows={flow} onSubmit={console.log} />
165
+ <TreegeRenderer flow={flow} onSubmit={console.log} />
156
166
  )}
157
167
  </div>
158
168
  );
159
169
  }
160
170
  ```
161
171
 
172
+ ### Live Preview (Editor → Renderer)
173
+
174
+ Use the editor's `onChange` (debounced) to render the form **live** next to the editor — no Save click needed. Because `onChange` isn't gated on having input nodes, the preview also reflects an emptied canvas after Clear. Omit `onSave` to hide the Save button entirely when you rely solely on live updates:
175
+
176
+ ```tsx
177
+ import { TreegeEditor } from "treege/editor";
178
+ import { TreegeRenderer } from "treege/renderer";
179
+ import { useState } from "react";
180
+ import type { Flow } from "treege";
181
+
182
+ function App() {
183
+ const [flow, setFlow] = useState<Flow | null>(null);
184
+
185
+ return (
186
+ <div style={{ display: "flex" }}>
187
+ <TreegeEditor onChange={setFlow} /> {/* live, no Save button */}
188
+ <TreegeRenderer flow={flow} onSubmit={console.log} />
189
+ </div>
190
+ );
191
+ }
192
+ ```
193
+
194
+ ## Read-Only Viewer (`TreegeViewer`)
195
+
196
+ Once a form has been submitted, `TreegeViewer` renders the result as a read-only **label / value recap** — no inputs, no validation. With a `flow` it replays the submitted `flowResponse` through the renderer's branch-visibility logic, so only the fields that were actually reachable for those values are shown. Option values resolve to their labels, dates/ranges and i18n labels are formatted exactly like the form, and `hidden`/`submit` fields are excluded.
197
+
198
+ ```tsx
199
+ import { TreegeRenderer, TreegeViewer } from "treege/renderer";
200
+ import { useState } from "react";
201
+ import type { Flow, FormValues } from "treege";
202
+
203
+ function App({ flow }: { flow: Flow }) {
204
+ const [submitted, setSubmitted] = useState<FormValues | null>(null);
205
+
206
+ if (submitted) {
207
+ return <TreegeViewer flow={flow} flowResponse={submitted} language="en" />;
208
+ }
209
+
210
+ return <TreegeRenderer flow={flow} onSubmit={setSubmitted} />;
211
+ }
212
+ ```
213
+
214
+ ### Without a flow
215
+
216
+ When you only have stored, self-describing values (e.g. a persisted `WorkflowValue[]`) and no flow definition, omit `flow` and pass them as `flowResponse`. Each entry carries its own `{ name, type, value, label }`, so values are still formatted by type. `flowResponse` is **typed conditionally on `flow`**: with a flow it's `FormValues`, without a flow it's `FlowResponseEntry[]`.
217
+
218
+ ```tsx
219
+ <TreegeViewer
220
+ flowResponse={[
221
+ { name: "city", type: "text", value: "Paris", label: { en: "City" } },
222
+ { name: "dates", type: "daterange", value: "2026-06-01,2026-07-15", label: { en: "Dates" } },
223
+ ]}
224
+ />
225
+ ```
226
+
227
+ ### Props
228
+
229
+ | Prop | Type | Default | Description |
230
+ |-------------------------|------------------------------------------------------------------|-------------------------|---------------------------------------------------------------------------------------------------|
231
+ | `flow` | `Flow` | - | The flow the values were submitted against (omit for flow-less mode) |
232
+ | `flowResponse` | `FormValues` *(with `flow`)* / `FlowResponseEntry[]` *(without)* | - | The submitted values — type is conditional on `flow` |
233
+ | `language` | `string` | provider, then `"en"` | Language used to resolve translatable labels/options |
234
+ | `theme` | `"light" \| "dark"` | provider, then `"dark"` | Light/dark theme (falls back to the `TreegeRendererProvider` config) |
235
+ | `baseUrl` | `string` | - | Resolves relative file paths into absolute URLs; `data:`/`blob:`/absolute URLs are left untouched |
236
+ | `excludedFields` | `string[]` | - | Field names (or ids) to hide from the view |
237
+ | `excludeEmptyFields` | `boolean` | `false` | Hide fields that have no submitted value (instead of showing `emptyText`) |
238
+ | `collapsed` | `boolean` | `false` | When `true`, only the first `collapsedVisibleCount` fields are rendered |
239
+ | `collapsedVisibleCount` | `number` | - | Number of fields kept visible while `collapsed` (defaults to all) |
240
+ | `emptyText` | `string` | `"—"` | Text shown when a field has no submitted value |
241
+ | `className` | `string` | - | Extra class names on the root element |
242
+ | `renderField` | `Partial<Record<InputType, (field) => ReactNode>>` | - | Per-type rendering overrides for the value cell (typically `file`) |
243
+ | `renderRow` | `(field, defaultRow) => ReactNode` | - | Wrap or replace a whole field row (label + value) |
244
+
245
+ ### Collapse
246
+
247
+ `collapsed` + `collapsedVisibleCount` are controlled — you render the toggle and own the state. While collapsed, only the first N fields show:
248
+
249
+ ```tsx
250
+ const [collapsed, setCollapsed] = useState(true);
251
+
252
+ <>
253
+ <button onClick={() => setCollapsed((c) => !c)}>{collapsed ? "Show all" : "Show less"}</button>
254
+ <TreegeViewer flow={flow} flowResponse={submitted} collapsed={collapsed} collapsedVisibleCount={3} />
255
+ </>
256
+ ```
257
+
258
+ ### Customizing rendering
259
+
260
+ Use `renderField` to override the value cell for a specific input type — most often `file`, to render thumbnails from your own storage — while every other type keeps its built-in rendering. Use `renderRow` to control the whole row layout (label + value):
261
+
262
+ ```tsx
263
+ <TreegeViewer
264
+ flow={flow}
265
+ flowResponse={submitted}
266
+ language="fr"
267
+ excludedFields={["internalNote"]}
268
+ renderField={{ file: ({ rawValue }) => <Thumbnails files={rawValue} /> }}
269
+ />
270
+ ```
271
+
272
+ ### Headless usage
273
+
274
+ `TreegeViewer` is a thin layer over two field builders that return the ordered, display-ready fields — use them directly for a fully custom layout (a table, a PDF, columns…):
275
+
276
+ - `getViewerFields(flow, values, { language, baseUrl })` — flow-based resolution.
277
+ - `viewerFieldsFromResponse(response, { language })` — flow-less, from self-describing entries.
278
+
279
+ ```tsx
280
+ import { getViewerFields } from "treege/renderer";
281
+
282
+ const fields = getViewerFields(flow, values, { language: "en", baseUrl });
283
+
284
+ fields.forEach((field) => {
285
+ // field.label, field.type, field.rawValue
286
+ // field.display — normalized, render-ready value:
287
+ // { kind: "text", text } | { kind: "boolean", checked }
288
+ // { kind: "tags", tags } | { kind: "files", files } | { kind: "empty" }
289
+ });
290
+ ```
291
+
162
292
  ## Module Structure
163
293
 
164
- Treege provides three import paths for optimal bundle size:
294
+ Treege provides multiple import paths for optimal bundle size:
165
295
 
166
296
  ```tsx
167
297
  // Import everything (editor + renderer + types)
@@ -170,25 +300,188 @@ import { TreegeEditor, TreegeRenderer } from "treege";
170
300
  // Import only the editor
171
301
  import { TreegeEditor } from "treege/editor";
172
302
 
173
- // Import only the renderer
303
+ // Import only the web renderer
174
304
  import { TreegeRenderer } from "treege/renderer";
305
+
306
+ // Import only the React Native renderer
307
+ import { TreegeRenderer } from "treege/renderer-native";
175
308
  ```
176
309
 
177
- ## Node Types
310
+ ## React Native Support
311
+
312
+ Treege 3.0 includes full React Native support with a dedicated renderer implementation.
313
+
314
+ ### Installation for React Native
315
+
316
+ ```bash
317
+ # Install Treege
318
+ npm install treege
319
+
320
+ # Install peer dependencies
321
+ npm install react-native
322
+
323
+ # Optional: Install for file input support
324
+ npm install react-native-document-picker
325
+ ```
178
326
 
179
- ### Flow Node
180
- Navigation node that controls the flow between different parts of the tree.
327
+ ### Basic Usage
181
328
 
182
329
  ```tsx
183
- {
184
- type: "flow",
185
- data: {
186
- targetId: "next-node-id",
187
- label: "Continue"
188
- }
330
+ import { TreegeRenderer } from "treege/renderer-native";
331
+ import type { Flow, FormValues } from "treege";
332
+
333
+ function App() {
334
+ const flow: Flow = {
335
+ id: "flow-1",
336
+ nodes: [
337
+ {
338
+ id: "name",
339
+ type: "input",
340
+ data: {
341
+ type: "text",
342
+ name: "fullName",
343
+ label: "Full Name",
344
+ required: true
345
+ }
346
+ },
347
+ {
348
+ id: "email",
349
+ type: "input",
350
+ data: {
351
+ type: "text",
352
+ name: "email",
353
+ label: "Email",
354
+ required: true,
355
+ pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"
356
+ }
357
+ }
358
+ ],
359
+ edges: []
360
+ };
361
+
362
+ const handleSubmit = (values: FormValues) => {
363
+ console.log("Form submitted:", values);
364
+ };
365
+
366
+ return (
367
+ <TreegeRenderer
368
+ flow={flow}
369
+ onSubmit={handleSubmit}
370
+ />
371
+ );
189
372
  }
190
373
  ```
191
374
 
375
+ ### Custom Styling
376
+
377
+ You can customize the appearance using the `style` and `contentContainerStyle` props:
378
+
379
+ ```tsx
380
+ <TreegeRenderer
381
+ flow={flow}
382
+ onSubmit={handleSubmit}
383
+ style={{ flex: 1, backgroundColor: "#f5f5f5" }}
384
+ contentContainerStyle={{ padding: 20 }}
385
+ />
386
+ ```
387
+
388
+ ### Custom Components
389
+
390
+ Override default components with your own React Native components.
391
+
392
+ Each input renderer is a **React component** receiving a single props object with two keys:
393
+
394
+ 1. `field` — DOM-safe props (`id`, `name`, `value`, `placeholder`, `required`, `aria-invalid`). On the web you can spread them onto an element (`<input {...field} />`); on React Native pick the ones you need.
395
+ 2. `extra` — Treege-specific props: `setValue`, `error`, `label`, `helperText`, `node`, `InputLabel` (the resolved, overridable label component), and `missingDependencies` (the unfilled fields this input's dynamic options depend on).
396
+
397
+ ```tsx
398
+ import { Text, TextInput, View } from "react-native";
399
+ import { TreegeRenderer } from "treege/renderer-native";
400
+
401
+ const CustomTextInput = ({ field, extra }) => {
402
+ return (
403
+ <View style={{ marginBottom: 16 }}>
404
+ <Text style={{ fontSize: 14, marginBottom: 4 }}>{extra.label}</Text>
405
+ <TextInput
406
+ value={field.value}
407
+ placeholder={field.placeholder}
408
+ onChangeText={extra.setValue}
409
+ style={{
410
+ borderWidth: 1,
411
+ borderColor: extra.error ? "red" : "#ccc",
412
+ padding: 10,
413
+ borderRadius: 8
414
+ }}
415
+ />
416
+ {extra.error && <Text style={{ color: "red", fontSize: 12 }}>{extra.error}</Text>}
417
+ {extra.missingDependencies.length > 0 && (
418
+ <Text style={{ color: "#b45309", fontSize: 12 }}>
419
+ Please fill in first: {extra.missingDependencies.map((d) => d.label).join(", ")}
420
+ </Text>
421
+ )}
422
+ </View>
423
+ );
424
+ };
425
+
426
+ <TreegeRenderer
427
+ flow={flow}
428
+ components={{
429
+ inputs: {
430
+ text: CustomTextInput
431
+ }
432
+ }}
433
+ />
434
+ ```
435
+
436
+ ### Supported Input Types
437
+
438
+ The React Native renderer includes default implementations for all input types:
439
+
440
+ **Fully Implemented (Vanilla React Native)**:
441
+ - `text`, `number`, `textarea`, `password`
442
+ - `checkbox`, `switch`, `hidden`
443
+
444
+ **With Optional Dependencies** (gracefully degrades if not installed):
445
+ - `file` - Requires [react-native-document-picker](https://github.com/rnmods/react-native-document-picker) (optional)
446
+
447
+ **Requires Custom Implementation** (placeholder provided):
448
+ - `select`, `radio`, `autocomplete`
449
+ - `date`, `daterange`, `time`, `timerange`
450
+ - `address`, `http`
451
+
452
+ You can implement these inputs using popular React Native libraries:
453
+ - [@react-native-picker/picker](https://github.com/react-native-picker/picker) for `select` and `radio`
454
+ - [react-native-date-picker](https://github.com/henninghall/react-native-date-picker) for `date` and `time` inputs
455
+ - [@react-native-community/google-places-autocomplete](https://github.com/FaridSafi/react-native-google-places-autocomplete) for `address`
456
+
457
+ ### API Reference
458
+
459
+ The React Native renderer shares the same API as the web renderer, with some platform-specific props:
460
+
461
+ | Prop | Type | Default | Description |
462
+ |-------------------------|-------------------------------------------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
463
+ | `flow` | `Flow \| null` | - | Decision tree to render |
464
+ | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
465
+ | `extraPayload` | `Record<string, unknown> \| (values) => Record` | - | Host-owned fields merged into every submission — the `onSubmit` payload **and** the HTTP submit body. Object or function of the current values (see below) |
466
+ | `onChange` | `(values: FormValues) => void` | - | Form change handler |
467
+ | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
468
+ | `initialValues` | `FormValues` | `{}` | Pre-fill values to edit a record. Accepts `node.id` or name keys; reactive (re-seeds if it changes after mount) |
469
+ | `components` | `TreegeRendererComponents` | - | Custom component overrides |
470
+ | `language` | `string` | `"en"` | UI language |
471
+ | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
472
+ | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
473
+ | `googleApiKey` | `string` | - | API key for address input |
474
+ | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
475
+ | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form |
476
+ | `isSubmitting` | `boolean` | `false` | Force the submit/continue button into its loading state (OR-ed with internal state) |
477
+ | `onBack` | `() => void` | - | Called when Back is clicked on the first step; bridges to an outer flow |
478
+ | `style` | `ViewStyle` | - | ScrollView style (RN only) |
479
+ | `contentContainerStyle` | `ViewStyle` | - | Content container style (RN) |
480
+
481
+ ## Node Types
482
+
483
+ Treege has three node types: `input`, `ui`, and `group`. Navigation is automatic — group nodes drive step navigation and conditional edges drive branching.
484
+
192
485
  ### Input Node
193
486
  Form input with validation, patterns, and conditional logic.
194
487
 
@@ -209,7 +502,7 @@ Form input with validation, patterns, and conditional logic.
209
502
  Supported input types: `text`, `number`, `textarea`, `password`, `select`, `radio`, `checkbox`, `switch`, `autocomplete`, `date`, `daterange`, `time`, `timerange`, `file`, `address`, `http`, `hidden`
210
503
 
211
504
  ### Group Node
212
- Container for organizing multiple nodes together.
505
+ Container for organizing multiple nodes together. Groups also drive **multi-step forms**: at runtime each group of visible nodes becomes a navigable step (Back/Continue). Child nodes belong to a group via their `parentId`.
213
506
 
214
507
  ```tsx
215
508
  {
@@ -239,7 +532,7 @@ Supported UI types:
239
532
 
240
533
  ## Conditional Edges
241
534
 
242
- Create dynamic flows with conditional logic:
535
+ Create dynamic flow with conditional logic:
243
536
 
244
537
  ```tsx
245
538
  {
@@ -285,17 +578,30 @@ Treege supports multiple languages out of the box:
285
578
 
286
579
  ### Custom Input Components
287
580
 
288
- Override default input renderers with your own:
581
+ Override default input renderers with your own. A renderer is a React component
582
+ receiving a single props object: `field` (DOM-safe props, spreadable onto an
583
+ element) and `extra` (`setValue`, `error`, `label`, `helperText`, `node`,
584
+ `InputLabel`, `missingDependencies`).
289
585
 
290
586
  ```tsx
291
587
  import { TreegeRenderer } from "treege/renderer";
292
588
 
293
- const CustomTextInput = ({ node }) => {
294
- return <input className="my-custom-input" />;
589
+ const CustomTextInput = ({ field, extra }) => {
590
+ return (
591
+ <label>
592
+ {extra.label}
593
+ <input
594
+ {...field}
595
+ className="my-custom-input"
596
+ onChange={(e) => extra.setValue(e.target.value)}
597
+ />
598
+ {extra.error && <span className="error">{extra.error}</span>}
599
+ </label>
600
+ );
295
601
  };
296
602
 
297
603
  <TreegeRenderer
298
- flows={flow}
604
+ flow={flow}
299
605
  components={{
300
606
  inputs: {
301
607
  text: CustomTextInput
@@ -304,13 +610,34 @@ const CustomTextInput = ({ node }) => {
304
610
  />
305
611
  ```
306
612
 
613
+ ### Custom Input Label
614
+
615
+ All default inputs render their label through a single shared component, `DefaultInputLabel`. Override it once via `components.inputLabel` to restyle every field label at once. It receives `{ label, required, htmlFor }` (web) and **renders nothing when the field has no label** — so the technical `name` key never leaks into the form. Each input also exposes the resolved label as `extra.InputLabel`, so custom inputs can reuse it:
616
+
617
+ ```tsx
618
+ <TreegeRenderer
619
+ flow={flow}
620
+ components={{
621
+ inputLabel: ({ label, required, htmlFor }) =>
622
+ label ? (
623
+ <label htmlFor={htmlFor} className="my-label">
624
+ {label}
625
+ {required && <span className="text-red-500"> *</span>}
626
+ </label>
627
+ ) : null,
628
+ }}
629
+ />
630
+ ```
631
+
632
+ Accessibility is preserved even without a visible label: the default inputs fall back to `aria-label={label || node.data.name}` on the control itself.
633
+
307
634
  ### Custom Validation
308
635
 
309
636
  Add custom validation logic:
310
637
 
311
638
  ```tsx
312
639
  <TreegeRenderer
313
- flows={flow}
640
+ flow={flow}
314
641
  validate={(values, visibleNodes) => {
315
642
  const errors = {};
316
643
 
@@ -363,112 +690,304 @@ Use the HTTP input type to fetch and map data from APIs:
363
690
 
364
691
  ### Global Configuration
365
692
 
366
- Configure the renderer globally using the TreegeConfigProvider:
693
+ Configure the renderer globally using the TreegeRendererProvider:
367
694
 
368
695
  ```tsx
369
- import { TreegeConfigProvider } from "treege/renderer";
696
+ import { TreegeRendererProvider } from "treege/renderer";
370
697
 
371
698
  function App() {
372
699
  return (
373
- <TreegeConfigProvider
374
- config={{
375
- language: "fr",
376
- googleApiKey: "your-google-api-key",
377
- components: {
378
- // Your custom components
379
- }
700
+ <TreegeRendererProvider
701
+ language="fr"
702
+ googleApiKey="your-google-api-key"
703
+ components={{
704
+ // Your custom components
380
705
  }}
381
706
  >
382
- <TreegeRenderer flows={flow} />
383
- </TreegeConfigProvider>
707
+ <TreegeRenderer flow={flow} />
708
+ </TreegeRendererProvider>
384
709
  );
385
710
  }
386
711
  ```
387
712
 
388
- ### Programmatic Control
713
+ ### Loading State
389
714
 
390
- Use the `useTreegeRenderer` hook for programmatic control:
715
+ When the flow is being fetched asynchronously, pass `isLoading` to render a skeleton in place of the form:
716
+
717
+ ```tsx
718
+ function App() {
719
+ const { data: flow, isPending } = useQuery(/* ... */);
720
+
721
+ return <TreegeRenderer flow={flow ?? null} isLoading={isPending} onSubmit={console.log} />;
722
+ }
723
+ ```
724
+
725
+ Customize the skeleton via `components.loadingSkeleton`:
726
+
727
+ ```tsx
728
+ <TreegeRenderer
729
+ flow={flow}
730
+ isLoading={isPending}
731
+ components={{
732
+ loadingSkeleton: () => <MyCustomSkeleton />,
733
+ }}
734
+ />
735
+ ```
736
+
737
+ ### Editing an Existing Submission
738
+
739
+ 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:
740
+
741
+ ```tsx
742
+ const handleSubmit = (values) => save(values); // e.g. { firstName: "Alice", email: "a@b.com" }
743
+
744
+ // later, to edit the saved record:
745
+ <TreegeRenderer flow={flow} initialValues={savedRecord} onSubmit={handleSubmit} />
746
+ ```
747
+
748
+ `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.
749
+
750
+ ```tsx
751
+ const { data } = useQuery(/* ... */);
752
+ <TreegeRenderer flow={flow} initialValues={data ?? {}} onSubmit={handleSubmit} />
753
+ ```
754
+
755
+ #### Pre-filling file fields
756
+
757
+ A `file` field's value is a serializable object (never a DOM `File`, so it round-trips through JSON):
758
+
759
+ ```ts
760
+ type SerializableFile = {
761
+ name: string;
762
+ size: number;
763
+ type: string;
764
+ lastModified: number;
765
+ data: string; // base64 data-URL (web) or file URI (native)
766
+ };
767
+ ```
768
+
769
+ The stored value is a single `SerializableFile` (or an array when the field is `multiple`, or `null`). Pass the same shape in `initialValues` to pre-fill a file field when editing — the renderer lists the files and lets the user remove them or add more. Only `name`/`size` are needed for display, so `data` can hold a server URL for already-uploaded files:
770
+
771
+ ```tsx
772
+ <TreegeRenderer
773
+ flow={flow}
774
+ initialValues={{
775
+ attachment: { name: "contract.pdf", size: 24576, type: "application/pdf", lastModified: 0, data: "https://cdn.example.com/contract.pdf" },
776
+ }}
777
+ onSubmit={handleSubmit}
778
+ />
779
+ ```
780
+
781
+ ### Injecting Host Data (`extraPayload`)
782
+
783
+ Use `extraPayload` to attach data owned by the host app — not by the form itself — to every submission (e.g. the logged-in user id, a tenant id). The fields are merged at the **top level** of both the `onSubmit` payload and the built-in HTTP submit body, so they ride along wherever the form data goes:
784
+
785
+ ```tsx
786
+ <TreegeRenderer flow={flow} extraPayload={{ userId }} onSubmit={handleSubmit} />
787
+ // onSubmit receives → { ...formValues, userId }
788
+ ```
789
+
790
+ Pass a **function** when the value must be read at submit time rather than captured at render — a rotating auth token, a timestamp, or a value derived from the current answers (it receives the same name-keyed values you get in `onSubmit`):
791
+
792
+ ```tsx
793
+ <TreegeRenderer flow={flow} extraPayload={() => ({ token: auth.getToken() })} />
794
+ <TreegeRenderer flow={flow} extraPayload={(values) => ({ fullName: `${values.firstName} ${values.lastName}` })} />
795
+ ```
796
+
797
+ Notes:
798
+
799
+ - The extra fields are spread **last**, so a key here intentionally overrides a same-named form field.
800
+ - It also applies to the built-in HTTP submit (`submitConfig`): the fields are merged into the request body, respecting any `payloadTemplate` shape. If the config would otherwise send no body, the extra is sent on its own — your data is never silently dropped.
801
+ - A function that returns a non-object (array / primitive) is ignored.
802
+
803
+ ### Submitting State
804
+
805
+ 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):
806
+
807
+ ```tsx
808
+ <TreegeRenderer flow={flow} isSubmitting={mutation.isPending} onSubmit={handleSubmit} />
809
+ ```
810
+
811
+ ### Multi-Step Forms
812
+
813
+ 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.
814
+
815
+ Override the default step layout via `components.step`:
816
+
817
+ ```tsx
818
+ <TreegeRenderer
819
+ flow={flow}
820
+ components={{
821
+ step: ({ label, children, canGoBack, isLastStep, canContinue, isSubmitting, onBack, onContinue }) => (
822
+ <section>
823
+ <h2>{label}</h2>
824
+ {children}
825
+ {canGoBack && <button onClick={onBack}>Back</button>}
826
+ <button disabled={!canContinue || isSubmitting} onClick={onContinue}>
827
+ {isSubmitting ? "Submitting…" : isLastStep ? "Submit" : "Continue"}
828
+ </button>
829
+ </section>
830
+ ),
831
+ }}
832
+ />
833
+ ```
834
+
835
+ 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.
836
+
837
+ #### Bridging navigation to an outer flow
838
+
839
+ 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:
840
+
841
+ ```tsx
842
+ <TreegeRenderer
843
+ flow={flow}
844
+ formId="treege-form"
845
+ onBack={() => modal.goToPreviousStep()} // Back on step 0 → previous modal step
846
+ onSubmit={handleSubmit}
847
+ />
848
+
849
+ // A submit button living outside the renderer (web): only submits on the last
850
+ // step — on earlier steps it advances, like the built-in Continue button.
851
+ <button type="submit" form="treege-form">Save</button>
852
+ ```
853
+
854
+ ### Headless / Programmatic Control
855
+
856
+ 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:
391
857
 
392
858
  ```tsx
393
859
  import { useTreegeRenderer } from "treege/renderer";
394
860
 
395
- function CustomForm() {
396
- const { values, setFieldValue, submit, reset } = useTreegeRenderer();
861
+ function CustomForm({ flow }) {
862
+ const {
863
+ formValues,
864
+ setFieldValue,
865
+ handleSubmit,
866
+ formErrors,
867
+ visibleNodes,
868
+ isSubmitting,
869
+ currentStep,
870
+ goToNextStep,
871
+ goToPreviousStep,
872
+ } = useTreegeRenderer({
873
+ flow,
874
+ onSubmit: (values) => console.log("Submitted:", values),
875
+ });
397
876
 
398
877
  return (
399
878
  <div>
400
879
  <button onClick={() => setFieldValue("email", "test@example.com")}>
401
880
  Prefill Email
402
881
  </button>
403
- <button onClick={submit}>Submit</button>
404
- <button onClick={reset}>Reset</button>
882
+ <button onClick={handleSubmit} disabled={isSubmitting}>
883
+ Submit
884
+ </button>
405
885
  </div>
406
886
  );
407
887
  }
408
888
  ```
409
889
 
890
+ > The `useTreegeRenderer` return type is exported as `UseTreegeRendererReturn` for TypeScript consumers building custom components.
891
+
410
892
  ## Examples
411
893
 
412
894
  Check out the `/example` directory for complete examples:
413
895
 
414
896
  ```bash
415
- # Run the example app
416
- bun example
897
+ # Run the web example app (Vite, opens /example)
898
+ bun run example
899
+
900
+ # Run the React Native example app (Expo)
901
+ bun run example:native
417
902
  ```
418
903
 
904
+ ### Available Example URLs
905
+
906
+ Once the development server is running, you can access these examples:
907
+
908
+ - **Default Example**: [http://localhost:5173/](http://localhost:5173/)
909
+ - Basic demonstration of Treege functionality
910
+
911
+ - **Demo Example**: [http://localhost:5173/example](http://localhost:5173/example)
912
+ - Full featured demo showcasing the library capabilities
913
+
914
+ - **All Inputs Example**: [http://localhost:5173/example-all-inputs](http://localhost:5173/example-all-inputs)
915
+ - Comprehensive showcase of all 16 input types
916
+
917
+ - **Custom Input Example**: [http://localhost:5173/example-custom-input](http://localhost:5173/example-custom-input)
918
+ - Demonstrates how to create and integrate custom input components
919
+
920
+ - **TreegeRendererProvider Example**: [http://localhost:5173/example-treege-renderer-provider](http://localhost:5173/example-treege-renderer-provider)
921
+ - Shows global configuration with TreegeRendererProvider
922
+
419
923
  ## API Reference
420
924
 
421
925
  ### TreegeEditor Props
422
926
 
423
- | Prop | Type | Default | Description |
424
- |------------|------------------------|----------|-----------------------------|
425
- | `flow` | `Flow \| null` | `null` | Initial decision tree |
426
- | `onSave` | `(flow: Flow) => void` | - | Callback when tree is saved |
427
- | `language` | `string` | `"en"` | UI language |
428
- | `theme` | `"light" \| "dark"` | `"dark"` | Editor theme |
927
+ | Prop | Type | Default | Description |
928
+ |-------------------|------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
929
+ | `flow` | `Flow \| null` | `null` | Initial decision tree |
930
+ | `onSave` | `(flow: Flow) => void` | - | Callback when the user saves the tree. The **Save button is only rendered when this prop is provided**, and is no longer disabled on an empty canvas (so a cleared flow can be saved) |
931
+ | `onChange` | `(flow: Flow) => void` | - | Called (debounced ~150 ms) on every canvas change with the current flow. Use it for **live preview / autosave**. Unlike `onSave` it isn't gated on having input nodes, so it also reports an emptied canvas after Clear, and it does **not** strip sensitive headers (live consumers need the real flow) |
932
+ | `onExportJson` | `() => { nodes: Node[]; edges: Edge[] }` | - | Callback for exporting JSON data |
933
+ | `language` | `string` | `"en"` | UI language |
934
+ | `theme` | `"light" \| "dark"` | `"dark"` | Editor theme |
935
+ | `aiConfig` | `AIConfig` | - | AI configuration for tree generation (see [AI Generation](./AI_GENERATION.md)) |
936
+ | `className` | `string` | - | Additional CSS class names for custom styling |
937
+ | `extraMenuItems` | `ExtraMenuItem[]` | - | Extra entries appended to the actions panel "more" dropdown |
938
+ | `openApi` | `OpenApiDocument \| string` | - | OpenAPI 3.x source used to power URL/route suggestions and the Authorize flow. Accepts a pre-parsed document or a URL string (the editor fetches it on mount and toasts on failure) |
939
+ | `baseUrl` | `string` | - | Base URL the tree runs against. HTTP/options-source urls are stored relative to it, shown as a read-only prefix, and used to resolve the "Detect fields" probe. Pass the same value as `TreegeRenderer`'s `baseUrl` |
940
+ | `headers` | `HttpHeaders` | - | Global HTTP headers applied to in-editor requests (e.g. the "Detect fields" button). Pass the same value you give to `TreegeRenderer` so editor previews use the same auth/headers as runtime |
941
+ | `onAuthorize` | `(headers: HttpHeaders) => void` | - | Called when the user submits the Authorize dialog. Forward the resulting headers to `TreegeRenderer` (or `TreegeRendererProvider`) so every form request is authenticated |
942
+ | `onHeadersChange` | `(headers: HttpHeaders) => void` | - | Called when the user edits headers in the built-in "Global headers" dialog. The component is controlled — update your `headers` state in response and pass the new object back via the `headers` prop |
429
943
 
430
944
  ### TreegeRenderer Props
431
945
 
432
- | Prop | Type | Default | Description |
433
- |------------------|---------------------------------------------|--------------|----------------------------|
434
- | `flows` | `Flow \| null` | - | Decision tree to render |
435
- | `onSubmit` | `(values: FormValues) => void` | - | Form submission handler |
436
- | `onChange` | `(values: FormValues) => void` | - | Form change handler |
437
- | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
438
- | `initialValues` | `FormValues` | `{}` | Initial form values |
439
- | `components` | `RendererComponents` | - | Custom component overrides |
440
- | `language` | `string` | `"en"` | UI language |
441
- | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
442
- | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
443
- | `googleApiKey` | `string` | - | API key for address input |
946
+ | Prop | Type | Default | Description |
947
+ |------------------|-------------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
948
+ | `flow` | `Flow \| null` | - | Decision tree to render |
949
+ | `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
950
+ | `extraPayload` | `Record<string, unknown> \| (values) => Record` | - | Host-owned fields merged into every submission — the `onSubmit` payload **and** the HTTP submit body. Object or function of the current values (see below) |
951
+ | `onChange` | `(values: FormValues) => void` | - | Form change handler |
952
+ | `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
953
+ | `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) |
954
+ | `components` | `TreegeRendererComponents` | - | Custom component overrides |
955
+ | `language` | `string` | `"en"` | UI language |
956
+ | `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
957
+ | `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
958
+ | `googleApiKey` | `string` | - | API key for address input |
959
+ | `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
960
+ | `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form (see below) |
961
+ | `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` |
962
+ | `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 |
963
+ | `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 |
964
+ | `className` | `string` | - | Additional CSS class names for custom styling |
444
965
 
445
966
  ## Development
446
967
 
447
968
  ```bash
448
969
  # Install dependencies
449
- yarn install
970
+ bun install
450
971
 
451
972
  # Start dev server
452
- yarn dev
973
+ bun run dev
453
974
 
454
975
  # Build library
455
- yarn build
976
+ bun run build
456
977
 
457
978
  # Run linter and type check
458
- yarn lint
979
+ bun run lint
459
980
 
460
981
  # Preview build
461
- yarn preview
982
+ bun run preview
462
983
  ```
463
984
 
464
985
  ## Tech Stack
465
986
 
466
- - **React** 18/19 - UI library
987
+ - **React** - UI library
467
988
  - **TypeScript** - Type safety
468
989
  - **TailwindCSS** 4 - Styling
469
990
  - **ReactFlow** - Node-based UI
470
- - **Radix UI** - Accessible components
471
- - **Zustand** - State management
472
991
  - **Vite** - Build tool
473
992
 
474
993
  ## Contributing
@@ -477,13 +996,13 @@ Contributions are welcome! Please feel free to submit a Pull Request.
477
996
 
478
997
  ## License
479
998
 
480
- ISC
999
+ MIT
481
1000
 
482
1001
  ## Credits
483
1002
 
484
- Created and maintained by [Mickaël Austoni](https://github.com/Tracktor)
1003
+ Created and maintained by [Mickaël Austoni](https://github.com/MickaelAustoni)
485
1004
 
486
1005
  ## Support
487
1006
 
488
- - [GitHub Issues](https://github.com/Tracktor/treege/issues)
489
- - [Repository](https://github.com/Tracktor/treege)
1007
+ - [GitHub Issues](https://github.com/MickaelAustoni/treege/issues)
1008
+ - [Repository](https://github.com/MickaelAustoni/treege)