@neasg/design-system 0.4.7 → 0.4.9
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/README.md +121 -0
- package/dist/alert.d.ts +21 -2
- package/dist/alert.js +10 -3
- package/dist/avatar.d.ts +5 -2
- package/dist/avatar.js +76 -8
- package/dist/back-button.d.ts +2 -0
- package/dist/back-button.js +1 -1
- package/dist/badge.d.ts +3 -2
- package/dist/badge.js +9 -3
- package/dist/breadcrumb.js +2 -1
- package/dist/button.d.ts +1 -1
- package/dist/button.js +13 -10
- package/dist/calendar.js +10 -9
- package/dist/card.d.ts +29 -1
- package/dist/card.js +61 -7
- package/dist/checkbox.d.ts +2 -0
- package/dist/checkbox.js +2 -2
- package/dist/close-button.d.ts +6 -0
- package/dist/close-button.js +8 -0
- package/dist/collapsible.d.ts +7 -1
- package/dist/collapsible.js +2 -2
- package/dist/command-search.d.ts +16 -1
- package/dist/command-search.js +42 -16
- package/dist/command.js +3 -3
- package/dist/copy-button.d.ts +3 -1
- package/dist/copy-button.js +4 -2
- package/dist/count-badge.d.ts +3 -1
- package/dist/count-badge.js +10 -5
- package/dist/date-input.d.ts +18 -3
- package/dist/date-input.js +94 -21
- package/dist/dialog-primitive.js +4 -3
- package/dist/draggable-tabs.d.ts +7 -0
- package/dist/draggable-tabs.js +6 -5
- package/dist/drawer.js +2 -2
- package/dist/dropdown-button.d.ts +18 -0
- package/dist/dropdown-button.js +31 -0
- package/dist/edit-button.d.ts +10 -0
- package/dist/edit-button.js +7 -0
- package/dist/editable-table.d.ts +3 -1
- package/dist/editable-table.js +25 -12
- package/dist/field.d.ts +2 -2
- package/dist/field.js +4 -3
- package/dist/file-upload-status-toast.d.ts +28 -0
- package/dist/file-upload-status-toast.js +136 -0
- package/dist/file-upload.js +8 -7
- package/dist/filter-popover.d.ts +37 -0
- package/dist/filter-popover.js +73 -0
- package/dist/filter-toggle.js +2 -2
- package/dist/index.d.ts +45 -14
- package/dist/index.js +19 -4
- package/dist/input-control.d.ts +3 -2
- package/dist/input-control.js +3 -2
- package/dist/label-value-grid.d.ts +4 -2
- package/dist/label-value-grid.js +7 -6
- package/dist/label-value.js +3 -1
- package/dist/layout-right-panel-edge.d.ts +6 -0
- package/dist/layout-right-panel-edge.js +6 -0
- package/dist/layout.d.ts +77 -5
- package/dist/layout.js +439 -35
- package/dist/lib/date-utils.d.ts +10 -2
- package/dist/lib/date-utils.js +91 -11
- package/dist/lib/utils.js +8 -1
- package/dist/link.js +2 -2
- package/dist/message-item.d.ts +62 -0
- package/dist/message-item.js +148 -0
- package/dist/multi-select.js +31 -5
- package/dist/notification.d.ts +82 -0
- package/dist/notification.js +121 -0
- package/dist/otp-input.js +1 -1
- package/dist/page-header.js +1 -1
- package/dist/page-section.d.ts +2 -1
- package/dist/page-section.js +4 -3
- package/dist/pagination.js +2 -2
- package/dist/popover-menu.d.ts +23 -1
- package/dist/popover-menu.js +75 -5
- package/dist/popover-primitive.js +1 -1
- package/dist/progress.d.ts +5 -2
- package/dist/progress.js +6 -3
- package/dist/radio-group.d.ts +21 -0
- package/dist/radio-group.js +41 -0
- package/dist/rich-text-editor.d.ts +56 -0
- package/dist/rich-text-editor.js +394 -0
- package/dist/routing-timeline.d.ts +22 -0
- package/dist/routing-timeline.js +58 -0
- package/dist/scroll-hint.d.ts +8 -0
- package/dist/scroll-hint.js +7 -0
- package/dist/search-input-shell.js +1 -1
- package/dist/search-input.js +2 -2
- package/dist/section-nav.js +4 -4
- package/dist/select-primitive.js +3 -3
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/styles.css +235 -57
- package/dist/table-column-visibility.d.ts +21 -0
- package/dist/table-column-visibility.js +74 -0
- package/dist/table-toolbar.js +1 -1
- package/dist/table.d.ts +12 -1
- package/dist/table.js +67 -33
- package/dist/tabs.d.ts +14 -3
- package/dist/tabs.js +60 -6
- package/dist/tailwind-preset.js +46 -0
- package/dist/task-mode-shell.d.ts +24 -0
- package/dist/task-mode-shell.js +110 -0
- package/dist/textarea.js +2 -1
- package/dist/theme-switcher.d.ts +28 -0
- package/dist/theme-switcher.js +27 -0
- package/dist/theme.d.ts +167 -0
- package/dist/theme.js +112 -0
- package/dist/toaster.js +5 -4
- package/dist/tooltip.js +1 -1
- package/dist/typography.d.ts +1 -1
- package/dist/typography.js +5 -5
- package/dist/workspace-header.d.ts +13 -0
- package/dist/workspace-header.js +11 -0
- package/package.json +15 -1
package/dist/card.js
CHANGED
|
@@ -1,16 +1,70 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "./lib/utils";
|
|
5
5
|
import { Skeleton } from "./skeleton";
|
|
6
6
|
import { Typography } from "./typography";
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const cardGridColumns = {
|
|
8
|
+
1: "grid-cols-1",
|
|
9
|
+
2: "sm:grid-cols-2",
|
|
10
|
+
3: "md:grid-cols-2 lg:grid-cols-3",
|
|
11
|
+
4: "sm:grid-cols-2 xl:grid-cols-4",
|
|
12
|
+
};
|
|
13
|
+
const cardSplitGridColumns = {
|
|
14
|
+
lg: {
|
|
15
|
+
sm: "lg:grid-cols-[minmax(0,1fr)_18rem]",
|
|
16
|
+
md: "lg:grid-cols-[minmax(0,1fr)_20rem]",
|
|
17
|
+
lg: "lg:grid-cols-[minmax(0,1fr)_22rem]",
|
|
18
|
+
},
|
|
19
|
+
xl: {
|
|
20
|
+
sm: "xl:grid-cols-[minmax(0,1fr)_18rem]",
|
|
21
|
+
md: "xl:grid-cols-[minmax(0,1fr)_20rem]",
|
|
22
|
+
lg: "xl:grid-cols-[minmax(0,1fr)_22rem]",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const Card = React.forwardRef(({ title, description, variant = "default", size = "default", stat, subMetric, footer, active, accent, loading = false, children, className, onClick, onKeyDown, role, tabIndex, ...props }, ref) => {
|
|
26
|
+
const interactive = Boolean(onClick);
|
|
27
|
+
const hasStat = stat !== undefined;
|
|
28
|
+
const handleKeyDown = (event) => {
|
|
29
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
|
|
30
|
+
if (event.defaultPrevented ||
|
|
31
|
+
!interactive ||
|
|
32
|
+
!onClick ||
|
|
33
|
+
(event.key !== "Enter" && event.key !== " ")) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
onClick(event);
|
|
38
|
+
};
|
|
39
|
+
const renderedTitle = React.isValidElement(title) ? (title) : (_jsx(Typography, { as: "p", variant: hasStat ? "caption" : "body", color: variant === "gradient" ? "inherit" : hasStat ? "muted" : "foreground", className: cn(hasStat && "font-medium", !hasStat && "font-semibold", variant === "gradient" && "opacity-80"), children: title }));
|
|
9
40
|
const renderedDescription = description == null ? null : React.isValidElement(description) ? (description) : (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-70" : undefined, children: description }));
|
|
10
|
-
return (_jsxs("div", { ref: ref, onClick: onClick, className: cn("rounded-
|
|
11
|
-
"border-
|
|
41
|
+
return (_jsxs("div", { ref: ref, onClick: onClick, onKeyDown: handleKeyDown, role: role !== null && role !== void 0 ? role : (interactive ? "button" : undefined), tabIndex: tabIndex !== null && tabIndex !== void 0 ? tabIndex : (interactive ? 0 : undefined), className: cn("rounded-surface border border-[hsl(var(--card-border))] text-card-foreground", variant === "default" && "bg-card", variant === "elevated" && "bg-card shadow-sm", variant === "gradient" &&
|
|
42
|
+
"border-[hsl(var(--card-gradient-border))]/30 bg-gradient-to-br from-[hsl(var(--card-gradient-from))] to-[hsl(var(--card-gradient-to))] text-[hsl(var(--card-gradient-foreground))]", active && "border-primary bg-primary/[0.04] ring-1 ring-primary/20", accent === "primary" &&
|
|
43
|
+
"border-[hsl(var(--card-border))] shadow-[inset_4px_0_0_0_hsl(var(--primary))]", interactive &&
|
|
44
|
+
"cursor-pointer transition-[border-color,background-color,box-shadow] hover:border-primary/50 hover:bg-primary/5 hover:shadow-md focus-visible:border-primary/50 focus-visible:bg-primary/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", className), ...props, children: [_jsxs("div", { className: cn("flex flex-col gap-2", size === "default" && "p-4", size === "compact" && "p-3"), children: [loading ? (_jsx(Skeleton, { className: "h-3.5 w-24" })) : (renderedTitle), loading
|
|
12
45
|
? description != null && _jsx(Skeleton, { className: "h-5 w-40" })
|
|
13
|
-
: renderedDescription, loading ? (stat !== undefined && _jsx(Skeleton, { className: "h-8 w-20" })) : stat ? (_jsx(Typography, { as: "p", variant: "title", color: variant === "gradient" ? "inherit" : undefined, children: stat })) : null, loading ? (subMetric !== undefined && _jsx(Skeleton, { className: "h-5 w-28" })) : subMetric ? (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-80" : undefined, children: subMetric })) : null] }), children ? (_jsx("div", { className: cn(size === "default" && "p-
|
|
46
|
+
: renderedDescription, loading ? (stat !== undefined && _jsx(Skeleton, { className: "h-8 w-20" })) : stat ? (_jsx(Typography, { as: "p", variant: "title", color: variant === "gradient" ? "inherit" : undefined, children: stat })) : null, loading ? (subMetric !== undefined && _jsx(Skeleton, { className: "h-5 w-28" })) : subMetric ? (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-80" : undefined, children: subMetric })) : null] }), children ? (_jsx("div", { className: cn(size === "default" && "p-4 pt-0", size === "compact" && "p-3 pt-0"), children: children })) : null, footer ? (_jsx("div", { className: cn("flex items-center", size === "default" && "p-4 pt-0", size === "compact" && "p-3 pt-0"), children: footer })) : null] }));
|
|
14
47
|
});
|
|
15
48
|
Card.displayName = "Card";
|
|
16
|
-
|
|
49
|
+
function CardGrid({ columns = 3, align = "stretch", className, ...props }) {
|
|
50
|
+
return (_jsx("div", { className: cn("grid gap-3", cardGridColumns[columns], align === "start" && "auto-rows-max items-start", className), ...props }));
|
|
51
|
+
}
|
|
52
|
+
function CardSplitGrid({ asideWidth = "md", breakpoint = "xl", align = "start", className, ...props }) {
|
|
53
|
+
return (_jsx("div", { className: cn("grid gap-3", cardSplitGridColumns[breakpoint][asideWidth], align === "start" && "auto-rows-max items-start", className), ...props }));
|
|
54
|
+
}
|
|
55
|
+
function CardList({ density = "default", variant = "cards", className, ...props }) {
|
|
56
|
+
return (_jsx("div", { className: cn("grid", variant === "cards" && density === "default" && "gap-2", variant === "cards" && density === "compact" && "gap-1.5", variant === "divided" &&
|
|
57
|
+
"overflow-hidden rounded-surface border border-[hsl(var(--card-border))] bg-background", variant === "divided" &&
|
|
58
|
+
"[&>[data-slot=card-list-item]]:rounded-none [&>[data-slot=card-list-item]]:border-0 [&>[data-slot=card-list-item]+[data-slot=card-list-item]]:border-t [&>[data-slot=card-list-item]+[data-slot=card-list-item]]:border-[hsl(var(--card-border))]", className), ...props }));
|
|
59
|
+
}
|
|
60
|
+
function CardListItem({ label, description, leading, leadingVariant = "badge", trailing, meta, labelLines = 1, descriptionLines = 1, className, onClick, ...props }) {
|
|
61
|
+
const interactive = Boolean(onClick);
|
|
62
|
+
const trailingNode = trailing == null || React.isValidElement(trailing) ? (trailing) : (_jsx(Typography, { as: "span", variant: "bodySm", className: "block truncate font-medium", children: trailing }));
|
|
63
|
+
const content = (_jsxs(_Fragment, { children: [leading !== undefined ? (leadingVariant === "badge" ? (_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-surface bg-muted text-sm font-semibold text-foreground", children: leading })) : (_jsx("div", { className: "shrink-0 text-muted-foreground", children: leading }))) : null, _jsxs("div", { className: "min-w-0 flex-1 overflow-hidden", children: [_jsxs("div", { className: "flex min-w-0 items-start justify-between gap-2", children: [_jsx(Typography, { as: "p", variant: "bodySm", className: cn("min-w-0 font-medium text-foreground", labelLines === 1 && "truncate", labelLines === 2 && "line-clamp-2"), children: label }), meta !== undefined ? (_jsx(Typography, { as: "span", variant: "caption", className: "min-w-0 max-w-[50%] shrink truncate text-right text-muted-foreground", children: meta })) : null] }), description !== undefined ? (_jsx(Typography, { as: "p", variant: "caption", className: cn("mt-0.5 text-muted-foreground", descriptionLines === 1 && "truncate", descriptionLines === 2 && "line-clamp-2"), children: description })) : null] }), trailingNode !== undefined ? (_jsx("div", { className: "min-w-0 max-w-[45%] shrink-0 overflow-hidden truncate text-right [&>*]:max-w-full", children: trailingNode })) : null] }));
|
|
64
|
+
const itemClassName = cn("flex w-full min-w-0 items-center gap-3 rounded-surface border border-[hsl(var(--card-border))] bg-background py-2 pl-3 pr-4 text-left", interactive && "cursor-pointer transition-colors hover:border-primary", className);
|
|
65
|
+
if (interactive) {
|
|
66
|
+
return (_jsx("button", { type: "button", "data-slot": "card-list-item", className: itemClassName, onClick: onClick, ...props, children: content }));
|
|
67
|
+
}
|
|
68
|
+
return (_jsx("div", { "data-slot": "card-list-item", className: itemClassName, ...props, children: content }));
|
|
69
|
+
}
|
|
70
|
+
export { Card, CardGrid, CardSplitGrid, CardList, CardListItem };
|
package/dist/checkbox.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputE
|
|
|
8
8
|
label?: React.ReactNode;
|
|
9
9
|
/** Description shown below the label in smaller muted text. */
|
|
10
10
|
description?: React.ReactNode;
|
|
11
|
+
/** Aligns the checkbox control against the label content. */
|
|
12
|
+
labelAlign?: "center" | "start";
|
|
11
13
|
}
|
|
12
14
|
declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
13
15
|
export { Checkbox };
|
package/dist/checkbox.js
CHANGED
|
@@ -8,7 +8,7 @@ const sizeClasses = {
|
|
|
8
8
|
md: "size-4",
|
|
9
9
|
lg: "size-5",
|
|
10
10
|
};
|
|
11
|
-
const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "md", checked, disabled, label, description, id, ...props }, ref) => {
|
|
11
|
+
const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "md", checked, disabled, label, description, labelAlign = "center", id, ...props }, ref) => {
|
|
12
12
|
const innerRef = React.useRef(null);
|
|
13
13
|
const generatedId = React.useId();
|
|
14
14
|
const inputId = id !== null && id !== void 0 ? id : `checkbox-${generatedId}`;
|
|
@@ -23,7 +23,7 @@ const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "m
|
|
|
23
23
|
: "border-input", disabled && "cursor-not-allowed opacity-50", !label && className), children: [_jsx("input", { ref: innerRef, type: "checkbox", id: inputId, checked: checked, disabled: disabled, className: "absolute inset-0 h-full w-full cursor-pointer appearance-none opacity-0 disabled:cursor-not-allowed", ...props }), indeterminate ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", className: "pointer-events-none absolute inset-0 m-auto h-3 w-3", "aria-hidden": "true", children: _jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) })) : checked ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", className: "pointer-events-none absolute inset-0 m-auto h-3 w-3", "aria-hidden": "true", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) : null] }));
|
|
24
24
|
if (!label)
|
|
25
25
|
return box;
|
|
26
|
-
return (_jsxs("label", { htmlFor: inputId, className: cn("inline-flex cursor-pointer items-center gap-2 text-sm", disabled && "cursor-not-allowed opacity-50", className), children: [box, _jsxs("div", { className: "select-none", children: [_jsx(Typography, { as: "span", variant: "bodySm", children: label }), description ? (_jsx(Typography, { as: "p", variant: "caption", className: "mt-1", children: description })) : null] })] }));
|
|
26
|
+
return (_jsxs("label", { htmlFor: inputId, className: cn("inline-flex cursor-pointer items-center gap-2 text-sm", labelAlign === "start" && "items-start", disabled && "cursor-not-allowed opacity-50", className), children: [box, _jsxs("div", { className: "select-none", children: [_jsx(Typography, { as: "span", variant: "bodySm", children: label }), description ? (_jsx(Typography, { as: "p", variant: "caption", className: "mt-1", children: description })) : null] })] }));
|
|
27
27
|
});
|
|
28
28
|
Checkbox.displayName = "Checkbox";
|
|
29
29
|
export { Checkbox };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ButtonProps } from "./button";
|
|
2
|
+
export interface CloseButtonProps extends Omit<ButtonProps, "children"> {
|
|
3
|
+
iconSize?: number;
|
|
4
|
+
}
|
|
5
|
+
declare function CloseButton({ className, iconSize, variant, size, "aria-label": ariaLabel, ...props }: CloseButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export { CloseButton };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { XIcon } from "./animated-icons/x";
|
|
3
|
+
import { Button } from "./button";
|
|
4
|
+
import { cn } from "./lib/utils";
|
|
5
|
+
function CloseButton({ className, iconSize = 16, variant = "ghost", size = "compactIcon", "aria-label": ariaLabel = "Close", ...props }) {
|
|
6
|
+
return (_jsx(Button, { type: "button", variant: variant, size: size, "aria-label": ariaLabel, className: cn("text-muted-foreground hover:text-foreground [&_svg]:h-4 [&_svg]:w-4", className), ...props, children: _jsx(XIcon, { size: iconSize }) }));
|
|
7
|
+
}
|
|
8
|
+
export { CloseButton };
|
package/dist/collapsible.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { type TypographyProps } from "./typography";
|
|
2
3
|
export interface CollapsibleProps {
|
|
3
4
|
id?: string;
|
|
4
5
|
title: React.ReactNode;
|
|
@@ -10,10 +11,15 @@ export interface CollapsibleProps {
|
|
|
10
11
|
headerAction?: React.ReactNode;
|
|
11
12
|
/** Element rendered inline after the title (e.g. a tooltip icon). */
|
|
12
13
|
titleAdornment?: React.ReactNode;
|
|
14
|
+
showChevron?: boolean;
|
|
13
15
|
className?: string;
|
|
14
16
|
headerClassName?: string;
|
|
17
|
+
triggerClassName?: string;
|
|
18
|
+
titleClassName?: string;
|
|
19
|
+
titleVariant?: TypographyProps["variant"];
|
|
20
|
+
chevronClassName?: string;
|
|
15
21
|
contentClassName?: string;
|
|
16
22
|
}
|
|
17
|
-
declare function Collapsible({ id, title, children, defaultOpen, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }: CollapsibleProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
declare function Collapsible({ id, title, children, defaultOpen, open: openProp, onOpenChange, headerAction, titleAdornment, showChevron, className, headerClassName, triggerClassName, titleClassName, titleVariant, chevronClassName, contentClassName, }: CollapsibleProps): import("react/jsx-runtime").JSX.Element;
|
|
18
24
|
declare const CollapsibleSection: typeof Collapsible;
|
|
19
25
|
export { Collapsible, CollapsibleSection };
|
package/dist/collapsible.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
|
5
5
|
import { ChevronUp } from "lucide-react";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
7
|
import { Typography } from "./typography";
|
|
8
|
-
function Collapsible({ id, title, children, defaultOpen = true, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }) {
|
|
8
|
+
function Collapsible({ id, title, children, defaultOpen = true, open: openProp, onOpenChange, headerAction, titleAdornment, showChevron = true, className, headerClassName, triggerClassName, titleClassName, titleVariant = "subheading", chevronClassName, contentClassName, }) {
|
|
9
9
|
const [uncontrolled, setUncontrolled] = React.useState(defaultOpen);
|
|
10
10
|
const isControlled = openProp !== undefined;
|
|
11
11
|
const open = isControlled ? openProp : uncontrolled;
|
|
@@ -14,7 +14,7 @@ function Collapsible({ id, title, children, defaultOpen = true, open: openProp,
|
|
|
14
14
|
setUncontrolled(next);
|
|
15
15
|
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
|
|
16
16
|
};
|
|
17
|
-
return (_jsxs(CollapsiblePrimitive.Root, { id: id, open: open, onOpenChange: setOpen, className: cn("scroll-mt-24 border-b border-border", className), children: [_jsxs("div", { className: cn("flex items-center gap-
|
|
17
|
+
return (_jsxs(CollapsiblePrimitive.Root, { id: id, open: open, onOpenChange: setOpen, className: cn("scroll-mt-24 border-b border-border", className), children: [_jsxs("div", { "data-slot": "collapsible-header", className: cn("flex items-center gap-1.5 py-2", headerClassName), children: [_jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsxs("button", { type: "button", "data-slot": "collapsible-trigger", className: cn("flex flex-1 cursor-pointer items-center gap-2 rounded-sm text-left text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", triggerClassName), children: [_jsx(Typography, { as: "h3", variant: titleVariant, className: titleClassName, children: title }), titleAdornment] }) }), headerAction, showChevron ? (_jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "data-slot": "collapsible-chevron-trigger", "aria-label": open ? "Collapse section" : "Expand section", className: "group ml-1 cursor-pointer rounded-sm text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(ChevronUp, { "aria-hidden": "true", className: cn("h-4 w-4 transition-transform duration-150 group-data-[state=closed]:rotate-180", chevronClassName) }) }) })) : null] }), _jsx(CollapsiblePrimitive.Content, { "data-slot": "collapsible-content", className: "overflow-hidden", children: _jsx("div", { className: cn("pb-6 pt-4", contentClassName), children: children }) })] }));
|
|
18
18
|
}
|
|
19
19
|
const CollapsibleSection = Collapsible;
|
|
20
20
|
export { Collapsible, CollapsibleSection };
|
package/dist/command-search.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface CommandSearchSection {
|
|
|
20
20
|
heading: string;
|
|
21
21
|
items: CommandSearchItem[];
|
|
22
22
|
}
|
|
23
|
+
export type CommandSearchShowAllResultsLabel = React.ReactNode | ((query: string, hasResults: boolean) => React.ReactNode);
|
|
23
24
|
export interface CommandSearchProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
24
25
|
value: string;
|
|
25
26
|
onValueChange: (value: string) => void;
|
|
@@ -29,6 +30,7 @@ export interface CommandSearchProps extends Omit<React.HTMLAttributes<HTMLDivEle
|
|
|
29
30
|
open?: boolean;
|
|
30
31
|
defaultOpen?: boolean;
|
|
31
32
|
onOpenChange?: (open: boolean) => void;
|
|
33
|
+
triggerVariant?: "default" | "sidebar";
|
|
32
34
|
triggerPlaceholder?: string;
|
|
33
35
|
inputPlaceholder?: string;
|
|
34
36
|
/** The key that opens the dialog when pressed with Cmd/Ctrl (e.g. "k", "j"). */
|
|
@@ -37,8 +39,21 @@ export interface CommandSearchProps extends Omit<React.HTMLAttributes<HTMLDivEle
|
|
|
37
39
|
shortcutLabel?: string;
|
|
38
40
|
allFilter?: CommandSearchFilter;
|
|
39
41
|
filters?: CommandSearchFilter[];
|
|
42
|
+
/** Shows command-list skeleton rows while results are being fetched. */
|
|
43
|
+
loading?: boolean;
|
|
44
|
+
/** Number of skeleton rows shown while `loading` is true. */
|
|
45
|
+
loadingRows?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Renders a footer action for routing to a full search results page.
|
|
48
|
+
* The action is shown only when the query is not empty and results are not loading.
|
|
49
|
+
*/
|
|
50
|
+
onShowAllResults?: (query: string) => void;
|
|
51
|
+
/** Custom label for the full-results footer action. */
|
|
52
|
+
showAllResultsLabel?: CommandSearchShowAllResultsLabel;
|
|
53
|
+
/** Class names applied to the button that opens the command dialog. */
|
|
54
|
+
triggerClassName?: string;
|
|
40
55
|
dialogClassName?: string;
|
|
41
56
|
resultsClassName?: string;
|
|
42
57
|
}
|
|
43
|
-
declare function CommandSearch({ value, onValueChange, sections, children, className, isCollapsed, open, defaultOpen, onOpenChange, triggerPlaceholder, inputPlaceholder, shortcutKey, shortcutLabel, allFilter, filters, dialogClassName, resultsClassName, ...props }: CommandSearchProps): import("react/jsx-runtime").JSX.Element;
|
|
58
|
+
declare function CommandSearch({ value, onValueChange, sections, children, className, isCollapsed, open, defaultOpen, onOpenChange, triggerVariant, triggerPlaceholder, inputPlaceholder, shortcutKey, shortcutLabel, allFilter, filters, loading, loadingRows, onShowAllResults, showAllResultsLabel, triggerClassName, dialogClassName, resultsClassName, ...props }: CommandSearchProps): import("react/jsx-runtime").JSX.Element;
|
|
44
59
|
export { CommandSearch };
|
package/dist/command-search.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Button } from "./button";
|
|
5
5
|
import { Command, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "./command";
|
|
6
6
|
import { EmptyState } from "./empty-state";
|
|
7
7
|
import { SearchIcon } from "./animated-icons/search";
|
|
8
|
-
import { DialogRoot, DialogSurface } from "./dialog-primitive";
|
|
8
|
+
import { DialogRoot, DialogSurface, DialogTitle } from "./dialog-primitive";
|
|
9
9
|
import { FilterToggle } from "./filter-toggle";
|
|
10
10
|
import { cn } from "./lib/utils";
|
|
11
|
+
import { PopoverMenuFooter, PopoverMenuFooterAction } from "./popover-menu";
|
|
12
|
+
import { Skeleton } from "./skeleton";
|
|
11
13
|
import { Typography } from "./typography";
|
|
12
14
|
import { SearchHighlight } from "./use-search-highlight";
|
|
13
15
|
function CommandSearchEmptyIcon({ className }) {
|
|
@@ -20,6 +22,9 @@ function getCommandSearchItemValue(item) {
|
|
|
20
22
|
.join(" ");
|
|
21
23
|
return (_b = item.value) !== null && _b !== void 0 ? _b : fallbackValue;
|
|
22
24
|
}
|
|
25
|
+
function CommandSearchSkeleton({ rows = 4 }) {
|
|
26
|
+
return (_jsx("div", { className: "space-y-[var(--space-1)] p-[var(--space-1)]", children: Array.from({ length: rows }).map((_, index) => (_jsxs("div", { className: "space-y-[var(--space-2)] rounded-sm px-[var(--space-2)] py-[var(--space-2)]", children: [_jsx(Skeleton, { className: "h-4 w-40" }), _jsx(Skeleton, { className: "h-3 w-56 max-w-full" })] }, index))) }));
|
|
27
|
+
}
|
|
23
28
|
function useControllableOpen({ open, defaultOpen, onOpenChange, }) {
|
|
24
29
|
const [internalOpen, setInternalOpen] = React.useState(defaultOpen !== null && defaultOpen !== void 0 ? defaultOpen : false);
|
|
25
30
|
const isControlled = open !== undefined;
|
|
@@ -32,7 +37,7 @@ function useControllableOpen({ open, defaultOpen, onOpenChange, }) {
|
|
|
32
37
|
}, [isControlled, onOpenChange]);
|
|
33
38
|
return [currentOpen, setOpen];
|
|
34
39
|
}
|
|
35
|
-
function CommandSearch({ value, onValueChange, sections, children, className, isCollapsed = false, open, defaultOpen, onOpenChange, triggerPlaceholder = "Search...", inputPlaceholder = "Search...", shortcutKey = "k", shortcutLabel, allFilter, filters = [], dialogClassName, resultsClassName, ...props }) {
|
|
40
|
+
function CommandSearch({ value, onValueChange, sections, children, className, isCollapsed = false, open, defaultOpen, onOpenChange, triggerVariant = "default", triggerPlaceholder = "Search...", inputPlaceholder = "Search...", shortcutKey = "k", shortcutLabel, allFilter, filters = [], loading = false, loadingRows = 4, onShowAllResults, showAllResultsLabel, triggerClassName, dialogClassName, resultsClassName, ...props }) {
|
|
36
41
|
const [isOpen, setIsOpen] = useControllableOpen({
|
|
37
42
|
open,
|
|
38
43
|
defaultOpen,
|
|
@@ -41,6 +46,13 @@ function CommandSearch({ value, onValueChange, sections, children, className, is
|
|
|
41
46
|
const inputRef = React.useRef(null);
|
|
42
47
|
const normalizedValue = value.trim();
|
|
43
48
|
const visibleSections = React.useMemo(() => (sections !== null && sections !== void 0 ? sections : []).filter((section) => section.items.length > 0), [sections]);
|
|
49
|
+
const hasResults = children !== undefined || visibleSections.length > 0;
|
|
50
|
+
const shouldShowAllResults = Boolean(onShowAllResults) && Boolean(normalizedValue) && !loading;
|
|
51
|
+
const resolvedShowAllResultsLabel = typeof showAllResultsLabel === "function"
|
|
52
|
+
? showAllResultsLabel(normalizedValue, hasResults)
|
|
53
|
+
: showAllResultsLabel !== null && showAllResultsLabel !== void 0 ? showAllResultsLabel : (hasResults
|
|
54
|
+
? `Show all results for "${normalizedValue}"`
|
|
55
|
+
: `Search all records for "${normalizedValue}"`);
|
|
44
56
|
const resolvedLabel = shortcutLabel !== null && shortcutLabel !== void 0 ? shortcutLabel : `⌘${shortcutKey.toUpperCase()}`;
|
|
45
57
|
React.useEffect(() => {
|
|
46
58
|
const handleKeyDown = (event) => {
|
|
@@ -57,18 +69,32 @@ function CommandSearch({ value, onValueChange, sections, children, className, is
|
|
|
57
69
|
window.setTimeout(() => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
58
70
|
}
|
|
59
71
|
}, [isOpen]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
const preserveInputFocus = React.useCallback((event) => {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
}, []);
|
|
75
|
+
const selectFilter = React.useCallback((onSelect) => {
|
|
76
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect();
|
|
77
|
+
window.setTimeout(() => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
78
|
+
}, []);
|
|
79
|
+
return (_jsxs("div", { className: className, ...props, children: [_jsxs(Button, { type: "button", onClick: () => setIsOpen(true), variant: "ghost", size: isCollapsed ? "icon" : "default", className: cn(triggerVariant === "sidebar" && isCollapsed
|
|
80
|
+
? "h-control min-h-control w-control min-w-control max-w-control shrink-0 rounded-control border-none bg-transparent p-0 !font-normal text-muted-foreground hover:bg-card hover:text-foreground focus-visible:bg-card focus-visible:ring-ring/30"
|
|
81
|
+
: triggerVariant === "sidebar"
|
|
82
|
+
? "h-control w-full min-w-[14rem] justify-start gap-2 rounded-control border border-[hsl(var(--layout-sidebar-border))] bg-card px-2.5 !font-normal text-muted-foreground shadow-none hover:bg-card hover:text-foreground focus-visible:border-ring focus-visible:bg-card focus-visible:ring-ring/30"
|
|
83
|
+
: isCollapsed
|
|
84
|
+
? "h-control min-h-control w-control min-w-control max-w-control shrink-0 rounded-control p-0 !font-normal text-muted-foreground hover:bg-card hover:text-foreground"
|
|
85
|
+
: "h-control w-full min-w-[14rem] justify-start gap-2 rounded-control border border-border bg-card px-2.5 !font-normal text-muted-foreground hover:bg-card hover:text-foreground", triggerClassName), children: [_jsx(SearchIcon, { className: "shrink-0", size: 16 }), !isCollapsed ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 text-left text-sm", children: triggerPlaceholder }), _jsx("kbd", { className: "hidden h-[20px] items-center gap-1 rounded border border-border bg-muted px-1.5 font-mono text-[11px] text-muted-foreground sm:inline-flex", children: resolvedLabel })] })) : null] }), _jsx(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, children: _jsxs(DialogSurface, { className: cn("w-[calc(100vw-2rem)] max-w-[52rem] gap-0 overflow-hidden p-0 sm:w-[min(64vw,52rem)]", dialogClassName), "aria-describedby": undefined, hideCloseButton: true, children: [_jsx(DialogTitle, { className: "sr-only", children: inputPlaceholder }), _jsxs(Command, { shouldFilter: false, className: "rounded-none border-0", children: [_jsx(CommandInput, { ref: inputRef, value: value, onValueChange: onValueChange, placeholder: inputPlaceholder, className: "text-sm" }), allFilter || filters.length ? (_jsxs("div", { className: "flex flex-wrap items-center gap-1 border-b px-2.5 py-1.5", children: [allFilter ? (_jsx(FilterToggle, { selected: allFilter.selected, onMouseDown: preserveInputFocus, onClick: () => selectFilter(allFilter.onSelect), children: allFilter.label })) : null, filters.map((filter) => (_jsx(FilterToggle, { selected: filter.selected, onMouseDown: preserveInputFocus, onClick: () => selectFilter(filter.onSelect), children: filter.label }, filter.value)))] })) : null, _jsx(CommandList, { "aria-busy": loading || undefined, className: cn("max-h-[400px] p-1", resultsClassName), children: loading ? (_jsx(CommandSearchSkeleton, { rows: loadingRows })) : children !== undefined ? children : sections ? (visibleSections.length ? (visibleSections.map((section, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx(CommandSeparator, { alwaysRender: true }) : null, _jsx(CommandGroup, { heading: section.heading, children: section.items.map((item) => (_jsx(CommandItem, { value: getCommandSearchItemValue(item), disabled: item.disabled, onSelect: () => {
|
|
86
|
+
var _a;
|
|
87
|
+
(_a = item.onSelect) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
88
|
+
if (item.closeOnSelect !== false) {
|
|
89
|
+
setIsOpen(false);
|
|
90
|
+
}
|
|
91
|
+
}, children: _jsxs("div", { className: "min-w-0", children: [_jsx(Typography, { as: "p", variant: "label", className: "truncate", children: _jsx(SearchHighlight, { text: item.title, query: value }) }), item.subtitle ? (_jsx(Typography, { as: "p", variant: "caption", className: "truncate", children: _jsx(SearchHighlight, { text: item.subtitle, query: value }) })) : null] }) }, item.id))) })] }, section.key)))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
|
|
92
|
+
? `No results found for "${value}".`
|
|
93
|
+
: "Results will appear here as you type." }))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
|
|
94
|
+
? `No results found for "${value}".`
|
|
95
|
+
: "Results will appear here as you type." })) }), shouldShowAllResults ? (_jsx(PopoverMenuFooter, { inset: "flush", children: _jsx(PopoverMenuFooterAction, { onClick: () => {
|
|
96
|
+
onShowAllResults === null || onShowAllResults === void 0 ? void 0 : onShowAllResults(normalizedValue);
|
|
97
|
+
setIsOpen(false);
|
|
98
|
+
}, children: _jsx("span", { className: "truncate", children: resolvedShowAllResultsLabel }) }) })) : null] })] }) })] }));
|
|
73
99
|
}
|
|
74
100
|
export { CommandSearch };
|
package/dist/command.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command as CommandPrimitive } from "cmdk";
|
|
|
5
5
|
import { inputControlClassName } from "./input-control";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
7
|
import { SearchInputShell } from "./search-input-shell";
|
|
8
|
-
const Command = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive, { ref: ref, className: cn("flex h-full w-full flex-col overflow-hidden rounded-
|
|
8
|
+
const Command = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive, { ref: ref, className: cn("flex h-full w-full flex-col overflow-hidden rounded-overlay bg-popover text-popover-foreground", className), ...props })));
|
|
9
9
|
Command.displayName = CommandPrimitive.displayName;
|
|
10
10
|
const CommandInput = React.forwardRef(({ className, wrapperClassName, iconClassName, iconSize = 16, ...props }, ref) => (_jsx("div", { "cmdk-input-wrapper": "", className: cn("border-b p-4", wrapperClassName), children: _jsx(SearchInputShell, { iconClassName: iconClassName, iconSize: iconSize, children: _jsx(CommandPrimitive.Input, { ref: ref, className: cn(inputControlClassName, "bg-background pl-9 pr-3", className), ...props }) }) })));
|
|
11
11
|
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
@@ -13,11 +13,11 @@ const CommandList = React.forwardRef(({ className, ...props }, ref) => (_jsx(Com
|
|
|
13
13
|
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
14
14
|
const CommandEmpty = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Empty, { ref: ref, className: cn("py-6 text-center text-sm text-muted-foreground", className), ...props })));
|
|
15
15
|
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
16
|
-
const CommandGroup = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Group, { ref: ref, className: cn("overflow-hidden py-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1
|
|
16
|
+
const CommandGroup = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Group, { ref: ref, className: cn("overflow-hidden py-[var(--space-1)] text-foreground [&_[cmdk-group-heading]]:px-[var(--space-2)] [&_[cmdk-group-heading]]:py-[var(--space-1)] [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:text-muted-foreground", className), ...props })));
|
|
17
17
|
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
18
18
|
const CommandSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Separator, { ref: ref, className: cn("-mx-1 my-1 h-px bg-border", className), ...props })));
|
|
19
19
|
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
20
|
-
const CommandItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Item, { ref: ref, className: cn("relative flex cursor-pointer select-none items-center rounded-sm px-2 py-
|
|
20
|
+
const CommandItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.Item, { ref: ref, className: cn("relative flex cursor-pointer select-none items-center rounded-sm px-[var(--space-2)] py-[var(--space-2)] text-sm outline-none transition-colors data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-muted data-[selected=true]:text-foreground", className), ...props })));
|
|
21
21
|
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
22
22
|
const CommandShortcut = ({ className, ...props }) => (_jsx("span", { className: cn("ml-auto text-xs tracking-widest text-muted-foreground", className), ...props }));
|
|
23
23
|
CommandShortcut.displayName = "CommandShortcut";
|
package/dist/copy-button.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLBut
|
|
|
14
14
|
copyLabel?: string;
|
|
15
15
|
/** Feedback label after copying. Defaults to "Copied". */
|
|
16
16
|
copiedLabel?: string;
|
|
17
|
+
/** Tooltip content shown briefly after copying. Defaults to "Copied!". */
|
|
18
|
+
copiedTooltipLabel?: React.ReactNode;
|
|
17
19
|
}
|
|
18
|
-
declare function CopyButton({ value, feedbackDuration, children, onCopy, onError, onClick, copyLabel, copiedLabel, className, type, ...props }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
declare function CopyButton({ value, feedbackDuration, children, onCopy, onError, onClick, copyLabel, copiedLabel, copiedTooltipLabel, className, type, ...props }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
19
21
|
export { CopyButton };
|
package/dist/copy-button.js
CHANGED
|
@@ -4,7 +4,8 @@ import * as React from "react";
|
|
|
4
4
|
import { Copy } from "lucide-react";
|
|
5
5
|
import { CheckIcon } from "./animated-icons/check";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
|
-
|
|
7
|
+
import { Tooltip } from "./tooltip";
|
|
8
|
+
function CopyButton({ value, feedbackDuration = 1500, children, onCopy, onError, onClick, copyLabel = "Copy", copiedLabel = "Copied", copiedTooltipLabel = "Copied!", className, type = "button", ...props }) {
|
|
8
9
|
const [copied, setCopied] = React.useState(false);
|
|
9
10
|
const timeoutRef = React.useRef(null);
|
|
10
11
|
React.useEffect(() => () => {
|
|
@@ -29,6 +30,7 @@ function CopyButton({ value, feedbackDuration = 1500, children, onCopy, onError,
|
|
|
29
30
|
}, [value, feedbackDuration, onCopy, onClick, onError]);
|
|
30
31
|
const iconOnly = children === undefined;
|
|
31
32
|
const label = copied ? copiedLabel : copyLabel;
|
|
32
|
-
|
|
33
|
+
const button = (_jsxs("button", { type: type, onClick: handleCopy, "aria-label": iconOnly ? label : undefined, className: cn("inline-flex cursor-pointer items-center gap-1.5 rounded text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50", !iconOnly && "text-sm font-medium", className), ...props, children: [copied ? (_jsx(CheckIcon, { size: 16, className: "text-green-600" })) : (_jsx(Copy, { className: "h-4 w-4", "aria-hidden": "true" })), iconOnly ? null : _jsx("span", { children: copied ? copiedLabel : children })] }));
|
|
34
|
+
return (_jsxs(_Fragment, { children: [_jsx(Tooltip, { content: copiedTooltipLabel, delayDuration: 0, open: copied, children: button }), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? copiedLabel : "" })] }));
|
|
33
35
|
}
|
|
34
36
|
export { CopyButton };
|
package/dist/count-badge.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ export interface CountBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
|
3
3
|
count: number;
|
|
4
4
|
variant?: "default" | "danger" | "muted";
|
|
5
5
|
size?: "sm" | "md";
|
|
6
|
+
/** Caps the displayed value, e.g. count={128} max={9} renders "9+". */
|
|
7
|
+
max?: number;
|
|
6
8
|
pulse?: boolean;
|
|
7
9
|
hideWhenZero?: boolean;
|
|
8
10
|
}
|
|
9
|
-
declare function CountBadge({ count, variant, size, pulse, className, hideWhenZero, ...props }: CountBadgeProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
declare function CountBadge({ count, variant, size, max, pulse, className, hideWhenZero, ...props }: CountBadgeProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
12
|
export { CountBadge };
|
package/dist/count-badge.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Badge } from "./badge";
|
|
3
3
|
import { cn } from "./lib/utils";
|
|
4
|
-
function CountBadge({ count, variant = "default", size = "md", pulse = false, className, hideWhenZero = false, ...props }) {
|
|
4
|
+
function CountBadge({ count, variant = "default", size = "md", max, pulse = false, className, hideWhenZero = false, ...props }) {
|
|
5
5
|
if (count < 0 || (count === 0 && hideWhenZero))
|
|
6
6
|
return null;
|
|
7
7
|
const effectiveVariant = count === 0 ? "muted" : variant;
|
|
8
|
+
const resolvedMax = typeof max === "number" && Number.isFinite(max) && max > 0
|
|
9
|
+
? Math.floor(max)
|
|
10
|
+
: undefined;
|
|
11
|
+
const isCapped = resolvedMax !== undefined && count > resolvedMax;
|
|
12
|
+
const displayCount = isCapped ? `${resolvedMax}+` : count;
|
|
8
13
|
const sizeClasses = {
|
|
9
|
-
sm: "
|
|
10
|
-
md: "
|
|
14
|
+
sm: "h-[18px] min-w-[18px] px-1",
|
|
15
|
+
md: "h-[20px] min-w-[20px] px-1.5",
|
|
11
16
|
};
|
|
12
17
|
const variantClasses = {
|
|
13
18
|
default: {
|
|
@@ -20,7 +25,7 @@ function CountBadge({ count, variant = "default", size = "md", pulse = false, cl
|
|
|
20
25
|
},
|
|
21
26
|
muted: {
|
|
22
27
|
badgeVariant: "muted",
|
|
23
|
-
className: "border-transparent",
|
|
28
|
+
className: "border-transparent bg-muted-foreground/15 text-foreground/80",
|
|
24
29
|
},
|
|
25
30
|
};
|
|
26
31
|
const pulseColor = {
|
|
@@ -29,6 +34,6 @@ function CountBadge({ count, variant = "default", size = "md", pulse = false, cl
|
|
|
29
34
|
muted: "bg-muted-foreground/50",
|
|
30
35
|
};
|
|
31
36
|
const shouldPulse = pulse && count > 0;
|
|
32
|
-
return (_jsxs("span", { className: cn("relative inline-flex", className), ...props, children: [shouldPulse ? (_jsx("span", { className: cn("absolute inline-flex h-full w-full animate-ping rounded-
|
|
37
|
+
return (_jsxs("span", { "data-slot": "count-badge", className: cn("relative inline-flex", className), ...props, children: [shouldPulse ? (_jsx("span", { className: cn("absolute inline-flex h-full w-full animate-ping rounded-control opacity-75", pulseColor[effectiveVariant]) })) : null, _jsx("span", { className: "relative inline-flex", children: _jsx(Badge, { variant: variantClasses[effectiveVariant].badgeVariant, className: cn("max-w-none", sizeClasses[size], variantClasses[effectiveVariant].className), children: displayCount }) })] }));
|
|
33
38
|
}
|
|
34
39
|
export { CountBadge };
|
package/dist/date-input.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
export interface
|
|
2
|
+
export interface DateRangeInputValue {
|
|
3
|
+
from?: string;
|
|
4
|
+
to?: string;
|
|
5
|
+
}
|
|
6
|
+
interface DateInputSharedProps {
|
|
3
7
|
label: React.ReactNode;
|
|
4
|
-
|
|
5
|
-
onValueChange: (value: string) => void;
|
|
8
|
+
appearance?: "field" | "inline";
|
|
6
9
|
description?: React.ReactNode;
|
|
7
10
|
error?: React.ReactNode;
|
|
8
11
|
invalid?: boolean;
|
|
@@ -18,5 +21,17 @@ export interface DateInputProps {
|
|
|
18
21
|
errorClassName?: string;
|
|
19
22
|
id?: string;
|
|
20
23
|
}
|
|
24
|
+
export interface DateInputSingleProps extends DateInputSharedProps {
|
|
25
|
+
mode?: "single";
|
|
26
|
+
value: string;
|
|
27
|
+
onValueChange: (value: string) => void;
|
|
28
|
+
}
|
|
29
|
+
export interface DateInputRangeProps extends DateInputSharedProps {
|
|
30
|
+
mode: "range";
|
|
31
|
+
value: DateRangeInputValue;
|
|
32
|
+
onValueChange: (value: DateRangeInputValue) => void;
|
|
33
|
+
numberOfMonths?: number;
|
|
34
|
+
}
|
|
35
|
+
export type DateInputProps = DateInputSingleProps | DateInputRangeProps;
|
|
21
36
|
declare const DateInput: React.ForwardRefExoticComponent<DateInputProps & React.RefAttributes<HTMLButtonElement>>;
|
|
22
37
|
export { DateInput };
|