atlas-react-kit 1.2.2 → 1.2.4
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 +7 -7
- package/dist/chart.js +1 -1
- package/dist/field.js +2 -2
- package/dist/form/feedback-field.js +2 -1
- package/dist/form/field-error.js +2 -1
- package/dist/internal/calendar-size.d.ts +1 -1
- package/dist/internal/calendar-size.js +1 -1
- package/dist/internal/styles.d.ts +5 -3
- package/dist/internal/styles.js +5 -3
- package/dist/internal/tabs-styles.js +1 -1
- package/dist/internal/use-horizontal-overflow.d.ts +2 -0
- package/dist/internal/use-horizontal-overflow.js +14 -0
- package/dist/kanban.js +7 -2
- package/dist/meter.js +1 -1
- package/dist/pagination.d.ts +1 -1
- package/dist/pagination.js +3 -3
- package/dist/progress.js +1 -1
- package/dist/separator.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/slider.js +1 -1
- package/dist/tabs.js +5 -2
- package/dist/toast.js +10 -19
- package/package.json +1 -1
- package/theme.css +299 -0
package/DESIGN_RULES.md
CHANGED
|
@@ -117,11 +117,11 @@ still read normal words.
|
|
|
117
117
|
## Shape and composition
|
|
118
118
|
|
|
119
119
|
Primitives have square corners. Reserve `rounded-full` for dots, avatars,
|
|
120
|
-
other circles
|
|
121
|
-
uppercase, tracked `font-heading` styling. Toasts
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
and other circles. Card and dialog titles already use
|
|
121
|
+
uppercase, tracked `font-heading` styling. Toasts use the same square corners
|
|
122
|
+
and Alert's left padding, with a square close button inside the top-right
|
|
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
|
|
|
@@ -146,8 +146,8 @@ toasts keep their width.
|
|
|
146
146
|
|
|
147
147
|
Parents do not force sizes on their children. A vertical `Field` stretches
|
|
148
148
|
its controls through the flex column, so a control's own width class (such
|
|
149
|
-
as `w-32`) wins; `Field
|
|
150
|
-
own. `FieldGroup`
|
|
149
|
+
as `w-32`) wins; `Field` and `Alert` set no width of their
|
|
150
|
+
own. `FieldGroup` and `Pagination` keep `w-full` because an inline-size container has no
|
|
151
151
|
intrinsic width. Size classes that `className` should be able to replace are
|
|
152
152
|
plain classes picked from props (`Avatar` `size`, `Separator` orientation,
|
|
153
153
|
`SelectTrigger` `size`, tab orientation), never `data-*` variants, which sort
|
package/dist/chart.js
CHANGED
|
@@ -144,7 +144,7 @@ export function ChartYAxisGrid({ frame, yMax, tickCount = 4, format = compactNum
|
|
|
144
144
|
const ticks = niceTicks(yMax, tickCount);
|
|
145
145
|
const top = ticks[ticks.length - 1] ?? 1;
|
|
146
146
|
const y = (value) => frame.bottom - (value / top) * frame.plotHeight;
|
|
147
|
-
return (_jsx("g", { "data-slot": "chart-y-axis", children: ticks.map((tick) => (_jsxs("g", { children: [_jsx("line", { x1: frame.left, y1: y(tick), x2: frame.right, y2: y(tick), strokeWidth: 1, className: "stroke-
|
|
147
|
+
return (_jsx("g", { "data-slot": "chart-y-axis", children: ticks.map((tick) => (_jsxs("g", { children: [_jsx("line", { x1: frame.left, y1: y(tick), x2: frame.right, y2: y(tick), strokeWidth: 1, className: "stroke-input" }), _jsx("text", { x: frame.left - 6, y: y(tick) + 3, textAnchor: "end", className: "fill-muted-foreground text-xs tabular-nums", children: format(tick) })] }, tick))) }));
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
150
150
|
* Readout for the hovered or focused point, placed in percent of the chart
|
package/dist/field.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
4
|
import { cva } from "class-variance-authority";
|
|
5
|
-
import { labelText } from "./internal/styles.js";
|
|
5
|
+
import { errorText, labelText } from "./internal/styles.js";
|
|
6
6
|
import { cn } from "./utils.js";
|
|
7
7
|
import { Label } from "./label.js";
|
|
8
8
|
import { Separator } from "./separator.js";
|
|
@@ -77,6 +77,6 @@ function FieldError({ className, children, errors, ...props }) {
|
|
|
77
77
|
if (!content) {
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
|
-
return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn(
|
|
80
|
+
return (_jsx("div", { role: "alert", "data-slot": "field-error", className: cn(errorText, className), ...props, children: content }));
|
|
81
81
|
}
|
|
82
82
|
export { Field, FieldLabel, FieldDescription, FieldError, FieldGroup, FieldLegend, FieldSeparator, FieldSet, FieldContent, FieldTitle, };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { errorText } from "../internal/styles.js";
|
|
2
3
|
import { cn } from "../utils.js";
|
|
3
4
|
/** Form-level submit or mutation error (not tied to a single field). */
|
|
4
5
|
export function FormFeedbackField({ message, className, }) {
|
|
5
6
|
if (!message)
|
|
6
7
|
return null;
|
|
7
|
-
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 }));
|
|
8
9
|
}
|
package/dist/form/field-error.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { errorText } from "../internal/styles.js";
|
|
2
3
|
import { cn } from "../utils.js";
|
|
3
4
|
/** First TanStack Form error message for a field, if any. */
|
|
4
5
|
export function getFieldErrorMessage(message) {
|
|
@@ -10,5 +11,5 @@ export function FieldError({ id, message, text, className, }) {
|
|
|
10
11
|
const resolved = text ?? getFieldErrorMessage(message);
|
|
11
12
|
if (!resolved)
|
|
12
13
|
return null;
|
|
13
|
-
return (_jsx("p", { id: id, "data-slot": "form-field-error", className: cn(
|
|
14
|
+
return (_jsx("p", { id: id, "data-slot": "form-field-error", className: cn(errorText, className), role: "alert", children: resolved }));
|
|
14
15
|
}
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Calendar cell size and padding, shared with LazyCalendar's placeholder
|
|
3
3
|
* (here, not in calendar.tsx, so the placeholder skips Day Picker).
|
|
4
4
|
*/
|
|
5
|
-
export declare const calendarSize = "[--cell-size:--spacing(8)] [--calendar-padding:--spacing(
|
|
5
|
+
export declare const calendarSize = "[--cell-size:--spacing(8)] [--calendar-padding:--spacing(2)]";
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Calendar cell size and padding, shared with LazyCalendar's placeholder
|
|
3
3
|
* (here, not in calendar.tsx, so the placeholder skips Day Picker).
|
|
4
4
|
*/
|
|
5
|
-
export const calendarSize = "[--cell-size:--spacing(8)] [--calendar-padding:--spacing(
|
|
5
|
+
export const calendarSize = "[--cell-size:--spacing(8)] [--calendar-padding:--spacing(2)]";
|
|
@@ -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: grey fill plus a 2px ring bar
|
|
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;
|
|
@@ -102,6 +102,8 @@ export declare const controlText = "text-xs font-semibold tracking-widest whites
|
|
|
102
102
|
* DialogDescription, AlertDescription).
|
|
103
103
|
*/
|
|
104
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";
|
|
105
107
|
/** Field-label text (Label, FieldLegend, FieldTitle, PopoverTitle). */
|
|
106
108
|
export declare const labelText = "text-xs font-semibold tracking-wide uppercase";
|
|
107
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,7 +60,7 @@ 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: grey fill plus a 2px ring bar
|
|
63
|
+
/** Highlight as focus moves: grey fill plus a 2px ring bar, unlike checked. */
|
|
64
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
66
|
active: "bg-accent text-accent-foreground shadow-[inset_2px_0_0_var(--color-ring)]",
|
|
@@ -102,6 +102,8 @@ export const controlText = "text-xs font-semibold tracking-widest whitespace-now
|
|
|
102
102
|
* DialogDescription, AlertDescription).
|
|
103
103
|
*/
|
|
104
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";
|
|
105
107
|
/** Field-label text (Label, FieldLegend, FieldTitle, PopoverTitle). */
|
|
106
108
|
export const labelText = "text-xs font-semibold tracking-wide uppercase";
|
|
107
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",
|
|
@@ -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
|
@@ -8,6 +8,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
10
|
import { focusRingWithin } 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", 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,
|
|
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) => {
|
|
@@ -125,7 +130,7 @@ function KanbanColumnView({ column, count, emptyLabel, loading, className, child
|
|
|
125
130
|
collisionPriority: COLUMN_DROP_PRIORITY,
|
|
126
131
|
});
|
|
127
132
|
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("
|
|
133
|
+
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
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");
|
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", 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/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/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
|
@@ -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`
|
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,18 @@ 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 front toast, closer together than the 24px target spacing, and their
|
|
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: the toaster floats at `position`; collapsed back toasts are
|
|
52
|
+
* `invisible`. Hovering or focusing expands it (see `Toaster`).
|
|
62
53
|
*
|
|
63
|
-
* Padding is asymmetric: `pl-4` matches Alert; `pr-
|
|
64
|
-
*
|
|
54
|
+
* Padding is asymmetric: `pl-4` matches Alert; `pr-10` clears the close
|
|
55
|
+
* button. Icon-to-text is `gap-x-2.5`
|
|
65
56
|
* so the status icon and copy read as one unit.
|
|
66
57
|
*/
|
|
67
58
|
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-
|
|
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"),
|
|
69
60
|
// Fills the row beside the icon, so action buttons wrap to their own row
|
|
70
61
|
// (aligned right by the toast's justify-end). Without an icon the basis
|
|
71
62
|
// falls back to the title's width, so a one-word toast stays compact.
|
|
@@ -76,7 +67,7 @@ const classNames = {
|
|
|
76
67
|
icon: "flex size-4 shrink-0 items-center justify-center [&_svg]:size-4",
|
|
77
68
|
actionButton: cn(buttonVariants({ size: "xs" }), "shrink-0"),
|
|
78
69
|
cancelButton: cn(buttonVariants({ variant: "outline", size: "xs" }), "shrink-0"),
|
|
79
|
-
closeButton: cn(buttonVariants({ variant: "ghost", size: "icon-xs" }), "!absolute
|
|
70
|
+
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
71
|
success: statusTone.success,
|
|
81
72
|
info: statusTone.neutral,
|
|
82
73
|
warning: statusTone.warning,
|
|
@@ -104,6 +95,6 @@ const Toaster = ({ position, closeButton = true, expand, visibleToasts, duration
|
|
|
104
95
|
setFocusWithin(false);
|
|
105
96
|
}
|
|
106
97
|
};
|
|
107
|
-
return (_jsx("div", { "data-slot": "toaster", className: "contents", onFocus: () => setFocusWithin(true), onBlur: onBlur, children: _jsx(Sonner, { theme: theme, className: "toaster group overflow-visible", position: position, closeButton: closeButton, expand: expand || focusWithin, visibleToasts: visibleToasts, duration: duration, icons: icons, toastOptions: { unstyled: true, classNames } }) }));
|
|
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 } }) }));
|
|
108
99
|
};
|
|
109
100
|
export { Toaster, toast };
|
package/package.json
CHANGED
package/theme.css
CHANGED
|
@@ -227,6 +227,305 @@
|
|
|
227
227
|
* without `!`. Size and flush still set the variable on `[data-slot=card]`.
|
|
228
228
|
*/
|
|
229
229
|
@layer components {
|
|
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"])) {
|
|
526
|
+
display: none;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
230
529
|
[data-slot="card"] {
|
|
231
530
|
padding-block: var(--card-p);
|
|
232
531
|
}
|