infinity-ui-elements 1.7.12 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Alert/Alert.d.ts +60 -0
- package/dist/components/Alert/Alert.d.ts.map +1 -0
- package/dist/components/Alert/Alert.stories.d.ts +16 -0
- package/dist/components/Alert/Alert.stories.d.ts.map +1 -0
- package/dist/components/Alert/index.d.ts +3 -0
- package/dist/components/Alert/index.d.ts.map +1 -0
- package/dist/components/Avatar/Avatar.d.ts +1 -1
- package/dist/components/Badge/Badge.d.ts +2 -2
- package/dist/components/Button/Button.d.ts +3 -3
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/ButtonGroup/ButtonGroup.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +1 -1
- package/dist/components/Counter/Counter.d.ts +1 -1
- package/dist/components/Divider/Divider.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.stories.d.ts +60 -60
- package/dist/components/IconButton/IconButton.d.ts +22 -0
- package/dist/components/IconButton/IconButton.d.ts.map +1 -0
- package/dist/components/IconButton/IconButton.stories.d.ts +17 -0
- package/dist/components/IconButton/IconButton.stories.d.ts.map +1 -0
- package/dist/components/IconButton/index.d.ts +3 -0
- package/dist/components/IconButton/index.d.ts.map +1 -0
- package/dist/components/Link/Link.d.ts +3 -3
- package/dist/components/Link/Link.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +1 -1
- package/dist/components/Radio/Radio.d.ts +1 -1
- package/dist/components/SearchableDropdown/SearchableDropdown.stories.d.ts +74 -74
- package/dist/components/Select/Select.d.ts +2 -2
- package/dist/components/Switch/Switch.d.ts +1 -1
- package/dist/components/TabItem/TabItem.d.ts +1 -1
- package/dist/components/Table/Table.d.ts +1 -5
- package/dist/components/Table/Table.d.ts.map +1 -1
- package/dist/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/components/Table/TableBody.d.ts +2 -5
- package/dist/components/Table/TableBody.d.ts.map +1 -1
- package/dist/components/Table/TableHeader.d.ts +1 -3
- package/dist/components/Table/TableHeader.d.ts.map +1 -1
- package/dist/components/Table/tableVariants.d.ts +3 -3
- package/dist/components/TextArea/TextArea.d.ts +2 -2
- package/dist/components/TextField/TextField.d.ts +2 -2
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +961 -600
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +963 -598
- package/dist/index.js.map +1 -1
- package/dist/lib/icons.d.ts +3 -0
- package/dist/lib/icons.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,14 +1,120 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
|
-
import { clsx } from 'clsx';
|
|
5
|
-
import { twMerge } from 'tailwind-merge';
|
|
6
4
|
import { Slot } from '@radix-ui/react-slot';
|
|
7
5
|
import { PulseLoader, ClipLoader } from 'react-spinners';
|
|
6
|
+
import { clsx } from 'clsx';
|
|
7
|
+
import { twMerge } from 'tailwind-merge';
|
|
8
8
|
import { ExternalLink, Loader2, Search, X, ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
9
9
|
import { createPortal } from 'react-dom';
|
|
10
10
|
import { flexRender } from '@tanstack/react-table';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* ==============================================
|
|
14
|
+
* HOW TO ADD A NEW ICON:
|
|
15
|
+
* ==============================================
|
|
16
|
+
*
|
|
17
|
+
* 1. Add your SVG file to: src/assets/icons/{iconName}.svg
|
|
18
|
+
*
|
|
19
|
+
* 2. Copy the SVG content from the file
|
|
20
|
+
*
|
|
21
|
+
* 3. Add it to the iconRegistry below:
|
|
22
|
+
* iconName: `<svg>...</svg>`,
|
|
23
|
+
*
|
|
24
|
+
* 4. Use it anywhere in your app:
|
|
25
|
+
* <Icon name="iconName" size={24} />
|
|
26
|
+
*
|
|
27
|
+
* The Icon component will automatically:
|
|
28
|
+
* - Replace hardcoded colors with currentColor
|
|
29
|
+
* - Allow you to control color via className or style
|
|
30
|
+
* - Resize based on the size prop
|
|
31
|
+
* ==============================================
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Icon registry - maps icon names to their SVG content
|
|
35
|
+
* Add your icons here by copying the SVG content from your icon files
|
|
36
|
+
*/
|
|
37
|
+
const iconRegistry = {
|
|
38
|
+
// Tick/Check icon
|
|
39
|
+
tick: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
40
|
+
<path d="M10.364 15.1924L19.5564 6L20.9706 7.41421L10.364 18.0208L4 11.6569L5.41422 10.2427L10.364 15.1924Z" fill="#081416"/>
|
|
41
|
+
</svg>`,
|
|
42
|
+
// Alias: check points to the same icon as tick
|
|
43
|
+
check: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
44
|
+
<path d="M10.364 15.1924L19.5564 6L20.9706 7.41421L10.364 18.0208L4 11.6569L5.41422 10.2427L10.364 15.1924Z" fill="#081416"/>
|
|
45
|
+
</svg>`,
|
|
46
|
+
add: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
47
|
+
<path d="M12.9 11.0999L21 11.0997V12.8997L12.9 12.8999V21H11.1V12.8999L3.00004 12.9001L3 11.1001L11.1 11.0999L11.0999 3.00001L12.8999 3L12.9 11.0999Z" fill="#081416"/>
|
|
48
|
+
</svg>`,
|
|
49
|
+
// Info icon
|
|
50
|
+
info: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
51
|
+
<path d="M12 22.5C6.20101 22.5 1.5 17.7989 1.5 12C1.5 6.20101 6.20101 1.5 12 1.5C17.7989 1.5 22.5 6.20101 22.5 12C22.5 17.7989 17.7989 22.5 12 22.5ZM12 20.4C16.6392 20.4 20.4 16.6392 20.4 12C20.4 7.36081 16.6392 3.6 12 3.6C7.36081 3.6 3.6 7.36081 3.6 12C3.6 16.6392 7.36081 20.4 12 20.4ZM10.95 6.75H13.05V8.85H10.95V6.75ZM10.95 10.95H13.05V17.25H10.95V10.95Z" fill="#081416"/>
|
|
52
|
+
</svg>
|
|
53
|
+
`,
|
|
54
|
+
// Exclamation/Warning icon
|
|
55
|
+
exclamation: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
56
|
+
<path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM13 17H11V15H13V17ZM13 13H11V7H13V13Z" fill="#081416"/>
|
|
57
|
+
</svg>`,
|
|
58
|
+
// Close/X icon
|
|
59
|
+
close: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
60
|
+
<path d="M18 6L6 18M6 6L18 18" stroke="#081416" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
61
|
+
</svg>`,
|
|
62
|
+
};
|
|
63
|
+
const Icon = ({ name, size = 24, className = "", style = {}, ...props }) => {
|
|
64
|
+
const svgContent = iconRegistry[name];
|
|
65
|
+
if (!svgContent) {
|
|
66
|
+
console.warn(`Icon "${String(name)}" not found in registry.\n` +
|
|
67
|
+
`Available icons: ${Object.keys(iconRegistry).join(", ")}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// Parse the SVG content
|
|
71
|
+
const parser = new DOMParser();
|
|
72
|
+
const svgDoc = parser.parseFromString(svgContent, "image/svg+xml");
|
|
73
|
+
const svgElement = svgDoc.querySelector("svg");
|
|
74
|
+
if (!svgElement) {
|
|
75
|
+
console.error(`Invalid SVG content for icon "${String(name)}"`);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
// Get the viewBox for proper scaling
|
|
79
|
+
const viewBox = svgElement.getAttribute("viewBox") || "0 0 24 24";
|
|
80
|
+
// Get all SVG content as string and replace hardcoded colors with currentColor
|
|
81
|
+
let innerSVG = svgElement.innerHTML;
|
|
82
|
+
// Replace common hardcoded colors with currentColor
|
|
83
|
+
// This allows the icon to inherit text color from parent
|
|
84
|
+
innerSVG = innerSVG
|
|
85
|
+
.replace(/fill="[^"]*"/g, 'fill="currentColor"')
|
|
86
|
+
.replace(/stroke="[^"]*"/g, 'stroke="currentColor"');
|
|
87
|
+
return (jsx("svg", { width: size, height: size, viewBox: viewBox, className: className, style: style, xmlns: "http://www.w3.org/2000/svg", ...props, dangerouslySetInnerHTML: { __html: innerSVG } }));
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Get all available icon names from the registry
|
|
91
|
+
* @returns Array of registered icon names
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* const icons = getAvailableIcons();
|
|
96
|
+
* console.log(icons); // ['tick', 'check', ...]
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
function getAvailableIcons() {
|
|
100
|
+
return Object.keys(iconRegistry);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if an icon exists in the registry
|
|
104
|
+
* @param name - Icon name to check
|
|
105
|
+
* @returns true if the icon exists
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```tsx
|
|
109
|
+
* if (hasIcon('tick')) {
|
|
110
|
+
* // Icon exists
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
function hasIcon(name) {
|
|
115
|
+
return name in iconRegistry;
|
|
116
|
+
}
|
|
117
|
+
|
|
12
118
|
// Define patterns for custom classes that should be preserved
|
|
13
119
|
// This approach is more scalable than hardcoding individual class names
|
|
14
120
|
const CUSTOM_CLASS_PATTERNS = [
|
|
@@ -48,123 +154,12 @@ function cn(...inputs) {
|
|
|
48
154
|
return clsx(mergedStandard, customClasses);
|
|
49
155
|
}
|
|
50
156
|
|
|
51
|
-
|
|
52
|
-
function getTextClassName(variant = "body", size = "medium", weight = "regular", color = "default") {
|
|
53
|
-
// Build the base class name
|
|
54
|
-
let baseClass = `text-${variant}`;
|
|
55
|
-
// Add size
|
|
56
|
-
if (size) {
|
|
57
|
-
baseClass += `-${size}`;
|
|
58
|
-
}
|
|
59
|
-
// Add weight
|
|
60
|
-
if (weight) {
|
|
61
|
-
baseClass += `-${weight}`;
|
|
62
|
-
}
|
|
63
|
-
// Add color class separately
|
|
64
|
-
const colorClass = `text-color-${color}`;
|
|
65
|
-
return `${baseClass} ${colorClass}`;
|
|
66
|
-
}
|
|
67
|
-
const Text = React.forwardRef(({ className, variant = "body", size = "medium", weight = "regular", color = "default", as = "p", children, ...props }, ref) => {
|
|
68
|
-
const Component = as;
|
|
69
|
-
const textClass = getTextClassName(variant, size, weight, color);
|
|
70
|
-
return React.createElement(Component, {
|
|
71
|
-
className: cn(textClass, className),
|
|
72
|
-
ref,
|
|
73
|
-
...props,
|
|
74
|
-
}, children);
|
|
75
|
-
});
|
|
76
|
-
Text.displayName = "Text";
|
|
77
|
-
|
|
78
|
-
const inverseColorClasses = {
|
|
79
|
-
a1: "bg-avatar-fill-a1-on-bg text-avatar-fill-a1-bg",
|
|
80
|
-
a2: "bg-avatar-fill-a2-on-bg text-avatar-fill-a2-bg",
|
|
81
|
-
a3: "bg-avatar-fill-a3-on-bg text-avatar-fill-a3-bg",
|
|
82
|
-
a4: "bg-avatar-fill-a4-on-bg text-avatar-fill-a4-bg",
|
|
83
|
-
a5: "bg-avatar-fill-a5-on-bg text-avatar-fill-a5-bg",
|
|
84
|
-
};
|
|
85
|
-
const avatarVariants = cva("inline-flex items-center justify-center font-medium text-center select-none", {
|
|
86
|
-
variants: {
|
|
87
|
-
color: {
|
|
88
|
-
a1: "bg-avatar-fill-a1-bg text-avatar-fill-a1-on-bg",
|
|
89
|
-
a2: "bg-avatar-fill-a2-bg text-avatar-fill-a2-on-bg",
|
|
90
|
-
a3: "bg-avatar-fill-a3-bg text-avatar-fill-a3-on-bg",
|
|
91
|
-
a4: "bg-avatar-fill-a4-bg text-avatar-fill-a4-on-bg",
|
|
92
|
-
a5: "bg-avatar-fill-a5-bg text-avatar-fill-a5-on-bg",
|
|
93
|
-
},
|
|
94
|
-
size: {
|
|
95
|
-
small: "h-[24px] w-[24px] text-body-medium-regular rounded-large",
|
|
96
|
-
medium: "h-[32px] w-[32px] text-body-medium-regular rounded-xlarge",
|
|
97
|
-
xlarge: "h-[36px] w-[36px] text-body-medium-regular rounded-xlarge",
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
defaultVariants: {
|
|
101
|
-
color: "a1",
|
|
102
|
-
size: "medium",
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
const statusVariants = cva("absolute flex items-center justify-center rounded-full border-2 border-surface-fill-neutral-intense", {
|
|
106
|
-
variants: {
|
|
107
|
-
size: {
|
|
108
|
-
small: "h-5 w-5 -bottom-0.5 -right-0.5",
|
|
109
|
-
medium: "h-6 w-6 -bottom-1 -right-1",
|
|
110
|
-
xlarge: "h-6 w-6 -bottom-1 -right-1",
|
|
111
|
-
},
|
|
112
|
-
statusColor: {
|
|
113
|
-
positive: "bg-action-fill-positive-default",
|
|
114
|
-
negative: "bg-action-fill-negative-default",
|
|
115
|
-
notice: "bg-action-fill-notice-default",
|
|
116
|
-
info: "bg-action-fill-info-default",
|
|
117
|
-
neutral: "bg-action-fill-neutral-default",
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
defaultVariants: {
|
|
121
|
-
size: "medium",
|
|
122
|
-
statusColor: "notice",
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
const Avatar = React.forwardRef(({ className, appearance = "default", color, size, children, src, alt, showStatus = false, statusColor = "notice", statusIcon, label, trailingComponent, containerClassName, ...props }, ref) => {
|
|
126
|
-
const [imageError, setImageError] = React.useState(false);
|
|
127
|
-
const handleImageError = () => {
|
|
128
|
-
setImageError(true);
|
|
129
|
-
};
|
|
130
|
-
const getStatusIconSize = () => {
|
|
131
|
-
switch (size) {
|
|
132
|
-
case "small":
|
|
133
|
-
return "h-3.5 w-3.5";
|
|
134
|
-
case "medium":
|
|
135
|
-
return "h-4 w-4";
|
|
136
|
-
default:
|
|
137
|
-
return "h-4 w-4";
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
const getTextSize = () => {
|
|
141
|
-
switch (size) {
|
|
142
|
-
case "small":
|
|
143
|
-
return "small";
|
|
144
|
-
case "medium":
|
|
145
|
-
return "medium";
|
|
146
|
-
default:
|
|
147
|
-
return "medium";
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
const resolvedColor = color ?? "a1";
|
|
151
|
-
const avatarElement = (jsxs("div", { className: "relative inline-block", children: [jsx("div", { className: cn(avatarVariants({ color: resolvedColor, size }), appearance === "inverse"
|
|
152
|
-
? inverseColorClasses[resolvedColor]
|
|
153
|
-
: undefined, className), ...props, children: src && !imageError ? (jsx("img", { src: src, alt: alt || "Avatar", className: cn("h-full w-full object-cover", size === "small" ? "rounded-large" : "rounded-xlarge"), onError: handleImageError })) : (children) }), showStatus && (jsx("div", { className: cn(statusVariants({ size, statusColor })), children: statusIcon && (jsx("span", { className: cn("text-action-ink-on-primary-normal", getStatusIconSize()), children: statusIcon })) }))] }));
|
|
154
|
-
// If no label or trailing component, return just the avatar
|
|
155
|
-
if (!label && !trailingComponent) {
|
|
156
|
-
return jsx("div", { ref: ref, children: avatarElement });
|
|
157
|
-
}
|
|
158
|
-
// Otherwise, return avatar with label and/or trailing component
|
|
159
|
-
return (jsxs("div", { ref: ref, className: cn("inline-flex items-center gap-3", containerClassName), children: [avatarElement, label && (jsx(Text, { variant: "body", size: getTextSize(), weight: "medium", color: "default", as: "span", children: label })), trailingComponent && (jsx("span", { className: "ml-auto", children: trailingComponent }))] }));
|
|
160
|
-
});
|
|
161
|
-
Avatar.displayName = "Avatar";
|
|
162
|
-
|
|
163
|
-
const badgeVariants = cva("inline-flex items-center whitespace-nowrap transition-colors", {
|
|
157
|
+
const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none", {
|
|
164
158
|
variants: {
|
|
165
159
|
variant: {
|
|
166
|
-
|
|
167
|
-
|
|
160
|
+
primary: "bg-action-fill-primary-default text-action-ink-on-primary-normal hover:bg-action-fill-primary-hover",
|
|
161
|
+
secondary: "border",
|
|
162
|
+
tertiary: "hover:bg-accent hover:text-accent-foreground",
|
|
168
163
|
},
|
|
169
164
|
color: {
|
|
170
165
|
primary: "",
|
|
@@ -173,171 +168,45 @@ const badgeVariants = cva("inline-flex items-center whitespace-nowrap transition
|
|
|
173
168
|
notice: "",
|
|
174
169
|
info: "",
|
|
175
170
|
neutral: "",
|
|
171
|
+
white: "",
|
|
176
172
|
},
|
|
177
173
|
size: {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
xsmall: "md:h-[28px] px-3 rounded-medium text-body-small-medium",
|
|
175
|
+
small: "md:h-[32px] px-4 rounded-medium text-body-small-medium",
|
|
176
|
+
medium: "md:h-[36px] px-5 py-2 rounded-large text-body-medium-medium",
|
|
177
|
+
large: "md:h-[44px] px-6 rounded-large text-body-large-medium",
|
|
178
|
+
},
|
|
179
|
+
isIconOnly: {
|
|
180
|
+
true: "aspect-square p-0",
|
|
181
|
+
false: "",
|
|
182
|
+
},
|
|
183
|
+
isLoading: {
|
|
184
|
+
true: "cursor-not-allowed",
|
|
185
|
+
false: "",
|
|
186
|
+
},
|
|
187
|
+
isDisabled: {
|
|
188
|
+
true: "cursor-not-allowed",
|
|
189
|
+
false: "cursor-pointer",
|
|
190
|
+
},
|
|
191
|
+
isFullWidth: {
|
|
192
|
+
true: "flex w-full",
|
|
193
|
+
false: "flex w-fit",
|
|
181
194
|
},
|
|
182
195
|
},
|
|
183
196
|
compoundVariants: [
|
|
184
|
-
//
|
|
197
|
+
// Primary variant colors
|
|
185
198
|
{
|
|
186
|
-
variant: "
|
|
199
|
+
variant: "primary",
|
|
187
200
|
color: "primary",
|
|
188
|
-
class:
|
|
201
|
+
class: `bg-action-fill-primary-default text-action-ink-on-primary-normal
|
|
202
|
+
hover:bg-action-fill-primary-hover
|
|
203
|
+
disabled:bg-action-fill-primary-disabled
|
|
204
|
+
disabled:text-action-ink-primary-disabled,
|
|
205
|
+
active:bg-action-fill-primary-activated
|
|
206
|
+
`,
|
|
189
207
|
},
|
|
190
208
|
{
|
|
191
|
-
variant: "
|
|
192
|
-
color: "positive",
|
|
193
|
-
class: "bg-action-fill-positive-faded text-action-ink-positive-normal",
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
variant: "light",
|
|
197
|
-
color: "negative",
|
|
198
|
-
class: "bg-action-fill-negative-faded text-action-ink-negative-normal",
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
variant: "light",
|
|
202
|
-
color: "notice",
|
|
203
|
-
class: "bg-action-fill-notice-faded text-action-ink-notice-normal",
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
variant: "light",
|
|
207
|
-
color: "info",
|
|
208
|
-
class: "bg-action-fill-info-faded text-action-ink-info-normal",
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
variant: "light",
|
|
212
|
-
color: "neutral",
|
|
213
|
-
class: "bg-action-fill-neutral-faded text-action-ink-neutral-normal",
|
|
214
|
-
},
|
|
215
|
-
// Filled variant colors
|
|
216
|
-
{
|
|
217
|
-
variant: "filled",
|
|
218
|
-
color: "primary",
|
|
219
|
-
class: "bg-action-fill-primary-default text-action-ink-on-primary-normal",
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
variant: "filled",
|
|
223
|
-
color: "positive",
|
|
224
|
-
class: "bg-action-fill-positive-default text-action-ink-on-primary-normal",
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
variant: "filled",
|
|
228
|
-
color: "negative",
|
|
229
|
-
class: "bg-action-fill-negative-default text-action-ink-on-primary-normal",
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
variant: "filled",
|
|
233
|
-
color: "notice",
|
|
234
|
-
class: "bg-action-fill-notice-default text-action-ink-on-primary-normal",
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
variant: "filled",
|
|
238
|
-
color: "info",
|
|
239
|
-
class: "bg-action-fill-info-default text-action-ink-on-primary-normal",
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
variant: "filled",
|
|
243
|
-
color: "neutral",
|
|
244
|
-
class: "bg-action-fill-neutral-default text-action-ink-on-primary-normal",
|
|
245
|
-
},
|
|
246
|
-
],
|
|
247
|
-
defaultVariants: {
|
|
248
|
-
variant: "light",
|
|
249
|
-
color: "info",
|
|
250
|
-
size: "medium",
|
|
251
|
-
},
|
|
252
|
-
});
|
|
253
|
-
const Badge = React.forwardRef(({ className, variant, size, color, showDot = false, children, ...props }, ref) => {
|
|
254
|
-
const getDotColor = () => {
|
|
255
|
-
if (variant === "filled") {
|
|
256
|
-
return "bg-action-ink-on-primary-normal";
|
|
257
|
-
}
|
|
258
|
-
// Light variant - use the corresponding action color
|
|
259
|
-
switch (color) {
|
|
260
|
-
case "primary":
|
|
261
|
-
return "bg-action-fill-primary-default";
|
|
262
|
-
case "positive":
|
|
263
|
-
return "bg-action-fill-positive-default";
|
|
264
|
-
case "negative":
|
|
265
|
-
return "bg-action-fill-negative-default";
|
|
266
|
-
case "notice":
|
|
267
|
-
return "bg-action-fill-notice-default";
|
|
268
|
-
case "info":
|
|
269
|
-
return "bg-action-fill-info-default";
|
|
270
|
-
case "neutral":
|
|
271
|
-
return "bg-action-fill-neutral-default";
|
|
272
|
-
default:
|
|
273
|
-
return "bg-action-fill-info-default";
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
const getDotSize = () => {
|
|
277
|
-
if (size === "small") {
|
|
278
|
-
return "h-2 w-2";
|
|
279
|
-
}
|
|
280
|
-
if (size === "medium") {
|
|
281
|
-
return "h-[6px] w-[6px]";
|
|
282
|
-
}
|
|
283
|
-
return "h-3 w-3";
|
|
284
|
-
};
|
|
285
|
-
return (jsxs("div", { ref: ref, className: cn(badgeVariants({ variant, size, color }), className), ...props, children: [showDot && (jsx("span", { className: cn("rounded-full", getDotColor(), getDotSize()), "aria-hidden": "true" })), children] }));
|
|
286
|
-
});
|
|
287
|
-
Badge.displayName = "Badge";
|
|
288
|
-
|
|
289
|
-
const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none", {
|
|
290
|
-
variants: {
|
|
291
|
-
variant: {
|
|
292
|
-
primary: "bg-action-fill-primary-default text-action-ink-on-primary-normal hover:bg-action-fill-primary-hover",
|
|
293
|
-
secondary: "border",
|
|
294
|
-
tertiary: "hover:bg-accent hover:text-accent-foreground",
|
|
295
|
-
},
|
|
296
|
-
color: {
|
|
297
|
-
primary: "",
|
|
298
|
-
positive: "",
|
|
299
|
-
negative: "",
|
|
300
|
-
notice: "",
|
|
301
|
-
info: "",
|
|
302
|
-
neutral: "",
|
|
303
|
-
},
|
|
304
|
-
size: {
|
|
305
|
-
xsmall: "md:h-[28px] px-3 rounded-medium text-body-small-medium",
|
|
306
|
-
small: "md:h-[32px] px-4 rounded-medium text-body-small-medium",
|
|
307
|
-
medium: "md:h-[36px] px-5 py-2 rounded-large text-body-medium-medium",
|
|
308
|
-
large: "md:h-[44px] px-6 rounded-large text-body-large-medium",
|
|
309
|
-
},
|
|
310
|
-
isIconOnly: {
|
|
311
|
-
true: "aspect-square p-0",
|
|
312
|
-
false: "",
|
|
313
|
-
},
|
|
314
|
-
isLoading: {
|
|
315
|
-
true: "cursor-not-allowed",
|
|
316
|
-
false: "",
|
|
317
|
-
},
|
|
318
|
-
isDisabled: {
|
|
319
|
-
true: "cursor-not-allowed",
|
|
320
|
-
false: "cursor-pointer",
|
|
321
|
-
},
|
|
322
|
-
isFullWidth: {
|
|
323
|
-
true: "flex w-full",
|
|
324
|
-
false: "flex w-fit",
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
compoundVariants: [
|
|
328
|
-
// Primary variant colors
|
|
329
|
-
{
|
|
330
|
-
variant: "primary",
|
|
331
|
-
color: "primary",
|
|
332
|
-
class: `bg-action-fill-primary-default text-action-ink-on-primary-normal
|
|
333
|
-
hover:bg-action-fill-primary-hover
|
|
334
|
-
disabled:bg-action-fill-primary-disabled
|
|
335
|
-
disabled:text-action-ink-primary-disabled,
|
|
336
|
-
active:bg-action-fill-primary-activated
|
|
337
|
-
`,
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
variant: "primary",
|
|
209
|
+
variant: "primary",
|
|
341
210
|
color: "positive",
|
|
342
211
|
class: `bg-action-fill-positive-default text-action-ink-on-primary-normal
|
|
343
212
|
hover:bg-action-fill-positive-hover
|
|
@@ -386,6 +255,16 @@ const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap
|
|
|
386
255
|
active:bg-action-fill-neutral-activated
|
|
387
256
|
`,
|
|
388
257
|
},
|
|
258
|
+
{
|
|
259
|
+
variant: "primary",
|
|
260
|
+
color: "white",
|
|
261
|
+
class: `bg-action-fill-white-default text-action-ink-neutral-subtle
|
|
262
|
+
hover:bg-action-fill-white-hover
|
|
263
|
+
disabled:bg-action-fill-white-disabled
|
|
264
|
+
disabled:text-action-ink-neutral-disabled
|
|
265
|
+
active:bg-action-fill-white-activated
|
|
266
|
+
`,
|
|
267
|
+
},
|
|
389
268
|
// Secondary variant colors
|
|
390
269
|
{
|
|
391
270
|
variant: "secondary",
|
|
@@ -474,6 +353,19 @@ const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap
|
|
|
474
353
|
active:bg-action-fill-neutral-faded-activated
|
|
475
354
|
`,
|
|
476
355
|
},
|
|
356
|
+
{
|
|
357
|
+
variant: "secondary",
|
|
358
|
+
color: "white",
|
|
359
|
+
class: `border-action-outline-white-faded
|
|
360
|
+
text-action-ink-on-primary-subtle
|
|
361
|
+
hover:border-action-outline-white-faded-hover
|
|
362
|
+
hover:bg-action-fill-white-faded-hover
|
|
363
|
+
disabled:text-surface-ink-white-disabled
|
|
364
|
+
disabled:border-action-outline-white-disabled
|
|
365
|
+
active:border-action-outline-white-faded-activated
|
|
366
|
+
active:bg-action-fill-white-faded-activated
|
|
367
|
+
`,
|
|
368
|
+
},
|
|
477
369
|
// Tertiary variant colors
|
|
478
370
|
{
|
|
479
371
|
variant: "tertiary",
|
|
@@ -529,6 +421,16 @@ const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap
|
|
|
529
421
|
active:bg-action-fill-neutral-faded-activated
|
|
530
422
|
`,
|
|
531
423
|
},
|
|
424
|
+
{
|
|
425
|
+
variant: "tertiary",
|
|
426
|
+
color: "white",
|
|
427
|
+
class: `text-action-ink-white-subtle
|
|
428
|
+
hover:bg-action-white-faded-hover
|
|
429
|
+
disabled:text-action-ink-white-disabled
|
|
430
|
+
disabled:bg-action-fill-white-disabled
|
|
431
|
+
active:bg-action-white-faded-activated
|
|
432
|
+
`,
|
|
433
|
+
},
|
|
532
434
|
// Icon only sizing
|
|
533
435
|
{
|
|
534
436
|
isIconOnly: true,
|
|
@@ -563,7 +465,13 @@ const buttonVariants = cva("items-center gap-3 justify-center whitespace-nowrap
|
|
|
563
465
|
const Button = React.forwardRef(({ className, variant = "primary", color = "primary", size, isIconOnly, isLoading, asChild = false, leadingIcon, trailingIcon, isFullWidth = false, children, disabled, ...props }, ref) => {
|
|
564
466
|
const Comp = asChild ? Slot : "button";
|
|
565
467
|
const isDisabled = disabled || isLoading || false;
|
|
566
|
-
const
|
|
468
|
+
const getLoaderColor = () => {
|
|
469
|
+
if (color === "white") {
|
|
470
|
+
return "var(--color-surface-ink-neutral-normal)";
|
|
471
|
+
}
|
|
472
|
+
return `var(--color-action-ink-${color}-normal)`;
|
|
473
|
+
};
|
|
474
|
+
const buttonContent = (jsxs(Fragment, { children: [isLoading && !isIconOnly && (jsx(PulseLoader, { color: getLoaderColor(), size: 10 })), isLoading && isIconOnly && (jsx(ClipLoader, { color: getLoaderColor(), size: 20 })), !isLoading && leadingIcon && (jsx("span", { className: "mr-2", children: leadingIcon })), !isIconOnly && !isLoading && children, isIconOnly && !isLoading && children, !isLoading && trailingIcon && jsx("span", { children: trailingIcon })] }));
|
|
567
475
|
return (jsx(Comp, { className: cn(buttonVariants({
|
|
568
476
|
variant,
|
|
569
477
|
color,
|
|
@@ -574,7 +482,752 @@ const Button = React.forwardRef(({ className, variant = "primary", color = "prim
|
|
|
574
482
|
isFullWidth,
|
|
575
483
|
}), className), ref: ref, disabled: isDisabled, ...props, children: buttonContent }));
|
|
576
484
|
});
|
|
577
|
-
Button.displayName = "Button";
|
|
485
|
+
Button.displayName = "Button";
|
|
486
|
+
|
|
487
|
+
const iconButtonVariants = cva("inline-flex items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none p-0 border-0 bg-transparent", {
|
|
488
|
+
variants: {
|
|
489
|
+
color: {
|
|
490
|
+
primary: "",
|
|
491
|
+
positive: "",
|
|
492
|
+
negative: "",
|
|
493
|
+
notice: "",
|
|
494
|
+
info: "",
|
|
495
|
+
neutral: "",
|
|
496
|
+
white: "",
|
|
497
|
+
},
|
|
498
|
+
size: {
|
|
499
|
+
xsmall: "",
|
|
500
|
+
small: "",
|
|
501
|
+
medium: "",
|
|
502
|
+
large: "",
|
|
503
|
+
},
|
|
504
|
+
isLoading: {
|
|
505
|
+
true: "cursor-not-allowed",
|
|
506
|
+
false: "",
|
|
507
|
+
},
|
|
508
|
+
isDisabled: {
|
|
509
|
+
true: "cursor-not-allowed",
|
|
510
|
+
false: "cursor-pointer",
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
defaultVariants: {
|
|
514
|
+
color: "primary",
|
|
515
|
+
size: "medium",
|
|
516
|
+
isLoading: false,
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
const IconButton = React.forwardRef(({ className, color = "primary", size = "medium", isLoading, asChild = false, icon, iconElement, disabled, ...props }, ref) => {
|
|
520
|
+
const Comp = asChild ? Slot : "button";
|
|
521
|
+
const isDisabled = disabled || isLoading || false;
|
|
522
|
+
const getLoaderColor = () => {
|
|
523
|
+
if (color === "white") {
|
|
524
|
+
return "var(--color-surface-ink-neutral-normal)";
|
|
525
|
+
}
|
|
526
|
+
return `var(--color-action-ink-${color}-normal)`;
|
|
527
|
+
};
|
|
528
|
+
const getIconSize = () => {
|
|
529
|
+
switch (size) {
|
|
530
|
+
case "xsmall":
|
|
531
|
+
return 16;
|
|
532
|
+
case "small":
|
|
533
|
+
return 18;
|
|
534
|
+
case "medium":
|
|
535
|
+
return 20;
|
|
536
|
+
case "large":
|
|
537
|
+
return 24;
|
|
538
|
+
default:
|
|
539
|
+
return 20;
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
const getIconColorClass = () => {
|
|
543
|
+
// Color classes with normal, hover, focus, and disabled states
|
|
544
|
+
const colorMap = {
|
|
545
|
+
primary: "text-action-ink-primary-normal hover:text-action-ink-primary-subtle focus-visible:text-action-ink-primary-subtle disabled:text-action-ink-primary-muted",
|
|
546
|
+
positive: "text-action-ink-positive-normal hover:text-action-ink-positive-subtle focus-visible:text-action-ink-positive-subtle disabled:text-action-ink-positive-muted",
|
|
547
|
+
negative: "text-action-ink-negative-normal hover:text-action-ink-negative-subtle focus-visible:text-action-ink-negative-subtle disabled:text-action-ink-negative-muted",
|
|
548
|
+
notice: "text-action-ink-notice-normal hover:text-action-ink-notice-subtle focus-visible:text-action-ink-notice-subtle disabled:text-action-ink-notice-muted",
|
|
549
|
+
info: "text-action-ink-info-normal hover:text-action-ink-info-subtle focus-visible:text-action-ink-info-subtle disabled:text-action-ink-info-muted",
|
|
550
|
+
neutral: "text-action-ink-neutral-normal hover:text-action-ink-neutral-subtle focus-visible:text-action-ink-neutral-subtle disabled:text-action-ink-neutral-muted",
|
|
551
|
+
white: "text-surface-ink-white-subtle hover:text-surface-ink-white-normal focus-visible:text-surface-ink-white-normal disabled:text-surface-ink-white-muted",
|
|
552
|
+
};
|
|
553
|
+
return colorMap[color] || colorMap.primary;
|
|
554
|
+
};
|
|
555
|
+
const buttonContent = (jsx(Fragment, { children: isLoading ? (jsx(ClipLoader, { color: getLoaderColor(), size: getIconSize() })) : icon ? (jsx(Icon, { name: icon, size: getIconSize(), className: getIconColorClass() })) : iconElement ? (jsx("span", { className: getIconColorClass(), children: iconElement })) : null }));
|
|
556
|
+
return (jsx(Comp, { className: cn(iconButtonVariants({
|
|
557
|
+
color,
|
|
558
|
+
size,
|
|
559
|
+
isLoading,
|
|
560
|
+
isDisabled,
|
|
561
|
+
}), className), ref: ref, disabled: isDisabled, ...props, children: buttonContent }));
|
|
562
|
+
});
|
|
563
|
+
IconButton.displayName = "IconButton";
|
|
564
|
+
|
|
565
|
+
const linkVariants = cva("inline-flex items-center gap-1 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none decoration-1 underline-offset-4", {
|
|
566
|
+
variants: {
|
|
567
|
+
type: {
|
|
568
|
+
anchor: "hover:underline",
|
|
569
|
+
action: "no-underline cursor-pointer",
|
|
570
|
+
},
|
|
571
|
+
color: {
|
|
572
|
+
primary: "",
|
|
573
|
+
positive: "",
|
|
574
|
+
negative: "",
|
|
575
|
+
notice: "",
|
|
576
|
+
info: "",
|
|
577
|
+
neutral: "",
|
|
578
|
+
white: "",
|
|
579
|
+
},
|
|
580
|
+
size: {
|
|
581
|
+
xsmall: "text-body-xsmall-medium gap-1",
|
|
582
|
+
small: "text-body-small-medium gap-1",
|
|
583
|
+
medium: "text-body-medium-medium gap-1.5",
|
|
584
|
+
large: "text-body-large-medium gap-1.5",
|
|
585
|
+
},
|
|
586
|
+
isIconOnly: {
|
|
587
|
+
true: "no-underline",
|
|
588
|
+
false: "",
|
|
589
|
+
},
|
|
590
|
+
isDisabled: {
|
|
591
|
+
true: "cursor-not-allowed opacity-50",
|
|
592
|
+
false: "cursor-pointer",
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
compoundVariants: [
|
|
596
|
+
// Primary color variants
|
|
597
|
+
{
|
|
598
|
+
color: "primary",
|
|
599
|
+
class: `text-action-ink-primary-normal
|
|
600
|
+
hover:text-action-ink-primary-subtle
|
|
601
|
+
hover:decoration-action-outline-primary-hover
|
|
602
|
+
disabled:text-action-ink-primary-disabled
|
|
603
|
+
focus:text-action-ink-primary-hover
|
|
604
|
+
`,
|
|
605
|
+
},
|
|
606
|
+
// Positive color variants
|
|
607
|
+
{
|
|
608
|
+
color: "positive",
|
|
609
|
+
class: `text-action-ink-positive-normal
|
|
610
|
+
hover:text-action-ink-positive-subtle
|
|
611
|
+
hover:decoration-action-outline-positive-hover
|
|
612
|
+
hover:text-action-ink-positive-hover
|
|
613
|
+
disabled:text-action-ink-positive-disabled
|
|
614
|
+
focus:text-action-ink-positive-hover
|
|
615
|
+
`,
|
|
616
|
+
},
|
|
617
|
+
// Negative color variants
|
|
618
|
+
{
|
|
619
|
+
color: "negative",
|
|
620
|
+
class: `text-action-ink-negative-normal
|
|
621
|
+
hover:text-action-ink-negative-subtle
|
|
622
|
+
hover:decoration-action-outline-negative-hover
|
|
623
|
+
hover:text-action-ink-negative-hover
|
|
624
|
+
disabled:text-action-ink-negative-disabled
|
|
625
|
+
focus:text-action-ink-negative-hover
|
|
626
|
+
`,
|
|
627
|
+
},
|
|
628
|
+
// Notice color variants
|
|
629
|
+
{
|
|
630
|
+
color: "notice",
|
|
631
|
+
class: `text-action-ink-notice-normal
|
|
632
|
+
hover:text-action-ink-notice-subtle
|
|
633
|
+
hover:decoration-action-outline-notice-hover
|
|
634
|
+
hover:text-action-ink-notice-hover
|
|
635
|
+
disabled:text-action-ink-notice-disabled
|
|
636
|
+
focus:text-action-ink-notice-hover
|
|
637
|
+
`,
|
|
638
|
+
},
|
|
639
|
+
// Info color variants
|
|
640
|
+
{
|
|
641
|
+
color: "info",
|
|
642
|
+
class: `text-action-ink-info-normal
|
|
643
|
+
hover:text-action-ink-info-subtle
|
|
644
|
+
hover:decoration-action-outline-info-hover
|
|
645
|
+
hover:text-action-ink-info-hover
|
|
646
|
+
disabled:text-action-ink-info-disabled
|
|
647
|
+
focus:text-action-ink-info-hover
|
|
648
|
+
`,
|
|
649
|
+
},
|
|
650
|
+
// Neutral color variants
|
|
651
|
+
{
|
|
652
|
+
color: "neutral",
|
|
653
|
+
class: `text-action-ink-neutral-normal
|
|
654
|
+
hover:text-action-ink-neutral-subtle
|
|
655
|
+
hover:decoration-action-outline-neutral-hover
|
|
656
|
+
hover:text-action-ink-neutral-hover
|
|
657
|
+
disabled:text-action-ink-neutral-disabled
|
|
658
|
+
focus:text-action-ink-neutral-hover
|
|
659
|
+
`,
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
color: "white",
|
|
663
|
+
class: `text-action-ink-white-subtle
|
|
664
|
+
hover:text-action-ink-white-subtle
|
|
665
|
+
hover:decoration-action-outline-white-hover
|
|
666
|
+
hover:text-action-ink-white-hover
|
|
667
|
+
disabled:text-action-ink-white-disabled
|
|
668
|
+
focus:text-action-ink-white-hover
|
|
669
|
+
`,
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
defaultVariants: {
|
|
673
|
+
type: "anchor",
|
|
674
|
+
color: "primary",
|
|
675
|
+
size: "medium",
|
|
676
|
+
isIconOnly: false,
|
|
677
|
+
isDisabled: false,
|
|
678
|
+
},
|
|
679
|
+
});
|
|
680
|
+
const Link = React.forwardRef(({ className, type = "anchor", color = "primary", size = "medium", isIconOnly = false, isDisabled = false, asChild = false, showIcon = false, icon, leadingIcon, trailingIcon, children, onClick, ...props }, ref) => {
|
|
681
|
+
const Comp = asChild ? Slot : "a";
|
|
682
|
+
const handleClick = (e) => {
|
|
683
|
+
if (isDisabled) {
|
|
684
|
+
e.preventDefault();
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
onClick?.(e);
|
|
688
|
+
};
|
|
689
|
+
// Icon size based on link size
|
|
690
|
+
const iconSize = {
|
|
691
|
+
xsmall: 12,
|
|
692
|
+
small: 14,
|
|
693
|
+
medium: 16,
|
|
694
|
+
large: 18,
|
|
695
|
+
}[size];
|
|
696
|
+
// Determine what to show as trailing icon
|
|
697
|
+
// Priority: trailingIcon > (showIcon && icon) > (showIcon && default ExternalLink)
|
|
698
|
+
const finalTrailingIcon = trailingIcon || (showIcon && (icon || jsx(ExternalLink, { size: iconSize })));
|
|
699
|
+
const linkContent = (jsxs(Fragment, { children: [leadingIcon && !isIconOnly && (jsx("span", { className: "inline-flex items-center", children: leadingIcon })), !isIconOnly && children, isIconOnly && children, finalTrailingIcon && !isIconOnly && (jsx("span", { className: "inline-flex items-center", children: finalTrailingIcon })), isIconOnly &&
|
|
700
|
+
(leadingIcon || finalTrailingIcon || (jsx(ExternalLink, { size: iconSize })))] }));
|
|
701
|
+
return (jsx(Comp, { className: cn(linkVariants({
|
|
702
|
+
type,
|
|
703
|
+
color,
|
|
704
|
+
size,
|
|
705
|
+
isIconOnly,
|
|
706
|
+
isDisabled,
|
|
707
|
+
}), className), ref: ref, onClick: handleClick, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : undefined, ...props, children: linkContent }));
|
|
708
|
+
});
|
|
709
|
+
Link.displayName = "Link";
|
|
710
|
+
|
|
711
|
+
const alertVariants = cva("relative flex gap-4 p-4 rounded-large transition-colors", {
|
|
712
|
+
variants: {
|
|
713
|
+
emphasis: {
|
|
714
|
+
subtle: "",
|
|
715
|
+
intense: "",
|
|
716
|
+
},
|
|
717
|
+
intent: {
|
|
718
|
+
positive: "",
|
|
719
|
+
negative: "",
|
|
720
|
+
notice: "",
|
|
721
|
+
info: "",
|
|
722
|
+
neutral: "",
|
|
723
|
+
},
|
|
724
|
+
},
|
|
725
|
+
compoundVariants: [
|
|
726
|
+
// Subtle emphasis
|
|
727
|
+
{
|
|
728
|
+
emphasis: "subtle",
|
|
729
|
+
intent: "positive",
|
|
730
|
+
class: "bg-feedback-fill-positive-subtle",
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
emphasis: "subtle",
|
|
734
|
+
intent: "negative",
|
|
735
|
+
class: "bg-feedback-fill-negative-subtle",
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
emphasis: "subtle",
|
|
739
|
+
intent: "notice",
|
|
740
|
+
class: "bg-feedback-fill-notice-subtle",
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
emphasis: "subtle",
|
|
744
|
+
intent: "info",
|
|
745
|
+
class: "bg-feedback-fill-info-subtle",
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
emphasis: "subtle",
|
|
749
|
+
intent: "neutral",
|
|
750
|
+
class: "bg-feedback-fill-neutral-subtle",
|
|
751
|
+
},
|
|
752
|
+
// Intense emphasis
|
|
753
|
+
{
|
|
754
|
+
emphasis: "intense",
|
|
755
|
+
intent: "positive",
|
|
756
|
+
class: "bg-feedback-fill-positive-intense",
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
emphasis: "intense",
|
|
760
|
+
intent: "negative",
|
|
761
|
+
class: "bg-feedback-fill-negative-intense",
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
emphasis: "intense",
|
|
765
|
+
intent: "notice",
|
|
766
|
+
class: "bg-feedback-fill-notice-intense",
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
emphasis: "intense",
|
|
770
|
+
intent: "info",
|
|
771
|
+
class: "bg-feedback-fill-info-intense",
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
emphasis: "intense",
|
|
775
|
+
intent: "neutral",
|
|
776
|
+
class: "bg-feedback-fill-neutral-intense",
|
|
777
|
+
},
|
|
778
|
+
],
|
|
779
|
+
defaultVariants: {
|
|
780
|
+
emphasis: "subtle",
|
|
781
|
+
intent: "info",
|
|
782
|
+
},
|
|
783
|
+
});
|
|
784
|
+
const alertIconVariants = cva("flex-shrink-0 rounded-full flex items-center justify-center mt-1", {
|
|
785
|
+
variants: {
|
|
786
|
+
emphasis: {
|
|
787
|
+
subtle: "",
|
|
788
|
+
intense: "text-white",
|
|
789
|
+
},
|
|
790
|
+
intent: {
|
|
791
|
+
positive: "",
|
|
792
|
+
negative: "",
|
|
793
|
+
notice: "",
|
|
794
|
+
info: "",
|
|
795
|
+
neutral: "",
|
|
796
|
+
},
|
|
797
|
+
},
|
|
798
|
+
compoundVariants: [
|
|
799
|
+
// Subtle emphasis - colored backgrounds with white icons
|
|
800
|
+
{
|
|
801
|
+
emphasis: "subtle",
|
|
802
|
+
intent: "positive",
|
|
803
|
+
class: "text-action-ink-positive-normal",
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
emphasis: "subtle",
|
|
807
|
+
intent: "negative",
|
|
808
|
+
class: " text-action-ink-negative-normal",
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
emphasis: "subtle",
|
|
812
|
+
intent: "notice",
|
|
813
|
+
class: " text-action-ink-notice-normal",
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
emphasis: "subtle",
|
|
817
|
+
intent: "info",
|
|
818
|
+
class: " text-action-ink-info-normal",
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
emphasis: "subtle",
|
|
822
|
+
intent: "neutral",
|
|
823
|
+
class: " text-action-ink-neutral-normal",
|
|
824
|
+
},
|
|
825
|
+
// Intense emphasis - white backgrounds with colored icons
|
|
826
|
+
{
|
|
827
|
+
emphasis: "intense",
|
|
828
|
+
intent: "positive",
|
|
829
|
+
class: " text-action-ink-on-primary-normal",
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
emphasis: "intense",
|
|
833
|
+
intent: "negative",
|
|
834
|
+
class: " text-action-ink-on-primary-normal",
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
emphasis: "intense",
|
|
838
|
+
intent: "notice",
|
|
839
|
+
class: " text-action-ink-on-primary-normal",
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
emphasis: "intense",
|
|
843
|
+
intent: "info",
|
|
844
|
+
class: " text-action-fill-info-default",
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
emphasis: "intense",
|
|
848
|
+
intent: "neutral",
|
|
849
|
+
class: " text-action-fill-neutral-default",
|
|
850
|
+
},
|
|
851
|
+
],
|
|
852
|
+
defaultVariants: {
|
|
853
|
+
emphasis: "subtle",
|
|
854
|
+
intent: "info",
|
|
855
|
+
},
|
|
856
|
+
});
|
|
857
|
+
const alertTextVariants = cva("", {
|
|
858
|
+
variants: {
|
|
859
|
+
emphasis: {
|
|
860
|
+
subtle: "",
|
|
861
|
+
intense: "",
|
|
862
|
+
},
|
|
863
|
+
intent: {
|
|
864
|
+
positive: "",
|
|
865
|
+
negative: "",
|
|
866
|
+
notice: "",
|
|
867
|
+
info: "",
|
|
868
|
+
neutral: "",
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
compoundVariants: [
|
|
872
|
+
// Subtle emphasis - dark text
|
|
873
|
+
{
|
|
874
|
+
emphasis: "subtle",
|
|
875
|
+
intent: "positive",
|
|
876
|
+
class: "text-surface-ink-neutral-normal",
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
emphasis: "subtle",
|
|
880
|
+
intent: "negative",
|
|
881
|
+
class: "text-surface-ink-neutral-normal",
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
emphasis: "subtle",
|
|
885
|
+
intent: "notice",
|
|
886
|
+
class: "text-surface-ink-neutral-normal",
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
emphasis: "subtle",
|
|
890
|
+
intent: "info",
|
|
891
|
+
class: "text-surface-ink-neutral-normal",
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
emphasis: "subtle",
|
|
895
|
+
intent: "neutral",
|
|
896
|
+
class: "text-surface-ink-neutral-normal",
|
|
897
|
+
},
|
|
898
|
+
// Intense emphasis - white text
|
|
899
|
+
{
|
|
900
|
+
emphasis: "intense",
|
|
901
|
+
intent: "positive",
|
|
902
|
+
class: "text-action-ink-on-primary-normal",
|
|
903
|
+
},
|
|
904
|
+
{
|
|
905
|
+
emphasis: "intense",
|
|
906
|
+
intent: "negative",
|
|
907
|
+
class: "text-action-ink-on-primary-normal",
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
emphasis: "intense",
|
|
911
|
+
intent: "notice",
|
|
912
|
+
class: "text-action-ink-on-primary-normal",
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
emphasis: "intense",
|
|
916
|
+
intent: "info",
|
|
917
|
+
class: "text-action-ink-on-primary-normal",
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
emphasis: "intense",
|
|
921
|
+
intent: "neutral",
|
|
922
|
+
class: "text-action-ink-on-primary-normal",
|
|
923
|
+
},
|
|
924
|
+
],
|
|
925
|
+
defaultVariants: {
|
|
926
|
+
emphasis: "subtle",
|
|
927
|
+
intent: "info",
|
|
928
|
+
},
|
|
929
|
+
});
|
|
930
|
+
const getDefaultIcon = (intent, emphasis) => {
|
|
931
|
+
const iconSize = 16;
|
|
932
|
+
switch (emphasis) {
|
|
933
|
+
case "intense":
|
|
934
|
+
return (jsx(Icon, { name: "info", size: iconSize, className: "text-white", "aria-hidden": "true" }));
|
|
935
|
+
default:
|
|
936
|
+
return jsx(Icon, { name: "info", size: iconSize, "aria-hidden": "true" });
|
|
937
|
+
}
|
|
938
|
+
};
|
|
939
|
+
const getButtonColor = (intent) => {
|
|
940
|
+
switch (intent) {
|
|
941
|
+
case "positive":
|
|
942
|
+
return "positive";
|
|
943
|
+
case "negative":
|
|
944
|
+
return "negative";
|
|
945
|
+
case "notice":
|
|
946
|
+
return "notice";
|
|
947
|
+
case "info":
|
|
948
|
+
return "info";
|
|
949
|
+
case "neutral":
|
|
950
|
+
return "neutral";
|
|
951
|
+
default:
|
|
952
|
+
return "neutral";
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
const getActionButton = (actionButtonText, onActionButtonClick, emphasis, intent) => {
|
|
956
|
+
if (!actionButtonText)
|
|
957
|
+
return null;
|
|
958
|
+
// For intense emphasis: secondary variant with white border and white text
|
|
959
|
+
// For subtle emphasis: secondary variant with colored border and colored text (default behavior)
|
|
960
|
+
if (emphasis === "intense") {
|
|
961
|
+
return (jsx(Button, { variant: "secondary", color: "white", size: "small", onClick: onActionButtonClick, children: actionButtonText }));
|
|
962
|
+
}
|
|
963
|
+
// Subtle emphasis: use default secondary variant styling
|
|
964
|
+
return (jsx(Button, { variant: "secondary", color: intent, size: "small", onClick: onActionButtonClick, children: actionButtonText }));
|
|
965
|
+
};
|
|
966
|
+
const getActionLink = (actionButtonText, onActionLinkClick, emphasis, intent) => {
|
|
967
|
+
if (!actionButtonText)
|
|
968
|
+
return null;
|
|
969
|
+
// For intense emphasis: secondary variant with white border and white text
|
|
970
|
+
// For subtle emphasis: secondary variant with colored border and colored text (default behavior)
|
|
971
|
+
if (emphasis === "intense") {
|
|
972
|
+
return (jsx(Link, { type: "action", color: "white", size: "small", onClick: onActionLinkClick, children: actionButtonText }));
|
|
973
|
+
}
|
|
974
|
+
// Subtle emphasis: use default secondary variant styling
|
|
975
|
+
return (jsx(Link, { type: "action", color: intent, size: "small", onClick: onActionLinkClick, children: actionButtonText }));
|
|
976
|
+
};
|
|
977
|
+
const Alert = React.forwardRef(({ className, emphasis = "subtle", intent = "info", title, children, isFullWidth = false, onClose, icon, actionButtonText, onActionButtonClick, actionLinkText, onActionLinkClick, ...props }, ref) => {
|
|
978
|
+
const displayIcon = icon ?? getDefaultIcon(intent, emphasis);
|
|
979
|
+
const actionButton = getActionButton(actionButtonText, onActionButtonClick, emphasis, intent);
|
|
980
|
+
const actionLink = getActionLink(actionLinkText, onActionLinkClick, emphasis, intent);
|
|
981
|
+
const hasActions = actionButton || actionLink;
|
|
982
|
+
return (jsxs("div", { ref: ref, className: cn(alertVariants({ emphasis, intent }), className), role: "alert", ...props, children: [jsx("div", { className: cn(alertIconVariants({ emphasis, intent }), "h-5 w-5 shrink-0"), children: displayIcon }), isFullWidth ? (
|
|
983
|
+
/* Full Width Layout: Icon, Content, Actions/Close in one row */
|
|
984
|
+
jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between gap-4", children: [jsxs("div", { className: "flex-1 min-w-0 flex flex-col gap-1", children: [title && (jsx("div", { className: cn("text-body-medium-semibold", alertTextVariants({ emphasis, intent })), children: title })), jsx("div", { className: cn("text-body-small-regular", alertTextVariants({ emphasis, intent })), children: children })] }), jsxs("div", { className: "flex items-center gap-3 shrink-0", children: [hasActions && (jsxs(Fragment, { children: [actionButton, actionLink] })), onClose && (jsx(IconButton, { icon: "close", color: emphasis === "intense" ? "white" : getButtonColor(intent), size: "xsmall", onClick: onClose, className: cn("shrink-0 h-5 w-5", emphasis === "intense"
|
|
985
|
+
? "hover:bg-white/20"
|
|
986
|
+
: "hover:bg-black/10"), "aria-label": "Close alert" }))] })] })) : (
|
|
987
|
+
/* Not Full Width Layout: Icon and Content in row, Actions below, Close top-right */
|
|
988
|
+
jsxs("div", { className: "flex-1 min-w-0 relative", children: [onClose && (jsx("div", { className: "absolute top-0 right-0", children: jsx(IconButton, { icon: "close", color: emphasis === "intense" ? "white" : getButtonColor(intent), size: "xsmall", onClick: onClose, className: cn("shrink-0 h-5 w-5", emphasis === "intense"
|
|
989
|
+
? "hover:bg-white/20"
|
|
990
|
+
: "hover:bg-black/10"), "aria-label": "Close alert" }) })), jsxs("div", { className: "flex flex-col gap-3 pr-8", children: [title && (jsx("div", { className: cn("text-body-medium-semibold", alertTextVariants({ emphasis, intent })), children: title })), jsx("div", { className: cn("text-body-small-regular", alertTextVariants({ emphasis, intent })), children: children }), hasActions && (jsxs("div", { className: "flex items-center gap-3", children: [actionButton, actionLink] }))] })] }))] }));
|
|
991
|
+
});
|
|
992
|
+
Alert.displayName = "Alert";
|
|
993
|
+
|
|
994
|
+
// Helper function to get the text utility class name
|
|
995
|
+
function getTextClassName(variant = "body", size = "medium", weight = "regular", color = "default") {
|
|
996
|
+
// Build the base class name
|
|
997
|
+
let baseClass = `text-${variant}`;
|
|
998
|
+
// Add size
|
|
999
|
+
if (size) {
|
|
1000
|
+
baseClass += `-${size}`;
|
|
1001
|
+
}
|
|
1002
|
+
// Add weight
|
|
1003
|
+
if (weight) {
|
|
1004
|
+
baseClass += `-${weight}`;
|
|
1005
|
+
}
|
|
1006
|
+
// Add color class separately
|
|
1007
|
+
const colorClass = `text-color-${color}`;
|
|
1008
|
+
return `${baseClass} ${colorClass}`;
|
|
1009
|
+
}
|
|
1010
|
+
const Text = React.forwardRef(({ className, variant = "body", size = "medium", weight = "regular", color = "default", as = "p", children, ...props }, ref) => {
|
|
1011
|
+
const Component = as;
|
|
1012
|
+
const textClass = getTextClassName(variant, size, weight, color);
|
|
1013
|
+
return React.createElement(Component, {
|
|
1014
|
+
className: cn(textClass, className),
|
|
1015
|
+
ref,
|
|
1016
|
+
...props,
|
|
1017
|
+
}, children);
|
|
1018
|
+
});
|
|
1019
|
+
Text.displayName = "Text";
|
|
1020
|
+
|
|
1021
|
+
const inverseColorClasses = {
|
|
1022
|
+
a1: "bg-avatar-fill-a1-on-bg text-avatar-fill-a1-bg",
|
|
1023
|
+
a2: "bg-avatar-fill-a2-on-bg text-avatar-fill-a2-bg",
|
|
1024
|
+
a3: "bg-avatar-fill-a3-on-bg text-avatar-fill-a3-bg",
|
|
1025
|
+
a4: "bg-avatar-fill-a4-on-bg text-avatar-fill-a4-bg",
|
|
1026
|
+
a5: "bg-avatar-fill-a5-on-bg text-avatar-fill-a5-bg",
|
|
1027
|
+
};
|
|
1028
|
+
const avatarVariants = cva("inline-flex items-center justify-center font-medium text-center select-none", {
|
|
1029
|
+
variants: {
|
|
1030
|
+
color: {
|
|
1031
|
+
a1: "bg-avatar-fill-a1-bg text-avatar-fill-a1-on-bg",
|
|
1032
|
+
a2: "bg-avatar-fill-a2-bg text-avatar-fill-a2-on-bg",
|
|
1033
|
+
a3: "bg-avatar-fill-a3-bg text-avatar-fill-a3-on-bg",
|
|
1034
|
+
a4: "bg-avatar-fill-a4-bg text-avatar-fill-a4-on-bg",
|
|
1035
|
+
a5: "bg-avatar-fill-a5-bg text-avatar-fill-a5-on-bg",
|
|
1036
|
+
},
|
|
1037
|
+
size: {
|
|
1038
|
+
small: "h-[24px] w-[24px] text-body-medium-regular rounded-large",
|
|
1039
|
+
medium: "h-[32px] w-[32px] text-body-medium-regular rounded-xlarge",
|
|
1040
|
+
xlarge: "h-[36px] w-[36px] text-body-medium-regular rounded-xlarge",
|
|
1041
|
+
},
|
|
1042
|
+
},
|
|
1043
|
+
defaultVariants: {
|
|
1044
|
+
color: "a1",
|
|
1045
|
+
size: "medium",
|
|
1046
|
+
},
|
|
1047
|
+
});
|
|
1048
|
+
const statusVariants = cva("absolute flex items-center justify-center rounded-full border-2 border-surface-fill-neutral-intense", {
|
|
1049
|
+
variants: {
|
|
1050
|
+
size: {
|
|
1051
|
+
small: "h-5 w-5 -bottom-0.5 -right-0.5",
|
|
1052
|
+
medium: "h-6 w-6 -bottom-1 -right-1",
|
|
1053
|
+
xlarge: "h-6 w-6 -bottom-1 -right-1",
|
|
1054
|
+
},
|
|
1055
|
+
statusColor: {
|
|
1056
|
+
positive: "bg-action-fill-positive-default",
|
|
1057
|
+
negative: "bg-action-fill-negative-default",
|
|
1058
|
+
notice: "bg-action-fill-notice-default",
|
|
1059
|
+
info: "bg-action-fill-info-default",
|
|
1060
|
+
neutral: "bg-action-fill-neutral-default",
|
|
1061
|
+
},
|
|
1062
|
+
},
|
|
1063
|
+
defaultVariants: {
|
|
1064
|
+
size: "medium",
|
|
1065
|
+
statusColor: "notice",
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
const Avatar = React.forwardRef(({ className, appearance = "default", color, size, children, src, alt, showStatus = false, statusColor = "notice", statusIcon, label, trailingComponent, containerClassName, ...props }, ref) => {
|
|
1069
|
+
const [imageError, setImageError] = React.useState(false);
|
|
1070
|
+
const handleImageError = () => {
|
|
1071
|
+
setImageError(true);
|
|
1072
|
+
};
|
|
1073
|
+
const getStatusIconSize = () => {
|
|
1074
|
+
switch (size) {
|
|
1075
|
+
case "small":
|
|
1076
|
+
return "h-3.5 w-3.5";
|
|
1077
|
+
case "medium":
|
|
1078
|
+
return "h-4 w-4";
|
|
1079
|
+
default:
|
|
1080
|
+
return "h-4 w-4";
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
const getTextSize = () => {
|
|
1084
|
+
switch (size) {
|
|
1085
|
+
case "small":
|
|
1086
|
+
return "small";
|
|
1087
|
+
case "medium":
|
|
1088
|
+
return "medium";
|
|
1089
|
+
default:
|
|
1090
|
+
return "medium";
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
const resolvedColor = color ?? "a1";
|
|
1094
|
+
const avatarElement = (jsxs("div", { className: "relative inline-block", children: [jsx("div", { className: cn(avatarVariants({ color: resolvedColor, size }), appearance === "inverse"
|
|
1095
|
+
? inverseColorClasses[resolvedColor]
|
|
1096
|
+
: undefined, className), ...props, children: src && !imageError ? (jsx("img", { src: src, alt: alt || "Avatar", className: cn("h-full w-full object-cover", size === "small" ? "rounded-large" : "rounded-xlarge"), onError: handleImageError })) : (children) }), showStatus && (jsx("div", { className: cn(statusVariants({ size, statusColor })), children: statusIcon && (jsx("span", { className: cn("text-action-ink-on-primary-normal", getStatusIconSize()), children: statusIcon })) }))] }));
|
|
1097
|
+
// If no label or trailing component, return just the avatar
|
|
1098
|
+
if (!label && !trailingComponent) {
|
|
1099
|
+
return jsx("div", { ref: ref, children: avatarElement });
|
|
1100
|
+
}
|
|
1101
|
+
// Otherwise, return avatar with label and/or trailing component
|
|
1102
|
+
return (jsxs("div", { ref: ref, className: cn("inline-flex items-center gap-3", containerClassName), children: [avatarElement, label && (jsx(Text, { variant: "body", size: getTextSize(), weight: "medium", color: "default", as: "span", children: label })), trailingComponent && (jsx("span", { className: "ml-auto", children: trailingComponent }))] }));
|
|
1103
|
+
});
|
|
1104
|
+
Avatar.displayName = "Avatar";
|
|
1105
|
+
|
|
1106
|
+
const badgeVariants = cva("inline-flex items-center whitespace-nowrap transition-colors", {
|
|
1107
|
+
variants: {
|
|
1108
|
+
variant: {
|
|
1109
|
+
light: "",
|
|
1110
|
+
filled: "",
|
|
1111
|
+
},
|
|
1112
|
+
color: {
|
|
1113
|
+
primary: "",
|
|
1114
|
+
positive: "",
|
|
1115
|
+
negative: "",
|
|
1116
|
+
notice: "",
|
|
1117
|
+
info: "",
|
|
1118
|
+
neutral: "",
|
|
1119
|
+
},
|
|
1120
|
+
size: {
|
|
1121
|
+
small: "px-2 h-[var(--size-20)] gap-2 rounded-large text-body-small-medium",
|
|
1122
|
+
medium: "px-3 h-[var(--size-24)] gap-3 rounded-large text-body-medium-medium",
|
|
1123
|
+
large: "px-4 h-[var(--size-28)] gap-3 rounded-xlarge text-body-large-medium",
|
|
1124
|
+
},
|
|
1125
|
+
},
|
|
1126
|
+
compoundVariants: [
|
|
1127
|
+
// Light variant colors
|
|
1128
|
+
{
|
|
1129
|
+
variant: "light",
|
|
1130
|
+
color: "primary",
|
|
1131
|
+
class: "bg-action-fill-primary-faded text-action-ink-primary-normal",
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
variant: "light",
|
|
1135
|
+
color: "positive",
|
|
1136
|
+
class: "bg-action-fill-positive-faded text-action-ink-positive-normal",
|
|
1137
|
+
},
|
|
1138
|
+
{
|
|
1139
|
+
variant: "light",
|
|
1140
|
+
color: "negative",
|
|
1141
|
+
class: "bg-action-fill-negative-faded text-action-ink-negative-normal",
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
variant: "light",
|
|
1145
|
+
color: "notice",
|
|
1146
|
+
class: "bg-action-fill-notice-faded text-action-ink-notice-normal",
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
variant: "light",
|
|
1150
|
+
color: "info",
|
|
1151
|
+
class: "bg-action-fill-info-faded text-action-ink-info-normal",
|
|
1152
|
+
},
|
|
1153
|
+
{
|
|
1154
|
+
variant: "light",
|
|
1155
|
+
color: "neutral",
|
|
1156
|
+
class: "bg-action-fill-neutral-faded text-action-ink-neutral-normal",
|
|
1157
|
+
},
|
|
1158
|
+
// Filled variant colors
|
|
1159
|
+
{
|
|
1160
|
+
variant: "filled",
|
|
1161
|
+
color: "primary",
|
|
1162
|
+
class: "bg-action-fill-primary-default text-action-ink-on-primary-normal",
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
variant: "filled",
|
|
1166
|
+
color: "positive",
|
|
1167
|
+
class: "bg-action-fill-positive-default text-action-ink-on-primary-normal",
|
|
1168
|
+
},
|
|
1169
|
+
{
|
|
1170
|
+
variant: "filled",
|
|
1171
|
+
color: "negative",
|
|
1172
|
+
class: "bg-action-fill-negative-default text-action-ink-on-primary-normal",
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
variant: "filled",
|
|
1176
|
+
color: "notice",
|
|
1177
|
+
class: "bg-action-fill-notice-default text-action-ink-on-primary-normal",
|
|
1178
|
+
},
|
|
1179
|
+
{
|
|
1180
|
+
variant: "filled",
|
|
1181
|
+
color: "info",
|
|
1182
|
+
class: "bg-action-fill-info-default text-action-ink-on-primary-normal",
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
variant: "filled",
|
|
1186
|
+
color: "neutral",
|
|
1187
|
+
class: "bg-action-fill-neutral-default text-action-ink-on-primary-normal",
|
|
1188
|
+
},
|
|
1189
|
+
],
|
|
1190
|
+
defaultVariants: {
|
|
1191
|
+
variant: "light",
|
|
1192
|
+
color: "info",
|
|
1193
|
+
size: "medium",
|
|
1194
|
+
},
|
|
1195
|
+
});
|
|
1196
|
+
const Badge = React.forwardRef(({ className, variant, size, color, showDot = false, children, ...props }, ref) => {
|
|
1197
|
+
const getDotColor = () => {
|
|
1198
|
+
if (variant === "filled") {
|
|
1199
|
+
return "bg-action-ink-on-primary-normal";
|
|
1200
|
+
}
|
|
1201
|
+
// Light variant - use the corresponding action color
|
|
1202
|
+
switch (color) {
|
|
1203
|
+
case "primary":
|
|
1204
|
+
return "bg-action-fill-primary-default";
|
|
1205
|
+
case "positive":
|
|
1206
|
+
return "bg-action-fill-positive-default";
|
|
1207
|
+
case "negative":
|
|
1208
|
+
return "bg-action-fill-negative-default";
|
|
1209
|
+
case "notice":
|
|
1210
|
+
return "bg-action-fill-notice-default";
|
|
1211
|
+
case "info":
|
|
1212
|
+
return "bg-action-fill-info-default";
|
|
1213
|
+
case "neutral":
|
|
1214
|
+
return "bg-action-fill-neutral-default";
|
|
1215
|
+
default:
|
|
1216
|
+
return "bg-action-fill-info-default";
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
const getDotSize = () => {
|
|
1220
|
+
if (size === "small") {
|
|
1221
|
+
return "h-2 w-2";
|
|
1222
|
+
}
|
|
1223
|
+
if (size === "medium") {
|
|
1224
|
+
return "h-[6px] w-[6px]";
|
|
1225
|
+
}
|
|
1226
|
+
return "h-3 w-3";
|
|
1227
|
+
};
|
|
1228
|
+
return (jsxs("div", { ref: ref, className: cn(badgeVariants({ variant, size, color }), className), ...props, children: [showDot && (jsx("span", { className: cn("rounded-full", getDotColor(), getDotSize()), "aria-hidden": "true" })), children] }));
|
|
1229
|
+
});
|
|
1230
|
+
Badge.displayName = "Badge";
|
|
578
1231
|
|
|
579
1232
|
const buttonGroupVariants = cva("inline-flex", {
|
|
580
1233
|
variants: {
|
|
@@ -756,99 +1409,6 @@ const FormFooter = React.forwardRef(({ helperText, trailingText, validationState
|
|
|
756
1409
|
});
|
|
757
1410
|
FormFooter.displayName = "FormFooter";
|
|
758
1411
|
|
|
759
|
-
/**
|
|
760
|
-
* ==============================================
|
|
761
|
-
* HOW TO ADD A NEW ICON:
|
|
762
|
-
* ==============================================
|
|
763
|
-
*
|
|
764
|
-
* 1. Add your SVG file to: src/assets/icons/{iconName}.svg
|
|
765
|
-
*
|
|
766
|
-
* 2. Copy the SVG content from the file
|
|
767
|
-
*
|
|
768
|
-
* 3. Add it to the iconRegistry below:
|
|
769
|
-
* iconName: `<svg>...</svg>`,
|
|
770
|
-
*
|
|
771
|
-
* 4. Use it anywhere in your app:
|
|
772
|
-
* <Icon name="iconName" size={24} />
|
|
773
|
-
*
|
|
774
|
-
* The Icon component will automatically:
|
|
775
|
-
* - Replace hardcoded colors with currentColor
|
|
776
|
-
* - Allow you to control color via className or style
|
|
777
|
-
* - Resize based on the size prop
|
|
778
|
-
* ==============================================
|
|
779
|
-
*/
|
|
780
|
-
/**
|
|
781
|
-
* Icon registry - maps icon names to their SVG content
|
|
782
|
-
* Add your icons here by copying the SVG content from your icon files
|
|
783
|
-
*/
|
|
784
|
-
const iconRegistry = {
|
|
785
|
-
// Tick/Check icon
|
|
786
|
-
tick: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
787
|
-
<path d="M10.364 15.1924L19.5564 6L20.9706 7.41421L10.364 18.0208L4 11.6569L5.41422 10.2427L10.364 15.1924Z" fill="#081416"/>
|
|
788
|
-
</svg>`,
|
|
789
|
-
// Alias: check points to the same icon as tick
|
|
790
|
-
check: `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
791
|
-
<path d="M10.364 15.1924L19.5564 6L20.9706 7.41421L10.364 18.0208L4 11.6569L5.41422 10.2427L10.364 15.1924Z" fill="#081416"/>
|
|
792
|
-
</svg>`,
|
|
793
|
-
add: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
794
|
-
<path d="M12.9 11.0999L21 11.0997V12.8997L12.9 12.8999V21H11.1V12.8999L3.00004 12.9001L3 11.1001L11.1 11.0999L11.0999 3.00001L12.8999 3L12.9 11.0999Z" fill="#081416"/>
|
|
795
|
-
</svg>`,
|
|
796
|
-
};
|
|
797
|
-
const Icon = ({ name, size = 24, className = "", style = {}, ...props }) => {
|
|
798
|
-
const svgContent = iconRegistry[name];
|
|
799
|
-
if (!svgContent) {
|
|
800
|
-
console.warn(`Icon "${String(name)}" not found in registry.\n` +
|
|
801
|
-
`Available icons: ${Object.keys(iconRegistry).join(", ")}`);
|
|
802
|
-
return null;
|
|
803
|
-
}
|
|
804
|
-
// Parse the SVG content
|
|
805
|
-
const parser = new DOMParser();
|
|
806
|
-
const svgDoc = parser.parseFromString(svgContent, "image/svg+xml");
|
|
807
|
-
const svgElement = svgDoc.querySelector("svg");
|
|
808
|
-
if (!svgElement) {
|
|
809
|
-
console.error(`Invalid SVG content for icon "${String(name)}"`);
|
|
810
|
-
return null;
|
|
811
|
-
}
|
|
812
|
-
// Get the viewBox for proper scaling
|
|
813
|
-
const viewBox = svgElement.getAttribute("viewBox") || "0 0 24 24";
|
|
814
|
-
// Get all SVG content as string and replace hardcoded colors with currentColor
|
|
815
|
-
let innerSVG = svgElement.innerHTML;
|
|
816
|
-
// Replace common hardcoded colors with currentColor
|
|
817
|
-
// This allows the icon to inherit text color from parent
|
|
818
|
-
innerSVG = innerSVG
|
|
819
|
-
.replace(/fill="[^"]*"/g, 'fill="currentColor"')
|
|
820
|
-
.replace(/stroke="[^"]*"/g, 'stroke="currentColor"');
|
|
821
|
-
return (jsx("svg", { width: size, height: size, viewBox: viewBox, className: className, style: style, xmlns: "http://www.w3.org/2000/svg", ...props, dangerouslySetInnerHTML: { __html: innerSVG } }));
|
|
822
|
-
};
|
|
823
|
-
/**
|
|
824
|
-
* Get all available icon names from the registry
|
|
825
|
-
* @returns Array of registered icon names
|
|
826
|
-
*
|
|
827
|
-
* @example
|
|
828
|
-
* ```tsx
|
|
829
|
-
* const icons = getAvailableIcons();
|
|
830
|
-
* console.log(icons); // ['tick', 'check', ...]
|
|
831
|
-
* ```
|
|
832
|
-
*/
|
|
833
|
-
function getAvailableIcons() {
|
|
834
|
-
return Object.keys(iconRegistry);
|
|
835
|
-
}
|
|
836
|
-
/**
|
|
837
|
-
* Check if an icon exists in the registry
|
|
838
|
-
* @param name - Icon name to check
|
|
839
|
-
* @returns true if the icon exists
|
|
840
|
-
*
|
|
841
|
-
* @example
|
|
842
|
-
* ```tsx
|
|
843
|
-
* if (hasIcon('tick')) {
|
|
844
|
-
* // Icon exists
|
|
845
|
-
* }
|
|
846
|
-
* ```
|
|
847
|
-
*/
|
|
848
|
-
function hasIcon(name) {
|
|
849
|
-
return name in iconRegistry;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
1412
|
const checkboxVariants = cva("relative inline-flex items-center justify-center shrink-0 transition-all cursor-pointer", {
|
|
853
1413
|
variants: {
|
|
854
1414
|
size: {
|
|
@@ -1298,141 +1858,6 @@ const ListItem = React.forwardRef(({ className, type = "single", leadingIcon, ti
|
|
|
1298
1858
|
});
|
|
1299
1859
|
ListItem.displayName = "ListItem";
|
|
1300
1860
|
|
|
1301
|
-
const linkVariants = cva("inline-flex items-center gap-1 whitespace-nowrap transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none decoration-1 underline-offset-4", {
|
|
1302
|
-
variants: {
|
|
1303
|
-
type: {
|
|
1304
|
-
anchor: "hover:underline",
|
|
1305
|
-
action: "no-underline cursor-pointer",
|
|
1306
|
-
},
|
|
1307
|
-
color: {
|
|
1308
|
-
primary: "",
|
|
1309
|
-
positive: "",
|
|
1310
|
-
negative: "",
|
|
1311
|
-
notice: "",
|
|
1312
|
-
info: "",
|
|
1313
|
-
neutral: "",
|
|
1314
|
-
},
|
|
1315
|
-
size: {
|
|
1316
|
-
xsmall: "text-body-xsmall-medium gap-1",
|
|
1317
|
-
small: "text-body-small-medium gap-1",
|
|
1318
|
-
medium: "text-body-medium-medium gap-1.5",
|
|
1319
|
-
large: "text-body-large-medium gap-1.5",
|
|
1320
|
-
},
|
|
1321
|
-
isIconOnly: {
|
|
1322
|
-
true: "no-underline",
|
|
1323
|
-
false: "",
|
|
1324
|
-
},
|
|
1325
|
-
isDisabled: {
|
|
1326
|
-
true: "cursor-not-allowed opacity-50",
|
|
1327
|
-
false: "cursor-pointer",
|
|
1328
|
-
},
|
|
1329
|
-
},
|
|
1330
|
-
compoundVariants: [
|
|
1331
|
-
// Primary color variants
|
|
1332
|
-
{
|
|
1333
|
-
color: "primary",
|
|
1334
|
-
class: `text-action-ink-primary-normal
|
|
1335
|
-
hover:text-action-ink-primary-subtle
|
|
1336
|
-
hover:decoration-action-outline-primary-hover
|
|
1337
|
-
disabled:text-action-ink-primary-disabled
|
|
1338
|
-
focus:text-action-ink-primary-hover
|
|
1339
|
-
`,
|
|
1340
|
-
},
|
|
1341
|
-
// Positive color variants
|
|
1342
|
-
{
|
|
1343
|
-
color: "positive",
|
|
1344
|
-
class: `text-action-ink-positive-normal
|
|
1345
|
-
hover:text-action-ink-positive-subtle
|
|
1346
|
-
hover:decoration-action-outline-positive-hover
|
|
1347
|
-
hover:text-action-ink-positive-hover
|
|
1348
|
-
disabled:text-action-ink-positive-disabled
|
|
1349
|
-
focus:text-action-ink-positive-hover
|
|
1350
|
-
`,
|
|
1351
|
-
},
|
|
1352
|
-
// Negative color variants
|
|
1353
|
-
{
|
|
1354
|
-
color: "negative",
|
|
1355
|
-
class: `text-action-ink-negative-normal
|
|
1356
|
-
hover:text-action-ink-negative-subtle
|
|
1357
|
-
hover:decoration-action-outline-negative-hover
|
|
1358
|
-
hover:text-action-ink-negative-hover
|
|
1359
|
-
disabled:text-action-ink-negative-disabled
|
|
1360
|
-
focus:text-action-ink-negative-hover
|
|
1361
|
-
`,
|
|
1362
|
-
},
|
|
1363
|
-
// Notice color variants
|
|
1364
|
-
{
|
|
1365
|
-
color: "notice",
|
|
1366
|
-
class: `text-action-ink-notice-normal
|
|
1367
|
-
hover:text-action-ink-notice-subtle
|
|
1368
|
-
hover:decoration-action-outline-notice-hover
|
|
1369
|
-
hover:text-action-ink-notice-hover
|
|
1370
|
-
disabled:text-action-ink-notice-disabled
|
|
1371
|
-
focus:text-action-ink-notice-hover
|
|
1372
|
-
`,
|
|
1373
|
-
},
|
|
1374
|
-
// Info color variants
|
|
1375
|
-
{
|
|
1376
|
-
color: "info",
|
|
1377
|
-
class: `text-action-ink-info-normal
|
|
1378
|
-
hover:text-action-ink-info-subtle
|
|
1379
|
-
hover:decoration-action-outline-info-hover
|
|
1380
|
-
hover:text-action-ink-info-hover
|
|
1381
|
-
disabled:text-action-ink-info-disabled
|
|
1382
|
-
focus:text-action-ink-info-hover
|
|
1383
|
-
`,
|
|
1384
|
-
},
|
|
1385
|
-
// Neutral color variants
|
|
1386
|
-
{
|
|
1387
|
-
color: "neutral",
|
|
1388
|
-
class: `text-action-ink-neutral-normal
|
|
1389
|
-
hover:text-action-ink-neutral-subtle
|
|
1390
|
-
hover:decoration-action-outline-neutral-hover
|
|
1391
|
-
hover:text-action-ink-neutral-hover
|
|
1392
|
-
disabled:text-action-ink-neutral-disabled
|
|
1393
|
-
focus:text-action-ink-neutral-hover
|
|
1394
|
-
`,
|
|
1395
|
-
},
|
|
1396
|
-
],
|
|
1397
|
-
defaultVariants: {
|
|
1398
|
-
type: "anchor",
|
|
1399
|
-
color: "primary",
|
|
1400
|
-
size: "medium",
|
|
1401
|
-
isIconOnly: false,
|
|
1402
|
-
isDisabled: false,
|
|
1403
|
-
},
|
|
1404
|
-
});
|
|
1405
|
-
const Link = React.forwardRef(({ className, type = "anchor", color = "primary", size = "medium", isIconOnly = false, isDisabled = false, asChild = false, showIcon = false, icon, leadingIcon, trailingIcon, children, onClick, ...props }, ref) => {
|
|
1406
|
-
const Comp = asChild ? Slot : "a";
|
|
1407
|
-
const handleClick = (e) => {
|
|
1408
|
-
if (isDisabled) {
|
|
1409
|
-
e.preventDefault();
|
|
1410
|
-
return;
|
|
1411
|
-
}
|
|
1412
|
-
onClick?.(e);
|
|
1413
|
-
};
|
|
1414
|
-
// Icon size based on link size
|
|
1415
|
-
const iconSize = {
|
|
1416
|
-
xsmall: 12,
|
|
1417
|
-
small: 14,
|
|
1418
|
-
medium: 16,
|
|
1419
|
-
large: 18,
|
|
1420
|
-
}[size];
|
|
1421
|
-
// Determine what to show as trailing icon
|
|
1422
|
-
// Priority: trailingIcon > (showIcon && icon) > (showIcon && default ExternalLink)
|
|
1423
|
-
const finalTrailingIcon = trailingIcon || (showIcon && (icon || jsx(ExternalLink, { size: iconSize })));
|
|
1424
|
-
const linkContent = (jsxs(Fragment, { children: [leadingIcon && !isIconOnly && (jsx("span", { className: "inline-flex items-center", children: leadingIcon })), !isIconOnly && children, isIconOnly && children, finalTrailingIcon && !isIconOnly && (jsx("span", { className: "inline-flex items-center", children: finalTrailingIcon })), isIconOnly &&
|
|
1425
|
-
(leadingIcon || finalTrailingIcon || (jsx(ExternalLink, { size: iconSize })))] }));
|
|
1426
|
-
return (jsx(Comp, { className: cn(linkVariants({
|
|
1427
|
-
type,
|
|
1428
|
-
color,
|
|
1429
|
-
size,
|
|
1430
|
-
isIconOnly,
|
|
1431
|
-
isDisabled,
|
|
1432
|
-
}), className), ref: ref, onClick: handleClick, "aria-disabled": isDisabled, tabIndex: isDisabled ? -1 : undefined, ...props, children: linkContent }));
|
|
1433
|
-
});
|
|
1434
|
-
Link.displayName = "Link";
|
|
1435
|
-
|
|
1436
1861
|
const DropdownMenu = React.forwardRef(({ items = [], customContent, sectionHeading, isLoading = false, isEmpty = false, emptyTitle = "No Search Results Found", emptyDescription = "Add description of what the user can search for here.", emptyLinkText = "Link to support site", onEmptyLinkClick, primaryButtonText = "Primary", secondaryButtonText = "Secondary", onPrimaryClick, onSecondaryClick, showChevron = false, emptyIcon, disableFooter = false, showFooter, footerLayout = "horizontal", onClose, focusedIndex = -1, className, width = "auto", }, ref) => {
|
|
1437
1862
|
const renderContent = () => {
|
|
1438
1863
|
if (isLoading) {
|
|
@@ -2839,7 +3264,7 @@ const tableCellVariants = cva("text-body-medium-regular border-b border-surface-
|
|
|
2839
3264
|
},
|
|
2840
3265
|
});
|
|
2841
3266
|
|
|
2842
|
-
function TableHeader({ headerGroups, enableRowSelection, enableSelectAll, showHeaderBackground, stickyHeader, size, headerClassName,
|
|
3267
|
+
function TableHeader({ headerGroups, enableRowSelection, enableSelectAll, showHeaderBackground, stickyHeader, size, headerClassName, onToggleAllRows, isAllRowsSelected, isSomeRowsSelected, getColumnStyle, }) {
|
|
2843
3268
|
const headerHeight = {
|
|
2844
3269
|
small: 32,
|
|
2845
3270
|
medium: 40,
|
|
@@ -2848,20 +3273,18 @@ function TableHeader({ headerGroups, enableRowSelection, enableSelectAll, showHe
|
|
|
2848
3273
|
return (jsx("thead", { className: cn(showHeaderBackground ? "bg-surface-fill-neutral-moderate" : "bg-white", stickyHeader && "sticky top-0 z-10"), children: headerGroups.map((headerGroup, groupIndex) => {
|
|
2849
3274
|
const stickyTop = stickyHeader ? groupIndex * headerHeight : undefined;
|
|
2850
3275
|
return (jsxs("tr", { children: [enableRowSelection && enableSelectAll && (jsx("th", { className: cn(tableHeaderVariants({ size }), showHeaderBackground && "bg-surface-fill-neutral-moderate", stickyHeader && "sticky z-20", "w-10 rounded-tl-xlarge rounded-bl-xlarge", headerClassName), style: { top: stickyTop }, children: jsx(Checkbox, { checked: isAllRowsSelected, isIndeterminate: isSomeRowsSelected, onChange: onToggleAllRows, "aria-label": "Select all rows" }) })), headerGroup.headers.map((header, index) => {
|
|
2851
|
-
const
|
|
2852
|
-
const
|
|
2853
|
-
? index === visibleHeadersCount - 1
|
|
2854
|
-
: index === headerGroup.headers.length - 1;
|
|
3276
|
+
const isFirstColumn = index === 0;
|
|
3277
|
+
const isLastColumn = index === headerGroup.headers.length - 1;
|
|
2855
3278
|
return (jsx("th", { className: cn(tableHeaderVariants({ size }), showHeaderBackground &&
|
|
2856
|
-
"bg-surface-fill-neutral-moderate border-none", stickyHeader && "sticky z-20", !enableRowSelection && index === 0 && "rounded-tl-xlarge ",
|
|
2857
|
-
? "opacity-0 translate-x-8 pointer-events-none"
|
|
2858
|
-
: "opacity-100 translate-x-0"), style: {
|
|
3279
|
+
"bg-surface-fill-neutral-moderate border-none", stickyHeader && "sticky z-20", !enableRowSelection && index === 0 && "rounded-tl-xlarge ", isLastColumn && "rounded-tr-xlarge", header.column.columnDef.meta?.headerClassName, headerClassName), style: {
|
|
2859
3280
|
...getColumnStyle(header.column.id, {
|
|
2860
3281
|
width: header.getSize(),
|
|
2861
3282
|
minWidth: header.column.columnDef.minSize,
|
|
2862
3283
|
maxWidth: header.column.columnDef.maxSize,
|
|
2863
3284
|
}),
|
|
2864
3285
|
top: stickyTop,
|
|
3286
|
+
...(isFirstColumn && { paddingLeft: "24px" }),
|
|
3287
|
+
...(isLastColumn && { paddingRight: "24px" }),
|
|
2865
3288
|
}, children: header.isPlaceholder ? null : (jsxs("div", { className: cn("flex items-center gap-2", header.column.getCanSort() &&
|
|
2866
3289
|
"cursor-pointer select-none"), onClick: header.column.getToggleSortingHandler(), children: [flexRender(header.column.columnDef.header, header.getContext()), header.column.getCanSort() && (jsx("span", { className: "text-surface-ink-neutral-muted", children: {
|
|
2867
3290
|
asc: "↑",
|
|
@@ -2871,42 +3294,41 @@ function TableHeader({ headerGroups, enableRowSelection, enableSelectAll, showHe
|
|
|
2871
3294
|
}) }));
|
|
2872
3295
|
}
|
|
2873
3296
|
|
|
2874
|
-
function TableBody({ rows, enableRowSelection, size, variant, showRowHover, cellClassName,
|
|
3297
|
+
function TableBody({ rows, enableRowSelection, size, variant, showRowHover, cellClassName, onRowClick, getRowClassName, handleRowClick, getColumnStyle, }) {
|
|
2875
3298
|
const [focusedCell, setFocusedCell] = React.useState(null);
|
|
2876
3299
|
const [hoveredRow, setHoveredRow] = React.useState(null);
|
|
2877
3300
|
return (jsx("tbody", { className: cn("bg-surface-fill-neutral-intense"), children: rows.map((row) => {
|
|
2878
|
-
const isRowSelected = row.id === effectiveSelectedRowId;
|
|
2879
3301
|
const isRowHovered = hoveredRow === row.id;
|
|
2880
|
-
const handleClick = () => handleRowClick(row.original
|
|
3302
|
+
const handleClick = () => handleRowClick(row.original);
|
|
2881
3303
|
return (jsxs("tr", { className: cn(variant === "striped" &&
|
|
2882
3304
|
row.index % 2 === 1 &&
|
|
2883
|
-
"bg-surface-fill-neutral-moderate", onRowClick && "cursor-pointer",
|
|
3305
|
+
"bg-surface-fill-neutral-moderate", onRowClick && "cursor-pointer", isRowHovered &&
|
|
2884
3306
|
showRowHover &&
|
|
2885
|
-
"bg-surface-fill-neutral-moderate", getRowClassName(row.original)), onClick: handleClick, onMouseEnter: () => setHoveredRow(row.id), onMouseLeave: () => setHoveredRow(null), children: [enableRowSelection && (jsx("td", { className: cn(tableCellVariants({ size }), "w-10", cellClassName),
|
|
2886
|
-
|
|
3307
|
+
"bg-surface-fill-neutral-moderate", getRowClassName(row.original)), onClick: handleClick, onMouseEnter: () => setHoveredRow(row.id), onMouseLeave: () => setHoveredRow(null), children: [enableRowSelection && (jsx("td", { className: cn(tableCellVariants({ size }), "w-10", cellClassName), style: {
|
|
3308
|
+
paddingTop: "20px",
|
|
3309
|
+
paddingBottom: "20px",
|
|
3310
|
+
}, children: jsx(Checkbox, { checked: row.getIsSelected(), isIndeterminate: row.getIsSomeSelected(), onChange: row.getToggleSelectedHandler(), onClick: (e) => e.stopPropagation(), "aria-label": `Select row ${row.id}` }) })), row.getVisibleCells().map((cell, cellIndex) => {
|
|
2887
3311
|
const isCellFocused = focusedCell?.rowId === row.id &&
|
|
2888
3312
|
focusedCell?.cellId === cell.id;
|
|
2889
3313
|
const cellState = isCellFocused ? "focus" : "default";
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
3314
|
+
const visibleCells = row.getVisibleCells();
|
|
3315
|
+
const isFirstCell = cellIndex === 0;
|
|
3316
|
+
const isLastCell = cellIndex === visibleCells.length - 1;
|
|
3317
|
+
return (jsx("td", { className: cn(tableCellVariants({ size, state: cellState }), cell.column.columnDef.meta?.cellClassName, cellClassName), style: {
|
|
3318
|
+
...getColumnStyle(cell.column.id, {
|
|
3319
|
+
width: cell.column.getSize(),
|
|
3320
|
+
minWidth: cell.column.columnDef.minSize,
|
|
3321
|
+
maxWidth: cell.column.columnDef.maxSize,
|
|
3322
|
+
}),
|
|
3323
|
+
paddingTop: "20px",
|
|
3324
|
+
paddingBottom: "20px",
|
|
3325
|
+
...(isFirstCell && { paddingLeft: "24px" }),
|
|
3326
|
+
...(isLastCell && { paddingRight: "24px" }),
|
|
3327
|
+
}, tabIndex: 0, onFocus: () => setFocusedCell({ rowId: row.id, cellId: cell.id }), onBlur: () => setFocusedCell(null), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
|
|
2897
3328
|
})] }, row.id));
|
|
2898
3329
|
}) }));
|
|
2899
3330
|
}
|
|
2900
3331
|
|
|
2901
|
-
function DetailPanel({ isOpen, content, data, onClose, }) {
|
|
2902
|
-
return (jsx("div", { className: cn("absolute top-0 right-0 h-full z-20 transition-all duration-300 ease-in-out", isOpen
|
|
2903
|
-
? "translate-x-0 opacity-100"
|
|
2904
|
-
: "translate-x-full opacity-0 pointer-events-none"), style: { width: "332px", paddingLeft: "12px" }, children: jsx("div", { className: "w-full h-full bg-white border border-surface-outline-neutral-muted rounded-tr-xlarge rounded-br-xlarge overflow-hidden", children: jsx("div", { className: "w-full h-full overflow-auto", children: data && (jsxs("div", { className: "relative h-full", children: [jsx("button", { onClick: (e) => {
|
|
2905
|
-
e.stopPropagation();
|
|
2906
|
-
onClose();
|
|
2907
|
-
}, className: "absolute top-4 right-4 z-10 p-2 rounded-medium hover:bg-surface-fill-neutral-faded transition-colors", "aria-label": "Close detail panel", children: jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", className: "text-surface-ink-neutral-muted", children: jsx("path", { d: "M12 4L4 12M4 4l8 8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }), content(data)] })) }) }) }));
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
3332
|
function renderDefaultLoadingState({ colSpan }) {
|
|
2911
3333
|
return (jsx("tr", { children: jsx("td", { colSpan: colSpan, className: "text-center py-12 text-surface-ink-neutral-muted", children: jsxs("div", { className: "flex items-center justify-center gap-2", children: [jsx("div", { className: "animate-spin rounded-full h-6 w-6 border-b-2 border-action-fill-primary-default" }), jsx("span", { children: "Loading..." })] }) }) }));
|
|
2912
3334
|
}
|
|
@@ -2915,47 +3337,10 @@ function renderDefaultEmptyState({ colSpan }) {
|
|
|
2915
3337
|
}
|
|
2916
3338
|
|
|
2917
3339
|
// ==================== Component ====================
|
|
2918
|
-
function TableComponent({ className, wrapperClassName, containerClassName, variant, size = "medium", table, enableRowSelection = false, enableSelectAll = false, isLoading = false, loading, loadingComponent, emptyComponent, enableHorizontalScroll = false, stickyHeader = false, maxHeight, showRowHover = true, onRowClick, rowClassName, headerClassName, cellClassName, showHeaderBackground = true,
|
|
2919
|
-
// ==================== State ====================
|
|
2920
|
-
const [internalSelectedRowId, setInternalSelectedRowId] = React.useState(null);
|
|
2921
|
-
const selectedRowIdRef = React.useRef(null);
|
|
2922
|
-
const effectiveSelectedRowId = selectedRowId !== undefined ? selectedRowId : internalSelectedRowId;
|
|
2923
|
-
const isDetailPanelOpen = Boolean(effectiveSelectedRowId);
|
|
2924
|
-
// ==================== Effects ====================
|
|
2925
|
-
// Keep ref in sync
|
|
2926
|
-
React.useEffect(() => {
|
|
2927
|
-
selectedRowIdRef.current = effectiveSelectedRowId;
|
|
2928
|
-
}, [effectiveSelectedRowId]);
|
|
2929
|
-
// Clear selection if selected row is not in current data
|
|
2930
|
-
React.useEffect(() => {
|
|
2931
|
-
if (effectiveSelectedRowId) {
|
|
2932
|
-
const rowExists = table
|
|
2933
|
-
.getRowModel()
|
|
2934
|
-
.rows.some((r) => r.id === effectiveSelectedRowId);
|
|
2935
|
-
if (!rowExists) {
|
|
2936
|
-
if (selectedRowId === undefined) {
|
|
2937
|
-
setInternalSelectedRowId(null);
|
|
2938
|
-
}
|
|
2939
|
-
if (onRowSelectionChange) {
|
|
2940
|
-
onRowSelectionChange(null);
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
}, [
|
|
2945
|
-
table.getRowModel().rows,
|
|
2946
|
-
effectiveSelectedRowId,
|
|
2947
|
-
selectedRowId,
|
|
2948
|
-
onRowSelectionChange,
|
|
2949
|
-
]);
|
|
3340
|
+
function TableComponent({ className, wrapperClassName, containerClassName, variant, size = "medium", table, enableRowSelection = false, enableSelectAll = false, isLoading = false, loading, loadingComponent, emptyComponent, enableHorizontalScroll = false, stickyHeader = false, maxHeight, showRowHover = true, onRowClick, rowClassName, headerClassName, cellClassName, showHeaderBackground = true, loadingSkeletonRows, loadingSkeletonHeight, columnWidths, columnMinWidths, columnMaxWidths, ...props }, ref) {
|
|
2950
3341
|
// ==================== Computed Values ====================
|
|
2951
3342
|
const hasData = table.getRowModel().rows?.length > 0;
|
|
2952
3343
|
const headerGroups = table.getHeaderGroups();
|
|
2953
|
-
const headers = headerGroups[0]?.headers || [];
|
|
2954
|
-
const visibleHeadersCount = React.useMemo(() => {
|
|
2955
|
-
return isDetailPanelOpen
|
|
2956
|
-
? headers.length - hideColumnsOnDetailOpen
|
|
2957
|
-
: headers.length;
|
|
2958
|
-
}, [isDetailPanelOpen, headers.length, hideColumnsOnDetailOpen]);
|
|
2959
3344
|
const normalizeSizeValue = (value) => {
|
|
2960
3345
|
if (value === undefined)
|
|
2961
3346
|
return undefined;
|
|
@@ -3022,42 +3407,18 @@ function TableComponent({ className, wrapperClassName, containerClassName, varia
|
|
|
3022
3407
|
}
|
|
3023
3408
|
return rowClassName || "";
|
|
3024
3409
|
}, [rowClassName]);
|
|
3025
|
-
const handleRowClickInternal = React.useCallback((row
|
|
3026
|
-
const currentSelectedId = selectedRowIdRef.current;
|
|
3027
|
-
const newSelectedId = currentSelectedId === rowId ? null : rowId;
|
|
3028
|
-
if (selectedRowId === undefined) {
|
|
3029
|
-
setInternalSelectedRowId(newSelectedId);
|
|
3030
|
-
}
|
|
3031
|
-
if (onRowSelectionChange) {
|
|
3032
|
-
onRowSelectionChange(newSelectedId);
|
|
3033
|
-
}
|
|
3410
|
+
const handleRowClickInternal = React.useCallback((row) => {
|
|
3034
3411
|
if (onRowClick) {
|
|
3035
3412
|
onRowClick(row);
|
|
3036
3413
|
}
|
|
3037
|
-
}, [
|
|
3038
|
-
const getSelectedRowData = () => {
|
|
3039
|
-
if (!effectiveSelectedRowId)
|
|
3040
|
-
return null;
|
|
3041
|
-
const row = table
|
|
3042
|
-
.getRowModel()
|
|
3043
|
-
.rows.find((r) => r.id === effectiveSelectedRowId);
|
|
3044
|
-
return row ? row.original : null;
|
|
3045
|
-
};
|
|
3046
|
-
const handleDetailPanelClose = () => {
|
|
3047
|
-
if (selectedRowId === undefined) {
|
|
3048
|
-
setInternalSelectedRowId(null);
|
|
3049
|
-
}
|
|
3050
|
-
if (onRowSelectionChange) {
|
|
3051
|
-
onRowSelectionChange(null);
|
|
3052
|
-
}
|
|
3053
|
-
};
|
|
3414
|
+
}, [onRowClick]);
|
|
3054
3415
|
const renderEmptyState = () => {
|
|
3055
3416
|
if (emptyComponent)
|
|
3056
3417
|
return emptyComponent;
|
|
3057
3418
|
return renderDefaultEmptyState({ colSpan: table.getAllColumns().length });
|
|
3058
3419
|
};
|
|
3059
3420
|
// ==================== Render ====================
|
|
3060
|
-
return (jsx("div", { ref: ref, className: cn("w-full", wrapperClassName), ...props, children:
|
|
3421
|
+
return (jsx("div", { ref: ref, className: cn("w-full", wrapperClassName), ...props, children: jsx("div", { className: cn("relative", enableHorizontalScroll ? "overflow-x-auto" : "overflow-x-hidden", maxHeight && "overflow-y-auto", containerClassName), style: containerStyle, children: jsxs("table", { className: cn(tableVariants({ variant, size }), className), children: [jsx(TableHeader, { headerGroups: headerGroups, enableRowSelection: enableRowSelection, enableSelectAll: enableSelectAll, showHeaderBackground: showHeaderBackground, stickyHeader: stickyHeader, size: size || "medium", headerClassName: headerClassName, onToggleAllRows: (e) => table.getToggleAllRowsSelectedHandler()(e), isAllRowsSelected: table.getIsAllRowsSelected(), isSomeRowsSelected: table.getIsSomeRowsSelected(), getColumnStyle: getColumnStyle }), resolvedLoading ? (jsx("tbody", { children: renderLoadingContent() })) : !hasData ? (jsx("tbody", { children: renderEmptyState() })) : (jsx(TableBody, { rows: table.getRowModel().rows, enableRowSelection: enableRowSelection, size: size || "medium", variant: variant || "default", showRowHover: showRowHover, cellClassName: cellClassName, onRowClick: onRowClick, getRowClassName: getRowClassName, handleRowClick: handleRowClickInternal, getColumnStyle: getColumnStyle }))] }) }) }));
|
|
3061
3422
|
}
|
|
3062
3423
|
// ==================== Export ====================
|
|
3063
3424
|
const Table = React.forwardRef(TableComponent);
|
|
@@ -3305,5 +3666,5 @@ const TextArea = React.forwardRef(({ label, helperText, errorText, successText,
|
|
|
3305
3666
|
});
|
|
3306
3667
|
TextArea.displayName = "TextArea";
|
|
3307
3668
|
|
|
3308
|
-
export { Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, dropdownVariants, getAvailableIcons, hasIcon, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
|
|
3669
|
+
export { Alert, Avatar, AvatarCell, Badge, Button, ButtonGroup, Checkbox, Counter, Divider, Dropdown, DropdownMenu, FormFooter, FormHeader, Icon, IconButton, IconCell, Link, ListItem, Modal, NumberCell, Pagination, Radio, SearchableDropdown, Select, Skeleton, SlotCell, SpacerCell, Switch, TabItem, Table, TableDetailPanel, Tabs, Text, TextArea, TextField, Tooltip, alertVariants, avatarVariants, badgeVariants, buttonGroupVariants, buttonVariants, checkboxVariants, cn, counterVariants, dropdownVariants, getAvailableIcons, hasIcon, iconButtonVariants, iconRegistry, linkVariants, listItemVariants, paginationVariants, radioVariants, selectVariants, switchVariants, tableCellVariants, tableHeaderVariants, tableVariants, textAreaVariants, textFieldVariants, tooltipVariants };
|
|
3309
3670
|
//# sourceMappingURL=index.esm.js.map
|