atlas-react-kit 1.2.3 → 1.2.5
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/DESIGN_RULES.md +2 -2
- package/dist/badge.js +1 -1
- package/dist/button.js +1 -1
- package/dist/combobox.js +3 -1
- package/dist/error-boundary.d.ts +3 -6
- package/dist/error-boundary.js +6 -9
- package/dist/form/feedback-field.js +1 -1
- package/dist/internal/styles.d.ts +1 -1
- package/dist/internal/styles.js +3 -3
- package/dist/internal/use-horizontal-overflow.d.ts +2 -0
- package/dist/internal/use-horizontal-overflow.js +14 -0
- package/dist/kanban.js +10 -6
- package/dist/markdown.js +1 -1
- package/dist/pagination.js +1 -1
- package/dist/search-picker.js +4 -4
- package/dist/select.js +1 -1
- package/dist/tabs.js +6 -3
- package/dist/toast.js +4 -5
- package/package.json +1 -1
- package/theme.css +296 -3
package/DESIGN_RULES.md
CHANGED
|
@@ -120,8 +120,8 @@ Primitives have square corners. Reserve `rounded-full` for dots, avatars,
|
|
|
120
120
|
and other circles. Card and dialog titles already use
|
|
121
121
|
uppercase, tracked `font-heading` styling. Toasts use the same square corners
|
|
122
122
|
and Alert's left padding, with a square close button inside the top-right
|
|
123
|
-
corner.
|
|
124
|
-
|
|
123
|
+
corner. The toaster floats over the page at its `position`, anchored to the
|
|
124
|
+
viewport; mount one near the app root. A plain `toast()` has no icon — status icons
|
|
125
125
|
belong to `success`, `info`, `warning`, `error`, and `loading`. Tone colors
|
|
126
126
|
the icon, title, and border, not the body.
|
|
127
127
|
|
package/dist/badge.js
CHANGED
|
@@ -21,7 +21,7 @@ const badgeVariants = cva([
|
|
|
21
21
|
ghost: "text-muted-foreground hover:text-foreground",
|
|
22
22
|
link: "text-foreground underline-offset-4 hover:underline",
|
|
23
23
|
/** Tinted chip; pick its color with `tone`. */
|
|
24
|
-
soft: "px-2 py-0.5",
|
|
24
|
+
soft: "px-2 py-0.5 text-xs font-medium tracking-normal normal-case",
|
|
25
25
|
},
|
|
26
26
|
/** Only `soft` reads this. */
|
|
27
27
|
tone: {
|
package/dist/button.js
CHANGED
|
@@ -21,7 +21,7 @@ const buttonVariants = cva([
|
|
|
21
21
|
disabledState,
|
|
22
22
|
"group/button inline-flex shrink-0 items-center justify-center rounded-none border border-transparent bg-clip-padding",
|
|
23
23
|
controlText,
|
|
24
|
-
"transition-all select-none active:not-aria-[haspopup]:translate-y-px
|
|
24
|
+
"transition-all select-none active:not-aria-[haspopup]:translate-y-px",
|
|
25
25
|
inlineIcon.default,
|
|
26
26
|
], {
|
|
27
27
|
variants: {
|
package/dist/combobox.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Button } from "./button.js";
|
|
|
6
6
|
import { Input } from "./input.js";
|
|
7
7
|
import { formControlTriggerClassName } from "./internal/form-control.js";
|
|
8
8
|
import { handleListboxKey } from "./internal/listbox-navigation.js";
|
|
9
|
+
import { clamp } from "./internal/math.js";
|
|
9
10
|
import { Listbox, ListboxEmptyStatus, listboxInputAria, PickerOption, } from "./internal/listbox-option.js";
|
|
10
11
|
import { createSearchIndex, filterSearchIndex, foldSearchText, normalizeSearchQuery, } from "./internal/search.js";
|
|
11
12
|
import { emptyValueText } from "./internal/styles.js";
|
|
@@ -53,7 +54,7 @@ function resolveCreateValue(query, existingValues, normalize) {
|
|
|
53
54
|
export function Combobox({ options, value, onValueChange, placeholder = "Select", searchPlaceholder = "Search", emptyText, disabled, id, className, listClassName, contentClassName, "aria-invalid": ariaInvalid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, creatable = false, normalizeCreateValue = defaultNormalizeCreateValue, createLabel = defaultCreateLabel, ...props }) {
|
|
54
55
|
const [open, setOpen] = React.useState(false);
|
|
55
56
|
const [query, setQuery] = React.useState("");
|
|
56
|
-
const [
|
|
57
|
+
const [highlightIndex, setHighlight] = React.useState(0);
|
|
57
58
|
const listId = React.useId();
|
|
58
59
|
const generatedId = React.useId();
|
|
59
60
|
const triggerId = id ?? generatedId;
|
|
@@ -84,6 +85,7 @@ export function Combobox({ options, value, onValueChange, placeholder = "Select"
|
|
|
84
85
|
: null;
|
|
85
86
|
}, [creatable, query, existingValues, normalizeCreateValue, createLabel]);
|
|
86
87
|
const list = createOption ? [...filtered, createOption] : filtered;
|
|
88
|
+
const highlight = clamp(highlightIndex, 0, Math.max(0, list.length - 1));
|
|
87
89
|
const onOpenChange = (next) => {
|
|
88
90
|
setOpen(next);
|
|
89
91
|
if (!next) {
|
package/dist/error-boundary.d.ts
CHANGED
|
@@ -10,9 +10,7 @@ type ErrorFallbackProps = {
|
|
|
10
10
|
className?: string;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* with the message and recovery buttons. Exported so the markup can be
|
|
15
|
-
* tested without throwing during render.
|
|
13
|
+
* Recovery UI used by `ErrorBoundary`: a large `EmptyPanel` with recovery buttons.
|
|
16
14
|
*/
|
|
17
15
|
export declare function ErrorFallback({ message, onRetry, onReload, className, }: ErrorFallbackProps): import("react").JSX.Element;
|
|
18
16
|
type ErrorBoundaryProps = {
|
|
@@ -24,15 +22,14 @@ type ErrorBoundaryProps = {
|
|
|
24
22
|
onError?: (error: Error, info: ErrorInfo) => void;
|
|
25
23
|
};
|
|
26
24
|
type ErrorBoundaryState = {
|
|
27
|
-
|
|
25
|
+
hasError: boolean;
|
|
28
26
|
};
|
|
29
27
|
/**
|
|
30
28
|
* Generic React error boundary with retry (reset) and full-page reload.
|
|
31
|
-
* Not tied to any data library.
|
|
32
29
|
*/
|
|
33
30
|
export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
34
31
|
state: ErrorBoundaryState;
|
|
35
|
-
static getDerivedStateFromError(
|
|
32
|
+
static getDerivedStateFromError(): ErrorBoundaryState;
|
|
36
33
|
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
37
34
|
retry: () => void;
|
|
38
35
|
reload: () => void;
|
package/dist/error-boundary.js
CHANGED
|
@@ -5,9 +5,7 @@ import { Button } from "./button.js";
|
|
|
5
5
|
import { EmptyPanel } from "./empty-panel.js";
|
|
6
6
|
import { cn } from "./utils.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* with the message and recovery buttons. Exported so the markup can be
|
|
10
|
-
* tested without throwing during render.
|
|
8
|
+
* Recovery UI used by `ErrorBoundary`: a large `EmptyPanel` with recovery buttons.
|
|
11
9
|
*/
|
|
12
10
|
export function ErrorFallback({ message = "Something went wrong.", onRetry, onReload, className, }) {
|
|
13
11
|
return (_jsxs(EmptyPanel, { role: "alert", "data-slot": "error-boundary", size: "lg",
|
|
@@ -16,24 +14,23 @@ export function ErrorFallback({ message = "Something went wrong.", onRetry, onRe
|
|
|
16
14
|
}
|
|
17
15
|
/**
|
|
18
16
|
* Generic React error boundary with retry (reset) and full-page reload.
|
|
19
|
-
* Not tied to any data library.
|
|
20
17
|
*/
|
|
21
18
|
export class ErrorBoundary extends Component {
|
|
22
|
-
state = {
|
|
23
|
-
static getDerivedStateFromError(
|
|
24
|
-
return {
|
|
19
|
+
state = { hasError: false };
|
|
20
|
+
static getDerivedStateFromError() {
|
|
21
|
+
return { hasError: true };
|
|
25
22
|
}
|
|
26
23
|
componentDidCatch(error, info) {
|
|
27
24
|
this.props.onError?.(error, info);
|
|
28
25
|
}
|
|
29
26
|
retry = () => {
|
|
30
|
-
this.setState({
|
|
27
|
+
this.setState({ hasError: false });
|
|
31
28
|
};
|
|
32
29
|
reload = () => {
|
|
33
30
|
window.location.reload();
|
|
34
31
|
};
|
|
35
32
|
render() {
|
|
36
|
-
if (!this.state.
|
|
33
|
+
if (!this.state.hasError)
|
|
37
34
|
return this.props.children;
|
|
38
35
|
return (_jsx(ErrorFallback, { message: this.props.message, onRetry: this.retry, onReload: this.reload }));
|
|
39
36
|
}
|
|
@@ -5,5 +5,5 @@ import { cn } from "../utils.js";
|
|
|
5
5
|
export function FormFeedbackField({ message, className, }) {
|
|
6
6
|
if (!message)
|
|
7
7
|
return null;
|
|
8
|
-
return (_jsx("p", { "data-slot": "form-feedback", className: cn(
|
|
8
|
+
return (_jsx("p", { "data-slot": "form-feedback", className: cn(errorText, className), role: "alert", children: message }));
|
|
9
9
|
}
|
|
@@ -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: grey fill plus a 2px ring bar, unlike checked. */
|
|
64
64
|
focus: string;
|
|
65
65
|
/** The same highlight for lists that track the active option in state. */
|
|
66
66
|
active: string;
|
package/dist/internal/styles.js
CHANGED
|
@@ -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: grey fill plus a 2px ring bar, unlike checked. */
|
|
64
|
+
focus: "focus:bg-accent focus:text-accent-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-accent text-accent-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. */
|
|
@@ -5,3 +5,5 @@ import * as React from "react";
|
|
|
5
5
|
* join the tab order only while it overflows (WCAG 2.1.1).
|
|
6
6
|
*/
|
|
7
7
|
export declare function useHorizontalOverflow(ref: React.RefObject<HTMLElement | null>): boolean;
|
|
8
|
+
/** Scrolls a keyboard-focused `element` and its ring into `scroller`'s view. */
|
|
9
|
+
export declare function revealInline(scroller: HTMLElement, element: Element): void;
|
|
@@ -21,3 +21,17 @@ export function useHorizontalOverflow(ref) {
|
|
|
21
21
|
}, [ref]);
|
|
22
22
|
return overflowing;
|
|
23
23
|
}
|
|
24
|
+
/** Scrolls a keyboard-focused `element` and its ring into `scroller`'s view. */
|
|
25
|
+
export function revealInline(scroller, element) {
|
|
26
|
+
const rect = element.getBoundingClientRect();
|
|
27
|
+
const focused = scroller.ownerDocument.activeElement;
|
|
28
|
+
if (!rect.width || !focused?.matches(":focus-visible"))
|
|
29
|
+
return;
|
|
30
|
+
const box = scroller.getBoundingClientRect();
|
|
31
|
+
const before = rect.left - 8 - box.left;
|
|
32
|
+
const after = rect.right + 8 - box.right;
|
|
33
|
+
if (before < 0)
|
|
34
|
+
scroller.scrollLeft += before;
|
|
35
|
+
else if (after > 0)
|
|
36
|
+
scroller.scrollLeft += Math.min(after, before);
|
|
37
|
+
}
|
package/dist/kanban.js
CHANGED
|
@@ -7,7 +7,8 @@ import { CheckCircle2, ChevronLeft, ChevronRight, GripVertical, Trash2, } from "
|
|
|
7
7
|
import { Button } from "./button.js";
|
|
8
8
|
import { KANBAN_COMPLETE_ID, KANBAN_DELETE_ID, buildKanbanGroups, kanbanOverflowEdges, kanbanScrollBy, resolveKanbanDrop, } from "./internal/kanban-layout.js";
|
|
9
9
|
import { configureCardSortablePlugins, configureKanbanPlugins, } from "./internal/kanban-plugins.js";
|
|
10
|
-
import {
|
|
10
|
+
import { focusRing } from "./internal/styles.js";
|
|
11
|
+
import { revealInline } from "./internal/use-horizontal-overflow.js";
|
|
11
12
|
import { Skeleton } from "./skeleton.js";
|
|
12
13
|
import { cn } from "./utils.js";
|
|
13
14
|
/** Column droppables lose to cards, so a drop lands between cards. */
|
|
@@ -77,7 +78,11 @@ function KanbanBoard({ columns, items, getColumnId, onMove, onComplete, onDelete
|
|
|
77
78
|
}, [cardClassName, itemById, renderCard]);
|
|
78
79
|
// `min-w-0` lets a flex or grid parent shrink the board so the scroller,
|
|
79
80
|
// 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
|
|
81
|
+
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, onFocus: (event) => {
|
|
82
|
+
const card = event.target.closest('[data-slot="kanban-card"]');
|
|
83
|
+
if (card)
|
|
84
|
+
revealInline(event.currentTarget, card);
|
|
85
|
+
}, className: cn("flex min-w-0 gap-4 overflow-x-auto pb-2",
|
|
81
86
|
// AutoScroller scrolls in small steps near the edge; mandatory
|
|
82
87
|
// snap would pull each one back, so it is off mid-drag.
|
|
83
88
|
"snap-x snap-mandatory scroll-px-2 has-data-dragging:snap-none", "data-loading:opacity-60", scrollerClassName), children: columns.map((column) => {
|
|
@@ -129,6 +134,7 @@ function KanbanColumnView({ column, count, emptyLabel, loading, className, child
|
|
|
129
134
|
}
|
|
130
135
|
const cardChrome = cn("flex border border-border bg-card text-card-foreground");
|
|
131
136
|
const handleChrome = cn("flex shrink-0 items-center self-stretch border-r border-border", "bg-muted/30 px-1.5 text-muted-foreground");
|
|
137
|
+
const stopFocus = cn(focusRing, "relative focus-visible:z-10");
|
|
132
138
|
function stopClick(event) {
|
|
133
139
|
event.stopPropagation();
|
|
134
140
|
}
|
|
@@ -145,9 +151,7 @@ function KanbanCardViewImpl({ item, index, column, onCardClick, className, rende
|
|
|
145
151
|
});
|
|
146
152
|
return (_jsxs("div", { ref: ref, "data-slot": "kanban-card", "data-dragging": isDragging || undefined, className: cn(cardChrome, "shadow-sm transition-[box-shadow,opacity,border-color]",
|
|
147
153
|
// The overlay moves; the source keeps its slot.
|
|
148
|
-
"data-dragging:pointer-events-none data-dragging:invisible",
|
|
149
|
-
// One ring on the card for the grip and the body alike.
|
|
150
|
-
focusRingWithin, onCardClick && "hover:border-foreground/15", className), children: [_jsx("button", { type: "button", ref: handleRef, "data-slot": "kanban-card-handle", "aria-label": "Drag to move", onClick: stopClick, className: cn(handleChrome, "cursor-grab outline-none hover:bg-muted/50 active:cursor-grabbing"), children: _jsx(GripVertical, { className: "size-4", "aria-hidden": true }) }), onCardClick ? (_jsx("button", { type: "button", "data-slot": "kanban-card-body", onClick: () => onCardClick(item), className: "min-w-0 flex-1 cursor-pointer p-3 text-left outline-none hover:bg-muted/20", children: children })) : (_jsx("div", { "data-slot": "kanban-card-body", className: "min-w-0 flex-1 p-3", children: children }))] }));
|
|
154
|
+
"data-dragging:pointer-events-none data-dragging:invisible", onCardClick && "hover:border-foreground/15", className), children: [_jsx("button", { type: "button", ref: handleRef, "data-slot": "kanban-card-handle", "aria-label": "Drag to move", onClick: stopClick, className: cn(handleChrome, stopFocus, "cursor-grab hover:bg-muted/50 active:cursor-grabbing"), children: _jsx(GripVertical, { className: "size-4", "aria-hidden": true }) }), onCardClick ? (_jsx("button", { type: "button", "data-slot": "kanban-card-body", onClick: () => onCardClick(item), className: cn("min-w-0 flex-1 cursor-pointer p-3 text-left hover:bg-muted/20", stopFocus), children: children })) : (_jsx("div", { "data-slot": "kanban-card-body", className: "min-w-0 flex-1 p-3", children: children }))] }));
|
|
151
155
|
}
|
|
152
156
|
/**
|
|
153
157
|
* Memoized so a board update re-renders only the cards whose item, index or
|
|
@@ -185,7 +189,7 @@ function ActionZone({ id, label, regionLabel, icon: Icon, tone, visible, }) {
|
|
|
185
189
|
}
|
|
186
190
|
function ScrollButton({ side, onClick, }) {
|
|
187
191
|
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
|
|
192
|
+
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 top-1/2 z-20 -translate-y-1/2", side === "start" ? "left-1" : "right-1"), children: _jsx(Icon, {}) }));
|
|
189
193
|
}
|
|
190
194
|
function OverflowFade({ side, visible, }) {
|
|
191
195
|
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/markdown.js
CHANGED
|
@@ -35,7 +35,7 @@ const markdownComponents = {
|
|
|
35
35
|
h3: ({ children }) => (_jsx("h3", { className: headingClass("text-base"), children: children })),
|
|
36
36
|
p: ({ children }) => _jsx("p", { className: "text-sm leading-relaxed", children: children }),
|
|
37
37
|
ul: ({ children }) => (_jsx("ul", { className: "list-disc space-y-1 pl-5 text-sm", children: children })),
|
|
38
|
-
ol: ({ children }) => (_jsx("ol", { className: "list-decimal space-y-1 pl-5 text-sm", children: children })),
|
|
38
|
+
ol: ({ children, start }) => (_jsx("ol", { start: start, className: "list-decimal space-y-1 pl-5 text-sm", children: children })),
|
|
39
39
|
li: ({ children }) => _jsx("li", { className: "leading-relaxed", children: children }),
|
|
40
40
|
blockquote: ({ children }) => (_jsx("blockquote", { className: "border-l-2 border-input pl-3 text-sm text-muted-foreground", children: children })),
|
|
41
41
|
a: ({ href, children }) => href ? (_jsx("a", { href: href, className: "text-selected-foreground underline underline-offset-2", ...(href.startsWith("http")
|
package/dist/pagination.js
CHANGED
|
@@ -11,7 +11,7 @@ import { cn } from "./utils.js";
|
|
|
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("@container/pagination flex w-full min-w-0
|
|
14
|
+
return (_jsx("nav", { "aria-label": "Pagination", "data-slot": "pagination", className: cn("@container/pagination flex w-full min-w-0", className), ...props }));
|
|
15
15
|
}
|
|
16
16
|
function PaginationContent({ className, ...props }) {
|
|
17
17
|
return (_jsx("ul", { "data-slot": "pagination-content", className: cn("flex flex-row flex-wrap items-center gap-1", className), ...props }));
|
package/dist/search-picker.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import { Input } from "./input.js";
|
|
5
5
|
import { Label } from "./label.js";
|
|
6
6
|
import { handleListboxKey } from "./internal/listbox-navigation.js";
|
|
7
|
+
import { clamp } from "./internal/math.js";
|
|
7
8
|
import { Listbox, ListboxEmptyStatus, listboxInputAria, PickerOption, } from "./internal/listbox-option.js";
|
|
8
9
|
import { createSearchIndex, filterSearchIndex, foldSearchText, normalizeSearchQuery, } from "./internal/search.js";
|
|
9
10
|
import { cn, onInputChange } from "./utils.js";
|
|
@@ -42,10 +43,9 @@ function SearchPicker({ items, getValue, getLabel, filter = defaultSearchFilter,
|
|
|
42
43
|
return index >= 0 ? index : 0;
|
|
43
44
|
}, [filtered, getValue, value]);
|
|
44
45
|
const rows = React.useMemo(() => filtered.map((item) => ({ item, value: getValue(item) })), [filtered, getValue]);
|
|
45
|
-
const [
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
// with the stale highlight and again with the reset.
|
|
46
|
+
const [highlightIndex, setHighlight] = React.useState(selectedIndex);
|
|
47
|
+
const highlight = clamp(highlightIndex, 0, Math.max(0, filtered.length - 1));
|
|
48
|
+
// Reset during render so a query or selection change commits only once.
|
|
49
49
|
const [highlightFor, setHighlightFor] = React.useState({
|
|
50
50
|
query,
|
|
51
51
|
selectedIndex,
|
package/dist/select.js
CHANGED
|
@@ -32,7 +32,7 @@ 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 *:[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 })] }));
|
|
35
|
+
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn(optionRow, optionState.focus, optionState.checked, dataDisabledState, inlineIcon.default, "pr-8 not-data-[variant=destructive]:focus:**:text-accent-foreground *:[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/tabs.js
CHANGED
|
@@ -7,7 +7,7 @@ import { activeLinkAttributes, activeLinkSelector, } from "./internal/active-lin
|
|
|
7
7
|
import { focusRing } from "./internal/styles.js";
|
|
8
8
|
import { tabsListVariants, tabsScrollerVariants, tabsTriggerVariants, } from "./internal/tabs-styles.js";
|
|
9
9
|
import { useDragScroll } from "./internal/use-drag-scroll.js";
|
|
10
|
-
import { useHorizontalOverflow } from "./internal/use-horizontal-overflow.js";
|
|
10
|
+
import { revealInline, useHorizontalOverflow, } from "./internal/use-horizontal-overflow.js";
|
|
11
11
|
import { cn } from "./utils.js";
|
|
12
12
|
/**
|
|
13
13
|
* The root's orientation, so the list can pick plain size classes (`h-7`)
|
|
@@ -48,7 +48,10 @@ function TabsScroller({ variant = "default", orientation = "horizontal", classNa
|
|
|
48
48
|
behavior: "auto",
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
|
-
return (_jsx("div", { ref: ref,
|
|
51
|
+
return (_jsx("div", { ref: ref, onFocus: (event) => {
|
|
52
|
+
if (event.target !== event.currentTarget)
|
|
53
|
+
revealInline(event.currentTarget, event.target);
|
|
54
|
+
}, "data-slot": "tabs-scroller", "data-variant": variant, tabIndex: overflowing ? 0 : undefined, className: cn(focusRing, tabsScrollerVariants({ variant, orientation }), className), children: children }));
|
|
52
55
|
}
|
|
53
56
|
/**
|
|
54
57
|
* The tab row inside its scroller. `className` styles the list (its `h-7`
|
|
@@ -65,7 +68,7 @@ function TabsTrigger({ className, ...props }) {
|
|
|
65
68
|
return (_jsx(TabsPrimitive.Trigger, { "data-slot": "tabs-trigger", className: cn(tabsTriggerVariants(), className), ...props }));
|
|
66
69
|
}
|
|
67
70
|
function TabsContent({ className, ...props }) {
|
|
68
|
-
return (_jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1
|
|
71
|
+
return (_jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn("flex-1 text-sm", focusRing, className), ...props }));
|
|
69
72
|
}
|
|
70
73
|
/**
|
|
71
74
|
* Tab-styled link for `TabsNav`. Pass `active` from the route: the active
|
package/dist/toast.js
CHANGED
|
@@ -48,16 +48,15 @@ const toast = Object.assign(show(sonnerToast), {
|
|
|
48
48
|
* Close button: a 24px square inside the top-right corner. Important kit
|
|
49
49
|
* utilities beat Sonner's unlayered close-button positioning and colors.
|
|
50
50
|
*
|
|
51
|
-
* Stacking:
|
|
52
|
-
*
|
|
53
|
-
* focusing the stack expands the visible notifications (see `Toaster`).
|
|
51
|
+
* Stacking: the toaster floats at `position`; collapsed back toasts are
|
|
52
|
+
* `invisible`. Hovering or focusing expands it (see `Toaster`).
|
|
54
53
|
*
|
|
55
54
|
* Padding is asymmetric: `pl-4` matches Alert; `pr-10` clears the close
|
|
56
55
|
* button. Icon-to-text is `gap-x-2.5`
|
|
57
56
|
* so the status icon and copy read as one unit.
|
|
58
57
|
*/
|
|
59
58
|
const classNames = {
|
|
60
|
-
toast: cn(focusRing, "
|
|
59
|
+
toast: cn(focusRing, "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-10 text-sm text-popover-foreground shadow-md focus-visible:!shadow-[var(--tw-ring-offset-shadow),var(--tw-ring-shadow)] data-[visible=false]:invisible data-[expanded=false]:data-[front=false]:*:invisible"),
|
|
61
60
|
// Fills the row beside the icon, so action buttons wrap to their own row
|
|
62
61
|
// (aligned right by the toast's justify-end). Without an icon the basis
|
|
63
62
|
// falls back to the title's width, so a one-word toast stays compact.
|
|
@@ -96,6 +95,6 @@ const Toaster = ({ position, closeButton = true, expand, visibleToasts, duration
|
|
|
96
95
|
setFocusWithin(false);
|
|
97
96
|
}
|
|
98
97
|
};
|
|
99
|
-
return (_jsx("div", { "data-slot": "toaster", className: "
|
|
98
|
+
return (_jsx("div", { "data-slot": "toaster", className: "contents", onFocus: () => setFocusWithin(true), onBlur: onBlur, children: _jsx(Sonner, { theme: theme, className: "toaster group overflow-visible", style: { fontFamily: "var(--font-sans)" }, position: position, closeButton: closeButton, expand: expand || focusWithin, visibleToasts: visibleToasts, duration: duration, icons: icons, toastOptions: { unstyled: true, classNames } }) }));
|
|
100
99
|
};
|
|
101
100
|
export { Toaster, toast };
|
package/package.json
CHANGED
package/theme.css
CHANGED
|
@@ -227,9 +227,302 @@
|
|
|
227
227
|
* without `!`. Size and flush still set the variable on `[data-slot=card]`.
|
|
228
228
|
*/
|
|
229
229
|
@layer components {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
230
|
+
/*
|
|
231
|
+
* Pagination that no longer fits its container drops pages in two steps,
|
|
232
|
+
* sized for 36px page links, 38px icon-only Previous / Next and a 4px gap
|
|
233
|
+
* (40px per item; `n` items fit in n x 40px). The first and last <li> are
|
|
234
|
+
* Previous and Next.
|
|
235
|
+
* 1. A list with an ellipsis keeps Previous, the first and last pages, the
|
|
236
|
+
* current page, the ellipses and Next (plus a lone page between the
|
|
237
|
+
* first or last page and the current one), so every gap is still marked.
|
|
238
|
+
* 2. Narrower still, or for a list without an ellipsis, only Previous, the
|
|
239
|
+
* current page and Next stay. The list also wraps rather than spill.
|
|
240
|
+
*/
|
|
241
|
+
@container pagination (width < 10rem) {
|
|
242
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
243
|
+
[data-slot="pagination-ellipsis"]
|
|
244
|
+
):has(> li:nth-child(4)):not(:has(> li:nth-child(5)))
|
|
245
|
+
> li:not(
|
|
246
|
+
:first-child,
|
|
247
|
+
:last-child,
|
|
248
|
+
:nth-child(2),
|
|
249
|
+
:nth-last-child(2),
|
|
250
|
+
:has([aria-current="page"]),
|
|
251
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
252
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
253
|
+
+ li [aria-current="page"]
|
|
254
|
+
),
|
|
255
|
+
:has([aria-current="page"])
|
|
256
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
257
|
+
),
|
|
258
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
259
|
+
:has([data-slot="pagination-ellipsis"])
|
|
260
|
+
):has(> li:nth-child(4)):not(:has(> li:nth-child(5)))
|
|
261
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
262
|
+
display: none;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
@container pagination (width < 7.5rem) {
|
|
266
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
267
|
+
[data-slot="pagination-ellipsis"]
|
|
268
|
+
):has(> li:nth-child(4)):not(:has(> li:nth-child(5)))
|
|
269
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
270
|
+
display: none;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
@container pagination (width < 12.5rem) {
|
|
274
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
275
|
+
[data-slot="pagination-ellipsis"]
|
|
276
|
+
):has(> li:nth-child(5)):not(:has(> li:nth-child(6)))
|
|
277
|
+
> li:not(
|
|
278
|
+
:first-child,
|
|
279
|
+
:last-child,
|
|
280
|
+
:nth-child(2),
|
|
281
|
+
:nth-last-child(2),
|
|
282
|
+
:has([aria-current="page"]),
|
|
283
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
284
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
285
|
+
+ li [aria-current="page"]
|
|
286
|
+
),
|
|
287
|
+
:has([aria-current="page"])
|
|
288
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
289
|
+
),
|
|
290
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
291
|
+
:has([data-slot="pagination-ellipsis"])
|
|
292
|
+
):has(> li:nth-child(5)):not(:has(> li:nth-child(6)))
|
|
293
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
294
|
+
display: none;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
@container pagination (width < 10rem) {
|
|
298
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
299
|
+
[data-slot="pagination-ellipsis"]
|
|
300
|
+
):has(> li:nth-child(5)):not(:has(> li:nth-child(6)))
|
|
301
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
302
|
+
display: none;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
@container pagination (width < 15rem) {
|
|
306
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
307
|
+
[data-slot="pagination-ellipsis"]
|
|
308
|
+
):has(> li:nth-child(6)):not(:has(> li:nth-child(7)))
|
|
309
|
+
> li:not(
|
|
310
|
+
:first-child,
|
|
311
|
+
:last-child,
|
|
312
|
+
:nth-child(2),
|
|
313
|
+
:nth-last-child(2),
|
|
314
|
+
:has([aria-current="page"]),
|
|
315
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
316
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
317
|
+
+ li [aria-current="page"]
|
|
318
|
+
),
|
|
319
|
+
:has([aria-current="page"])
|
|
320
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
321
|
+
),
|
|
322
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
323
|
+
:has([data-slot="pagination-ellipsis"])
|
|
324
|
+
):has(> li:nth-child(6)):not(:has(> li:nth-child(7)))
|
|
325
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
326
|
+
display: none;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
@container pagination (width < 12.5rem) {
|
|
330
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
331
|
+
[data-slot="pagination-ellipsis"]
|
|
332
|
+
):has(> li:nth-child(6)):not(:has(> li:nth-child(7)))
|
|
333
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
334
|
+
display: none;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
@container pagination (width < 17.5rem) {
|
|
338
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
339
|
+
[data-slot="pagination-ellipsis"]
|
|
340
|
+
):has(> li:nth-child(7)):not(:has(> li:nth-child(8)))
|
|
341
|
+
> li:not(
|
|
342
|
+
:first-child,
|
|
343
|
+
:last-child,
|
|
344
|
+
:nth-child(2),
|
|
345
|
+
:nth-last-child(2),
|
|
346
|
+
:has([aria-current="page"]),
|
|
347
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
348
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
349
|
+
+ li [aria-current="page"]
|
|
350
|
+
),
|
|
351
|
+
:has([aria-current="page"])
|
|
352
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
353
|
+
),
|
|
354
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
355
|
+
:has([data-slot="pagination-ellipsis"])
|
|
356
|
+
):has(> li:nth-child(7)):not(:has(> li:nth-child(8)))
|
|
357
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
358
|
+
display: none;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
@container pagination (width < 15rem) {
|
|
362
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
363
|
+
[data-slot="pagination-ellipsis"]
|
|
364
|
+
):has(> li:nth-child(7)):not(:has(> li:nth-child(8)))
|
|
365
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
366
|
+
display: none;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
@container pagination (width < 20rem) {
|
|
370
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
371
|
+
[data-slot="pagination-ellipsis"]
|
|
372
|
+
):has(> li:nth-child(8)):not(:has(> li:nth-child(9)))
|
|
373
|
+
> li:not(
|
|
374
|
+
:first-child,
|
|
375
|
+
:last-child,
|
|
376
|
+
:nth-child(2),
|
|
377
|
+
:nth-last-child(2),
|
|
378
|
+
:has([aria-current="page"]),
|
|
379
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
380
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
381
|
+
+ li [aria-current="page"]
|
|
382
|
+
),
|
|
383
|
+
:has([aria-current="page"])
|
|
384
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
385
|
+
),
|
|
386
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
387
|
+
:has([data-slot="pagination-ellipsis"])
|
|
388
|
+
):has(> li:nth-child(8)):not(:has(> li:nth-child(9)))
|
|
389
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
390
|
+
display: none;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
@container pagination (width < 17.5rem) {
|
|
394
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
395
|
+
[data-slot="pagination-ellipsis"]
|
|
396
|
+
):has(> li:nth-child(8)):not(:has(> li:nth-child(9)))
|
|
397
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
398
|
+
display: none;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
@container pagination (width < 22.5rem) {
|
|
402
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
403
|
+
[data-slot="pagination-ellipsis"]
|
|
404
|
+
):has(> li:nth-child(9)):not(:has(> li:nth-child(10)))
|
|
405
|
+
> li:not(
|
|
406
|
+
:first-child,
|
|
407
|
+
:last-child,
|
|
408
|
+
:nth-child(2),
|
|
409
|
+
:nth-last-child(2),
|
|
410
|
+
:has([aria-current="page"]),
|
|
411
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
412
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
413
|
+
+ li [aria-current="page"]
|
|
414
|
+
),
|
|
415
|
+
:has([aria-current="page"])
|
|
416
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
417
|
+
),
|
|
418
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
419
|
+
:has([data-slot="pagination-ellipsis"])
|
|
420
|
+
):has(> li:nth-child(9)):not(:has(> li:nth-child(10)))
|
|
421
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
422
|
+
display: none;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
@container pagination (width < 17.5rem) {
|
|
426
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
427
|
+
[data-slot="pagination-ellipsis"]
|
|
428
|
+
):has(> li:nth-child(9)):not(:has(> li:nth-child(10)))
|
|
429
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
430
|
+
display: none;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
@container pagination (width < 25rem) {
|
|
434
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
435
|
+
[data-slot="pagination-ellipsis"]
|
|
436
|
+
):has(> li:nth-child(10)):not(:has(> li:nth-child(11)))
|
|
437
|
+
> li:not(
|
|
438
|
+
:first-child,
|
|
439
|
+
:last-child,
|
|
440
|
+
:nth-child(2),
|
|
441
|
+
:nth-last-child(2),
|
|
442
|
+
:has([aria-current="page"]),
|
|
443
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
444
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
445
|
+
+ li [aria-current="page"]
|
|
446
|
+
),
|
|
447
|
+
:has([aria-current="page"])
|
|
448
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
449
|
+
),
|
|
450
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
451
|
+
:has([data-slot="pagination-ellipsis"])
|
|
452
|
+
):has(> li:nth-child(10)):not(:has(> li:nth-child(11)))
|
|
453
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
454
|
+
display: none;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
@container pagination (width < 17.5rem) {
|
|
458
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
459
|
+
[data-slot="pagination-ellipsis"]
|
|
460
|
+
):has(> li:nth-child(10)):not(:has(> li:nth-child(11)))
|
|
461
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
462
|
+
display: none;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
@container pagination (width < 27.5rem) {
|
|
466
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
467
|
+
[data-slot="pagination-ellipsis"]
|
|
468
|
+
):has(> li:nth-child(11)):not(:has(> li:nth-child(12)))
|
|
469
|
+
> li:not(
|
|
470
|
+
:first-child,
|
|
471
|
+
:last-child,
|
|
472
|
+
:nth-child(2),
|
|
473
|
+
:nth-last-child(2),
|
|
474
|
+
:has([aria-current="page"]),
|
|
475
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
476
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
477
|
+
+ li [aria-current="page"]
|
|
478
|
+
),
|
|
479
|
+
:has([aria-current="page"])
|
|
480
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
481
|
+
),
|
|
482
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
483
|
+
:has([data-slot="pagination-ellipsis"])
|
|
484
|
+
):has(> li:nth-child(11)):not(:has(> li:nth-child(12)))
|
|
485
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
486
|
+
display: none;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
@container pagination (width < 17.5rem) {
|
|
490
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
491
|
+
[data-slot="pagination-ellipsis"]
|
|
492
|
+
):has(> li:nth-child(11)):not(:has(> li:nth-child(12)))
|
|
493
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
494
|
+
display: none;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
@container pagination (width < 30rem) {
|
|
498
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
499
|
+
[data-slot="pagination-ellipsis"]
|
|
500
|
+
):has(> li:nth-child(12))
|
|
501
|
+
> li:not(
|
|
502
|
+
:first-child,
|
|
503
|
+
:last-child,
|
|
504
|
+
:nth-child(2),
|
|
505
|
+
:nth-last-child(2),
|
|
506
|
+
:has([aria-current="page"]),
|
|
507
|
+
:has([data-slot="pagination-ellipsis"]),
|
|
508
|
+
:nth-child(3):not(:has([data-slot="pagination-ellipsis"]) + li):has(
|
|
509
|
+
+ li [aria-current="page"]
|
|
510
|
+
),
|
|
511
|
+
:has([aria-current="page"])
|
|
512
|
+
+ :nth-last-child(3):not(:has(+ li [data-slot="pagination-ellipsis"]))
|
|
513
|
+
),
|
|
514
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):not(
|
|
515
|
+
:has([data-slot="pagination-ellipsis"])
|
|
516
|
+
):has(> li:nth-child(12))
|
|
517
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
518
|
+
display: none;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
@container pagination (width < 17.5rem) {
|
|
522
|
+
[data-slot="pagination-content"]:has([aria-current="page"]):has(
|
|
523
|
+
[data-slot="pagination-ellipsis"]
|
|
524
|
+
):has(> li:nth-child(12))
|
|
525
|
+
> li:not(:first-child, :last-child, :has([aria-current="page"])) {
|
|
233
526
|
display: none;
|
|
234
527
|
}
|
|
235
528
|
}
|