atlas-react-kit 0.12.0 → 1.0.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 +201 -100
- package/DESIGN_RULES.md +44 -1
- package/README.md +10 -9
- package/dist/accordion.d.ts +1 -0
- package/dist/alert.d.ts +1 -1
- package/dist/avatar.d.ts +1 -0
- package/dist/badge.d.ts +4 -5
- package/dist/breadcrumb.d.ts +2 -3
- package/dist/button.d.ts +4 -5
- package/dist/calendar.d.ts +2 -0
- package/dist/card.d.ts +3 -0
- package/dist/chart.d.ts +152 -0
- package/dist/chart.js +177 -0
- package/dist/color-legend.d.ts +8 -0
- package/dist/combobox.d.ts +13 -4
- package/dist/combobox.js +1 -8
- package/dist/date-picker.d.ts +16 -6
- package/dist/date-picker.js +13 -20
- package/dist/date-time-picker.d.ts +5 -2
- package/dist/date-time-picker.js +6 -5
- package/dist/dialog.d.ts +1 -0
- package/dist/dialog.js +4 -2
- package/dist/dropdown-menu.d.ts +9 -8
- package/dist/empty-panel.d.ts +8 -2
- package/dist/empty-panel.js +2 -2
- package/dist/error-boundary.d.ts +7 -2
- package/dist/field.d.ts +4 -1
- package/dist/field.js +1 -1
- package/dist/form/checkbox-field.d.ts +45 -0
- package/dist/form/checkbox-field.js +39 -0
- package/dist/form/combobox-field.d.ts +13 -0
- package/dist/form/combobox-field.js +14 -0
- package/dist/form/control-field.d.ts +30 -0
- package/dist/form/control-field.js +22 -0
- package/dist/form/date-picker-field.d.ts +7 -21
- package/dist/form/date-picker-field.js +4 -4
- package/dist/form/date-time-picker-field.d.ts +7 -22
- package/dist/form/date-time-picker-field.js +3 -3
- package/dist/form/feedback-field.d.ts +2 -0
- package/dist/form/field-error.d.ts +49 -0
- package/dist/form/field-shell.d.ts +47 -8
- package/dist/form/field-shell.js +24 -7
- package/dist/form/markdown-field.d.ts +4 -16
- package/dist/form/markdown-field.js +2 -2
- package/dist/form/select-field.d.ts +7 -7
- package/dist/form/select-field.js +2 -2
- package/dist/form/text-field.d.ts +29 -12
- package/dist/form/text-field.js +10 -6
- package/dist/form/toggle-group-field.d.ts +30 -0
- package/dist/form/toggle-group-field.js +19 -0
- package/dist/info-tip.d.ts +10 -1
- package/dist/internal/as-child.d.ts +8 -0
- package/dist/internal/as-child.js +1 -0
- package/dist/internal/date-like.d.ts +23 -0
- package/dist/internal/form-control.d.ts +3 -2
- package/dist/internal/form-control.js +3 -2
- package/dist/internal/kanban-layout.d.ts +55 -0
- package/dist/internal/kanban-layout.js +80 -0
- package/dist/internal/kanban-plugins.d.ts +17 -0
- package/dist/internal/kanban-plugins.js +17 -0
- package/dist/internal/use-media-query.d.ts +4 -2
- package/dist/internal/use-media-query.js +11 -15
- package/dist/kanban.d.ts +84 -0
- package/dist/kanban.js +197 -0
- package/dist/markdown.d.ts +2 -0
- package/dist/meter.d.ts +7 -0
- package/dist/nav-link.d.ts +23 -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/next/period-stepper.d.ts +11 -0
- package/dist/next/period-stepper.js +16 -0
- package/dist/page-header.d.ts +19 -0
- package/dist/page-header.js +11 -0
- package/dist/pagination.d.ts +2 -0
- package/dist/period-stepper.d.ts +32 -0
- package/dist/period-stepper.js +27 -0
- package/dist/picker-shell.d.ts +43 -6
- package/dist/picker-shell.js +2 -2
- package/dist/progress.d.ts +1 -0
- package/dist/search-picker.d.ts +12 -0
- package/dist/select.d.ts +1 -0
- package/dist/skip-link.d.ts +7 -0
- package/dist/skip-link.js +10 -0
- package/dist/slider.d.ts +11 -0
- package/dist/sortable-table-head.d.ts +2 -0
- package/dist/stat-tile.d.ts +5 -0
- package/dist/table-body-skeleton.d.ts +2 -0
- package/dist/table.d.ts +1 -0
- package/dist/tabs.d.ts +9 -5
- package/dist/tabs.js +1 -1
- package/dist/toast.d.ts +7 -1
- package/dist/toggle-group.d.ts +9 -2
- package/dist/toggle-group.js +2 -1
- package/dist/toggle.d.ts +1 -1
- package/package.json +85 -11
- package/skills/atlas-react-kit/SKILL.md +2 -0
- package/theme.css +11 -0
package/dist/combobox.js
CHANGED
|
@@ -53,7 +53,6 @@ export function Combobox({ options, value, onValueChange, placeholder = "Select"
|
|
|
53
53
|
const [open, setOpen] = React.useState(false);
|
|
54
54
|
const [query, setQuery] = React.useState("");
|
|
55
55
|
const [highlight, setHighlight] = React.useState(0);
|
|
56
|
-
const inputRef = React.useRef(null);
|
|
57
56
|
const listId = React.useId();
|
|
58
57
|
const generatedId = React.useId();
|
|
59
58
|
const triggerId = id ?? generatedId;
|
|
@@ -101,12 +100,6 @@ export function Combobox({ options, value, onValueChange, placeholder = "Select"
|
|
|
101
100
|
const selectedIndex = resolvedOptions.findIndex((option) => option.value === value);
|
|
102
101
|
setHighlight(selectedIndex >= 0 ? selectedIndex : 0);
|
|
103
102
|
};
|
|
104
|
-
React.useEffect(() => {
|
|
105
|
-
if (!open)
|
|
106
|
-
return;
|
|
107
|
-
const frame = window.requestAnimationFrame(() => inputRef.current?.focus());
|
|
108
|
-
return () => window.cancelAnimationFrame(frame);
|
|
109
|
-
}, [open]);
|
|
110
103
|
const onQueryChange = onInputChange((next) => {
|
|
111
104
|
setQuery(next);
|
|
112
105
|
setHighlight(0);
|
|
@@ -141,7 +134,7 @@ export function Combobox({ options, value, onValueChange, placeholder = "Select"
|
|
|
141
134
|
},
|
|
142
135
|
});
|
|
143
136
|
};
|
|
144
|
-
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { ...props, id: triggerId, type: "button", variant: "outline", role: "combobox", "aria-expanded": open, "aria-controls": listId, "aria-invalid": ariaInvalid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, disabled: disabled, onKeyDown: onTriggerKeyDown, className: cn(formControlTriggerClassName, "justify-between", !selected && "text-muted-foreground", className), children: [_jsx("span", { className: "truncate", children: selected?.label ?? placeholder }), _jsx(ChevronDownIcon, { "data-icon": "inline-end", className: "opacity-50" })] }) }), _jsxs(PopoverContent, { align: "start", className: cn("w-[var(--radix-popover-trigger-width)] gap-0 rounded-none p-0", contentClassName), children: [_jsx("div", { "data-slot": "combobox-search", className: "border-b p-2", children: _jsx(Input, {
|
|
137
|
+
return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { ...props, id: triggerId, type: "button", variant: "outline", role: "combobox", "aria-expanded": open, "aria-controls": listId, "aria-invalid": ariaInvalid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, disabled: disabled, onKeyDown: onTriggerKeyDown, className: cn(formControlTriggerClassName, "justify-between", !selected && "text-muted-foreground", className), children: [_jsx("span", { className: "truncate", children: selected?.label ?? placeholder }), _jsx(ChevronDownIcon, { "data-icon": "inline-end", className: "opacity-50" })] }) }), _jsxs(PopoverContent, { align: "start", className: cn("w-[var(--radix-popover-trigger-width)] gap-0 rounded-none p-0", contentClassName), children: [_jsx("div", { "data-slot": "combobox-search", className: "border-b p-2", children: _jsx(Input, { value: query, onChange: onQueryChange, onKeyDown: onSearchKeyDown, placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-autocomplete": "list", "aria-controls": listId, "aria-activedescendant": activeOption ? listboxOptionId(listId, highlight) : undefined }) }), _jsx("ul", { id: listId, role: "listbox", "data-slot": "combobox-list", "aria-label": ariaLabelledBy ? undefined : ariaLabel, "aria-labelledby": ariaLabelledBy ?? (ariaLabel ? undefined : triggerId), className: empty
|
|
145
138
|
? "sr-only"
|
|
146
139
|
: cn("max-h-60 overflow-y-auto p-1", listClassName), children: list.map((option, index) => {
|
|
147
140
|
const isCreate = createOption != null && option === createOption;
|
package/dist/date-picker.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type
|
|
3
|
-
import { toDate, type DateLike } from "./internal/date-like.js";
|
|
2
|
+
import { toDate, type DateLike, type DateMatcher, type DateRange } from "./internal/date-like.js";
|
|
4
3
|
import { type PickerCalendarProps, type PickerTriggerProps } from "./picker-shell.js";
|
|
5
|
-
export type { DateRange };
|
|
6
|
-
export type { DateLike };
|
|
4
|
+
export type { DateLike, DateMatcher, DateRange };
|
|
7
5
|
export { toDate };
|
|
8
6
|
/** From/to value for `DatePickerButton` in range mode; each side is `DateLike`. */
|
|
9
7
|
export type DatePickerRangeValue = {
|
|
8
|
+
/** First day of the range. */
|
|
10
9
|
from?: DateLike;
|
|
10
|
+
/** Last day of the range; missing while only the start is picked. */
|
|
11
11
|
to?: DateLike;
|
|
12
12
|
};
|
|
13
13
|
/** Format a Date as a timezone-safe calendar date (`yyyy-MM-dd`). */
|
|
@@ -22,14 +22,24 @@ type DatePickerSharedProps = PickerTriggerProps & {
|
|
|
22
22
|
numberOfMonths?: number;
|
|
23
23
|
};
|
|
24
24
|
export type DatePickerSingleProps = DatePickerSharedProps & {
|
|
25
|
+
/** Pick one day. Default `"single"`. */
|
|
25
26
|
mode?: "single";
|
|
27
|
+
/** Controlled day, as a `Date` or `yyyy-MM-dd`. Omitted is empty. */
|
|
26
28
|
value?: DateLike;
|
|
27
|
-
|
|
29
|
+
/** Called with the picked day, or `undefined` on Clear. */
|
|
30
|
+
onValueChange?: (date: Date | undefined) => void;
|
|
31
|
+
/** @deprecated Use `onValueChange`; `onChange` keeps working until 2.0. */
|
|
32
|
+
onChange?: (date: Date | undefined) => void;
|
|
28
33
|
};
|
|
29
34
|
export type DatePickerRangeProps = DatePickerSharedProps & {
|
|
35
|
+
/** Pick a from/to range of days. */
|
|
30
36
|
mode: "range";
|
|
37
|
+
/** Controlled range; each side is a `Date` or `yyyy-MM-dd`. Omitted is empty. */
|
|
31
38
|
value?: DatePickerRangeValue;
|
|
32
|
-
|
|
39
|
+
/** Called on every range click, or with `undefined` on Clear. */
|
|
40
|
+
onValueChange?: (range: DateRange | undefined) => void;
|
|
41
|
+
/** @deprecated Use `onValueChange`; `onChange` keeps working until 2.0. */
|
|
42
|
+
onChange?: (range: DateRange | undefined) => void;
|
|
33
43
|
};
|
|
34
44
|
export type DatePickerButtonProps = DatePickerSingleProps | DatePickerRangeProps;
|
|
35
45
|
/**
|
package/dist/date-picker.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { format, isSameDay } from "date-fns";
|
|
5
|
-
import { toDate } from "./internal/date-like.js";
|
|
5
|
+
import { toDate, } from "./internal/date-like.js";
|
|
6
6
|
import { MD_MEDIA_QUERY, useMediaQuery } from "./internal/use-media-query.js";
|
|
7
7
|
import { LazyCalendar } from "./lazy-calendar.js";
|
|
8
8
|
import { PickerClearFooter, PickerShell, limitCalendarProps, } from "./picker-shell.js";
|
|
@@ -22,41 +22,34 @@ function formatRangeTriggerLabel(from, to, placeholder) {
|
|
|
22
22
|
return format(from, "PPP");
|
|
23
23
|
return `${format(from, "PPP")} – ${format(to, "PPP")}`;
|
|
24
24
|
}
|
|
25
|
-
function DatePickerSingleButton({ value, onChange, placeholder = "Pick a date", numberOfMonths, defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
25
|
+
function DatePickerSingleButton({ value, onValueChange, onChange, placeholder = "Pick a date", numberOfMonths, defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
26
26
|
const [open, setOpen] = React.useState(false);
|
|
27
|
+
const emit = onValueChange ?? onChange;
|
|
27
28
|
const date = toDate(value);
|
|
28
29
|
return (_jsx(PickerShell, { ...shell, empty: !date, label: date ? format(date, "PPP") : placeholder, dialogLabel: "Choose date", open: open, onOpenChange: setOpen, children: _jsx(LazyCalendar, { ...limitCalendarProps(calendarProps, minDate, maxDate), mode: "single", autoFocus: true, selected: date, defaultMonth: defaultMonth ?? date, numberOfMonths: numberOfMonths, onSelect: (next) => {
|
|
29
|
-
|
|
30
|
+
emit?.(next);
|
|
30
31
|
setOpen(false);
|
|
31
32
|
} }) }));
|
|
32
33
|
}
|
|
33
|
-
function DatePickerRangeButton({ value, onChange, placeholder = "Pick a date range", numberOfMonths, defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
34
|
+
function DatePickerRangeButton({ value, onValueChange, onChange, placeholder = "Pick a date range", numberOfMonths, defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
34
35
|
const [open, setOpen] = React.useState(false);
|
|
36
|
+
const emit = onValueChange ?? onChange;
|
|
35
37
|
const mdUp = useMediaQuery(MD_MEDIA_QUERY);
|
|
36
38
|
const months = numberOfMonths ?? (mdUp ? 2 : 1);
|
|
37
39
|
const from = toDate(value?.from);
|
|
38
40
|
const to = toDate(value?.to);
|
|
39
41
|
const selected = from || to ? { from, to } : undefined;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
restartRef.current = Boolean(from && to);
|
|
47
|
-
setOpen(next);
|
|
48
|
-
};
|
|
49
|
-
return (_jsxs(PickerShell, { ...shell, empty: !from, label: formatRangeTriggerLabel(from, to, placeholder), dialogLabel: "Choose dates", open: open, onOpenChange: onOpenChange, children: [_jsx(LazyCalendar, { ...limitCalendarProps(calendarProps, minDate, maxDate), mode: "range", autoFocus: true, selected: selected, defaultMonth: defaultMonth ?? from ?? to, numberOfMonths: months, onSelect: (next, day) => {
|
|
50
|
-
const range = restartRef.current ? { from: day, to: day } : next;
|
|
51
|
-
restartRef.current = false;
|
|
52
|
-
onChange(range);
|
|
53
|
-
// First click is a same-day range; keep the popover open so the
|
|
54
|
-
// user can set `to`. Close once the ends differ.
|
|
42
|
+
return (_jsxs(PickerShell, { ...shell, empty: !from, label: formatRangeTriggerLabel(from, to, placeholder), dialogLabel: "Choose dates", open: open, onOpenChange: setOpen, children: [_jsx(LazyCalendar, { ...limitCalendarProps(calendarProps, minDate, maxDate), mode: "range",
|
|
43
|
+
// A click on a complete range (or on none) starts a new one, so a
|
|
44
|
+
// fresh range never needs Clear first. The start emits `to: undefined`.
|
|
45
|
+
resetOnSelect: true, autoFocus: true, selected: selected, defaultMonth: defaultMonth ?? from ?? to, numberOfMonths: months, onSelect: (range) => {
|
|
46
|
+
emit?.(range);
|
|
47
|
+
// Close once the ends differ; a start or a one-day range stays open.
|
|
55
48
|
if (range?.from && range.to && !isSameDay(range.from, range.to)) {
|
|
56
49
|
setOpen(false);
|
|
57
50
|
}
|
|
58
51
|
} }), _jsx(PickerClearFooter, { disabled: !from && !to, onClear: () => {
|
|
59
|
-
|
|
52
|
+
emit?.(undefined);
|
|
60
53
|
setOpen(false);
|
|
61
54
|
} })] }));
|
|
62
55
|
}
|
|
@@ -5,7 +5,10 @@ export declare const DEFAULT_TIME_STEP = 15;
|
|
|
5
5
|
export type DateTimePickerButtonProps = PickerTriggerProps & {
|
|
6
6
|
/** Controlled instant. `null` or omitted is empty. */
|
|
7
7
|
value?: Date | null;
|
|
8
|
-
|
|
8
|
+
/** Called with the picked instant, or `null` on Clear. */
|
|
9
|
+
onValueChange?: (date: Date | null) => void;
|
|
10
|
+
/** @deprecated Use `onValueChange`; `onChange` keeps working until 2.0. */
|
|
11
|
+
onChange?: (date: Date | null) => void;
|
|
9
12
|
/**
|
|
10
13
|
* Minute increment for the time selects (1, 5, 15, 30, or 60).
|
|
11
14
|
* Values that do not divide 60 fall back to 15 so the list stays even.
|
|
@@ -25,4 +28,4 @@ export declare function resolveTimeStep(step: number | undefined): number;
|
|
|
25
28
|
* stays on-screen at a 390px width. `className` styles the trigger,
|
|
26
29
|
* `contentClassName` the popover, and `calendarProps` reaches Day Picker.
|
|
27
30
|
*/
|
|
28
|
-
export declare function DateTimePickerButton({ value, onChange, timeStep, placeholder, defaultMonth, calendarProps, minDate, maxDate, ...shell }: DateTimePickerButtonProps): React.JSX.Element;
|
|
31
|
+
export declare function DateTimePickerButton({ value, onValueChange, onChange, timeStep, placeholder, defaultMonth, calendarProps, minDate, maxDate, ...shell }: DateTimePickerButtonProps): React.JSX.Element;
|
package/dist/date-time-picker.js
CHANGED
|
@@ -68,8 +68,9 @@ function preventDismissForPortaledSelect(event) {
|
|
|
68
68
|
* stays on-screen at a 390px width. `className` styles the trigger,
|
|
69
69
|
* `contentClassName` the popover, and `calendarProps` reaches Day Picker.
|
|
70
70
|
*/
|
|
71
|
-
export function DateTimePickerButton({ value, onChange, timeStep, placeholder = "Pick a date and time", defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
71
|
+
export function DateTimePickerButton({ value, onValueChange, onChange, timeStep, placeholder = "Pick a date and time", defaultMonth, calendarProps, minDate, maxDate, ...shell }) {
|
|
72
72
|
const [open, setOpen] = React.useState(false);
|
|
73
|
+
const emit = onValueChange ?? onChange;
|
|
73
74
|
const date = value ?? null;
|
|
74
75
|
const step = resolveTimeStep(timeStep);
|
|
75
76
|
const empty = date == null;
|
|
@@ -80,20 +81,20 @@ export function DateTimePickerButton({ value, onChange, timeStep, placeholder =
|
|
|
80
81
|
// so a time already set is not dropped by an accidental second tap.
|
|
81
82
|
if (!next)
|
|
82
83
|
return;
|
|
83
|
-
|
|
84
|
+
emit?.(combineDateAndTime(next, date?.getHours() ?? 0, date?.getMinutes() ?? 0));
|
|
84
85
|
} }), _jsxs("div", { role: "group", "aria-label": "Time", "data-slot": "date-time-picker-time", className: "flex min-w-0 flex-col gap-2 border-t p-3", children: [_jsx("p", { className: "text-xs font-semibold tracking-wide uppercase", children: "Time" }), _jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsxs(Select, { value: date ? padTimePart(date.getHours()) : undefined, onValueChange: (nextHour) => {
|
|
85
86
|
if (!date)
|
|
86
87
|
return;
|
|
87
|
-
|
|
88
|
+
emit?.(combineDateAndTime(date, Number(nextHour), date.getMinutes()));
|
|
88
89
|
}, disabled: empty, children: [_jsx(SelectTrigger, { id: hourId, "aria-label": "Hour", className: "min-w-0 flex-1", children: _jsx(SelectValue, { placeholder: "\u2013\u2013" }) }), _jsx(SelectContent, { children: HOUR_OPTIONS.map((hour) => (_jsx(SelectItem, { value: hour, children: hour }, hour))) })] }), _jsx("span", { className: "text-muted-foreground", "aria-hidden": "true", children: ":" }), _jsxs(Select, { value: date ? padTimePart(date.getMinutes()) : undefined, onValueChange: (nextMinute) => {
|
|
89
90
|
if (!date)
|
|
90
91
|
return;
|
|
91
|
-
|
|
92
|
+
emit?.(combineDateAndTime(date, date.getHours(), Number(nextMinute)));
|
|
92
93
|
}, disabled: empty, children: [_jsx(SelectTrigger, { id: minuteId, "aria-label": "Minute", className: "min-w-0 flex-1", children: _jsx(SelectValue, { placeholder: "\u2013\u2013" }) }), _jsx(SelectContent, { children: minuteOptions(step, date?.getMinutes()).map((minute) => {
|
|
93
94
|
const value = padTimePart(minute);
|
|
94
95
|
return (_jsx(SelectItem, { value: value, children: value }, value));
|
|
95
96
|
}) })] })] })] }), _jsx(PickerClearFooter, { disabled: empty, onClear: () => {
|
|
96
|
-
|
|
97
|
+
emit?.(null);
|
|
97
98
|
setOpen(false);
|
|
98
99
|
} })] }));
|
|
99
100
|
}
|
package/dist/dialog.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ declare function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPr
|
|
|
6
6
|
declare function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>): React.JSX.Element;
|
|
7
7
|
declare function DialogOverlay({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Overlay>): React.JSX.Element;
|
|
8
8
|
declare function DialogContent({ className, children, showCloseButton, overlayClassName, closeButtonClassName, ...props }: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
9
|
+
/** Show the X close button in the top-right corner. Default `true`. */
|
|
9
10
|
showCloseButton?: boolean;
|
|
10
11
|
/** Classes for the backdrop, e.g. a darker scrim. */
|
|
11
12
|
overlayClassName?: string;
|
package/dist/dialog.js
CHANGED
|
@@ -22,7 +22,9 @@ function DialogOverlay({ className, ...props }) {
|
|
|
22
22
|
return (_jsx(DialogPrimitive.Overlay, { "data-slot": "dialog-overlay", className: cn(overlayFade, "fixed inset-0 isolate z-50 bg-black/20 supports-backdrop-filter:backdrop-blur-sm", className), ...props }));
|
|
23
23
|
}
|
|
24
24
|
function DialogContent({ className, children, showCloseButton = true, overlayClassName, closeButtonClassName, ...props }) {
|
|
25
|
-
return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, { className: overlayClassName }), _jsxs(DialogPrimitive.Content, { "data-slot": "dialog-content", className: cn(overlaySurface, overlayFadeZoom, "fixed top-1/2 left-1/2 z-50 grid max-h-[90dvh] w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 overflow-y-auto p-6 text-sm outline-none",
|
|
25
|
+
return (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, { className: overlayClassName }), _jsxs(DialogPrimitive.Content, { "data-slot": "dialog-content", className: cn(overlaySurface, overlayFadeZoom, "fixed top-1/2 left-1/2 z-50 grid max-h-[90dvh] w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 overflow-y-auto p-6 text-sm outline-none", showCloseButton
|
|
26
|
+
? "[--dialog-close-gutter:--spacing(10)]"
|
|
27
|
+
: "[--dialog-close-gutter:0px]", className), ...props, children: [children, showCloseButton && (_jsx(DialogPrimitive.Close, { "data-slot": "dialog-close-button", asChild: true, children: _jsxs(Button, { variant: "ghost", size: "icon-sm", className: cn("absolute top-4 right-4 text-muted-foreground hover:text-foreground", closeButtonClassName), children: [_jsx(XIcon, {}), _jsx("span", { className: "sr-only", children: "Close" })] }) }))] })] }));
|
|
26
28
|
}
|
|
27
29
|
function DialogHeader({ className, ...props }) {
|
|
28
30
|
return (_jsx("div", { "data-slot": "dialog-header", className: cn("flex flex-col gap-2", className), ...props }));
|
|
@@ -31,7 +33,7 @@ function DialogFooter({ className, children, ...props }) {
|
|
|
31
33
|
return (_jsx("div", { "data-slot": "dialog-footer", className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className), ...props, children: children }));
|
|
32
34
|
}
|
|
33
35
|
function DialogTitle({ className, ...props }) {
|
|
34
|
-
return (_jsx(DialogPrimitive.Title, { "data-slot": "dialog-title", className: cn("font-heading text-lg leading-none font-semibold tracking-wider uppercase", className), ...props }));
|
|
36
|
+
return (_jsx(DialogPrimitive.Title, { "data-slot": "dialog-title", className: cn("pr-[var(--dialog-close-gutter,0px)] font-heading text-lg leading-none font-semibold tracking-wider uppercase", className), ...props }));
|
|
35
37
|
}
|
|
36
38
|
function DialogDescription({ className, ...props }) {
|
|
37
39
|
return (_jsx(DialogPrimitive.Description, { "data-slot": "dialog-description", className: cn("mt-0.5 text-sm leading-relaxed text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className), ...props }));
|
package/dist/dropdown-menu.d.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
3
|
+
/** Props for menu rows that can line up with checkbox and radio items. */
|
|
4
|
+
type MenuInsetProps = {
|
|
5
|
+
/** Indent the row to line up with checkbox and radio item text. */
|
|
6
|
+
inset?: boolean;
|
|
7
|
+
};
|
|
3
8
|
/** Action menu for commands (row actions, overflow menus). Use `Select` to pick a value. */
|
|
4
9
|
declare function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>): React.JSX.Element;
|
|
5
10
|
declare function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>): React.JSX.Element;
|
|
6
11
|
declare function DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>): React.JSX.Element;
|
|
7
12
|
declare function DropdownMenuContent({ className, align, sideOffset, collisionPadding, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>): React.JSX.Element;
|
|
8
13
|
declare function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>): React.JSX.Element;
|
|
9
|
-
declare function DropdownMenuItem({ className, inset, variant, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
|
10
|
-
|
|
14
|
+
declare function DropdownMenuItem({ className, inset, variant, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & MenuInsetProps & {
|
|
15
|
+
/** `destructive` colors the row for a dangerous action. Default `default`. */
|
|
11
16
|
variant?: "default" | "destructive";
|
|
12
17
|
}): React.JSX.Element;
|
|
13
18
|
declare function DropdownMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>): React.JSX.Element;
|
|
14
19
|
declare function DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>): React.JSX.Element;
|
|
15
20
|
declare function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>): React.JSX.Element;
|
|
16
|
-
declare function DropdownMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> &
|
|
17
|
-
inset?: boolean;
|
|
18
|
-
}): React.JSX.Element;
|
|
21
|
+
declare function DropdownMenuLabel({ className, inset, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & MenuInsetProps): React.JSX.Element;
|
|
19
22
|
declare function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>): React.JSX.Element;
|
|
20
23
|
declare function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
21
24
|
declare function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>): React.JSX.Element;
|
|
22
|
-
declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> &
|
|
23
|
-
inset?: boolean;
|
|
24
|
-
}): React.JSX.Element;
|
|
25
|
+
declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & MenuInsetProps): React.JSX.Element;
|
|
25
26
|
declare function DropdownMenuSubContent({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>): React.JSX.Element;
|
|
26
27
|
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, };
|
package/dist/empty-panel.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type * as React from "react";
|
|
2
2
|
type Props = React.ComponentProps<"div"> & {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* `sm` is tighter padding for compact widgets; `default` is standard form
|
|
6
|
+
* empty states; `lg` is roomier, for page-level states. `md` is a
|
|
7
|
+
* deprecated alias of `default`, kept until 2.0. Default `default`.
|
|
8
|
+
*/
|
|
9
|
+
size?: "sm" | "default" | "lg" | "md";
|
|
10
|
+
/** Tinted muted background. Default `true`. */
|
|
6
11
|
muted?: boolean;
|
|
12
|
+
/** Classes for the root `div`. */
|
|
7
13
|
className?: string;
|
|
8
14
|
};
|
|
9
15
|
/** Dashed empty-state panel for lists, widgets, and form sections. Other props go to the root `div`. */
|
package/dist/empty-panel.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
|
/** Dashed empty-state panel for lists, widgets, and form sections. Other props go to the root `div`. */
|
|
4
|
-
export function EmptyPanel({ children, size = "
|
|
5
|
-
return (_jsx("div", { "data-slot": "empty-panel", ...props, className: cn("rounded-none border border-dashed text-center text-sm text-muted-foreground", muted && "bg-muted/30", size === "sm" && "px-3 py-4", size === "md" && "px-4 py-6", size === "lg" && "px-4 py-8", className), children: children }));
|
|
4
|
+
export function EmptyPanel({ children, size = "default", muted = true, className, ...props }) {
|
|
5
|
+
return (_jsx("div", { "data-slot": "empty-panel", ...props, className: cn("rounded-none border border-dashed text-center text-sm text-muted-foreground", muted && "bg-muted/30", size === "sm" && "px-3 py-4", (size === "default" || size === "md") && "px-4 py-6", size === "lg" && "px-4 py-8", className), children: children }));
|
|
6
6
|
}
|
package/dist/error-boundary.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Component, type ErrorInfo, type ReactNode } from "react";
|
|
2
2
|
type ErrorFallbackProps = {
|
|
3
|
-
/** User-facing recovery copy. */
|
|
3
|
+
/** User-facing recovery copy. Default "Something went wrong.". */
|
|
4
4
|
message?: string;
|
|
5
|
+
/** Shows a "Try again" button that calls this. Hidden when omitted. */
|
|
5
6
|
onRetry?: () => void;
|
|
7
|
+
/** Shows a "Reload" button that calls this. Hidden when omitted. */
|
|
6
8
|
onReload?: () => void;
|
|
9
|
+
/** Classes for the panel. */
|
|
7
10
|
className?: string;
|
|
8
11
|
};
|
|
9
12
|
/**
|
|
@@ -13,9 +16,11 @@ type ErrorFallbackProps = {
|
|
|
13
16
|
*/
|
|
14
17
|
export declare function ErrorFallback({ message, onRetry, onReload, className, }: ErrorFallbackProps): import("react").JSX.Element;
|
|
15
18
|
type ErrorBoundaryProps = {
|
|
19
|
+
/** Content to render until it throws. */
|
|
16
20
|
children: ReactNode;
|
|
17
21
|
/** Overrides the default recovery message. */
|
|
18
22
|
message?: string;
|
|
23
|
+
/** Called with the caught error and its component stack, e.g. to log it. */
|
|
19
24
|
onError?: (error: Error, info: ErrorInfo) => void;
|
|
20
25
|
};
|
|
21
26
|
type ErrorBoundaryState = {
|
|
@@ -31,6 +36,6 @@ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBo
|
|
|
31
36
|
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
32
37
|
retry: () => void;
|
|
33
38
|
reload: () => void;
|
|
34
|
-
render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean |
|
|
39
|
+
render(): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
|
|
35
40
|
}
|
|
36
41
|
export {};
|
package/dist/field.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
2
2
|
import { Label } from "./label.js";
|
|
3
3
|
declare function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">): import("react").JSX.Element;
|
|
4
4
|
declare function FieldLegend({ className, variant, ...props }: React.ComponentProps<"legend"> & {
|
|
5
|
+
/** `label` styles the legend like a field label. Default `legend`. */
|
|
5
6
|
variant?: "legend" | "label";
|
|
6
7
|
}): import("react").JSX.Element;
|
|
7
8
|
/**
|
|
@@ -19,7 +20,7 @@ declare function FieldGroup({ className, ...props }: React.ComponentProps<"div">
|
|
|
19
20
|
* content in a row.
|
|
20
21
|
*/
|
|
21
22
|
declare const fieldVariants: (props?: ({
|
|
22
|
-
orientation?: "horizontal" | "
|
|
23
|
+
orientation?: "horizontal" | "responsive" | "vertical" | null | undefined;
|
|
23
24
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
24
25
|
declare function Field({ className, orientation, ...props }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>): import("react").JSX.Element;
|
|
25
26
|
declare function FieldContent({ className, ...props }: React.ComponentProps<"div">): import("react").JSX.Element;
|
|
@@ -27,9 +28,11 @@ declare function FieldLabel({ className, ...props }: React.ComponentProps<typeof
|
|
|
27
28
|
declare function FieldTitle({ className, ...props }: React.ComponentProps<"div">): import("react").JSX.Element;
|
|
28
29
|
declare function FieldDescription({ className, ...props }: React.ComponentProps<"p">): import("react").JSX.Element;
|
|
29
30
|
declare function FieldSeparator({ children, className, ...props }: React.ComponentProps<"div"> & {
|
|
31
|
+
/** Optional text shown in a gap in the middle of the line, e.g. "Or". */
|
|
30
32
|
children?: React.ReactNode;
|
|
31
33
|
}): import("react").JSX.Element;
|
|
32
34
|
declare function FieldError({ className, children, errors, ...props }: React.ComponentProps<"div"> & {
|
|
35
|
+
/** Errors to list, deduplicated by message; `children` replaces them. */
|
|
33
36
|
errors?: Array<{
|
|
34
37
|
message?: string;
|
|
35
38
|
} | undefined>;
|
package/dist/field.js
CHANGED
|
@@ -71,7 +71,7 @@ function FieldError({ className, children, errors, ...props }) {
|
|
|
71
71
|
if (uniqueErrors?.length == 1) {
|
|
72
72
|
return uniqueErrors[0]?.message;
|
|
73
73
|
}
|
|
74
|
-
return (_jsx("ul", { className: "ml-4 flex list-disc flex-col gap-1", children: uniqueErrors.map((error
|
|
74
|
+
return (_jsx("ul", { className: "ml-4 flex list-disc flex-col gap-1", children: uniqueErrors.map((error) => error?.message && _jsx("li", { children: error.message }, error.message)) }));
|
|
75
75
|
}, [children, errors]);
|
|
76
76
|
if (!content) {
|
|
77
77
|
return null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type FormFieldBaseProps, type FormFieldDescriptionProps, type FormFieldMetaProps } from "./field-error.js";
|
|
2
|
+
type CheckboxFieldProps = FormFieldBaseProps & FormFieldMetaProps & FormFieldDescriptionProps & {
|
|
3
|
+
/** Whether the box is checked. */
|
|
4
|
+
checked: boolean;
|
|
5
|
+
/** Called with the new checked state when the person toggles the box. */
|
|
6
|
+
onCheckedChange: (checked: boolean) => void;
|
|
7
|
+
/** Called when the checkbox loses focus; pass the field's blur handler. */
|
|
8
|
+
onBlur?: () => void;
|
|
9
|
+
/** Checkbox id the label points at. Defaults to a generated id. */
|
|
10
|
+
id?: string;
|
|
11
|
+
/** Sets `required` on the checkbox and marks the label. */
|
|
12
|
+
required?: boolean;
|
|
13
|
+
/** Disables the checkbox. */
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/** Checkbox before the label (default) or after the label and hint. */
|
|
16
|
+
controlPosition?: "start" | "end";
|
|
17
|
+
/** Forwarded to the checkbox. */
|
|
18
|
+
className?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* One boolean as a labelled checkbox, with an optional hint and the same
|
|
22
|
+
* error text and timing as the other `form/*` fields.
|
|
23
|
+
*/
|
|
24
|
+
export declare function FormCheckboxField({ checked, onCheckedChange, onBlur, label, description, id: idProp, meta, submitted, showError, required, disabled, controlPosition, className, fieldClassName, }: CheckboxFieldProps): import("react").JSX.Element;
|
|
25
|
+
export type CheckboxGroupOption<T extends string | number> = {
|
|
26
|
+
/** Value added to the group's `value` while this box is checked. */
|
|
27
|
+
value: T;
|
|
28
|
+
/** Text shown next to the box. */
|
|
29
|
+
label: string;
|
|
30
|
+
};
|
|
31
|
+
type CheckboxGroupFieldProps<T extends string | number> = FormFieldBaseProps & FormFieldMetaProps & FormFieldDescriptionProps & {
|
|
32
|
+
/** The boxes to show, in order. */
|
|
33
|
+
options: CheckboxGroupOption<T>[];
|
|
34
|
+
/** The checked values. */
|
|
35
|
+
value: T[];
|
|
36
|
+
/** Called with the checked values, in `options` order. */
|
|
37
|
+
onValueChange: (value: T[]) => void;
|
|
38
|
+
/** Disables every checkbox in the group. */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** Layout of the options, e.g. a grid. Defaults to a wrapping row. */
|
|
41
|
+
className?: string;
|
|
42
|
+
};
|
|
43
|
+
/** Several values from a short list, as a labelled set of checkboxes. */
|
|
44
|
+
export declare function FormCheckboxGroupField<T extends string | number>({ label, description, options, value, onValueChange, meta, submitted, showError, disabled, className, fieldClassName, }: CheckboxGroupFieldProps<T>): import("react").JSX.Element;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Checkbox } from "../checkbox.js";
|
|
5
|
+
import { Field, FieldContent, FieldDescription, FieldLabel, FieldLegend, FieldSet, } from "../field.js";
|
|
6
|
+
import { cn } from "../utils.js";
|
|
7
|
+
import { FieldError, } from "./field-error.js";
|
|
8
|
+
import { describedBy, descriptionIdFor, errorIdFor, invalidWhen, metaErrorText, } from "./field-shell.js";
|
|
9
|
+
/**
|
|
10
|
+
* One boolean as a labelled checkbox, with an optional hint and the same
|
|
11
|
+
* error text and timing as the other `form/*` fields.
|
|
12
|
+
*/
|
|
13
|
+
export function FormCheckboxField({ checked, onCheckedChange, onBlur, label, description, id: idProp, meta, submitted, showError, required, disabled, controlPosition = "start", className, fieldClassName, }) {
|
|
14
|
+
const generatedId = useId();
|
|
15
|
+
const id = idProp ?? generatedId;
|
|
16
|
+
const errorText = metaErrorText(meta, { submitted, showError });
|
|
17
|
+
const descriptionId = description ? descriptionIdFor(id) : undefined;
|
|
18
|
+
const checkbox = (_jsx(Checkbox, { id: id, checked: checked, onCheckedChange: (next) => onCheckedChange(next === true), onBlur: onBlur, disabled: disabled, required: required, "aria-required": required || undefined, "aria-invalid": invalidWhen(errorText), "aria-describedby": describedBy(id, errorText, descriptionId), className: className }));
|
|
19
|
+
const labelNode = (_jsx(FieldLabel, { htmlFor: id, required: required, children: label }));
|
|
20
|
+
return (_jsxs("div", { "data-slot": "form-field", className: cn("flex flex-col gap-1.5", fieldClassName), children: [_jsxs(Field, { orientation: "horizontal", children: [controlPosition === "start" ? checkbox : null, description ? (_jsxs(FieldContent, { children: [labelNode, _jsx(FieldDescription, { id: descriptionId, children: description })] })) : (labelNode), controlPosition === "end" ? checkbox : null] }), _jsx(FieldError, { id: errorIdFor(id), text: errorText })] }));
|
|
21
|
+
}
|
|
22
|
+
/** Several values from a short list, as a labelled set of checkboxes. */
|
|
23
|
+
export function FormCheckboxGroupField({ label, description, options, value, onValueChange, meta, submitted, showError, disabled, className, fieldClassName, }) {
|
|
24
|
+
const id = useId();
|
|
25
|
+
const errorText = metaErrorText(meta, { submitted, showError });
|
|
26
|
+
const descriptionId = description ? descriptionIdFor(id) : undefined;
|
|
27
|
+
function toggle(option, on) {
|
|
28
|
+
const next = new Set(value);
|
|
29
|
+
if (on)
|
|
30
|
+
next.add(option);
|
|
31
|
+
else
|
|
32
|
+
next.delete(option);
|
|
33
|
+
onValueChange(options.map((o) => o.value).filter((v) => next.has(v)));
|
|
34
|
+
}
|
|
35
|
+
return (_jsxs(FieldSet, { "data-slot": "form-field", "aria-invalid": invalidWhen(errorText), "aria-describedby": describedBy(id, errorText, descriptionId), className: cn("gap-1.5", fieldClassName), children: [_jsx(FieldLegend, { variant: "label", className: "mb-0", children: label }), description ? (_jsx("p", { id: descriptionId, "data-slot": "form-field-description", className: "text-xs text-muted-foreground", children: description })) : null, _jsx("div", { "data-slot": "form-checkbox-group-options", className: cn("flex flex-wrap gap-x-6 gap-y-3 pt-1", className), children: options.map((option) => {
|
|
36
|
+
const optionId = `${id}-${option.value}`;
|
|
37
|
+
return (_jsxs(Field, { orientation: "horizontal", children: [_jsx(Checkbox, { id: optionId, checked: value.includes(option.value), onCheckedChange: (next) => toggle(option.value, next === true), disabled: disabled }), _jsx(FieldLabel, { htmlFor: optionId, children: option.label })] }, option.value));
|
|
38
|
+
}) }), _jsx(FieldError, { id: errorIdFor(id), text: errorText })] }));
|
|
39
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ComponentProps } from "react";
|
|
2
|
+
import { Combobox } from "../combobox.js";
|
|
3
|
+
import type { FormFieldBaseProps, FormFieldDescriptionProps, FormFieldMetaProps } from "./field-error.js";
|
|
4
|
+
type Props = FormFieldBaseProps & FormFieldMetaProps & FormFieldDescriptionProps & Omit<ComponentProps<typeof Combobox>, "id" | "aria-invalid" | "aria-describedby" | "aria-required"> & {
|
|
5
|
+
/** Marks the label and passes `aria-required` to the trigger. */
|
|
6
|
+
required?: boolean;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* `Combobox` with a label, optional hint, and the `form/*` error text and
|
|
10
|
+
* timing. Pass the field's blur handler as `onBlur` so touch state updates.
|
|
11
|
+
*/
|
|
12
|
+
export declare function FormComboboxField({ label, description, meta, submitted, showError, required, fieldClassName, ...props }: Props): import("react").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { Combobox } from "../combobox.js";
|
|
5
|
+
import { describedBy, descriptionIdFor, FormFieldShell, invalidWhen, metaErrorText, } from "./field-shell.js";
|
|
6
|
+
/**
|
|
7
|
+
* `Combobox` with a label, optional hint, and the `form/*` error text and
|
|
8
|
+
* timing. Pass the field's blur handler as `onBlur` so touch state updates.
|
|
9
|
+
*/
|
|
10
|
+
export function FormComboboxField({ label, description, meta, submitted, showError, required, fieldClassName, ...props }) {
|
|
11
|
+
const id = useId();
|
|
12
|
+
const errorText = metaErrorText(meta, { submitted, showError });
|
|
13
|
+
return (_jsx(FormFieldShell, { id: id, label: label, description: description, errorText: errorText, required: required, className: fieldClassName, children: _jsx(Combobox, { ...props, id: id, "aria-required": required || undefined, "aria-invalid": invalidWhen(errorText), "aria-describedby": describedBy(id, errorText, description ? descriptionIdFor(id) : undefined) }) }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ComponentProps, type ReactNode } from "react";
|
|
2
|
+
import type { FormFieldBaseProps, FormFieldDescriptionProps, FormFieldMetaProps } from "./field-error.js";
|
|
3
|
+
/** Props `FormControlField` hands its control: spread them onto it. */
|
|
4
|
+
export type FormControlProps = {
|
|
5
|
+
/** Id the label points at. */
|
|
6
|
+
id: string;
|
|
7
|
+
/** `true` while the field shows error text. */
|
|
8
|
+
"aria-invalid": true | undefined;
|
|
9
|
+
/** Ids of the hint and the error text, when shown. */
|
|
10
|
+
"aria-describedby": string | undefined;
|
|
11
|
+
/** `true` when the field is `required`. */
|
|
12
|
+
"aria-required": true | undefined;
|
|
13
|
+
};
|
|
14
|
+
type Props = Omit<FormFieldBaseProps, "fieldClassName"> & FormFieldMetaProps & FormFieldDescriptionProps & Omit<ComponentProps<"div">, "id" | "children"> & {
|
|
15
|
+
/** Control id the label points at. Defaults to a generated id. */
|
|
16
|
+
id?: string;
|
|
17
|
+
/** Marks the label and passes `aria-required` to the control. */
|
|
18
|
+
required?: boolean;
|
|
19
|
+
/** Renders the control from the id and ARIA props it should carry. */
|
|
20
|
+
children: (control: FormControlProps) => ReactNode;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The `form/*` field layout for a control the kit does not ship (a
|
|
24
|
+
* combobox, a segmented picker): label with the required marker, optional
|
|
25
|
+
* hint, the control, and its error, with the same spacing, ids, and error
|
|
26
|
+
* timing as `FormTextField`. `className` and other div props go to the
|
|
27
|
+
* wrapper (`data-slot="form-field"`).
|
|
28
|
+
*/
|
|
29
|
+
export declare function FormControlField({ id: idProp, label, description, required, meta, submitted, showError, children, ...props }: Props): import("react").JSX.Element;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { describedBy, descriptionIdFor, FormFieldShell, invalidWhen, metaErrorText, } from "./field-shell.js";
|
|
5
|
+
/**
|
|
6
|
+
* The `form/*` field layout for a control the kit does not ship (a
|
|
7
|
+
* combobox, a segmented picker): label with the required marker, optional
|
|
8
|
+
* hint, the control, and its error, with the same spacing, ids, and error
|
|
9
|
+
* timing as `FormTextField`. `className` and other div props go to the
|
|
10
|
+
* wrapper (`data-slot="form-field"`).
|
|
11
|
+
*/
|
|
12
|
+
export function FormControlField({ id: idProp, label, description, required, meta, submitted, showError, children, ...props }) {
|
|
13
|
+
const generatedId = useId();
|
|
14
|
+
const id = idProp ?? generatedId;
|
|
15
|
+
const errorText = metaErrorText(meta, { submitted, showError });
|
|
16
|
+
return (_jsx(FormFieldShell, { ...props, id: id, label: label, description: description, errorText: errorText, required: required, children: children({
|
|
17
|
+
id,
|
|
18
|
+
"aria-invalid": invalidWhen(errorText),
|
|
19
|
+
"aria-describedby": describedBy(id, errorText, description ? descriptionIdFor(id) : undefined),
|
|
20
|
+
"aria-required": required || undefined,
|
|
21
|
+
}) }));
|
|
22
|
+
}
|
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import { type DateLike
|
|
2
|
-
import type
|
|
3
|
-
type Props = {
|
|
1
|
+
import { type DateLike } from "../date-picker.js";
|
|
2
|
+
import { type PickerFieldBaseProps } from "./field-shell.js";
|
|
3
|
+
type Props = PickerFieldBaseProps & {
|
|
4
|
+
/** The picked day, as a `Date` or `yyyy-MM-dd`; empty when unset. */
|
|
4
5
|
value: DateLike;
|
|
6
|
+
/** Called with the picked day, or `undefined` when cleared. */
|
|
5
7
|
onValueChange: (date: Date | undefined) => void;
|
|
6
|
-
|
|
7
|
-
meta?: FieldMetaState;
|
|
8
|
+
/** Trigger text while no day is picked. Default "Pick a date". */
|
|
8
9
|
placeholder?: string;
|
|
9
|
-
disabled?: boolean;
|
|
10
|
-
/** Marks the label and adds "Required" to the trigger's description. */
|
|
11
|
-
required?: boolean;
|
|
12
|
-
/** Earliest day that can be picked; earlier days are disabled. */
|
|
13
|
-
minDate?: DateLike;
|
|
14
|
-
/** Latest day that can be picked; later days are disabled. */
|
|
15
|
-
maxDate?: DateLike;
|
|
16
|
-
/** Forwarded to the date picker trigger. */
|
|
17
|
-
className?: string;
|
|
18
|
-
/** Classes for the field wrapper (label, trigger, and error). */
|
|
19
|
-
fieldClassName?: string;
|
|
20
|
-
/** Forwarded to the date picker popover. */
|
|
21
|
-
contentClassName?: string;
|
|
22
|
-
/** Day Picker options forwarded to the calendar (disabled days, etc.). */
|
|
23
|
-
calendarProps?: DatePickerCalendarProps;
|
|
24
10
|
};
|
|
25
11
|
/** Date picker with built-in field error text and invalid styling. */
|
|
26
|
-
export declare function FormDatePickerField({ onValueChange, label, meta, required, fieldClassName, ...picker }: Props): import("react").JSX.Element;
|
|
12
|
+
export declare function FormDatePickerField({ onValueChange, label, meta, submitted, showError, required, fieldClassName, ...picker }: Props): import("react").JSX.Element;
|
|
27
13
|
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { useId } from "react";
|
|
4
|
-
import { DatePickerButton
|
|
4
|
+
import { DatePickerButton } from "../date-picker.js";
|
|
5
5
|
import { FormFieldShell, metaErrorText, pickerFieldAria, } from "./field-shell.js";
|
|
6
6
|
/** Date picker with built-in field error text and invalid styling. */
|
|
7
|
-
export function FormDatePickerField({ onValueChange, label, meta, required, fieldClassName, ...picker }) {
|
|
8
|
-
const errorText = metaErrorText(meta);
|
|
7
|
+
export function FormDatePickerField({ onValueChange, label, meta, submitted, showError, required, fieldClassName, ...picker }) {
|
|
8
|
+
const errorText = metaErrorText(meta, { submitted, showError });
|
|
9
9
|
const id = useId();
|
|
10
|
-
return (_jsx(FormFieldShell, { id: id, label: label, errorText: errorText, required: required, className: fieldClassName, children: _jsx(DatePickerButton, { ...picker, id: id,
|
|
10
|
+
return (_jsx(FormFieldShell, { id: id, label: label, errorText: errorText, required: required, className: fieldClassName, children: _jsx(DatePickerButton, { ...picker, id: id, onValueChange: onValueChange, ...pickerFieldAria(id, errorText, required) }) }));
|
|
11
11
|
}
|