atlas-react-kit 1.2.1 → 1.2.3
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/COMPONENTS.md +22 -18
- package/DESIGN_RULES.md +7 -7
- package/dist/alert.js +2 -2
- package/dist/badge.js +1 -1
- package/dist/button.js +1 -1
- package/dist/card.js +2 -1
- package/dist/chart.js +1 -1
- package/dist/combobox.d.ts +4 -3
- package/dist/combobox.js +3 -7
- package/dist/dialog.js +2 -1
- package/dist/dropdown-menu.js +6 -4
- package/dist/field.js +2 -2
- package/dist/form/checkbox-field.d.ts +2 -4
- package/dist/form/checkbox-field.js +9 -12
- package/dist/form/combobox-field.d.ts +2 -2
- package/dist/form/combobox-field.js +5 -6
- package/dist/form/control-field.d.ts +5 -5
- package/dist/form/control-field.js +9 -7
- package/dist/form/date-picker-field.d.ts +1 -1
- package/dist/form/date-picker-field.js +3 -10
- package/dist/form/date-time-picker-field.d.ts +1 -1
- package/dist/form/date-time-picker-field.js +3 -10
- package/dist/form/feedback-field.js +2 -1
- package/dist/form/field-error.d.ts +10 -1
- package/dist/form/field-error.js +2 -1
- package/dist/form/field-shell.d.ts +27 -16
- package/dist/form/field-shell.js +27 -2
- package/dist/form/focus-first-invalid.d.ts +7 -4
- package/dist/form/focus-first-invalid.js +10 -6
- package/dist/form/markdown-field.d.ts +1 -1
- package/dist/form/markdown-field.js +8 -4
- package/dist/form/select-field.d.ts +2 -8
- package/dist/form/select-field.js +5 -7
- package/dist/form/text-field.d.ts +2 -8
- package/dist/form/text-field.js +8 -3
- package/dist/form/toggle-group-field.d.ts +2 -2
- package/dist/form/toggle-group-field.js +5 -6
- package/dist/info-tip.d.ts +3 -1
- package/dist/info-tip.js +4 -1
- package/dist/internal/calendar-size.d.ts +1 -1
- package/dist/internal/calendar-size.js +1 -1
- package/dist/internal/form-control.d.ts +6 -0
- package/dist/internal/form-control.js +6 -0
- package/dist/internal/kanban-layout.js +2 -1
- package/dist/internal/listbox-navigation.d.ts +8 -8
- package/dist/internal/listbox-navigation.js +23 -23
- package/dist/internal/overlay-styles.d.ts +5 -0
- package/dist/internal/overlay-styles.js +5 -0
- package/dist/internal/styles.d.ts +10 -3
- package/dist/internal/styles.js +12 -5
- package/dist/internal/tabs-styles.js +1 -1
- package/dist/kanban.js +3 -3
- package/dist/meter.js +1 -1
- package/dist/pagination.d.ts +1 -1
- package/dist/pagination.js +3 -3
- package/dist/picker-shell.d.ts +3 -1
- package/dist/picker-shell.js +3 -3
- package/dist/popover.js +4 -4
- package/dist/progress.js +1 -1
- package/dist/search-picker.js +4 -8
- package/dist/select.js +4 -4
- package/dist/separator.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/slider.js +1 -1
- package/dist/tabs.js +1 -1
- package/dist/toast.js +11 -19
- package/dist/toggle-group.d.ts +1 -1
- package/dist/toggle-group.js +36 -2
- package/package.json +1 -1
- package/skills/atlas-react-kit/SKILL.md +1 -1
- package/theme.css +6 -0
|
@@ -17,6 +17,11 @@ export const overlaySideSlide = "data-[side=bottom]:slide-in-from-top-2 data-[si
|
|
|
17
17
|
export const overlayFade = "duration-100 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0";
|
|
18
18
|
/** Fade plus a slight zoom, for panels (the backdrop only fades). */
|
|
19
19
|
export const overlayFadeZoom = `${overlayFade} data-open:zoom-in-95 data-closed:zoom-out-95`;
|
|
20
|
+
/**
|
|
21
|
+
* A panel opened from a trigger (Popover, Select, DropdownMenu): the
|
|
22
|
+
* surface, sliding in from the trigger's side with a fade and zoom.
|
|
23
|
+
*/
|
|
24
|
+
export const anchoredPanel = `${overlaySurface} ${overlaySideSlide} ${overlayFadeZoom}`;
|
|
20
25
|
/**
|
|
21
26
|
* Base of a menu or listbox row (SelectItem, DropdownMenuItem, Combobox and
|
|
22
27
|
* SearchPicker options). Each component adds its own right padding and
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
export declare const focusRing = "outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";
|
|
11
11
|
/** The same ring on a wrapper with keyboard focus inside it. */
|
|
12
12
|
export declare const focusRingWithin = "has-focus-visible:ring-2 has-focus-visible:ring-ring has-focus-visible:ring-offset-2 has-focus-visible:ring-offset-background";
|
|
13
|
-
/** `aria-invalid`: destructive border
|
|
14
|
-
export declare const invalidState = "aria-invalid:border-destructive
|
|
13
|
+
/** `aria-invalid`: a destructive border; keyboard focus keeps the shared solid ring. */
|
|
14
|
+
export declare const invalidState = "aria-invalid:border-destructive";
|
|
15
15
|
/** Muted trigger text while empty (`data-placeholder` or `data-empty`). */
|
|
16
16
|
export declare const emptyValueText = "data-placeholder:text-muted-foreground data-[empty=true]:text-muted-foreground";
|
|
17
17
|
/** Native `disabled`: dimmed, with no hover or click. */
|
|
@@ -60,7 +60,7 @@ export declare const listboxEmpty = "px-3 py-4 text-center text-sm text-muted-fo
|
|
|
60
60
|
export declare const listboxScroll = "max-h-60 overflow-y-auto";
|
|
61
61
|
/** Options in menus and listboxes. */
|
|
62
62
|
export declare const optionState: {
|
|
63
|
-
/** Highlight as focus moves:
|
|
63
|
+
/** Highlight as focus moves: the selected wash plus a 2px inset ring bar. */
|
|
64
64
|
focus: string;
|
|
65
65
|
/** The same highlight for lists that track the active option in state. */
|
|
66
66
|
active: string;
|
|
@@ -97,6 +97,13 @@ export declare const controlSize: {
|
|
|
97
97
|
* tailwind-merge then drops the `text-xs`.
|
|
98
98
|
*/
|
|
99
99
|
export declare const controlText = "text-xs font-semibold tracking-widest whitespace-nowrap uppercase";
|
|
100
|
+
/**
|
|
101
|
+
* Secondary text under a title (CardDescription, PopoverDescription,
|
|
102
|
+
* DialogDescription, AlertDescription).
|
|
103
|
+
*/
|
|
104
|
+
export declare const descriptionText = "text-sm leading-relaxed text-muted-foreground";
|
|
105
|
+
/** Field and form-level error text share one size, weight, and color. */
|
|
106
|
+
export declare const errorText = "text-sm font-normal text-destructive";
|
|
100
107
|
/** Field-label text (Label, FieldLegend, FieldTitle, PopoverTitle). */
|
|
101
108
|
export declare const labelText = "text-xs font-semibold tracking-wide uppercase";
|
|
102
109
|
/**
|
package/dist/internal/styles.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
export const focusRing = "outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";
|
|
11
11
|
/** The same ring on a wrapper with keyboard focus inside it. */
|
|
12
12
|
export const focusRingWithin = "has-focus-visible:ring-2 has-focus-visible:ring-ring has-focus-visible:ring-offset-2 has-focus-visible:ring-offset-background";
|
|
13
|
-
/** `aria-invalid`: destructive border
|
|
14
|
-
export const invalidState = "aria-invalid:border-destructive
|
|
13
|
+
/** `aria-invalid`: a destructive border; keyboard focus keeps the shared solid ring. */
|
|
14
|
+
export const invalidState = "aria-invalid:border-destructive";
|
|
15
15
|
/** Muted trigger text while empty (`data-placeholder` or `data-empty`). */
|
|
16
16
|
export const emptyValueText = "data-placeholder:text-muted-foreground data-[empty=true]:text-muted-foreground";
|
|
17
17
|
/** Native `disabled`: dimmed, with no hover or click. */
|
|
@@ -60,10 +60,10 @@ export const listboxEmpty = "px-3 py-4 text-center text-sm text-muted-foreground
|
|
|
60
60
|
export const listboxScroll = "max-h-60 overflow-y-auto";
|
|
61
61
|
/** Options in menus and listboxes. */
|
|
62
62
|
export const optionState = {
|
|
63
|
-
/** Highlight as focus moves:
|
|
64
|
-
focus: "focus:bg-
|
|
63
|
+
/** Highlight as focus moves: the selected wash plus a 2px inset ring bar. */
|
|
64
|
+
focus: "focus:bg-selected focus:text-selected-foreground focus:shadow-[inset_2px_0_0_var(--color-ring)]",
|
|
65
65
|
/** The same highlight for lists that track the active option in state. */
|
|
66
|
-
active: "bg-
|
|
66
|
+
active: "bg-selected text-selected-foreground shadow-[inset_2px_0_0_var(--color-ring)]",
|
|
67
67
|
/** The chosen value (`data-state="checked"`); a check icon marks it too. */
|
|
68
68
|
checked: "data-[state=checked]:bg-selected data-[state=checked]:text-selected-foreground",
|
|
69
69
|
/** The chosen value in lists that track selection in state. */
|
|
@@ -97,6 +97,13 @@ export const controlSize = {
|
|
|
97
97
|
* tailwind-merge then drops the `text-xs`.
|
|
98
98
|
*/
|
|
99
99
|
export const controlText = "text-xs font-semibold tracking-widest whitespace-nowrap uppercase";
|
|
100
|
+
/**
|
|
101
|
+
* Secondary text under a title (CardDescription, PopoverDescription,
|
|
102
|
+
* DialogDescription, AlertDescription).
|
|
103
|
+
*/
|
|
104
|
+
export const descriptionText = "text-sm leading-relaxed text-muted-foreground";
|
|
105
|
+
/** Field and form-level error text share one size, weight, and color. */
|
|
106
|
+
export const errorText = "text-sm font-normal text-destructive";
|
|
100
107
|
/** Field-label text (Label, FieldLegend, FieldTitle, PopoverTitle). */
|
|
101
108
|
export const labelText = "text-xs font-semibold tracking-wide uppercase";
|
|
102
109
|
/**
|
|
@@ -6,7 +6,7 @@ import { disabledState, focusRing, inlineIcon, selectedState, } from "./styles.j
|
|
|
6
6
|
* without it (`auto`), the row reads the orientation from the `group/tabs`
|
|
7
7
|
* root instead, as it always has for apps building their own list.
|
|
8
8
|
*/
|
|
9
|
-
const tabsListVariants = cva("group/tabs-list inline-flex w-max min-w-full items-stretch justify-start p-0 text-muted-foreground", {
|
|
9
|
+
const tabsListVariants = cva("group/tabs-list inline-flex w-max min-w-full items-stretch justify-start p-0 after:w-1 after:shrink-0 after:content-[''] text-muted-foreground", {
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
12
12
|
default: "bg-muted",
|
package/dist/kanban.js
CHANGED
|
@@ -77,7 +77,7 @@ function KanbanBoard({ columns, items, getColumnId, onMove, onComplete, onDelete
|
|
|
77
77
|
}, [cardClassName, itemById, renderCard]);
|
|
78
78
|
// `min-w-0` lets a flex or grid parent shrink the board so the scroller,
|
|
79
79
|
// not the page, overflows.
|
|
80
|
-
return (_jsx("div", { "data-slot": "kanban-board", className: cn("min-w-0", className), ...props, children: _jsxs(DragDropProvider, { plugins: configureKanbanPlugins, onDragOver: handleDragOver, onDragEnd: handleDragEnd, children: [_jsxs("div", { className: "relative min-w-0", children: [_jsx("div", { ref: scrollerRef, "data-slot": "kanban-scroller", "data-loading": dimmed || undefined, "data-overflow-start": overflow.start || undefined, "data-overflow-end": overflow.end || undefined, onScroll: overflow.measure, className: cn("flex min-w-0 gap-4 overflow-x-auto pb-2",
|
|
80
|
+
return (_jsx("div", { "data-slot": "kanban-board", className: cn("min-w-0", className), ...props, children: _jsxs(DragDropProvider, { plugins: configureKanbanPlugins, onDragOver: handleDragOver, onDragEnd: handleDragEnd, children: [_jsxs("div", { className: "relative min-w-0 pb-12", children: [_jsx("div", { ref: scrollerRef, "data-slot": "kanban-scroller", "data-loading": dimmed || undefined, "data-overflow-start": overflow.start || undefined, "data-overflow-end": overflow.end || undefined, onScroll: overflow.measure, className: cn("flex min-w-0 gap-4 overflow-x-auto pb-2",
|
|
81
81
|
// AutoScroller scrolls in small steps near the edge; mandatory
|
|
82
82
|
// snap would pull each one back, so it is off mid-drag.
|
|
83
83
|
"snap-x snap-mandatory scroll-px-2 has-data-dragging:snap-none", "data-loading:opacity-60", scrollerClassName), children: columns.map((column) => {
|
|
@@ -125,7 +125,7 @@ function KanbanColumnView({ column, count, emptyLabel, loading, className, child
|
|
|
125
125
|
collisionPriority: COLUMN_DROP_PRIORITY,
|
|
126
126
|
});
|
|
127
127
|
const empty = count === 0;
|
|
128
|
-
return (_jsxs("div", { ref: ref, "data-slot": "kanban-column", "data-drop-target": isDropTarget || undefined, className: cn("flex snap-start flex-col gap-3 p-3", "bg-muted/40 ring-1 ring-foreground/5", "data-drop-target:bg-muted/60 data-drop-target:ring-2 data-drop-target:ring-ring/60", columnSize, className), children: [_jsxs("
|
|
128
|
+
return (_jsxs("div", { ref: ref, "data-slot": "kanban-column", "data-drop-target": isDropTarget || undefined, className: cn("flex snap-start flex-col gap-3 p-3", "bg-muted/40 ring-1 ring-foreground/5", "data-drop-target:bg-muted/60 data-drop-target:ring-2 data-drop-target:ring-ring/60", columnSize, className), children: [_jsxs("div", { "data-slot": "kanban-column-header", className: "flex flex-wrap items-start justify-between gap-x-2 gap-y-0.5", children: [_jsxs("span", { className: "flex max-w-full min-w-0 items-center gap-2 text-xs font-semibold tracking-widest uppercase", children: [column.color ? (_jsx("span", { "aria-hidden": true, className: "size-2 shrink-0 rounded-full", style: { backgroundColor: column.color } })) : null, _jsx("span", { className: "truncate leading-tight", title: column.label, children: column.label })] }), _jsxs("span", { className: "ml-auto flex max-w-full min-w-0 flex-col items-end gap-0.5 text-muted-foreground tabular-nums", children: [_jsx("span", { className: "text-xs", children: count }), column.badge ? (_jsx("span", { className: "max-w-full truncate text-[10px] font-medium", children: column.badge })) : null] })] }), _jsx("div", { className: "-m-1 mr-0 flex min-h-32 flex-1 flex-col gap-2 overflow-y-auto p-1", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-20" }), _jsx(Skeleton, { className: "h-16" })] })) : (_jsxs(_Fragment, { children: [children, _jsx("p", { "data-slot": "kanban-column-empty", "aria-hidden": !empty, className: cn("border border-dashed px-3 py-6 text-center text-xs text-muted-foreground", !empty && "hidden"), children: emptyLabel })] })) })] }));
|
|
129
129
|
}
|
|
130
130
|
const cardChrome = cn("flex border border-border bg-card text-card-foreground");
|
|
131
131
|
const handleChrome = cn("flex shrink-0 items-center self-stretch border-r border-border", "bg-muted/30 px-1.5 text-muted-foreground");
|
|
@@ -185,7 +185,7 @@ function ActionZone({ id, label, regionLabel, icon: Icon, tone, visible, }) {
|
|
|
185
185
|
}
|
|
186
186
|
function ScrollButton({ side, onClick, }) {
|
|
187
187
|
const Icon = side === "start" ? ChevronLeft : ChevronRight;
|
|
188
|
-
return (_jsx(Button, { type: "button", variant: "outline", size: "icon-sm", "data-slot": "kanban-scroll-button", "aria-label": side === "start" ? "Show previous columns" : "Show next columns", onClick: onClick, className: cn("absolute
|
|
188
|
+
return (_jsx(Button, { type: "button", variant: "outline", size: "icon-sm", "data-slot": "kanban-scroll-button", "aria-label": side === "start" ? "Show previous columns" : "Show next columns", onClick: onClick, className: cn("absolute bottom-1 z-20", side === "start" ? "left-1" : "right-1"), children: _jsx(Icon, {}) }));
|
|
189
189
|
}
|
|
190
190
|
function OverflowFade({ side, visible, }) {
|
|
191
191
|
return (_jsx("div", { "aria-hidden": true, "data-slot": "kanban-overflow-fade", "data-side": side, className: cn("pointer-events-none absolute inset-y-0 z-10 w-10 to-transparent transition-opacity", side === "start"
|
package/dist/meter.js
CHANGED
|
@@ -15,6 +15,6 @@ function Meter({ value, min = 0, max, fillClassName = "bg-primary", markers, "ar
|
|
|
15
15
|
return 0;
|
|
16
16
|
return clamp(((amount - min) / span) * 100, 0, 100);
|
|
17
17
|
};
|
|
18
|
-
return (_jsxs("div", { ...props, role: "meter", "data-slot": "meter", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": clamp(current, min, max), "aria-label": ariaLabel, className: cn("relative h-1.5 w-full overflow-hidden bg-
|
|
18
|
+
return (_jsxs("div", { ...props, role: "meter", "data-slot": "meter", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": clamp(current, min, max), "aria-label": ariaLabel, className: cn("relative h-1.5 w-full overflow-hidden bg-input", className), children: [_jsx("div", { "data-slot": "meter-fill", className: cn("h-full", fillClassName), style: { width: `${toPercent(current)}%` } }), markers?.map((marker) => (_jsx("div", { "aria-hidden": true, "data-slot": "meter-marker", className: cn("absolute inset-y-0 w-px bg-foreground/40", marker.className), style: { left: `${toPercent(marker.position)}%` } }, marker.position)))] }));
|
|
19
19
|
}
|
|
20
20
|
export { Meter };
|
package/dist/pagination.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
/**
|
|
3
3
|
* Page links for long lists and tables. Links are plain anchors so the page
|
|
4
4
|
* lives in the URL; pass `onClick` with `href` for client-side routing.
|
|
5
|
-
* The nav
|
|
5
|
+
* The nav fills its container: place its links with `className` (`justify-center`,
|
|
6
6
|
* `justify-end`, `mx-auto`) to suit the layout.
|
|
7
7
|
*/
|
|
8
8
|
declare function Pagination({ className, ...props }: React.ComponentProps<"nav">): React.JSX.Element;
|
package/dist/pagination.js
CHANGED
|
@@ -7,14 +7,14 @@ import { cn } from "./utils.js";
|
|
|
7
7
|
/**
|
|
8
8
|
* Page links for long lists and tables. Links are plain anchors so the page
|
|
9
9
|
* lives in the URL; pass `onClick` with `href` for client-side routing.
|
|
10
|
-
* The nav
|
|
10
|
+
* The nav fills its container: place its links with `className` (`justify-center`,
|
|
11
11
|
* `justify-end`, `mx-auto`) to suit the layout.
|
|
12
12
|
*/
|
|
13
13
|
function Pagination({ className, ...props }) {
|
|
14
|
-
return (_jsx("nav", { "aria-label": "Pagination", "data-slot": "pagination", className: cn("flex", className), ...props }));
|
|
14
|
+
return (_jsx("nav", { "aria-label": "Pagination", "data-slot": "pagination", className: cn("@container/pagination flex w-full min-w-0 p-1", className), ...props }));
|
|
15
15
|
}
|
|
16
16
|
function PaginationContent({ className, ...props }) {
|
|
17
|
-
return (_jsx("ul", { "data-slot": "pagination-content", className: cn("flex flex-row items-center gap-1", className), ...props }));
|
|
17
|
+
return (_jsx("ul", { "data-slot": "pagination-content", className: cn("flex flex-row flex-wrap items-center gap-1", className), ...props }));
|
|
18
18
|
}
|
|
19
19
|
function PaginationItem({ ...props }) {
|
|
20
20
|
return _jsx("li", { "data-slot": "pagination-item", ...props });
|
package/dist/picker-shell.d.ts
CHANGED
|
@@ -64,6 +64,8 @@ export type PickerTriggerProps = {
|
|
|
64
64
|
"aria-labelledby"?: string;
|
|
65
65
|
/** Forwarded to the trigger, e.g. the id of a hint or error text. */
|
|
66
66
|
"aria-describedby"?: string;
|
|
67
|
+
/** Forwarded to the trigger; a form field sets it for `focusFirstInvalid`. */
|
|
68
|
+
"data-field-name"?: string;
|
|
67
69
|
/** Popover side. Defaults to `bottom`; Radix still flips on collision. */
|
|
68
70
|
side?: React.ComponentProps<typeof PopoverContent>["side"];
|
|
69
71
|
/** Month shown when the popover opens; falls back to the selected date. */
|
|
@@ -112,5 +114,5 @@ type PickerShellProps = Omit<PickerTriggerProps, "placeholder"> & {
|
|
|
112
114
|
* Form-control trigger plus the viewport-clamped popover holding the
|
|
113
115
|
* calendar, any extra rows, and an optional Clear row.
|
|
114
116
|
*/
|
|
115
|
-
export declare function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled, children, }: PickerShellProps): React.JSX.Element;
|
|
117
|
+
export declare function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-field-name": fieldName, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled, children, }: PickerShellProps): React.JSX.Element;
|
|
116
118
|
export {};
|
package/dist/picker-shell.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { CalendarIcon } from "lucide-react";
|
|
5
5
|
import { Button } from "./button.js";
|
|
6
6
|
import { toDate, } from "./internal/date-like.js";
|
|
7
|
-
import { PICKER_COLLISION_PADDING, pickerContentClassName, pickerTriggerClassName, pickerValueId, } from "./internal/form-control.js";
|
|
7
|
+
import { fieldNameProps, PICKER_COLLISION_PADDING, pickerContentClassName, pickerTriggerClassName, pickerValueId, } from "./internal/form-control.js";
|
|
8
8
|
import { LazyCalendar, preloadCalendar } from "./lazy-calendar.js";
|
|
9
9
|
import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
10
10
|
import { cn } from "./utils.js";
|
|
@@ -39,8 +39,8 @@ function limitCalendarProps(calendarProps, minDate, maxDate) {
|
|
|
39
39
|
* Form-control trigger plus the viewport-clamped popover holding the
|
|
40
40
|
* calendar, any extra rows, and an optional Clear row.
|
|
41
41
|
*/
|
|
42
|
-
export function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled = false, children, }) {
|
|
43
|
-
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { id: id, type: "button", variant: "outline", disabled: disabled, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-empty": empty, className: cn(pickerTriggerClassName, className), onPointerEnter: preloadCalendar, onFocus: preloadCalendar, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), _jsx("span", { "data-slot": "date-picker-value", className: "min-w-0 text-left whitespace-normal", id: id ? pickerValueId(id) : undefined, children: label })] }) }), _jsxs(PopoverContent, { align: "start", side: side, collisionPadding: PICKER_COLLISION_PADDING, "aria-label": dialogLabel,
|
|
42
|
+
export function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-field-name": fieldName, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled = false, children, }) {
|
|
43
|
+
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { id: id, type: "button", variant: "outline", disabled: disabled, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...fieldNameProps(fieldName), "data-empty": empty, className: cn(pickerTriggerClassName, className), onPointerEnter: preloadCalendar, onFocus: preloadCalendar, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), _jsx("span", { "data-slot": "date-picker-value", className: "min-w-0 text-left whitespace-normal", id: id ? pickerValueId(id) : undefined, children: label })] }) }), _jsxs(PopoverContent, { align: "start", side: side, collisionPadding: PICKER_COLLISION_PADDING, "aria-label": dialogLabel,
|
|
44
44
|
// The calendar's `autoFocus` puts focus on the selected day (or
|
|
45
45
|
// today) once it loads, as the APG date picker dialog does; Radix
|
|
46
46
|
// focusing the popover first would leave it on the container.
|
package/dist/popover.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Popover as PopoverPrimitive } from "radix-ui";
|
|
5
|
-
import { OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET,
|
|
6
|
-
import { labelText } from "./internal/styles.js";
|
|
5
|
+
import { anchoredPanel, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, } from "./internal/overlay-styles.js";
|
|
6
|
+
import { descriptionText, labelText } from "./internal/styles.js";
|
|
7
7
|
import { cn } from "./utils.js";
|
|
8
8
|
function Popover({ ...props }) {
|
|
9
9
|
return _jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
|
|
@@ -12,7 +12,7 @@ function PopoverTrigger({ ...props }) {
|
|
|
12
12
|
return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
13
13
|
}
|
|
14
14
|
function PopoverContent({ className, align = "center", sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, ...props }) {
|
|
15
|
-
return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(
|
|
15
|
+
return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(anchoredPanel, "z-50 flex max-w-(--radix-popover-content-available-width) origin-(--radix-popover-content-transform-origin) flex-col gap-4 p-4 text-sm outline-hidden", className), ...props }) }));
|
|
16
16
|
}
|
|
17
17
|
function PopoverAnchor({ ...props }) {
|
|
18
18
|
return _jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
|
|
@@ -24,6 +24,6 @@ function PopoverTitle({ className, ...props }) {
|
|
|
24
24
|
return (_jsx("h2", { "data-slot": "popover-title", className: cn(labelText, className), ...props }));
|
|
25
25
|
}
|
|
26
26
|
function PopoverDescription({ className, ...props }) {
|
|
27
|
-
return (_jsx("p", { "data-slot": "popover-description", className: cn("mt-0.5
|
|
27
|
+
return (_jsx("p", { "data-slot": "popover-description", className: cn("mt-0.5", descriptionText, className), ...props }));
|
|
28
28
|
}
|
|
29
29
|
export { Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, };
|
package/dist/progress.js
CHANGED
|
@@ -14,6 +14,6 @@ function Progress({ className, indicatorClassName, value, max = 100, ...props })
|
|
|
14
14
|
const scale = Number.isFinite(max) && max > 0 ? max : 100;
|
|
15
15
|
const current = value != null && Number.isFinite(value) ? clamp(value, 0, scale) : null;
|
|
16
16
|
const filled = current == null ? 0 : (current / scale) * 100;
|
|
17
|
-
return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", value: current, max: scale, className: cn("relative h-2 w-full overflow-hidden rounded-none bg-
|
|
17
|
+
return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", value: current, max: scale, className: cn("relative h-2 w-full overflow-hidden rounded-none bg-input", className), ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: cn("h-full w-full flex-1 bg-primary transition-transform", indicatorClassName), style: { transform: `translateX(-${100 - filled}%)` } }) }));
|
|
18
18
|
}
|
|
19
19
|
export { Progress };
|
package/dist/search-picker.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Label } from "./label.js";
|
|
|
6
6
|
import { handleListboxKey } from "./internal/listbox-navigation.js";
|
|
7
7
|
import { Listbox, ListboxEmptyStatus, listboxInputAria, PickerOption, } from "./internal/listbox-option.js";
|
|
8
8
|
import { createSearchIndex, filterSearchIndex, foldSearchText, normalizeSearchQuery, } from "./internal/search.js";
|
|
9
|
-
import { cn } from "./utils.js";
|
|
9
|
+
import { cn, onInputChange } from "./utils.js";
|
|
10
10
|
export { foldSearchText };
|
|
11
11
|
/**
|
|
12
12
|
* Default SearchPicker filter: the folded label includes the folded query.
|
|
@@ -63,14 +63,10 @@ function SearchPicker({ items, getValue, getLabel, filter = defaultSearchFilter,
|
|
|
63
63
|
}, [onSelect]);
|
|
64
64
|
const onKeyDown = (event) => {
|
|
65
65
|
const handled = handleListboxKey(event, {
|
|
66
|
+
items: filtered,
|
|
66
67
|
highlight,
|
|
67
|
-
length: filtered.length,
|
|
68
68
|
setHighlight,
|
|
69
|
-
|
|
70
|
-
const item = filtered[index];
|
|
71
|
-
if (item)
|
|
72
|
-
selectItem(item);
|
|
73
|
-
},
|
|
69
|
+
onPick: selectItem,
|
|
74
70
|
});
|
|
75
71
|
if (handled || event.key !== "Escape")
|
|
76
72
|
return;
|
|
@@ -81,6 +77,6 @@ function SearchPicker({ items, getValue, getLabel, filter = defaultSearchFilter,
|
|
|
81
77
|
}
|
|
82
78
|
event.currentTarget.blur();
|
|
83
79
|
};
|
|
84
|
-
return (_jsxs("div", { "data-slot": "search-picker", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx(Label, { htmlFor: inputId, children: label }), _jsx(Input, { id: inputId, role: "combobox", "aria-expanded": true, "aria-controls": listId, ...listboxInputAria(listId, active ? highlight : undefined), value: query, disabled: disabled, placeholder: placeholder, onChange: (
|
|
80
|
+
return (_jsxs("div", { "data-slot": "search-picker", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx(Label, { htmlFor: inputId, children: label }), _jsx(Input, { id: inputId, role: "combobox", "aria-expanded": true, "aria-controls": listId, ...listboxInputAria(listId, active ? highlight : undefined), value: query, disabled: disabled, placeholder: placeholder, onChange: onInputChange(setQuery), onKeyDown: onKeyDown }), _jsx(Listbox, { id: listId, empty: empty, "aria-label": listLabel ?? label, className: cn(listFrame, listClassName), children: rows.map(({ item, value: itemValue }, index) => (_jsx(PickerOption, { "data-slot": "search-picker-option", listId: listId, index: index, active: index === highlight, selected: itemValue === value, disabled: disabled, item: item, getLabel: getLabel, onHighlight: setHighlight, onSelect: selectItem }, itemValue))) }), _jsx(ListboxEmptyStatus, { "data-slot": "search-picker-empty", empty: empty, className: listFrame, children: emptyText })] }));
|
|
85
81
|
}
|
|
86
82
|
export { SearchPicker };
|
package/dist/select.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Select as SelectPrimitive } from "radix-ui";
|
|
5
5
|
import { dataDisabledState, disabledState, emptyValueText, fieldSurface, focusRing, inlineIcon, invalidState, optionState, } from "./internal/styles.js";
|
|
6
|
-
import { menuLabel, optionRow, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET,
|
|
6
|
+
import { anchoredPanel, menuLabel, optionRow, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, } from "./internal/overlay-styles.js";
|
|
7
7
|
import { cn } from "./utils.js";
|
|
8
8
|
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
|
|
9
9
|
/**
|
|
@@ -22,17 +22,17 @@ function SelectValue({ ...props }) {
|
|
|
22
22
|
return _jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
|
|
23
23
|
}
|
|
24
24
|
function SelectTrigger({ className, size = "default", children, ...props }) {
|
|
25
|
-
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn(fieldSurface, focusRing, invalidState, disabledState, emptyValueText,
|
|
25
|
+
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn(fieldSurface, focusRing, invalidState, disabledState, emptyValueText, inlineIcon.default, triggerHeight[size], "flex items-center justify-between gap-1.5 whitespace-nowrap *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { "data-slot": "select-icon", asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-3.5 text-muted-foreground" }) })] }));
|
|
26
26
|
}
|
|
27
27
|
function SelectContent({ className, children, position = "popper", align = "center", sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, ...props }) {
|
|
28
|
-
return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { "data-slot": "select-content", "data-align-trigger": position === "item-aligned", className: cn(
|
|
28
|
+
return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { "data-slot": "select-content", "data-align-trigger": position === "item-aligned", className: cn(anchoredPanel, "relative z-50 max-h-(--radix-select-content-available-height) min-w-(--radix-select-trigger-width) origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none", position === "popper" &&
|
|
29
29
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className), position: position, align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { "data-slot": "select-viewport", "data-position": position, className: "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)", children: children }), _jsx(SelectScrollDownButton, {})] }) }));
|
|
30
30
|
}
|
|
31
31
|
function SelectLabel({ className, ...props }) {
|
|
32
32
|
return (_jsx(SelectPrimitive.Label, { "data-slot": "select-label", className: cn(menuLabel, className), ...props }));
|
|
33
33
|
}
|
|
34
34
|
function SelectItem({ className, children, ...props }) {
|
|
35
|
-
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn(optionRow, optionState.focus, optionState.checked, dataDisabledState, inlineIcon.default, "pr-8
|
|
35
|
+
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn(optionRow, optionState.focus, optionState.checked, dataDisabledState, inlineIcon.default, "pr-8 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className), ...props, children: [_jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { "data-slot": "select-item-indicator", children: _jsx(CheckIcon, { className: "pointer-events-none" }) }) }), _jsx(SelectPrimitive.ItemText, { children: children })] }));
|
|
36
36
|
}
|
|
37
37
|
function SelectSeparator({ className, ...props }) {
|
|
38
38
|
return (_jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn("pointer-events-none -mx-1.5 my-1.5 h-px bg-border", className), ...props }));
|
package/dist/separator.js
CHANGED
|
@@ -8,6 +8,6 @@ import { cn } from "./utils.js";
|
|
|
8
8
|
* `orientation`, so `className="w-12"` or `"w-0.5"` replaces them.
|
|
9
9
|
*/
|
|
10
10
|
function Separator({ className, orientation = "horizontal", decorative = true, ...props }) {
|
|
11
|
-
return (_jsx(SeparatorPrimitive.Root, { "data-slot": "separator", decorative: decorative, orientation: orientation, className: cn("shrink-0 bg-
|
|
11
|
+
return (_jsx(SeparatorPrimitive.Root, { "data-slot": "separator", decorative: decorative, orientation: orientation, className: cn("shrink-0 bg-input", orientation === "vertical" ? "w-px self-stretch" : "h-px w-full", className), ...props }));
|
|
12
12
|
}
|
|
13
13
|
export { Separator };
|
package/dist/skeleton.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "./utils.js";
|
|
3
3
|
function Skeleton({ className, ...props }) {
|
|
4
|
-
return (_jsx("div", { "data-slot": "skeleton", className: cn("animate-pulse bg-
|
|
4
|
+
return (_jsx("div", { "data-slot": "skeleton", className: cn("animate-pulse bg-input", className), ...props }));
|
|
5
5
|
}
|
|
6
6
|
export { Skeleton };
|
package/dist/slider.js
CHANGED
|
@@ -18,6 +18,6 @@ function Slider({ value, onValueChange, onValueCommit, min = 0, max = 100, step
|
|
|
18
18
|
const amount = next[0];
|
|
19
19
|
if (amount !== undefined)
|
|
20
20
|
onValueCommit?.(amount);
|
|
21
|
-
}, className: cn(dataDisabledState, "relative flex w-full touch-none items-center select-none", className), children: [_jsx(SliderPrimitive.Track, { "data-slot": "slider-track", className: "relative h-1.5 w-full grow overflow-hidden rounded-none bg-
|
|
21
|
+
}, className: cn(dataDisabledState, "relative flex w-full touch-none items-center select-none", className), children: [_jsx(SliderPrimitive.Track, { "data-slot": "slider-track", className: "relative h-1.5 w-full grow overflow-hidden rounded-none bg-input", children: _jsx(SliderPrimitive.Range, { "data-slot": "slider-range", className: "absolute h-full bg-primary" }) }), _jsx(SliderPrimitive.Thumb, { id: id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "data-slot": "slider-thumb", className: cn(focusRing, hitArea44, "relative block size-4 shrink-0 rounded-none border border-primary bg-background shadow-xs") })] }));
|
|
22
22
|
}
|
|
23
23
|
export { Slider };
|
package/dist/tabs.js
CHANGED
|
@@ -65,7 +65,7 @@ function TabsTrigger({ className, ...props }) {
|
|
|
65
65
|
return (_jsx(TabsPrimitive.Trigger, { "data-slot": "tabs-trigger", className: cn(tabsTriggerVariants(), className), ...props }));
|
|
66
66
|
}
|
|
67
67
|
function TabsContent({ className, ...props }) {
|
|
68
|
-
return (_jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1 text-sm", focusRing, className), ...props }));
|
|
68
|
+
return (_jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1 p-2 text-sm", focusRing, className), ...props }));
|
|
69
69
|
}
|
|
70
70
|
/**
|
|
71
71
|
* Tab-styled link for `TabsNav`. Pass `active` from the route: the active
|
package/dist/toast.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CircleAlertIcon, CircleCheckIcon, InfoIcon, LoaderCircleIcon, XIcon, }
|
|
|
5
5
|
import { useTheme } from "next-themes";
|
|
6
6
|
import { Toaster as Sonner, toast as sonnerToast, } from "sonner";
|
|
7
7
|
import { buttonVariants } from "./button.js";
|
|
8
|
-
import { statusTone } from "./internal/styles.js";
|
|
8
|
+
import { focusRing, statusTone } from "./internal/styles.js";
|
|
9
9
|
import { cn } from "./utils.js";
|
|
10
10
|
/**
|
|
11
11
|
* Copies only the kit's options, so plain JavaScript callers cannot hand the
|
|
@@ -45,27 +45,19 @@ const toast = Object.assign(show(sonnerToast), {
|
|
|
45
45
|
* `error`, and `loading` each show a status icon. Tone colors the icon, title,
|
|
46
46
|
* and border (`statusTone`, shared with Alert), not the body text.
|
|
47
47
|
*
|
|
48
|
-
* Close button: a
|
|
49
|
-
*
|
|
50
|
-
* shared focus ring, but Sonner's unlayered `[data-button]` default
|
|
51
|
-
* (`background: var(--normal-text)`) and the dark `[data-close-button]` rule
|
|
52
|
-
* (not gated on `data-styled`) would paint a foreground square. Important
|
|
53
|
-
* popover fill, border, and muted text beat those fills. The 24px hit area
|
|
54
|
-
* is the badge itself; the X is 12px. `overflow-visible` on the toast and
|
|
55
|
-
* toaster keeps stacked badges from being clipped.
|
|
48
|
+
* Close button: a 24px square inside the top-right corner. Important kit
|
|
49
|
+
* utilities beat Sonner's unlayered close-button positioning and colors.
|
|
56
50
|
*
|
|
57
|
-
* Stacking:
|
|
58
|
-
*
|
|
59
|
-
* the
|
|
60
|
-
* buttons would stay in the tab order unseen. Hovering or focusing the stack
|
|
61
|
-
* expands it (see `Toaster`), which shows them again.
|
|
51
|
+
* Stacking: notifications occupy normal flow in their mount area. Hidden
|
|
52
|
+
* and overflow notifications take no space or keyboard stops. Hovering or
|
|
53
|
+
* focusing the stack expands the visible notifications (see `Toaster`).
|
|
62
54
|
*
|
|
63
|
-
* Padding is asymmetric: `pl-4` matches Alert; `pr-
|
|
64
|
-
*
|
|
55
|
+
* Padding is asymmetric: `pl-4` matches Alert; `pr-10` clears the close
|
|
56
|
+
* button. Icon-to-text is `gap-x-2.5`
|
|
65
57
|
* so the status icon and copy read as one unit.
|
|
66
58
|
*/
|
|
67
59
|
const classNames = {
|
|
68
|
-
toast: "relative flex w-max max-w-[min(356px,calc(100vw-2rem))] flex-wrap items-center justify-end gap-x-2.5 gap-y-2 overflow-visible rounded-none border border-border bg-popover py-3 pl-4 pr-
|
|
60
|
+
toast: cn(focusRing, "!relative !transform-none flex w-max max-w-[min(356px,calc(100vw-2rem))] flex-wrap items-center justify-end gap-x-2.5 gap-y-2 overflow-visible rounded-none border border-border bg-popover py-3 pl-4 pr-10 text-sm text-popover-foreground shadow-md focus-visible:!shadow-[var(--tw-ring-offset-shadow),var(--tw-ring-shadow)] data-[visible=false]:hidden data-[expanded=false]:data-[front=false]:hidden"),
|
|
69
61
|
// Fills the row beside the icon, so action buttons wrap to their own row
|
|
70
62
|
// (aligned right by the toast's justify-end). Without an icon the basis
|
|
71
63
|
// falls back to the title's width, so a one-word toast stays compact.
|
|
@@ -76,7 +68,7 @@ const classNames = {
|
|
|
76
68
|
icon: "flex size-4 shrink-0 items-center justify-center [&_svg]:size-4",
|
|
77
69
|
actionButton: cn(buttonVariants({ size: "xs" }), "shrink-0"),
|
|
78
70
|
cancelButton: cn(buttonVariants({ variant: "outline", size: "xs" }), "shrink-0"),
|
|
79
|
-
closeButton: cn(buttonVariants({ variant: "ghost", size: "icon-xs" }), "!absolute
|
|
71
|
+
closeButton: cn(buttonVariants({ variant: "ghost", size: "icon-xs" }), "!absolute !top-2 !right-2 !left-auto !z-10 !size-6 !rounded-none !border !border-border !bg-popover !p-0 !text-muted-foreground !translate-x-0 !translate-y-0 hover:!border-border hover:!bg-popover hover:!text-foreground focus-visible:!text-foreground active:!translate-y-0 [&_svg]:!size-3"),
|
|
80
72
|
success: statusTone.success,
|
|
81
73
|
info: statusTone.neutral,
|
|
82
74
|
warning: statusTone.warning,
|
|
@@ -104,6 +96,6 @@ const Toaster = ({ position, closeButton = true, expand, visibleToasts, duration
|
|
|
104
96
|
setFocusWithin(false);
|
|
105
97
|
}
|
|
106
98
|
};
|
|
107
|
-
return (_jsx("div", { "data-slot": "toaster", className: "
|
|
99
|
+
return (_jsx("div", { "data-slot": "toaster", className: "min-w-0", onFocus: () => setFocusWithin(true), onBlur: onBlur, children: _jsx(Sonner, { theme: theme, className: "toaster group !relative !inset-auto !transform-none flex !w-full flex-col gap-3 overflow-visible p-2 data-[x-position=right]:items-end data-[x-position=center]:items-center data-[y-position=bottom]:flex-col-reverse", style: { fontFamily: "var(--font-sans)", height: "auto" }, position: position, closeButton: closeButton, expand: expand || focusWithin, visibleToasts: visibleToasts, duration: duration, icons: icons, toastOptions: { unstyled: true, classNames } }) }));
|
|
108
100
|
};
|
|
109
101
|
export { Toaster, toast };
|
package/dist/toggle-group.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ type ToggleGroupLayoutProps = {
|
|
|
12
12
|
/** Lay items out in a row or a column. Default `horizontal`. */
|
|
13
13
|
orientation?: "horizontal" | "vertical";
|
|
14
14
|
};
|
|
15
|
-
declare function ToggleGroup({ className, variant, size, spacing, orientation, children, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & ToggleGroupLayoutProps): React.JSX.Element;
|
|
15
|
+
declare function ToggleGroup({ className, variant, size, spacing, orientation, children, onKeyDown, onPointerDown, onFocus, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & ToggleGroupLayoutProps): React.JSX.Element;
|
|
16
16
|
declare function ToggleGroupItem({ className, children, variant, size, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>): React.JSX.Element;
|
|
17
17
|
export { ToggleGroup, ToggleGroupItem };
|
package/dist/toggle-group.js
CHANGED
|
@@ -5,15 +5,49 @@ import {} from "class-variance-authority";
|
|
|
5
5
|
import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
|
|
6
6
|
import { cn } from "./utils.js";
|
|
7
7
|
import { toggleVariants } from "./toggle.js";
|
|
8
|
+
/** The keys Radix's roving focus moves between items with. */
|
|
9
|
+
const arrowKeys = new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"]);
|
|
10
|
+
function isItem(target) {
|
|
11
|
+
return (target instanceof HTMLElement && target.dataset.slot === "toggle-group-item");
|
|
12
|
+
}
|
|
8
13
|
const ToggleGroupContext = React.createContext({
|
|
9
14
|
size: "default",
|
|
10
15
|
variant: "default",
|
|
11
16
|
spacing: 2,
|
|
12
17
|
orientation: "horizontal",
|
|
13
18
|
});
|
|
14
|
-
function ToggleGroup({ className, variant, size, spacing = 2, orientation = "horizontal", children, ...props }) {
|
|
19
|
+
function ToggleGroup({ className, variant, size, spacing = 2, orientation = "horizontal", children, onKeyDown, onPointerDown, onFocus, ...props }) {
|
|
20
|
+
// The item an arrow key was pressed on, until focus lands on the next one.
|
|
21
|
+
// A single group's items are radios, and focus that arrives by arrow key
|
|
22
|
+
// selects, as in any radio group; Tab and clicks do not.
|
|
23
|
+
const arrowFrom = React.useRef(null);
|
|
24
|
+
const selectsOnArrow = props.type === "single" && props.rovingFocus !== false;
|
|
15
25
|
const context = React.useMemo(() => ({ variant, size, spacing, orientation }), [variant, size, spacing, orientation]);
|
|
16
|
-
return (_jsx(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation,
|
|
26
|
+
return (_jsx(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation, onKeyDown: (event) => {
|
|
27
|
+
onKeyDown?.(event);
|
|
28
|
+
// Radix moves focus to the next item once the key has bubbled up.
|
|
29
|
+
if (selectsOnArrow &&
|
|
30
|
+
arrowKeys.has(event.key) &&
|
|
31
|
+
isItem(event.target) &&
|
|
32
|
+
!(event.metaKey || event.ctrlKey || event.altKey || event.shiftKey)) {
|
|
33
|
+
arrowFrom.current = event.target;
|
|
34
|
+
}
|
|
35
|
+
}, onPointerDown: (event) => {
|
|
36
|
+
onPointerDown?.(event);
|
|
37
|
+
arrowFrom.current = null;
|
|
38
|
+
}, onFocus: (event) => {
|
|
39
|
+
onFocus?.(event);
|
|
40
|
+
const from = arrowFrom.current;
|
|
41
|
+
arrowFrom.current = null;
|
|
42
|
+
const item = event.target;
|
|
43
|
+
// Clicking runs the selection Radix already owns, onValueChange included.
|
|
44
|
+
if (from &&
|
|
45
|
+
from !== item &&
|
|
46
|
+
isItem(item) &&
|
|
47
|
+
item.getAttribute("aria-checked") !== "true") {
|
|
48
|
+
item.click();
|
|
49
|
+
}
|
|
50
|
+
}, style: { "--gap": spacing }, className: cn("group/toggle-group flex w-fit max-w-full flex-row flex-wrap items-center gap-[--spacing(var(--gap))] data-[spacing=0]:data-[variant=outline]:rounded-none data-vertical:flex-col data-vertical:flex-nowrap data-vertical:items-stretch", className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: context, children: children }) }));
|
|
17
51
|
}
|
|
18
52
|
function ToggleGroupItem({ className, children, variant = "default", size = "default", ...props }) {
|
|
19
53
|
const context = React.useContext(ToggleGroupContext);
|
package/package.json
CHANGED
|
@@ -61,7 +61,7 @@ Import each component from its subpath, e.g.
|
|
|
61
61
|
| Checkbox, checkbox group, toggle group, combobox in a form | `FormCheckboxField`, `FormCheckboxGroupField`, `FormToggleGroupField`, `FormComboboxField` from `form/*` |
|
|
62
62
|
| Custom control the kit has no form field for | `FormControlField` from `form/control-field` |
|
|
63
63
|
| Form-level error (save failed) | `FormFeedbackField` from `form/feedback-field` |
|
|
64
|
-
| Focus the first invalid field when a submit fails | `focusFirstInvalid` from `form/focus-first-invalid`
|
|
64
|
+
| Focus the first invalid field when a submit fails | `focusFirstInvalid` from `form/focus-first-invalid`; fields without a `field` prop take `fieldName={field.name}` |
|
|
65
65
|
| Content panels on one page | `Tabs` from `tabs` |
|
|
66
66
|
| View switch that changes the URL | `TabsNav` and `TabsNavLink` from `tabs`; in Next, `next/tabs-nav-link` |
|
|
67
67
|
| App shell nav (Calendar, Tasks, Settings) | `NavLink` from `nav-link`; in Next, `next/nav-link` |
|
package/theme.css
CHANGED
|
@@ -227,6 +227,12 @@
|
|
|
227
227
|
* without `!`. Size and flush still set the variable on `[data-slot=card]`.
|
|
228
228
|
*/
|
|
229
229
|
@layer components {
|
|
230
|
+
@container pagination (max-width: 36rem) {
|
|
231
|
+
[data-slot="pagination-content"]:has([aria-current="page"])
|
|
232
|
+
> li:not(:first-child):not(:last-child):not(:has([aria-current="page"])) {
|
|
233
|
+
display: none;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
230
236
|
[data-slot="card"] {
|
|
231
237
|
padding-block: var(--card-p);
|
|
232
238
|
}
|