torch-glare 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -338
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -317
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -383
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -84
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -63
- package/apps/lib/components/DataViews/states.tsx +0 -38
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -420
- package/apps/lib/components/DropdownMenu.tsx +0 -540
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -73
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -47
- package/apps/lib/components/FormBuilder/types.ts +0 -311
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
- package/apps/lib/components/FormRenderer/detail.tsx +0 -207
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -15
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
- package/apps/lib/components/FormRenderer/types.ts +0 -78
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -147
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -253
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -610
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -214
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1201
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -712
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1495
- package/docs/components/data-views/migration.md +0 -79
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -276
- package/docs/components/form-renderer.md +0 -326
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -477
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -54
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1500
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -704
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { useFormState, type Control, type FieldPath, type FieldValues } from "react-hook-form";
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../utils/cn";
|
|
7
|
-
import { Button } from "../Button";
|
|
8
|
-
// The step *registry* stays with the fields: `FieldShell` registers each field name into it, so
|
|
9
|
-
// it must ship with FormBuilder (which is installable on its own). Everything else about the
|
|
10
|
-
// stepper — the rail, the state, Back/Next — is chrome and lives here. The dependency only ever
|
|
11
|
-
// points this way: FormRenderer → FormBuilder, never back.
|
|
12
|
-
import { StepContext, type StepRegistry } from "../FormBuilder/context";
|
|
13
|
-
// Aliased: this module exports its own `Stepper` and `Step` (the wizard behaviour —
|
|
14
|
-
// `FormRenderer.Stepper` / `.Step`), which would otherwise collide with the presentational
|
|
15
|
-
// component of the same name.
|
|
16
|
-
import {
|
|
17
|
-
Stepper as StepperRail,
|
|
18
|
-
Step as StepPill,
|
|
19
|
-
StepIndicator,
|
|
20
|
-
StepLabel,
|
|
21
|
-
StepConnector,
|
|
22
|
-
} from "../Stepper";
|
|
23
|
-
|
|
24
|
-
// ─── Stepper state context ───────────────────────────────────────────────────
|
|
25
|
-
|
|
26
|
-
/** Stepper state shared by the nav, the step slots and the Back/Next buttons. */
|
|
27
|
-
export interface StepperContextValue {
|
|
28
|
-
currentStep: number;
|
|
29
|
-
totalSteps: number;
|
|
30
|
-
titles: string[];
|
|
31
|
-
isFirstStep: boolean;
|
|
32
|
-
isLastStep: boolean;
|
|
33
|
-
goToNext: () => void | Promise<void>;
|
|
34
|
-
goToPrevious: () => void;
|
|
35
|
-
goToStep: (index: number) => void;
|
|
36
|
-
/** Field names registered per step, for per-step validation. */
|
|
37
|
-
stepFields: Record<number, Set<string>>;
|
|
38
|
-
/** Steps that have passed validation — stay checked even after navigating back. */
|
|
39
|
-
completedSteps: Set<number>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const StepperContext = React.createContext<StepperContextValue | null>(null);
|
|
43
|
-
|
|
44
|
-
export const useStepper = () => {
|
|
45
|
-
const ctx = React.useContext(StepperContext);
|
|
46
|
-
if (!ctx) throw new Error("FormRenderer.Step/Back/Next must be used within FormRenderer.Stepper");
|
|
47
|
-
return ctx;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// ─── Step (declaration only — the Stepper reads its props) ───────────────────
|
|
51
|
-
|
|
52
|
-
export interface StepProps {
|
|
53
|
-
title: string;
|
|
54
|
-
description?: string;
|
|
55
|
-
children: React.ReactNode;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Declares a wizard step. It renders nothing itself — `FormRenderer.Stepper`
|
|
60
|
-
* collects Step elements as an array and renders every step's fields (so the
|
|
61
|
-
* **whole form is registered**), toggling visibility per the active step.
|
|
62
|
-
*/
|
|
63
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- props are read by Stepper, not rendered here
|
|
64
|
-
export function Step(_props: StepProps) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
(Step as unknown as { __isFormStep: boolean }).__isFormStep = true;
|
|
68
|
-
|
|
69
|
-
export function isStepElement(node: React.ReactNode): node is React.ReactElement<StepProps> {
|
|
70
|
-
return (
|
|
71
|
-
React.isValidElement(node) && (node.type as { __isFormStep?: boolean })?.__isFormStep === true
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ─── StepSlot — mounts one step's fields; hidden when not active ─────────────
|
|
76
|
-
|
|
77
|
-
function StepSlot({
|
|
78
|
-
index,
|
|
79
|
-
active,
|
|
80
|
-
children,
|
|
81
|
-
}: {
|
|
82
|
-
index: number;
|
|
83
|
-
active: boolean;
|
|
84
|
-
children: React.ReactNode;
|
|
85
|
-
}) {
|
|
86
|
-
const stepper = useStepper();
|
|
87
|
-
const registry: StepRegistry = React.useMemo(
|
|
88
|
-
() => ({
|
|
89
|
-
register: (name) => {
|
|
90
|
-
(stepper.stepFields[index] ??= new Set()).add(name);
|
|
91
|
-
},
|
|
92
|
-
unregister: (name) => {
|
|
93
|
-
stepper.stepFields[index]?.delete(name);
|
|
94
|
-
},
|
|
95
|
-
}),
|
|
96
|
-
[stepper, index],
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Always mounted (fields stay registered); CSS hides inactive steps.
|
|
100
|
-
return (
|
|
101
|
-
<div className={cn("flex flex-col gap-4", !active && "hidden")}>
|
|
102
|
-
<StepContext.Provider value={registry}>{children}</StepContext.Provider>
|
|
103
|
-
</div>
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ─── Stepper navigation (style only) ─────────────────────────────────────────
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Vertical step rail (matches `Tabs.svg`): the numbered state badges stacked top
|
|
111
|
-
* to bottom, joined by a short vertical connector between consecutive steps.
|
|
112
|
-
*
|
|
113
|
-
* `control` is passed in rather than read from context: the rail renders in its own grid column
|
|
114
|
-
* **outside** the `<form>`, so there is no `FormProvider` above it to read. Same reason
|
|
115
|
-
* `useStepperState` takes `trigger` as an argument.
|
|
116
|
-
*/
|
|
117
|
-
function StepperNav({ control }: { control: Control<FieldValues> }) {
|
|
118
|
-
const { titles, currentStep, goToStep, stepFields, completedSteps } = useStepper();
|
|
119
|
-
const { errors } = useFormState({ control });
|
|
120
|
-
|
|
121
|
-
const stepHasError = (index: number) =>
|
|
122
|
-
[...(stepFields[index] ?? [])].some((name) => name in errors);
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
// `min-w-0` so the rail can be squeezed: its grid track no longer grows to fit a long label
|
|
126
|
-
// (see form-renderer.tsx), so the column has to be allowed to shrink and let the labels
|
|
127
|
-
// truncate instead of spilling over the fields column.
|
|
128
|
-
<StepperRail activeStep={currentStep} orientation="vertical" className="min-w-0 shrink-0">
|
|
129
|
-
{titles.map((title, index) => {
|
|
130
|
-
// The step buttons ARE the navigation: click to move. Backward is free;
|
|
131
|
-
// clicking forward validates the steps in between (goToStep) and stops at
|
|
132
|
-
// the first one with errors. A live error shows red; a step that has passed
|
|
133
|
-
// validation stays checked (success) even after navigating back to it.
|
|
134
|
-
const type = stepHasError(index)
|
|
135
|
-
? "negative"
|
|
136
|
-
: completedSteps.has(index)
|
|
137
|
-
? "success"
|
|
138
|
-
: "default";
|
|
139
|
-
return (
|
|
140
|
-
<React.Fragment key={title}>
|
|
141
|
-
{/* The shrink/truncate pair is passed in rather than changed in `Stepper`, so its
|
|
142
|
-
other consumers keep sizing to their labels. `shrink` beats the pill's own
|
|
143
|
-
`shrink-0` and `truncate` beats the label's `whitespace-nowrap` — both via
|
|
144
|
-
tailwind-merge, which `Stepper` runs the caller's className through. */}
|
|
145
|
-
<StepPill
|
|
146
|
-
index={index}
|
|
147
|
-
type={type}
|
|
148
|
-
onClick={() => void goToStep(index)}
|
|
149
|
-
// `max-w-full` is what actually makes the label truncate: the rail is
|
|
150
|
-
// `items-start`, so without a cap the pill shrink-wraps its label and grows straight
|
|
151
|
-
// past the track instead of clipping inside it.
|
|
152
|
-
className="min-w-0 max-w-full shrink"
|
|
153
|
-
>
|
|
154
|
-
<StepIndicator />
|
|
155
|
-
{/* `max-w-none` opts out of the component's 106px cap: the rail sizes to its own
|
|
156
|
-
grid track, so the label should truncate there rather than 106px early. */}
|
|
157
|
-
<StepLabel className="max-w-none truncate">{title}</StepLabel>
|
|
158
|
-
</StepPill>
|
|
159
|
-
{/* Connector between steps — the component centres it under the indicator per size. */}
|
|
160
|
-
{index < titles.length - 1 && <StepConnector />}
|
|
161
|
-
</React.Fragment>
|
|
162
|
-
);
|
|
163
|
-
})}
|
|
164
|
-
</StepperRail>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// ─── Back / Next chevron nav (the Figma header action bar) ───────────────────
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Shared chevron nav button, matching the Figma header action bar (Body-HeaderBar-1.0) — the
|
|
172
|
-
* Glare `Button` icon variant, the same control Select/SearchableSelect use for their chevrons.
|
|
173
|
-
*/
|
|
174
|
-
function StepNavButton({
|
|
175
|
-
dir,
|
|
176
|
-
onClick,
|
|
177
|
-
disabled,
|
|
178
|
-
}: {
|
|
179
|
-
dir: "left" | "right";
|
|
180
|
-
onClick: () => void;
|
|
181
|
-
disabled: boolean;
|
|
182
|
-
}) {
|
|
183
|
-
return (
|
|
184
|
-
<Button
|
|
185
|
-
type="button"
|
|
186
|
-
buttonType="icon"
|
|
187
|
-
size="M"
|
|
188
|
-
onClick={onClick}
|
|
189
|
-
disabled={disabled}
|
|
190
|
-
aria-label={dir === "left" ? "Previous step" : "Next step"}
|
|
191
|
-
>
|
|
192
|
-
<i
|
|
193
|
-
className={cn(
|
|
194
|
-
"text-[18px]",
|
|
195
|
-
dir === "left" ? "ri-arrow-left-s-line" : "ri-arrow-right-s-line",
|
|
196
|
-
)}
|
|
197
|
-
/>
|
|
198
|
-
</Button>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** `FormRenderer.Back` — chevron to the previous step; disabled on the first. */
|
|
203
|
-
export function Back() {
|
|
204
|
-
const { goToPrevious, isFirstStep } = useStepper();
|
|
205
|
-
return <StepNavButton dir="left" onClick={goToPrevious} disabled={isFirstStep} />;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** `FormRenderer.Next` — chevron to the next step (validates first); disabled on the last. */
|
|
209
|
-
export function Next() {
|
|
210
|
-
const { goToNext, isLastStep } = useStepper();
|
|
211
|
-
return <StepNavButton dir="right" onClick={() => void goToNext()} disabled={isLastStep} />;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ─── Stepper action bar (Back/Next + divider, then the Submit) ────────────────
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* The FormRenderer root wraps its `actions` in this. When the form is a stepper it prepends the
|
|
218
|
-
* chevron `Back`/`Next` controls + a divider before the (user-provided) Submit — the Figma
|
|
219
|
-
* `Body-HeaderBar-1.0` layout. Outside a stepper there's no `StepperContext`, so it renders
|
|
220
|
-
* the actions untouched.
|
|
221
|
-
*/
|
|
222
|
-
export function StepperActions({ children }: { children?: React.ReactNode }) {
|
|
223
|
-
const stepper = React.useContext(StepperContext);
|
|
224
|
-
if (!stepper) return <>{children}</>;
|
|
225
|
-
return (
|
|
226
|
-
<div className="flex items-center gap-2">
|
|
227
|
-
<Back />
|
|
228
|
-
<Next />
|
|
229
|
-
{/* Divider — white-alpha hairline between the nav and the Submit. */}
|
|
230
|
-
<span aria-hidden className="mx-1 h-5 w-px rounded-[2px] bg-white-alpha-20" />
|
|
231
|
-
{children}
|
|
232
|
-
</div>
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// ─── Stepper root (marker) + state hook ──────────────────────────────────────
|
|
237
|
-
|
|
238
|
-
export interface StepperProps {
|
|
239
|
-
children: React.ReactNode;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* `FormRenderer.Stepper` — declares a wizard. It renders **nothing itself**: the
|
|
244
|
-
* FormRenderer root detects it, lifts its state (so the nav can live in its own
|
|
245
|
-
* grid column *outside* the `<form>`), and renders `[nav | active step's fields]`.
|
|
246
|
-
* Children are `FormRenderer.Step`s (plus an optional custom footer).
|
|
247
|
-
*
|
|
248
|
-
* Every step's fields stay registered with react-hook-form at all times — the
|
|
249
|
-
* stepper only controls which step is *visible*. **Navigation is the step buttons
|
|
250
|
-
* themselves**: click a step to move there. Backward is free; clicking forward
|
|
251
|
-
* validates every step in between and stops at the first with errors (which shows a
|
|
252
|
-
* red indicator). Only the last step shows the Submit button.
|
|
253
|
-
*/
|
|
254
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- children are read by the FormRenderer root
|
|
255
|
-
export function Stepper(_props: StepperProps) {
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
(Stepper as unknown as { __isFormStepper: boolean }).__isFormStepper = true;
|
|
259
|
-
|
|
260
|
-
export function isStepperElement(node: React.ReactNode): node is React.ReactElement<StepperProps> {
|
|
261
|
-
return (
|
|
262
|
-
React.isValidElement(node) &&
|
|
263
|
-
(node.type as { __isFormStepper?: boolean })?.__isFormStepper === true
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
type TriggerFn = (names?: FieldPath<FieldValues>[]) => Promise<boolean>;
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Stepper state — lifted to the FormRenderer root so the nav (rail) and the step
|
|
271
|
-
* fields can render in separate grid columns while sharing one state. `trigger` is
|
|
272
|
-
* the form's `trigger` (passed in — no `useFormContext` needed). Inert when
|
|
273
|
-
* `steps` is empty (a form without a stepper still calls this, for hooks order).
|
|
274
|
-
*/
|
|
275
|
-
export function useStepperState(
|
|
276
|
-
steps: React.ReactElement<StepProps>[],
|
|
277
|
-
trigger: TriggerFn,
|
|
278
|
-
): StepperContextValue {
|
|
279
|
-
const [currentStep, setCurrentStep] = React.useState(0);
|
|
280
|
-
// Steps that have passed their last validation — kept so their checkmark persists when the
|
|
281
|
-
// user navigates back to an earlier step.
|
|
282
|
-
const [completedSteps, setCompletedSteps] = React.useState<Set<number>>(new Set());
|
|
283
|
-
const stepFieldsRef = React.useRef<Record<number, Set<string>>>({});
|
|
284
|
-
const titles = steps.map((s) => s.props.title);
|
|
285
|
-
const lastIndex = steps.length - 1;
|
|
286
|
-
|
|
287
|
-
const markStep = (step: number, passed: boolean) =>
|
|
288
|
-
setCompletedSteps((prev) => {
|
|
289
|
-
if (passed === prev.has(step)) return prev; // no change
|
|
290
|
-
const next = new Set(prev);
|
|
291
|
-
if (passed) next.add(step);
|
|
292
|
-
else next.delete(step);
|
|
293
|
-
return next;
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
const validateStep = async (step: number) => {
|
|
297
|
-
const names = [...(stepFieldsRef.current[step] ?? [])] as FieldPath<FieldValues>[];
|
|
298
|
-
const passed = names.length === 0 ? true : await trigger(names);
|
|
299
|
-
markStep(step, passed);
|
|
300
|
-
return passed;
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
// Navigation runs through the step buttons. Backward is free; going forward
|
|
304
|
-
// validates every step between the current one and the target, and stops at
|
|
305
|
-
// the first step that has errors (so you can't skip past an invalid step).
|
|
306
|
-
const goToStep = async (index: number) => {
|
|
307
|
-
const target = Math.max(0, Math.min(index, Math.max(0, lastIndex)));
|
|
308
|
-
if (target <= currentStep) {
|
|
309
|
-
setCurrentStep(target);
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
for (let s = currentStep; s < target; s++) {
|
|
313
|
-
if (!(await validateStep(s))) {
|
|
314
|
-
setCurrentStep(s);
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
setCurrentStep(target);
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
const goToNext = async () => {
|
|
322
|
-
if (await validateStep(currentStep)) setCurrentStep((s) => Math.min(s + 1, lastIndex));
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
return {
|
|
326
|
-
currentStep,
|
|
327
|
-
totalSteps: steps.length,
|
|
328
|
-
titles,
|
|
329
|
-
isFirstStep: currentStep === 0,
|
|
330
|
-
isLastStep: currentStep === lastIndex,
|
|
331
|
-
goToNext,
|
|
332
|
-
goToPrevious: () => setCurrentStep((s) => Math.max(s - 1, 0)),
|
|
333
|
-
goToStep,
|
|
334
|
-
stepFields: stepFieldsRef.current,
|
|
335
|
-
completedSteps,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
export { StepperNav, StepSlot };
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
import type {
|
|
3
|
-
DefaultValues,
|
|
4
|
-
FieldErrors,
|
|
5
|
-
FieldValues,
|
|
6
|
-
Resolver,
|
|
7
|
-
UseFormReturn,
|
|
8
|
-
} from "react-hook-form";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* FormRenderer — the chrome around a `FormBuilder`. You author the fields as **JSX children**
|
|
12
|
-
* (`FormRenderer.Section`, `FormBuilder.Text`, …); the renderer owns everything drawn around
|
|
13
|
-
* them: page-vs-drawer display, the absolute title header, the `actions` bar, the titled section
|
|
14
|
-
* cards, the page gutters and scroll shell, the wizard rail, the `summary` column, and vertical
|
|
15
|
-
* field layout inside a drawer.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
export type FormRendererDisplay = "page" | "drawer";
|
|
19
|
-
export type FieldDirection = "horizontal" | "vertical" | "flexible";
|
|
20
|
-
|
|
21
|
-
export interface FormRendererProps<T extends FieldValues = FieldValues> {
|
|
22
|
-
/** The form body — `FormRenderer.Section` / field / `FormRenderer.Stepper` JSX. */
|
|
23
|
-
children: ReactNode;
|
|
24
|
-
|
|
25
|
-
// --- react-hook-form root (forwarded to FormBuilder) ---
|
|
26
|
-
/** Submit handler. Optional — a display-only detail-tabs view (`FormRenderer.Sidebar`) has no form. */
|
|
27
|
-
onSubmit?: (values: T) => void | Promise<void>;
|
|
28
|
-
onInvalid?: (errors: FieldErrors<T>) => void;
|
|
29
|
-
resolver?: Resolver<T>;
|
|
30
|
-
defaultValues?: DefaultValues<T>;
|
|
31
|
-
values?: T;
|
|
32
|
-
loading?: boolean;
|
|
33
|
-
resetOnSuccess?: boolean;
|
|
34
|
-
/** Row layout; defaults to vertical inside a drawer. */
|
|
35
|
-
fieldDirection?: FieldDirection;
|
|
36
|
-
/**
|
|
37
|
-
* A hoisted `useForm` instance to bind the form to. Pass this when something outside the
|
|
38
|
-
* form (e.g. a `summary` `FormSummary`) must read the same live values; the caller owns
|
|
39
|
-
* `resolver`/`defaultValues` on that instance. Omit to let FormRenderer create its own.
|
|
40
|
-
*/
|
|
41
|
-
form?: UseFormReturn<T>;
|
|
42
|
-
|
|
43
|
-
// --- display ---
|
|
44
|
-
display?: FormRendererDisplay;
|
|
45
|
-
/**
|
|
46
|
-
* A live panel rendered beside the form (page) or in the drawer tray (drawer) — typically a
|
|
47
|
-
* `FormSummary`. Give FormRenderer the same hoisted `form` so the panel reads live values.
|
|
48
|
-
*/
|
|
49
|
-
summary?: ReactNode;
|
|
50
|
-
/**
|
|
51
|
-
* Lands on the form's outermost element (page display). Use it to let the form fill its
|
|
52
|
-
* parent — e.g. `"flex-1 min-h-0"` inside a flex column that has a height.
|
|
53
|
-
*/
|
|
54
|
-
className?: string;
|
|
55
|
-
/**
|
|
56
|
-
* Absolute title header + action bar. Used by **both** displays — the page and the
|
|
57
|
-
* drawer render the same `HeaderBar` title pill, so a form looks identical in either.
|
|
58
|
-
*/
|
|
59
|
-
header?: { title: string; label?: string; variant?: "new" | "edit" | "detail" };
|
|
60
|
-
/**
|
|
61
|
-
* The form's action bar — rendered in the header's right-hand action pill (page) or the drawer
|
|
62
|
-
* header (drawer). Put the Save here: `actions={<FormBuilder.Submit>Save</FormBuilder.Submit>}`.
|
|
63
|
-
* A bare `FormBuilder.Submit` auto-targets this form (see `FormBuilder`'s form-id context), so it
|
|
64
|
-
* submits even though the header sits outside the `<form>`.
|
|
65
|
-
*/
|
|
66
|
-
actions?: ReactNode;
|
|
67
|
-
/** `id` on the underlying `<form>`. Optional — FormRenderer generates and wires one otherwise. */
|
|
68
|
-
id?: string;
|
|
69
|
-
|
|
70
|
-
/** Drawer control (when `display === "drawer"`). */
|
|
71
|
-
open?: boolean;
|
|
72
|
-
onOpenChange?: (open: boolean) => void;
|
|
73
|
-
/** Overrides `header.title` for the drawer. Plain text — it renders via `HeaderBar`. */
|
|
74
|
-
title?: string;
|
|
75
|
-
/** Overrides `header.label` for the drawer. */
|
|
76
|
-
badge?: string;
|
|
77
|
-
onOpenInNewTab?: () => void;
|
|
78
|
-
}
|