treege 3.0.0-beta.8 → 3.0.0-beta.81
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/LICENSE +18 -12
- package/README.md +474 -79
- package/dist/DefaultSubmitButton-Dg9GPvh-.js +1853 -0
- package/dist/ThemeContext-BgTIhoK6.js +985 -0
- package/dist/editor/components/input/ComboboxWithCreate.d.ts +2 -1
- package/dist/editor/components/styles/EditorStyles.d.ts +2 -0
- package/dist/editor/constants/defaultNode.d.ts +1 -1
- package/dist/editor/constants/edgeTypes.d.ts +3 -2
- package/dist/editor/constants/inputTypeIcons.d.ts +3 -0
- package/dist/editor/constants/nodeSpacing.d.ts +25 -0
- package/dist/editor/constants/nodeTypes.d.ts +4 -5
- package/dist/editor/context/OpenApiContext.d.ts +79 -0
- package/dist/editor/context/TreegeEditorRuntimeProvider.d.ts +78 -0
- package/dist/editor/features/TreegeEditor/TreegeEditor.d.ts +1 -1
- package/dist/editor/features/TreegeEditor/controls/MiniMapControl.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/dialogs/AuthorizeDialog.d.ts +20 -0
- package/dist/editor/features/TreegeEditor/dialogs/ChangeNodeTypeDialog.d.ts +2 -0
- package/dist/editor/features/TreegeEditor/dialogs/DeleteNodeDialog.d.ts +2 -0
- package/dist/editor/features/TreegeEditor/dialogs/HeadersDialog.d.ts +19 -0
- package/dist/editor/features/TreegeEditor/dialogs/OpenApiDialog.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/edges/ConditionalEdge.d.ts +2 -2
- package/dist/editor/features/TreegeEditor/edges/DefaultEdge.d.ts +3 -0
- package/dist/editor/features/TreegeEditor/forms/HttpConfigForm.d.ts +4 -1
- package/dist/editor/features/TreegeEditor/forms/JsonTemplateEditor.d.ts +13 -0
- package/dist/editor/features/TreegeEditor/forms/OptionsMappingFields.d.ts +34 -0
- package/dist/editor/features/TreegeEditor/forms/OptionsSourceForm.d.ts +7 -0
- package/dist/editor/features/TreegeEditor/forms/SensitiveHeaderWarning.d.ts +13 -0
- package/dist/editor/features/TreegeEditor/forms/SubmitConfigForm.d.ts +7 -0
- package/dist/editor/features/TreegeEditor/inputs/ApiUrlCombobox.d.ts +20 -0
- package/dist/editor/features/TreegeEditor/inputs/ComboboxPattern.d.ts +2 -1
- package/dist/editor/features/TreegeEditor/inputs/DefaultFileValueField.d.ts +14 -0
- package/dist/editor/features/TreegeEditor/inputs/OptionImageField.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/inputs/SelectNodeGroup.d.ts +22 -1
- package/dist/editor/features/TreegeEditor/layout/AutoLayout.d.ts +15 -0
- package/dist/editor/features/TreegeEditor/listeners/FlowChangeEmitter.d.ts +19 -0
- package/dist/editor/features/TreegeEditor/nodes/TreegeNode.d.ts +5 -0
- package/dist/editor/features/TreegeEditor/nodes/components/BottomHandleDropdown.d.ts +25 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeGroupBadge.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeImage.d.ts +5 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeImageButton.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeInputPreview.d.ts +12 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeLabelInput.d.ts +10 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeMoreMenu.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeRequiredButton.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeStackOrderButtons.d.ts +6 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeTypeBadge.d.ts +7 -0
- package/dist/editor/features/TreegeEditor/nodes/components/NodeTypePickerMenuContent.d.ts +12 -0
- package/dist/editor/features/TreegeEditor/nodes/layout/NodeWrapper.d.ts +4 -2
- package/dist/editor/features/TreegeEditor/panel/AIGeneratorDialog.d.ts +16 -0
- package/dist/editor/features/TreegeEditor/panel/ActionsPanel.d.ts +7 -2
- package/dist/editor/features/TreegeEditor/panel/MultiSelectionPanel.d.ts +7 -0
- package/dist/editor/hooks/useAvailableParentFields.d.ts +13 -0
- package/dist/editor/hooks/useFlowActions.d.ts +6 -2
- package/dist/editor/hooks/useFlowConnections.d.ts +14 -0
- package/dist/editor/hooks/useFlowContent.d.ts +16 -0
- package/dist/editor/hooks/useHistoryStore.d.ts +26 -0
- package/dist/editor/hooks/useIsStackedEdge.d.ts +8 -0
- package/dist/editor/hooks/useKeyValueRows.d.ts +15 -0
- package/dist/editor/hooks/useNodesSelection.d.ts +5 -5
- package/dist/editor/hooks/useStackPosition.d.ts +14 -0
- package/dist/editor/hooks/useTranslate.d.ts +1 -1
- package/dist/editor/hooks/useUndoRedo.d.ts +31 -0
- package/dist/editor/types/ai.d.ts +65 -0
- package/dist/editor/types/editor.d.ts +106 -10
- package/dist/editor/types/openapi.d.ts +106 -0
- package/dist/editor/utils/aiFlowGenerator.d.ts +5 -0
- package/dist/editor/utils/cleanEmptyData.d.ts +18 -0
- package/dist/editor/utils/cleanNodeConfig.d.ts +5 -0
- package/dist/editor/utils/dagreLayout.d.ts +8 -0
- package/dist/editor/utils/edge.d.ts +50 -0
- package/dist/editor/utils/groupColor.d.ts +14 -0
- package/dist/editor/utils/image.d.ts +7 -0
- package/dist/editor/utils/inputTypeIcon.d.ts +6 -0
- package/dist/editor/utils/jsonBindTarget.d.ts +15 -0
- package/dist/editor/utils/openApiPayload.d.ts +12 -0
- package/dist/editor/utils/openapi.d.ts +35 -0
- package/dist/editor/utils/sensitiveHeaders.d.ts +20 -0
- package/dist/editor/utils/stackPositionIndex.d.ts +9 -0
- package/dist/editor-h20-TVM8.js +6575 -0
- package/dist/editor.js +3 -7
- package/dist/main.js +6 -52
- package/dist/renderer/context/TreegeRenderRuntimeProvider.d.ts +135 -0
- package/dist/renderer/context/TreegeRendererProvider.d.ts +15 -0
- package/dist/renderer/features/TreegeRenderer/native/TreegeRenderer.d.ts +19 -11
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultFormWrapper.d.ts +7 -7
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputLabel.d.ts +10 -0
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputWrapper.d.ts +9 -0
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultInputs.d.ts +20 -15
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultLoadingSkeleton.d.ts +8 -0
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultStep.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultSubmitButton.d.ts +9 -7
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultSubmitButtonWrapper.d.ts +11 -0
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultUI.d.ts +8 -7
- package/dist/renderer/features/TreegeRenderer/native/components/DependencyHint.d.ts +15 -0
- package/dist/renderer/features/TreegeRenderer/native/components/OptionItemContent.d.ts +17 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultAddressInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultAutocompleteInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultCheckboxInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultDateInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultDateRangeInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultFileInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultHiddenInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultHttpInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultNumberInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultPasswordInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultRadioInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSelectInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSubmitInput.d.ts +11 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultSwitchInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTextInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTextareaInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTimeInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/native/components/inputs/DefaultTimeRangeInput.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/useTreegeRenderer.d.ts +97 -24
- package/dist/renderer/features/TreegeRenderer/web/TreegeRenderer.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultFormWrapper.d.ts +3 -2
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultInputLabel.d.ts +9 -0
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultInputWrapper.d.ts +9 -0
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultLoadingSkeleton.d.ts +7 -0
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultStep.d.ts +3 -0
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultSubmitButton.d.ts +5 -1
- package/dist/renderer/features/TreegeRenderer/web/components/DependencyHint.d.ts +22 -0
- package/dist/renderer/features/TreegeRenderer/web/components/OptionItemContent.d.ts +17 -0
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultAddressInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultAutocompleteInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultCheckboxInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultDateInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultDateRangeInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultFileInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultHiddenInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultHttpInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultNumberInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultPasswordInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultRadioInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSelectInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSubmitInput.d.ts +11 -0
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultSwitchInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTextAreaInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTextInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTimeInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/inputs/DefaultTimeRangeInput.d.ts +1 -1
- package/dist/renderer/features/TreegeRenderer/web/components/styles/RendererStyles.d.ts +2 -0
- package/dist/renderer/hooks/useInputOptions.d.ts +28 -0
- package/dist/renderer/hooks/useRenderNode.d.ts +62 -0
- package/dist/renderer/hooks/useSubmitHandler.d.ts +36 -0
- package/dist/renderer/hooks/useTranslate.d.ts +7 -5
- package/dist/renderer/index.d.ts +5 -2
- package/dist/renderer/index.native.d.ts +20 -0
- package/dist/renderer/types/renderer.d.ts +316 -42
- package/dist/renderer/utils/file.d.ts +11 -10
- package/dist/renderer/utils/flow.d.ts +1 -18
- package/dist/renderer/utils/form.d.ts +54 -2
- package/dist/renderer/utils/http.d.ts +177 -0
- package/dist/renderer/utils/jsonTemplate.d.ts +30 -0
- package/dist/renderer/utils/node.d.ts +29 -1
- package/dist/renderer/utils/sanitize.d.ts +85 -0
- package/dist/renderer/utils/sanitize.native.d.ts +69 -0
- package/dist/renderer/utils/step.d.ts +27 -0
- package/dist/renderer/utils/submit.d.ts +49 -0
- package/dist/renderer/utils/templateDependencies.d.ts +17 -0
- package/dist/renderer-DI6nF4St.js +256 -0
- package/dist/renderer-native.d.ts +2 -0
- package/dist/renderer-native.js +3704 -0
- package/dist/renderer.js +5 -45
- package/dist/shared/components/ui/badge.d.ts +2 -2
- package/dist/shared/components/ui/button.d.ts +3 -3
- package/dist/shared/components/ui/collapsible.d.ts +1 -1
- package/dist/shared/components/ui/command.d.ts +1 -1
- package/dist/shared/components/ui/dropdown-menu.d.ts +1 -1
- package/dist/shared/components/ui/field.d.ts +24 -0
- package/dist/shared/components/ui/form.d.ts +1 -1
- package/dist/shared/components/ui/item.d.ts +23 -0
- package/dist/shared/components/ui/popover.d.ts +10 -2
- package/dist/shared/components/ui/select.d.ts +3 -1
- package/dist/shared/components/ui/sheet.d.ts +1 -1
- package/dist/shared/components/ui/skeleton.d.ts +3 -0
- package/dist/shared/components/ui/toggle-group.d.ts +7 -0
- package/dist/shared/components/ui/toggle.d.ts +9 -0
- package/dist/shared/components/ui/tooltip.d.ts +1 -1
- package/dist/shared/constants/colors.d.ts +45 -0
- package/dist/shared/constants/inputType.d.ts +6 -0
- package/dist/shared/constants/node.d.ts +0 -1
- package/dist/shared/context/PortalContainerContext.d.ts +5 -0
- package/dist/shared/context/ThemeContext.d.ts +2 -0
- package/dist/shared/context/ThemeContext.native.d.ts +22 -0
- package/dist/shared/hooks/useMediaQuery.d.ts +12 -0
- package/dist/shared/hooks/useThemeColors.d.ts +37 -0
- package/dist/shared/locales/ar.json.d.ts +259 -19
- package/dist/shared/locales/de.json.d.ts +260 -20
- package/dist/shared/locales/en.json.d.ts +261 -21
- package/dist/shared/locales/es.json.d.ts +260 -20
- package/dist/shared/locales/fr.json.d.ts +260 -20
- package/dist/shared/locales/it.json.d.ts +260 -20
- package/dist/shared/locales/pt.json.d.ts +260 -20
- package/dist/shared/types/edge.d.ts +6 -0
- package/dist/shared/types/file.d.ts +14 -0
- package/dist/shared/types/node.d.ts +155 -19
- package/dist/shared/utils/httpRecord.d.ts +20 -0
- package/dist/shared/utils/inputTypeGuards.d.ts +7 -0
- package/dist/shared/utils/nodeTypeGuards.d.ts +1 -6
- package/dist/shared/utils/normalizeLabel.d.ts +21 -0
- package/dist/useRenderNode-B1sfwbia.js +527 -0
- package/package.json +54 -22
- package/dist/ThemeContext-BIvs8Kw-.js +0 -758
- package/dist/TreegeEditor-Lv5Tn9_F.js +0 -2152
- package/dist/TreegeRenderer-D3EvsEfJ.js +0 -1413
- package/dist/editor/context/TreegeEditorContext.d.ts +0 -12
- package/dist/editor/features/TreegeEditor/forms/FlowNodeForm.d.ts +0 -2
- package/dist/editor/features/TreegeEditor/inputs/SelectInputType.d.ts +0 -7
- package/dist/editor/features/TreegeEditor/nodes/FlowNode.d.ts +0 -6
- package/dist/editor/features/TreegeEditor/nodes/GroupNode.d.ts +0 -6
- package/dist/editor/features/TreegeEditor/nodes/InputNode.d.ts +0 -6
- package/dist/editor/features/TreegeEditor/nodes/UINode.d.ts +0 -6
- package/dist/editor/hooks/useEdgesSelection.d.ts +0 -11
- package/dist/renderer/context/TreegeConfigContext.d.ts +0 -39
- package/dist/renderer/context/TreegeRendererContext.d.ts +0 -25
- package/dist/renderer/features/TreegeRenderer/native/components/DefaultGroup.d.ts +0 -7
- package/dist/renderer/features/TreegeRenderer/web/components/DefaultGroup.d.ts +0 -6
- /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>
|
|
5
|
+
<p><strong>Building complex, dynamic forms has never been this simple</strong></p>
|
|
6
6
|
|
|
7
7
|
[](https://badge.fury.io/js/treege)
|
|
8
|
-
[](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
|
|
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
|
-
- **
|
|
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,11 +39,17 @@ 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
|
-
- **
|
|
44
|
-
- **
|
|
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
|
|
51
|
+
- **Fully Customizable**: Override any component (form, inputs, inputLabel, ui, step, submitButton, submitButtonWrapper, loadingSkeleton)
|
|
52
|
+
- **Optional Dependencies**: Graceful degradation when optional packages like `react-native-document-picker` aren't installed
|
|
45
53
|
- **Theme Support**: Dark/light mode out of the box
|
|
46
54
|
- **Google API Integration**: Address autocomplete support
|
|
47
55
|
|
|
@@ -54,6 +62,9 @@ Treege is a modern React library for creating and rendering interactive decision
|
|
|
54
62
|
## Installation
|
|
55
63
|
|
|
56
64
|
```bash
|
|
65
|
+
# bun
|
|
66
|
+
bun add treege
|
|
67
|
+
|
|
57
68
|
# npm
|
|
58
69
|
npm install treege
|
|
59
70
|
|
|
@@ -62,9 +73,6 @@ pnpm add treege
|
|
|
62
73
|
|
|
63
74
|
# yarn
|
|
64
75
|
yarn add treege
|
|
65
|
-
|
|
66
|
-
# bun
|
|
67
|
-
bun add treege
|
|
68
76
|
```
|
|
69
77
|
|
|
70
78
|
## Quick Start
|
|
@@ -125,7 +133,7 @@ function App() {
|
|
|
125
133
|
|
|
126
134
|
return (
|
|
127
135
|
<TreegeRenderer
|
|
128
|
-
|
|
136
|
+
flow={flow}
|
|
129
137
|
onSubmit={handleSubmit}
|
|
130
138
|
/>
|
|
131
139
|
);
|
|
@@ -152,16 +160,38 @@ function App() {
|
|
|
152
160
|
{mode === "edit" ? (
|
|
153
161
|
<TreegeEditor flow={flow} onSave={setFlow} />
|
|
154
162
|
) : (
|
|
155
|
-
<TreegeRenderer
|
|
163
|
+
<TreegeRenderer flow={flow} onSubmit={console.log} />
|
|
156
164
|
)}
|
|
157
165
|
</div>
|
|
158
166
|
);
|
|
159
167
|
}
|
|
160
168
|
```
|
|
161
169
|
|
|
170
|
+
### Live Preview (Editor → Renderer)
|
|
171
|
+
|
|
172
|
+
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:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { TreegeEditor } from "treege/editor";
|
|
176
|
+
import { TreegeRenderer } from "treege/renderer";
|
|
177
|
+
import { useState } from "react";
|
|
178
|
+
import type { Flow } from "treege";
|
|
179
|
+
|
|
180
|
+
function App() {
|
|
181
|
+
const [flow, setFlow] = useState<Flow | null>(null);
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<div style={{ display: "flex" }}>
|
|
185
|
+
<TreegeEditor onChange={setFlow} /> {/* live, no Save button */}
|
|
186
|
+
<TreegeRenderer flow={flow} onSubmit={console.log} />
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
162
192
|
## Module Structure
|
|
163
193
|
|
|
164
|
-
Treege provides
|
|
194
|
+
Treege provides multiple import paths for optimal bundle size:
|
|
165
195
|
|
|
166
196
|
```tsx
|
|
167
197
|
// Import everything (editor + renderer + types)
|
|
@@ -170,25 +200,187 @@ import { TreegeEditor, TreegeRenderer } from "treege";
|
|
|
170
200
|
// Import only the editor
|
|
171
201
|
import { TreegeEditor } from "treege/editor";
|
|
172
202
|
|
|
173
|
-
// Import only the renderer
|
|
203
|
+
// Import only the web renderer
|
|
174
204
|
import { TreegeRenderer } from "treege/renderer";
|
|
205
|
+
|
|
206
|
+
// Import only the React Native renderer
|
|
207
|
+
import { TreegeRenderer } from "treege/renderer-native";
|
|
175
208
|
```
|
|
176
209
|
|
|
177
|
-
##
|
|
210
|
+
## React Native Support
|
|
211
|
+
|
|
212
|
+
Treege 3.0 includes full React Native support with a dedicated renderer implementation.
|
|
213
|
+
|
|
214
|
+
### Installation for React Native
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Install Treege
|
|
218
|
+
npm install treege
|
|
219
|
+
|
|
220
|
+
# Install peer dependencies
|
|
221
|
+
npm install react-native
|
|
178
222
|
|
|
179
|
-
|
|
180
|
-
|
|
223
|
+
# Optional: Install for file input support
|
|
224
|
+
npm install react-native-document-picker
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Basic Usage
|
|
181
228
|
|
|
182
229
|
```tsx
|
|
183
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
230
|
+
import { TreegeRenderer } from "treege/renderer-native";
|
|
231
|
+
import type { Flow, FormValues } from "treege";
|
|
232
|
+
|
|
233
|
+
function App() {
|
|
234
|
+
const flow: Flow = {
|
|
235
|
+
id: "flow-1",
|
|
236
|
+
nodes: [
|
|
237
|
+
{
|
|
238
|
+
id: "name",
|
|
239
|
+
type: "input",
|
|
240
|
+
data: {
|
|
241
|
+
type: "text",
|
|
242
|
+
name: "fullName",
|
|
243
|
+
label: "Full Name",
|
|
244
|
+
required: true
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
id: "email",
|
|
249
|
+
type: "input",
|
|
250
|
+
data: {
|
|
251
|
+
type: "text",
|
|
252
|
+
name: "email",
|
|
253
|
+
label: "Email",
|
|
254
|
+
required: true,
|
|
255
|
+
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
edges: []
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const handleSubmit = (values: FormValues) => {
|
|
263
|
+
console.log("Form submitted:", values);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
<TreegeRenderer
|
|
268
|
+
flow={flow}
|
|
269
|
+
onSubmit={handleSubmit}
|
|
270
|
+
/>
|
|
271
|
+
);
|
|
189
272
|
}
|
|
190
273
|
```
|
|
191
274
|
|
|
275
|
+
### Custom Styling
|
|
276
|
+
|
|
277
|
+
You can customize the appearance using the `style` and `contentContainerStyle` props:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
<TreegeRenderer
|
|
281
|
+
flow={flow}
|
|
282
|
+
onSubmit={handleSubmit}
|
|
283
|
+
style={{ flex: 1, backgroundColor: "#f5f5f5" }}
|
|
284
|
+
contentContainerStyle={{ padding: 20 }}
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Custom Components
|
|
289
|
+
|
|
290
|
+
Override default components with your own React Native components.
|
|
291
|
+
|
|
292
|
+
Each input renderer is a **React component** receiving a single props object with two keys:
|
|
293
|
+
|
|
294
|
+
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.
|
|
295
|
+
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).
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
import { Text, TextInput, View } from "react-native";
|
|
299
|
+
import { TreegeRenderer } from "treege/renderer-native";
|
|
300
|
+
|
|
301
|
+
const CustomTextInput = ({ field, extra }) => {
|
|
302
|
+
return (
|
|
303
|
+
<View style={{ marginBottom: 16 }}>
|
|
304
|
+
<Text style={{ fontSize: 14, marginBottom: 4 }}>{extra.label}</Text>
|
|
305
|
+
<TextInput
|
|
306
|
+
value={field.value}
|
|
307
|
+
placeholder={field.placeholder}
|
|
308
|
+
onChangeText={extra.setValue}
|
|
309
|
+
style={{
|
|
310
|
+
borderWidth: 1,
|
|
311
|
+
borderColor: extra.error ? "red" : "#ccc",
|
|
312
|
+
padding: 10,
|
|
313
|
+
borderRadius: 8
|
|
314
|
+
}}
|
|
315
|
+
/>
|
|
316
|
+
{extra.error && <Text style={{ color: "red", fontSize: 12 }}>{extra.error}</Text>}
|
|
317
|
+
{extra.missingDependencies.length > 0 && (
|
|
318
|
+
<Text style={{ color: "#b45309", fontSize: 12 }}>
|
|
319
|
+
Please fill in first: {extra.missingDependencies.map((d) => d.label).join(", ")}
|
|
320
|
+
</Text>
|
|
321
|
+
)}
|
|
322
|
+
</View>
|
|
323
|
+
);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
<TreegeRenderer
|
|
327
|
+
flow={flow}
|
|
328
|
+
components={{
|
|
329
|
+
inputs: {
|
|
330
|
+
text: CustomTextInput
|
|
331
|
+
}
|
|
332
|
+
}}
|
|
333
|
+
/>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Supported Input Types
|
|
337
|
+
|
|
338
|
+
The React Native renderer includes default implementations for all input types:
|
|
339
|
+
|
|
340
|
+
**Fully Implemented (Vanilla React Native)**:
|
|
341
|
+
- `text`, `number`, `textarea`, `password`
|
|
342
|
+
- `checkbox`, `switch`, `hidden`
|
|
343
|
+
|
|
344
|
+
**With Optional Dependencies** (gracefully degrades if not installed):
|
|
345
|
+
- `file` - Requires [react-native-document-picker](https://github.com/rnmods/react-native-document-picker) (optional)
|
|
346
|
+
|
|
347
|
+
**Requires Custom Implementation** (placeholder provided):
|
|
348
|
+
- `select`, `radio`, `autocomplete`
|
|
349
|
+
- `date`, `daterange`, `time`, `timerange`
|
|
350
|
+
- `address`, `http`
|
|
351
|
+
|
|
352
|
+
You can implement these inputs using popular React Native libraries:
|
|
353
|
+
- [@react-native-picker/picker](https://github.com/react-native-picker/picker) for `select` and `radio`
|
|
354
|
+
- [react-native-date-picker](https://github.com/henninghall/react-native-date-picker) for `date` and `time` inputs
|
|
355
|
+
- [@react-native-community/google-places-autocomplete](https://github.com/FaridSafi/react-native-google-places-autocomplete) for `address`
|
|
356
|
+
|
|
357
|
+
### API Reference
|
|
358
|
+
|
|
359
|
+
The React Native renderer shares the same API as the web renderer, with some platform-specific props:
|
|
360
|
+
|
|
361
|
+
| Prop | Type | Default | Description |
|
|
362
|
+
|-------------------------|---------------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------|
|
|
363
|
+
| `flow` | `Flow \| null` | - | Decision tree to render |
|
|
364
|
+
| `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
|
|
365
|
+
| `onChange` | `(values: FormValues) => void` | - | Form change handler |
|
|
366
|
+
| `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
|
|
367
|
+
| `initialValues` | `FormValues` | `{}` | Pre-fill values to edit a record. Accepts `node.id` or name keys; reactive (re-seeds if it changes after mount) |
|
|
368
|
+
| `components` | `TreegeRendererComponents` | - | Custom component overrides |
|
|
369
|
+
| `language` | `string` | `"en"` | UI language |
|
|
370
|
+
| `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
|
|
371
|
+
| `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
|
|
372
|
+
| `googleApiKey` | `string` | - | API key for address input |
|
|
373
|
+
| `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
|
|
374
|
+
| `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form |
|
|
375
|
+
| `isSubmitting` | `boolean` | `false` | Force the submit/continue button into its loading state (OR-ed with internal state) |
|
|
376
|
+
| `onBack` | `() => void` | - | Called when Back is clicked on the first step; bridges to an outer flow |
|
|
377
|
+
| `style` | `ViewStyle` | - | ScrollView style (RN only) |
|
|
378
|
+
| `contentContainerStyle` | `ViewStyle` | - | Content container style (RN) |
|
|
379
|
+
|
|
380
|
+
## Node Types
|
|
381
|
+
|
|
382
|
+
Treege has three node types: `input`, `ui`, and `group`. Navigation is automatic — group nodes drive step navigation and conditional edges drive branching.
|
|
383
|
+
|
|
192
384
|
### Input Node
|
|
193
385
|
Form input with validation, patterns, and conditional logic.
|
|
194
386
|
|
|
@@ -209,7 +401,7 @@ Form input with validation, patterns, and conditional logic.
|
|
|
209
401
|
Supported input types: `text`, `number`, `textarea`, `password`, `select`, `radio`, `checkbox`, `switch`, `autocomplete`, `date`, `daterange`, `time`, `timerange`, `file`, `address`, `http`, `hidden`
|
|
210
402
|
|
|
211
403
|
### Group Node
|
|
212
|
-
Container for organizing multiple nodes together.
|
|
404
|
+
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
405
|
|
|
214
406
|
```tsx
|
|
215
407
|
{
|
|
@@ -239,7 +431,7 @@ Supported UI types:
|
|
|
239
431
|
|
|
240
432
|
## Conditional Edges
|
|
241
433
|
|
|
242
|
-
Create dynamic
|
|
434
|
+
Create dynamic flow with conditional logic:
|
|
243
435
|
|
|
244
436
|
```tsx
|
|
245
437
|
{
|
|
@@ -285,17 +477,30 @@ Treege supports multiple languages out of the box:
|
|
|
285
477
|
|
|
286
478
|
### Custom Input Components
|
|
287
479
|
|
|
288
|
-
Override default input renderers with your own
|
|
480
|
+
Override default input renderers with your own. A renderer is a React component
|
|
481
|
+
receiving a single props object: `field` (DOM-safe props, spreadable onto an
|
|
482
|
+
element) and `extra` (`setValue`, `error`, `label`, `helperText`, `node`,
|
|
483
|
+
`InputLabel`, `missingDependencies`).
|
|
289
484
|
|
|
290
485
|
```tsx
|
|
291
486
|
import { TreegeRenderer } from "treege/renderer";
|
|
292
487
|
|
|
293
|
-
const CustomTextInput = ({
|
|
294
|
-
return
|
|
488
|
+
const CustomTextInput = ({ field, extra }) => {
|
|
489
|
+
return (
|
|
490
|
+
<label>
|
|
491
|
+
{extra.label}
|
|
492
|
+
<input
|
|
493
|
+
{...field}
|
|
494
|
+
className="my-custom-input"
|
|
495
|
+
onChange={(e) => extra.setValue(e.target.value)}
|
|
496
|
+
/>
|
|
497
|
+
{extra.error && <span className="error">{extra.error}</span>}
|
|
498
|
+
</label>
|
|
499
|
+
);
|
|
295
500
|
};
|
|
296
501
|
|
|
297
502
|
<TreegeRenderer
|
|
298
|
-
|
|
503
|
+
flow={flow}
|
|
299
504
|
components={{
|
|
300
505
|
inputs: {
|
|
301
506
|
text: CustomTextInput
|
|
@@ -304,13 +509,34 @@ const CustomTextInput = ({ node }) => {
|
|
|
304
509
|
/>
|
|
305
510
|
```
|
|
306
511
|
|
|
512
|
+
### Custom Input Label
|
|
513
|
+
|
|
514
|
+
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:
|
|
515
|
+
|
|
516
|
+
```tsx
|
|
517
|
+
<TreegeRenderer
|
|
518
|
+
flow={flow}
|
|
519
|
+
components={{
|
|
520
|
+
inputLabel: ({ label, required, htmlFor }) =>
|
|
521
|
+
label ? (
|
|
522
|
+
<label htmlFor={htmlFor} className="my-label">
|
|
523
|
+
{label}
|
|
524
|
+
{required && <span className="text-red-500"> *</span>}
|
|
525
|
+
</label>
|
|
526
|
+
) : null,
|
|
527
|
+
}}
|
|
528
|
+
/>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Accessibility is preserved even without a visible label: the default inputs fall back to `aria-label={label || node.data.name}` on the control itself.
|
|
532
|
+
|
|
307
533
|
### Custom Validation
|
|
308
534
|
|
|
309
535
|
Add custom validation logic:
|
|
310
536
|
|
|
311
537
|
```tsx
|
|
312
538
|
<TreegeRenderer
|
|
313
|
-
|
|
539
|
+
flow={flow}
|
|
314
540
|
validate={(values, visibleNodes) => {
|
|
315
541
|
const errors = {};
|
|
316
542
|
|
|
@@ -363,112 +589,281 @@ Use the HTTP input type to fetch and map data from APIs:
|
|
|
363
589
|
|
|
364
590
|
### Global Configuration
|
|
365
591
|
|
|
366
|
-
Configure the renderer globally using the
|
|
592
|
+
Configure the renderer globally using the TreegeRendererProvider:
|
|
367
593
|
|
|
368
594
|
```tsx
|
|
369
|
-
import {
|
|
595
|
+
import { TreegeRendererProvider } from "treege/renderer";
|
|
370
596
|
|
|
371
597
|
function App() {
|
|
372
598
|
return (
|
|
373
|
-
<
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
components
|
|
378
|
-
// Your custom components
|
|
379
|
-
}
|
|
599
|
+
<TreegeRendererProvider
|
|
600
|
+
language="fr"
|
|
601
|
+
googleApiKey="your-google-api-key"
|
|
602
|
+
components={{
|
|
603
|
+
// Your custom components
|
|
380
604
|
}}
|
|
381
605
|
>
|
|
382
|
-
<TreegeRenderer
|
|
383
|
-
</
|
|
606
|
+
<TreegeRenderer flow={flow} />
|
|
607
|
+
</TreegeRendererProvider>
|
|
384
608
|
);
|
|
385
609
|
}
|
|
386
610
|
```
|
|
387
611
|
|
|
388
|
-
###
|
|
612
|
+
### Loading State
|
|
613
|
+
|
|
614
|
+
When the flow is being fetched asynchronously, pass `isLoading` to render a skeleton in place of the form:
|
|
615
|
+
|
|
616
|
+
```tsx
|
|
617
|
+
function App() {
|
|
618
|
+
const { data: flow, isPending } = useQuery(/* ... */);
|
|
619
|
+
|
|
620
|
+
return <TreegeRenderer flow={flow ?? null} isLoading={isPending} onSubmit={console.log} />;
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
Customize the skeleton via `components.loadingSkeleton`:
|
|
625
|
+
|
|
626
|
+
```tsx
|
|
627
|
+
<TreegeRenderer
|
|
628
|
+
flow={flow}
|
|
629
|
+
isLoading={isPending}
|
|
630
|
+
components={{
|
|
631
|
+
loadingSkeleton: () => <MyCustomSkeleton />,
|
|
632
|
+
}}
|
|
633
|
+
/>
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Editing an Existing Submission
|
|
637
|
+
|
|
638
|
+
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:
|
|
639
|
+
|
|
640
|
+
```tsx
|
|
641
|
+
const handleSubmit = (values) => save(values); // e.g. { firstName: "Alice", email: "a@b.com" }
|
|
642
|
+
|
|
643
|
+
// later, to edit the saved record:
|
|
644
|
+
<TreegeRenderer flow={flow} initialValues={savedRecord} onSubmit={handleSubmit} />
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
`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.
|
|
648
|
+
|
|
649
|
+
```tsx
|
|
650
|
+
const { data } = useQuery(/* ... */);
|
|
651
|
+
<TreegeRenderer flow={flow} initialValues={data ?? {}} onSubmit={handleSubmit} />
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
#### Pre-filling file fields
|
|
389
655
|
|
|
390
|
-
|
|
656
|
+
A `file` field's value is a serializable object (never a DOM `File`, so it round-trips through JSON):
|
|
657
|
+
|
|
658
|
+
```ts
|
|
659
|
+
type SerializableFile = {
|
|
660
|
+
name: string;
|
|
661
|
+
size: number;
|
|
662
|
+
type: string;
|
|
663
|
+
lastModified: number;
|
|
664
|
+
data: string; // base64 data-URL (web) or file URI (native)
|
|
665
|
+
};
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
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:
|
|
669
|
+
|
|
670
|
+
```tsx
|
|
671
|
+
<TreegeRenderer
|
|
672
|
+
flow={flow}
|
|
673
|
+
initialValues={{
|
|
674
|
+
attachment: { name: "contract.pdf", size: 24576, type: "application/pdf", lastModified: 0, data: "https://cdn.example.com/contract.pdf" },
|
|
675
|
+
}}
|
|
676
|
+
onSubmit={handleSubmit}
|
|
677
|
+
/>
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Submitting State
|
|
681
|
+
|
|
682
|
+
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):
|
|
683
|
+
|
|
684
|
+
```tsx
|
|
685
|
+
<TreegeRenderer flow={flow} isSubmitting={mutation.isPending} onSubmit={handleSubmit} />
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Multi-Step Forms
|
|
689
|
+
|
|
690
|
+
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.
|
|
691
|
+
|
|
692
|
+
Override the default step layout via `components.step`:
|
|
693
|
+
|
|
694
|
+
```tsx
|
|
695
|
+
<TreegeRenderer
|
|
696
|
+
flow={flow}
|
|
697
|
+
components={{
|
|
698
|
+
step: ({ label, children, canGoBack, isLastStep, canContinue, isSubmitting, onBack, onContinue }) => (
|
|
699
|
+
<section>
|
|
700
|
+
<h2>{label}</h2>
|
|
701
|
+
{children}
|
|
702
|
+
{canGoBack && <button onClick={onBack}>Back</button>}
|
|
703
|
+
<button disabled={!canContinue || isSubmitting} onClick={onContinue}>
|
|
704
|
+
{isSubmitting ? "Submitting…" : isLastStep ? "Submit" : "Continue"}
|
|
705
|
+
</button>
|
|
706
|
+
</section>
|
|
707
|
+
),
|
|
708
|
+
}}
|
|
709
|
+
/>
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
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.
|
|
713
|
+
|
|
714
|
+
#### Bridging navigation to an outer flow
|
|
715
|
+
|
|
716
|
+
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:
|
|
717
|
+
|
|
718
|
+
```tsx
|
|
719
|
+
<TreegeRenderer
|
|
720
|
+
flow={flow}
|
|
721
|
+
formId="treege-form"
|
|
722
|
+
onBack={() => modal.goToPreviousStep()} // Back on step 0 → previous modal step
|
|
723
|
+
onSubmit={handleSubmit}
|
|
724
|
+
/>
|
|
725
|
+
|
|
726
|
+
// A submit button living outside the renderer (web): only submits on the last
|
|
727
|
+
// step — on earlier steps it advances, like the built-in Continue button.
|
|
728
|
+
<button type="submit" form="treege-form">Save</button>
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
### Headless / Programmatic Control
|
|
732
|
+
|
|
733
|
+
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
734
|
|
|
392
735
|
```tsx
|
|
393
736
|
import { useTreegeRenderer } from "treege/renderer";
|
|
394
737
|
|
|
395
|
-
function CustomForm() {
|
|
396
|
-
const {
|
|
738
|
+
function CustomForm({ flow }) {
|
|
739
|
+
const {
|
|
740
|
+
formValues,
|
|
741
|
+
setFieldValue,
|
|
742
|
+
handleSubmit,
|
|
743
|
+
formErrors,
|
|
744
|
+
visibleNodes,
|
|
745
|
+
isSubmitting,
|
|
746
|
+
currentStep,
|
|
747
|
+
goToNextStep,
|
|
748
|
+
goToPreviousStep,
|
|
749
|
+
} = useTreegeRenderer({
|
|
750
|
+
flow,
|
|
751
|
+
onSubmit: (values) => console.log("Submitted:", values),
|
|
752
|
+
});
|
|
397
753
|
|
|
398
754
|
return (
|
|
399
755
|
<div>
|
|
400
756
|
<button onClick={() => setFieldValue("email", "test@example.com")}>
|
|
401
757
|
Prefill Email
|
|
402
758
|
</button>
|
|
403
|
-
<button onClick={
|
|
404
|
-
|
|
759
|
+
<button onClick={handleSubmit} disabled={isSubmitting}>
|
|
760
|
+
Submit
|
|
761
|
+
</button>
|
|
405
762
|
</div>
|
|
406
763
|
);
|
|
407
764
|
}
|
|
408
765
|
```
|
|
409
766
|
|
|
767
|
+
> The `useTreegeRenderer` return type is exported as `UseTreegeRendererReturn` for TypeScript consumers building custom components.
|
|
768
|
+
|
|
410
769
|
## Examples
|
|
411
770
|
|
|
412
771
|
Check out the `/example` directory for complete examples:
|
|
413
772
|
|
|
414
773
|
```bash
|
|
415
|
-
|
|
416
|
-
|
|
774
|
+
# Run the web example app (Vite, opens /example)
|
|
775
|
+
bun run example
|
|
776
|
+
|
|
777
|
+
# Run the React Native example app (Expo)
|
|
778
|
+
bun run example:native
|
|
417
779
|
```
|
|
418
780
|
|
|
781
|
+
### Available Example URLs
|
|
782
|
+
|
|
783
|
+
Once the development server is running, you can access these examples:
|
|
784
|
+
|
|
785
|
+
- **Default Example**: [http://localhost:5173/](http://localhost:5173/)
|
|
786
|
+
- Basic demonstration of Treege functionality
|
|
787
|
+
|
|
788
|
+
- **Demo Example**: [http://localhost:5173/example](http://localhost:5173/example)
|
|
789
|
+
- Full featured demo showcasing the library capabilities
|
|
790
|
+
|
|
791
|
+
- **All Inputs Example**: [http://localhost:5173/example-all-inputs](http://localhost:5173/example-all-inputs)
|
|
792
|
+
- Comprehensive showcase of all 16 input types
|
|
793
|
+
|
|
794
|
+
- **Custom Input Example**: [http://localhost:5173/example-custom-input](http://localhost:5173/example-custom-input)
|
|
795
|
+
- Demonstrates how to create and integrate custom input components
|
|
796
|
+
|
|
797
|
+
- **TreegeRendererProvider Example**: [http://localhost:5173/example-treege-renderer-provider](http://localhost:5173/example-treege-renderer-provider)
|
|
798
|
+
- Shows global configuration with TreegeRendererProvider
|
|
799
|
+
|
|
419
800
|
## API Reference
|
|
420
801
|
|
|
421
802
|
### TreegeEditor Props
|
|
422
803
|
|
|
423
|
-
| Prop
|
|
424
|
-
|
|
425
|
-
| `flow`
|
|
426
|
-
| `onSave`
|
|
427
|
-
| `
|
|
428
|
-
| `
|
|
804
|
+
| Prop | Type | Default | Description |
|
|
805
|
+
|-------------------|------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
806
|
+
| `flow` | `Flow \| null` | `null` | Initial decision tree |
|
|
807
|
+
| `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) |
|
|
808
|
+
| `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) |
|
|
809
|
+
| `onExportJson` | `() => { nodes: Node[]; edges: Edge[] }` | - | Callback for exporting JSON data |
|
|
810
|
+
| `language` | `string` | `"en"` | UI language |
|
|
811
|
+
| `theme` | `"light" \| "dark"` | `"dark"` | Editor theme |
|
|
812
|
+
| `aiConfig` | `AIConfig` | - | AI configuration for tree generation (see [AI Generation](./AI_GENERATION.md)) |
|
|
813
|
+
| `className` | `string` | - | Additional CSS class names for custom styling |
|
|
814
|
+
| `extraMenuItems` | `ExtraMenuItem[]` | - | Extra entries appended to the actions panel "more" dropdown |
|
|
815
|
+
| `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) |
|
|
816
|
+
| `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` |
|
|
817
|
+
| `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 |
|
|
818
|
+
| `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 |
|
|
819
|
+
| `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
820
|
|
|
430
821
|
### TreegeRenderer Props
|
|
431
822
|
|
|
432
|
-
| Prop | Type | Default | Description
|
|
433
|
-
|
|
434
|
-
| `
|
|
435
|
-
| `onSubmit` | `(values: FormValues) => void`
|
|
436
|
-
| `onChange` | `(values: FormValues) => void` | - | Form change handler
|
|
437
|
-
| `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function
|
|
438
|
-
| `initialValues` | `FormValues` | `{}` |
|
|
439
|
-
| `components` | `
|
|
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
|
|
823
|
+
| Prop | Type | Default | Description |
|
|
824
|
+
|------------------|---------------------------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
825
|
+
| `flow` | `Flow \| null` | - | Decision tree to render |
|
|
826
|
+
| `onSubmit` | `(values: FormValues, meta?: Meta) => void` | - | Form submission handler (meta includes HTTP response data) |
|
|
827
|
+
| `onChange` | `(values: FormValues) => void` | - | Form change handler |
|
|
828
|
+
| `validate` | `(values, nodes) => Record<string, string>` | - | Custom validation function |
|
|
829
|
+
| `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) |
|
|
830
|
+
| `components` | `TreegeRendererComponents` | - | Custom component overrides |
|
|
831
|
+
| `language` | `string` | `"en"` | UI language |
|
|
832
|
+
| `validationMode` | `"onSubmit" \| "onChange"` | `"onSubmit"` | When to validate |
|
|
833
|
+
| `theme` | `"light" \| "dark"` | `"dark"` | Renderer theme |
|
|
834
|
+
| `googleApiKey` | `string` | - | API key for address input |
|
|
835
|
+
| `headers` | `HttpHeaders` | - | HTTP headers as `{ name: value }`, applied to every request (field-level wins) |
|
|
836
|
+
| `isLoading` | `boolean` | `false` | Render a loading skeleton instead of the form (see below) |
|
|
837
|
+
| `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` |
|
|
838
|
+
| `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 |
|
|
839
|
+
| `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 |
|
|
840
|
+
| `className` | `string` | - | Additional CSS class names for custom styling |
|
|
444
841
|
|
|
445
842
|
## Development
|
|
446
843
|
|
|
447
844
|
```bash
|
|
448
845
|
# Install dependencies
|
|
449
|
-
|
|
846
|
+
bun install
|
|
450
847
|
|
|
451
848
|
# Start dev server
|
|
452
|
-
|
|
849
|
+
bun run dev
|
|
453
850
|
|
|
454
851
|
# Build library
|
|
455
|
-
|
|
852
|
+
bun run build
|
|
456
853
|
|
|
457
854
|
# Run linter and type check
|
|
458
|
-
|
|
855
|
+
bun run lint
|
|
459
856
|
|
|
460
857
|
# Preview build
|
|
461
|
-
|
|
858
|
+
bun run preview
|
|
462
859
|
```
|
|
463
860
|
|
|
464
861
|
## Tech Stack
|
|
465
862
|
|
|
466
|
-
- **React**
|
|
863
|
+
- **React** - UI library
|
|
467
864
|
- **TypeScript** - Type safety
|
|
468
865
|
- **TailwindCSS** 4 - Styling
|
|
469
866
|
- **ReactFlow** - Node-based UI
|
|
470
|
-
- **Radix UI** - Accessible components
|
|
471
|
-
- **Zustand** - State management
|
|
472
867
|
- **Vite** - Build tool
|
|
473
868
|
|
|
474
869
|
## Contributing
|
|
@@ -477,13 +872,13 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
477
872
|
|
|
478
873
|
## License
|
|
479
874
|
|
|
480
|
-
|
|
875
|
+
MIT
|
|
481
876
|
|
|
482
877
|
## Credits
|
|
483
878
|
|
|
484
|
-
Created and maintained by [Mickaël Austoni](https://github.com/
|
|
879
|
+
Created and maintained by [Mickaël Austoni](https://github.com/MickaelAustoni)
|
|
485
880
|
|
|
486
881
|
## Support
|
|
487
882
|
|
|
488
|
-
- [GitHub Issues](https://github.com/
|
|
489
|
-
- [Repository](https://github.com/
|
|
883
|
+
- [GitHub Issues](https://github.com/MickaelAustoni/treege/issues)
|
|
884
|
+
- [Repository](https://github.com/MickaelAustoni/treege)
|