@neasg/design-system 0.4.7 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +121 -0
  2. package/dist/alert.d.ts +21 -2
  3. package/dist/alert.js +10 -3
  4. package/dist/avatar.d.ts +5 -2
  5. package/dist/avatar.js +76 -8
  6. package/dist/back-button.d.ts +2 -0
  7. package/dist/back-button.js +1 -1
  8. package/dist/badge.d.ts +3 -2
  9. package/dist/badge.js +9 -3
  10. package/dist/breadcrumb.js +2 -1
  11. package/dist/button.d.ts +1 -1
  12. package/dist/button.js +13 -10
  13. package/dist/calendar.js +10 -9
  14. package/dist/card.d.ts +29 -1
  15. package/dist/card.js +61 -7
  16. package/dist/checkbox.d.ts +2 -0
  17. package/dist/checkbox.js +2 -2
  18. package/dist/close-button.d.ts +6 -0
  19. package/dist/close-button.js +8 -0
  20. package/dist/collapsible.d.ts +7 -1
  21. package/dist/collapsible.js +2 -2
  22. package/dist/command-search.d.ts +16 -1
  23. package/dist/command-search.js +42 -16
  24. package/dist/command.js +3 -3
  25. package/dist/copy-button.d.ts +3 -1
  26. package/dist/copy-button.js +4 -2
  27. package/dist/count-badge.d.ts +3 -1
  28. package/dist/count-badge.js +10 -5
  29. package/dist/date-input.d.ts +18 -3
  30. package/dist/date-input.js +94 -21
  31. package/dist/dialog-primitive.js +4 -3
  32. package/dist/draggable-tabs.d.ts +7 -0
  33. package/dist/draggable-tabs.js +6 -5
  34. package/dist/drawer.js +2 -2
  35. package/dist/dropdown-button.d.ts +18 -0
  36. package/dist/dropdown-button.js +31 -0
  37. package/dist/edit-button.d.ts +10 -0
  38. package/dist/edit-button.js +7 -0
  39. package/dist/editable-table.d.ts +3 -1
  40. package/dist/editable-table.js +25 -12
  41. package/dist/field.d.ts +2 -2
  42. package/dist/field.js +4 -3
  43. package/dist/file-upload-status-toast.d.ts +28 -0
  44. package/dist/file-upload-status-toast.js +136 -0
  45. package/dist/file-upload.js +8 -7
  46. package/dist/filter-popover.d.ts +37 -0
  47. package/dist/filter-popover.js +73 -0
  48. package/dist/filter-toggle.js +2 -2
  49. package/dist/index.d.ts +45 -14
  50. package/dist/index.js +19 -4
  51. package/dist/input-control.d.ts +3 -2
  52. package/dist/input-control.js +3 -2
  53. package/dist/label-value-grid.d.ts +4 -2
  54. package/dist/label-value-grid.js +7 -6
  55. package/dist/label-value.js +3 -1
  56. package/dist/layout-right-panel-edge.d.ts +6 -0
  57. package/dist/layout-right-panel-edge.js +6 -0
  58. package/dist/layout.d.ts +77 -5
  59. package/dist/layout.js +439 -35
  60. package/dist/lib/date-utils.d.ts +10 -2
  61. package/dist/lib/date-utils.js +91 -11
  62. package/dist/lib/utils.js +8 -1
  63. package/dist/link.js +2 -2
  64. package/dist/message-item.d.ts +62 -0
  65. package/dist/message-item.js +148 -0
  66. package/dist/multi-select.js +31 -5
  67. package/dist/notification.d.ts +82 -0
  68. package/dist/notification.js +121 -0
  69. package/dist/otp-input.js +1 -1
  70. package/dist/page-header.js +1 -1
  71. package/dist/page-section.d.ts +2 -1
  72. package/dist/page-section.js +4 -3
  73. package/dist/pagination.js +2 -2
  74. package/dist/popover-menu.d.ts +23 -1
  75. package/dist/popover-menu.js +75 -5
  76. package/dist/popover-primitive.js +1 -1
  77. package/dist/progress.d.ts +5 -2
  78. package/dist/progress.js +6 -3
  79. package/dist/radio-group.d.ts +21 -0
  80. package/dist/radio-group.js +41 -0
  81. package/dist/rich-text-editor.d.ts +56 -0
  82. package/dist/rich-text-editor.js +394 -0
  83. package/dist/routing-timeline.d.ts +22 -0
  84. package/dist/routing-timeline.js +58 -0
  85. package/dist/scroll-hint.d.ts +8 -0
  86. package/dist/scroll-hint.js +7 -0
  87. package/dist/search-input-shell.js +1 -1
  88. package/dist/search-input.js +2 -2
  89. package/dist/section-nav.js +4 -4
  90. package/dist/select-primitive.js +3 -3
  91. package/dist/select.js +1 -1
  92. package/dist/skeleton.js +1 -1
  93. package/dist/styles.css +235 -57
  94. package/dist/table-column-visibility.d.ts +21 -0
  95. package/dist/table-column-visibility.js +74 -0
  96. package/dist/table-toolbar.js +1 -1
  97. package/dist/table.d.ts +12 -1
  98. package/dist/table.js +67 -33
  99. package/dist/tabs.d.ts +14 -3
  100. package/dist/tabs.js +60 -6
  101. package/dist/tailwind-preset.js +46 -0
  102. package/dist/task-mode-shell.d.ts +24 -0
  103. package/dist/task-mode-shell.js +110 -0
  104. package/dist/textarea.js +2 -1
  105. package/dist/theme-switcher.d.ts +28 -0
  106. package/dist/theme-switcher.js +27 -0
  107. package/dist/theme.d.ts +167 -0
  108. package/dist/theme.js +112 -0
  109. package/dist/toaster.js +5 -4
  110. package/dist/tooltip.js +1 -1
  111. package/dist/typography.d.ts +1 -1
  112. package/dist/typography.js +5 -5
  113. package/dist/workspace-header.d.ts +13 -0
  114. package/dist/workspace-header.js +11 -0
  115. package/package.json +15 -1
package/README.md CHANGED
@@ -17,6 +17,127 @@ npm run build
17
17
  npm run storybook
18
18
  ```
19
19
 
20
+ ## Package Usage
21
+
22
+ Import the stylesheet once at your app root before rendering package
23
+ components:
24
+
25
+ ```ts
26
+ import "@neasg/design-system/styles.css";
27
+ ```
28
+
29
+ Use the root package import by default:
30
+
31
+ ```ts
32
+ import {
33
+ Badge,
34
+ Button,
35
+ Card,
36
+ PageHeader,
37
+ Table,
38
+ Typography,
39
+ } from "@neasg/design-system";
40
+ ```
41
+
42
+ For Tailwind-based apps, use the exported preset so you inherit the shared
43
+ colors, font tokens, radius tokens, spacing, and motion defaults:
44
+
45
+ ```ts
46
+ // tailwind.config.ts
47
+ import type { Config } from "tailwindcss";
48
+ import {
49
+ neaDesignSystemContent,
50
+ neaTailwindPreset,
51
+ } from "@neasg/design-system";
52
+
53
+ const config: Config = {
54
+ presets: [neaTailwindPreset],
55
+ content: [
56
+ "./app/**/*.{ts,tsx}",
57
+ "./components/**/*.{ts,tsx}",
58
+ ...neaDesignSystemContent,
59
+ ],
60
+ };
61
+
62
+ export default config;
63
+ ```
64
+
65
+ Theme tokens are provided through the exported stylesheet. The default root font
66
+ size is 12.5px. If you want to change the package base font size, override
67
+ `--font-size-root` after importing the stylesheet:
68
+
69
+ ```css
70
+ :root {
71
+ --font-size-root: 14px;
72
+ }
73
+ ```
74
+
75
+ If you want the package font token to resolve to the actual Inter font in
76
+ Next.js, load it into `--font-sans`:
77
+
78
+ ```ts
79
+ import { Inter } from "next/font/google";
80
+
81
+ const inter = Inter({
82
+ subsets: ["latin"],
83
+ variable: "--font-sans",
84
+ });
85
+ ```
86
+
87
+ Use package components before creating app-local UI copies. If a reusable
88
+ pattern is missing, extract it into the design system instead of duplicating it
89
+ locally. This design system is light-theme only.
90
+
91
+ ## AI Usage
92
+
93
+ This design system includes the
94
+ [Storybook MCP addon](https://storybook.js.org/docs/ai/mcp/overview), which
95
+ lets AI coding assistants read component documentation, props, stories, and
96
+ usage examples from Storybook.
97
+
98
+ 1. Start Storybook in this repo:
99
+
100
+ ```bash
101
+ npm run storybook
102
+ ```
103
+
104
+ Storybook runs on `http://localhost:6007`, with the MCP endpoint at
105
+ `http://localhost:6007/mcp`.
106
+
107
+ 2. In the consuming project, add a `.mcp.json` at the project root:
108
+
109
+ ```json
110
+ {
111
+ "mcpServers": {
112
+ "nea-design-system": {
113
+ "type": "http",
114
+ "url": "http://localhost:6007/mcp"
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ 3. Restart your MCP-compatible AI tool. The docs toolset can list all
121
+ documentation, fetch documentation for a component, and fetch documentation
122
+ for a specific story. The development toolset can preview stories and fetch
123
+ Storybook story-writing instructions.
124
+
125
+ If you are not using MCP, give your AI coding assistant these instructions:
126
+
127
+ ```text
128
+ Use @neasg/design-system as the source of truth for shared UI.
129
+
130
+ - Use the Storybook MCP server to discover available components and their APIs before writing UI code.
131
+ - Prefer components from @neasg/design-system before creating app-local UI.
132
+ - Import components from the root package:
133
+ import { Button, Input, Card, Table, Typography } from "@neasg/design-system";
134
+ - Use the documented props-driven API. Do not build custom compositions from internal primitives.
135
+ - Use the package theme tokens and Tailwind preset instead of inventing ad hoc colors, spacing, or radius values.
136
+ - Use Typography for headings, body copy, labels, and captions.
137
+ - This design system is light-theme only. Do not generate dark-mode styles, tokens, or examples.
138
+ - If a needed shared pattern is missing, extract it into @neasg/design-system rather than duplicating it locally.
139
+ ```
140
+
20
141
  ## Publishing
21
142
 
22
143
  This package is built to `dist/` before publish. The public package entry points are the compiled files in `dist`, not the raw `src` files.
package/dist/alert.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
+ import { type ButtonProps } from "./button";
4
+ import { type CheckboxProps } from "./checkbox";
3
5
  declare const alertVariants: (props?: ({
4
- variant?: "info" | "success" | "warning" | "destructive" | null | undefined;
6
+ variant?: "destructive" | "info" | "success" | "warning" | null | undefined;
5
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
8
  export interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof alertVariants> {
7
9
  title?: React.ReactNode;
@@ -11,5 +13,22 @@ export interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "
11
13
  }>;
12
14
  action?: React.ReactNode;
13
15
  }
16
+ export interface AlertActionProps extends Omit<ButtonProps, "variant" | "size"> {
17
+ }
18
+ export interface AlertConsentProps extends Omit<AlertProps, "children" | "description" | "icon"> {
19
+ checked?: CheckboxProps["checked"];
20
+ defaultChecked?: CheckboxProps["defaultChecked"];
21
+ disabled?: CheckboxProps["disabled"];
22
+ required?: CheckboxProps["required"];
23
+ name?: CheckboxProps["name"];
24
+ value?: CheckboxProps["value"];
25
+ checkboxId?: CheckboxProps["id"];
26
+ checkboxClassName?: string;
27
+ label: React.ReactNode;
28
+ description?: React.ReactNode;
29
+ onCheckedChange?: (checked: boolean) => void;
30
+ }
31
+ declare const AlertAction: React.ForwardRefExoticComponent<AlertActionProps & React.RefAttributes<HTMLButtonElement>>;
14
32
  declare const Alert: React.ForwardRefExoticComponent<AlertProps & React.RefAttributes<HTMLDivElement>>;
15
- export { Alert, alertVariants };
33
+ declare const AlertConsent: React.ForwardRefExoticComponent<AlertConsentProps & React.RefAttributes<HTMLDivElement>>;
34
+ export { Alert, AlertAction, AlertConsent, alertVariants };
package/dist/alert.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cva } from "class-variance-authority";
4
+ import { Button } from "./button";
5
+ import { Checkbox } from "./checkbox";
4
6
  import { cn } from "./lib/utils";
5
7
  import { Typography } from "./typography";
6
- const alertVariants = cva("relative flex w-full items-start gap-3 rounded-md border px-4 py-3", {
8
+ const alertVariants = cva("relative flex w-full items-start gap-2 rounded-surface border px-4 py-3", {
7
9
  variants: {
8
10
  variant: {
9
11
  info: "border-[hsl(var(--status-info-foreground))]/20 bg-[hsl(var(--status-info))] text-[hsl(var(--status-info-foreground))]",
@@ -16,9 +18,14 @@ const alertVariants = cva("relative flex w-full items-start gap-3 rounded-md bor
16
18
  variant: "info",
17
19
  },
18
20
  });
21
+ const AlertAction = React.forwardRef(({ className, type = "button", ...props }, ref) => (_jsx(Button, { ref: ref, type: type, variant: "link", size: "compact", className: cn("h-auto min-h-6 px-0 text-inherit hover:text-inherit", className), ...props })));
22
+ AlertAction.displayName = "AlertAction";
19
23
  const Alert = React.forwardRef(({ variant, title, description, icon: Icon, action, className, children, role = "alert", ...props }, ref) => {
20
24
  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] }));
25
+ const hasStackedContent = Boolean(title);
26
+ return (_jsxs("div", { ref: ref, role: role, className: cn(alertVariants({ variant }), !hasStackedContent && "items-center", className), ...props, children: [Icon ? (_jsx(Icon, { className: cn("h-4 w-4 shrink-0", hasStackedContent && "mt-0.5") })) : 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-bold", children: title })) : null, body ? (_jsx(Typography, { as: "div", variant: "caption", color: "inherit", className: "opacity-95", children: body })) : null] }), action ? (_jsx("div", { className: cn("shrink-0 text-inherit [&_a]:text-inherit [&_button]:text-inherit [&_button:hover]:text-inherit", hasStackedContent ? "self-start" : "self-center"), children: action })) : null] }));
22
27
  });
23
28
  Alert.displayName = "Alert";
24
- export { Alert, alertVariants };
29
+ const AlertConsent = React.forwardRef(({ variant = "success", checked, defaultChecked, disabled, required, name, value, checkboxId, checkboxClassName, label, description, onCheckedChange, role = "status", className, ...props }, ref) => (_jsx(Alert, { ref: ref, variant: variant, role: role, className: cn("items-start", className), description: _jsx(Checkbox, { id: checkboxId, name: name, value: value, checked: checked, defaultChecked: defaultChecked, disabled: disabled, required: required, onChange: (event) => onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(event.target.checked), className: cn("[&>span:first-child]:mt-0.5", checkboxClassName), labelAlign: "start", label: label, description: description }), ...props })));
30
+ AlertConsent.displayName = "AlertConsent";
31
+ export { Alert, AlertAction, AlertConsent, alertVariants };
package/dist/avatar.d.ts CHANGED
@@ -3,7 +3,7 @@ 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
+ export type AvatarSize = "xs" | "sm" | "md";
7
7
  interface AvatarProps extends Omit<React.ComponentPropsWithoutRef<typeof AvatarRoot>, "children"> {
8
8
  src?: string | null;
9
9
  alt?: string;
@@ -20,6 +20,8 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
20
20
  size?: AvatarSize;
21
21
  loading?: boolean;
22
22
  name?: React.ReactNode;
23
+ nameAs?: React.ElementType;
24
+ nameTrailing?: React.ReactNode;
23
25
  role?: React.ReactNode;
24
26
  rolePlacement?: "above" | "below";
25
27
  topInfo?: React.ReactNode;
@@ -28,6 +30,7 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
28
30
  imageClassName?: string;
29
31
  fallbackClassName?: string;
30
32
  contentClassName?: string;
33
+ nameRowClassName?: string;
31
34
  nameClassName?: string;
32
35
  roleClassName?: string;
33
36
  topInfoClassName?: string;
@@ -35,7 +38,7 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
35
38
  avatarOverlay?: React.ReactNode;
36
39
  }
37
40
  declare function Avatar({ src, alt, fallback, size, loading, className, imageClassName, fallbackClassName, ...props }: AvatarProps): import("react/jsx-runtime").JSX.Element;
38
- declare function AvatarProfile({ src, alt, fallback, size, loading, name, role, rolePlacement, topInfo, bottomInfo, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, topInfoClassName, bottomInfoClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
41
+ declare function AvatarProfile({ src, alt, fallback, size, loading, name, nameAs: NameElement, nameTrailing, role, rolePlacement, topInfo, bottomInfo, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameRowClassName, nameClassName, roleClassName, topInfoClassName, bottomInfoClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
39
42
  export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
40
43
  export type AvatarRootProps = React.ComponentPropsWithoutRef<typeof AvatarRoot>;
41
44
  export type { AvatarProps, AvatarProfileProps };
package/dist/avatar.js CHANGED
@@ -11,28 +11,96 @@ AvatarImage.displayName = "AvatarImage";
11
11
  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 })));
12
12
  AvatarFallback.displayName = "AvatarFallback";
13
13
  const avatarSizeClasses = {
14
- sm: "h-8 w-8 text-xs",
15
- md: "h-10 w-10 text-sm",
14
+ xs: "h-[24px] w-[24px] text-[11px]",
15
+ sm: "h-[32px] w-[32px] text-xs",
16
+ md: "h-[40px] w-[40px] text-sm",
16
17
  };
18
+ const avatarProfileGapClasses = {
19
+ xs: "gap-2",
20
+ sm: "gap-2.5",
21
+ md: "gap-2.5",
22
+ };
23
+ const avatarProfileNameClasses = {
24
+ xs: "text-xs leading-4",
25
+ sm: "text-sm leading-5",
26
+ md: "text-sm leading-5",
27
+ };
28
+ const avatarProfileInfoClasses = {
29
+ xs: "text-[11px] leading-3",
30
+ sm: "text-xs leading-4",
31
+ md: "text-xs leading-4",
32
+ };
33
+ const avatarProfileContentGapClass = "gap-[2px]";
34
+ const avatarFallbackPalette = [
35
+ {
36
+ background: "var(--nea-green-100)",
37
+ foreground: "var(--nea-green-800)",
38
+ },
39
+ {
40
+ background: "var(--nea-blue-100)",
41
+ foreground: "var(--nea-blue-800)",
42
+ },
43
+ {
44
+ background: "var(--nea-amber-100)",
45
+ foreground: "var(--nea-amber-800)",
46
+ },
47
+ {
48
+ background: "var(--nea-violet-100)",
49
+ foreground: "var(--nea-violet-800)",
50
+ },
51
+ ];
52
+ function getAvatarFallbackSeed(value) {
53
+ if (value === null || value === undefined || typeof value === "boolean") {
54
+ return "";
55
+ }
56
+ if (typeof value === "string" || typeof value === "number") {
57
+ return String(value);
58
+ }
59
+ if (Array.isArray(value)) {
60
+ return value.map(getAvatarFallbackSeed).join("");
61
+ }
62
+ if (React.isValidElement(value)) {
63
+ return getAvatarFallbackSeed(value.props.children);
64
+ }
65
+ return "";
66
+ }
67
+ function getAvatarFallbackTone(seed) {
68
+ let hash = 0;
69
+ for (let index = 0; index < seed.length; index += 1) {
70
+ hash = (hash * 31 + seed.charCodeAt(index)) >>> 0;
71
+ }
72
+ return avatarFallbackPalette[hash % avatarFallbackPalette.length];
73
+ }
17
74
  function Avatar({ src, alt = "", fallback, size = "sm", loading = false, className, imageClassName, fallbackClassName, ...props }) {
18
75
  if (loading) {
19
76
  return (_jsx(Skeleton, { className: cn("shrink-0 rounded-full", avatarSizeClasses[size], className), ...props }));
20
77
  }
21
- 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 })] }));
78
+ const fallbackTone = getAvatarFallbackTone(getAvatarFallbackSeed(fallback) || alt || "avatar");
79
+ const fallbackStyle = {
80
+ "--avatar-fallback-background": fallbackTone.background,
81
+ "--avatar-fallback-foreground": fallbackTone.foreground,
82
+ };
83
+ return (_jsxs(AvatarRoot, { className: cn(avatarSizeClasses[size], className), ...props, children: [src ? (_jsx(AvatarImage, { src: src, alt: alt, className: imageClassName })) : null, _jsx(AvatarFallback, { style: fallbackStyle, className: cn("bg-[hsl(var(--avatar-fallback-background))] font-medium text-[hsl(var(--avatar-fallback-foreground))]", fallbackClassName), children: fallback })] }));
22
84
  }
23
- function AvatarProfile({ src, alt = "", fallback, size = "sm", loading = false, name, role, rolePlacement = "above", topInfo, bottomInfo, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, topInfoClassName, bottomInfoClassName, avatarOverlay, ...props }) {
85
+ function AvatarProfile({ src, alt = "", fallback, size = "sm", loading = false, name, nameAs: NameElement = "span", nameTrailing, role, rolePlacement = "below", topInfo, bottomInfo, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameRowClassName, nameClassName, roleClassName, topInfoClassName, bottomInfoClassName, avatarOverlay, ...props }) {
24
86
  const resolvedTop = topInfo !== null && topInfo !== void 0 ? topInfo : (rolePlacement === "above" ? role : undefined);
25
87
  const resolvedBottom = bottomInfo !== null && bottomInfo !== void 0 ? bottomInfo : (rolePlacement === "below" ? role : undefined);
88
+ const hasSupportingInfo = (resolvedTop !== undefined && resolvedTop !== null) ||
89
+ (resolvedBottom !== undefined && resolvedBottom !== null);
90
+ const alignmentClassName = hasSupportingInfo ? "items-start" : "items-center";
91
+ const avatarOffsetClassName = hasSupportingInfo ? "mt-0.5" : undefined;
26
92
  if (loading) {
27
- return (_jsxs("div", { className: cn("flex items-center gap-2", className), "aria-busy": "true", ...props, children: [_jsx(Skeleton, { className: cn("shrink-0 rounded-full", avatarSizeClasses[size], avatarClassName) }), _jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col gap-1.5", contentClassName), children: [resolvedTop !== undefined ? (_jsx(Skeleton, { className: "h-3 w-20" })) : null, _jsx(Skeleton, { className: "h-4 w-32" }), resolvedBottom !== undefined ? (_jsx(Skeleton, { className: "h-3 w-20" })) : null] })] }));
93
+ return (_jsxs("div", { className: cn("flex min-w-0 max-w-full", alignmentClassName, avatarProfileGapClasses[size], className), "aria-busy": "true", ...props, children: [_jsx(Skeleton, { className: cn("shrink-0 rounded-full", avatarSizeClasses[size], avatarOffsetClassName, avatarClassName) }), _jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col", avatarProfileContentGapClass, contentClassName), children: [resolvedTop !== undefined ? (_jsx(Skeleton, { className: "h-3 w-20" })) : null, _jsx(Skeleton, { className: "h-4 w-32" }), resolvedBottom !== undefined ? (_jsx(Skeleton, { className: "h-3 w-20" })) : null] })] }));
28
94
  }
29
95
  const hasMeta = name !== undefined ||
96
+ nameTrailing !== undefined ||
30
97
  resolvedTop !== undefined ||
31
98
  resolvedBottom !== undefined;
32
- const infoBaseClass = "truncate text-[10px] leading-tight font-medium uppercase tracking-wide text-muted-foreground";
99
+ const infoBaseClass = cn("min-w-0 truncate text-muted-foreground", avatarProfileInfoClasses[size]);
33
100
  const topNode = resolvedTop !== undefined && resolvedTop !== null ? (_jsx("span", { className: cn(infoBaseClass, topInfo !== undefined ? topInfoClassName : roleClassName), children: resolvedTop })) : null;
34
101
  const bottomNode = resolvedBottom !== undefined && resolvedBottom !== null ? (_jsx("span", { className: cn(infoBaseClass, bottomInfo !== undefined ? bottomInfoClassName : roleClassName), children: resolvedBottom })) : null;
35
- const nameNode = name ? (_jsx("span", { className: cn("truncate text-sm leading-tight font-medium text-foreground", nameClassName), children: name })) : null;
36
- 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: [topNode, nameNode, bottomNode] })) : null] }));
102
+ const nameTextNode = name !== undefined && name !== null ? (_jsx(NameElement, { className: cn("min-w-0 truncate font-medium text-foreground", avatarProfileNameClasses[size], nameClassName), children: name })) : null;
103
+ const nameNode = nameTrailing !== undefined && nameTrailing !== null ? (_jsxs("div", { className: cn("flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1", nameRowClassName), children: [nameTextNode, nameTrailing] })) : (nameTextNode);
104
+ return (_jsxs("div", { className: cn("flex min-w-0 max-w-full", alignmentClassName, avatarProfileGapClasses[size], className), ...props, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: src, alt: alt, fallback: fallback, size: size, className: cn(avatarOffsetClassName, avatarClassName), imageClassName: imageClassName, fallbackClassName: fallbackClassName }), avatarOverlay] }), hasMeta ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col", avatarProfileContentGapClass, contentClassName), children: [topNode, nameNode, bottomNode] })) : null] }));
37
105
  }
38
106
  export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
@@ -1,6 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { type ButtonProps } from "./button";
3
3
  export interface BackButtonProps extends Omit<ButtonProps, "asChild" | "size" | "variant"> {
4
+ /** Use `muted` for nested panel backs; keep `default` for leaving a page or task workspace. */
5
+ tone?: "default" | "muted";
4
6
  }
5
7
  declare const BackButton: React.ForwardRefExoticComponent<BackButtonProps & React.RefAttributes<HTMLButtonElement>>;
6
8
  export { BackButton };
@@ -3,6 +3,6 @@ import * as React from "react";
3
3
  import { ChevronLeftIcon } from "./animated-icons/chevron-left";
4
4
  import { Button } from "./button";
5
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 })] })));
6
+ const BackButton = React.forwardRef(({ children = "Back", className, tone = "default", 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", tone === "muted" && "text-muted-foreground hover:text-foreground", className), ...props, children: [_jsx(ChevronLeftIcon, { "aria-hidden": "true", className: "shrink-0", size: 16 }), _jsx("span", { children: children })] })));
7
7
  BackButton.displayName = "BackButton";
8
8
  export { BackButton };
package/dist/badge.d.ts CHANGED
@@ -1,7 +1,8 @@
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" | "info" | "success" | "warning" | "destructive" | "secondary" | "accent" | null | undefined;
4
+ variant?: "accent" | "muted" | "outline" | "destructive" | "secondary" | "info" | "success" | "warning" | null | undefined;
5
+ size?: "default" | "icon" | null | undefined;
5
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
7
  /**
7
8
  * Visual status label used for short categorical values like case state,
@@ -12,5 +13,5 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, Varian
12
13
  /** Show a visible border matching the badge colour. */
13
14
  bordered?: boolean;
14
15
  }
15
- declare function Badge({ className, variant, bordered, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
16
+ declare function Badge({ className, variant, size, bordered, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
16
17
  export { Badge, badgeVariants };
package/dist/badge.js CHANGED
@@ -2,7 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { cn } from "./lib/utils";
5
- const badgeVariants = cva("inline-flex max-w-[200px] items-center justify-center text-center rounded-md border px-2 py-0.5 text-xs font-semibold uppercase transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 truncate", {
5
+ import { Typography } from "./typography";
6
+ const badgeVariants = cva("inline-flex items-center justify-center text-center rounded-md border transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 truncate", {
6
7
  variants: {
7
8
  variant: {
8
9
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
@@ -14,12 +15,17 @@ const badgeVariants = cva("inline-flex max-w-[200px] items-center justify-center
14
15
  info: "border-transparent bg-[hsl(var(--status-info))] text-[hsl(var(--status-info-foreground))]",
15
16
  accent: "border-transparent bg-[hsl(var(--status-accent))] text-[hsl(var(--status-accent-foreground))]",
16
17
  },
18
+ size: {
19
+ default: "max-w-[200px] px-2 py-0.5",
20
+ icon: "h-5 w-5 min-w-5 max-w-5 shrink-0 px-0 py-0",
21
+ },
17
22
  },
18
23
  defaultVariants: {
19
24
  variant: "secondary",
25
+ size: "default",
20
26
  },
21
27
  });
22
- function Badge({ className, variant, bordered = false, children, ...props }) {
28
+ function Badge({ className, variant, size, bordered = false, children, ...props }) {
23
29
  const textContent = typeof children === "string"
24
30
  ? children
25
31
  : React.Children.toArray(children)
@@ -36,6 +42,6 @@ function Badge({ className, variant, bordered = false, children, ...props }) {
36
42
  info: "border-[hsl(var(--status-info-foreground))]/30",
37
43
  accent: "border-[hsl(var(--status-accent-foreground))]/30",
38
44
  };
39
- return (_jsx("div", { className: cn(badgeVariants({ variant }), bordered && borderedClasses[resolvedVariant], className), title: textContent || undefined, ...props, children: children }));
45
+ return (_jsx("div", { className: cn(badgeVariants({ variant, size }), bordered && borderedClasses[resolvedVariant], className), title: textContent || undefined, ...props, children: _jsx(Typography, { as: "span", variant: "eyebrow", color: "inherit", className: "inline-flex min-w-0 max-w-full items-center gap-1 truncate", children: children }) }));
40
46
  }
41
47
  export { Badge, badgeVariants };
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Slot } from "@radix-ui/react-slot";
5
5
  import { cn } from "./lib/utils";
6
+ import { Typography } from "./typography";
6
7
  const BreadcrumbNav = React.forwardRef(({ ...props }, ref) => _jsx("nav", { ref: ref, "aria-label": "breadcrumb", ...props }));
7
8
  BreadcrumbNav.displayName = "BreadcrumbNav";
8
9
  const BreadcrumbList = React.forwardRef(({ className, ...props }, ref) => (_jsx("ol", { ref: ref, className: cn("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", className), ...props })));
@@ -18,7 +19,7 @@ const BreadcrumbPage = React.forwardRef(({ className, ...props }, ref) => (_jsx(
18
19
  BreadcrumbPage.displayName = "BreadcrumbPage";
19
20
  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
21
  BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
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
+ 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(Typography, { as: "span", variant: "subheading", color: "inherit", children: "\u2026" }), _jsx("span", { className: "sr-only", children: "More" })] }));
22
23
  BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
23
24
  function Breadcrumb({ items, separator, className, listClassName, itemClassName, linkClassName, currentClassName, ...props }) {
24
25
  if (!items.length) {
package/dist/button.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
4
  variant?: "link" | "default" | "outline" | "destructive" | "secondary" | "ghost" | null | undefined;
5
- size?: "default" | "sm" | "icon" | null | undefined;
5
+ size?: "default" | "sm" | "compact" | "icon" | "compactIcon" | 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
@@ -3,20 +3,22 @@ import * as React from "react";
3
3
  import { Slot } from "@radix-ui/react-slot";
4
4
  import { cva } from "class-variance-authority";
5
5
  import { cn } from "./lib/utils";
6
- const buttonVariants = cva("inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0", {
6
+ const buttonVariants = cva("inline-flex cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-control text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 disabled:pointer-events-none [&_svg]:h-4 [&_svg]:min-h-4 [&_svg]:w-4 [&_svg]:min-w-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", {
7
7
  variants: {
8
8
  variant: {
9
9
  default: "bg-primary text-primary-foreground hover:bg-primary/90",
10
10
  destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
11
- outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
11
+ outline: "border border-[hsl(var(--button-outline-border))] bg-[hsl(var(--button-outline-background))] text-foreground hover:bg-[hsl(var(--button-outline-hover-background))] hover:text-accent-foreground",
12
12
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
13
13
  ghost: "hover:bg-accent hover:text-accent-foreground",
14
- link: "text-primary underline-offset-4 hover:underline",
14
+ link: "text-primary underline-offset-4 hover:text-primary/85 hover:underline",
15
15
  },
16
16
  size: {
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",
17
+ sm: "h-8 px-2.5 text-sm",
18
+ compact: "h-8 gap-1 px-2 text-sm",
19
+ default: "h-control px-3 py-1.5",
20
+ icon: "h-control w-control",
21
+ compactIcon: "h-8 w-8",
20
22
  },
21
23
  },
22
24
  defaultVariants: {
@@ -25,7 +27,7 @@ const buttonVariants = cva("inline-flex cursor-pointer items-center justify-cent
25
27
  },
26
28
  });
27
29
  function DefaultLoadingIndicator() {
28
- return (_jsx("span", { "aria-hidden": "true", className: "h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent" }));
30
+ return (_jsx("span", { "aria-hidden": "true", className: "h-4 min-h-4 w-4 min-w-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent" }));
29
31
  }
30
32
  function hasTextLikeContent(node) {
31
33
  if (typeof node === "string") {
@@ -75,7 +77,7 @@ function attachAnimatedIconRefs(node, refs) {
75
77
  return node;
76
78
  }
77
79
  if (Array.isArray(node)) {
78
- return node.map((child) => attachAnimatedIconRefs(child, refs));
80
+ return React.Children.map(node, (child) => attachAnimatedIconRefs(child, refs));
79
81
  }
80
82
  if (!React.isValidElement(node)) {
81
83
  return node;
@@ -104,8 +106,9 @@ const Button = React.forwardRef(({ className, variant, size, asChild = false, lo
104
106
  const loadingLabel = loadingText !== null && loadingText !== void 0 ? loadingText : children;
105
107
  const animatedIconRefs = React.useRef([]);
106
108
  animatedIconRefs.current = [];
107
- if (size === "icon" && hasTextLikeContent(children)) {
108
- throw new Error('NEA Button `size="icon"` only accepts icon components or SVG content. Do not pass text or emoji.');
109
+ if ((size === "icon" || size === "compactIcon") &&
110
+ hasTextLikeContent(children)) {
111
+ throw new Error('NEA Button `size="icon"` and `size="compactIcon"` only accepts icon components or SVG content. Do not pass text or emoji.');
109
112
  }
110
113
  const content = loading ? (loadingLabel ? (_jsxs("span", { className: "inline-flex items-center gap-2", children: [loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}), _jsx("span", { children: attachAnimatedIconRefs(loadingLabel, animatedIconRefs) })] })) : (loadingIndicator !== null && loadingIndicator !== void 0 ? loadingIndicator : _jsx(DefaultLoadingIndicator, {}))) : (attachAnimatedIconRefs(children, animatedIconRefs));
111
114
  const startAnimatedIcons = () => {
package/dist/calendar.js CHANGED
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { DayPicker, getDefaultClassNames } from "react-day-picker";
5
5
  import { buttonVariants } from "./button";
6
6
  import { cn } from "./lib/utils";
7
+ import { Typography } from "./typography";
7
8
  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
9
  const defaultClassNames = getDefaultClassNames();
9
10
  const ref = React.useRef(null);
@@ -15,7 +16,7 @@ function CalendarDayButton({ className, day, modifiers, children, disabled, onCl
15
16
  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
17
  !modifiers.range_start &&
17
18
  !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
+ !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-control 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-primary/10 data-[range-middle=true]:text-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] data-[range-end=true]:rounded-control data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-control group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px]", defaultClassNames.day, className), children: _jsx(Typography, { as: "span", variant: "bodySm", color: "inherit", children: children }) }));
19
20
  }
20
21
  function Calendar({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", formatters, components, ...props }) {
21
22
  const defaultClassNames = getDefaultClassNames();
@@ -31,22 +32,22 @@ function Calendar({ className, classNames, showOutsideDays = true, captionLayout
31
32
  button_next: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_next),
32
33
  month_caption: cn("flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", defaultClassNames.month_caption),
33
34
  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_root: cn("has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-control border", defaultClassNames.dropdown_root),
35
36
  dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
36
37
  caption_label: cn("select-none font-medium", captionLayout === "label"
37
38
  ? "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
+ : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-control pl-2 pr-1 text-sm [&>svg]:size-3.5", defaultClassNames.caption_label),
39
40
  table: "w-full border-collapse",
40
41
  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
+ weekday: cn("text-muted-foreground flex-1 select-none rounded-control text-[0.8rem] font-normal", defaultClassNames.weekday),
42
43
  week: cn("mt-2 flex w-full", defaultClassNames.week),
43
44
  week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
44
45
  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),
46
+ 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-[var(--radius-control)] [&:last-child[data-selected=true]_button]:rounded-r-[var(--radius-control)]", defaultClassNames.day),
47
+ range_start: cn("bg-primary/10 rounded-l-[var(--radius-control)]", defaultClassNames.range_start),
48
+ range_middle: cn("bg-primary/10 rounded-none", defaultClassNames.range_middle),
49
+ range_end: cn("bg-primary/10 rounded-r-[var(--radius-control)]", defaultClassNames.range_end),
50
+ today: cn("bg-accent text-accent-foreground rounded-control data-[selected=true]:rounded-none", defaultClassNames.today),
50
51
  outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
51
52
  disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
52
53
  hidden: cn("invisible", defaultClassNames.hidden),
package/dist/card.d.ts CHANGED
@@ -10,8 +10,36 @@ export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "t
10
10
  subMetric?: React.ReactNode;
11
11
  footer?: React.ReactNode;
12
12
  active?: boolean;
13
+ accent?: "primary";
13
14
  /** Replaces title/stat/subMetric with skeleton placeholders while data is loading. */
14
15
  loading?: boolean;
15
16
  }
17
+ export interface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {
18
+ columns?: 1 | 2 | 3 | 4;
19
+ align?: "stretch" | "start";
20
+ }
21
+ export interface CardSplitGridProps extends React.HTMLAttributes<HTMLDivElement> {
22
+ asideWidth?: "sm" | "md" | "lg";
23
+ breakpoint?: "lg" | "xl";
24
+ align?: "stretch" | "start";
25
+ }
26
+ export interface CardListProps extends React.HTMLAttributes<HTMLDivElement> {
27
+ density?: "default" | "compact";
28
+ variant?: "cards" | "divided";
29
+ }
30
+ export interface CardListItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
31
+ label: React.ReactNode;
32
+ description?: React.ReactNode;
33
+ leading?: React.ReactNode;
34
+ leadingVariant?: "badge" | "plain";
35
+ trailing?: React.ReactNode;
36
+ meta?: React.ReactNode;
37
+ labelLines?: 1 | 2;
38
+ descriptionLines?: 1 | 2;
39
+ }
16
40
  declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
17
- export { Card };
41
+ declare function CardGrid({ columns, align, className, ...props }: CardGridProps): import("react/jsx-runtime").JSX.Element;
42
+ declare function CardSplitGrid({ asideWidth, breakpoint, align, className, ...props }: CardSplitGridProps): import("react/jsx-runtime").JSX.Element;
43
+ declare function CardList({ density, variant, className, ...props }: CardListProps): import("react/jsx-runtime").JSX.Element;
44
+ declare function CardListItem({ label, description, leading, leadingVariant, trailing, meta, labelLines, descriptionLines, className, onClick, ...props }: CardListItemProps): import("react/jsx-runtime").JSX.Element;
45
+ export { Card, CardGrid, CardSplitGrid, CardList, CardListItem };