atlas-react-kit 0.11.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +176 -83
- package/DESIGN_RULES.md +14 -1
- package/README.md +3 -3
- package/dist/alert.d.ts +1 -1
- package/dist/badge.d.ts +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/date-picker.d.ts +3 -9
- package/dist/date-picker.js +8 -38
- package/dist/date-time-picker.d.ts +1 -1
- package/dist/date-time-picker.js +3 -3
- package/dist/error-boundary.d.ts +1 -1
- package/dist/field.d.ts +1 -1
- package/dist/form/control-field.d.ts +31 -0
- package/dist/form/control-field.js +22 -0
- package/dist/form/date-picker-field.d.ts +9 -3
- package/dist/form/date-picker-field.js +3 -3
- package/dist/form/date-time-picker-field.d.ts +10 -4
- package/dist/form/date-time-picker-field.js +3 -3
- package/dist/form/field-error.d.ts +18 -0
- package/dist/form/field-shell.d.ts +29 -10
- package/dist/form/field-shell.js +37 -11
- package/dist/form/markdown-field.d.ts +4 -2
- package/dist/form/markdown-field.js +3 -3
- package/dist/form/select-field.d.ts +5 -3
- package/dist/form/select-field.js +3 -3
- package/dist/form/text-field.d.ts +3 -4
- package/dist/form/text-field.js +6 -6
- package/dist/internal/date-like.d.ts +31 -0
- package/dist/internal/date-like.js +33 -0
- package/dist/label.d.ts +16 -1
- package/dist/label.js +7 -3
- package/dist/nav-link.d.ts +22 -0
- package/dist/nav-link.js +31 -0
- package/dist/next/nav-link.d.ts +11 -0
- package/dist/next/nav-link.js +14 -0
- package/dist/picker-shell.d.ts +48 -6
- package/dist/picker-shell.js +28 -0
- package/dist/toast.d.ts +4 -2
- package/dist/toast.js +18 -3
- package/dist/toggle.d.ts +1 -1
- package/package.json +17 -5
- package/skills/atlas-react-kit/SKILL.md +2 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { parseISO } from "date-fns";
|
|
2
|
+
/**
|
|
3
|
+
* Coerce a date-like value to a local `Date`.
|
|
4
|
+
* Plain calendar dates (`yyyy-MM-dd`) parse as local midnight so they do not
|
|
5
|
+
* shift when the runtime timezone is behind UTC.
|
|
6
|
+
*/
|
|
7
|
+
export function toDate(value) {
|
|
8
|
+
if (value == null || value === "")
|
|
9
|
+
return undefined;
|
|
10
|
+
if (value instanceof Date) {
|
|
11
|
+
return Number.isNaN(value.getTime()) ? undefined : value;
|
|
12
|
+
}
|
|
13
|
+
if (typeof value === "number") {
|
|
14
|
+
const date = new Date(value);
|
|
15
|
+
return Number.isNaN(date.getTime()) ? undefined : date;
|
|
16
|
+
}
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
const ymd = /^(\d{4})-(\d{2})-(\d{2})$/.exec(trimmed);
|
|
19
|
+
if (ymd) {
|
|
20
|
+
const year = Number(ymd[1]);
|
|
21
|
+
const month = Number(ymd[2]);
|
|
22
|
+
const day = Number(ymd[3]);
|
|
23
|
+
const date = new Date(year, month - 1, day);
|
|
24
|
+
if (date.getFullYear() !== year ||
|
|
25
|
+
date.getMonth() !== month - 1 ||
|
|
26
|
+
date.getDate() !== day) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return date;
|
|
30
|
+
}
|
|
31
|
+
const parsed = parseISO(trimmed);
|
|
32
|
+
return Number.isNaN(parsed.getTime()) ? undefined : parsed;
|
|
33
|
+
}
|
package/dist/label.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Label as LabelPrimitive } from "radix-ui";
|
|
3
|
-
|
|
3
|
+
type LabelProps = React.ComponentProps<typeof LabelPrimitive.Root> & {
|
|
4
|
+
/**
|
|
5
|
+
* Shows a visible required marker after the text. The marker is hidden
|
|
6
|
+
* from assistive tech, so set `required` (or `aria-required`) on the
|
|
7
|
+
* control too; screen readers announce it from there.
|
|
8
|
+
*/
|
|
9
|
+
required?: boolean;
|
|
10
|
+
/** Classes for the required marker (`data-slot="label-required"`). */
|
|
11
|
+
requiredClassName?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Form label. `required` adds a visible marker; style it with
|
|
15
|
+
* `requiredClassName` or the `label-required` slot.
|
|
16
|
+
*/
|
|
17
|
+
declare function Label({ className, required, requiredClassName, children, ...props }: LabelProps): React.JSX.Element;
|
|
4
18
|
export { Label };
|
|
19
|
+
export type { LabelProps };
|
package/dist/label.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Label as LabelPrimitive } from "radix-ui";
|
|
5
5
|
import { cn } from "./utils.js";
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Form label. `required` adds a visible marker; style it with
|
|
8
|
+
* `requiredClassName` or the `label-required` slot.
|
|
9
|
+
*/
|
|
10
|
+
function Label({ className, required, requiredClassName, children, ...props }) {
|
|
11
|
+
return (_jsxs(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex items-center gap-2 text-xs font-semibold tracking-wide uppercase select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-data-[slot=checkbox]:text-sm peer-data-[slot=checkbox]:font-normal peer-data-[slot=checkbox]:tracking-normal peer-data-[slot=checkbox]:normal-case peer-data-[slot=radio-group-item]:text-sm peer-data-[slot=radio-group-item]:font-normal peer-data-[slot=radio-group-item]:tracking-normal peer-data-[slot=radio-group-item]:normal-case peer-data-[slot=switch]:text-sm peer-data-[slot=switch]:font-normal peer-data-[slot=switch]:tracking-normal peer-data-[slot=switch]:normal-case", className), ...props, children: [children, required ? (_jsx("span", { "data-slot": "label-required", "aria-hidden": "true", className: cn("-ml-1.5 text-destructive", requiredClassName), children: "*" })) : null] }));
|
|
8
12
|
}
|
|
9
13
|
export { Label };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Pill chrome for app-shell navigation. Inactive is muted text with an
|
|
4
|
+
* accent hover; active uses the shared selected wash, text, and border
|
|
5
|
+
* (`selectedState.active`) so the current page meets non-text contrast.
|
|
6
|
+
* Apps pass `active` — the kit has no router.
|
|
7
|
+
*/
|
|
8
|
+
declare const navLinkVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Pill link for app-shell destinations (Calendar, Tasks, Settings). Pass
|
|
11
|
+
* `active` from the route; the kit does not read the URL. `asChild` wraps a
|
|
12
|
+
* router `Link` with these styles, the same Slot pattern as `BreadcrumbLink`.
|
|
13
|
+
*
|
|
14
|
+
* Not a tab: in-page view switches that belong in the URL use `TabsNav`
|
|
15
|
+
* and `tabsTriggerVariants()`. Next apps can import the optional adapter
|
|
16
|
+
* from `atlas-react-kit/next/nav-link` instead of composing `asChild`.
|
|
17
|
+
*/
|
|
18
|
+
declare function NavLink({ asChild, active, className, ...props }: React.ComponentProps<"a"> & {
|
|
19
|
+
asChild?: boolean;
|
|
20
|
+
active: boolean;
|
|
21
|
+
}): React.JSX.Element;
|
|
22
|
+
export { NavLink, navLinkVariants };
|
package/dist/nav-link.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { Slot } from "radix-ui";
|
|
5
|
+
import { focusRing, selectedState } from "./internal/styles.js";
|
|
6
|
+
import { cn } from "./utils.js";
|
|
7
|
+
/**
|
|
8
|
+
* Pill chrome for app-shell navigation. Inactive is muted text with an
|
|
9
|
+
* accent hover; active uses the shared selected wash, text, and border
|
|
10
|
+
* (`selectedState.active`) so the current page meets non-text contrast.
|
|
11
|
+
* Apps pass `active` — the kit has no router.
|
|
12
|
+
*/
|
|
13
|
+
const navLinkVariants = cva([
|
|
14
|
+
focusRing,
|
|
15
|
+
selectedState.active,
|
|
16
|
+
"inline-flex items-center gap-1.5 rounded-none border border-transparent px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent data-[state=active]:font-medium",
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* Pill link for app-shell destinations (Calendar, Tasks, Settings). Pass
|
|
20
|
+
* `active` from the route; the kit does not read the URL. `asChild` wraps a
|
|
21
|
+
* router `Link` with these styles, the same Slot pattern as `BreadcrumbLink`.
|
|
22
|
+
*
|
|
23
|
+
* Not a tab: in-page view switches that belong in the URL use `TabsNav`
|
|
24
|
+
* and `tabsTriggerVariants()`. Next apps can import the optional adapter
|
|
25
|
+
* from `atlas-react-kit/next/nav-link` instead of composing `asChild`.
|
|
26
|
+
*/
|
|
27
|
+
function NavLink({ asChild, active, className, ...props }) {
|
|
28
|
+
const Comp = asChild ? Slot.Root : "a";
|
|
29
|
+
return (_jsx(Comp, { "data-slot": "nav-link", "data-state": active ? "active" : "inactive", "aria-current": active ? "page" : undefined, className: cn(navLinkVariants(), className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
export { NavLink, navLinkVariants };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import Link from "next/link.js";
|
|
3
|
+
/**
|
|
4
|
+
* Next.js adapter for the shell `NavLink` pill. Same contract as
|
|
5
|
+
* `TabsNavLink`: Next `Link` props plus a required `active` boolean. The
|
|
6
|
+
* kit still does not read the router; the app passes `active`.
|
|
7
|
+
*/
|
|
8
|
+
declare function NavLink({ active, className, ...props }: React.ComponentProps<typeof Link> & {
|
|
9
|
+
active: boolean;
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
export { NavLink };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import Link from "next/link.js";
|
|
4
|
+
import { navLinkVariants } from "../nav-link.js";
|
|
5
|
+
import { cn } from "../utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* Next.js adapter for the shell `NavLink` pill. Same contract as
|
|
8
|
+
* `TabsNavLink`: Next `Link` props plus a required `active` boolean. The
|
|
9
|
+
* kit still does not read the router; the app passes `active`.
|
|
10
|
+
*/
|
|
11
|
+
function NavLink({ active, className, ...props }) {
|
|
12
|
+
return (_jsx(Link, { "data-slot": "nav-link", "data-state": active ? "active" : "inactive", "aria-current": active ? "page" : undefined, className: cn(navLinkVariants(), className), ...props }));
|
|
13
|
+
}
|
|
14
|
+
export { NavLink };
|
package/dist/picker-shell.d.ts
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Locale } from "date-fns";
|
|
3
|
+
import { type DateLike, type DateMatcher } from "./internal/date-like.js";
|
|
3
4
|
import { PopoverContent } from "./popover.js";
|
|
4
5
|
/**
|
|
5
6
|
* Not a public entry. The trigger, popover, and Clear footer that
|
|
6
7
|
* `DatePickerButton` and `DateTimePickerButton` share.
|
|
7
8
|
*/
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Options for the picker's calendar. The picker owns the selection, focus,
|
|
11
|
+
* and month props; these are the kit's own types, so a Day Picker upgrade
|
|
12
|
+
* does not change them.
|
|
12
13
|
*/
|
|
13
|
-
export type PickerCalendarProps =
|
|
14
|
+
export type PickerCalendarProps = {
|
|
15
|
+
/** Days that cannot be picked. */
|
|
16
|
+
disabled?: DateMatcher | DateMatcher[];
|
|
17
|
+
/** Days left out of the grid. */
|
|
18
|
+
hidden?: DateMatcher | DateMatcher[];
|
|
19
|
+
/** Earliest month the calendar pages to. */
|
|
20
|
+
startMonth?: Date;
|
|
21
|
+
/** Latest month the calendar pages to. */
|
|
22
|
+
endMonth?: Date;
|
|
23
|
+
/** First day of the week, `0` (Sunday) to `6`. Defaults to the locale's. */
|
|
24
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
25
|
+
/** A date-fns locale for month and weekday names. */
|
|
26
|
+
locale?: Locale;
|
|
27
|
+
/** Show the leading and trailing days of the neighbouring months. Default `true`. */
|
|
28
|
+
showOutsideDays?: boolean;
|
|
29
|
+
/** Always show six weeks, so the popover height does not change. */
|
|
30
|
+
fixedWeeks?: boolean;
|
|
31
|
+
/** Show ISO or locale week numbers in a first column. */
|
|
32
|
+
showWeekNumber?: boolean;
|
|
33
|
+
/** Month and year as text (`label`, default) or as dropdowns. */
|
|
34
|
+
captionLayout?: "label" | "dropdown" | "dropdown-months" | "dropdown-years";
|
|
35
|
+
/** The day marked as today. Defaults to the current date. */
|
|
36
|
+
today?: Date;
|
|
37
|
+
/** Classes for the calendar root. */
|
|
38
|
+
className?: string;
|
|
39
|
+
};
|
|
14
40
|
/** Props both pickers take for their trigger and popover. */
|
|
15
41
|
export type PickerTriggerProps = {
|
|
16
42
|
id?: string;
|
|
@@ -34,10 +60,26 @@ export type PickerTriggerProps = {
|
|
|
34
60
|
side?: React.ComponentProps<typeof PopoverContent>["side"];
|
|
35
61
|
/** Month shown when the popover opens; falls back to the selected date. */
|
|
36
62
|
defaultMonth?: Date;
|
|
63
|
+
/**
|
|
64
|
+
* Earliest day that can be picked. Earlier days are disabled and the
|
|
65
|
+
* calendar does not page before its month.
|
|
66
|
+
*/
|
|
67
|
+
minDate?: DateLike;
|
|
68
|
+
/**
|
|
69
|
+
* Latest day that can be picked. Later days are disabled and the calendar
|
|
70
|
+
* does not page past its month.
|
|
71
|
+
*/
|
|
72
|
+
maxDate?: DateLike;
|
|
37
73
|
/** Day Picker options passed through to the calendar. */
|
|
38
74
|
calendarProps?: PickerCalendarProps;
|
|
39
75
|
};
|
|
40
|
-
|
|
76
|
+
/**
|
|
77
|
+
* `calendarProps` with `minDate` / `maxDate` applied: days outside them join
|
|
78
|
+
* any `disabled` matchers, and they bound paging unless `startMonth` /
|
|
79
|
+
* `endMonth` are set.
|
|
80
|
+
*/
|
|
81
|
+
export declare function limitCalendarProps(calendarProps: PickerCalendarProps | undefined, minDate: DateLike, maxDate: DateLike): PickerCalendarProps | undefined;
|
|
82
|
+
type PickerShellProps = Omit<PickerTriggerProps, "placeholder" | "defaultMonth" | "calendarProps" | "minDate" | "maxDate"> & {
|
|
41
83
|
/** Muted trigger text while nothing is picked. */
|
|
42
84
|
empty: boolean;
|
|
43
85
|
/** Trigger text: the formatted value or the placeholder. */
|
package/dist/picker-shell.js
CHANGED
|
@@ -3,10 +3,38 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { CalendarIcon } from "lucide-react";
|
|
5
5
|
import { Button } from "./button.js";
|
|
6
|
+
import { toDate, } from "./internal/date-like.js";
|
|
6
7
|
import { PICKER_COLLISION_PADDING, pickerContentClassName, pickerTriggerClassName, pickerValueId, } from "./internal/form-control.js";
|
|
7
8
|
import { preloadCalendar } from "./lazy-calendar.js";
|
|
8
9
|
import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
9
10
|
import { cn } from "./utils.js";
|
|
11
|
+
/**
|
|
12
|
+
* `calendarProps` with `minDate` / `maxDate` applied: days outside them join
|
|
13
|
+
* any `disabled` matchers, and they bound paging unless `startMonth` /
|
|
14
|
+
* `endMonth` are set.
|
|
15
|
+
*/
|
|
16
|
+
export function limitCalendarProps(calendarProps, minDate, maxDate) {
|
|
17
|
+
const min = toDate(minDate);
|
|
18
|
+
const max = toDate(maxDate);
|
|
19
|
+
if (!min && !max)
|
|
20
|
+
return calendarProps;
|
|
21
|
+
const disabled = calendarProps?.disabled;
|
|
22
|
+
const matchers = [
|
|
23
|
+
...(disabled === undefined
|
|
24
|
+
? []
|
|
25
|
+
: Array.isArray(disabled)
|
|
26
|
+
? disabled
|
|
27
|
+
: [disabled]),
|
|
28
|
+
...(min ? [{ before: min }] : []),
|
|
29
|
+
...(max ? [{ after: max }] : []),
|
|
30
|
+
];
|
|
31
|
+
return {
|
|
32
|
+
...calendarProps,
|
|
33
|
+
disabled: matchers,
|
|
34
|
+
startMonth: calendarProps?.startMonth ?? min,
|
|
35
|
+
endMonth: calendarProps?.endMonth ?? max,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
10
38
|
/** Form-control trigger plus the viewport-clamped calendar popover. */
|
|
11
39
|
export function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, side, empty, label, dialogLabel, open, onOpenChange, onInteractOutside, children, }) {
|
|
12
40
|
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", id: id ? pickerValueId(id) : undefined, children: label })] }) }), _jsx(PopoverContent, { align: "start", side: side, collisionPadding: PICKER_COLLISION_PADDING, "aria-label": dialogLabel,
|
package/dist/toast.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
2
|
/** Identifies a toast, to replace it in place or dismiss it. */
|
|
3
3
|
type ToastId = string | number;
|
|
4
4
|
/** A button in a toast. Clicking it runs `onClick`, then closes the toast. */
|
|
@@ -50,7 +50,9 @@ interface ToasterProps {
|
|
|
50
50
|
declare const toast: Toast;
|
|
51
51
|
/**
|
|
52
52
|
* Mount one near the app root, and show toasts with `toast()` from this
|
|
53
|
-
* module. Only the props declared here reach the library.
|
|
53
|
+
* module. Only the props declared here reach the library. The stack
|
|
54
|
+
* expands while keyboard focus is inside it, as it does on hover, so every
|
|
55
|
+
* toast's buttons are visible and reachable.
|
|
54
56
|
*/
|
|
55
57
|
declare const Toaster: ({ position, closeButton, expand, visibleToasts, duration, }: ToasterProps) => import("react").JSX.Element;
|
|
56
58
|
export { Toaster, toast };
|
package/dist/toast.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
3
4
|
import { CircleAlertIcon, CircleCheckIcon, InfoIcon, LoaderCircleIcon, XIcon, } from "lucide-react";
|
|
4
5
|
import { useTheme } from "next-themes";
|
|
5
6
|
import { Toaster as Sonner, toast as sonnerToast, } from "sonner";
|
|
@@ -52,12 +53,18 @@ const toast = Object.assign(show(sonnerToast), {
|
|
|
52
53
|
* is the badge itself; the X is 12px. `overflow-visible` on the toast and
|
|
53
54
|
* toaster keeps stacked badges from being clipped.
|
|
54
55
|
*
|
|
56
|
+
* Stacking: while the stack is collapsed, every part of the toasts behind
|
|
57
|
+
* the front one is `invisible`. Their badges would otherwise peek out above
|
|
58
|
+
* the front toast, closer together than the 24px target spacing, and their
|
|
59
|
+
* buttons would stay in the tab order unseen. Hovering or focusing the stack
|
|
60
|
+
* expands it (see `Toaster`), which shows them again.
|
|
61
|
+
*
|
|
55
62
|
* Padding is asymmetric: `pl-4` matches Alert; `pr-6` clears the badge
|
|
56
63
|
* (about 16px of it sits inside the border). Icon-to-text is `gap-x-2.5`
|
|
57
64
|
* so the status icon and copy read as one unit.
|
|
58
65
|
*/
|
|
59
66
|
const classNames = {
|
|
60
|
-
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-6 text-sm text-popover-foreground shadow-md",
|
|
67
|
+
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-6 text-sm text-popover-foreground shadow-md data-[expanded=false]:data-[front=false]:*:invisible",
|
|
61
68
|
// Fills the row beside the icon, so action buttons wrap to their own row
|
|
62
69
|
// (aligned right by the toast's justify-end). Without an icon the basis
|
|
63
70
|
// falls back to the title's width, so a one-word toast stays compact.
|
|
@@ -84,10 +91,18 @@ const icons = {
|
|
|
84
91
|
};
|
|
85
92
|
/**
|
|
86
93
|
* Mount one near the app root, and show toasts with `toast()` from this
|
|
87
|
-
* module. Only the props declared here reach the library.
|
|
94
|
+
* module. Only the props declared here reach the library. The stack
|
|
95
|
+
* expands while keyboard focus is inside it, as it does on hover, so every
|
|
96
|
+
* toast's buttons are visible and reachable.
|
|
88
97
|
*/
|
|
89
98
|
const Toaster = ({ position, closeButton = true, expand, visibleToasts, duration, }) => {
|
|
90
99
|
const { theme = "system" } = useTheme();
|
|
91
|
-
|
|
100
|
+
const [focusWithin, setFocusWithin] = useState(false);
|
|
101
|
+
const onBlur = (event) => {
|
|
102
|
+
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
103
|
+
setFocusWithin(false);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
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 } }) }));
|
|
92
107
|
};
|
|
93
108
|
export { Toaster, toast };
|
package/dist/toggle.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { Toggle as TogglePrimitive } from "radix-ui";
|
|
|
9
9
|
declare const selectedToggleChrome: string;
|
|
10
10
|
declare const toggleVariants: (props?: ({
|
|
11
11
|
variant?: "default" | "outline" | null | undefined;
|
|
12
|
-
size?: "default" | "
|
|
12
|
+
size?: "default" | "lg" | "sm" | null | undefined;
|
|
13
13
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
14
14
|
declare function Toggle({ className, variant, size, ...props }: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>): React.JSX.Element;
|
|
15
15
|
export { Toggle, toggleVariants, selectedToggleChrome };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atlas-react-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Shared React components and Tailwind theme for Atlas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -112,6 +112,10 @@
|
|
|
112
112
|
"types": "./dist/meter.d.ts",
|
|
113
113
|
"default": "./dist/meter.js"
|
|
114
114
|
},
|
|
115
|
+
"./nav-link": {
|
|
116
|
+
"types": "./dist/nav-link.d.ts",
|
|
117
|
+
"default": "./dist/nav-link.js"
|
|
118
|
+
},
|
|
115
119
|
"./pagination": {
|
|
116
120
|
"types": "./dist/pagination.d.ts",
|
|
117
121
|
"default": "./dist/pagination.js"
|
|
@@ -200,6 +204,10 @@
|
|
|
200
204
|
"types": "./dist/tooltip.d.ts",
|
|
201
205
|
"default": "./dist/tooltip.js"
|
|
202
206
|
},
|
|
207
|
+
"./form/control-field": {
|
|
208
|
+
"types": "./dist/form/control-field.d.ts",
|
|
209
|
+
"default": "./dist/form/control-field.js"
|
|
210
|
+
},
|
|
203
211
|
"./form/date-picker-field": {
|
|
204
212
|
"types": "./dist/form/date-picker-field.d.ts",
|
|
205
213
|
"default": "./dist/form/date-picker-field.js"
|
|
@@ -228,6 +236,10 @@
|
|
|
228
236
|
"types": "./dist/form/text-field.d.ts",
|
|
229
237
|
"default": "./dist/form/text-field.js"
|
|
230
238
|
},
|
|
239
|
+
"./next/nav-link": {
|
|
240
|
+
"types": "./dist/next/nav-link.d.ts",
|
|
241
|
+
"default": "./dist/next/nav-link.js"
|
|
242
|
+
},
|
|
231
243
|
"./next/tabs-nav-link": {
|
|
232
244
|
"types": "./dist/next/tabs-nav-link.d.ts",
|
|
233
245
|
"default": "./dist/next/tabs-nav-link.js"
|
|
@@ -307,10 +319,10 @@
|
|
|
307
319
|
"@types/node": "^25.5.0",
|
|
308
320
|
"@types/react": "^19.2.14",
|
|
309
321
|
"@types/react-dom": "^19.2.3",
|
|
310
|
-
"@vitest/coverage-v8": "
|
|
322
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
311
323
|
"date-fns": "^4.4.0",
|
|
312
324
|
"jsdom": "^29.1.1",
|
|
313
|
-
"next": "16.2
|
|
325
|
+
"next": "16.4.2",
|
|
314
326
|
"next-themes": "^0.4.6",
|
|
315
327
|
"prettier": "^3.8.1",
|
|
316
328
|
"react": "^19.2.4",
|
|
@@ -320,8 +332,8 @@
|
|
|
320
332
|
"remark-gfm": "^4.0.1",
|
|
321
333
|
"sonner": "^2.0.7",
|
|
322
334
|
"tailwindcss": "^4.2.1",
|
|
323
|
-
"typescript": "^
|
|
335
|
+
"typescript": "^7.0.2",
|
|
324
336
|
"unified": "^11.0.5",
|
|
325
|
-
"vitest": "^
|
|
337
|
+
"vitest": "^5.0.5"
|
|
326
338
|
}
|
|
327
339
|
}
|
|
@@ -61,9 +61,11 @@ Import each component from its subpath, e.g.
|
|
|
61
61
|
| One date, or a from/to range | `DatePickerButton` from `date-picker` (`mode="range"` for ranges) |
|
|
62
62
|
| Date and time (not `datetime-local`) | `DateTimePickerButton` from `date-time-picker` |
|
|
63
63
|
| Labelled field with error text | `FormTextField`, `FormSelectField`, `FormDatePickerField`, `FormDateTimePickerField`, `FormMarkdownField` from `form/*` |
|
|
64
|
+
| Labelled custom control (combobox) in a form | `FormControlField` from `form/control-field` |
|
|
64
65
|
| Form-level error (save failed) | `FormFeedbackField` from `form/feedback-field` |
|
|
65
66
|
| Content panels on one page | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` from `tabs` |
|
|
66
67
|
| View switch that changes the URL | `TabsNav` with links: `TabsNavLink` from `next/tabs-nav-link` in Next, else `tabsTriggerVariants()` |
|
|
68
|
+
| App shell nav (Calendar, Tasks, Settings) | `NavLink` from `nav-link` (`asChild` for a router link); Next: `next/nav-link` |
|
|
67
69
|
| Status chip (paid, pending, failed) | `Badge variant="soft"` with `tone="success"`, `"warning"`, `"destructive"`, or `"neutral"` |
|
|
68
70
|
| Data table | `Table` family from `table`; `SortableTableHead`; `TableBodySkeleton` while loading |
|
|
69
71
|
| Nothing to show yet | `EmptyPanel` from `empty-panel` |
|