torch-glare 2.3.0 → 2.4.1
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 +8 -0
- package/apps/lib/components/ActionButton.tsx +7 -12
- package/apps/lib/components/ActionsGroup.tsx +4 -15
- package/apps/lib/components/AlertDialog.tsx +173 -191
- package/apps/lib/components/Avatar.tsx +13 -16
- package/apps/lib/components/Badge.tsx +7 -3
- package/apps/lib/components/BadgeField.tsx +76 -71
- package/apps/lib/components/Breadcrumb.tsx +49 -85
- package/apps/lib/components/Button.tsx +20 -19
- package/apps/lib/components/ButtonGroup.tsx +31 -41
- package/apps/lib/components/Calendar.tsx +51 -29
- package/apps/lib/components/Card.tsx +2 -13
- package/apps/lib/components/ChartBlockTool.ts +17 -52
- package/apps/lib/components/Checkbox.tsx +9 -16
- package/apps/lib/components/ContextMenu.tsx +110 -106
- package/apps/lib/components/CountBadge.tsx +4 -6
- package/apps/lib/components/DataTable.tsx +196 -216
- package/apps/lib/components/DataViews/DataViewRadio.tsx +10 -8
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +21 -55
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
- package/apps/lib/components/DataViews/FilterPanel.tsx +173 -150
- package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
- package/apps/lib/components/DataViews/InboxView.tsx +22 -68
- package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
- package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
- package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
- package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
- package/apps/lib/components/DataViews/TableView.tsx +8 -28
- package/apps/lib/components/DataViews/TreeView.tsx +12 -40
- package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
- package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +87 -0
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
- package/apps/lib/components/DataViews/index.ts +26 -26
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
- package/apps/lib/components/DataViews/types.ts +111 -114
- package/apps/lib/components/DatePicker.tsx +198 -191
- package/apps/lib/components/Dialog.tsx +92 -105
- package/apps/lib/components/Divider.tsx +21 -24
- package/apps/lib/components/Drawer.tsx +79 -139
- package/apps/lib/components/DropdownMenu.tsx +144 -181
- package/apps/lib/components/FieldHint.tsx +4 -11
- package/apps/lib/components/Form.tsx +146 -155
- package/apps/lib/components/FormStepper.tsx +9 -39
- package/apps/lib/components/HeaderBar.tsx +119 -0
- package/apps/lib/components/ImageAttachment.tsx +111 -73
- package/apps/lib/components/InnerLabelField.tsx +20 -16
- package/apps/lib/components/Input.tsx +171 -172
- package/apps/lib/components/InputField.tsx +44 -45
- package/apps/lib/components/InputOTP.tsx +68 -69
- package/apps/lib/components/Label.tsx +31 -35
- package/apps/lib/components/LabelField.tsx +4 -5
- package/apps/lib/components/LabeledCheckBox.tsx +8 -12
- package/apps/lib/components/LabeledRadio.tsx +7 -5
- package/apps/lib/components/LinkButton.tsx +2 -9
- package/apps/lib/components/LoginButton.tsx +4 -9
- package/apps/lib/components/PasswordLevel.tsx +5 -5
- package/apps/lib/components/Popover.tsx +15 -33
- package/apps/lib/components/ProfileMenu.tsx +67 -72
- package/apps/lib/components/Radio.tsx +1 -5
- package/apps/lib/components/RadioCard.tsx +9 -28
- package/apps/lib/components/ScrollArea.tsx +45 -43
- package/apps/lib/components/SearchField.tsx +49 -39
- package/apps/lib/components/SearchableSelect.tsx +46 -52
- package/apps/lib/components/SearchableTable.tsx +199 -219
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +4 -16
- package/apps/lib/components/Select.tsx +53 -80
- package/apps/lib/components/SimpleSelect.tsx +196 -187
- package/apps/lib/components/Skeleton.tsx +9 -12
- package/apps/lib/components/SlideDatePicker.tsx +215 -166
- package/apps/lib/components/SpinLoading.tsx +33 -49
- package/apps/lib/components/Stepper.tsx +13 -56
- package/apps/lib/components/Switch.tsx +8 -10
- package/apps/lib/components/TabFormItem.tsx +3 -12
- package/apps/lib/components/TabSwitch.tsx +7 -34
- package/apps/lib/components/Table.tsx +60 -75
- package/apps/lib/components/TableDnDWrapper.ts +15 -48
- package/apps/lib/components/TextEditor.tsx +93 -104
- package/apps/lib/components/Textarea.tsx +8 -12
- package/apps/lib/components/Timeline.tsx +21 -41
- package/apps/lib/components/Toast.tsx +83 -83
- package/apps/lib/components/Toggle.tsx +112 -114
- package/apps/lib/components/ToggleButton.tsx +1 -1
- package/apps/lib/components/Tooltip.tsx +24 -19
- package/apps/lib/components/TransparentLabel.tsx +61 -62
- package/apps/lib/components/TreeDropDown.tsx +86 -52
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
- package/apps/lib/components/TreeFolder/icons.tsx +14 -17
- package/apps/lib/components/TreeFolder/index.ts +15 -8
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
- package/apps/lib/components/TreeFolder/types.ts +32 -32
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
- package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
- package/apps/lib/hooks/useClickOutside.ts +21 -20
- package/apps/lib/hooks/useDataViewsState.ts +86 -80
- package/apps/lib/hooks/useIsMobile.ts +12 -12
- package/apps/lib/hooks/useResize.ts +54 -65
- package/apps/lib/hooks/useTagSelection.ts +201 -201
- package/apps/lib/layouts/CNLayout.tsx +181 -140
- package/apps/lib/layouts/DataViewCard.tsx +4 -18
- package/apps/lib/layouts/FieldSection.tsx +2 -6
- package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
- package/apps/lib/providers/ThemeProvider.tsx +8 -23
- package/apps/lib/registry.json +1004 -0
- package/apps/lib/tsconfig.json +9 -0
- package/apps/lib/utils/cn.ts +1 -1
- package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
- package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
- package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
- package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
- package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
- package/apps/lib/utils/dateFormat.ts +64 -54
- package/apps/lib/utils/markdownParser.ts +2 -7
- package/apps/lib/utils/resize.ts +21 -25
- package/apps/lib/utils/types.ts +13 -13
- package/dist/bin/index.js +8 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
- package/dist/src/shared/getAvailableFiles.js +6 -1
- package/dist/src/shared/getAvailableFiles.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +7 -0
- package/dist/src/shared/loadRegistry.d.ts.map +1 -0
- package/dist/src/shared/loadRegistry.js +31 -0
- package/dist/src/shared/loadRegistry.js.map +1 -0
- package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
- package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
- package/dist/src/shared/resolveInstallPlan.js +39 -0
- package/dist/src/shared/resolveInstallPlan.js.map +1 -0
- package/dist/src/types/main.d.ts +24 -0
- package/dist/src/types/main.d.ts.map +1 -1
- package/docs/README.md +10 -2
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +19 -16
- package/docs/components/chart-block-tool.md +128 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/context-menu.md +47 -24
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +18 -14
- package/docs/components/data-views-layout.md +20 -17
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +8 -33
- package/docs/components/dropdown-menu.md +51 -32
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +187 -0
- package/docs/components/image-attachment.md +33 -41
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +60 -41
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +130 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +105 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +19 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +7 -4
- package/docs/how-to/guides.md +24 -18
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +20 -13
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +31 -3
- package/dist/src/commands/block.d.ts +0 -5
- package/dist/src/commands/block.d.ts.map +0 -1
- package/dist/src/commands/block.js +0 -255
- package/dist/src/commands/block.js.map +0 -1
- package/dist/src/shared/configureFonts.d.ts +0 -6
- package/dist/src/shared/configureFonts.d.ts.map +0 -1
- package/dist/src/shared/configureFonts.js +0 -106
- package/dist/src/shared/configureFonts.js.map +0 -1
- package/dist/src/shared/configureGlobalCss.d.ts +0 -6
- package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
- package/dist/src/shared/configureGlobalCss.js +0 -154
- package/dist/src/shared/configureGlobalCss.js.map +0 -1
- package/dist/src/shared/configureTailwind.d.ts +0 -7
- package/dist/src/shared/configureTailwind.d.ts.map +0 -1
- package/dist/src/shared/configureTailwind.js +0 -163
- package/dist/src/shared/configureTailwind.js.map +0 -1
- package/dist/src/shared/detectFramework.d.ts +0 -23
- package/dist/src/shared/detectFramework.d.ts.map +0 -1
- package/dist/src/shared/detectFramework.js +0 -119
- package/dist/src/shared/detectFramework.js.map +0 -1
- package/dist/src/shared/installBaseUtils.d.ts +0 -5
- package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
- package/dist/src/shared/installBaseUtils.js +0 -79
- package/dist/src/shared/installBaseUtils.js.map +0 -1
- package/dist/src/shared/resolveAliases.d.ts +0 -24
- package/dist/src/shared/resolveAliases.d.ts.map +0 -1
- package/dist/src/shared/resolveAliases.js +0 -98
- package/dist/src/shared/resolveAliases.js.map +0 -1
|
@@ -11,28 +11,22 @@ keywords: [data-views, layout, table, kanban, inbox, tree, multi-view, filter, s
|
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
+
|
|
14
17
|
```bash
|
|
15
|
-
npx torch-glare@latest
|
|
18
|
+
npx torch-glare@latest init
|
|
19
|
+
npx torch-glare@latest add DataViewsLayout
|
|
16
20
|
```
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
the `DataViewCard` layout, the `useDataViewsState` hook, the `dataViews` utils,
|
|
20
|
-
and the `TreeFolder` component — plus the 3rd-party deps it uses
|
|
21
|
-
(`@radix-ui/react-slider`, `react-day-picker`, `lucide-react`, `vaul`).
|
|
22
|
-
|
|
23
|
-
> **Badge version:** DataViews uses the current Badge API
|
|
24
|
-
> (`color` / `badgeStyle` / `showIcon`). If your project vendored an older
|
|
25
|
-
> `Badge.tsx` (with `variant` / `isSelected`), refresh it with
|
|
26
|
-
> `npx torch-glare@latest add Badge --force` and migrate call sites
|
|
27
|
-
> (`variant=` → `color=`, `isSelected`+`onUnselect` → `isClosable`+`onClose`).
|
|
28
|
-
> The Badge also needs `mapping-color-system-v4` tokens
|
|
29
|
-
> (`--background-presentation-badge-{color}-{subtle|solid}`) in your CSS.
|
|
22
|
+
`add` also copies any components, hooks, and utilities that `DataViewsLayout` depends on.
|
|
30
23
|
|
|
31
24
|
## Import
|
|
32
25
|
|
|
26
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
+
|
|
33
28
|
```tsx
|
|
34
|
-
import { DataViewsLayout } from "
|
|
35
|
-
import type { FieldConfig, ViewVisibility } from "torch-glare"
|
|
29
|
+
import { DataViewsLayout } from "@/components/DataViewsLayout";
|
|
36
30
|
```
|
|
37
31
|
|
|
38
32
|
## Quick Examples
|
|
@@ -176,7 +170,11 @@ Inbox auto-detects `isRead`, `isStarred`, `hasAttachment`, `priority`. Override
|
|
|
176
170
|
| `type` | `FieldType` | Renderer key (see below). Auto-inferred if omitted. |
|
|
177
171
|
| `visible` | `boolean` | Show in cells. Default `true`. |
|
|
178
172
|
| `order` | `number` | Display order. |
|
|
179
|
-
| `filterable` | `boolean` | Surface this field in the filter panel. |
|
|
173
|
+
| `filterable` | `boolean` | Surface this field in the filter panel. The control adapts to the field `type`: categorical fields render checkboxes/radios (or a searchable dropdown via `filterVariant`), numeric fields a range slider, and **date / date-format fields a From + To pair of Glare `DatePicker`s** (two single-date pickers bounding the range). Set `false` to explicitly exclude a field the panel would otherwise auto-detect (e.g. an `id` or `name` with few unique values). |
|
|
174
|
+
| `filterLabel` | `string` | Override the label shown above this field's filter (defaults to `label`). |
|
|
175
|
+
| `filterMode` | `"single" \| "multi"` | Categorical selection mode. `"multi"` (default) renders checkboxes; `"single"` renders radios. |
|
|
176
|
+
| `filterVariant` | `"checkbox" \| "searchable-select"` | Categorical control style. `"checkbox"` (default) is the inline checkbox/radio list; `"searchable-select"` renders a single-select `SearchableSelect` dropdown — useful when a field has many options. Implies single-select. |
|
|
177
|
+
| `filterOptions` | `string[] \| { label: string; value: string }[]` | Explicit option list for the categorical filter (otherwise options are collected from the data). |
|
|
180
178
|
| `variants` | `Record<string, BadgeVariant>` | For `enum-badge`: per-value color map. |
|
|
181
179
|
| `currency` | `string \| CurrencyOptions` | For `currency`: ISO code or `{ symbol, locale, decimals, code }`. |
|
|
182
180
|
| `thresholds` | `[number, number]` | For `progress-bar`: warning/ok thresholds. |
|
|
@@ -188,6 +186,8 @@ Inbox auto-detects `isRead`, `isStarred`, `hasAttachment`, `priority`. Override
|
|
|
188
186
|
|
|
189
187
|
`text` · `number` · `date` · `date-format` · `boolean` · `currency` · `number-format` · `enum-badge` · `badge-array` · `progress-bar` · `star-rating` · `icon-text` · `two-line` · `avatar` · `link` · `image` · `hidden`
|
|
190
188
|
|
|
189
|
+
> **`hidden` vs `filterable: false`** — use `type: "hidden"` to drop a field from the UI **entirely** (no column, no column-toggle in the config panel, no filter) while it stays in the data for row identity — e.g. an `id` you key rows by but never want shown. Use `filterable: false` to keep a field as a **column** but remove only its **filter**.
|
|
190
|
+
|
|
191
191
|
### `BadgeVariant`
|
|
192
192
|
|
|
193
193
|
`green` · `greenLight` · `cocktailGreen` · `yellow` · `redOrange` · `redLight` · `rose` · `purple` · `bluePurple` · `blue` · `navy` · `gray` · `highlight`
|
|
@@ -241,7 +241,10 @@ passes `savedViews` to `DataViewsLayout` expecting it to work.
|
|
|
241
241
|
When you want a custom layout (e.g. Table on the left, Kanban on the right), bypass `DataViewsLayout` and compose the views directly.
|
|
242
242
|
|
|
243
243
|
```tsx
|
|
244
|
-
import {
|
|
244
|
+
import { FilterPanel } from "@/components/FilterPanel";
|
|
245
|
+
import { KanbanView } from "@/components/KanbanView";
|
|
246
|
+
import { TableView } from "@/components/TableView";
|
|
247
|
+
import { useDataViewsState } from "@/hooks/useDataViewsState";
|
|
245
248
|
|
|
246
249
|
function CustomScreen({ data, fields }: Props) {
|
|
247
250
|
const state = useDataViewsState({ data, fields })
|
|
@@ -11,15 +11,22 @@ keywords: [date-picker, calendar, time, datetime, input, popover]
|
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
+
|
|
14
17
|
```bash
|
|
15
|
-
|
|
18
|
+
npx torch-glare@latest init
|
|
19
|
+
npx torch-glare@latest add DatePicker
|
|
16
20
|
```
|
|
17
21
|
|
|
22
|
+
`add` also copies any components, hooks, and utilities that `DatePicker` depends on.
|
|
23
|
+
|
|
18
24
|
## Import
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
23
30
|
```
|
|
24
31
|
|
|
25
32
|
## Quick Examples
|
|
@@ -27,7 +34,7 @@ import type { DatePickerProps } from '@torch-ui/components'
|
|
|
27
34
|
### Basic Usage
|
|
28
35
|
|
|
29
36
|
```typescript
|
|
30
|
-
import { DatePicker } from
|
|
37
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
31
38
|
import { useState } from 'react'
|
|
32
39
|
|
|
33
40
|
function Example() {
|
|
@@ -46,7 +53,7 @@ function Example() {
|
|
|
46
53
|
### With Time Picker
|
|
47
54
|
|
|
48
55
|
```typescript
|
|
49
|
-
import { DatePicker } from
|
|
56
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
50
57
|
import { useState } from 'react'
|
|
51
58
|
|
|
52
59
|
function DateTimePicker() {
|
|
@@ -66,7 +73,7 @@ function DateTimePicker() {
|
|
|
66
73
|
### Range Selection
|
|
67
74
|
|
|
68
75
|
```typescript
|
|
69
|
-
import { DatePicker } from
|
|
76
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
70
77
|
import { useState } from 'react'
|
|
71
78
|
import { DateRange } from 'react-day-picker'
|
|
72
79
|
|
|
@@ -91,7 +98,7 @@ function RangePicker() {
|
|
|
91
98
|
### Multiple Date Selection
|
|
92
99
|
|
|
93
100
|
```typescript
|
|
94
|
-
import { DatePicker } from
|
|
101
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
95
102
|
import { useState } from 'react'
|
|
96
103
|
|
|
97
104
|
function MultipleDates() {
|
|
@@ -111,7 +118,7 @@ function MultipleDates() {
|
|
|
111
118
|
### Custom Date Format
|
|
112
119
|
|
|
113
120
|
```typescript
|
|
114
|
-
import { DatePicker } from
|
|
121
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
115
122
|
|
|
116
123
|
function CustomFormat() {
|
|
117
124
|
const [date, setDate] = useState<Date>(new Date())
|
|
@@ -129,8 +136,8 @@ function CustomFormat() {
|
|
|
129
136
|
### Custom Trigger Element
|
|
130
137
|
|
|
131
138
|
```typescript
|
|
132
|
-
import { DatePicker } from
|
|
133
|
-
import { Button } from
|
|
139
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
140
|
+
import { Button } from "@/components/Button";
|
|
134
141
|
|
|
135
142
|
function CustomTrigger() {
|
|
136
143
|
const [date, setDate] = useState<Date>(new Date())
|
|
@@ -140,7 +147,7 @@ function CustomTrigger() {
|
|
|
140
147
|
value={date}
|
|
141
148
|
onChange={(e) => setDate(e.target.value)}
|
|
142
149
|
>
|
|
143
|
-
<Button variant="
|
|
150
|
+
<Button variant="BluSecStyle">
|
|
144
151
|
<i className="ri-calendar-line" />
|
|
145
152
|
Select Date
|
|
146
153
|
</Button>
|
|
@@ -152,8 +159,8 @@ function CustomTrigger() {
|
|
|
152
159
|
### With Controlled Input
|
|
153
160
|
|
|
154
161
|
```typescript
|
|
155
|
-
import { DatePicker } from
|
|
156
|
-
import { InputField } from
|
|
162
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
163
|
+
import { InputField } from "@/components/InputField";
|
|
157
164
|
import { useState } from 'react'
|
|
158
165
|
|
|
159
166
|
function ControlledInput() {
|
|
@@ -176,7 +183,7 @@ function ControlledInput() {
|
|
|
176
183
|
### Date Restrictions
|
|
177
184
|
|
|
178
185
|
```typescript
|
|
179
|
-
import { DatePicker } from
|
|
186
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
180
187
|
|
|
181
188
|
function RestrictedDates() {
|
|
182
189
|
const [date, setDate] = useState<Date>()
|
|
@@ -201,7 +208,7 @@ function RestrictedDates() {
|
|
|
201
208
|
### Booking System
|
|
202
209
|
|
|
203
210
|
```typescript
|
|
204
|
-
import { DatePicker } from
|
|
211
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
205
212
|
import { useState } from 'react'
|
|
206
213
|
import { DateRange } from 'react-day-picker'
|
|
207
214
|
|
|
@@ -243,7 +250,7 @@ function BookingPicker() {
|
|
|
243
250
|
### Deadline Picker with Time
|
|
244
251
|
|
|
245
252
|
```typescript
|
|
246
|
-
import { DatePicker } from
|
|
253
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
247
254
|
import { useState } from 'react'
|
|
248
255
|
|
|
249
256
|
function DeadlinePicker() {
|
|
@@ -356,7 +363,7 @@ type RangeDatePicker = DatePickerProps & {
|
|
|
356
363
|
### Event Scheduler
|
|
357
364
|
|
|
358
365
|
```typescript
|
|
359
|
-
import { DatePicker } from
|
|
366
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
360
367
|
import { useState } from 'react'
|
|
361
368
|
|
|
362
369
|
function EventScheduler() {
|
|
@@ -399,7 +406,7 @@ function EventScheduler() {
|
|
|
399
406
|
### Birthday Picker
|
|
400
407
|
|
|
401
408
|
```typescript
|
|
402
|
-
import { DatePicker } from
|
|
409
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
403
410
|
import { useState } from 'react'
|
|
404
411
|
|
|
405
412
|
function BirthdayPicker() {
|
|
@@ -431,7 +438,7 @@ function BirthdayPicker() {
|
|
|
431
438
|
### Work Schedule Picker
|
|
432
439
|
|
|
433
440
|
```typescript
|
|
434
|
-
import { DatePicker } from
|
|
441
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
435
442
|
import { useState } from 'react'
|
|
436
443
|
|
|
437
444
|
function WorkSchedule() {
|
|
@@ -462,7 +469,7 @@ function WorkSchedule() {
|
|
|
462
469
|
|
|
463
470
|
```typescript
|
|
464
471
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
|
465
|
-
import { DatePicker } from
|
|
472
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
466
473
|
import userEvent from '@testing-library/user-event'
|
|
467
474
|
|
|
468
475
|
describe('DatePicker', () => {
|
|
@@ -753,7 +760,7 @@ Reverse-engineer the implementation from the call sites in `DatePicker.tsx` unti
|
|
|
753
760
|
### With Form Libraries
|
|
754
761
|
|
|
755
762
|
```typescript
|
|
756
|
-
import { DatePicker } from
|
|
763
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
757
764
|
import { useForm, Controller } from 'react-hook-form'
|
|
758
765
|
|
|
759
766
|
function FormExample() {
|
|
@@ -788,7 +795,7 @@ function FormExample() {
|
|
|
788
795
|
### With State Management
|
|
789
796
|
|
|
790
797
|
```typescript
|
|
791
|
-
import { DatePicker } from
|
|
798
|
+
import { DatePicker } from "@/components/DatePicker";
|
|
792
799
|
import { useStore } from './store'
|
|
793
800
|
|
|
794
801
|
function DatePickerWithStore() {
|
|
@@ -11,24 +11,22 @@ keywords: [dialog, modal, overlay, popup, radix-ui, compound-component]
|
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
+
|
|
14
17
|
```bash
|
|
15
|
-
|
|
18
|
+
npx torch-glare@latest init
|
|
19
|
+
npx torch-glare@latest add Dialog
|
|
16
20
|
```
|
|
17
21
|
|
|
22
|
+
`add` also copies any components, hooks, and utilities that `Dialog` depends on.
|
|
23
|
+
|
|
18
24
|
## Import
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
DialogContent,
|
|
25
|
-
DialogHeader,
|
|
26
|
-
DialogFooter,
|
|
27
|
-
DialogTitle,
|
|
28
|
-
DialogDescription,
|
|
29
|
-
DialogClose,
|
|
30
|
-
DialogCloseButton,
|
|
31
|
-
} from '@torch-ui/components'
|
|
26
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { Dialog } from "@/components/Dialog";
|
|
32
30
|
```
|
|
33
31
|
|
|
34
32
|
## Quick Examples
|
|
@@ -36,8 +34,8 @@ import {
|
|
|
36
34
|
### Basic Usage
|
|
37
35
|
|
|
38
36
|
```typescript
|
|
39
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from
|
|
40
|
-
import { Button } from
|
|
37
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/Dialog";
|
|
38
|
+
import { Button } from "@/components/Button";
|
|
41
39
|
|
|
42
40
|
function Example() {
|
|
43
41
|
return (
|
|
@@ -61,8 +59,8 @@ function Example() {
|
|
|
61
59
|
### With Header and Footer
|
|
62
60
|
|
|
63
61
|
```typescript
|
|
64
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose } from
|
|
65
|
-
import { Button } from
|
|
62
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose } from "@/components/Dialog";
|
|
63
|
+
import { Button } from "@/components/Button";
|
|
66
64
|
|
|
67
65
|
function FormDialog() {
|
|
68
66
|
return (
|
|
@@ -86,9 +84,9 @@ function FormDialog() {
|
|
|
86
84
|
|
|
87
85
|
<DialogFooter>
|
|
88
86
|
<DialogClose asChild>
|
|
89
|
-
<Button variant="
|
|
87
|
+
<Button variant="BluSecStyle">Cancel</Button>
|
|
90
88
|
</DialogClose>
|
|
91
|
-
<Button variant="
|
|
89
|
+
<Button variant="PrimeStyle">Save Changes</Button>
|
|
92
90
|
</DialogFooter>
|
|
93
91
|
</DialogContent>
|
|
94
92
|
</Dialog>
|
|
@@ -99,7 +97,7 @@ function FormDialog() {
|
|
|
99
97
|
### Controlled State
|
|
100
98
|
|
|
101
99
|
```typescript
|
|
102
|
-
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from
|
|
100
|
+
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from "@/components/Dialog";
|
|
103
101
|
import { useState } from 'react'
|
|
104
102
|
|
|
105
103
|
function ControlledDialog() {
|
|
@@ -123,8 +121,8 @@ function ControlledDialog() {
|
|
|
123
121
|
### With Custom Close Button
|
|
124
122
|
|
|
125
123
|
```typescript
|
|
126
|
-
import { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogCloseButton } from
|
|
127
|
-
import { ActionButton } from
|
|
124
|
+
import { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogCloseButton } from "@/components/Dialog";
|
|
125
|
+
import { ActionButton } from "@/components/ActionButton";
|
|
128
126
|
|
|
129
127
|
function CustomCloseDialog() {
|
|
130
128
|
return (
|
|
@@ -150,14 +148,14 @@ function CustomCloseDialog() {
|
|
|
150
148
|
### Confirmation Dialog
|
|
151
149
|
|
|
152
150
|
```typescript
|
|
153
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose } from
|
|
154
|
-
import { Button } from
|
|
151
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose } from "@/components/Dialog";
|
|
152
|
+
import { Button } from "@/components/Button";
|
|
155
153
|
|
|
156
154
|
function ConfirmationDialog({ onConfirm }: { onConfirm: () => void }) {
|
|
157
155
|
return (
|
|
158
156
|
<Dialog>
|
|
159
157
|
<DialogTrigger asChild>
|
|
160
|
-
<Button variant="
|
|
158
|
+
<Button variant="RedSecStyle">Delete Account</Button>
|
|
161
159
|
</DialogTrigger>
|
|
162
160
|
<DialogContent>
|
|
163
161
|
<DialogHeader>
|
|
@@ -170,10 +168,10 @@ function ConfirmationDialog({ onConfirm }: { onConfirm: () => void }) {
|
|
|
170
168
|
|
|
171
169
|
<DialogFooter>
|
|
172
170
|
<DialogClose asChild>
|
|
173
|
-
<Button variant="
|
|
171
|
+
<Button variant="BluSecStyle">Cancel</Button>
|
|
174
172
|
</DialogClose>
|
|
175
173
|
<DialogClose asChild>
|
|
176
|
-
<Button variant="
|
|
174
|
+
<Button variant="RedSecStyle" onClick={onConfirm}>
|
|
177
175
|
Delete Account
|
|
178
176
|
</Button>
|
|
179
177
|
</DialogClose>
|
|
@@ -187,8 +185,9 @@ function ConfirmationDialog({ onConfirm }: { onConfirm: () => void }) {
|
|
|
187
185
|
### Nested Form Dialog
|
|
188
186
|
|
|
189
187
|
```typescript
|
|
190
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from
|
|
191
|
-
import { Button
|
|
188
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from "@/components/Dialog";
|
|
189
|
+
import { Button } from "@/components/Button";
|
|
190
|
+
import { Input } from "@/components/Input";
|
|
192
191
|
import { useForm } from 'react-hook-form'
|
|
193
192
|
|
|
194
193
|
interface FormData {
|
|
@@ -236,8 +235,9 @@ function FormDialog() {
|
|
|
236
235
|
### Content-Heavy Dialog
|
|
237
236
|
|
|
238
237
|
```typescript
|
|
239
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from
|
|
240
|
-
import { Button
|
|
238
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/Dialog";
|
|
239
|
+
import { Button } from "@/components/Button";
|
|
240
|
+
import { ScrollArea } from "@/components/ScrollArea";
|
|
241
241
|
|
|
242
242
|
function ContentDialog() {
|
|
243
243
|
return (
|
|
@@ -273,8 +273,8 @@ function ContentDialog() {
|
|
|
273
273
|
### Multi-Step Dialog
|
|
274
274
|
|
|
275
275
|
```typescript
|
|
276
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle } from
|
|
277
|
-
import { Button } from
|
|
276
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle } from "@/components/Dialog";
|
|
277
|
+
import { Button } from "@/components/Button";
|
|
278
278
|
import { useState } from 'react'
|
|
279
279
|
|
|
280
280
|
function MultiStepDialog() {
|
|
@@ -298,7 +298,7 @@ function MultiStepDialog() {
|
|
|
298
298
|
|
|
299
299
|
<DialogFooter>
|
|
300
300
|
{step > 1 && (
|
|
301
|
-
<Button variant="
|
|
301
|
+
<Button variant="BluSecStyle" onClick={() => setStep(step - 1)}>
|
|
302
302
|
Back
|
|
303
303
|
</Button>
|
|
304
304
|
)}
|
|
@@ -317,7 +317,7 @@ function MultiStepDialog() {
|
|
|
317
317
|
### Image Preview Dialog
|
|
318
318
|
|
|
319
319
|
```typescript
|
|
320
|
-
import { Dialog, DialogTrigger, DialogContent } from
|
|
320
|
+
import { Dialog, DialogTrigger, DialogContent } from "@/components/Dialog";
|
|
321
321
|
|
|
322
322
|
function ImageDialog({ src, alt }: { src: string; alt: string }) {
|
|
323
323
|
return (
|
|
@@ -340,8 +340,9 @@ function ImageDialog({ src, alt }: { src: string; alt: string }) {
|
|
|
340
340
|
### Loading State Dialog
|
|
341
341
|
|
|
342
342
|
```typescript
|
|
343
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle } from
|
|
344
|
-
import { Button
|
|
343
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle } from "@/components/Dialog";
|
|
344
|
+
import { Button } from "@/components/Button";
|
|
345
|
+
import { SpinLoading } from "@/components/SpinLoading";
|
|
345
346
|
import { useState } from 'react'
|
|
346
347
|
|
|
347
348
|
function LoadingDialog() {
|
|
@@ -676,8 +677,8 @@ Pick an icon that matches the entity (`ri-bank-line` for accounts, `ri-calendar-
|
|
|
676
677
|
### Alert/Confirmation Pattern
|
|
677
678
|
|
|
678
679
|
```typescript
|
|
679
|
-
import { Dialog, DialogContent, DialogTitle, DialogDescription } from
|
|
680
|
-
import { Button } from
|
|
680
|
+
import { Dialog, DialogContent, DialogTitle, DialogDescription } from "@/components/Dialog";
|
|
681
|
+
import { Button } from "@/components/Button";
|
|
681
682
|
|
|
682
683
|
function useConfirmDialog() {
|
|
683
684
|
const [open, setOpen] = useState(false)
|
|
@@ -730,7 +731,7 @@ function useConfirmDialog() {
|
|
|
730
731
|
|
|
731
732
|
```typescript
|
|
732
733
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
733
|
-
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from
|
|
734
|
+
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from "@/components/Dialog";
|
|
734
735
|
|
|
735
736
|
describe('Dialog', () => {
|
|
736
737
|
it('opens when trigger is clicked', () => {
|
|
@@ -839,7 +840,7 @@ describe('Dialog', () => {
|
|
|
839
840
|
|
|
840
841
|
```diff
|
|
841
842
|
- import { Dialog, DialogTitle, DialogContent } from '@mui/material'
|
|
842
|
-
+ import { Dialog, DialogTrigger, DialogContent, DialogTitle } from
|
|
843
|
+
+ import { Dialog, DialogTrigger, DialogContent, DialogTitle } from "@/components/Dialog";
|
|
843
844
|
|
|
844
845
|
- <Dialog open={open} onClose={() => setOpen(false)}>
|
|
845
846
|
- <DialogTitle>Title</DialogTitle>
|
|
@@ -858,7 +859,7 @@ describe('Dialog', () => {
|
|
|
858
859
|
|
|
859
860
|
```diff
|
|
860
861
|
- import { Dialog } from '@headlessui/react'
|
|
861
|
-
+ import { Dialog, DialogContent, DialogTitle } from
|
|
862
|
+
+ import { Dialog, DialogContent, DialogTitle } from "@/components/Dialog";
|
|
862
863
|
|
|
863
864
|
- <Dialog open={open} onClose={setOpen}>
|
|
864
865
|
- <Dialog.Panel>
|
|
@@ -12,10 +12,16 @@ A flexible separator component for creating visual divisions between content sec
|
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
16
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
17
|
+
|
|
15
18
|
```bash
|
|
16
|
-
npx torch-
|
|
19
|
+
npx torch-glare@latest init
|
|
20
|
+
npx torch-glare@latest add Divider
|
|
17
21
|
```
|
|
18
22
|
|
|
23
|
+
`add` also copies any components, hooks, and utilities that `Divider` depends on.
|
|
24
|
+
|
|
19
25
|
## Imports
|
|
20
26
|
|
|
21
27
|
```typescript
|
|
@@ -282,7 +288,7 @@ export function FormWithDividers() {
|
|
|
282
288
|
<Divider />
|
|
283
289
|
|
|
284
290
|
<div className="flex justify-end gap-3">
|
|
285
|
-
<Button variant="
|
|
291
|
+
<Button variant="BluSecStyle">Cancel</Button>
|
|
286
292
|
<Button variant="PrimeStyle">Save Changes</Button>
|
|
287
293
|
</div>
|
|
288
294
|
</form>
|
|
@@ -317,11 +323,11 @@ export function DividerWithText() {
|
|
|
317
323
|
|
|
318
324
|
{/* Social login */}
|
|
319
325
|
<div className="space-y-2">
|
|
320
|
-
<Button className="w-full" variant="
|
|
326
|
+
<Button className="w-full" variant="BluSecStyle">
|
|
321
327
|
<i className="ri-google-fill mr-2"></i>
|
|
322
328
|
Continue with Google
|
|
323
329
|
</Button>
|
|
324
|
-
<Button className="w-full" variant="
|
|
330
|
+
<Button className="w-full" variant="BluSecStyle">
|
|
325
331
|
<i className="ri-github-fill mr-2"></i>
|
|
326
332
|
Continue with GitHub
|
|
327
333
|
</Button>
|
|
@@ -14,47 +14,22 @@ keywords: [drawer, sheet, side-panel, bottom-sheet, slide, vaul, form, create, e
|
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
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
|
+
|
|
17
20
|
```bash
|
|
21
|
+
npx torch-glare@latest init
|
|
18
22
|
npx torch-glare@latest add Drawer
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
> [!NOTE]
|
|
24
|
-
> **Building create / edit forms?** The Drawer ships on its own. The form examples on this page also use `SectionBlock`, `InputField`, and `Button`. Install them alongside it:
|
|
25
|
-
>
|
|
26
|
-
> ```bash
|
|
27
|
-
> npx torch-glare@latest add Drawer SectionBlock InputField Button
|
|
28
|
-
> ```
|
|
29
|
-
>
|
|
30
|
-
> These are *not* auto-installed by `add Drawer`, because `Drawer.tsx` does not import them — they are only needed for the form composition pattern, not for the Drawer itself.
|
|
25
|
+
`add` also copies any components, hooks, and utilities that `Drawer` depends on.
|
|
31
26
|
|
|
32
27
|
## Import
|
|
33
28
|
|
|
29
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
30
|
+
|
|
34
31
|
```tsx
|
|
35
|
-
import {
|
|
36
|
-
Drawer,
|
|
37
|
-
DrawerNested,
|
|
38
|
-
DrawerTrigger,
|
|
39
|
-
DrawerClose,
|
|
40
|
-
DrawerContent,
|
|
41
|
-
DrawerHeader,
|
|
42
|
-
DrawerHeaderTitle,
|
|
43
|
-
DrawerHeaderActions,
|
|
44
|
-
DrawerBadge,
|
|
45
|
-
DrawerFooter,
|
|
46
|
-
DrawerTitle,
|
|
47
|
-
DrawerDescription,
|
|
48
|
-
// Notch (the tab that sticks out of the top edge)
|
|
49
|
-
DrawerNotch,
|
|
50
|
-
DrawerNotchClose,
|
|
51
|
-
DrawerNotchPill,
|
|
52
|
-
DrawerNotchDivider,
|
|
53
|
-
DrawerNotchApp,
|
|
54
|
-
// Lower-level primitives (rarely needed directly)
|
|
55
|
-
DrawerPortal,
|
|
56
|
-
DrawerOverlay,
|
|
57
|
-
} from "@/components/Drawer";
|
|
32
|
+
import { Drawer } from "@/components/Drawer";
|
|
58
33
|
```
|
|
59
34
|
|
|
60
35
|
## Anatomy
|