@neasg/design-system 0.2.1 → 0.4.2
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 +37 -1
- package/dist/alert.d.ts +15 -0
- package/dist/alert.js +24 -0
- package/dist/avatar.d.ts +5 -2
- package/dist/avatar.js +8 -4
- package/dist/back-button.d.ts +6 -0
- package/dist/back-button.js +8 -0
- package/dist/badge.d.ts +4 -2
- package/dist/badge.js +13 -2
- package/dist/breadcrumb.js +2 -2
- package/dist/button.d.ts +2 -2
- package/dist/button.js +3 -4
- package/dist/calendar.d.ts +8 -0
- package/dist/calendar.js +80 -0
- package/dist/card.d.ts +17 -0
- package/dist/card.js +16 -0
- package/dist/checkbox.d.ts +13 -0
- package/dist/checkbox.js +29 -0
- package/dist/collapsible.d.ts +19 -0
- package/dist/collapsible.js +20 -0
- package/dist/command-search.js +4 -3
- package/dist/copy-button.d.ts +19 -0
- package/dist/copy-button.js +31 -0
- package/dist/date-input.d.ts +22 -0
- package/dist/date-input.js +61 -0
- package/dist/dialog-primitive.js +1 -1
- package/dist/draggable-tabs.js +1 -1
- package/dist/drawer.js +1 -1
- package/dist/editable-table.js +2 -2
- package/dist/empty-state.js +1 -1
- package/dist/field.d.ts +4 -1
- package/dist/field.js +3 -3
- package/dist/file-upload.d.ts +12 -0
- package/dist/file-upload.js +106 -0
- package/dist/index.d.ts +56 -4
- package/dist/index.js +30 -3
- package/dist/input-control.d.ts +1 -1
- package/dist/input-control.js +1 -1
- package/dist/input.js +2 -2
- package/dist/label-value-grid.d.ts +3 -1
- package/dist/label-value-grid.js +15 -2
- package/dist/label-value.d.ts +4 -1
- package/dist/label-value.js +5 -3
- package/dist/layout.d.ts +7 -1
- package/dist/layout.js +3 -3
- package/dist/lib/date-utils.d.ts +9 -0
- package/dist/lib/date-utils.js +34 -0
- package/dist/link.d.ts +9 -0
- package/dist/link.js +19 -0
- package/dist/multi-select.d.ts +31 -0
- package/dist/multi-select.js +78 -0
- package/dist/otp-input.js +1 -1
- package/dist/page-section.d.ts +14 -0
- package/dist/page-section.js +13 -0
- package/dist/pagination.js +3 -2
- package/dist/popover-menu.d.ts +35 -0
- package/dist/popover-menu.js +36 -0
- package/dist/popover-primitive.d.ts +7 -0
- package/dist/popover-primitive.js +11 -0
- package/dist/popover.d.ts +12 -0
- package/dist/popover.js +8 -0
- package/dist/progress.d.ts +10 -0
- package/dist/progress.js +17 -0
- package/dist/search-input.js +1 -1
- package/dist/section-nav.d.ts +22 -0
- package/dist/section-nav.js +25 -0
- package/dist/select-primitive.d.ts +3 -1
- package/dist/select-primitive.js +3 -2
- package/dist/select.d.ts +1 -0
- package/dist/select.js +3 -3
- package/dist/separator.d.ts +6 -0
- package/dist/separator.js +6 -0
- package/dist/skeleton.d.ts +4 -0
- package/dist/skeleton.js +6 -0
- package/dist/spinner.d.ts +22 -0
- package/dist/spinner.js +24 -0
- package/dist/styles.css +42 -0
- package/dist/switch.d.ts +12 -0
- package/dist/switch.js +16 -0
- package/dist/table.d.ts +7 -1
- package/dist/table.js +26 -12
- package/dist/tabs.d.ts +24 -1
- package/dist/tabs.js +61 -3
- package/dist/tailwind-preset.js +9 -0
- package/dist/textarea.js +1 -1
- package/dist/toaster.d.ts +13 -0
- package/dist/toaster.js +27 -0
- package/dist/typography.d.ts +2 -0
- package/dist/typography.js +9 -2
- package/dist/use-error-shake.d.ts +7 -0
- package/dist/use-error-shake.js +36 -0
- package/dist/use-file-upload.d.ts +34 -0
- package/dist/use-file-upload.js +133 -0
- package/dist/use-sticky-sentinel.d.ts +16 -0
- package/dist/use-sticky-sentinel.js +62 -0
- package/dist/use-table-sort.d.ts +28 -0
- package/dist/use-table-sort.js +53 -0
- package/dist/use-viewport-threshold.d.ts +12 -0
- package/dist/use-viewport-threshold.js +43 -0
- package/package.json +36 -6
package/README.md
CHANGED
|
@@ -76,7 +76,42 @@ The package currently includes:
|
|
|
76
76
|
|
|
77
77
|
## AI Usage
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
### MCP Server (recommended)
|
|
80
|
+
|
|
81
|
+
This design system includes the [Storybook MCP addon](https://storybook.js.org/docs/next/ai/mcp/overview/), which gives AI coding assistants direct access to component documentation, props, stories, and usage examples.
|
|
82
|
+
|
|
83
|
+
**Setup:**
|
|
84
|
+
|
|
85
|
+
1. Start the Storybook dev server in this repo:
|
|
86
|
+
```bash
|
|
87
|
+
npm run storybook
|
|
88
|
+
```
|
|
89
|
+
This starts on `http://localhost:6007` with the MCP endpoint at `/mcp`.
|
|
90
|
+
|
|
91
|
+
2. In your consuming project, add a `.mcp.json` at the project root:
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"nea-design-system": {
|
|
96
|
+
"type": "http",
|
|
97
|
+
"url": "http://localhost:6007/mcp"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
3. Restart Claude Code (or your MCP-compatible AI tool) in the consuming project. The following tools become available:
|
|
104
|
+
- **list-all-documentation** — discover all components and their story IDs
|
|
105
|
+
- **get-documentation** — get full component docs, props, and code examples
|
|
106
|
+
- **get-documentation-for-story** — get details for a specific story variant
|
|
107
|
+
- **preview-stories** — generate preview URLs for stories
|
|
108
|
+
- **get-storybook-story-instructions** — get guidance on writing stories
|
|
109
|
+
|
|
110
|
+
The MCP server requires the Storybook dev server to be running. Start it before opening your AI tool.
|
|
111
|
+
|
|
112
|
+
### Manual instructions
|
|
113
|
+
|
|
114
|
+
If you are not using the MCP server, give your AI coding assistant these instructions explicitly:
|
|
80
115
|
|
|
81
116
|
```text
|
|
82
117
|
Use @neasg/design-system as the source of truth for shared UI.
|
|
@@ -105,6 +140,7 @@ Use @neasg/design-system as the source of truth for shared UI.
|
|
|
105
140
|
- `@neasg/design-system/draggable-tabs`
|
|
106
141
|
- `@neasg/design-system/layout`
|
|
107
142
|
- `@neasg/design-system/page-header`
|
|
143
|
+
- `@neasg/design-system/popover`
|
|
108
144
|
- `@neasg/design-system/pagination`
|
|
109
145
|
- `@neasg/design-system/table`
|
|
110
146
|
- `@neasg/design-system/tailwind-preset`
|
package/dist/alert.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const alertVariants: (props?: ({
|
|
4
|
+
variant?: "info" | "success" | "warning" | "destructive" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
export interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof alertVariants> {
|
|
7
|
+
title?: React.ReactNode;
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
icon?: React.ComponentType<{
|
|
10
|
+
className?: string;
|
|
11
|
+
}>;
|
|
12
|
+
action?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
declare const Alert: React.ForwardRefExoticComponent<AlertProps & React.RefAttributes<HTMLDivElement>>;
|
|
15
|
+
export { Alert, alertVariants };
|
package/dist/alert.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { cn } from "./lib/utils";
|
|
5
|
+
import { Typography } from "./typography";
|
|
6
|
+
const alertVariants = cva("relative flex w-full items-start gap-3 rounded-md border px-4 py-3", {
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
info: "border-[hsl(var(--status-info-foreground))]/20 bg-[hsl(var(--status-info))] text-[hsl(var(--status-info-foreground))]",
|
|
10
|
+
success: "border-[hsl(var(--status-success-foreground))]/20 bg-[hsl(var(--status-success))] text-[hsl(var(--status-success-foreground))]",
|
|
11
|
+
warning: "border-[hsl(var(--status-warning-foreground))]/20 bg-[hsl(var(--status-warning))] text-[hsl(var(--status-warning-foreground))]",
|
|
12
|
+
destructive: "border-[hsl(var(--status-destructive-foreground))]/20 bg-[hsl(var(--status-destructive))] text-[hsl(var(--status-destructive-foreground))]",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: "info",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const Alert = React.forwardRef(({ variant, title, description, icon: Icon, action, className, children, role = "alert", ...props }, ref) => {
|
|
20
|
+
const body = description !== null && description !== void 0 ? description : children;
|
|
21
|
+
return (_jsxs("div", { ref: ref, role: role, className: cn(alertVariants({ variant }), className), ...props, children: [Icon ? (_jsx(Icon, { className: "mt-0.5 h-4 w-4 shrink-0" })) : null, _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [title ? (_jsx(Typography, { as: "p", variant: "bodySm", color: "inherit", className: "font-semibold", children: title })) : null, body ? (_jsx(Typography, { as: "div", variant: "caption", color: "inherit", className: "opacity-90", children: body })) : null] }), action ? _jsx("div", { className: "shrink-0 self-start", children: action }) : null] }));
|
|
22
|
+
});
|
|
23
|
+
Alert.displayName = "Alert";
|
|
24
|
+
export { Alert, alertVariants };
|
package/dist/avatar.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
|
3
3
|
declare const AvatarRoot: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
4
|
declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
5
5
|
declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
6
|
+
export type AvatarSize = "sm" | "md";
|
|
6
7
|
interface AvatarProps extends Omit<React.ComponentPropsWithoutRef<typeof AvatarRoot>, "children"> {
|
|
7
8
|
src?: string | null;
|
|
8
9
|
alt?: string;
|
|
9
10
|
fallback: React.ReactNode;
|
|
11
|
+
size?: AvatarSize;
|
|
10
12
|
imageClassName?: string;
|
|
11
13
|
fallbackClassName?: string;
|
|
12
14
|
}
|
|
@@ -14,6 +16,7 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
|
14
16
|
src?: string | null;
|
|
15
17
|
alt?: string;
|
|
16
18
|
fallback: React.ReactNode;
|
|
19
|
+
size?: AvatarSize;
|
|
17
20
|
name?: React.ReactNode;
|
|
18
21
|
role?: React.ReactNode;
|
|
19
22
|
rolePlacement?: "above" | "below";
|
|
@@ -25,8 +28,8 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
|
25
28
|
roleClassName?: string;
|
|
26
29
|
avatarOverlay?: React.ReactNode;
|
|
27
30
|
}
|
|
28
|
-
declare function Avatar({ src, alt, fallback, className, imageClassName, fallbackClassName, ...props }: AvatarProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
-
declare function AvatarProfile({ src, alt, fallback, name, role, rolePlacement, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
declare function Avatar({ src, alt, fallback, size, className, imageClassName, fallbackClassName, ...props }: AvatarProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
declare function AvatarProfile({ src, alt, fallback, size, name, role, rolePlacement, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
|
|
30
33
|
export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
|
|
31
34
|
export type AvatarRootProps = React.ComponentPropsWithoutRef<typeof AvatarRoot>;
|
|
32
35
|
export type { AvatarProps, AvatarProfileProps };
|
package/dist/avatar.js
CHANGED
|
@@ -9,13 +9,17 @@ const AvatarImage = React.forwardRef(({ className, ...props }, ref) => (_jsx(Ava
|
|
|
9
9
|
AvatarImage.displayName = "AvatarImage";
|
|
10
10
|
const AvatarFallback = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Fallback, { ref: ref, className: cn("flex size-full items-center justify-center rounded-full bg-muted", className), ...props })));
|
|
11
11
|
AvatarFallback.displayName = "AvatarFallback";
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const avatarSizeClasses = {
|
|
13
|
+
sm: "h-8 w-8 text-xs",
|
|
14
|
+
md: "h-10 w-10 text-sm",
|
|
15
|
+
};
|
|
16
|
+
function Avatar({ src, alt = "", fallback, size = "sm", className, imageClassName, fallbackClassName, ...props }) {
|
|
17
|
+
return (_jsxs(AvatarRoot, { className: cn(avatarSizeClasses[size], className), ...props, children: [src ? (_jsx(AvatarImage, { src: src, alt: alt, className: imageClassName })) : null, _jsx(AvatarFallback, { className: cn("bg-green-100 font-medium text-green-800", fallbackClassName), children: fallback })] }));
|
|
14
18
|
}
|
|
15
|
-
function AvatarProfile({ src, alt = "", fallback, name, role, rolePlacement = "above", className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }) {
|
|
19
|
+
function AvatarProfile({ src, alt = "", fallback, size = "sm", name, role, rolePlacement = "above", className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }) {
|
|
16
20
|
const hasMeta = name !== undefined || role !== undefined;
|
|
17
21
|
const roleNode = role ? (_jsx("span", { className: cn("text-[10px] font-medium uppercase tracking-wide text-muted-foreground", roleClassName), children: role })) : null;
|
|
18
22
|
const nameNode = name ? (_jsx("span", { className: cn("truncate text-sm font-medium text-foreground", nameClassName), children: name })) : null;
|
|
19
|
-
return (_jsxs("div", { className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: src, alt: alt, fallback: fallback,
|
|
23
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: src, alt: alt, fallback: fallback, size: size, className: avatarClassName, imageClassName: imageClassName, fallbackClassName: fallbackClassName }), avatarOverlay] }), hasMeta ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col", contentClassName), children: [rolePlacement === "above" ? roleNode : null, nameNode, rolePlacement === "below" ? roleNode : null] })) : null] }));
|
|
20
24
|
}
|
|
21
25
|
export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ButtonProps } from "./button";
|
|
3
|
+
export interface BackButtonProps extends Omit<ButtonProps, "asChild" | "size" | "variant"> {
|
|
4
|
+
}
|
|
5
|
+
declare const BackButton: React.ForwardRefExoticComponent<BackButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
6
|
+
export { BackButton };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ChevronLeftIcon } from "./animated-icons/chevron-left";
|
|
4
|
+
import { Button } from "./button";
|
|
5
|
+
import { cn } from "./lib/utils";
|
|
6
|
+
const BackButton = React.forwardRef(({ children = "Back", className, type, ...props }, ref) => (_jsxs(Button, { ref: ref, type: type !== null && type !== void 0 ? type : "button", variant: "link", className: cn("h-auto gap-1 px-0", className), ...props, children: [_jsx(ChevronLeftIcon, { "aria-hidden": "true", className: "shrink-0", size: 16 }), _jsx("span", { children: children })] })));
|
|
7
|
+
BackButton.displayName = "BackButton";
|
|
8
|
+
export { BackButton };
|
package/dist/badge.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "muted" | "outline" | "
|
|
4
|
+
variant?: "muted" | "outline" | "info" | "success" | "warning" | "destructive" | "secondary" | "accent" | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
6
|
/**
|
|
7
7
|
* Visual status label used for short categorical values like case state,
|
|
@@ -9,6 +9,8 @@ declare const badgeVariants: (props?: ({
|
|
|
9
9
|
* surface the full label via `title`.
|
|
10
10
|
*/
|
|
11
11
|
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
12
|
+
/** Show a visible border matching the badge colour. */
|
|
13
|
+
bordered?: boolean;
|
|
12
14
|
}
|
|
13
|
-
declare function Badge({ className, variant, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function Badge({ className, variant, bordered, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
14
16
|
export { Badge, badgeVariants };
|
package/dist/badge.js
CHANGED
|
@@ -19,12 +19,23 @@ const badgeVariants = cva("inline-flex max-w-[200px] items-center justify-center
|
|
|
19
19
|
variant: "secondary",
|
|
20
20
|
},
|
|
21
21
|
});
|
|
22
|
-
function Badge({ className, variant, children, ...props }) {
|
|
22
|
+
function Badge({ className, variant, bordered = false, children, ...props }) {
|
|
23
23
|
const textContent = typeof children === "string"
|
|
24
24
|
? children
|
|
25
25
|
: React.Children.toArray(children)
|
|
26
26
|
.filter((child) => typeof child === "string")
|
|
27
27
|
.join("");
|
|
28
|
-
|
|
28
|
+
const resolvedVariant = variant !== null && variant !== void 0 ? variant : "secondary";
|
|
29
|
+
const borderedClasses = {
|
|
30
|
+
secondary: "border-secondary-foreground/30",
|
|
31
|
+
muted: "border-muted-foreground/30",
|
|
32
|
+
destructive: "border-[hsl(var(--status-destructive-foreground))]/30",
|
|
33
|
+
outline: "border-foreground/30",
|
|
34
|
+
success: "border-[hsl(var(--status-success-foreground))]/30",
|
|
35
|
+
warning: "border-[hsl(var(--status-warning-foreground))]/30",
|
|
36
|
+
info: "border-[hsl(var(--status-info-foreground))]/30",
|
|
37
|
+
accent: "border-[hsl(var(--status-accent-foreground))]/30",
|
|
38
|
+
};
|
|
39
|
+
return (_jsx("div", { className: cn(badgeVariants({ variant }), bordered && borderedClasses[resolvedVariant], className), title: textContent || undefined, ...props, children: children }));
|
|
29
40
|
}
|
|
30
41
|
export { Badge, badgeVariants };
|
package/dist/breadcrumb.js
CHANGED
|
@@ -11,14 +11,14 @@ const BreadcrumbItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(
|
|
|
11
11
|
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
12
12
|
const BreadcrumbLink = React.forwardRef(({ asChild, className, ...props }, ref) => {
|
|
13
13
|
const Comp = asChild ? Slot : "a";
|
|
14
|
-
return (_jsx(Comp, { ref: ref, className: cn("transition-colors hover:text-foreground", className), ...props }));
|
|
14
|
+
return (_jsx(Comp, { ref: ref, className: cn("cursor-pointer transition-colors hover:text-foreground", className), ...props }));
|
|
15
15
|
});
|
|
16
16
|
BreadcrumbLink.displayName = "BreadcrumbLink";
|
|
17
17
|
const BreadcrumbPage = React.forwardRef(({ className, ...props }, ref) => (_jsx("span", { ref: ref, role: "link", "aria-disabled": "true", "aria-current": "page", className: cn("font-normal text-foreground", className), ...props })));
|
|
18
18
|
BreadcrumbPage.displayName = "BreadcrumbPage";
|
|
19
19
|
const BreadcrumbSeparator = ({ children, className, ...props }) => (_jsx("li", { role: "presentation", "aria-hidden": "true", className: cn("[&>svg]:h-3.5 [&>svg]:w-3.5", className), ...props, children: children !== null && children !== void 0 ? children : (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M6 3.5 10.5 8 6 12.5" }) })) }));
|
|
20
20
|
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
|
|
21
|
-
const BreadcrumbEllipsis = ({ className, ...props }) => (_jsxs("span", { role: "presentation", "aria-hidden": "true", className: cn("flex h-
|
|
21
|
+
const BreadcrumbEllipsis = ({ className, ...props }) => (_jsxs("span", { role: "presentation", "aria-hidden": "true", className: cn("flex h-control w-control items-center justify-center", className), ...props, children: [_jsx("span", { className: "text-lg leading-none", children: "\u2026" }), _jsx("span", { className: "sr-only", children: "More" })] }));
|
|
22
22
|
BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
|
|
23
23
|
function Breadcrumb({ items, separator, className, listClassName, itemClassName, linkClassName, currentClassName, ...props }) {
|
|
24
24
|
if (!items.length) {
|
package/dist/button.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "link" | "default" | "outline" | "
|
|
5
|
-
size?: "default" | "sm" | "icon" |
|
|
4
|
+
variant?: "link" | "default" | "outline" | "destructive" | "secondary" | "ghost" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "icon" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
8
|
/**
|
package/dist/button.js
CHANGED
|
@@ -14,10 +14,9 @@ const buttonVariants = cva("inline-flex cursor-pointer items-center justify-cent
|
|
|
14
14
|
link: "text-primary underline-offset-4 hover:underline",
|
|
15
15
|
},
|
|
16
16
|
size: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
icon: "h-10 w-10 [&_svg]:h-4 [&_svg]:w-4",
|
|
17
|
+
sm: "h-9 px-3 text-sm [&_svg]:h-4 [&_svg]:w-4",
|
|
18
|
+
default: "h-control px-4 py-2 [&_svg]:h-4 [&_svg]:w-4",
|
|
19
|
+
icon: "h-control w-control [&_svg]:h-4 [&_svg]:w-4",
|
|
21
20
|
},
|
|
22
21
|
},
|
|
23
22
|
defaultVariants: {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { DayButton, DayPicker } from "react-day-picker";
|
|
3
|
+
import { Button } from "./button";
|
|
4
|
+
declare function CalendarDayButton({ className, day, modifiers, children, disabled, onClick, onFocus, onBlur, onKeyDown, onMouseEnter, onMouseLeave, tabIndex, type, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, }: React.ComponentProps<typeof DayButton>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
|
|
6
|
+
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export { Calendar, CalendarDayButton };
|
package/dist/calendar.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
5
|
+
import { buttonVariants } from "./button";
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
function CalendarDayButton({ className, day, modifiers, children, disabled, onClick, onFocus, onBlur, onKeyDown, onMouseEnter, onMouseLeave, tabIndex, type, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, }) {
|
|
8
|
+
const defaultClassNames = getDefaultClassNames();
|
|
9
|
+
const ref = React.useRef(null);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
var _a;
|
|
12
|
+
if (modifiers.focused)
|
|
13
|
+
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
14
|
+
}, [modifiers.focused]);
|
|
15
|
+
return (_jsx("button", { ref: ref, type: type, disabled: disabled, onClick: onClick, onFocus: onFocus, onBlur: onBlur, onKeyDown: onKeyDown, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, tabIndex: tabIndex, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, "data-day": day.date.toLocaleDateString(), "data-selected-single": modifiers.selected &&
|
|
16
|
+
!modifiers.range_start &&
|
|
17
|
+
!modifiers.range_end &&
|
|
18
|
+
!modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, className: cn("inline-flex cursor-pointer items-center justify-center rounded-md text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 aspect-square w-full min-w-[--cell-size] font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px]", defaultClassNames.day, className), children: children }));
|
|
19
|
+
}
|
|
20
|
+
function Calendar({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", formatters, components, ...props }) {
|
|
21
|
+
const defaultClassNames = getDefaultClassNames();
|
|
22
|
+
return (_jsx(DayPicker, { showOutsideDays: showOutsideDays, className: cn("bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent", String.raw `rtl:**:[.rdp-button\_next>svg]:rotate-180`, String.raw `rtl:**:[.rdp-button\_previous>svg]:rotate-180`, className), captionLayout: captionLayout, formatters: {
|
|
23
|
+
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
24
|
+
...formatters,
|
|
25
|
+
}, classNames: {
|
|
26
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
27
|
+
months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
|
|
28
|
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
29
|
+
nav: cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", defaultClassNames.nav),
|
|
30
|
+
button_previous: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_previous),
|
|
31
|
+
button_next: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_next),
|
|
32
|
+
month_caption: cn("flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", defaultClassNames.month_caption),
|
|
33
|
+
dropdowns: cn("flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
|
|
34
|
+
dropdown_root: cn("has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border", defaultClassNames.dropdown_root),
|
|
35
|
+
dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
36
|
+
caption_label: cn("select-none font-medium", captionLayout === "label"
|
|
37
|
+
? "text-sm"
|
|
38
|
+
: "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5", defaultClassNames.caption_label),
|
|
39
|
+
table: "w-full border-collapse",
|
|
40
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
41
|
+
weekday: cn("text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", defaultClassNames.weekday),
|
|
42
|
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
43
|
+
week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
|
|
44
|
+
week_number: cn("text-muted-foreground select-none text-[0.8rem]", defaultClassNames.week_number),
|
|
45
|
+
day: cn("group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md", defaultClassNames.day),
|
|
46
|
+
range_start: cn("bg-accent rounded-l-md", defaultClassNames.range_start),
|
|
47
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
48
|
+
range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
|
|
49
|
+
today: cn("bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", defaultClassNames.today),
|
|
50
|
+
outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
|
|
51
|
+
disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
|
|
52
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
53
|
+
...classNames,
|
|
54
|
+
}, components: {
|
|
55
|
+
Root: ({ className: rootClassName, rootRef, ...rootProps }) => (_jsx("div", { "data-slot": "calendar", ref: rootRef, className: cn(rootClassName), ...rootProps })),
|
|
56
|
+
Chevron: ({ className: chevronClassName, orientation }) => {
|
|
57
|
+
const svgProps = {
|
|
58
|
+
className: cn("size-4", chevronClassName),
|
|
59
|
+
viewBox: "0 0 24 24",
|
|
60
|
+
fill: "none",
|
|
61
|
+
stroke: "currentColor",
|
|
62
|
+
strokeWidth: 2,
|
|
63
|
+
strokeLinecap: "round",
|
|
64
|
+
strokeLinejoin: "round",
|
|
65
|
+
"aria-hidden": true,
|
|
66
|
+
};
|
|
67
|
+
if (orientation === "left") {
|
|
68
|
+
return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m15 18-6-6 6-6" }) });
|
|
69
|
+
}
|
|
70
|
+
if (orientation === "right") {
|
|
71
|
+
return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m9 18 6-6-6-6" }) });
|
|
72
|
+
}
|
|
73
|
+
return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m6 9 6 6 6-6" }) });
|
|
74
|
+
},
|
|
75
|
+
DayButton: CalendarDayButton,
|
|
76
|
+
WeekNumber: ({ children, ...weekNumberProps }) => (_jsx("td", { ...weekNumberProps, children: _jsx("div", { className: "flex size-[--cell-size] items-center justify-center text-center", children: children }) })),
|
|
77
|
+
...components,
|
|
78
|
+
}, ...props }));
|
|
79
|
+
}
|
|
80
|
+
export { Calendar, CalendarDayButton };
|
package/dist/card.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
3
|
+
title: React.ReactNode;
|
|
4
|
+
description?: React.ReactNode;
|
|
5
|
+
variant?: "default" | "elevated" | "gradient";
|
|
6
|
+
size?: "default" | "compact";
|
|
7
|
+
/** Large value displayed above the title — use for stat/metric cards. */
|
|
8
|
+
stat?: React.ReactNode;
|
|
9
|
+
/** Small supporting text below the stat or body — use for sub-metrics. */
|
|
10
|
+
subMetric?: React.ReactNode;
|
|
11
|
+
footer?: React.ReactNode;
|
|
12
|
+
active?: boolean;
|
|
13
|
+
/** Replaces title/stat/subMetric with skeleton placeholders while data is loading. */
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
}
|
|
16
|
+
declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export { Card };
|
package/dist/card.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "./lib/utils";
|
|
5
|
+
import { Skeleton } from "./skeleton";
|
|
6
|
+
import { Typography } from "./typography";
|
|
7
|
+
const Card = React.forwardRef(({ title, description, variant = "default", size = "default", stat, subMetric, footer, active, loading = false, children, className, onClick, ...props }, ref) => {
|
|
8
|
+
const renderedTitle = React.isValidElement(title) ? (title) : (_jsx(Typography, { as: "p", variant: "label", color: variant === "gradient" ? "inherit" : "muted", className: variant === "gradient" ? "opacity-80" : undefined, children: title }));
|
|
9
|
+
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-lg border text-card-foreground", variant === "default" && "bg-card", variant === "elevated" && "bg-card shadow-sm", variant === "gradient" &&
|
|
11
|
+
"border-primary/20 bg-gradient-to-br from-primary to-primary/80 text-primary-foreground", active && "border-primary bg-primary/[0.04] ring-1 ring-primary/20", onClick && "cursor-pointer transition-colors hover:border-primary", className), ...props, children: [_jsxs("div", { className: cn("flex flex-col gap-2", size === "default" && "p-6", size === "compact" && "p-3"), children: [loading ? (_jsx(Skeleton, { className: "h-3.5 w-24" })) : (renderedTitle), loading
|
|
12
|
+
? 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-6 pt-0", size === "compact" && "p-3 pt-0"), children: children })) : null, footer ? (_jsx("div", { className: cn("flex items-center", size === "default" && "p-6 pt-0", size === "compact" && "p-3 pt-0"), children: footer })) : null] }));
|
|
14
|
+
});
|
|
15
|
+
Card.displayName = "Card";
|
|
16
|
+
export { Card };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
|
|
3
|
+
/** Renders the checkbox in an indeterminate (mixed) state. */
|
|
4
|
+
indeterminate?: boolean;
|
|
5
|
+
/** Visual size of the checkbox. */
|
|
6
|
+
size?: "sm" | "md" | "lg";
|
|
7
|
+
/** Label rendered next to the checkbox. When provided, the checkbox and label are wrapped in a `<label>`. */
|
|
8
|
+
label?: React.ReactNode;
|
|
9
|
+
/** Description shown below the label in smaller muted text. */
|
|
10
|
+
description?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
13
|
+
export { Checkbox };
|
package/dist/checkbox.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "./lib/utils";
|
|
5
|
+
import { Typography } from "./typography";
|
|
6
|
+
const sizeClasses = {
|
|
7
|
+
sm: "size-3.5",
|
|
8
|
+
md: "size-4",
|
|
9
|
+
lg: "size-5",
|
|
10
|
+
};
|
|
11
|
+
const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "md", checked, disabled, label, description, id, ...props }, ref) => {
|
|
12
|
+
const innerRef = React.useRef(null);
|
|
13
|
+
const generatedId = React.useId();
|
|
14
|
+
const inputId = id !== null && id !== void 0 ? id : `checkbox-${generatedId}`;
|
|
15
|
+
React.useImperativeHandle(ref, () => innerRef.current);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (innerRef.current) {
|
|
18
|
+
innerRef.current.indeterminate = indeterminate;
|
|
19
|
+
}
|
|
20
|
+
}, [indeterminate]);
|
|
21
|
+
const box = (_jsxs("span", { className: cn("relative inline-block shrink-0 rounded-sm border bg-background align-middle text-primary-foreground transition-colors", sizeClasses[size], (checked || indeterminate) && !disabled
|
|
22
|
+
? "border-primary bg-primary"
|
|
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
|
+
if (!label)
|
|
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] })] }));
|
|
27
|
+
});
|
|
28
|
+
Checkbox.displayName = "Checkbox";
|
|
29
|
+
export { Checkbox };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CollapsibleProps {
|
|
3
|
+
id?: string;
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
open?: boolean;
|
|
8
|
+
onOpenChange?: (open: boolean) => void;
|
|
9
|
+
/** Element rendered on the right of the header, before the chevron (e.g. an edit button). */
|
|
10
|
+
headerAction?: React.ReactNode;
|
|
11
|
+
/** Element rendered inline after the title (e.g. a tooltip icon). */
|
|
12
|
+
titleAdornment?: React.ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
headerClassName?: string;
|
|
15
|
+
contentClassName?: string;
|
|
16
|
+
}
|
|
17
|
+
declare function Collapsible({ id, title, children, defaultOpen, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }: CollapsibleProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
declare const CollapsibleSection: typeof Collapsible;
|
|
19
|
+
export { Collapsible, CollapsibleSection };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
|
|
5
|
+
import { ChevronUp } from "lucide-react";
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
import { Typography } from "./typography";
|
|
8
|
+
function Collapsible({ id, title, children, defaultOpen = true, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }) {
|
|
9
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultOpen);
|
|
10
|
+
const isControlled = openProp !== undefined;
|
|
11
|
+
const open = isControlled ? openProp : uncontrolled;
|
|
12
|
+
const setOpen = (next) => {
|
|
13
|
+
if (!isControlled)
|
|
14
|
+
setUncontrolled(next);
|
|
15
|
+
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
|
|
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-2 py-3", headerClassName), children: [_jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex flex-1 cursor-pointer items-center gap-2 text-left text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", children: [_jsx(Typography, { as: "h3", variant: "subheading", children: title }), titleAdornment] }) }), headerAction, _jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": open ? "Collapse section" : "Expand section", className: "group ml-1 cursor-pointer text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", children: _jsx(ChevronUp, { "aria-hidden": "true", className: "h-4 w-4 transition-transform duration-150 group-data-[state=closed]:rotate-180" }) }) })] }), _jsx(CollapsiblePrimitive.Content, { "data-slot": "collapsible-content", className: "overflow-hidden", children: _jsx("div", { className: cn("pb-6 pt-4", contentClassName), children: children }) })] }));
|
|
18
|
+
}
|
|
19
|
+
const CollapsibleSection = Collapsible;
|
|
20
|
+
export { Collapsible, CollapsibleSection };
|
package/dist/command-search.js
CHANGED
|
@@ -8,6 +8,7 @@ import { SearchIcon } from "./animated-icons/search";
|
|
|
8
8
|
import { DialogRoot, DialogSurface } from "./dialog-primitive";
|
|
9
9
|
import { FilterToggle } from "./filter-toggle";
|
|
10
10
|
import { cn } from "./lib/utils";
|
|
11
|
+
import { Typography } from "./typography";
|
|
11
12
|
import { SearchHighlight } from "./use-search-highlight";
|
|
12
13
|
function CommandSearchEmptyIcon({ className }) {
|
|
13
14
|
return _jsx(SearchIcon, { className: className, size: 20 });
|
|
@@ -57,14 +58,14 @@ function CommandSearch({ value, onValueChange, sections, children, className, is
|
|
|
57
58
|
}
|
|
58
59
|
}, [isOpen]);
|
|
59
60
|
return (_jsxs("div", { className: className, ...props, children: [_jsxs(Button, { type: "button", onClick: () => setIsOpen(true), variant: "ghost", className: cn(isCollapsed
|
|
60
|
-
? "h-
|
|
61
|
-
: "h-
|
|
61
|
+
? "h-control w-full justify-center rounded-lg px-3 !font-normal text-muted-foreground hover:bg-white hover:text-foreground"
|
|
62
|
+
: "h-control w-full min-w-[14rem] justify-start gap-3 rounded-lg border border-gray-200 bg-white px-3 !font-normal text-muted-foreground hover:bg-white hover:text-foreground"), 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-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground sm:inline-flex", children: resolvedLabel })] })) : null] }), _jsx(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, children: _jsx(DialogSurface, { className: cn("max-w-xl gap-0 overflow-hidden p-0 sm:max-w-xl", dialogClassName), hideCloseButton: true, children: _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 items-center gap-1 border-b px-3 py-2", children: [allFilter ? (_jsx(FilterToggle, { selected: allFilter.selected, onClick: allFilter.onSelect, children: allFilter.label })) : null, filters.map((filter) => (_jsx(FilterToggle, { selected: filter.selected, onClick: filter.onSelect, children: filter.label }, filter.value)))] })) : null, _jsx(CommandList, { className: cn("max-h-[400px] p-1", resultsClassName), children: 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: () => {
|
|
62
63
|
var _a;
|
|
63
64
|
(_a = item.onSelect) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
64
65
|
if (item.closeOnSelect !== false) {
|
|
65
66
|
setIsOpen(false);
|
|
66
67
|
}
|
|
67
|
-
}, children: _jsxs("div", { className: "min-w-0", children: [_jsx("p",
|
|
68
|
+
}, 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
|
|
68
69
|
? `No results found for "${value}".`
|
|
69
70
|
: "Results will appear here as you type." }))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
|
|
70
71
|
? `No results found for "${value}".`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onCopy"> {
|
|
3
|
+
/** Text to copy to the clipboard. */
|
|
4
|
+
value: string;
|
|
5
|
+
/** Milliseconds the "copied" state stays visible. */
|
|
6
|
+
feedbackDuration?: number;
|
|
7
|
+
/** Optional label rendered next to the icon. When omitted, renders as icon-only. */
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
/** Called after a successful copy. */
|
|
10
|
+
onCopy?: (value: string) => void;
|
|
11
|
+
/** Called if the clipboard write fails. */
|
|
12
|
+
onError?: (error: unknown) => void;
|
|
13
|
+
/** Accessible label for the icon-only button. Defaults to "Copy". */
|
|
14
|
+
copyLabel?: string;
|
|
15
|
+
/** Accessible label announced after copy. Defaults to "Copied". */
|
|
16
|
+
copiedLabel?: string;
|
|
17
|
+
}
|
|
18
|
+
declare function CopyButton({ value, feedbackDuration, children, onCopy, onError, copyLabel, copiedLabel, className, type, ...props }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export { CopyButton };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Copy } from "lucide-react";
|
|
5
|
+
import { CheckIcon } from "./animated-icons/check";
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
function CopyButton({ value, feedbackDuration = 1500, children, onCopy, onError, copyLabel = "Copy", copiedLabel = "Copied", className, type = "button", ...props }) {
|
|
8
|
+
const [copied, setCopied] = React.useState(false);
|
|
9
|
+
const timeoutRef = React.useRef(null);
|
|
10
|
+
React.useEffect(() => () => {
|
|
11
|
+
if (timeoutRef.current)
|
|
12
|
+
clearTimeout(timeoutRef.current);
|
|
13
|
+
}, []);
|
|
14
|
+
const handleCopy = React.useCallback(async () => {
|
|
15
|
+
try {
|
|
16
|
+
await navigator.clipboard.writeText(value);
|
|
17
|
+
setCopied(true);
|
|
18
|
+
onCopy === null || onCopy === void 0 ? void 0 : onCopy(value);
|
|
19
|
+
if (timeoutRef.current)
|
|
20
|
+
clearTimeout(timeoutRef.current);
|
|
21
|
+
timeoutRef.current = setTimeout(() => setCopied(false), feedbackDuration);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
25
|
+
}
|
|
26
|
+
}, [value, feedbackDuration, onCopy, onError]);
|
|
27
|
+
const iconOnly = children === undefined;
|
|
28
|
+
const label = copied ? copiedLabel : copyLabel;
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_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 })] }), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? copiedLabel : "" })] }));
|
|
30
|
+
}
|
|
31
|
+
export { CopyButton };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface DateInputProps {
|
|
3
|
+
label: React.ReactNode;
|
|
4
|
+
value: string;
|
|
5
|
+
onValueChange: (value: string) => void;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
error?: React.ReactNode;
|
|
8
|
+
invalid?: boolean;
|
|
9
|
+
hideLabel?: boolean;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
minDate?: Date;
|
|
13
|
+
maxDate?: Date;
|
|
14
|
+
className?: string;
|
|
15
|
+
triggerClassName?: string;
|
|
16
|
+
labelClassName?: string;
|
|
17
|
+
descriptionClassName?: string;
|
|
18
|
+
errorClassName?: string;
|
|
19
|
+
id?: string;
|
|
20
|
+
}
|
|
21
|
+
declare const DateInput: React.ForwardRefExoticComponent<DateInputProps & React.RefAttributes<HTMLButtonElement>>;
|
|
22
|
+
export { DateInput };
|