@neasg/design-system 0.4.8 → 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 +4 -4
- 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 +12 -9
- 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/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 };
|
package/dist/date-input.js
CHANGED
|
@@ -2,26 +2,41 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { format, parse } from "date-fns";
|
|
5
|
+
import { CalendarIcon } from "lucide-react";
|
|
5
6
|
import { Calendar } from "./calendar";
|
|
6
7
|
import { inputControlClassName } from "./input-control";
|
|
7
8
|
import { Field, FieldDescription, FieldError, FieldLabel } from "./field";
|
|
8
9
|
import { PopoverContent, PopoverRoot, PopoverTrigger } from "./popover-primitive";
|
|
9
10
|
import { cn } from "./lib/utils";
|
|
11
|
+
function createLocalDate(year, monthIndex, day) {
|
|
12
|
+
const date = new Date(year, monthIndex, day);
|
|
13
|
+
if (date.getFullYear() !== year ||
|
|
14
|
+
date.getMonth() !== monthIndex ||
|
|
15
|
+
date.getDate() !== day) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return date;
|
|
19
|
+
}
|
|
10
20
|
function parseDateString(dateStr) {
|
|
11
21
|
if (!(dateStr === null || dateStr === void 0 ? void 0 : dateStr.trim()))
|
|
12
22
|
return undefined;
|
|
13
23
|
try {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
const normalizedDateStr = dateStr.trim();
|
|
25
|
+
const isoDateMatch = normalizedDateStr.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
|
|
26
|
+
if (isoDateMatch) {
|
|
27
|
+
const [, year, month, day] = isoDateMatch;
|
|
28
|
+
return createLocalDate(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10));
|
|
29
|
+
}
|
|
30
|
+
const ddmmyyyyMatch = normalizedDateStr.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})/);
|
|
18
31
|
if (ddmmyyyyMatch) {
|
|
19
32
|
const [, day, month, year] = ddmmyyyyMatch;
|
|
20
|
-
|
|
21
|
-
if (!isNaN(date.getTime()))
|
|
22
|
-
return date;
|
|
33
|
+
return createLocalDate(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10));
|
|
23
34
|
}
|
|
24
|
-
const
|
|
35
|
+
const nativeDate = new Date(normalizedDateStr);
|
|
36
|
+
if (!isNaN(nativeDate.getTime())) {
|
|
37
|
+
return nativeDate;
|
|
38
|
+
}
|
|
39
|
+
const date = parse(normalizedDateStr, "yyyy-MM-dd", new Date());
|
|
25
40
|
if (!isNaN(date.getTime()))
|
|
26
41
|
return date;
|
|
27
42
|
return undefined;
|
|
@@ -33,7 +48,51 @@ function parseDateString(dateStr) {
|
|
|
33
48
|
function formatISODate(date) {
|
|
34
49
|
return format(date, "yyyy-MM-dd");
|
|
35
50
|
}
|
|
36
|
-
|
|
51
|
+
function formatDisplayDate(date) {
|
|
52
|
+
return format(date, "d MMM yyyy");
|
|
53
|
+
}
|
|
54
|
+
function getDateTime(date) {
|
|
55
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
|
56
|
+
}
|
|
57
|
+
function isDateOutsideBounds(date, minDate, maxDate) {
|
|
58
|
+
const dateTime = getDateTime(date);
|
|
59
|
+
if (minDate && dateTime < getDateTime(minDate))
|
|
60
|
+
return true;
|
|
61
|
+
if (maxDate && dateTime > getDateTime(maxDate))
|
|
62
|
+
return true;
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
function parseDateRangeValue(value) {
|
|
66
|
+
const from = parseDateString(value.from);
|
|
67
|
+
const to = parseDateString(value.to);
|
|
68
|
+
if (!from && !to)
|
|
69
|
+
return undefined;
|
|
70
|
+
return { from, to };
|
|
71
|
+
}
|
|
72
|
+
function formatDateRangeValue(range) {
|
|
73
|
+
if (!(range === null || range === void 0 ? void 0 : range.from) && !(range === null || range === void 0 ? void 0 : range.to)) {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
...(range.from ? { from: formatISODate(range.from) } : {}),
|
|
78
|
+
...(range.to ? { to: formatISODate(range.to) } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function formatDisplayRange(range) {
|
|
82
|
+
if ((range === null || range === void 0 ? void 0 : range.from) && range.to) {
|
|
83
|
+
return `${formatDisplayDate(range.from)} - ${formatDisplayDate(range.to)}`;
|
|
84
|
+
}
|
|
85
|
+
if (range === null || range === void 0 ? void 0 : range.from) {
|
|
86
|
+
return `${formatDisplayDate(range.from)} -`;
|
|
87
|
+
}
|
|
88
|
+
if (range === null || range === void 0 ? void 0 : range.to) {
|
|
89
|
+
return `- ${formatDisplayDate(range.to)}`;
|
|
90
|
+
}
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const DateInput = React.forwardRef((props, ref) => {
|
|
94
|
+
var _a, _b, _c;
|
|
95
|
+
const { label, appearance = "field", description, error, invalid = false, hideLabel = false, disabled = false, minDate, maxDate, className, triggerClassName, labelClassName, descriptionClassName, errorClassName, id, } = props;
|
|
37
96
|
const [open, setOpen] = React.useState(false);
|
|
38
97
|
const generatedId = React.useId();
|
|
39
98
|
const inputId = id !== null && id !== void 0 ? id : `date-input-${generatedId}`;
|
|
@@ -41,21 +100,35 @@ const DateInput = React.forwardRef(({ label, value, onValueChange, description,
|
|
|
41
100
|
const showDescription = Boolean(description) && !error;
|
|
42
101
|
const descriptionId = showDescription ? `${inputId}-description` : undefined;
|
|
43
102
|
const isInvalid = invalid || Boolean(error);
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
103
|
+
const isRange = props.mode === "range";
|
|
104
|
+
const selectedDate = React.useMemo(() => (isRange ? undefined : parseDateString(props.value)), [isRange, props.value]);
|
|
105
|
+
const selectedRange = React.useMemo(() => (isRange ? parseDateRangeValue(props.value) : undefined), [isRange, props.value]);
|
|
106
|
+
const displayValue = isRange
|
|
107
|
+
? formatDisplayRange(selectedRange)
|
|
108
|
+
: selectedDate
|
|
109
|
+
? formatDisplayDate(selectedDate)
|
|
110
|
+
: undefined;
|
|
111
|
+
const placeholder = (_a = props.placeholder) !== null && _a !== void 0 ? _a : (isRange ? "Pick range" : "Pick a date");
|
|
48
112
|
const handleSelect = (date) => {
|
|
49
|
-
|
|
113
|
+
if (props.mode === "range")
|
|
114
|
+
return;
|
|
115
|
+
props.onValueChange(date ? formatISODate(date) : "");
|
|
50
116
|
setOpen(false);
|
|
51
117
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
118
|
+
const handleRangeSelect = (range) => {
|
|
119
|
+
if (props.mode !== "range")
|
|
120
|
+
return;
|
|
121
|
+
props.onValueChange(formatDateRangeValue(range));
|
|
122
|
+
if ((range === null || range === void 0 ? void 0 : range.from) && range.to) {
|
|
123
|
+
setOpen(false);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const disabledDays = (date) => isDateOutsideBounds(date, minDate, maxDate);
|
|
127
|
+
const calendarContent = (_jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: props.mode === "range" ? (_jsx(Calendar, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, defaultMonth: (_b = selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.from) !== null && _b !== void 0 ? _b : selectedRange === null || selectedRange === void 0 ? void 0 : selectedRange.to, numberOfMonths: (_c = props.numberOfMonths) !== null && _c !== void 0 ? _c : 2, autoFocus: true })) : (_jsx(Calendar, { mode: "single", selected: selectedDate, onSelect: handleSelect, disabled: disabledDays, defaultMonth: selectedDate, autoFocus: true })) }));
|
|
128
|
+
if (appearance === "inline") {
|
|
129
|
+
return (_jsxs("span", { className: cn("inline-flex", className), "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsxs(PopoverRoot, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { ref: ref, type: "button", id: inputId, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": [descriptionId, errorId].filter(Boolean).join(" ") || undefined, className: cn("inline-flex cursor-pointer items-baseline rounded-sm border-0 bg-transparent p-0 font-medium text-primary underline decoration-primary/40 underline-offset-4 transition-colors hover:decoration-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", !displayValue && "text-muted-foreground decoration-border", isInvalid && "text-destructive decoration-destructive", triggerClassName), children: [_jsxs("span", { className: "sr-only", children: [label, ": "] }), _jsx("span", { children: displayValue !== null && displayValue !== void 0 ? displayValue : placeholder })] }) }), calendarContent] }), showDescription ? (_jsx("span", { id: descriptionId, className: "sr-only", children: description })) : null, error ? (_jsx("span", { id: errorId, role: "alert", className: "sr-only", children: error })) : null] }));
|
|
130
|
+
}
|
|
131
|
+
return (_jsxs(Field, { className: className, "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: inputId, className: cn(hideLabel && "sr-only", labelClassName), children: label }), _jsxs(PopoverRoot, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { ref: ref, type: "button", id: inputId, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": [descriptionId, errorId].filter(Boolean).join(" ") || undefined, className: cn(inputControlClassName, "relative cursor-pointer pr-9 text-left", !displayValue && "text-muted-foreground", isInvalid && "border-destructive focus-visible:ring-destructive", triggerClassName), children: [_jsx("span", { className: "block truncate", children: displayValue !== null && displayValue !== void 0 ? displayValue : placeholder }), _jsx(CalendarIcon, { "aria-hidden": "true", className: "pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground", strokeWidth: 2 })] }) }), calendarContent] }), showDescription ? (_jsx(FieldDescription, { id: descriptionId, className: descriptionClassName, children: description })) : null, _jsx(FieldError, { id: errorId, className: errorClassName, children: error })] }));
|
|
59
132
|
});
|
|
60
133
|
DateInput.displayName = "DateInput";
|
|
61
134
|
export { DateInput };
|
package/dist/dialog-primitive.js
CHANGED
|
@@ -4,20 +4,21 @@ import * as React from "react";
|
|
|
4
4
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
5
5
|
import { XIcon } from "./animated-icons/x";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
|
+
import { typographyVariants } from "./typography";
|
|
7
8
|
const DialogRoot = DialogPrimitive.Root;
|
|
8
9
|
const DialogTrigger = DialogPrimitive.Trigger;
|
|
9
10
|
const DialogPortal = DialogPrimitive.Portal;
|
|
10
11
|
const DialogClose = DialogPrimitive.Close;
|
|
11
12
|
const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className), ...props })));
|
|
12
13
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
13
|
-
const DialogSurface = React.forwardRef(({ className, children, hideCloseButton, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-
|
|
14
|
+
const DialogSurface = React.forwardRef(({ className, children, hideCloseButton, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-3 border bg-background p-4 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-overlay", className), ...props, children: [children, !hideCloseButton ? (_jsxs(DialogPrimitive.Close, { className: "absolute right-2 top-2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-control text-muted-foreground ring-offset-background transition-colors hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none", children: [_jsx(XIcon, { size: 16 }), _jsx("span", { className: "sr-only", children: "Close" })] })) : null] })] })));
|
|
14
15
|
DialogSurface.displayName = DialogPrimitive.Content.displayName;
|
|
15
16
|
const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props }));
|
|
16
17
|
DialogHeader.displayName = "DialogHeader";
|
|
17
18
|
const DialogFooter = ({ className, ...props }) => (_jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props }));
|
|
18
19
|
DialogFooter.displayName = "DialogFooter";
|
|
19
|
-
const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn(
|
|
20
|
+
const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn(typographyVariants({ variant: "subheading" }), className), ...props })));
|
|
20
21
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
21
|
-
const DialogDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Description, { ref: ref, className: cn("
|
|
22
|
+
const DialogDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Description, { ref: ref, className: cn(typographyVariants({ variant: "bodySm" }), "text-muted-foreground", className), ...props })));
|
|
22
23
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
23
24
|
export { DialogRoot, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogSurface, DialogHeader, DialogFooter, DialogTitle, DialogDescription, };
|
package/dist/draggable-tabs.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import { type BadgeProps } from "./badge";
|
|
2
3
|
import { type TooltipProps } from "./tooltip";
|
|
4
|
+
export interface DraggableTabBadge {
|
|
5
|
+
label: React.ReactNode;
|
|
6
|
+
variant?: BadgeProps["variant"];
|
|
7
|
+
bordered?: BadgeProps["bordered"];
|
|
8
|
+
}
|
|
3
9
|
export interface DraggableTabItem {
|
|
4
10
|
id: string;
|
|
5
11
|
label: React.ReactNode;
|
|
6
12
|
active?: boolean;
|
|
7
13
|
disabled?: boolean;
|
|
14
|
+
badge?: DraggableTabBadge;
|
|
8
15
|
leading?: React.ReactNode;
|
|
9
16
|
trailing?: React.ReactNode;
|
|
10
17
|
tooltip?: React.ReactNode;
|