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,168 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { ReactNode, useEffect } from "react";
|
|
4
|
-
import {
|
|
5
|
-
useFormContext,
|
|
6
|
-
useFormState,
|
|
7
|
-
type ControllerRenderProps,
|
|
8
|
-
type ControllerFieldState,
|
|
9
|
-
type FieldErrors,
|
|
10
|
-
type FieldValues,
|
|
11
|
-
type FieldPath,
|
|
12
|
-
} from "react-hook-form";
|
|
13
|
-
|
|
14
|
-
import { FieldSection } from "../../../layouts/FieldSection";
|
|
15
|
-
import { FormField, FormItem, FormControl } from "../../Form";
|
|
16
|
-
import { FieldHint } from "../../FieldHint";
|
|
17
|
-
import { useDirection, useStepRegistry, useBare, useRequiredLabel } from "../context";
|
|
18
|
-
import type { FieldHintSpec } from "../types";
|
|
19
|
-
|
|
20
|
-
export interface FieldShellProps {
|
|
21
|
-
name: string;
|
|
22
|
-
label?: ReactNode;
|
|
23
|
-
description?: ReactNode;
|
|
24
|
-
required?: boolean;
|
|
25
|
-
fullWidth?: boolean;
|
|
26
|
-
hidden?: boolean;
|
|
27
|
-
/** Force the field's layout direction, overriding the form's `useDirection()` context. */
|
|
28
|
-
direction?: "horizontal" | "vertical" | "flexible";
|
|
29
|
-
/** Alerts stacked under the validation error. See `FieldHintSpec`. */
|
|
30
|
-
hints?: FieldHintSpec[];
|
|
31
|
-
/** The input, wired to the react-hook-form field. */
|
|
32
|
-
children: (
|
|
33
|
-
field: ControllerRenderProps<FieldValues, string>,
|
|
34
|
-
fieldState: ControllerFieldState,
|
|
35
|
-
) => ReactNode;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Shared wrapper for every `FormBuilder.*` field: the FieldSection row + the RHF
|
|
40
|
-
* `FormField`/`FormItem`/`FormControl`/`FormMessage` scaffolding. Also registers the
|
|
41
|
-
* field name into the enclosing `FormRenderer.Step` (if any) so the stepper can
|
|
42
|
-
* validate per step.
|
|
43
|
-
*/
|
|
44
|
-
export function FieldShell({
|
|
45
|
-
name,
|
|
46
|
-
label,
|
|
47
|
-
description,
|
|
48
|
-
required,
|
|
49
|
-
fullWidth,
|
|
50
|
-
hidden,
|
|
51
|
-
direction: directionProp,
|
|
52
|
-
hints,
|
|
53
|
-
children,
|
|
54
|
-
}: FieldShellProps) {
|
|
55
|
-
const form = useFormContext();
|
|
56
|
-
const bare = useBare();
|
|
57
|
-
const ctxDirection = useDirection();
|
|
58
|
-
// LOCAL PATCH (Contact Center): upstream hardcodes "(Required)". See context.ts.
|
|
59
|
-
const requiredLabel = useRequiredLabel();
|
|
60
|
-
// A field may pin its own direction (e.g. RichText forces vertical), else the form's. When
|
|
61
|
-
// neither is set this stays `undefined` — FieldSection then falls back to its responsive
|
|
62
|
-
// `flexible` layout rather than a fixed two-column one.
|
|
63
|
-
const direction = directionProp ?? ctxDirection;
|
|
64
|
-
const step = useStepRegistry();
|
|
65
|
-
|
|
66
|
-
// Read this field's error at the shell level (not inside the FormField render) so
|
|
67
|
-
// the FieldHint can go in FieldSection's `childrenUnderLabel` — under the label.
|
|
68
|
-
// Subscribe to the whole `errors` object and resolve the field's path ourselves:
|
|
69
|
-
// `getFieldState(name)` misses controls that register late (DatePicker, RichText),
|
|
70
|
-
// whereas the errors object always carries every failing key from the resolver.
|
|
71
|
-
const { errors } = useFormState({ control: form.control });
|
|
72
|
-
const fieldError = resolveFieldError(errors, name);
|
|
73
|
-
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (!step) return;
|
|
76
|
-
step.register(name);
|
|
77
|
-
return () => step.unregister(name);
|
|
78
|
-
}, [step, name]);
|
|
79
|
-
|
|
80
|
-
if (hidden) return null;
|
|
81
|
-
|
|
82
|
-
// Chrome-less mode — a `FormBuilder.Table` cell (`"table"`) or a panel field (`"bare"`).
|
|
83
|
-
// Render just the control: no FieldSection label/row, so a row stays one line tall. Step
|
|
84
|
-
// registration above still applies. The control's border treatment is the caller's call,
|
|
85
|
-
// via `useOnTable`.
|
|
86
|
-
//
|
|
87
|
-
// LOCAL PATCH (Contact Center): the error Tooltip that used to wrap the control is gone.
|
|
88
|
-
// Upstream bound it to `open={Boolean(fieldError)}`, so it was not a hover tooltip at all — it
|
|
89
|
-
// was a bubble pinned open for as long as the field was invalid, anchored `top`, which in a
|
|
90
|
-
// table's first row sat directly on top of the column header. Several invalid cells meant
|
|
91
|
-
// several permanent bubbles over the header row. Its `TooltipTrigger` also stamped
|
|
92
|
-
// `aria-label="Open tooltip"` onto EVERY cell wrapper, error or not, so a screen reader
|
|
93
|
-
// announced every table input that way.
|
|
94
|
-
//
|
|
95
|
-
// The controls already signal invalidity themselves (`state="negative"` / `invalid`), so the
|
|
96
|
-
// red border remains; only the bubble is dropped. Re-apply after any `npx torch-glare update`.
|
|
97
|
-
if (bare) {
|
|
98
|
-
return (
|
|
99
|
-
<FormField
|
|
100
|
-
control={form.control}
|
|
101
|
-
name={name as FieldPath<FieldValues>}
|
|
102
|
-
render={({ field, fieldState }) => (
|
|
103
|
-
<FormItem className="w-full">
|
|
104
|
-
<FormControl>
|
|
105
|
-
<div className="w-full">{children(field, fieldState)}</div>
|
|
106
|
-
</FormControl>
|
|
107
|
-
</FormItem>
|
|
108
|
-
)}
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<FieldSection
|
|
115
|
-
label={label}
|
|
116
|
-
requiredLabel={required ? requiredLabel : undefined}
|
|
117
|
-
secondaryLabel={description}
|
|
118
|
-
direction={direction}
|
|
119
|
-
className={fullWidth ? "max-w-full" : undefined}
|
|
120
|
-
childrenUnderLabel={<FieldMessages message={fieldError} hints={hints} />}
|
|
121
|
-
>
|
|
122
|
-
<FormField
|
|
123
|
-
control={form.control}
|
|
124
|
-
name={name as FieldPath<FieldValues>}
|
|
125
|
-
render={({ field, fieldState }) => (
|
|
126
|
-
<FormItem className="w-full">
|
|
127
|
-
<FormControl>
|
|
128
|
-
<div className="w-full">{children(field, fieldState)}</div>
|
|
129
|
-
</FormControl>
|
|
130
|
-
</FormItem>
|
|
131
|
-
)}
|
|
132
|
-
/>
|
|
133
|
-
</FieldSection>
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* The stack under a field: the validation error first (it is the actionable one), then any author
|
|
139
|
-
* `hints` in order. Renders nothing when there is neither, so a field without hints is unchanged.
|
|
140
|
-
*/
|
|
141
|
-
function FieldMessages({ message, hints }: { message?: string; hints?: FieldHintSpec[] }) {
|
|
142
|
-
if (!message && !hints?.length) return null;
|
|
143
|
-
return (
|
|
144
|
-
<div className="flex flex-col items-start gap-[4px]">
|
|
145
|
-
{message && <FieldHint state="error" label={message} />}
|
|
146
|
-
{hints?.map((hint, i) => (
|
|
147
|
-
<FieldHint key={i} state={hint.state ?? "info"} label={hint.label} icon={hint.icon} />
|
|
148
|
-
))}
|
|
149
|
-
</div>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Resolve a field's error message from the RHF `errors` tree by its dotted `name`
|
|
155
|
-
* (handles nested field-array paths like `contacts.0.email`). Reading the errors
|
|
156
|
-
* object directly is more reliable than `getFieldState` for controls that register
|
|
157
|
-
* late (DatePicker, RichText), whose hints were otherwise missing.
|
|
158
|
-
*/
|
|
159
|
-
function resolveFieldError(errors: FieldErrors, name: string): string | undefined {
|
|
160
|
-
const node = name
|
|
161
|
-
.split(".")
|
|
162
|
-
.reduce<unknown>(
|
|
163
|
-
(acc, key) => (acc == null ? undefined : (acc as Record<string, unknown>)[key]),
|
|
164
|
-
errors,
|
|
165
|
-
);
|
|
166
|
-
const message = (node as { message?: unknown } | undefined)?.message;
|
|
167
|
-
return typeof message === "string" ? message : undefined;
|
|
168
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { ImageAttachment } from "../../ImageAttachment";
|
|
4
|
-
import { useLoading } from "../context";
|
|
5
|
-
import type { FileFieldProps } from "../types";
|
|
6
|
-
import { FieldShell } from "./FieldShell";
|
|
7
|
-
|
|
8
|
-
/** `FormBuilder.File` / `.Image` — stores the selected `File` (consumer uploads). */
|
|
9
|
-
export function FileField(props: FileFieldProps & { image?: boolean }) {
|
|
10
|
-
const loading = useLoading();
|
|
11
|
-
return (
|
|
12
|
-
<FieldShell {...props}>
|
|
13
|
-
{(field) => {
|
|
14
|
-
const current: unknown = field.value;
|
|
15
|
-
const fileName = Array.isArray(current)
|
|
16
|
-
? `${current.length} file(s)`
|
|
17
|
-
: current instanceof File
|
|
18
|
-
? current.name
|
|
19
|
-
: "";
|
|
20
|
-
return (
|
|
21
|
-
<ImageAttachment
|
|
22
|
-
mainLabel={props.placeholder ?? (props.image ? "Upload image" : "Upload file")}
|
|
23
|
-
secondaryLabel={
|
|
24
|
-
fileName || (typeof props.description === "string" ? props.description : "")
|
|
25
|
-
}
|
|
26
|
-
accept={props.accept ?? (props.image ? "image/*" : undefined)}
|
|
27
|
-
multiple={props.multiple}
|
|
28
|
-
disabled={props.disabled || loading}
|
|
29
|
-
onChange={(e) => {
|
|
30
|
-
const files = (e.target as HTMLInputElement).files;
|
|
31
|
-
if (!files || files.length === 0) return;
|
|
32
|
-
field.onChange(props.multiple ? Array.from(files) : files[0]);
|
|
33
|
-
}}
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
}}
|
|
37
|
-
</FieldShell>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { ReactNode } from "react";
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../../utils/cn";
|
|
6
|
-
import { Label } from "../../Label";
|
|
7
|
-
import { RadioGroup, Radio } from "../../Radio";
|
|
8
|
-
import { Checkbox } from "../../Checkbox";
|
|
9
|
-
import { useLoading } from "../context";
|
|
10
|
-
import type { OptionItem, OptionsFieldProps } from "../types";
|
|
11
|
-
import { FieldShell } from "./FieldShell";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The `#f9f9f9` rounded box that holds the option rows, with a full-width divider
|
|
15
|
-
* between each (design nodes 8999:170512 / 8999:170546).
|
|
16
|
-
*/
|
|
17
|
-
function OptionBox({ children }: { children: ReactNode }) {
|
|
18
|
-
return (
|
|
19
|
-
<div
|
|
20
|
-
className={cn(
|
|
21
|
-
"flex w-full flex-col rounded-[8px] px-[10px]",
|
|
22
|
-
"bg-background-presentation-form-field-primary",
|
|
23
|
-
"divide-y divide-border-presentation-global-primary",
|
|
24
|
-
)}
|
|
25
|
-
>
|
|
26
|
-
{children}
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* One option row: control on the **left**, then the primary label and an optional
|
|
33
|
-
* secondary label. Uses the `Label` component so the row is a real `<label>` — the
|
|
34
|
-
* whole row is clickable and toggles the control (same mechanism as `LabeledCheckBox`
|
|
35
|
-
* / `LabeledRadio`). `w-full` makes the entire row width tappable; `reverseChildren`
|
|
36
|
-
* puts the control first (left) and `justify-end` keeps the content left-packed.
|
|
37
|
-
*/
|
|
38
|
-
function OptionRow({
|
|
39
|
-
control,
|
|
40
|
-
label,
|
|
41
|
-
description,
|
|
42
|
-
}: {
|
|
43
|
-
control: ReactNode;
|
|
44
|
-
label?: string;
|
|
45
|
-
description?: string;
|
|
46
|
-
}) {
|
|
47
|
-
return (
|
|
48
|
-
<Label
|
|
49
|
-
label={label}
|
|
50
|
-
secondaryLabel={description}
|
|
51
|
-
labelDirections="horizontal"
|
|
52
|
-
childrenDirections="horizontal"
|
|
53
|
-
reverseChildren
|
|
54
|
-
className="w-full cursor-pointer justify-end gap-[6px] py-[8px]"
|
|
55
|
-
>
|
|
56
|
-
{control}
|
|
57
|
-
</Label>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* `FormBuilder.RadioList` — single-select options (`string`) as a boxed, divided list
|
|
63
|
-
* (design nodes 8999:170512). Uses the Radix `RadioGroup` for roving-focus / arrow-key nav.
|
|
64
|
-
*/
|
|
65
|
-
export function RadioListField(props: OptionsFieldProps) {
|
|
66
|
-
const loading = useLoading();
|
|
67
|
-
return (
|
|
68
|
-
<FieldShell {...props}>
|
|
69
|
-
{(field) => (
|
|
70
|
-
<RadioGroup value={field.value ?? ""} onValueChange={field.onChange} className="w-full">
|
|
71
|
-
<OptionBox>
|
|
72
|
-
{props.options.map((opt: OptionItem) => (
|
|
73
|
-
<OptionRow
|
|
74
|
-
key={opt.value}
|
|
75
|
-
label={opt.label}
|
|
76
|
-
description={opt.description}
|
|
77
|
-
control={
|
|
78
|
-
<Radio
|
|
79
|
-
id={`${props.name}-${opt.value}`}
|
|
80
|
-
value={opt.value}
|
|
81
|
-
size="S"
|
|
82
|
-
disabled={props.disabled || loading}
|
|
83
|
-
/>
|
|
84
|
-
}
|
|
85
|
-
/>
|
|
86
|
-
))}
|
|
87
|
-
</OptionBox>
|
|
88
|
-
</RadioGroup>
|
|
89
|
-
)}
|
|
90
|
-
</FieldShell>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* `FormBuilder.CheckboxGroup` — multi-select options as a boxed, divided list (design
|
|
96
|
-
* node 8999:170546). Value is a `string[]` of the selected option values.
|
|
97
|
-
*/
|
|
98
|
-
export function CheckboxGroupField(props: OptionsFieldProps) {
|
|
99
|
-
const loading = useLoading();
|
|
100
|
-
return (
|
|
101
|
-
<FieldShell {...props}>
|
|
102
|
-
{(field) => {
|
|
103
|
-
const selected: string[] = Array.isArray(field.value) ? field.value : [];
|
|
104
|
-
const toggle = (value: string, checked: boolean) => {
|
|
105
|
-
field.onChange(checked ? [...selected, value] : selected.filter((v) => v !== value));
|
|
106
|
-
};
|
|
107
|
-
return (
|
|
108
|
-
<div role="group" aria-label={typeof props.label === "string" ? props.label : undefined}>
|
|
109
|
-
<OptionBox>
|
|
110
|
-
{props.options.map((opt: OptionItem) => (
|
|
111
|
-
<OptionRow
|
|
112
|
-
key={opt.value}
|
|
113
|
-
label={opt.label}
|
|
114
|
-
description={opt.description}
|
|
115
|
-
control={
|
|
116
|
-
<Checkbox
|
|
117
|
-
id={`${props.name}-${opt.value}`}
|
|
118
|
-
size="S"
|
|
119
|
-
checked={selected.includes(opt.value)}
|
|
120
|
-
onCheckedChange={(checked) => toggle(opt.value, checked === true)}
|
|
121
|
-
disabled={props.disabled || loading}
|
|
122
|
-
/>
|
|
123
|
-
}
|
|
124
|
-
/>
|
|
125
|
-
))}
|
|
126
|
-
</OptionBox>
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
129
|
-
}}
|
|
130
|
-
</FieldShell>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { InputOTP, InputOTPGroup, InputOTPSlot } from "../../InputOTP";
|
|
4
|
-
import { useLoading } from "../context";
|
|
5
|
-
import type { OtpFieldProps } from "../types";
|
|
6
|
-
import { FieldShell } from "./FieldShell";
|
|
7
|
-
|
|
8
|
-
/** `FormBuilder.Otp` — a code / PIN input (Glare `InputOTP`). Value is a string. */
|
|
9
|
-
export function OtpField(props: OtpFieldProps) {
|
|
10
|
-
const loading = useLoading();
|
|
11
|
-
const length = props.length ?? 6;
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<FieldShell {...props}>
|
|
15
|
-
{(field) => (
|
|
16
|
-
<InputOTP
|
|
17
|
-
maxLength={length}
|
|
18
|
-
value={field.value ?? ""}
|
|
19
|
-
onChange={(v: string) => field.onChange(v)}
|
|
20
|
-
disabled={props.disabled || loading}
|
|
21
|
-
>
|
|
22
|
-
<InputOTPGroup>
|
|
23
|
-
{Array.from({ length }, (_, i) => (
|
|
24
|
-
<InputOTPSlot key={i} index={i} />
|
|
25
|
-
))}
|
|
26
|
-
</InputOTPGroup>
|
|
27
|
-
</InputOTP>
|
|
28
|
-
)}
|
|
29
|
-
</FieldShell>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { SearchableSelect } from "../../SearchableSelect";
|
|
4
|
-
import { InputField } from "../../InputField";
|
|
5
|
-
import { cn } from "../../../utils/cn";
|
|
6
|
-
import { useLoading, useBare, useOnTable } from "../context";
|
|
7
|
-
import type { PhoneFieldProps } from "../types";
|
|
8
|
-
import { FieldShell } from "./FieldShell";
|
|
9
|
-
import { COUNTRIES, countryByCode, countryByDial, flagEmoji } from "./countries";
|
|
10
|
-
|
|
11
|
-
// Dial codes longest-first, so "+1" doesn't shadow "+1…"-style codes when prefix-matching.
|
|
12
|
-
const DIALS = [...new Set(COUNTRIES.map((c) => c.dial))].sort((a, b) => b.length - a.length);
|
|
13
|
-
|
|
14
|
-
// Country picker rows. Keyed by the unique ISO code; the row shows flag + dial, but `searchText`
|
|
15
|
-
// makes filtering match the country NAME (typing a dial code won't match).
|
|
16
|
-
const COUNTRY_OPTIONS = COUNTRIES.map((c) => ({
|
|
17
|
-
value: c.code,
|
|
18
|
-
label: `${flagEmoji(c.code)} ${c.dial}`,
|
|
19
|
-
searchText: c.name,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
function splitPhone(value: unknown, defaultDial: string): { dial: string; number: string } {
|
|
23
|
-
const s = typeof value === "string" ? value.trim() : "";
|
|
24
|
-
if (!s) return { dial: defaultDial, number: "" };
|
|
25
|
-
const idx = s.indexOf(" ");
|
|
26
|
-
if (s.startsWith("+") && idx > 0) {
|
|
27
|
-
return { dial: s.slice(0, idx), number: s.slice(idx + 1).trim() };
|
|
28
|
-
}
|
|
29
|
-
if (s.startsWith("+")) {
|
|
30
|
-
const dial = DIALS.find((d) => s.startsWith(d));
|
|
31
|
-
if (dial) return { dial, number: s.slice(dial.length).trim() };
|
|
32
|
-
}
|
|
33
|
-
return { dial: defaultDial, number: s };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* `FormBuilder.Phone` — country dial-code (every country) + number. The picker is a
|
|
38
|
-
* `SearchableSelect` keyed by the unique ISO code (dial codes repeat) — type to filter by
|
|
39
|
-
* country name or dial. The value is stored as a `"+<dial> <number>"` string.
|
|
40
|
-
*
|
|
41
|
-
* **Inside a `FormBuilder.Table` cell** this collapses to a single plain number input: the
|
|
42
|
-
* fixed-width picker imposed a ~155px floor on the column and left the number truncated,
|
|
43
|
-
* and two controls in one cell is not a table column. Add a separate column (e.g. a
|
|
44
|
-
* `FormBuilder.Select` of dial codes) when a table needs the country code.
|
|
45
|
-
*/
|
|
46
|
-
export function PhoneField(props: PhoneFieldProps) {
|
|
47
|
-
const loading = useLoading();
|
|
48
|
-
// Neither a table cell nor a narrow config rail has room for the dial-code composite, so both
|
|
49
|
-
// collapse to a single tel input — but only a real table cell takes the flush border.
|
|
50
|
-
const bare = useBare();
|
|
51
|
-
const onTable = useOnTable();
|
|
52
|
-
const defaultDial = props.defaultCountry ?? "+964"; // Iraq
|
|
53
|
-
|
|
54
|
-
if (bare) {
|
|
55
|
-
return (
|
|
56
|
-
<FieldShell {...props}>
|
|
57
|
-
{(field) => (
|
|
58
|
-
<InputField
|
|
59
|
-
type="tel"
|
|
60
|
-
inputMode="tel"
|
|
61
|
-
value={typeof field.value === "string" ? field.value : ""}
|
|
62
|
-
onChange={(e) => field.onChange(e.target.value.replace(/[^\d\s+-]/g, ""))}
|
|
63
|
-
onBlur={field.onBlur}
|
|
64
|
-
placeholder={props.placeholder ?? "Phone number"}
|
|
65
|
-
disabled={props.disabled || loading}
|
|
66
|
-
onTable={onTable}
|
|
67
|
-
className="w-full"
|
|
68
|
-
/>
|
|
69
|
-
)}
|
|
70
|
-
</FieldShell>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return (
|
|
75
|
-
<FieldShell {...props}>
|
|
76
|
-
{(field) => {
|
|
77
|
-
const { dial, number } = splitPhone(field.value, defaultDial);
|
|
78
|
-
const country = countryByDial(dial);
|
|
79
|
-
const disabled = props.disabled || loading;
|
|
80
|
-
const commit = (d: string, n: string) => field.onChange(n ? `${d} ${n}` : d);
|
|
81
|
-
return (
|
|
82
|
-
<div className="flex w-full min-w-0 items-center gap-2">
|
|
83
|
-
{/* Searchable country picker — filter by name or dial; rows carry the full country name. */}
|
|
84
|
-
<SearchableSelect
|
|
85
|
-
options={COUNTRY_OPTIONS}
|
|
86
|
-
value={country?.code ?? null}
|
|
87
|
-
onValueChange={(code) => commit(countryByCode(code)?.dial ?? dial, number)}
|
|
88
|
-
placeholder="+964"
|
|
89
|
-
size="M"
|
|
90
|
-
inputClassName="w-[100px] min-w-[0px]"
|
|
91
|
-
className={cn("w-[113px] shrink-0", disabled && "pointer-events-none opacity-60")}
|
|
92
|
-
/>
|
|
93
|
-
<div className="min-w-0 flex-1">
|
|
94
|
-
<InputField
|
|
95
|
-
type="tel"
|
|
96
|
-
inputMode="tel"
|
|
97
|
-
value={number}
|
|
98
|
-
onChange={(e) => commit(dial, e.target.value.replace(/[^\d\s-]/g, ""))}
|
|
99
|
-
placeholder={props.placeholder ?? "Phone number"}
|
|
100
|
-
disabled={disabled}
|
|
101
|
-
className="w-full"
|
|
102
|
-
/>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
}}
|
|
107
|
-
</FieldShell>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import type { OutputData } from "@editorjs/editorjs";
|
|
4
|
-
|
|
5
|
-
// Import the lazy wrapper from its file directly, NOT the folder barrel: the barrel
|
|
6
|
-
// statically re-exports `TextEditor` (which loads EditorJS at module init) and would drag
|
|
7
|
-
// it into the SSR bundle, crashing server rendering. This path stays SSR-safe (lazy inside).
|
|
8
|
-
import { RichTextField as RichTextEditor } from "../../TextEditor/RichTextField";
|
|
9
|
-
import type { BaseFieldProps } from "../types";
|
|
10
|
-
import { FieldShell } from "./FieldShell";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* `FormBuilder.RichText` — EditorJS content (value = `OutputData`).
|
|
14
|
-
*
|
|
15
|
-
* Forced to a **vertical, full-width** layout (label on top, editor below spanning the whole
|
|
16
|
-
* section): the editor + its toolbar need the full width, not the cramped right column.
|
|
17
|
-
*/
|
|
18
|
-
export function RichTextField(props: BaseFieldProps) {
|
|
19
|
-
return (
|
|
20
|
-
<FieldShell {...props} direction="vertical" fullWidth>
|
|
21
|
-
{(field) => (
|
|
22
|
-
<RichTextEditor
|
|
23
|
-
data={field.value as OutputData | undefined}
|
|
24
|
-
onChange={field.onChange}
|
|
25
|
-
readOnly={props.disabled}
|
|
26
|
-
placeholder={props.placeholder}
|
|
27
|
-
/>
|
|
28
|
-
)}
|
|
29
|
-
</FieldShell>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { SearchableSelect } from "../../SearchableSelect";
|
|
4
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../Select";
|
|
5
|
-
import { BadgeField } from "../../BadgeField";
|
|
6
|
-
import type { Tag } from "../../../hooks/useTagSelection";
|
|
7
|
-
import { useLoading, useOnTable } from "../context";
|
|
8
|
-
import type { SelectFieldProps, SearchableSelectFieldProps, OptionsFieldProps } from "../types";
|
|
9
|
-
import { FieldShell } from "./FieldShell";
|
|
10
|
-
|
|
11
|
-
/** `FormBuilder.Select` — the plain `Select` dropdown. */
|
|
12
|
-
export function SelectField(props: SelectFieldProps) {
|
|
13
|
-
const loading = useLoading();
|
|
14
|
-
const onTable = useOnTable();
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<FieldShell {...props}>
|
|
18
|
-
{(field) => (
|
|
19
|
-
<Select
|
|
20
|
-
value={typeof field.value === "string" ? field.value : ""}
|
|
21
|
-
onValueChange={field.onChange}
|
|
22
|
-
disabled={props.disabled || loading}
|
|
23
|
-
>
|
|
24
|
-
<SelectTrigger size="XL" onTable={onTable} className="w-full">
|
|
25
|
-
<SelectValue placeholder={props.placeholder ?? "Select…"} />
|
|
26
|
-
</SelectTrigger>
|
|
27
|
-
<SelectContent>
|
|
28
|
-
{props.options.map((opt) => (
|
|
29
|
-
<SelectItem key={opt.value} value={opt.value}>
|
|
30
|
-
{opt.label}
|
|
31
|
-
</SelectItem>
|
|
32
|
-
))}
|
|
33
|
-
</SelectContent>
|
|
34
|
-
</Select>
|
|
35
|
-
)}
|
|
36
|
-
</FieldShell>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* `FormBuilder.SearchableSelect` — the `SearchableSelect` combobox: a search box with
|
|
42
|
-
* client-side filtering, or server-side search + infinite scroll via the async props.
|
|
43
|
-
*/
|
|
44
|
-
export function SearchableSelectField(props: SearchableSelectFieldProps) {
|
|
45
|
-
const onTable = useOnTable();
|
|
46
|
-
return (
|
|
47
|
-
<FieldShell {...props}>
|
|
48
|
-
{(field) => (
|
|
49
|
-
<SearchableSelect
|
|
50
|
-
options={props.options}
|
|
51
|
-
value={field.value ?? null}
|
|
52
|
-
onValueChange={(value) => field.onChange(value)}
|
|
53
|
-
placeholder={props.placeholder ?? "Select…"}
|
|
54
|
-
filterClientSide={props.filterClientSide ?? true}
|
|
55
|
-
onSearchChange={props.onSearchChange}
|
|
56
|
-
onLoadMore={props.onLoadMore}
|
|
57
|
-
hasMore={props.hasMore}
|
|
58
|
-
loading={props.loading}
|
|
59
|
-
onTable={onTable}
|
|
60
|
-
className="w-full"
|
|
61
|
-
/>
|
|
62
|
-
)}
|
|
63
|
-
</FieldShell>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* `FormBuilder.MultiSelect` / `.Tags` — BadgeField, value is `string[]`.
|
|
69
|
-
*
|
|
70
|
-
* With `creatable`, the user can type a value that is not in `options` and it becomes a badge —
|
|
71
|
-
* so a free-text list (emails, aliases, tags) is one field rather than a one-column table. Pass
|
|
72
|
-
* `options={[]}` for a pure free-text list.
|
|
73
|
-
*/
|
|
74
|
-
export function MultiSelectField(props: OptionsFieldProps) {
|
|
75
|
-
const onTable = useOnTable();
|
|
76
|
-
return (
|
|
77
|
-
<FieldShell {...props}>
|
|
78
|
-
{(field) => {
|
|
79
|
-
const values: string[] = Array.isArray(field.value) ? field.value : [];
|
|
80
|
-
const byValue = new Map(props.options.map((opt) => [opt.value, opt]));
|
|
81
|
-
// Selected first, IN VALUE ORDER, then whatever is left to offer. Order matters: the
|
|
82
|
-
// hook re-syncs from this list, so building it in `options` order would reshuffle the
|
|
83
|
-
// user's badges on every keystroke — and drop any created value that is not an option.
|
|
84
|
-
const tags: Tag[] = [
|
|
85
|
-
...values.map((value) => ({
|
|
86
|
-
id: value,
|
|
87
|
-
name: byValue.get(value)?.label ?? value,
|
|
88
|
-
value,
|
|
89
|
-
isSelected: true,
|
|
90
|
-
})),
|
|
91
|
-
...props.options
|
|
92
|
-
.filter((opt) => !values.includes(opt.value))
|
|
93
|
-
.map((opt) => ({
|
|
94
|
-
id: opt.value,
|
|
95
|
-
name: opt.label,
|
|
96
|
-
value: opt.value,
|
|
97
|
-
isSelected: false,
|
|
98
|
-
})),
|
|
99
|
-
];
|
|
100
|
-
return (
|
|
101
|
-
<BadgeField
|
|
102
|
-
tags={tags}
|
|
103
|
-
creatable={props.creatable}
|
|
104
|
-
placeholder={props.placeholder}
|
|
105
|
-
disabled={props.disabled}
|
|
106
|
-
onValueChange={(picked) => field.onChange(picked.map((t) => t.value ?? t.id))}
|
|
107
|
-
onTable={onTable}
|
|
108
|
-
className="w-full"
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
}}
|
|
112
|
-
</FieldShell>
|
|
113
|
-
);
|
|
114
|
-
}
|