torch-glare 2.5.6 → 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 -403
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -325
- 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 -395
- 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 -88
- 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 -72
- package/apps/lib/components/DataViews/states.tsx +0 -73
- 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 -451
- package/apps/lib/components/DropdownMenu.tsx +0 -554
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -85
- 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 -168
- 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 -114
- 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 -67
- package/apps/lib/components/FormBuilder/types.ts +0 -316
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
- package/apps/lib/components/FormRenderer/detail.tsx +0 -256
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -17
- package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
- package/apps/lib/components/FormRenderer/types.ts +0 -115
- 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 -168
- 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 -255
- 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 -597
- 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 -61
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useHtmlDir.ts +0 -31
- 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 -300
- 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 -1217
- 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/scroller.ts +0 -26
- 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 -738
- 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 -1521
- package/docs/components/data-views/migration.md +0 -81
- 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 -284
- package/docs/components/form-renderer.md +0 -396
- 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 -483
- 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 -60
- 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 -1523
- 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 -726
- 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,200 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: SearchableTree
|
|
3
|
-
description: Searchable tree-select that opens on focus and filters hierarchical nodes as you type, on a Popover surface, with client or server-side search
|
|
4
|
-
group: Inputs
|
|
5
|
-
keywords: [searchable-tree, tree, tree-select, hierarchy, search, combobox, async, popover]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# SearchableTree
|
|
9
|
-
|
|
10
|
-
> A searchable tree-select. It renders a field that opens a Popover containing a hierarchical
|
|
11
|
-
> tree of nodes and filters them as you type. Accepts either nested data (via `getNodeChildren`)
|
|
12
|
-
> or a flat list that it nests for you (via `parentIdKey`). Supports local filtering or
|
|
13
|
-
> debounced server-side search, optional folder selection, and controlled selection.
|
|
14
|
-
|
|
15
|
-
## Installation
|
|
16
|
-
|
|
17
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
18
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npx torch-glare@latest init
|
|
22
|
-
npx torch-glare@latest add SearchableTree
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
The CLI also copies its internal dependencies: `Button`, `Input`, `Popover`, the
|
|
26
|
-
`useClickOutside` hook, and the `cn`/`types` utils.
|
|
27
|
-
|
|
28
|
-
## Import
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
import { SearchableTree } from "@/components/SearchableTree";
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Quick Examples
|
|
35
|
-
|
|
36
|
-
### Basic Usage (nested data)
|
|
37
|
-
|
|
38
|
-
```tsx
|
|
39
|
-
import { SearchableTree } from "@/components/SearchableTree";
|
|
40
|
-
|
|
41
|
-
type Node = { id: string; name: string; children?: Node[] };
|
|
42
|
-
|
|
43
|
-
const data: Node[] = [
|
|
44
|
-
{
|
|
45
|
-
id: "eng",
|
|
46
|
-
name: "Engineering",
|
|
47
|
-
children: [
|
|
48
|
-
{ id: "fe", name: "Frontend" },
|
|
49
|
-
{ id: "be", name: "Backend" },
|
|
50
|
-
],
|
|
51
|
-
},
|
|
52
|
-
{ id: "design", name: "Design" },
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
export function DepartmentPicker() {
|
|
56
|
-
const [value, setValue] = useState<Node | null>(null);
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<SearchableTree
|
|
60
|
-
nodes={data}
|
|
61
|
-
getNodeId={(n) => n.id}
|
|
62
|
-
getNodeLabel={(n) => n.name}
|
|
63
|
-
getNodeChildren={(n) => n.children}
|
|
64
|
-
value={value}
|
|
65
|
-
onSelect={setValue}
|
|
66
|
-
placeholder="Select a department"
|
|
67
|
-
title="Departments"
|
|
68
|
-
size="M"
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Flat data (built from a parent id)
|
|
75
|
-
|
|
76
|
-
```tsx
|
|
77
|
-
type Row = { id: string; label: string; parentId: string | null };
|
|
78
|
-
|
|
79
|
-
const rows: Row[] = [
|
|
80
|
-
{ id: "1", label: "Company", parentId: null },
|
|
81
|
-
{ id: "2", label: "Sales", parentId: "1" },
|
|
82
|
-
{ id: "3", label: "EMEA", parentId: "2" },
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
<SearchableTree
|
|
86
|
-
nodes={rows}
|
|
87
|
-
parentIdKey="parentId"
|
|
88
|
-
getNodeId={(r) => r.id}
|
|
89
|
-
getNodeLabel={(r) => r.label}
|
|
90
|
-
onSelect={(r) => console.log(r.id)}
|
|
91
|
-
/>;
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Server-side search
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
<SearchableTree
|
|
98
|
-
nodes={results}
|
|
99
|
-
getNodeId={(n) => n.id}
|
|
100
|
-
getNodeLabel={(n) => n.name}
|
|
101
|
-
getNodeChildren={(n) => n.children}
|
|
102
|
-
filterClientSide={false}
|
|
103
|
-
onSearchChange={(query) => fetchNodes(query)}
|
|
104
|
-
loading={isFetching}
|
|
105
|
-
searchDebounceMs={300}
|
|
106
|
-
/>
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Selectable folders
|
|
110
|
-
|
|
111
|
-
```tsx
|
|
112
|
-
<SearchableTree
|
|
113
|
-
nodes={data}
|
|
114
|
-
getNodeId={(n) => n.id}
|
|
115
|
-
getNodeLabel={(n) => n.name}
|
|
116
|
-
getNodeChildren={(n) => n.children}
|
|
117
|
-
selectableFolders
|
|
118
|
-
onSelect={(n) => console.log(n.id)}
|
|
119
|
-
/>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## API Reference
|
|
123
|
-
|
|
124
|
-
### Props
|
|
125
|
-
|
|
126
|
-
| Prop | Type | Default | Description |
|
|
127
|
-
|------|------|---------|-------------|
|
|
128
|
-
| `nodes` | `T[]` | — | Tree data. Nested by default; treated as a flat list when `parentIdKey` is set. |
|
|
129
|
-
| `getNodeId` | `(node: T) => string` | — | Returns a stable unique id for a node. |
|
|
130
|
-
| `getNodeLabel` | `(node: T) => ReactNode` | — | Returns a node's display label. |
|
|
131
|
-
| `getNodeChildren` | `(node: T) => T[] \| undefined` | — | Returns a node's children (nested mode). Ignored when `parentIdKey` is set. |
|
|
132
|
-
| `parentIdKey` | `keyof T & string` | — | When set, `nodes` is a FLAT list and the tree is built from this parent-id key. |
|
|
133
|
-
| `value` | `T \| null` | — | Controlled selected node. |
|
|
134
|
-
| `onSelect` | `(node: T) => void` | — | Called when a node is selected. |
|
|
135
|
-
| `getSearchText` | `(node: T) => string` | `String(getNodeLabel(node))` | Plain text used for search matching. |
|
|
136
|
-
| `placeholder` | `string` | `"Select…"` | Field placeholder shown when nothing is selected. |
|
|
137
|
-
| `title` | `string` | `"Select an item"` | Section heading above the tree rows in the dropdown. |
|
|
138
|
-
| `size` | `"XS" \| "S" \| "M"` | `"M"` | Field size. |
|
|
139
|
-
| `variant` | `"SystemStyle" \| "PresentationStyle"` | `"PresentationStyle"` | Visual style. `SystemStyle` is reserved for internal library system surfaces. |
|
|
140
|
-
| `icon` | `ReactNode` | — | Leading icon in the field. |
|
|
141
|
-
| `theme` | `Themes` | — | `"dark" \| "light" \| "default"`. |
|
|
142
|
-
| `dir` | `string` | — | Text direction. |
|
|
143
|
-
| `className` | `string` | — | Extra classes for the field. |
|
|
144
|
-
| `defaultExpanded` | `boolean` | `true` | Expand every node when the dropdown opens. |
|
|
145
|
-
| `selectableFolders` | `boolean` | `false` | When true, folder nodes are selectable too; otherwise folders only expand/collapse. |
|
|
146
|
-
| `maxBodyHeight` | `number` | `320` | Max height (px) of the scrollable tree body before it scrolls. |
|
|
147
|
-
| `filterClientSide` | `boolean` | `true` | Filter locally. Set `false` for server-side search. |
|
|
148
|
-
| `onSearchChange` | `(query: string) => void` | — | Debounced as the user types — refetch your data here (server search). |
|
|
149
|
-
| `searchDebounceMs` | `number` | `300` | Debounce for `onSearchChange`. |
|
|
150
|
-
| `loading` | `boolean` | `false` | Whether a fetch is in flight; shows a loading indicator. |
|
|
151
|
-
|
|
152
|
-
### TypeScript
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
import { ReactNode } from "react";
|
|
156
|
-
import { Themes } from "@/utils/types";
|
|
157
|
-
|
|
158
|
-
interface SearchableTreeProps<T> {
|
|
159
|
-
nodes: T[];
|
|
160
|
-
getNodeId: (node: T) => string;
|
|
161
|
-
getNodeLabel: (node: T) => ReactNode;
|
|
162
|
-
getNodeChildren?: (node: T) => T[] | undefined;
|
|
163
|
-
parentIdKey?: keyof T & string;
|
|
164
|
-
value?: T | null;
|
|
165
|
-
onSelect?: (node: T) => void;
|
|
166
|
-
getSearchText?: (node: T) => string;
|
|
167
|
-
placeholder?: string;
|
|
168
|
-
title?: string;
|
|
169
|
-
size?: "XS" | "S" | "M";
|
|
170
|
-
variant?: "SystemStyle" | "PresentationStyle";
|
|
171
|
-
icon?: ReactNode;
|
|
172
|
-
theme?: Themes;
|
|
173
|
-
dir?: string;
|
|
174
|
-
className?: string;
|
|
175
|
-
defaultExpanded?: boolean;
|
|
176
|
-
selectableFolders?: boolean;
|
|
177
|
-
maxBodyHeight?: number;
|
|
178
|
-
filterClientSide?: boolean;
|
|
179
|
-
onSearchChange?: (query: string) => void;
|
|
180
|
-
searchDebounceMs?: number;
|
|
181
|
-
loading?: boolean;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export function SearchableTree<T>(props: SearchableTreeProps<T>): JSX.Element;
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Common Patterns
|
|
188
|
-
|
|
189
|
-
- **Nested vs flat data:** provide `getNodeChildren` for already-nested data, or `parentIdKey`
|
|
190
|
-
to let the component nest a flat list for you. Do not use both.
|
|
191
|
-
- **Async search:** set `filterClientSide={false}` and handle `onSearchChange` to fetch from a
|
|
192
|
-
backend; pass `loading` while the request is in flight.
|
|
193
|
-
- **Folder selection:** by default only leaf nodes are selectable. Set `selectableFolders` to
|
|
194
|
-
allow selecting a folder node (clicking any node selects it and closes the dropdown).
|
|
195
|
-
|
|
196
|
-
## Related Components
|
|
197
|
-
|
|
198
|
-
- [SearchableTreeDialog](./searchable-tree-dialog.md) — the same tree-select in a modal dialog.
|
|
199
|
-
- [SearchableSelect](./searchable-select.md) — flat searchable single-select combobox.
|
|
200
|
-
- [TreeDropDown](./tree-drop-down.md) — dropdown tree without search.
|
|
@@ -1,483 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: SectionBlock
|
|
3
|
-
title: SectionBlock
|
|
4
|
-
description: Sectioned card container with a colored title badge for grouping related content like forms, tables, or lists.
|
|
5
|
-
category: layout
|
|
6
|
-
group: Layout & Containers
|
|
7
|
-
tags: [layout, card, section, container, form, group]
|
|
8
|
-
status: stable
|
|
9
|
-
version: 2.4.5
|
|
10
|
-
dependencies:
|
|
11
|
-
- "class-variance-authority": "^0.7.0"
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# SectionBlock
|
|
15
|
-
|
|
16
|
-
> A card container with an optional colored title badge. Use it to group related content — custom field forms, tables, settings groups — under a clear, color-coded heading.
|
|
17
|
-
|
|
18
|
-
## Installation
|
|
19
|
-
|
|
20
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
21
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npx torch-glare@latest init
|
|
25
|
-
npx torch-glare@latest add SectionBlock
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
`add` also copies any components, hooks, and utilities that `SectionBlock` depends on.
|
|
29
|
-
|
|
30
|
-
## Import
|
|
31
|
-
|
|
32
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Basic Usage
|
|
39
|
-
|
|
40
|
-
```tsx
|
|
41
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
42
|
-
|
|
43
|
-
export function Example() {
|
|
44
|
-
return (
|
|
45
|
-
<SectionBlock color="Blue" title="Project details">
|
|
46
|
-
<p className="text-content-presentation-action-light-primary py-4">
|
|
47
|
-
Card body content goes here.
|
|
48
|
-
</p>
|
|
49
|
-
</SectionBlock>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## API Reference
|
|
55
|
-
|
|
56
|
-
### Props
|
|
57
|
-
|
|
58
|
-
| Prop | Type | Default | Description |
|
|
59
|
-
|------|------|---------|-------------|
|
|
60
|
-
| `color` | `SectionColor` | `"Blue"` | Color of the title badge. One of `Blue`, `Yellow`, `Green`, `Red`, `Orange`, `Purple`, `Pink`, `Gray`. |
|
|
61
|
-
| `title` | `ReactNode` | — | Title rendered inside the colored badge. Optional — when omitted, the header is hidden entirely. Accepts any ReactNode (string, JSX with icons, links, etc.). |
|
|
62
|
-
| `icon` | `ReactNode` | — | Rendered inside the badge, to the left of `title`. |
|
|
63
|
-
| `action` | `ReactNode` | — | Right-aligned content on the title row — typically action buttons. |
|
|
64
|
-
| `variant` | `SectionVariant` | `"Default"` | `"Default"` is the padded form card. `"Table"` is the full-bleed table shell: no body padding, a rule under the header, no bottom padding, and the card clipped to its radius. See [Table Variant](#table-variant). |
|
|
65
|
-
| `containerClassName` | `string` | — | Class name applied to the outer container (alongside `className`). |
|
|
66
|
-
| `headerClassName` | `string` | — | Class name applied to the header wrapper around the title badge. |
|
|
67
|
-
| `bodyClassName` | `string` | — | Class name applied to the body wrapper holding `children`. |
|
|
68
|
-
| `className` | `string` | — | Standard React class name on the outer container. |
|
|
69
|
-
| `children` | `ReactNode` | — | Body content. |
|
|
70
|
-
| `...rest` | `HTMLAttributes<HTMLDivElement>` | — | All standard div props except `title` (which is overridden). |
|
|
71
|
-
|
|
72
|
-
### TypeScript
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
export type SectionColor =
|
|
76
|
-
| "Blue"
|
|
77
|
-
| "Yellow"
|
|
78
|
-
| "Green"
|
|
79
|
-
| "Red"
|
|
80
|
-
| "Orange"
|
|
81
|
-
| "Purple"
|
|
82
|
-
| "Pink"
|
|
83
|
-
| "Gray";
|
|
84
|
-
|
|
85
|
-
export type SectionVariant = "Default" | "Table";
|
|
86
|
-
|
|
87
|
-
export interface SectionBlockProps
|
|
88
|
-
extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
89
|
-
color?: SectionColor;
|
|
90
|
-
variant?: SectionVariant;
|
|
91
|
-
title?: ReactNode;
|
|
92
|
-
icon?: ReactNode;
|
|
93
|
-
action?: ReactNode;
|
|
94
|
-
containerClassName?: string;
|
|
95
|
-
headerClassName?: string;
|
|
96
|
-
bodyClassName?: string;
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
The component is a `forwardRef<HTMLDivElement, SectionBlockProps>`.
|
|
101
|
-
|
|
102
|
-
## Examples
|
|
103
|
-
|
|
104
|
-
### All Colors
|
|
105
|
-
|
|
106
|
-
```tsx
|
|
107
|
-
import { SectionBlock, type SectionColor } from "@/components/SectionBlock";
|
|
108
|
-
|
|
109
|
-
const COLORS: SectionColor[] = [
|
|
110
|
-
"Blue",
|
|
111
|
-
"Yellow",
|
|
112
|
-
"Green",
|
|
113
|
-
"Red",
|
|
114
|
-
"Orange",
|
|
115
|
-
"Purple",
|
|
116
|
-
"Pink",
|
|
117
|
-
"Gray",
|
|
118
|
-
];
|
|
119
|
-
|
|
120
|
-
export function AllColors() {
|
|
121
|
-
return (
|
|
122
|
-
<div className="flex flex-col gap-[24px]">
|
|
123
|
-
{COLORS.map((color) => (
|
|
124
|
-
<SectionBlock key={color} color={color} title={`${color} section`}>
|
|
125
|
-
<p className="text-content-presentation-action-light-primary py-4">
|
|
126
|
-
This is a {color.toLowerCase()} sectioned card.
|
|
127
|
-
</p>
|
|
128
|
-
</SectionBlock>
|
|
129
|
-
))}
|
|
130
|
-
</div>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### No Title
|
|
136
|
-
|
|
137
|
-
When `title` is omitted, the header is hidden but the body padding remains.
|
|
138
|
-
|
|
139
|
-
```tsx
|
|
140
|
-
<SectionBlock>
|
|
141
|
-
<p className="text-content-presentation-action-light-primary py-4">
|
|
142
|
-
A SectionBlock without a title — header is hidden, body still padded.
|
|
143
|
-
</p>
|
|
144
|
-
</SectionBlock>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Rich Title with Icon
|
|
148
|
-
|
|
149
|
-
`title` accepts any ReactNode, so you can pass JSX with icons, counts, links, etc.
|
|
150
|
-
|
|
151
|
-
```tsx
|
|
152
|
-
<SectionBlock
|
|
153
|
-
color="Purple"
|
|
154
|
-
title={
|
|
155
|
-
<span className="flex items-center gap-[6px]">
|
|
156
|
-
<i className="ri-magic-line" />
|
|
157
|
-
Rich title with icon
|
|
158
|
-
</span>
|
|
159
|
-
}
|
|
160
|
-
>
|
|
161
|
-
<p className="text-content-presentation-action-light-primary py-4">
|
|
162
|
-
The title prop is fully customizable.
|
|
163
|
-
</p>
|
|
164
|
-
</SectionBlock>
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Custom Fields Form
|
|
168
|
-
|
|
169
|
-
A common pattern: pair `SectionBlock` with a row layout to build labeled-field forms.
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
import { type ReactNode } from "react";
|
|
173
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
174
|
-
import { InputField } from "@/components/InputField";
|
|
175
|
-
import { ActionButton } from "@/components/ActionButton";
|
|
176
|
-
|
|
177
|
-
export function CustomFieldsForm() {
|
|
178
|
-
return (
|
|
179
|
-
<SectionBlock
|
|
180
|
-
color="Blue"
|
|
181
|
-
title={
|
|
182
|
-
<span className="flex items-center gap-[6px]">
|
|
183
|
-
<i className="ri-edit-box-line" />
|
|
184
|
-
Custom fields
|
|
185
|
-
</span>
|
|
186
|
-
}
|
|
187
|
-
>
|
|
188
|
-
<FieldRow
|
|
189
|
-
label="Name"
|
|
190
|
-
required
|
|
191
|
-
right={
|
|
192
|
-
<div className="flex flex-1 items-center gap-[12px]">
|
|
193
|
-
<InputField placeholder="First Name*" className="flex-1" />
|
|
194
|
-
<InputField placeholder="Last Name*" className="flex-1" />
|
|
195
|
-
</div>
|
|
196
|
-
}
|
|
197
|
-
/>
|
|
198
|
-
|
|
199
|
-
<RowDivider />
|
|
200
|
-
|
|
201
|
-
<FieldRow
|
|
202
|
-
label="Department"
|
|
203
|
-
right={<InputField placeholder="Write Hint Here" className="flex-1" />}
|
|
204
|
-
/>
|
|
205
|
-
|
|
206
|
-
<RowDivider />
|
|
207
|
-
|
|
208
|
-
<FieldRow
|
|
209
|
-
label="Alias names"
|
|
210
|
-
right={
|
|
211
|
-
<InputField
|
|
212
|
-
placeholder="Write Hint Here"
|
|
213
|
-
className="flex-1"
|
|
214
|
-
childrenSide={
|
|
215
|
-
<ActionButton aria-label="Add alias name">
|
|
216
|
-
<i className="ri-add-line" />
|
|
217
|
-
</ActionButton>
|
|
218
|
-
}
|
|
219
|
-
/>
|
|
220
|
-
}
|
|
221
|
-
/>
|
|
222
|
-
</SectionBlock>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
interface FieldRowProps {
|
|
227
|
-
label: string;
|
|
228
|
-
required?: boolean;
|
|
229
|
-
right: ReactNode;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function FieldRow({ label, required, right }: FieldRowProps) {
|
|
233
|
-
return (
|
|
234
|
-
<div className="flex items-center gap-[24px] py-[18px]">
|
|
235
|
-
<div className="flex w-[220px] shrink-0 items-center gap-[6px]">
|
|
236
|
-
<span className="typography-body-medium-regular text-content-presentation-action-light-primary">
|
|
237
|
-
{label}
|
|
238
|
-
</span>
|
|
239
|
-
{required && (
|
|
240
|
-
<span className="typography-body-small-medium text-content-presentation-state-negative">
|
|
241
|
-
(Required)
|
|
242
|
-
</span>
|
|
243
|
-
)}
|
|
244
|
-
</div>
|
|
245
|
-
<div className="flex flex-1 items-center">{right}</div>
|
|
246
|
-
</div>
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function RowDivider() {
|
|
251
|
-
return <div className="h-px w-full bg-border-presentation-global-primary" />;
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Bilingual Form with Language Switch (EN / AR)
|
|
256
|
-
|
|
257
|
-
A real-world pattern: a `SectionBlock` form with an EN/AR language switcher in the header. The colored title badge and the `TabSwitch` stay LTR; only the field rows flip to RTL when Arabic is selected, and all labels/placeholders are translated.
|
|
258
|
-
|
|
259
|
-
Key points:
|
|
260
|
-
|
|
261
|
-
- Put the `TabSwitch` in a `relative` wrapper and position it `absolute top-2 right-2` so it sits at the header's top-right **outside** the colored title badge (the badge wraps the entire `title` node).
|
|
262
|
-
- Apply `dir` to each field **row**, not to the `SectionBlock` root — otherwise the header (badge + switch) flips too.
|
|
263
|
-
- Drive copy through a tiny `t(en, ar)` helper keyed off the selected language.
|
|
264
|
-
|
|
265
|
-
```tsx
|
|
266
|
-
import { type ReactNode, useState } from "react";
|
|
267
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
268
|
-
import { InputField } from "@/components/InputField";
|
|
269
|
-
import { ActionButton } from "@/components/ActionButton";
|
|
270
|
-
import { TabSwitch } from "@/components/TabSwitch";
|
|
271
|
-
|
|
272
|
-
export function BilingualFieldsForm() {
|
|
273
|
-
const [language, setLanguage] = useState<"ar" | "en">("en");
|
|
274
|
-
const isAr = language === "ar";
|
|
275
|
-
const t = (en: string, ar: string) => (isAr ? ar : en);
|
|
276
|
-
|
|
277
|
-
return (
|
|
278
|
-
<div className="relative">
|
|
279
|
-
<SectionBlock
|
|
280
|
-
color="Blue"
|
|
281
|
-
title={
|
|
282
|
-
<span className="flex items-center gap-[6px]">
|
|
283
|
-
<i className="ri-edit-box-line" />
|
|
284
|
-
{t("Custom fields", "حقول مخصصة")}
|
|
285
|
-
</span>
|
|
286
|
-
}
|
|
287
|
-
>
|
|
288
|
-
<FieldRow
|
|
289
|
-
dir={isAr ? "rtl" : "ltr"}
|
|
290
|
-
label={t("Name", "الاسم")}
|
|
291
|
-
required
|
|
292
|
-
requiredLabel={t("(Required)", "(مطلوب)")}
|
|
293
|
-
right={
|
|
294
|
-
<div className="flex flex-1 items-center gap-[12px] min-w-0">
|
|
295
|
-
<InputField placeholder={t("First Name*", "الاسم الأول*")} className="flex-1 min-w-0" />
|
|
296
|
-
<InputField placeholder={t("Last Name*", "اسم العائلة*")} className="flex-1 min-w-0" />
|
|
297
|
-
</div>
|
|
298
|
-
}
|
|
299
|
-
/>
|
|
300
|
-
|
|
301
|
-
<RowDivider />
|
|
302
|
-
|
|
303
|
-
<FieldRow
|
|
304
|
-
dir={isAr ? "rtl" : "ltr"}
|
|
305
|
-
label={t("Department", "القسم")}
|
|
306
|
-
right={<InputField placeholder={t("Write Hint Here", "اكتب التلميح هنا")} className="flex-1" />}
|
|
307
|
-
/>
|
|
308
|
-
|
|
309
|
-
<RowDivider />
|
|
310
|
-
|
|
311
|
-
<FieldRow
|
|
312
|
-
dir={isAr ? "rtl" : "ltr"}
|
|
313
|
-
label={t("Alias names", "الأسماء المستعارة")}
|
|
314
|
-
right={
|
|
315
|
-
<InputField
|
|
316
|
-
placeholder={t("Write Hint Here", "اكتب التلميح هنا")}
|
|
317
|
-
className="flex-1"
|
|
318
|
-
childrenSide={
|
|
319
|
-
<ActionButton aria-label={t("Add alias name", "إضافة اسم مستعار")}>
|
|
320
|
-
<i className="ri-add-line" />
|
|
321
|
-
</ActionButton>
|
|
322
|
-
}
|
|
323
|
-
/>
|
|
324
|
-
}
|
|
325
|
-
/>
|
|
326
|
-
</SectionBlock>
|
|
327
|
-
|
|
328
|
-
<TabSwitch
|
|
329
|
-
className="absolute top-2 right-2 z-10"
|
|
330
|
-
size="S"
|
|
331
|
-
value={language}
|
|
332
|
-
onValueChange={setLanguage}
|
|
333
|
-
options={[
|
|
334
|
-
{ value: "en", label: "English" },
|
|
335
|
-
{ value: "ar", label: "العربية" },
|
|
336
|
-
]}
|
|
337
|
-
/>
|
|
338
|
-
</div>
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
interface FieldRowProps {
|
|
343
|
-
label: string;
|
|
344
|
-
required?: boolean;
|
|
345
|
-
requiredLabel?: string;
|
|
346
|
-
right: ReactNode;
|
|
347
|
-
dir?: "ltr" | "rtl";
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
function FieldRow({ label, required, requiredLabel = "(Required)", right, dir }: FieldRowProps) {
|
|
351
|
-
return (
|
|
352
|
-
<div dir={dir} className="flex items-center gap-[24px] py-[18px]">
|
|
353
|
-
<div className="flex w-[140px] shrink-0 items-center gap-[6px]">
|
|
354
|
-
<span className="typography-body-medium-regular text-content-presentation-action-light-primary">
|
|
355
|
-
{label}
|
|
356
|
-
</span>
|
|
357
|
-
{required && (
|
|
358
|
-
<span className="typography-body-small-medium text-content-presentation-state-negative">
|
|
359
|
-
{requiredLabel}
|
|
360
|
-
</span>
|
|
361
|
-
)}
|
|
362
|
-
</div>
|
|
363
|
-
<div className="flex flex-1 items-center min-w-0">{right}</div>
|
|
364
|
-
</div>
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
function RowDivider() {
|
|
369
|
-
return <div className="h-px w-full bg-border-presentation-global-primary" />;
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
### Table Variant
|
|
374
|
-
|
|
375
|
-
`variant="Table"` swaps the padded form body for the full-bleed table shell: the body loses
|
|
376
|
-
its `px-[42px]` gutter, gains a rule under the header, and the card is clipped to its 16px
|
|
377
|
-
radius with no bottom padding — so an end-action row meets the card edge.
|
|
378
|
-
|
|
379
|
-
The layout has three stacked parts, and the order matters. Only the **scroller** scrolls
|
|
380
|
-
horizontally; the header actions above it and the end-action below it stay put, which is
|
|
381
|
-
what keeps `Add New` reachable on a wide table.
|
|
382
|
-
|
|
383
|
-
The section body is itself the horizontal scrollport, so a table wider than the card scrolls
|
|
384
|
-
**inside** it rather than being clipped or widening the page. One consequence worth knowing: a
|
|
385
|
-
scrollport is the containing block for `position: sticky`, so a `Table`'s sticky header inside a
|
|
386
|
-
section now resolves against a box that never scrolls vertically — i.e. it stops sticking. If you
|
|
387
|
-
need a sticky header, give the table its own vertical scroller.
|
|
388
|
-
|
|
389
|
-
```tsx
|
|
390
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
391
|
-
import { Button } from "@/components/Button";
|
|
392
|
-
import {
|
|
393
|
-
Table,
|
|
394
|
-
TableBody,
|
|
395
|
-
TableCell,
|
|
396
|
-
TableEndAction,
|
|
397
|
-
TableHead,
|
|
398
|
-
TableHeader,
|
|
399
|
-
TableRow,
|
|
400
|
-
TableScroller,
|
|
401
|
-
} from "@/components/Table";
|
|
402
|
-
|
|
403
|
-
<SectionBlock
|
|
404
|
-
variant="Table"
|
|
405
|
-
color="Purple"
|
|
406
|
-
title="Items Table"
|
|
407
|
-
icon={<i className="ri-box-3-line text-[18px]" />}
|
|
408
|
-
action={
|
|
409
|
-
<>
|
|
410
|
-
<Button type="button" size="M" variant="BorderStyle" disabled>
|
|
411
|
-
Delete Row
|
|
412
|
-
</Button>
|
|
413
|
-
<Button type="button" size="M" variant="BluColStyle">
|
|
414
|
-
Add New
|
|
415
|
-
</Button>
|
|
416
|
-
</>
|
|
417
|
-
}
|
|
418
|
-
>
|
|
419
|
-
<TableScroller>
|
|
420
|
-
<Table className="min-w-full">
|
|
421
|
-
<TableHeader>
|
|
422
|
-
<TableRow>
|
|
423
|
-
<TableHead style={{ width: 200 }}>Items</TableHead>
|
|
424
|
-
<TableHead style={{ width: 200 }}>Label</TableHead>
|
|
425
|
-
</TableRow>
|
|
426
|
-
</TableHeader>
|
|
427
|
-
<TableBody>
|
|
428
|
-
<TableRow>
|
|
429
|
-
<TableCell minWidth={0}>Product name</TableCell>
|
|
430
|
-
<TableCell minWidth={0}>Label</TableCell>
|
|
431
|
-
</TableRow>
|
|
432
|
-
</TableBody>
|
|
433
|
-
</Table>
|
|
434
|
-
</TableScroller>
|
|
435
|
-
|
|
436
|
-
<TableEndAction>
|
|
437
|
-
<i className="ri-add-line" />
|
|
438
|
-
Add New
|
|
439
|
-
</TableEndAction>
|
|
440
|
-
</SectionBlock>
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
For a table that edits form values, don't hand-compose this — use
|
|
444
|
-
[`FormBuilder.Table`](./form-builder.md#field-components), which renders exactly this shell
|
|
445
|
-
and wires rows to `react-hook-form`.
|
|
446
|
-
|
|
447
|
-
### Custom Layout (override defaults)
|
|
448
|
-
|
|
449
|
-
Use `containerClassName`, `headerClassName`, and `bodyClassName` to override the built-in spacing and width without losing the title/body structure.
|
|
450
|
-
|
|
451
|
-
```tsx
|
|
452
|
-
<SectionBlock
|
|
453
|
-
color="Green"
|
|
454
|
-
title="Compact card"
|
|
455
|
-
containerClassName="w-[600px] pt-[4px] pb-[16px]"
|
|
456
|
-
bodyClassName="px-[24px]"
|
|
457
|
-
>
|
|
458
|
-
<p className="text-content-presentation-action-light-primary py-2">
|
|
459
|
-
Tighter, narrower variant.
|
|
460
|
-
</p>
|
|
461
|
-
</SectionBlock>
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
## Patterns
|
|
465
|
-
|
|
466
|
-
- **Color coding**: Use distinct colors to help users scan a page of multiple sections (e.g., Blue for primary forms, Yellow for warnings, Red for destructive zones).
|
|
467
|
-
- **No-title sections**: Drop the `title` prop entirely when the section's purpose is obvious from context — keeps the body padding without the visual weight of a header.
|
|
468
|
-
- **Composing with form fields**: `SectionBlock` does not impose any inner layout — pair it with helpers like the `FieldRow` pattern above, or with `InputField`, `Form`, or `FieldSection` for more structured forms.
|
|
469
|
-
- **Width**: The component is `w-full` — it fills its parent. Constrain it from the outside, or with `containerClassName="max-w-[1100px]"`.
|
|
470
|
-
|
|
471
|
-
## Accessibility
|
|
472
|
-
|
|
473
|
-
- The container is a plain `<div>`. If the section represents a distinct landmark, add `role="region"` and an `aria-label` (or use `aria-labelledby` pointing at the title).
|
|
474
|
-
- The title is rendered as styled text inside a badge `<div>`, not as a heading element. If the section needs a heading semantically, wrap your `title` content in an appropriate `<h2>`/`<h3>` and reset its margin via Tailwind classes.
|
|
475
|
-
|
|
476
|
-
## Troubleshooting
|
|
477
|
-
|
|
478
|
-
| Issue | Fix |
|
|
479
|
-
|-------|-----|
|
|
480
|
-
| Card overflows on small screens | The card is `w-full`; the overflow is coming from its content. Give the content `min-w-0`, or cap the card with `containerClassName="max-w-[…]"`. |
|
|
481
|
-
| Title not showing | The `title` prop is optional — omitting it hides the entire header. Pass any non-null `ReactNode` to render it. |
|
|
482
|
-
| Badge color looks wrong | `color` only accepts the predefined `SectionColor` values. For custom badge colors, override via `headerClassName` and a custom child node. |
|
|
483
|
-
| Need a different background | The body uses `bg-background-presentation-form-base`. Override via `containerClassName` (your class wins via `cn()` merging). |
|