@neasg/design-system 0.4.35 → 0.4.95
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/dist/activity-card.d.ts +29 -0
- package/dist/activity-card.js +65 -0
- package/dist/autocomplete.d.ts +84 -0
- package/dist/autocomplete.js +267 -0
- package/dist/avatar.d.ts +3 -1
- package/dist/avatar.js +27 -10
- package/dist/badge.js +1 -1
- package/dist/button.d.ts +1 -1
- package/dist/button.js +1 -0
- package/dist/calendar.js +1 -1
- package/dist/card.d.ts +1 -1
- package/dist/card.js +1 -1
- package/dist/compound-search-input.d.ts +8 -0
- package/dist/compound-search-input.js +9 -0
- package/dist/date-input.js +3 -3
- package/dist/dialog.d.ts +3 -1
- package/dist/dialog.js +6 -2
- package/dist/draggable-tabs.js +9 -8
- package/dist/index.d.ts +12 -4
- package/dist/index.js +6 -2
- package/dist/label-value-grid.js +6 -4
- package/dist/layout.d.ts +39 -6
- package/dist/layout.js +118 -42
- package/dist/lib/utils.js +1 -0
- package/dist/message-item.d.ts +23 -3
- package/dist/message-item.js +115 -16
- package/dist/notification.d.ts +14 -3
- package/dist/notification.js +32 -7
- package/dist/popover-menu.d.ts +4 -2
- package/dist/popover-menu.js +65 -5
- package/dist/popover.d.ts +5 -2
- package/dist/popover.js +3 -3
- package/dist/rich-text-editor.d.ts +2 -1
- package/dist/rich-text-editor.js +28 -3
- package/dist/routing-timeline.d.ts +7 -2
- package/dist/routing-timeline.js +67 -29
- package/dist/search-input.d.ts +4 -0
- package/dist/search-input.js +2 -2
- package/dist/select-primitive.js +1 -1
- package/dist/select.d.ts +3 -1
- package/dist/select.js +9 -4
- package/dist/status-dot.d.ts +13 -0
- package/dist/status-dot.js +19 -0
- package/dist/styles.css +0 -19
- package/dist/table-column-filter.js +7 -5
- package/dist/table.d.ts +9 -1
- package/dist/table.js +25 -11
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +6 -4
- package/dist/textarea.d.ts +1 -0
- package/dist/textarea.js +3 -2
- package/dist/theme-switcher.d.ts +3 -1
- package/dist/theme-switcher.js +8 -2
- package/package.json +1 -1
package/dist/routing-timeline.js
CHANGED
|
@@ -1,58 +1,96 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowRight, Mail, Route } from "lucide-react";
|
|
3
|
+
import { ActivityCard, ActivityCardContent } from "./activity-card";
|
|
4
|
+
import { AvatarProfile } from "./avatar";
|
|
3
5
|
import { Badge } from "./badge";
|
|
4
6
|
import { EmptyState } from "./empty-state";
|
|
5
7
|
import { cn } from "./lib/utils";
|
|
6
8
|
import { Typography } from "./typography";
|
|
7
9
|
const routingKindConfig = {
|
|
8
10
|
assigned: {
|
|
9
|
-
title: "Assigned
|
|
10
|
-
label: "
|
|
11
|
-
|
|
12
|
-
markerClassName: "border-[hsl(var(--status-info-foreground)/0.35)] bg-[hsl(var(--status-info))]",
|
|
11
|
+
title: "Assigned case",
|
|
12
|
+
label: "ASSIGNED",
|
|
13
|
+
icon: "route",
|
|
13
14
|
},
|
|
14
15
|
reassigned: {
|
|
15
|
-
title: "Reassigned
|
|
16
|
-
label: "
|
|
17
|
-
|
|
18
|
-
markerClassName: "border-[hsl(var(--status-accent-foreground)/0.35)] bg-[hsl(var(--status-accent))]",
|
|
16
|
+
title: "Reassigned case",
|
|
17
|
+
label: "REASSIGNED",
|
|
18
|
+
icon: "route",
|
|
19
19
|
},
|
|
20
20
|
returned: {
|
|
21
|
-
title: "
|
|
22
|
-
label: "
|
|
23
|
-
|
|
24
|
-
markerClassName: "border-[hsl(var(--status-warning-foreground)/0.35)] bg-[hsl(var(--status-warning))]",
|
|
21
|
+
title: "Case returned",
|
|
22
|
+
label: "RETURNED",
|
|
23
|
+
icon: "route",
|
|
25
24
|
},
|
|
26
25
|
routed: {
|
|
27
|
-
title: "Case
|
|
28
|
-
label: "
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
title: "Case routed",
|
|
27
|
+
label: "ROUTED",
|
|
28
|
+
icon: "route",
|
|
29
|
+
},
|
|
30
|
+
"message-received": {
|
|
31
|
+
title: "Received from applicant",
|
|
32
|
+
label: "RECEIVED",
|
|
33
|
+
detailLabel: "Response from applicant:",
|
|
34
|
+
icon: "mail",
|
|
35
|
+
},
|
|
36
|
+
"message-sent": {
|
|
37
|
+
title: "Sent to applicant",
|
|
38
|
+
label: "SENT",
|
|
39
|
+
detailLabel: "Officer sent a message:",
|
|
40
|
+
icon: "mail",
|
|
31
41
|
},
|
|
32
42
|
system: {
|
|
33
|
-
title: "System
|
|
34
|
-
label: "
|
|
35
|
-
|
|
36
|
-
markerClassName: "border-muted-foreground/30 bg-muted",
|
|
43
|
+
title: "System update",
|
|
44
|
+
label: "SYSTEM",
|
|
45
|
+
icon: "route",
|
|
37
46
|
},
|
|
38
47
|
};
|
|
39
|
-
function RoutingTimelineHandoffEndpoint({ value, }) {
|
|
48
|
+
function RoutingTimelineHandoffEndpoint({ value, label, }) {
|
|
40
49
|
const isTextValue = typeof value === "string" || typeof value === "number";
|
|
41
|
-
|
|
50
|
+
if (!isTextValue) {
|
|
51
|
+
return (_jsx("div", { "data-slot": "routing-timeline-profile", "data-avatar-size": "xs", className: "min-w-0", children: value }));
|
|
52
|
+
}
|
|
53
|
+
const name = String(value);
|
|
54
|
+
const fallback = name
|
|
55
|
+
.split(/\s+/)
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.slice(0, 2)
|
|
58
|
+
.map((part) => part.charAt(0))
|
|
59
|
+
.join("")
|
|
60
|
+
.toUpperCase();
|
|
61
|
+
return (_jsx("div", { "data-slot": "routing-timeline-profile", "data-avatar-size": "xs", className: "min-w-0", children: _jsx(AvatarProfile, { size: "xs", fallback: fallback || "?", name: name, role: label, rolePlacement: "below" }) }));
|
|
62
|
+
}
|
|
63
|
+
function RoutingEventIcon({ icon, kind, density, }) {
|
|
64
|
+
if (icon)
|
|
65
|
+
return _jsx(_Fragment, { children: icon });
|
|
66
|
+
return routingKindConfig[kind].icon === "mail" ? (_jsx(Mail, { "aria-hidden": "true", className: density === "compact" ? "size-4" : "size-6" })) : (_jsx(Route, { "aria-hidden": "true", className: density === "compact" ? "size-4" : "size-6" }));
|
|
42
67
|
}
|
|
43
|
-
function RoutingTimeline({ items, emptyMessage = "No routing activity yet.", className, ...props }) {
|
|
68
|
+
function RoutingTimeline({ items, emptyMessage = "No routing activity yet.", density = "default", className, ...props }) {
|
|
44
69
|
if (items.length === 0) {
|
|
45
|
-
return (_jsx(EmptyState, { "data-slot": "routing-timeline", message: emptyMessage, className: cn("border-0 bg-transparent px-0
|
|
70
|
+
return (_jsx(EmptyState, { "data-slot": "routing-timeline", message: emptyMessage, className: cn("border-0 bg-transparent px-0", density === "compact"
|
|
71
|
+
? "py-[var(--space-4)]"
|
|
72
|
+
: "py-[var(--space-6)]", className), ...props }));
|
|
46
73
|
}
|
|
47
|
-
return (_jsx("div", { "data-slot": "routing-timeline", className: cn("min-w-0", className), ...props, children: _jsx("ol", { "data-slot": "routing-timeline-list", className:
|
|
48
|
-
var
|
|
74
|
+
return (_jsx("div", { "data-slot": "routing-timeline", "data-density": density, className: cn("min-w-0", className), ...props, children: _jsx("ol", { "data-slot": "routing-timeline-list", className: cn(density === "compact"
|
|
75
|
+
? "space-y-[var(--space-4)]"
|
|
76
|
+
: "space-y-[32px]"), children: items.map((item) => {
|
|
77
|
+
var _a, _b, _c, _d, _e;
|
|
49
78
|
const kind = (_a = item.kind) !== null && _a !== void 0 ? _a : "routed";
|
|
50
79
|
const config = routingKindConfig[kind];
|
|
51
80
|
const hasRouteEndpoints = Boolean(item.from || item.to);
|
|
52
81
|
const hasCompleteRoute = Boolean(item.from && item.to);
|
|
53
82
|
const title = (_b = item.title) !== null && _b !== void 0 ? _b : config.title;
|
|
54
83
|
const remark = (_c = item.remark) !== null && _c !== void 0 ? _c : item.description;
|
|
55
|
-
|
|
84
|
+
const detailLabel = (_d = item.detailLabel) !== null && _d !== void 0 ? _d : config.detailLabel;
|
|
85
|
+
const showDefaultBadge = item.badgeLabel !== null;
|
|
86
|
+
return (_jsx("li", { children: _jsx(ActivityCard, { "data-slot": "routing-timeline-event-card", density: density, icon: _jsx(RoutingEventIcon, { icon: item.icon, kind: kind, density: density }), title: title, meta: item.timestamp, trailing: item.badge ? (item.badge) : showDefaultBadge ? (_jsx(Badge, { variant: "outline", bordered: true, className: "max-w-full shrink-0", children: (_e = item.badgeLabel) !== null && _e !== void 0 ? _e : config.label })) : null, children: hasRouteEndpoints || remark ? (_jsxs(ActivityCardContent, { density: density, children: [hasRouteEndpoints ? (_jsxs("div", { "data-slot": "routing-timeline-handoff", "data-complete-route": hasCompleteRoute ? "true" : undefined, className: cn("flex min-w-0 items-center", density === "compact"
|
|
87
|
+
? "gap-[var(--space-3)]"
|
|
88
|
+
: "gap-[24px]"), children: [item.from ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.from, label: item.fromLabel })) : null, item.from && item.to ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "sr-only", children: "to" }), _jsx(ArrowRight, { "aria-hidden": "true", "data-slot": "routing-timeline-handoff-arrow", className: cn("shrink-0 text-foreground", density === "compact" ? "size-4" : "size-6") })] })) : null, item.to ? (_jsx(RoutingTimelineHandoffEndpoint, { value: item.to, label: item.toLabel })) : null] })) : null, remark ? (_jsxs("div", { "data-slot": "routing-timeline-remark", className: cn("bg-muted", density === "compact"
|
|
89
|
+
? "rounded-control p-[var(--space-2)]"
|
|
90
|
+
: "rounded-md p-[12px]"), children: [detailLabel ? (_jsx(Typography, { as: "p", variant: "bodySm", className: "font-semibold text-instructional", children: detailLabel })) : null, _jsx(Typography, { as: "div", variant: "bodySm", className: cn(detailLabel &&
|
|
91
|
+
(density === "compact"
|
|
92
|
+
? "mt-[var(--space-1)]"
|
|
93
|
+
: "mt-[4px]")), children: remark })] })) : null] })) : null }) }, item.id));
|
|
56
94
|
}) }) }));
|
|
57
95
|
}
|
|
58
96
|
export { RoutingTimeline };
|
package/dist/search-input.d.ts
CHANGED
|
@@ -4,9 +4,13 @@ export interface SearchInputProps extends Omit<React.ComponentProps<typeof Input
|
|
|
4
4
|
value: string;
|
|
5
5
|
onValueChange: (value: string) => void;
|
|
6
6
|
label?: React.ReactNode;
|
|
7
|
+
/** Visually hides the label while keeping it available to assistive technology. */
|
|
8
|
+
hideLabel?: boolean;
|
|
7
9
|
description?: React.ReactNode;
|
|
8
10
|
error?: React.ReactNode;
|
|
9
11
|
invalid?: boolean;
|
|
12
|
+
/** Keeps the control visually marked after a search result is selected. */
|
|
13
|
+
selected?: boolean;
|
|
10
14
|
containerClassName?: string;
|
|
11
15
|
labelClassName?: string;
|
|
12
16
|
descriptionClassName?: string;
|
package/dist/search-input.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Field, FieldDescription, FieldError, FieldLabel } from "./field";
|
|
|
6
6
|
import { InputControl } from "./input-control";
|
|
7
7
|
import { cn } from "./lib/utils";
|
|
8
8
|
import { SearchInputShell } from "./search-input-shell";
|
|
9
|
-
const SearchInput = React.forwardRef(({ value, onValueChange, label = "Search", description, error, invalid = false, placeholder = "Search...", containerClassName, labelClassName, descriptionClassName, errorClassName, onSearch, searchDelay = 300, searchOnChange = true, searchOnEnter = true, className, id, disabled, onKeyDown, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, ...props }, ref) => {
|
|
9
|
+
const SearchInput = React.forwardRef(({ value, onValueChange, label = "Search", hideLabel = true, description, error, invalid = false, selected = false, placeholder = "Search...", containerClassName, labelClassName, descriptionClassName, errorClassName, onSearch, searchDelay = 300, searchOnChange = true, searchOnEnter = true, className, id, disabled, onKeyDown, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, ...props }, ref) => {
|
|
10
10
|
const searchTimeoutRef = React.useRef();
|
|
11
11
|
React.useEffect(() => {
|
|
12
12
|
return () => {
|
|
@@ -64,7 +64,7 @@ const SearchInput = React.forwardRef(({ value, onValueChange, label = "Search",
|
|
|
64
64
|
}
|
|
65
65
|
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
66
66
|
}, [onKeyDown, runSearch, searchOnEnter]);
|
|
67
|
-
return (_jsxs(Field, { className: containerClassName, "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: inputId, className: cn("sr-only", labelClassName), children: label }), _jsxs(SearchInputShell, { children: [_jsx(InputControl, { ref: ref, id: inputId, type: "text", placeholder: placeholder, value: value, onChange: handleChange, onKeyDown: handleKeyDown, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": describedBy, className: cn("bg-background pl-8 pr-7", className), ...props }), value ? (_jsx("button", { type: "button", onClick: () => {
|
|
67
|
+
return (_jsxs(Field, { className: containerClassName, "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: inputId, className: cn(hideLabel && "sr-only", labelClassName), children: label }), _jsxs(SearchInputShell, { children: [_jsx(InputControl, { ref: ref, id: inputId, type: "text", placeholder: placeholder, value: value, onChange: handleChange, onKeyDown: handleKeyDown, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": describedBy, "data-selected": selected ? "true" : undefined, className: cn("bg-background pl-8 pr-7 data-[selected=true]:border-interactive data-[selected=true]:bg-highlight data-[selected=true]:ring-[3px] data-[selected=true]:ring-interactive/20", className), ...props }), value ? (_jsx("button", { type: "button", onClick: () => {
|
|
68
68
|
onValueChange("");
|
|
69
69
|
runSearch("");
|
|
70
70
|
}, disabled: disabled, className: "absolute right-1.5 top-1/2 -translate-y-1/2 cursor-pointer rounded-sm p-0.5 text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:pointer-events-none", "aria-label": "Clear search", children: _jsx(XIcon, { size: 14 }) })) : null] }), showDescription ? (_jsx(FieldDescription, { id: descriptionId, className: descriptionClassName, children: description })) : null, _jsx(FieldError, { id: errorId, className: errorClassName, children: error })] }));
|
package/dist/select-primitive.js
CHANGED
|
@@ -36,7 +36,7 @@ const SelectContent = React.forwardRef(({ className, children, header, position
|
|
|
36
36
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
37
37
|
const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, "data-slot": "select-label", className: cn("px-2 py-1.5 text-xs text-muted-foreground", className), ...props })));
|
|
38
38
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
39
|
-
const SelectItem = React.forwardRef(({ className, children, description, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, "data-slot": "select-item", className: cn("relative flex min-h-8 w-full cursor-pointer select-none items-center gap-1.5 rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-highlight data-[state=checked]:text-highlight-foreground data-[state=checked]:hover:bg-highlight/80 data-[state=checked]:hover:text-highlight-foreground data-[state=checked]:focus:bg-highlight/80 data-[state=checked]:focus:text-highlight-foreground data-[disabled]:
|
|
39
|
+
const SelectItem = React.forwardRef(({ className, children, description, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, "data-slot": "select-item", className: cn("relative flex min-h-8 w-full cursor-pointer select-none items-center gap-1.5 rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[state=checked]:bg-highlight data-[state=checked]:text-highlight-foreground data-[state=checked]:hover:bg-highlight/80 data-[state=checked]:hover:text-highlight-foreground data-[state=checked]:focus:bg-highlight/80 data-[state=checked]:focus:text-highlight-foreground data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:hover:bg-transparent data-[disabled]:hover:text-foreground", className), ...props, children: [_jsx("span", { "data-slot": "select-item-indicator", className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { children: _jsx(Check, { className: "h-4 w-4" }) }) }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx(SelectPrimitive.ItemText, { className: "break-words font-normal", children: children }), description ? (_jsx(Typography, { as: "span", variant: "caption", children: description })) : null] })] })));
|
|
40
40
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
41
41
|
const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Separator, { ref: ref, "data-slot": "select-separator", className: cn("-mx-1 my-1 h-px bg-border", className), ...props })));
|
|
42
42
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
package/dist/select.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface SelectOption {
|
|
|
5
5
|
value: string;
|
|
6
6
|
description?: React.ReactNode;
|
|
7
7
|
disabled?: boolean;
|
|
8
|
+
disabledReason?: React.ReactNode;
|
|
8
9
|
group?: string;
|
|
9
10
|
textValue?: string;
|
|
10
11
|
}
|
|
@@ -12,6 +13,7 @@ export interface SelectProps extends Pick<React.ComponentProps<typeof SelectRoot
|
|
|
12
13
|
label: React.ReactNode;
|
|
13
14
|
options: SelectOption[];
|
|
14
15
|
placeholder?: string;
|
|
16
|
+
size?: "default" | "comfortable";
|
|
15
17
|
description?: React.ReactNode;
|
|
16
18
|
error?: React.ReactNode;
|
|
17
19
|
invalid?: boolean;
|
|
@@ -28,5 +30,5 @@ export interface SelectProps extends Pick<React.ComponentProps<typeof SelectRoot
|
|
|
28
30
|
errorClassName?: string;
|
|
29
31
|
id?: string;
|
|
30
32
|
}
|
|
31
|
-
declare function Select({ label, options, placeholder, description, error, invalid, hideLabel, searchable, searchPlaceholder, searchEmptyMessage, searchInputAriaLabel, className, triggerClassName, contentClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, open, onOpenChange, ...props }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
declare function Select({ label, options, placeholder, size, description, error, invalid, hideLabel, searchable, searchPlaceholder, searchEmptyMessage, searchInputAriaLabel, className, triggerClassName, contentClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, open, onOpenChange, ...props }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
32
34
|
export { Select };
|
package/dist/select.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Field, FieldDescription, FieldError, FieldLabel } from "./field";
|
|
|
5
5
|
import { InputControl } from "./input-control";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
7
|
import { usePopoverTabExit } from "./popover-focus";
|
|
8
|
+
import { Tooltip } from "./tooltip";
|
|
8
9
|
import { SearchHighlight } from "./use-search-highlight";
|
|
9
10
|
import { SelectContent, SelectGroup, SelectItem, SelectLabel, SelectRoot, SelectSeparator, SelectTrigger, SelectValue, } from "./select-primitive";
|
|
10
11
|
function groupOptions(options) {
|
|
@@ -40,7 +41,7 @@ function renderHighlightedLabel(label, query) {
|
|
|
40
41
|
}
|
|
41
42
|
return label;
|
|
42
43
|
}
|
|
43
|
-
function Select({ label, options, placeholder = "Select an option", description, error, invalid = false, hideLabel = false, searchable = false, searchPlaceholder = "Search options...", searchEmptyMessage = "No options found.", searchInputAriaLabel = "Search options", className, triggerClassName, contentClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, open, onOpenChange, ...props }) {
|
|
44
|
+
function Select({ label, options, placeholder = "Select an option", size = "default", description, error, invalid = false, hideLabel = false, searchable = false, searchPlaceholder = "Search options...", searchEmptyMessage = "No options found.", searchInputAriaLabel = "Search options", className, triggerClassName, contentClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, open, onOpenChange, ...props }) {
|
|
44
45
|
const generatedId = React.useId();
|
|
45
46
|
const selectId = id !== null && id !== void 0 ? id : `select-${generatedId}`;
|
|
46
47
|
const triggerRef = React.useRef(null);
|
|
@@ -153,7 +154,8 @@ function Select({ label, options, placeholder = "Select an option", description,
|
|
|
153
154
|
searchable,
|
|
154
155
|
searchQuery,
|
|
155
156
|
]);
|
|
156
|
-
return (_jsxs(Field, { className: className, "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: selectId, className: cn(hideLabel && "sr-only", labelClassName), children: label }), _jsxs(SelectRoot, { disabled: disabled, open: isOpen, onOpenChange: handleOpenChange, ...props, children: [_jsx(SelectTrigger, { ref: triggerRef, id: selectId, className:
|
|
157
|
+
return (_jsxs(Field, { className: cn(size === "comfortable" && "gap-[8px]", className), "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: selectId, className: cn(size === "comfortable" && "text-[16px] leading-[24px]", hideLabel && "sr-only", labelClassName), children: label }), _jsxs(SelectRoot, { disabled: disabled, open: isOpen, onOpenChange: handleOpenChange, ...props, children: [_jsx(SelectTrigger, { ref: triggerRef, id: selectId, className: cn(size === "comfortable" &&
|
|
158
|
+
"h-[46px] px-[16px] py-[11px] text-[16px] leading-[24px]", triggerClassName), "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": [descriptionId, errorId].filter(Boolean).join(" ") || undefined, children: _jsx(SelectValue, { placeholder: placeholder }) }), _jsx(SelectContent, { ref: contentRef, className: contentClassName, onCloseAutoFocus: handleCloseAutoFocus, onKeyDownCapture: handleContentKeyDownCapture, header: searchable ? (_jsx(InputControl, { ref: searchInputRef, value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), placeholder: searchPlaceholder, "aria-label": searchInputAriaLabel, autoComplete: "off", className: "h-control border-0 bg-transparent px-2 py-0 text-sm shadow-none", onKeyDown: (event) => {
|
|
157
159
|
if (event.key === "ArrowDown" ||
|
|
158
160
|
event.key === "ArrowUp") {
|
|
159
161
|
event.preventDefault();
|
|
@@ -167,7 +169,10 @@ function Select({ label, options, placeholder = "Select an option", description,
|
|
|
167
169
|
event.stopPropagation();
|
|
168
170
|
} })) : undefined, viewportClassName: searchable ? "max-h-64" : undefined, children: hasVisibleOptions ? (optionGroups.map((group, groupIndex) => {
|
|
169
171
|
var _a;
|
|
170
|
-
return (_jsxs(React.Fragment, { children: [_jsxs(SelectGroup, { children: [group.group ? (_jsx(SelectLabel, { children: _jsx(SearchHighlight, { text: group.group, query: searchQuery }) })) : null, group.options.map((option) =>
|
|
171
|
-
|
|
172
|
+
return (_jsxs(React.Fragment, { children: [_jsxs(SelectGroup, { children: [group.group ? (_jsx(SelectLabel, { children: _jsx(SearchHighlight, { text: group.group, query: searchQuery }) })) : null, group.options.map((option) => {
|
|
173
|
+
const optionItem = (_jsx(SelectItem, { value: option.value, disabled: option.disabled, textValue: getOptionTextValue(option), description: option.description, children: renderHighlightedLabel(option.label, searchQuery) }));
|
|
174
|
+
return option.disabled && option.disabledReason ? (_jsx(Tooltip, { content: option.disabledReason, side: "right", children: optionItem }, option.value)) : (_jsx(React.Fragment, { children: optionItem }, option.value));
|
|
175
|
+
})] }), groupIndex < optionGroups.length - 1 ? (_jsx(SelectSeparator, {})) : null] }, (_a = group.group) !== null && _a !== void 0 ? _a : `group-${groupIndex}`));
|
|
176
|
+
})) : (_jsx("div", { className: "px-2.5 py-1.5 text-sm text-muted-foreground", children: searchEmptyMessage })) })] }), showDescription ? (_jsx(FieldDescription, { id: descriptionId, className: cn(size === "comfortable" && "text-[14px] leading-[20px]", descriptionClassName), children: description })) : null, _jsx(FieldError, { id: errorId, className: errorClassName, children: error })] }));
|
|
172
177
|
}
|
|
173
178
|
export { Select };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type StatusDotVariant = "default" | "muted" | "success" | "warning" | "info" | "destructive";
|
|
3
|
+
export type StatusDotSize = "sm" | "md" | "lg";
|
|
4
|
+
export interface StatusDotProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
|
|
5
|
+
/** Semantic colour of the status. */
|
|
6
|
+
variant?: StatusDotVariant;
|
|
7
|
+
/** Diameter of the dot. */
|
|
8
|
+
size?: StatusDotSize;
|
|
9
|
+
/** Accessible name. Omit when nearby text already describes the status. */
|
|
10
|
+
label?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const StatusDot: React.ForwardRefExoticComponent<StatusDotProps & React.RefAttributes<HTMLSpanElement>>;
|
|
13
|
+
export { StatusDot };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "./lib/utils";
|
|
4
|
+
const sizeClasses = {
|
|
5
|
+
sm: "size-[6px]",
|
|
6
|
+
md: "size-[8px]",
|
|
7
|
+
lg: "size-[10px]",
|
|
8
|
+
};
|
|
9
|
+
const variantClasses = {
|
|
10
|
+
default: "bg-primary",
|
|
11
|
+
muted: "bg-muted-foreground",
|
|
12
|
+
success: "bg-[hsl(var(--nea-green-400))]",
|
|
13
|
+
warning: "bg-[hsl(var(--nea-amber-400))]",
|
|
14
|
+
info: "bg-[hsl(var(--nea-blue-400))]",
|
|
15
|
+
destructive: "bg-[hsl(var(--nea-red-400))]",
|
|
16
|
+
};
|
|
17
|
+
const StatusDot = React.forwardRef(({ variant = "default", size = "md", label, className, ...props }, ref) => (_jsx("span", { ref: ref, "data-slot": "status-dot", role: label ? "img" : undefined, "aria-label": label, "aria-hidden": label ? undefined : true, className: cn("inline-block shrink-0 rounded-full", sizeClasses[size], variantClasses[variant], className), ...props })));
|
|
18
|
+
StatusDot.displayName = "StatusDot";
|
|
19
|
+
export { StatusDot };
|
package/dist/styles.css
CHANGED
|
@@ -413,25 +413,6 @@
|
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
@layer components {
|
|
416
|
-
[data-slot="routing-timeline"] {
|
|
417
|
-
--routing-timeline-background: var(--layout-right-panel-background);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
[data-slot="routing-timeline-list"]::before {
|
|
421
|
-
position: absolute;
|
|
422
|
-
top: var(--space-2);
|
|
423
|
-
bottom: var(--space-0);
|
|
424
|
-
left: calc(var(--space-3) / 2);
|
|
425
|
-
width: 1px;
|
|
426
|
-
content: "";
|
|
427
|
-
transform: translateX(-50%);
|
|
428
|
-
background: hsl(var(--border));
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
[data-slot="routing-timeline-marker"] {
|
|
432
|
-
box-shadow: 0 0 0 var(--space-1) hsl(var(--routing-timeline-background));
|
|
433
|
-
}
|
|
434
|
-
|
|
435
416
|
[data-slot="routing-timeline-event-card"] {
|
|
436
417
|
container-type: inline-size;
|
|
437
418
|
}
|
|
@@ -2,6 +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 { FilterIcon } from "./animated-icons";
|
|
5
|
+
import { buttonVariants } from "./button";
|
|
5
6
|
import { DateInput } from "./date-input";
|
|
6
7
|
import { FilterPopover } from "./filter-popover";
|
|
7
8
|
import { FilterToggle, filterToggleVariants, } from "./filter-toggle";
|
|
@@ -29,7 +30,7 @@ function getOptionsFilterSummary(filter) {
|
|
|
29
30
|
}
|
|
30
31
|
return ((_c = (_b = filter.options.find((option) => option.value === filter.values[0])) === null || _b === void 0 ? void 0 : _b.label) !== null && _c !== void 0 ? _c : filter.values[0]);
|
|
31
32
|
}
|
|
32
|
-
const TableFilterTrigger = React.forwardRef(({ active, disabled, label, children, ...props }, ref) => (_jsx(FilterToggle, { ref: ref, type: "button", disabled: disabled, selected: active, "aria-label": `Filter by ${label}${active ? ", active" : ""}`, className: cn("h-
|
|
33
|
+
const TableFilterTrigger = React.forwardRef(({ active, disabled, label, children, ...props }, ref) => (_jsx(FilterToggle, { ref: ref, type: "button", disabled: disabled, selected: active, "aria-label": `Filter by ${label}${active ? ", active" : ""}`, className: cn("h-8 w-full min-w-0 justify-start overflow-hidden px-2 text-sm font-normal", !active &&
|
|
33
34
|
"bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground"), icon: _jsx(FilterIcon, { "aria-hidden": "true", className: "shrink-0", size: 16 }), ...props, children: _jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: children }) })));
|
|
34
35
|
TableFilterTrigger.displayName = "TableFilterTrigger";
|
|
35
36
|
function TextColumnFilter({ filter, label, }) {
|
|
@@ -71,15 +72,16 @@ function DateColumnFilter({ filter, label, }) {
|
|
|
71
72
|
var _a, _b;
|
|
72
73
|
const active = isTableColumnFilterActive(filter);
|
|
73
74
|
const accessibleLabel = (_a = filter.label) !== null && _a !== void 0 ? _a : label;
|
|
74
|
-
return (_jsx(DateInput, { label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick a date", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(
|
|
75
|
-
"border-
|
|
75
|
+
return (_jsx(DateInput, { label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick a date", popoverTitle: `Filter by ${accessibleLabel}`, disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(buttonVariants({ variant: "outline", size: "sm" }), "h-8 w-full min-w-0 justify-start font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", active
|
|
76
|
+
? "border-transparent bg-highlight text-highlight-foreground hover:bg-highlight/80"
|
|
77
|
+
: "bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
76
78
|
}
|
|
77
79
|
function DateRangeColumnFilter({ filter, label, }) {
|
|
78
80
|
var _a, _b;
|
|
79
81
|
const active = isTableColumnFilterActive(filter);
|
|
80
82
|
const accessibleLabel = (_a = filter.label) !== null && _a !== void 0 ? _a : label;
|
|
81
|
-
return (_jsx(DateInput, { mode: "range", label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick date range", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-
|
|
82
|
-
"
|
|
83
|
+
return (_jsx(DateInput, { mode: "range", label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick date range", popoverTitle: `Filter by ${accessibleLabel}`, disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-8 w-full min-w-0 justify-start border-0 text-sm font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", !active &&
|
|
84
|
+
"bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
83
85
|
}
|
|
84
86
|
function TableColumnFilterControl({ filter, label, }) {
|
|
85
87
|
if (filter.type === "text") {
|
package/dist/table.d.ts
CHANGED
|
@@ -123,6 +123,12 @@ export interface TableRowExpansionProps<Row> {
|
|
|
123
123
|
/** Accessible label for a row's expansion toggle. */
|
|
124
124
|
getToggleLabel?: (row: Row, rowIndex: number, expanded: boolean) => string;
|
|
125
125
|
}
|
|
126
|
+
export interface TableRowIndicatorProps<Row> {
|
|
127
|
+
/** Renders a compact status marker in a fixed leading column for each row. */
|
|
128
|
+
render: (row: Row, rowIndex: number) => React.ReactNode;
|
|
129
|
+
/** Accessible name for the otherwise visually empty indicator column header. */
|
|
130
|
+
headerLabel?: string;
|
|
131
|
+
}
|
|
126
132
|
interface SortableTableHeadProps extends Omit<React.ThHTMLAttributes<HTMLTableCellElement>, "children" | "style"> {
|
|
127
133
|
field: string;
|
|
128
134
|
children: React.ReactNode;
|
|
@@ -194,6 +200,8 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
|
|
|
194
200
|
emptyStateMinHeight?: React.CSSProperties["minHeight"];
|
|
195
201
|
/** When true, applies alternating row backgrounds for easier scanning. */
|
|
196
202
|
striped?: boolean;
|
|
203
|
+
/** Adds a compact, non-reorderable status column at the leading edge of every row. */
|
|
204
|
+
rowIndicator?: TableRowIndicatorProps<Row>;
|
|
197
205
|
/** Adds a disclosure column and full-width expandable content for nested tables or row details. */
|
|
198
206
|
rowExpansion?: TableRowExpansionProps<Row>;
|
|
199
207
|
/** When true, non-sticky header cells become draggable for column reordering. */
|
|
@@ -201,5 +209,5 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
|
|
|
201
209
|
/** Called with the new ordered column key array after a drag-and-drop reorder. */
|
|
202
210
|
onColumnOrderChange?: (columnKeys: string[]) => void;
|
|
203
211
|
}
|
|
204
|
-
declare function Table<Row>({ accessibleLabel, columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingLabel, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowExpansion, reorderableColumns, onColumnOrderChange, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
212
|
+
declare function Table<Row>({ accessibleLabel, columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingLabel, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowIndicator, rowExpansion, reorderableColumns, onColumnOrderChange, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
205
213
|
export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, SortableTableHead, TableRowSkeleton, };
|
package/dist/table.js
CHANGED
|
@@ -19,6 +19,7 @@ const DEFAULT_COLUMN_RESIZE_MIN_WIDTH = 64;
|
|
|
19
19
|
const DEFAULT_COLUMN_RESIZE_START_WIDTH = 160;
|
|
20
20
|
const DEFAULT_COLUMN_RESIZE_MAX_WIDTH = 1200;
|
|
21
21
|
const COLUMN_RESIZE_KEYBOARD_STEP = 16;
|
|
22
|
+
const TABLE_ROW_INDICATOR_COLUMN_WIDTH = 32;
|
|
22
23
|
const TABLE_EXPANSION_COLUMN_WIDTH = 48;
|
|
23
24
|
const TABLE_MIN_WIDTH_CSS_VAR = "--table-min-width";
|
|
24
25
|
const DEFAULT_TABLE_MIN_HEIGHT = "var(--table-min-height, var(--app-table-min-height, 24rem))";
|
|
@@ -159,7 +160,7 @@ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("tf
|
|
|
159
160
|
TableFooter.displayName = "TableFooter";
|
|
160
161
|
const TableRow = React.forwardRef(({ className, ...props }, ref) => (_jsx("tr", { ref: ref, className: cn("border-b border-[hsl(var(--table-border))] bg-card text-card-foreground transition-colors data-[state=selected]:bg-muted", className), ...props })));
|
|
161
162
|
TableRow.displayName = "TableRow";
|
|
162
|
-
const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-
|
|
163
|
+
const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-[4px] text-left align-middle font-medium text-instructional [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
163
164
|
style: {
|
|
164
165
|
...style,
|
|
165
166
|
fontWeight: 500,
|
|
@@ -170,7 +171,7 @@ const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidt
|
|
|
170
171
|
treatWidthAsMinWidth,
|
|
171
172
|
}), ...props })));
|
|
172
173
|
TableHead.displayName = "TableHead";
|
|
173
|
-
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-
|
|
174
|
+
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-[4px] align-middle text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
174
175
|
style,
|
|
175
176
|
width,
|
|
176
177
|
minWidth,
|
|
@@ -178,7 +179,7 @@ const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidt
|
|
|
178
179
|
treatWidthAsMinWidth,
|
|
179
180
|
}), ...props })));
|
|
180
181
|
TableCell.displayName = "TableCell";
|
|
181
|
-
const TableRowHeader = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, scope = "row", ...props }, ref) => (_jsx("th", { ref: ref, scope: scope, className: cn("h-12 px-4 py-
|
|
182
|
+
const TableRowHeader = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, scope = "row", ...props }, ref) => (_jsx("th", { ref: ref, scope: scope, className: cn("h-12 px-4 py-[4px] text-left align-middle font-medium text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
182
183
|
style,
|
|
183
184
|
width,
|
|
184
185
|
minWidth,
|
|
@@ -240,7 +241,7 @@ function SkeletonCell({ config }) {
|
|
|
240
241
|
return (_jsx(TableCell, { children: _jsx(SkeletonBlock, { width: config.width, height: config.height, badge: config.badge }) }));
|
|
241
242
|
}
|
|
242
243
|
function TableRowSkeleton({ columns, rows = 1 }) {
|
|
243
|
-
return (_jsx(_Fragment, { children: Array.from({ length: rows }).map((_, rowIndex) => (_jsx(TableRow, { children: columns.map((config, columnIndex) => (_jsx(SkeletonCell, { config: config }, columnIndex))) }, rowIndex))) }));
|
|
244
|
+
return (_jsx(_Fragment, { children: Array.from({ length: rows }).map((_, rowIndex) => (_jsx(TableRow, { "data-slot": "table-skeleton-row", className: "h-12", children: columns.map((config, columnIndex) => (_jsx(SkeletonCell, { config: config }, columnIndex))) }, rowIndex))) }));
|
|
244
245
|
}
|
|
245
246
|
export const TABLE_SKELETON_PRESETS = {
|
|
246
247
|
text: (width = "8rem", height = "1rem") => ({
|
|
@@ -278,7 +279,7 @@ const SortableTableHead = React.forwardRef(function SortableTableHead({ field, c
|
|
|
278
279
|
? currentSortDirection === "asc"
|
|
279
280
|
? "ascending"
|
|
280
281
|
: "descending"
|
|
281
|
-
: undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), style: style, wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, ...rest, children: [gripIcon, _jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
|
|
282
|
+
: undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), style: style, wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, ...rest, children: [gripIcon, _jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-auto min-h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
|
|
282
283
|
? "max-w-full whitespace-normal text-left"
|
|
283
284
|
: "whitespace-nowrap", align === "right" && "ml-auto justify-end", align === "center" && "mx-auto justify-center"), style: { font: "inherit", color: "inherit", fontWeight: 500 }, "aria-label": `Sort by ${resolvedSortLabel}`, children: [_jsx("span", { className: cn("min-w-0", containOverflow && !allowWrap && "truncate", containOverflow &&
|
|
284
285
|
allowWrap &&
|
|
@@ -398,8 +399,10 @@ function getColumnPairResizeRange(column, nextColumn, columnWidths) {
|
|
|
398
399
|
maxWidth: Math.round(currentWidth + maxDelta),
|
|
399
400
|
};
|
|
400
401
|
}
|
|
401
|
-
function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingLabel = "Loading table data", loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowExpansion, reorderableColumns = false, onColumnOrderChange, onScroll, style, ...props }) {
|
|
402
|
+
function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingLabel = "Loading table data", loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowIndicator, rowExpansion, reorderableColumns = false, onColumnOrderChange, onScroll, style, ...props }) {
|
|
403
|
+
var _a;
|
|
402
404
|
const visibleColumns = getVisibleColumns(columns, visibleColumnKeys);
|
|
405
|
+
const hasRowIndicatorColumn = Boolean(rowIndicator);
|
|
403
406
|
const hasExpansionColumn = Boolean(rowExpansion);
|
|
404
407
|
const hasColumnFilters = visibleColumns.some((column) => column.filter);
|
|
405
408
|
const isGrowResizeMode = columnResizeMode === "grow";
|
|
@@ -413,6 +416,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
413
416
|
const hasResolvedColumnWidths = hasColumnWidthOverrides(resolvedColumnWidths);
|
|
414
417
|
const growTableMinWidth = isGrowResizeMode
|
|
415
418
|
? getTableMinWidth(visibleColumns, resolvedColumnWidths) +
|
|
419
|
+
(hasRowIndicatorColumn ? TABLE_ROW_INDICATOR_COLUMN_WIDTH : 0) +
|
|
416
420
|
(hasExpansionColumn ? TABLE_EXPANSION_COLUMN_WIDTH : 0)
|
|
417
421
|
: undefined;
|
|
418
422
|
const resolvedMinHeight = minHeight !== null && minHeight !== void 0 ? minHeight : (centerEmptyState ? DEFAULT_TABLE_MIN_HEIGHT : undefined);
|
|
@@ -673,7 +677,11 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
673
677
|
}, ...props, children: [_jsxs(TableRoot, { "aria-busy": loading, className: cn(shouldUseFixedLayout && "table-fixed", isGrowResizeMode &&
|
|
674
678
|
(hasResolvedColumnWidths
|
|
675
679
|
? "w-[var(--table-min-width)]"
|
|
676
|
-
: "min-w-[var(--table-min-width)]"), tableClassName), children: [_jsx(TableCaption, { className: caption ? undefined : "sr-only !m-0", children: caption !== null && caption !== void 0 ? caption : accessibleLabel }), _jsxs("colgroup", { children: [
|
|
680
|
+
: "min-w-[var(--table-min-width)]"), tableClassName), children: [_jsx(TableCaption, { className: caption ? undefined : "sr-only !m-0", children: caption !== null && caption !== void 0 ? caption : accessibleLabel }), _jsxs("colgroup", { children: [hasRowIndicatorColumn ? (_jsx("col", { style: {
|
|
681
|
+
width: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
682
|
+
minWidth: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
683
|
+
maxWidth: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
684
|
+
} })) : null, hasExpansionColumn ? (_jsx("col", { style: {
|
|
677
685
|
width: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
678
686
|
minWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
679
687
|
maxWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
@@ -686,14 +694,17 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
686
694
|
minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
|
|
687
695
|
maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
|
|
688
696
|
treatWidthAsMinWidth: !isColumnResizingEnabled,
|
|
689
|
-
}) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", scope: "col", className: "w-12 px-2" })) : null, renderColumnHeaders(visibleColumns)] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasExpansionColumn ? (_jsx(TableCell, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "w-12 px-2" })) : null, visibleColumns.map((column) => {
|
|
697
|
+
}) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasRowIndicatorColumn ? (_jsx(TableHead, { "data-slot": "table-row-indicator-head", "aria-label": (_a = rowIndicator === null || rowIndicator === void 0 ? void 0 : rowIndicator.headerLabel) !== null && _a !== void 0 ? _a : "Row status", scope: "col", className: "w-8 px-2" })) : null, hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", scope: "col", className: "w-12 px-2" })) : null, renderColumnHeaders(visibleColumns)] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasRowIndicatorColumn ? (_jsx(TableCell, { "data-slot": "table-row-indicator-filter-cell", "aria-hidden": "true", className: "h-11 w-8 px-2 py-[4px]" })) : null, hasExpansionColumn ? (_jsx(TableCell, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "h-11 w-12 px-2 py-[4px]" })) : null, visibleColumns.map((column) => {
|
|
690
698
|
const columnWidth = getRenderedColumnWidth({
|
|
691
699
|
column,
|
|
692
700
|
columnWidths: resolvedColumnWidths,
|
|
693
701
|
resizing: isColumnResizingEnabled,
|
|
694
702
|
});
|
|
695
|
-
return (_jsx(TableCell, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-
|
|
703
|
+
return (_jsx(TableCell, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-[4px] font-normal", stickyClassName(column.sticky, "filter", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.filterClassName), children: column.filter ? (_jsx("div", { "data-slot": "table-filter-control", className: "absolute inset-x-2 inset-y-[4px] min-w-0", children: _jsx(TableColumnFilterControl, { filter: column.filter, label: getColumnResizeLabel(column) }) })) : null }, column.key));
|
|
696
704
|
})] })) : null] }), _jsx(TableBody, { "aria-hidden": loading ? "true" : undefined, children: loading ? (_jsx(TableRowSkeleton, { rows: loadingRows, columns: [
|
|
705
|
+
...(hasRowIndicatorColumn
|
|
706
|
+
? [{ width: "0.5rem", height: "0.5rem", badge: true }]
|
|
707
|
+
: []),
|
|
697
708
|
...(hasExpansionColumn
|
|
698
709
|
? [{ width: "1rem", height: "1rem" }]
|
|
699
710
|
: []),
|
|
@@ -715,7 +726,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
715
726
|
!resolvedTone &&
|
|
716
727
|
"bg-[hsl(var(--table-row-striped-background))]", tableRowToneClassName(resolvedTone), typeof rowClassName === "function"
|
|
717
728
|
? rowClassName(row, rowIndex)
|
|
718
|
-
: rowClassName), children: [hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": isExpanded ? expandedContentId : undefined, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
|
|
729
|
+
: rowClassName), children: [hasRowIndicatorColumn ? (_jsx(TableCell, { "data-slot": "table-row-indicator-cell", className: "w-8 px-2 text-center", children: rowIndicator === null || rowIndicator === void 0 ? void 0 : rowIndicator.render(row, rowIndex) })) : null, hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": isExpanded ? expandedContentId : undefined, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
|
|
719
730
|
event.stopPropagation();
|
|
720
731
|
toggleExpandedRow(rowKey);
|
|
721
732
|
}, className: "inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(ChevronRight, { "aria-hidden": "true", className: cn("h-4 w-4 transition-transform duration-150", isExpanded && "rotate-90") }) })) : null })) : null, visibleColumns.map((column) => {
|
|
@@ -733,8 +744,11 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
733
744
|
: TableCell;
|
|
734
745
|
return (_jsx(Cell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
|
|
735
746
|
})] }), isExpanded ? (_jsx(TableRow, { id: expandedContentId, "data-slot": "table-expanded-row", className: "bg-[hsl(var(--table-row-striped-background))] hover:bg-[hsl(var(--table-row-striped-background))]", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
747
|
+
(hasRowIndicatorColumn ? 1 : 0) +
|
|
736
748
|
(hasExpansionColumn ? 1 : 0), 1), className: "h-auto whitespace-normal p-4", children: rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.renderExpandedContent(row, rowIndex) }) })) : null] }, rowKey));
|
|
737
|
-
})) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
749
|
+
})) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
750
|
+
(hasRowIndicatorColumn ? 1 : 0) +
|
|
751
|
+
(hasExpansionColumn ? 1 : 0), 1), className: "p-6", children: resolvedEmptyState }) })) })] }), _jsx("div", { role: "status", className: "sr-only", children: loading ? loadingLabel : null })] }));
|
|
738
752
|
const reorderableContainer = reorderableColumns ? (_jsx(DndContext, { sensors: columnReorderSensors, collisionDetection: closestCenter, onDragEnd: handleColumnDragEnd, children: _jsx(SortableContext, { items: reorderableColumnIds, strategy: horizontalListSortingStrategy, children: container }) })) : (container);
|
|
739
753
|
if (!pagination) {
|
|
740
754
|
return (_jsxs("div", { className: "space-y-4", children: [toolbar, reorderableContainer] }));
|
package/dist/tabs.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export interface TabsProps extends Omit<React.ComponentPropsWithoutRef<typeof Ta
|
|
|
65
65
|
defaultValue?: string;
|
|
66
66
|
value?: string;
|
|
67
67
|
onValueChange?: (value: string) => void;
|
|
68
|
-
size?: "default" | "compact";
|
|
68
|
+
size?: "default" | "compact" | "comfortable";
|
|
69
69
|
renderPanels?: boolean;
|
|
70
70
|
listWrapperClassName?: string;
|
|
71
71
|
listClassName?: string;
|
package/dist/tabs.js
CHANGED
|
@@ -144,13 +144,15 @@ function Tabs({ items, defaultValue, value, onValueChange, size = "default", ren
|
|
|
144
144
|
if (!items.length) {
|
|
145
145
|
return null;
|
|
146
146
|
}
|
|
147
|
-
return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
148
|
-
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm",
|
|
149
|
-
"min-h-
|
|
147
|
+
return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", size === "comfortable" && "rounded-[10px]", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
148
|
+
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", size === "comfortable" &&
|
|
149
|
+
"min-h-[40px] rounded-md px-[12px] py-[8px] text-[16px]", triggerClassName) }, item.value)) : (_jsx(TabTriggerItem, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
150
|
+
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", size === "comfortable" &&
|
|
151
|
+
"min-h-[40px] rounded-md px-[12px] py-[8px] text-[16px]", triggerClassName) }, item.value))) }) }), renderPanels
|
|
150
152
|
? items.map((item) => (_jsx(TabsContent, { value: item.value, className: cn("pt-4", panelClassName), children: item.content }, item.value)))
|
|
151
153
|
: null] }));
|
|
152
154
|
}
|
|
153
155
|
function SubTabs({ className, listWrapperClassName, listClassName, triggerClassName, panelClassName, ...props }) {
|
|
154
|
-
return (_jsx(Tabs, { className: cn("space-y-0", className), listWrapperClassName: cn("min-w-0 overflow-x-auto", listWrapperClassName), listClassName: cn("w-full min-w-max justify-start overflow-visible rounded-none border-0 border-b border-[hsl(var(--tab-list-border))] bg-transparent p-0", listClassName), triggerClassName: cn("min-h-9 rounded-none border-b-
|
|
156
|
+
return (_jsx(Tabs, { className: cn("space-y-0", className), listWrapperClassName: cn("min-w-0 overflow-x-auto", listWrapperClassName), listClassName: cn("w-full min-w-max justify-start overflow-visible rounded-none border-0 border-b border-[hsl(var(--tab-list-border))] bg-transparent p-0", listClassName), triggerClassName: cn("min-h-9 rounded-none border-b-[3px] border-transparent bg-transparent px-3 py-2 text-[hsl(var(--tab-trigger-foreground))] shadow-none focus-visible:ring-inset focus-visible:ring-offset-0 data-[state=inactive]:hover:bg-[hsl(var(--tab-trigger-hover-background))] data-[state=active]:border-[hsl(var(--tab-indicator))] data-[state=active]:bg-transparent data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:shadow-none", triggerClassName), panelClassName: cn("pt-4", panelClassName), ...props }));
|
|
155
157
|
}
|
|
156
158
|
export { Tabs, SubTabs, TabsRoot, TabsList, TabsTrigger, TabsContent, TabWithDropdown, };
|
package/dist/textarea.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
declare const TextareaControl: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
|
|
3
3
|
export interface TextareaProps extends Omit<React.ComponentProps<typeof TextareaControl>, "className"> {
|
|
4
4
|
label: React.ReactNode;
|
|
5
|
+
size?: "default" | "comfortable";
|
|
5
6
|
description?: React.ReactNode;
|
|
6
7
|
error?: React.ReactNode;
|
|
7
8
|
invalid?: boolean;
|