@sixthshift/design-system 0.2.1 → 0.3.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 +135 -28
- package/dist/components/Badge/Badge.d.ts +5 -2
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +5 -3
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/BarChart/BarChart.d.ts +8 -2
- package/dist/components/BarChart/BarChart.d.ts.map +1 -1
- package/dist/components/BarChart/BarChart.js +5 -3
- package/dist/components/BarChart/BarChart.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +17 -1
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +80 -225
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/CalendarView.d.ts +15 -0
- package/dist/components/Calendar/CalendarView.d.ts.map +1 -0
- package/dist/components/Calendar/CalendarView.js +255 -0
- package/dist/components/Calendar/CalendarView.js.map +1 -0
- package/dist/components/Calendar/calendar.types.d.ts +78 -27
- package/dist/components/Calendar/calendar.types.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.types.js +10 -3
- package/dist/components/Calendar/calendar.types.js.map +1 -1
- package/dist/components/Calendar/index.d.ts +16 -2
- package/dist/components/Calendar/index.d.ts.map +1 -1
- package/dist/components/Calendar/index.js +15 -1
- package/dist/components/Calendar/index.js.map +1 -1
- package/dist/components/ColorDot/ColorDot.d.ts +9 -3
- package/dist/components/ColorDot/ColorDot.d.ts.map +1 -1
- package/dist/components/ColorDot/ColorDot.js +5 -3
- package/dist/components/ColorDot/ColorDot.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2 -2
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +65 -10
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePicker/datepicker.types.d.ts +34 -36
- package/dist/components/DatePicker/datepicker.types.d.ts.map +1 -1
- package/dist/components/DatePicker/datepicker.types.js +5 -3
- package/dist/components/DatePicker/datepicker.types.js.map +1 -1
- package/dist/components/DatePicker/index.d.ts +10 -1
- package/dist/components/DatePicker/index.d.ts.map +1 -1
- package/dist/components/DatePicker/index.js +8 -0
- package/dist/components/DatePicker/index.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +3 -2
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +17 -21
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts +20 -20
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.js +6 -0
- package/dist/components/DateRangePicker/daterangepicker.types.js.map +1 -1
- package/dist/components/DateRangePicker/index.d.ts +8 -1
- package/dist/components/DateRangePicker/index.d.ts.map +1 -1
- package/dist/components/DateRangePicker/index.js +6 -0
- package/dist/components/DateRangePicker/index.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +3 -3
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +30 -12
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts +20 -17
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimePicker/datetimepicker.types.js +10 -0
- package/dist/components/DateTimePicker/datetimepicker.types.js.map +1 -1
- package/dist/components/DateTimePicker/index.d.ts +8 -1
- package/dist/components/DateTimePicker/index.d.ts.map +1 -1
- package/dist/components/DateTimePicker/index.js +6 -0
- package/dist/components/DateTimePicker/index.js.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts +3 -3
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +41 -20
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts +22 -18
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.js +8 -0
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.js.map +1 -1
- package/dist/components/DateTimeRangePicker/index.d.ts +8 -0
- package/dist/components/DateTimeRangePicker/index.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/index.js +7 -0
- package/dist/components/DateTimeRangePicker/index.js.map +1 -1
- package/dist/components/EmptyState/EmptyState.d.ts +16 -5
- package/dist/components/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/components/EmptyState/EmptyState.js +5 -3
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +3 -3
- package/dist/components/Field/Field.d.ts.map +1 -1
- package/dist/components/Field/Field.js +6 -4
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/LineChart/LineChart.d.ts +18 -2
- package/dist/components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/components/LineChart/LineChart.js +5 -3
- package/dist/components/LineChart/LineChart.js.map +1 -1
- package/dist/components/Markdown/Markdown.d.ts +2 -4
- package/dist/components/Markdown/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown/Markdown.js +3 -2
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Message/Message.d.ts.map +1 -1
- package/dist/components/Message/Message.js +16 -1
- package/dist/components/Message/Message.js.map +1 -1
- package/dist/components/MetricList/MetricList.d.ts +3 -3
- package/dist/components/MetricList/MetricList.d.ts.map +1 -1
- package/dist/components/MetricList/MetricList.js +5 -3
- package/dist/components/MetricList/MetricList.js.map +1 -1
- package/dist/components/Modal/Modal.d.ts +24 -5
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +16 -6
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/components/ModalContext.d.ts +14 -0
- package/dist/components/Modal/components/ModalContext.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalContext.js.map +1 -1
- package/dist/components/Modal/components/ModalHeader.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalHeader.js +13 -2
- package/dist/components/Modal/components/ModalHeader.js.map +1 -1
- package/dist/components/NavBottom/NavBottom.d.ts +2 -1
- package/dist/components/NavBottom/NavBottom.d.ts.map +1 -1
- package/dist/components/NavBottom/NavBottom.js +6 -4
- package/dist/components/NavBottom/NavBottom.js.map +1 -1
- package/dist/components/NavSide/NavItem.js +1 -1
- package/dist/components/NavSide/NavItem.js.map +1 -1
- package/dist/components/NavSide/NavSide.d.ts +2 -1
- package/dist/components/NavSide/NavSide.d.ts.map +1 -1
- package/dist/components/NavSide/NavSide.js +5 -3
- package/dist/components/NavSide/NavSide.js.map +1 -1
- package/dist/components/Popover/Popover.d.ts.map +1 -1
- package/dist/components/Popover/Popover.js +7 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverBody.js +5 -2
- package/dist/components/Popover/components/PopoverBody.js.map +1 -1
- package/dist/components/Popover/components/PopoverContext.d.ts +1 -0
- package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverContext.js.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.js +2 -2
- package/dist/components/Popover/components/PopoverTrigger.js.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts +2 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.js +5 -3
- package/dist/components/ProgressBar/ProgressBar.js.map +1 -1
- package/dist/components/Select/Select.d.ts +11 -2
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +64 -18
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectDropdown.d.ts +14 -2
- package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
- package/dist/components/Select/SelectDropdown.js +19 -4
- package/dist/components/Select/SelectDropdown.js.map +1 -1
- package/dist/components/Select/SelectTrigger.d.ts +10 -3
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
- package/dist/components/Select/SelectTrigger.js +12 -3
- package/dist/components/Select/SelectTrigger.js.map +1 -1
- package/dist/components/Select/useSelectKeyboard.d.ts +15 -1
- package/dist/components/Select/useSelectKeyboard.d.ts.map +1 -1
- package/dist/components/Select/useSelectKeyboard.js +73 -65
- package/dist/components/Select/useSelectKeyboard.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +19 -5
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +18 -6
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Sheet/components/SheetContext.d.ts +10 -0
- package/dist/components/Sheet/components/SheetContext.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetContext.js.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.js +11 -2
- package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +2 -1
- package/dist/components/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/components/Skeleton/Skeleton.js +5 -3
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.d.ts +10 -2
- package/dist/components/Sparkline/Sparkline.d.ts.map +1 -1
- package/dist/components/Sparkline/Sparkline.js +5 -3
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/StatsCard/StatsCard.d.ts +4 -4
- package/dist/components/StatsCard/StatsCard.d.ts.map +1 -1
- package/dist/components/StatsCard/StatsCard.js +5 -3
- package/dist/components/StatsCard/StatsCard.js.map +1 -1
- package/dist/components/Tabs/Tabs.d.ts +2 -2
- package/dist/components/Tabs/components/TabsList.d.ts +1 -1
- package/dist/components/Tabs/components/TabsList.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsList.js +5 -4
- package/dist/components/Tabs/components/TabsList.js.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.d.ts +1 -1
- package/dist/components/Tabs/components/TabsPanels.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.js +5 -3
- package/dist/components/Tabs/components/TabsPanels.js.map +1 -1
- package/dist/components/TagChip/TagChip.d.ts +2 -1
- package/dist/components/TagChip/TagChip.d.ts.map +1 -1
- package/dist/components/TagChip/TagChip.js +5 -3
- package/dist/components/TagChip/TagChip.js.map +1 -1
- package/dist/components/TagInput/TagInput.d.ts +1 -1
- package/dist/components/TagInput/TagInput.d.ts.map +1 -1
- package/dist/components/TagInput/TagInput.js +5 -4
- package/dist/components/TagInput/TagInput.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.d.ts +2 -2
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +27 -11
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/TimePicker/timepicker.types.d.ts +14 -13
- package/dist/components/TimePicker/timepicker.types.d.ts.map +1 -1
- package/dist/components/TimePicker/timepicker.types.js +4 -3
- package/dist/components/TimePicker/timepicker.types.js.map +1 -1
- package/dist/date-time/index.d.ts +2 -0
- package/dist/date-time/index.d.ts.map +1 -1
- package/dist/date-time/index.js +9 -0
- package/dist/date-time/index.js.map +1 -1
- package/dist/date-time/iso.d.ts +261 -0
- package/dist/date-time/iso.d.ts.map +1 -0
- package/dist/date-time/iso.js +358 -0
- package/dist/date-time/iso.js.map +1 -0
- package/dist/date-time/now.d.ts +7 -6
- package/dist/date-time/now.d.ts.map +1 -1
- package/dist/date-time/now.js +3 -3
- package/dist/date-time/now.js.map +1 -1
- package/dist/theme/index.d.ts +4 -3
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +3 -2
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/schema.d.ts +70 -32
- package/dist/theme/schema.d.ts.map +1 -1
- package/dist/theme/schema.js +36 -18
- package/dist/theme/schema.js.map +1 -1
- package/package.json +9 -15
- package/src/components/Badge/Badge.tsx +5 -4
- package/src/components/BarChart/BarChart.tsx +25 -30
- package/src/components/Calendar/Calendar.tsx +91 -401
- package/src/components/Calendar/CalendarView.tsx +445 -0
- package/src/components/Calendar/calendar.types.ts +94 -29
- package/src/components/Calendar/index.ts +16 -17
- package/src/components/ColorDot/ColorDot.tsx +6 -4
- package/src/components/DatePicker/DatePicker.tsx +92 -16
- package/src/components/DatePicker/datepicker.types.ts +38 -39
- package/src/components/DatePicker/index.ts +11 -10
- package/src/components/DateRangePicker/DateRangePicker.tsx +17 -21
- package/src/components/DateRangePicker/daterangepicker.types.ts +22 -22
- package/src/components/DateRangePicker/index.ts +9 -1
- package/src/components/DateTimePicker/DateTimePicker.tsx +46 -18
- package/src/components/DateTimePicker/datetimepicker.types.ts +22 -18
- package/src/components/DateTimePicker/index.ts +9 -1
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +62 -28
- package/src/components/DateTimeRangePicker/datetimerangepicker.types.ts +24 -19
- package/src/components/DateTimeRangePicker/index.ts +9 -0
- package/src/components/EmptyState/EmptyState.tsx +8 -7
- package/src/components/Field/Field.tsx +7 -6
- package/src/components/LineChart/LineChart.tsx +147 -141
- package/src/components/Markdown/Markdown.tsx +4 -3
- package/src/components/Message/Message.tsx +17 -1
- package/src/components/MetricList/MetricList.tsx +10 -5
- package/src/components/Modal/Modal.tsx +119 -87
- package/src/components/Modal/components/ModalContext.tsx +14 -0
- package/src/components/Modal/components/ModalHeader.tsx +14 -2
- package/src/components/NavBottom/NavBottom.tsx +6 -4
- package/src/components/NavSide/NavItem.tsx +1 -1
- package/src/components/NavSide/NavSide.tsx +5 -3
- package/src/components/Popover/Popover.tsx +7 -0
- package/src/components/Popover/components/PopoverBody.tsx +6 -1
- package/src/components/Popover/components/PopoverContext.tsx +1 -0
- package/src/components/Popover/components/PopoverTrigger.tsx +2 -1
- package/src/components/ProgressBar/ProgressBar.tsx +32 -28
- package/src/components/Select/Select.tsx +76 -19
- package/src/components/Select/SelectDropdown.tsx +32 -3
- package/src/components/Select/SelectTrigger.tsx +26 -3
- package/src/components/Select/useSelectKeyboard.ts +20 -10
- package/src/components/Sheet/Sheet.tsx +108 -83
- package/src/components/Sheet/components/SheetContext.tsx +10 -0
- package/src/components/Sheet/components/SheetHeader.tsx +17 -2
- package/src/components/Skeleton/Skeleton.tsx +5 -3
- package/src/components/Sparkline/Sparkline.tsx +29 -36
- package/src/components/StatsCard/StatsCard.tsx +7 -6
- package/src/components/Tabs/components/TabsList.tsx +5 -3
- package/src/components/Tabs/components/TabsPanels.tsx +5 -3
- package/src/components/TagChip/TagChip.tsx +10 -3
- package/src/components/TagInput/TagInput.tsx +5 -3
- package/src/components/TimePicker/TimePicker.tsx +31 -13
- package/src/components/TimePicker/timepicker.types.ts +14 -13
- package/src/date-time/index.ts +61 -0
- package/src/date-time/iso.ts +511 -0
- package/src/date-time/now.ts +10 -9
- package/src/theme/index.ts +11 -3
- package/src/theme/schema.ts +82 -54
- package/src/theme/tokens.css +807 -0
- package/dist/styles.css +0 -2
- package/dist/theme.generated.css +0 -438
- package/src/styles/base.css +0 -41
- package/src/theme/palette.json +0 -100
- package/src/theme/palette.schema.json +0 -40
- package/src/theme/theme.json +0 -349
- package/src/theme/theme.schema.json +0 -876
- package/src/theme/typography.json +0 -7
- package/src/theme/typography.schema.json +0 -36
- package/tailwind.config.ts +0 -261
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback } from "react";
|
|
2
2
|
import type { SelectOption } from "./Select";
|
|
3
3
|
|
|
4
4
|
interface UseSelectKeyboardOptions<T extends string> {
|
|
@@ -14,6 +14,20 @@ interface UseSelectKeyboardOptions<T extends string> {
|
|
|
14
14
|
focusTrigger: () => void;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Returns the keydown handler for an open Select. It is attached to the element
|
|
19
|
+
* that actually holds focus — the listbox, or the search input in searchable
|
|
20
|
+
* mode — rather than to `document`.
|
|
21
|
+
*
|
|
22
|
+
* A document-level listener fired for every keystroke on the page while any
|
|
23
|
+
* Select was open, which meant a Select could swallow Escape or an arrow key
|
|
24
|
+
* from an overlay stacked above it, and two open Selects raced each other. It
|
|
25
|
+
* also decoupled key handling from focus, so nothing guaranteed the element the
|
|
26
|
+
* user was typing into was the one being navigated. Scoping the handler to the
|
|
27
|
+
* focused element makes both problems structurally impossible and is what lets
|
|
28
|
+
* `aria-activedescendant` mean something: the focused element owns the active
|
|
29
|
+
* option.
|
|
30
|
+
*/
|
|
17
31
|
export function useSelectKeyboard<T extends string>({
|
|
18
32
|
open,
|
|
19
33
|
searchable,
|
|
@@ -26,8 +40,8 @@ export function useSelectKeyboard<T extends string>({
|
|
|
26
40
|
handleSelect,
|
|
27
41
|
focusTrigger,
|
|
28
42
|
}: UseSelectKeyboardOptions<T>) {
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
return useCallback(
|
|
44
|
+
(event: React.KeyboardEvent<HTMLElement>) => {
|
|
31
45
|
if (!open) return;
|
|
32
46
|
|
|
33
47
|
const isTyping = searchable && event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
@@ -101,11 +115,7 @@ export function useSelectKeyboard<T extends string>({
|
|
|
101
115
|
}
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
108
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
109
|
-
}
|
|
110
|
-
}, [open, searchable, searchValue, highlightedIndex, displayOptions, setOpen, setHighlightedIndex, setSearchValue, handleSelect, focusTrigger]);
|
|
118
|
+
},
|
|
119
|
+
[open, searchable, searchValue, highlightedIndex, displayOptions, setOpen, setHighlightedIndex, setSearchValue, handleSelect, focusTrigger]
|
|
120
|
+
);
|
|
111
121
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { FloatingFocusManager, useDismiss, useFloating, useInteractions, useRole } from "@floating-ui/react";
|
|
2
2
|
import { useMergedFloatingRef, usePresence } from "@sixthshift/design-system/hooks";
|
|
3
3
|
import { cn } from "@sixthshift/design-system/utils";
|
|
4
|
-
import { type HTMLAttributes, type ReactNode, useCallback, useEffect, useMemo } from "react";
|
|
4
|
+
import { forwardRef, type HTMLAttributes, type ReactNode, useCallback, useEffect, useId, useMemo, useState } from "react";
|
|
5
5
|
import { SheetBody, SheetContext, SheetFooter, SheetHeader } from "./components";
|
|
6
6
|
|
|
7
7
|
// =============================================================================
|
|
8
8
|
// Types
|
|
9
9
|
// =============================================================================
|
|
10
10
|
|
|
11
|
-
export type SheetProps = Pick<HTMLAttributes<HTMLDivElement>, "className" | "style"> & {
|
|
11
|
+
export type SheetProps = Pick<HTMLAttributes<HTMLDivElement>, "className" | "style" | "aria-label" | "aria-labelledby" | "aria-describedby"> & {
|
|
12
12
|
/** Whether the sheet is open. Sheet owns its own mount lifecycle so exit animations can play. */
|
|
13
13
|
open: boolean;
|
|
14
14
|
/** Called when the sheet requests a state change (Esc, outside press, X button). */
|
|
@@ -41,88 +41,113 @@ const sizeClasses = {
|
|
|
41
41
|
// Sheet
|
|
42
42
|
// =============================================================================
|
|
43
43
|
|
|
44
|
-
const SheetRoot = (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
if (open) {
|
|
62
|
-
show();
|
|
63
|
-
} else if (isMounted) {
|
|
64
|
-
hide();
|
|
65
|
-
}
|
|
66
|
-
}, [open, isMounted, show, hide]);
|
|
67
|
-
|
|
68
|
-
const requestClose = useCallback(() => {
|
|
69
|
-
onOpenChange(false);
|
|
70
|
-
}, [onOpenChange]);
|
|
71
|
-
|
|
72
|
-
const { refs, context } = useFloating({
|
|
73
|
-
open,
|
|
74
|
-
onOpenChange: (nextOpen) => {
|
|
75
|
-
if (!nextOpen) requestClose();
|
|
44
|
+
const SheetRoot = forwardRef<HTMLDivElement, SheetProps>(
|
|
45
|
+
(
|
|
46
|
+
{
|
|
47
|
+
open,
|
|
48
|
+
onOpenChange,
|
|
49
|
+
side = "right",
|
|
50
|
+
size = "md",
|
|
51
|
+
dismissable = true,
|
|
52
|
+
dismissOnOutsidePress = false,
|
|
53
|
+
closable,
|
|
54
|
+
className,
|
|
55
|
+
style,
|
|
56
|
+
children,
|
|
57
|
+
"aria-label": ariaLabel,
|
|
58
|
+
"aria-labelledby": ariaLabelledBy,
|
|
59
|
+
"aria-describedby": ariaDescribedBy,
|
|
76
60
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
};
|
|
61
|
+
ref
|
|
62
|
+
) => {
|
|
63
|
+
const { ref: presenceRef, state, isMounted, show, hide } = usePresence();
|
|
64
|
+
|
|
65
|
+
// Drive presence from the controlled `open` prop.
|
|
66
|
+
// When `open` flips to false, we play the exit animation, then unmount.
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (open) {
|
|
69
|
+
show();
|
|
70
|
+
} else if (isMounted) {
|
|
71
|
+
hide();
|
|
72
|
+
}
|
|
73
|
+
}, [open, isMounted, show, hide]);
|
|
74
|
+
|
|
75
|
+
const requestClose = useCallback(() => {
|
|
76
|
+
onOpenChange(false);
|
|
77
|
+
}, [onOpenChange]);
|
|
78
|
+
|
|
79
|
+
const { refs, context } = useFloating({
|
|
80
|
+
open,
|
|
81
|
+
onOpenChange: (nextOpen) => {
|
|
82
|
+
if (!nextOpen) requestClose();
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const mergedRef = useMergedFloatingRef<HTMLDivElement>(refs, presenceRef, ref);
|
|
87
|
+
|
|
88
|
+
const dismiss = useDismiss(context, {
|
|
89
|
+
enabled: dismissable,
|
|
90
|
+
escapeKey: true,
|
|
91
|
+
outsidePress: dismissOnOutsidePress,
|
|
92
|
+
outsidePressEvent: "mousedown",
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const role = useRole(context, { role: "dialog" });
|
|
96
|
+
|
|
97
|
+
const { getFloatingProps } = useInteractions([dismiss, role]);
|
|
98
|
+
|
|
99
|
+
// Named from its header, same contract as Modal — see SheetContext.
|
|
100
|
+
const titleId = useId();
|
|
101
|
+
const [hasTitle, setHasTitle] = useState(false);
|
|
102
|
+
const registerTitle = useCallback((present: boolean) => setHasTitle(present), []);
|
|
103
|
+
|
|
104
|
+
// `aria-labelledby` beats `aria-label` in the name computation, so a caller
|
|
105
|
+
// who passes a label must not also be pointed at the header — they would
|
|
106
|
+
// never see their own string win.
|
|
107
|
+
const labelledBy = ariaLabelledBy ?? (ariaLabel || !hasTitle ? undefined : titleId);
|
|
108
|
+
|
|
109
|
+
const sheetContextValue = useMemo(() => ({ onClose: requestClose, closable, titleId, registerTitle }), [requestClose, closable, titleId, registerTitle]);
|
|
110
|
+
|
|
111
|
+
if (!isMounted) return null;
|
|
112
|
+
|
|
113
|
+
const isEntering = state === "entering";
|
|
114
|
+
const isExiting = state === "exiting";
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<FloatingFocusManager context={context} modal={false}>
|
|
118
|
+
<div
|
|
119
|
+
ref={mergedRef}
|
|
120
|
+
// Explicit, though `getFloatingProps` also supplies it from `useRole`:
|
|
121
|
+
// the ARIA attributes below are only valid on a dialog, and static
|
|
122
|
+
// analysis cannot see a role that arrives through a spread. Matches Modal.
|
|
123
|
+
role="dialog"
|
|
124
|
+
aria-label={ariaLabel}
|
|
125
|
+
aria-labelledby={labelledBy}
|
|
126
|
+
aria-describedby={ariaDescribedBy}
|
|
127
|
+
tabIndex={-1}
|
|
128
|
+
data-state={state}
|
|
129
|
+
data-side={side}
|
|
130
|
+
className={cn(
|
|
131
|
+
"fixed top-0 bottom-0 z-sheet flex flex-col overflow-hidden bg-bg-normal outline-hidden",
|
|
132
|
+
"border-border-normal shadow-lg",
|
|
133
|
+
side === "right" ? "right-0 border-l" : "left-0 border-r",
|
|
134
|
+
sizeClasses[size],
|
|
135
|
+
"max-sm:inset-x-0",
|
|
136
|
+
isEntering && side === "right" && "animate-slide-right-in",
|
|
137
|
+
isExiting && side === "right" && "animate-slide-right-out",
|
|
138
|
+
isEntering && side === "left" && "animate-slide-left-in",
|
|
139
|
+
isExiting && side === "left" && "animate-slide-left-out",
|
|
140
|
+
className
|
|
141
|
+
)}
|
|
142
|
+
style={style}
|
|
143
|
+
{...getFloatingProps({})}
|
|
144
|
+
>
|
|
145
|
+
<SheetContext.Provider value={sheetContextValue}>{children}</SheetContext.Provider>
|
|
146
|
+
</div>
|
|
147
|
+
</FloatingFocusManager>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
);
|
|
126
151
|
SheetRoot.displayName = "Sheet";
|
|
127
152
|
|
|
128
153
|
// =============================================================================
|
|
@@ -5,6 +5,16 @@ export type OnClose = (event?: MouseEvent<Element> | KeyboardEvent<Element>) =>
|
|
|
5
5
|
interface SheetContextValue {
|
|
6
6
|
onClose: OnClose;
|
|
7
7
|
closable?: boolean | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* The id `Sheet.Header` stamps on itself so the dialog can name itself from
|
|
10
|
+
* its own title instead of being announced as a bare "dialog".
|
|
11
|
+
*/
|
|
12
|
+
titleId?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The header reports its presence — a headerless sheet must not point
|
|
15
|
+
* `aria-labelledby` at an element that never rendered.
|
|
16
|
+
*/
|
|
17
|
+
registerTitle?: (present: boolean) => void;
|
|
8
18
|
}
|
|
9
19
|
|
|
10
20
|
export const SheetContext = createContext<SheetContextValue | null>(null);
|
|
@@ -5,13 +5,28 @@ import { SheetContext } from "./SheetContext";
|
|
|
5
5
|
|
|
6
6
|
export type SheetHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
7
7
|
|
|
8
|
-
export const SheetHeader = React.forwardRef<HTMLDivElement, SheetHeaderProps>(({ className, children, ...props }, ref) => {
|
|
8
|
+
export const SheetHeader = React.forwardRef<HTMLDivElement, SheetHeaderProps>(({ className, children, id, ...props }, ref) => {
|
|
9
9
|
const context = React.useContext(SheetContext);
|
|
10
10
|
const closable = context?.closable;
|
|
11
11
|
const onClose = context?.onClose;
|
|
12
|
+
const registerTitle = context?.registerTitle;
|
|
13
|
+
|
|
14
|
+
// Report the title to the sheet so it can name itself, and withdraw it on
|
|
15
|
+
// unmount. A caller-supplied `id` wins over the generated one — which the
|
|
16
|
+
// sheet can no longer resolve, so it is told there is no title to point at.
|
|
17
|
+
const ownsTitleId = id === undefined;
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
registerTitle?.(ownsTitleId);
|
|
20
|
+
return () => registerTitle?.(false);
|
|
21
|
+
}, [registerTitle, ownsTitleId]);
|
|
12
22
|
|
|
13
23
|
return (
|
|
14
|
-
<div
|
|
24
|
+
<div
|
|
25
|
+
ref={ref}
|
|
26
|
+
id={id ?? context?.titleId}
|
|
27
|
+
className={cn("flex flex-col space-y-1.5 border-border-normal border-b p-6", closable && "pr-12", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
15
30
|
{children}
|
|
16
31
|
{closable && (
|
|
17
32
|
<button
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { cn } from "@sixthshift/design-system/utils";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
|
|
3
|
-
const Skeleton = ({ className, ...props }
|
|
4
|
-
return <div className={cn("animate-pulse rounded-md bg-bg-strong/10", className)} {...props} />;
|
|
5
|
-
};
|
|
4
|
+
const Skeleton = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => {
|
|
5
|
+
return <div ref={ref} className={cn("animate-pulse rounded-md bg-bg-strong/10", className)} {...props} />;
|
|
6
|
+
});
|
|
7
|
+
Skeleton.displayName = "Skeleton";
|
|
6
8
|
|
|
7
9
|
export { Skeleton };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Interpolation } from "@sixthshift/design-system/line-chart";
|
|
2
2
|
import { cn } from "@sixthshift/design-system/utils";
|
|
3
|
-
import
|
|
3
|
+
import * as React from "react";
|
|
4
4
|
|
|
5
5
|
export type SparklineProps = React.HTMLAttributes<HTMLSpanElement> & {
|
|
6
6
|
data: number[];
|
|
@@ -51,43 +51,36 @@ function buildPath(points: { x: number; y: number }[], interpolation: Interpolat
|
|
|
51
51
|
return parts.join(" ");
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export const Sparkline = (
|
|
55
|
-
data,
|
|
56
|
-
|
|
57
|
-
height = 24,
|
|
58
|
-
color = "var(--fg-brand)",
|
|
59
|
-
fillArea = false,
|
|
60
|
-
interpolation = "monotone",
|
|
61
|
-
strokeWidth = 1.5,
|
|
62
|
-
className,
|
|
63
|
-
...rest
|
|
64
|
-
}: SparklineProps) => {
|
|
65
|
-
if (data.length < 2) return null;
|
|
54
|
+
export const Sparkline = React.forwardRef<HTMLSpanElement, SparklineProps>(
|
|
55
|
+
({ data, width = 80, height = 24, color = "var(--fg-brand)", fillArea = false, interpolation = "monotone", strokeWidth = 1.5, className, ...rest }, ref) => {
|
|
56
|
+
if (data.length < 2) return null;
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
const min = Math.min(...data);
|
|
59
|
+
const max = Math.max(...data);
|
|
60
|
+
const range = max - min || 1;
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
62
|
+
const padY = 2;
|
|
63
|
+
const padX = 1;
|
|
64
|
+
const innerW = width - padX * 2;
|
|
65
|
+
const innerH = height - padY * 2;
|
|
75
66
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
const points = data.map((v, i) => ({
|
|
68
|
+
x: padX + (i / (data.length - 1)) * innerW,
|
|
69
|
+
y: padY + innerH - ((v - min) / range) * innerH,
|
|
70
|
+
}));
|
|
80
71
|
|
|
81
|
-
|
|
72
|
+
const path = buildPath(points, interpolation);
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
74
|
+
return (
|
|
75
|
+
<span ref={ref} {...rest} className={cn("inline-block align-middle", className)}>
|
|
76
|
+
<svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} role="img" aria-label="Trend line">
|
|
77
|
+
{fillArea && path && (
|
|
78
|
+
<path d={`${path} L ${points[points.length - 1]!.x} ${height - padY} L ${points[0]!.x} ${height - padY} Z`} fill={color} opacity={0.12} />
|
|
79
|
+
)}
|
|
80
|
+
<path d={path} fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" />
|
|
81
|
+
</svg>
|
|
82
|
+
</span>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
Sparkline.displayName = "Sparkline";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Caption } from "@sixthshift/design-system/caption";
|
|
2
2
|
import { cn } from "@sixthshift/design-system/utils";
|
|
3
|
-
import
|
|
3
|
+
import * as React from "react";
|
|
4
4
|
|
|
5
5
|
export type StatsCardProps = {
|
|
6
6
|
/** Title of the stats card */
|
|
@@ -8,11 +8,11 @@ export type StatsCardProps = {
|
|
|
8
8
|
/** Description text shown below the title */
|
|
9
9
|
description: string;
|
|
10
10
|
/** Optional icon displayed in the header */
|
|
11
|
-
icon?: ReactNode;
|
|
11
|
+
icon?: React.ReactNode;
|
|
12
12
|
/** Visual status indicator via left border color */
|
|
13
13
|
status?: "healthy" | "warning" | "error" | "neutral";
|
|
14
14
|
/** Card content */
|
|
15
|
-
children: ReactNode;
|
|
15
|
+
children: React.ReactNode;
|
|
16
16
|
/** Additional CSS classes */
|
|
17
17
|
className?: string;
|
|
18
18
|
};
|
|
@@ -24,9 +24,9 @@ const statusColors = {
|
|
|
24
24
|
neutral: "border-l-border-subtle",
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export const StatsCard = ({ title, description, icon, status = "neutral", children, className }
|
|
27
|
+
export const StatsCard = React.forwardRef<HTMLDivElement, StatsCardProps>(({ title, description, icon, status = "neutral", children, className }, ref) => {
|
|
28
28
|
return (
|
|
29
|
-
<div className={cn("flex flex-col gap-3 rounded border border-border-subtle border-l-2 bg-bg-subtle p-4", statusColors[status], className)}>
|
|
29
|
+
<div ref={ref} className={cn("flex flex-col gap-3 rounded border border-border-subtle border-l-2 bg-bg-subtle p-4", statusColors[status], className)}>
|
|
30
30
|
<div className="flex items-start justify-between gap-2">
|
|
31
31
|
<div className="flex flex-col gap-0.5">
|
|
32
32
|
<span className="font-medium text-fg-normal">{title}</span>
|
|
@@ -37,4 +37,5 @@ export const StatsCard = ({ title, description, icon, status = "neutral", childr
|
|
|
37
37
|
<div className="flex-1">{children}</div>
|
|
38
38
|
</div>
|
|
39
39
|
);
|
|
40
|
-
};
|
|
40
|
+
});
|
|
41
|
+
StatsCard.displayName = "StatsCard";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from "@sixthshift/design-system/utils";
|
|
2
2
|
import type * as React from "react";
|
|
3
|
-
import { useCallback, useRef } from "react";
|
|
3
|
+
import { forwardRef, useCallback, useRef } from "react";
|
|
4
4
|
import { useTabsContext } from "./TabsContext";
|
|
5
5
|
import { TabsTrigger } from "./TabsTrigger";
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ export type TabsListProps = {
|
|
|
11
11
|
className?: string;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export const TabsList = ({ orientation = "horizontal", className }
|
|
14
|
+
export const TabsList = forwardRef<HTMLDivElement, TabsListProps>(({ orientation = "horizontal", className }, ref) => {
|
|
15
15
|
const { items, value, onValueChange } = useTabsContext();
|
|
16
16
|
const triggerRefs = useRef<(HTMLButtonElement | null)[]>([]);
|
|
17
17
|
|
|
@@ -78,6 +78,7 @@ export const TabsList = ({ orientation = "horizontal", className }: TabsListProp
|
|
|
78
78
|
|
|
79
79
|
return (
|
|
80
80
|
<div
|
|
81
|
+
ref={ref}
|
|
81
82
|
role="tablist"
|
|
82
83
|
aria-orientation={orientation}
|
|
83
84
|
className={cn("inline-flex gap-1", orientation === "vertical" ? "flex-col" : "flex-row items-center", className)}
|
|
@@ -95,4 +96,5 @@ export const TabsList = ({ orientation = "horizontal", className }: TabsListProp
|
|
|
95
96
|
))}
|
|
96
97
|
</div>
|
|
97
98
|
);
|
|
98
|
-
};
|
|
99
|
+
});
|
|
100
|
+
TabsList.displayName = "TabsList";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cn } from "@sixthshift/design-system/utils";
|
|
2
|
+
import { forwardRef } from "react";
|
|
2
3
|
import { useTabsContext } from "./TabsContext";
|
|
3
4
|
|
|
4
5
|
export type TabsPanelsProps = {
|
|
@@ -6,7 +7,7 @@ export type TabsPanelsProps = {
|
|
|
6
7
|
className?: string;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
|
-
export const TabsPanels = ({ className }
|
|
10
|
+
export const TabsPanels = forwardRef<HTMLDivElement, TabsPanelsProps>(({ className }, ref) => {
|
|
10
11
|
const { items, value, baseId } = useTabsContext();
|
|
11
12
|
|
|
12
13
|
const activeItem = items.find((item) => item.value === value);
|
|
@@ -19,8 +20,9 @@ export const TabsPanels = ({ className }: TabsPanelsProps) => {
|
|
|
19
20
|
const content = typeof activeItem.content === "function" ? activeItem.content() : activeItem.content;
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
|
-
<div id={panelId} role="tabpanel" aria-labelledby={triggerId} className={cn("focus-visible:outline-hidden", className)}>
|
|
23
|
+
<div ref={ref} id={panelId} role="tabpanel" aria-labelledby={triggerId} className={cn("focus-visible:outline-hidden", className)}>
|
|
23
24
|
{content}
|
|
24
25
|
</div>
|
|
25
26
|
);
|
|
26
|
-
};
|
|
27
|
+
});
|
|
28
|
+
TabsPanels.displayName = "TabsPanels";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Badge } from "@sixthshift/design-system/badge";
|
|
2
2
|
import { cn } from "@sixthshift/design-system/utils";
|
|
3
3
|
import { X } from "lucide-react";
|
|
4
|
+
import * as React from "react";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* One tag, rendered prettily. A `namespace:value` tag (`project:website`)
|
|
@@ -22,13 +23,18 @@ export type TagChipProps = {
|
|
|
22
23
|
className?: string;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
export const TagChip = ({ tag, onRemove, size = "sm", className }
|
|
26
|
+
export const TagChip = React.forwardRef<HTMLSpanElement, TagChipProps>(({ tag, onRemove, size = "sm", className }, ref) => {
|
|
26
27
|
const sep = tag.indexOf(":");
|
|
27
28
|
const namespace = sep > 0 ? tag.slice(0, sep) : null;
|
|
28
29
|
const value = sep > 0 ? tag.slice(sep + 1) : tag;
|
|
29
30
|
|
|
30
31
|
return (
|
|
31
|
-
<Badge
|
|
32
|
+
<Badge
|
|
33
|
+
ref={ref}
|
|
34
|
+
variant="outline"
|
|
35
|
+
intent="muted"
|
|
36
|
+
className={cn("gap-1 font-normal", size === "sm" ? "px-1.5 py-0 text-[10px]" : "px-2 py-0.5 text-xs", className)}
|
|
37
|
+
>
|
|
32
38
|
{namespace && <span className="text-fg-subtle">{namespace}:</span>}
|
|
33
39
|
<span>{value}</span>
|
|
34
40
|
{onRemove && (
|
|
@@ -43,4 +49,5 @@ export const TagChip = ({ tag, onRemove, size = "sm", className }: TagChipProps)
|
|
|
43
49
|
)}
|
|
44
50
|
</Badge>
|
|
45
51
|
);
|
|
46
|
-
};
|
|
52
|
+
});
|
|
53
|
+
TagChip.displayName = "TagChip";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TagChip } from "@sixthshift/design-system/tag-chip";
|
|
2
2
|
import { cn } from "@sixthshift/design-system/utils";
|
|
3
|
-
import { type KeyboardEvent, useState } from "react";
|
|
3
|
+
import { forwardRef, type KeyboardEvent, useState } from "react";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Token input for tags: existing tags render as removable chips, typing plus
|
|
@@ -18,7 +18,7 @@ export type TagInputProps = {
|
|
|
18
18
|
className?: string;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export const TagInput = ({ value, onChange, placeholder = "Add a tag…", id, className }
|
|
21
|
+
export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onChange, placeholder = "Add a tag…", id, className }, ref) => {
|
|
22
22
|
const [draft, setDraft] = useState("");
|
|
23
23
|
|
|
24
24
|
const commit = () => {
|
|
@@ -38,6 +38,7 @@ export const TagInput = ({ value, onChange, placeholder = "Add a tag…", id, cl
|
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<div
|
|
41
|
+
ref={ref}
|
|
41
42
|
className={cn(
|
|
42
43
|
"flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-border-normal bg-bg-normal px-2 py-1.5 text-sm shadow-xs transition-colors focus-within:ring-2 focus-within:ring-focus-ring",
|
|
43
44
|
className
|
|
@@ -57,4 +58,5 @@ export const TagInput = ({ value, onChange, placeholder = "Add a tag…", id, cl
|
|
|
57
58
|
/>
|
|
58
59
|
</div>
|
|
59
60
|
);
|
|
60
|
-
};
|
|
61
|
+
});
|
|
62
|
+
TagInput.displayName = "TagInput";
|