@cytario/design 1.13.1 → 1.15.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/index.d.ts +164 -4
- package/dist/index.js +659 -112
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -542,6 +542,7 @@ function Select({
|
|
|
542
542
|
items,
|
|
543
543
|
placeholder = "Select an option",
|
|
544
544
|
errorMessage,
|
|
545
|
+
hideLabel = false,
|
|
545
546
|
isDisabled,
|
|
546
547
|
isRequired,
|
|
547
548
|
className,
|
|
@@ -561,8 +562,9 @@ function Select({
|
|
|
561
562
|
Label2,
|
|
562
563
|
{
|
|
563
564
|
className: [
|
|
564
|
-
"text-[length:var(--font-size-sm)] font-[var(--font-weight-medium)] text-[var(--color-text-primary)]"
|
|
565
|
-
|
|
565
|
+
"text-[length:var(--font-size-sm)] font-[var(--font-weight-medium)] text-[var(--color-text-primary)]",
|
|
566
|
+
hideLabel && "sr-only"
|
|
567
|
+
].filter(Boolean).join(" "),
|
|
566
568
|
children: [
|
|
567
569
|
label,
|
|
568
570
|
isRequired && /* @__PURE__ */ jsx7(
|
|
@@ -2141,35 +2143,320 @@ function SegmentedControlItem({
|
|
|
2141
2143
|
);
|
|
2142
2144
|
}
|
|
2143
2145
|
|
|
2146
|
+
// src/components/FileCard/FileCard.tsx
|
|
2147
|
+
import { useCallback as useCallback3 } from "react";
|
|
2148
|
+
import {
|
|
2149
|
+
File as File2,
|
|
2150
|
+
FileSpreadsheet,
|
|
2151
|
+
Folder as Folder2,
|
|
2152
|
+
Image,
|
|
2153
|
+
Info as Info2,
|
|
2154
|
+
Microscope
|
|
2155
|
+
} from "lucide-react";
|
|
2156
|
+
import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2157
|
+
function getFileIcon(type, extension) {
|
|
2158
|
+
if (type === "directory") return Folder2;
|
|
2159
|
+
const ext = (extension ?? "").toLowerCase();
|
|
2160
|
+
if (ext === "ome.tif" || ext === "ome.tiff") return Microscope;
|
|
2161
|
+
if (/^(tiff?|png|jpe?g)$/.test(ext)) return Image;
|
|
2162
|
+
if (/^(csv|parquet)$/.test(ext)) return FileSpreadsheet;
|
|
2163
|
+
return File2;
|
|
2164
|
+
}
|
|
2165
|
+
function getTypeLabel(type, extension) {
|
|
2166
|
+
if (type === "directory") return "Folder";
|
|
2167
|
+
const ext = (extension ?? "").toLowerCase();
|
|
2168
|
+
if (ext === "ome.tif" || ext === "ome.tiff") return "OME-TIFF";
|
|
2169
|
+
if (/^tiff?$/.test(ext)) return "TIFF";
|
|
2170
|
+
if (ext === "csv") return "CSV";
|
|
2171
|
+
if (ext === "parquet") return "Parquet";
|
|
2172
|
+
if (ext === "png") return "PNG";
|
|
2173
|
+
if (/^jpe?g$/.test(ext)) return "JPEG";
|
|
2174
|
+
return ext.toUpperCase() || "File";
|
|
2175
|
+
}
|
|
2176
|
+
function FileIcon({
|
|
2177
|
+
type,
|
|
2178
|
+
extension,
|
|
2179
|
+
size = 16
|
|
2180
|
+
}) {
|
|
2181
|
+
const IconComponent = getFileIcon(type, extension);
|
|
2182
|
+
return /* @__PURE__ */ jsx30(
|
|
2183
|
+
IconComponent,
|
|
2184
|
+
{
|
|
2185
|
+
size,
|
|
2186
|
+
className: "shrink-0 text-[var(--color-text-secondary)]"
|
|
2187
|
+
}
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
function FileCard({
|
|
2191
|
+
name,
|
|
2192
|
+
type,
|
|
2193
|
+
size,
|
|
2194
|
+
extension,
|
|
2195
|
+
compact = false,
|
|
2196
|
+
children,
|
|
2197
|
+
onInfo,
|
|
2198
|
+
href,
|
|
2199
|
+
onPress,
|
|
2200
|
+
className
|
|
2201
|
+
}) {
|
|
2202
|
+
const isInteractive = !!href || !!onPress;
|
|
2203
|
+
const radius = compact ? "rounded-[var(--border-radius-md)]" : "rounded-[var(--border-radius-lg)]";
|
|
2204
|
+
const IconComponent = getFileIcon(type, extension);
|
|
2205
|
+
const iconSize = compact ? 24 : 32;
|
|
2206
|
+
const iconColor = type === "directory" ? "text-[var(--color-text-tertiary)]" : "text-[var(--color-text-secondary)]";
|
|
2207
|
+
const thumbnailClass = compact ? "aspect-square rounded-t-[var(--border-radius-md)]" : "aspect-[4/3] rounded-t-[var(--border-radius-lg)]";
|
|
2208
|
+
const handleInfoClick = useCallback3(
|
|
2209
|
+
(e) => {
|
|
2210
|
+
if (isInteractive) {
|
|
2211
|
+
e.stopPropagation();
|
|
2212
|
+
e.preventDefault();
|
|
2213
|
+
}
|
|
2214
|
+
onInfo?.();
|
|
2215
|
+
},
|
|
2216
|
+
[onInfo, isInteractive]
|
|
2217
|
+
);
|
|
2218
|
+
const handleKeyDown = useCallback3(
|
|
2219
|
+
(e) => {
|
|
2220
|
+
if (onPress && (e.key === "Enter" || e.key === " ")) {
|
|
2221
|
+
e.preventDefault();
|
|
2222
|
+
onPress();
|
|
2223
|
+
}
|
|
2224
|
+
},
|
|
2225
|
+
[onPress]
|
|
2226
|
+
);
|
|
2227
|
+
const cardContent = /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
2228
|
+
/* @__PURE__ */ jsxs20(
|
|
2229
|
+
"div",
|
|
2230
|
+
{
|
|
2231
|
+
className: `shrink-0 relative overflow-hidden bg-[var(--color-neutral-900)] ${thumbnailClass}`,
|
|
2232
|
+
children: [
|
|
2233
|
+
children ? /* @__PURE__ */ jsx30("div", { className: "h-full w-full overflow-hidden", children }) : /* @__PURE__ */ jsx30("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx30(IconComponent, { size: iconSize, className: iconColor }) }),
|
|
2234
|
+
onInfo && /* @__PURE__ */ jsx30(
|
|
2235
|
+
"div",
|
|
2236
|
+
{
|
|
2237
|
+
className: [
|
|
2238
|
+
"absolute opacity-0 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
2239
|
+
"transition-opacity duration-150",
|
|
2240
|
+
compact ? "bottom-1.5 right-1.5" : "bottom-2 right-2"
|
|
2241
|
+
].join(" "),
|
|
2242
|
+
children: /* @__PURE__ */ jsx30(
|
|
2243
|
+
"span",
|
|
2244
|
+
{
|
|
2245
|
+
onClick: handleInfoClick,
|
|
2246
|
+
onKeyDown: (e) => {
|
|
2247
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2248
|
+
handleInfoClick(e);
|
|
2249
|
+
}
|
|
2250
|
+
},
|
|
2251
|
+
role: "presentation",
|
|
2252
|
+
children: /* @__PURE__ */ jsx30(
|
|
2253
|
+
IconButton,
|
|
2254
|
+
{
|
|
2255
|
+
icon: Info2,
|
|
2256
|
+
"aria-label": `Show info for ${name}`,
|
|
2257
|
+
variant: "ghost",
|
|
2258
|
+
size: "sm",
|
|
2259
|
+
className: "bg-[var(--color-neutral-900)]/75 text-[var(--color-text-inverse)] hover:bg-[var(--color-neutral-900)]/90 rounded-[var(--border-radius-sm)]",
|
|
2260
|
+
onPress: onInfo
|
|
2261
|
+
}
|
|
2262
|
+
)
|
|
2263
|
+
}
|
|
2264
|
+
)
|
|
2265
|
+
}
|
|
2266
|
+
)
|
|
2267
|
+
]
|
|
2268
|
+
}
|
|
2269
|
+
),
|
|
2270
|
+
/* @__PURE__ */ jsx30(
|
|
2271
|
+
"div",
|
|
2272
|
+
{
|
|
2273
|
+
className: [
|
|
2274
|
+
"flex flex-col border-t border-[var(--color-border-default)]",
|
|
2275
|
+
"bg-[var(--color-surface-default)]",
|
|
2276
|
+
compact ? "px-2 py-1.5 rounded-b-[var(--border-radius-md)]" : "gap-0.5 px-3 py-2 rounded-b-[var(--border-radius-lg)]"
|
|
2277
|
+
].join(" "),
|
|
2278
|
+
children: compact ? /* @__PURE__ */ jsx30("span", { className: "text-xs font-medium text-[var(--color-text-primary)] truncate", children: name }) : /* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
2279
|
+
/* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1.5", children: [
|
|
2280
|
+
/* @__PURE__ */ jsx30(FileIcon, { type, extension, size: 16 }),
|
|
2281
|
+
/* @__PURE__ */ jsx30("span", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name })
|
|
2282
|
+
] }),
|
|
2283
|
+
size && /* @__PURE__ */ jsx30("span", { className: "text-xs text-[var(--color-text-secondary)] tabular-nums pl-[22px]", children: size })
|
|
2284
|
+
] })
|
|
2285
|
+
}
|
|
2286
|
+
)
|
|
2287
|
+
] });
|
|
2288
|
+
const baseStyles = [
|
|
2289
|
+
"group flex flex-col overflow-hidden",
|
|
2290
|
+
radius,
|
|
2291
|
+
"border border-[var(--color-border-default)]",
|
|
2292
|
+
"shadow-sm",
|
|
2293
|
+
"transition-all",
|
|
2294
|
+
isInteractive && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
|
|
2295
|
+
isInteractive && "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
|
|
2296
|
+
className
|
|
2297
|
+
].filter(Boolean).join(" ");
|
|
2298
|
+
if (href) {
|
|
2299
|
+
return /* @__PURE__ */ jsx30(
|
|
2300
|
+
"a",
|
|
2301
|
+
{
|
|
2302
|
+
href,
|
|
2303
|
+
"aria-label": name,
|
|
2304
|
+
className: [baseStyles, "no-underline"].join(" "),
|
|
2305
|
+
children: cardContent
|
|
2306
|
+
}
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
if (onPress) {
|
|
2310
|
+
return /* @__PURE__ */ jsx30(
|
|
2311
|
+
"div",
|
|
2312
|
+
{
|
|
2313
|
+
role: "button",
|
|
2314
|
+
tabIndex: 0,
|
|
2315
|
+
"aria-label": name,
|
|
2316
|
+
className: baseStyles,
|
|
2317
|
+
onClick: onPress,
|
|
2318
|
+
onKeyDown: handleKeyDown,
|
|
2319
|
+
children: cardContent
|
|
2320
|
+
}
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
return /* @__PURE__ */ jsx30("div", { className: baseStyles, children: cardContent });
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2144
2326
|
// src/components/StorageConnectionCard/StorageConnectionCard.tsx
|
|
2145
|
-
import {
|
|
2327
|
+
import { useCallback as useCallback4 } from "react";
|
|
2328
|
+
import { AlertCircle, Database, Info as Info3 } from "lucide-react";
|
|
2329
|
+
import { twMerge as twMerge9 } from "tailwind-merge";
|
|
2330
|
+
|
|
2331
|
+
// src/components/Pill/Pill.tsx
|
|
2146
2332
|
import { twMerge as twMerge7 } from "tailwind-merge";
|
|
2147
|
-
import {
|
|
2333
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
2334
|
+
var HASH_PALETTE = [
|
|
2335
|
+
"teal",
|
|
2336
|
+
// sky
|
|
2337
|
+
"amber",
|
|
2338
|
+
// amber
|
|
2339
|
+
"green",
|
|
2340
|
+
// emerald
|
|
2341
|
+
"rose",
|
|
2342
|
+
// rose
|
|
2343
|
+
"purple",
|
|
2344
|
+
// violet
|
|
2345
|
+
"amber",
|
|
2346
|
+
// orange (mapped to amber -- closest warm token)
|
|
2347
|
+
"teal",
|
|
2348
|
+
// teal
|
|
2349
|
+
"rose"
|
|
2350
|
+
// fuchsia (mapped to rose -- closest pink token)
|
|
2351
|
+
];
|
|
2352
|
+
function pillColorFromName(name) {
|
|
2353
|
+
let hash = 0;
|
|
2354
|
+
for (let i = 0; i < name.length; i++) {
|
|
2355
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
2356
|
+
}
|
|
2357
|
+
return HASH_PALETTE[Math.abs(hash) % HASH_PALETTE.length];
|
|
2358
|
+
}
|
|
2359
|
+
var colorStyles = {
|
|
2360
|
+
neutral: "bg-[var(--color-badge-neutral-bg)] text-[var(--color-badge-neutral-text)]",
|
|
2361
|
+
purple: "bg-[var(--color-badge-purple-bg)] text-[var(--color-badge-purple-text)]",
|
|
2362
|
+
teal: "bg-[var(--color-badge-teal-bg)] text-[var(--color-badge-teal-text)]",
|
|
2363
|
+
rose: "bg-[var(--color-badge-rose-bg)] text-[var(--color-badge-rose-text)]",
|
|
2364
|
+
slate: "bg-[var(--color-badge-slate-bg)] text-[var(--color-badge-slate-text)]",
|
|
2365
|
+
green: "bg-[var(--color-badge-green-bg)] text-[var(--color-badge-green-text)]",
|
|
2366
|
+
amber: "bg-[var(--color-badge-amber-bg)] text-[var(--color-badge-amber-text)]"
|
|
2367
|
+
};
|
|
2368
|
+
var dotColorStyles = {
|
|
2369
|
+
neutral: "bg-[var(--color-badge-neutral-text)]",
|
|
2370
|
+
purple: "bg-[var(--color-badge-purple-text)]",
|
|
2371
|
+
teal: "bg-[var(--color-badge-teal-text)]",
|
|
2372
|
+
rose: "bg-[var(--color-badge-rose-text)]",
|
|
2373
|
+
slate: "bg-[var(--color-badge-slate-text)]",
|
|
2374
|
+
green: "bg-[var(--color-badge-green-text)]",
|
|
2375
|
+
amber: "bg-[var(--color-badge-amber-text)]"
|
|
2376
|
+
};
|
|
2377
|
+
function resolveColor(color, name) {
|
|
2378
|
+
if (color && color !== "auto") return color;
|
|
2379
|
+
if (name) return pillColorFromName(name);
|
|
2380
|
+
return "neutral";
|
|
2381
|
+
}
|
|
2382
|
+
function Pill({ children, color, name, className }) {
|
|
2383
|
+
const resolved = resolveColor(color, name);
|
|
2384
|
+
return /* @__PURE__ */ jsx31(
|
|
2385
|
+
"span",
|
|
2386
|
+
{
|
|
2387
|
+
className: twMerge7(
|
|
2388
|
+
"inline-flex items-center rounded-full",
|
|
2389
|
+
"px-2 py-0.5",
|
|
2390
|
+
"text-[length:var(--font-size-xs)] font-[number:var(--font-weight-medium)] leading-[var(--line-height-tight)]",
|
|
2391
|
+
colorStyles[resolved],
|
|
2392
|
+
className
|
|
2393
|
+
),
|
|
2394
|
+
children
|
|
2395
|
+
}
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
// src/components/Pill/GroupPill.tsx
|
|
2400
|
+
import { twMerge as twMerge8 } from "tailwind-merge";
|
|
2401
|
+
import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2402
|
+
function GroupPill({
|
|
2403
|
+
path,
|
|
2404
|
+
visibleCount = 3,
|
|
2405
|
+
className
|
|
2406
|
+
}) {
|
|
2407
|
+
const segments = path.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
2408
|
+
if (segments.length === 0) return null;
|
|
2409
|
+
const hiddenCount = Math.max(0, segments.length - visibleCount);
|
|
2410
|
+
const hiddenSegments = segments.slice(0, hiddenCount);
|
|
2411
|
+
const visibleSegments = segments.slice(hiddenCount);
|
|
2412
|
+
return /* @__PURE__ */ jsxs21(
|
|
2413
|
+
"span",
|
|
2414
|
+
{
|
|
2415
|
+
className: twMerge8(
|
|
2416
|
+
"inline-flex items-center gap-1",
|
|
2417
|
+
className
|
|
2418
|
+
),
|
|
2419
|
+
"aria-label": `Group: ${segments.join(" / ")}`,
|
|
2420
|
+
children: [
|
|
2421
|
+
hiddenSegments.map((segment, index) => {
|
|
2422
|
+
const color = pillColorFromName(segment);
|
|
2423
|
+
return /* @__PURE__ */ jsx32(
|
|
2424
|
+
"span",
|
|
2425
|
+
{
|
|
2426
|
+
className: twMerge8(
|
|
2427
|
+
"inline-block size-2 shrink-0 rounded-full",
|
|
2428
|
+
dotColorStyles[color]
|
|
2429
|
+
),
|
|
2430
|
+
"aria-hidden": "true",
|
|
2431
|
+
title: segment
|
|
2432
|
+
},
|
|
2433
|
+
`dot-${index}-${segment}`
|
|
2434
|
+
);
|
|
2435
|
+
}),
|
|
2436
|
+
visibleSegments.map((segment, index) => /* @__PURE__ */ jsx32(Pill, { name: segment, children: segment }, `pill-${index}-${segment}`))
|
|
2437
|
+
]
|
|
2438
|
+
}
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// src/components/StorageConnectionCard/StorageConnectionCard.tsx
|
|
2443
|
+
import { Fragment as Fragment9, jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2148
2444
|
var statusDotStyles = {
|
|
2149
2445
|
connected: "bg-[var(--color-status-success)]",
|
|
2150
2446
|
error: "border-2 border-[var(--color-status-danger)] bg-transparent",
|
|
2151
2447
|
loading: "bg-[var(--color-status-warning)] animate-pulse"
|
|
2152
2448
|
};
|
|
2153
2449
|
var providerConfig = {
|
|
2154
|
-
aws: { label: "AWS", color: "
|
|
2155
|
-
azure: { label: "Azure", color: "
|
|
2156
|
-
gcp: { label: "GCP", color: "
|
|
2157
|
-
minio: { label: "MinIO", color: "
|
|
2450
|
+
aws: { label: "AWS", color: "purple" },
|
|
2451
|
+
azure: { label: "Azure", color: "teal" },
|
|
2452
|
+
gcp: { label: "GCP", color: "slate" },
|
|
2453
|
+
minio: { label: "MinIO", color: "rose" }
|
|
2158
2454
|
};
|
|
2159
2455
|
function ProviderBadge({ provider }) {
|
|
2160
2456
|
const config = providerConfig[provider.toLowerCase()];
|
|
2161
2457
|
const label = config?.label ?? provider;
|
|
2162
|
-
const
|
|
2163
|
-
return /* @__PURE__ */
|
|
2164
|
-
"span",
|
|
2165
|
-
{
|
|
2166
|
-
className: twMerge7(
|
|
2167
|
-
"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
|
|
2168
|
-
colorClass
|
|
2169
|
-
),
|
|
2170
|
-
children: label
|
|
2171
|
-
}
|
|
2172
|
-
);
|
|
2458
|
+
const color = config?.color ?? "neutral";
|
|
2459
|
+
return /* @__PURE__ */ jsx33(Pill, { color, children: label });
|
|
2173
2460
|
}
|
|
2174
2461
|
function PreviewArea({
|
|
2175
2462
|
status = "connected",
|
|
@@ -2177,11 +2464,11 @@ function PreviewArea({
|
|
|
2177
2464
|
children
|
|
2178
2465
|
}) {
|
|
2179
2466
|
if (status === "loading") {
|
|
2180
|
-
return /* @__PURE__ */
|
|
2467
|
+
return /* @__PURE__ */ jsx33("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx33(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
|
|
2181
2468
|
}
|
|
2182
2469
|
if (status === "error") {
|
|
2183
|
-
return /* @__PURE__ */
|
|
2184
|
-
/* @__PURE__ */
|
|
2470
|
+
return /* @__PURE__ */ jsxs22("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-[var(--color-surface-danger)] px-4", children: [
|
|
2471
|
+
/* @__PURE__ */ jsx33(
|
|
2185
2472
|
Icon,
|
|
2186
2473
|
{
|
|
2187
2474
|
icon: AlertCircle,
|
|
@@ -2189,13 +2476,13 @@ function PreviewArea({
|
|
|
2189
2476
|
className: "text-[var(--color-text-danger)]"
|
|
2190
2477
|
}
|
|
2191
2478
|
),
|
|
2192
|
-
errorMessage && /* @__PURE__ */
|
|
2479
|
+
errorMessage && /* @__PURE__ */ jsx33("p", { className: "text-center text-xs text-[var(--color-text-danger)]", children: errorMessage })
|
|
2193
2480
|
] });
|
|
2194
2481
|
}
|
|
2195
2482
|
if (children) {
|
|
2196
|
-
return /* @__PURE__ */
|
|
2483
|
+
return /* @__PURE__ */ jsx33("div", { className: "h-full w-full overflow-hidden", children });
|
|
2197
2484
|
}
|
|
2198
|
-
return /* @__PURE__ */
|
|
2485
|
+
return /* @__PURE__ */ jsx33("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx33(
|
|
2199
2486
|
Icon,
|
|
2200
2487
|
{
|
|
2201
2488
|
icon: Database,
|
|
@@ -2213,42 +2500,73 @@ function StorageConnectionCard({
|
|
|
2213
2500
|
imageCount,
|
|
2214
2501
|
children,
|
|
2215
2502
|
href,
|
|
2503
|
+
onPress,
|
|
2216
2504
|
onInfo,
|
|
2217
2505
|
className
|
|
2218
2506
|
}) {
|
|
2219
|
-
const
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2507
|
+
const isInteractive = !!href || !!onPress;
|
|
2508
|
+
const handleInfoPress = useCallback4(
|
|
2509
|
+
(e) => {
|
|
2510
|
+
if (isInteractive) {
|
|
2511
|
+
e.stopPropagation();
|
|
2512
|
+
e.preventDefault();
|
|
2513
|
+
}
|
|
2514
|
+
onInfo?.();
|
|
2515
|
+
},
|
|
2516
|
+
[onInfo, isInteractive]
|
|
2517
|
+
);
|
|
2518
|
+
const handleKeyDown = useCallback4(
|
|
2519
|
+
(e) => {
|
|
2520
|
+
if (onPress && (e.key === "Enter" || e.key === " ")) {
|
|
2521
|
+
e.preventDefault();
|
|
2522
|
+
onPress();
|
|
2523
|
+
}
|
|
2524
|
+
},
|
|
2525
|
+
[onPress]
|
|
2526
|
+
);
|
|
2527
|
+
const cardContent = /* @__PURE__ */ jsxs22(Fragment9, { children: [
|
|
2528
|
+
/* @__PURE__ */ jsx33("div", { className: "aspect-[4/3] bg-[var(--color-neutral-900)] overflow-hidden rounded-t-[var(--border-radius-lg)]", children: /* @__PURE__ */ jsx33(PreviewArea, { status, errorMessage, children }) }),
|
|
2529
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-1.5 border-t border-[var(--color-border-default)] bg-[var(--color-surface-default)] px-3 py-2.5 rounded-b-[var(--border-radius-lg)]", children: [
|
|
2530
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-start gap-2", children: [
|
|
2531
|
+
status && /* @__PURE__ */ jsx33(
|
|
2224
2532
|
"span",
|
|
2225
2533
|
{
|
|
2226
|
-
className:
|
|
2534
|
+
className: twMerge9(
|
|
2227
2535
|
"mt-1.5 h-2 w-2 shrink-0 rounded-full",
|
|
2228
2536
|
statusDotStyles[status]
|
|
2229
2537
|
),
|
|
2230
2538
|
"aria-label": `Status: ${status}`
|
|
2231
2539
|
}
|
|
2232
2540
|
),
|
|
2233
|
-
/* @__PURE__ */
|
|
2234
|
-
onInfo && /* @__PURE__ */
|
|
2235
|
-
|
|
2541
|
+
/* @__PURE__ */ jsx33("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-[var(--color-text-primary)]", children: name }),
|
|
2542
|
+
onInfo && /* @__PURE__ */ jsx33(
|
|
2543
|
+
"span",
|
|
2236
2544
|
{
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2545
|
+
onClick: handleInfoPress,
|
|
2546
|
+
onKeyDown: (e) => {
|
|
2547
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2548
|
+
handleInfoPress(e);
|
|
2549
|
+
}
|
|
2550
|
+
},
|
|
2551
|
+
role: "presentation",
|
|
2552
|
+
children: /* @__PURE__ */ jsx33(
|
|
2553
|
+
IconButton,
|
|
2554
|
+
{
|
|
2555
|
+
icon: Info3,
|
|
2556
|
+
"aria-label": "Connection info",
|
|
2557
|
+
variant: "ghost",
|
|
2558
|
+
size: "sm",
|
|
2559
|
+
className: "shrink-0 -mt-1 -mr-1",
|
|
2560
|
+
onPress: onInfo
|
|
2561
|
+
}
|
|
2562
|
+
)
|
|
2245
2563
|
}
|
|
2246
2564
|
)
|
|
2247
2565
|
] }),
|
|
2248
|
-
(provider || imageCount != null && (!status || status === "connected")) && /* @__PURE__ */
|
|
2249
|
-
provider && /* @__PURE__ */
|
|
2250
|
-
provider && region && /* @__PURE__ */
|
|
2251
|
-
imageCount != null && (!status || status === "connected") && /* @__PURE__ */
|
|
2566
|
+
(provider || imageCount != null && (!status || status === "connected")) && /* @__PURE__ */ jsxs22("div", { className: twMerge9("flex items-center gap-2", status && "pl-4"), children: [
|
|
2567
|
+
provider && /* @__PURE__ */ jsx33(ProviderBadge, { provider }),
|
|
2568
|
+
provider && region && /* @__PURE__ */ jsx33("span", { className: "shrink-0 text-xs text-[var(--color-text-secondary)]", children: region }),
|
|
2569
|
+
imageCount != null && (!status || status === "connected") && /* @__PURE__ */ jsxs22("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-[var(--color-text-secondary)]", children: [
|
|
2252
2570
|
imageCount,
|
|
2253
2571
|
" ",
|
|
2254
2572
|
imageCount === 1 ? "image" : "images"
|
|
@@ -2256,22 +2574,36 @@ function StorageConnectionCard({
|
|
|
2256
2574
|
] })
|
|
2257
2575
|
] })
|
|
2258
2576
|
] });
|
|
2259
|
-
const baseStyles =
|
|
2577
|
+
const baseStyles = twMerge9(
|
|
2260
2578
|
"flex flex-col overflow-hidden rounded-[var(--border-radius-lg)]",
|
|
2261
2579
|
"border border-[var(--color-border-default)]",
|
|
2262
2580
|
"shadow-sm transition-all",
|
|
2263
|
-
|
|
2581
|
+
isInteractive && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
|
|
2582
|
+
isInteractive && "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
|
|
2264
2583
|
className
|
|
2265
2584
|
);
|
|
2266
2585
|
if (href) {
|
|
2267
|
-
return /* @__PURE__ */
|
|
2586
|
+
return /* @__PURE__ */ jsx33("a", { href, className: twMerge9(baseStyles, "no-underline"), children: cardContent });
|
|
2268
2587
|
}
|
|
2269
|
-
|
|
2588
|
+
if (onPress) {
|
|
2589
|
+
return /* @__PURE__ */ jsx33(
|
|
2590
|
+
"div",
|
|
2591
|
+
{
|
|
2592
|
+
role: "button",
|
|
2593
|
+
tabIndex: 0,
|
|
2594
|
+
className: baseStyles,
|
|
2595
|
+
onClick: onPress,
|
|
2596
|
+
onKeyDown: handleKeyDown,
|
|
2597
|
+
children: cardContent
|
|
2598
|
+
}
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return /* @__PURE__ */ jsx33("div", { className: baseStyles, children: cardContent });
|
|
2270
2602
|
}
|
|
2271
2603
|
|
|
2272
2604
|
// src/components/Badge/Badge.tsx
|
|
2273
|
-
import { twMerge as
|
|
2274
|
-
import { jsx as
|
|
2605
|
+
import { twMerge as twMerge10 } from "tailwind-merge";
|
|
2606
|
+
import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2275
2607
|
var variantStyles4 = {
|
|
2276
2608
|
neutral: "bg-[var(--color-badge-neutral-bg)] text-[var(--color-badge-neutral-text)]",
|
|
2277
2609
|
purple: "bg-[var(--color-badge-purple-bg)] text-[var(--color-badge-purple-text)]",
|
|
@@ -2296,10 +2628,10 @@ function Badge({
|
|
|
2296
2628
|
icon: IconComponent,
|
|
2297
2629
|
className
|
|
2298
2630
|
}) {
|
|
2299
|
-
return /* @__PURE__ */
|
|
2631
|
+
return /* @__PURE__ */ jsxs23(
|
|
2300
2632
|
"span",
|
|
2301
2633
|
{
|
|
2302
|
-
className:
|
|
2634
|
+
className: twMerge10(
|
|
2303
2635
|
"inline-flex items-center gap-1 rounded-[var(--border-radius-full)]",
|
|
2304
2636
|
"text-[length:var(--font-size-xs)] font-[number:var(--font-weight-medium)] leading-[var(--line-height-tight)]",
|
|
2305
2637
|
variantStyles4[variant],
|
|
@@ -2307,7 +2639,7 @@ function Badge({
|
|
|
2307
2639
|
className
|
|
2308
2640
|
),
|
|
2309
2641
|
children: [
|
|
2310
|
-
IconComponent && /* @__PURE__ */
|
|
2642
|
+
IconComponent && /* @__PURE__ */ jsx34(IconComponent, { size: iconSizeMap4[size], "aria-hidden": "true" }),
|
|
2311
2643
|
children
|
|
2312
2644
|
]
|
|
2313
2645
|
}
|
|
@@ -2315,8 +2647,9 @@ function Badge({
|
|
|
2315
2647
|
}
|
|
2316
2648
|
|
|
2317
2649
|
// src/components/Card/Card.tsx
|
|
2318
|
-
import {
|
|
2319
|
-
import {
|
|
2650
|
+
import { useCallback as useCallback5 } from "react";
|
|
2651
|
+
import { twMerge as twMerge11 } from "tailwind-merge";
|
|
2652
|
+
import { Fragment as Fragment10, jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2320
2653
|
var paddingStyles = {
|
|
2321
2654
|
none: "p-0",
|
|
2322
2655
|
sm: "p-3",
|
|
@@ -2329,32 +2662,42 @@ function Card({
|
|
|
2329
2662
|
footer,
|
|
2330
2663
|
padding = "md",
|
|
2331
2664
|
href,
|
|
2665
|
+
onPress,
|
|
2332
2666
|
interactive = false,
|
|
2333
2667
|
className
|
|
2334
2668
|
}) {
|
|
2335
|
-
const isInteractive = interactive || !!href;
|
|
2336
|
-
const containerClass =
|
|
2669
|
+
const isInteractive = interactive || !!href || !!onPress;
|
|
2670
|
+
const containerClass = twMerge11(
|
|
2337
2671
|
"bg-[var(--color-surface-default)] border border-[var(--color-border-default)] rounded-[var(--border-radius-lg)] overflow-hidden shadow-sm",
|
|
2338
|
-
isInteractive && "transition-
|
|
2339
|
-
href && "block focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
|
|
2672
|
+
isInteractive && "transition-all hover:shadow-md hover:border-[var(--color-border-focus)] cursor-pointer",
|
|
2673
|
+
(href || onPress) && "block focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
|
|
2340
2674
|
className
|
|
2341
2675
|
);
|
|
2342
|
-
const
|
|
2343
|
-
|
|
2676
|
+
const handleKeyDown = useCallback5(
|
|
2677
|
+
(e) => {
|
|
2678
|
+
if (onPress && (e.key === "Enter" || e.key === " ")) {
|
|
2679
|
+
e.preventDefault();
|
|
2680
|
+
onPress();
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
2683
|
+
[onPress]
|
|
2684
|
+
);
|
|
2685
|
+
const content = /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
2686
|
+
header && /* @__PURE__ */ jsx35(
|
|
2344
2687
|
"div",
|
|
2345
2688
|
{
|
|
2346
|
-
className:
|
|
2689
|
+
className: twMerge11(
|
|
2347
2690
|
"border-b border-[var(--color-border-default)]",
|
|
2348
2691
|
paddingStyles[padding]
|
|
2349
2692
|
),
|
|
2350
2693
|
children: header
|
|
2351
2694
|
}
|
|
2352
2695
|
),
|
|
2353
|
-
/* @__PURE__ */
|
|
2354
|
-
footer && /* @__PURE__ */
|
|
2696
|
+
/* @__PURE__ */ jsx35("div", { className: paddingStyles[padding], children }),
|
|
2697
|
+
footer && /* @__PURE__ */ jsx35(
|
|
2355
2698
|
"div",
|
|
2356
2699
|
{
|
|
2357
|
-
className:
|
|
2700
|
+
className: twMerge11(
|
|
2358
2701
|
"border-t border-[var(--color-border-default)]",
|
|
2359
2702
|
paddingStyles[padding]
|
|
2360
2703
|
),
|
|
@@ -2363,15 +2706,28 @@ function Card({
|
|
|
2363
2706
|
)
|
|
2364
2707
|
] });
|
|
2365
2708
|
if (href) {
|
|
2366
|
-
return /* @__PURE__ */
|
|
2709
|
+
return /* @__PURE__ */ jsx35("a", { href, className: containerClass, children: content });
|
|
2367
2710
|
}
|
|
2368
|
-
|
|
2711
|
+
if (onPress) {
|
|
2712
|
+
return /* @__PURE__ */ jsx35(
|
|
2713
|
+
"div",
|
|
2714
|
+
{
|
|
2715
|
+
role: "button",
|
|
2716
|
+
tabIndex: 0,
|
|
2717
|
+
className: containerClass,
|
|
2718
|
+
onClick: onPress,
|
|
2719
|
+
onKeyDown: handleKeyDown,
|
|
2720
|
+
children: content
|
|
2721
|
+
}
|
|
2722
|
+
);
|
|
2723
|
+
}
|
|
2724
|
+
return /* @__PURE__ */ jsx35("div", { className: containerClass, children: content });
|
|
2369
2725
|
}
|
|
2370
2726
|
|
|
2371
2727
|
// src/components/DeltaIndicator/DeltaIndicator.tsx
|
|
2372
2728
|
import { ArrowUp, ArrowDown, Minus } from "lucide-react";
|
|
2373
|
-
import { twMerge as
|
|
2374
|
-
import { jsx as
|
|
2729
|
+
import { twMerge as twMerge12 } from "tailwind-merge";
|
|
2730
|
+
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2375
2731
|
function getDirection(current, previous) {
|
|
2376
2732
|
const diff = current - previous;
|
|
2377
2733
|
if (diff > 0) return "increase";
|
|
@@ -2424,16 +2780,16 @@ function DeltaIndicator({
|
|
|
2424
2780
|
className
|
|
2425
2781
|
}) {
|
|
2426
2782
|
if (unavailable) {
|
|
2427
|
-
return /* @__PURE__ */
|
|
2783
|
+
return /* @__PURE__ */ jsxs25(
|
|
2428
2784
|
"span",
|
|
2429
2785
|
{
|
|
2430
|
-
className:
|
|
2786
|
+
className: twMerge12(
|
|
2431
2787
|
"inline-flex items-center gap-1 font-[number:var(--font-weight-medium)]",
|
|
2432
2788
|
"text-[var(--color-text-tertiary)]",
|
|
2433
2789
|
className
|
|
2434
2790
|
),
|
|
2435
2791
|
children: [
|
|
2436
|
-
label && /* @__PURE__ */
|
|
2792
|
+
label && /* @__PURE__ */ jsx36("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
|
|
2437
2793
|
unavailableText
|
|
2438
2794
|
]
|
|
2439
2795
|
}
|
|
@@ -2441,7 +2797,7 @@ function DeltaIndicator({
|
|
|
2441
2797
|
}
|
|
2442
2798
|
const diff = current - previous;
|
|
2443
2799
|
const direction = getDirection(current, previous);
|
|
2444
|
-
const
|
|
2800
|
+
const colorStyles2 = reverseColor ? reverseDirectionColors[direction] : directionColors[direction];
|
|
2445
2801
|
const IconComponent = directionIcons[direction];
|
|
2446
2802
|
const isNew = previous === 0 && current > 0;
|
|
2447
2803
|
let valueText;
|
|
@@ -2463,12 +2819,12 @@ function DeltaIndicator({
|
|
|
2463
2819
|
}
|
|
2464
2820
|
}
|
|
2465
2821
|
const isPill = mode === "pill";
|
|
2466
|
-
return /* @__PURE__ */
|
|
2822
|
+
return /* @__PURE__ */ jsxs25(
|
|
2467
2823
|
"span",
|
|
2468
2824
|
{
|
|
2469
|
-
className:
|
|
2825
|
+
className: twMerge12(
|
|
2470
2826
|
"inline-flex items-center gap-1 font-[number:var(--font-weight-medium)]",
|
|
2471
|
-
|
|
2827
|
+
colorStyles2,
|
|
2472
2828
|
isPill && [
|
|
2473
2829
|
"rounded-[var(--border-radius-full)] px-2 py-0.5",
|
|
2474
2830
|
"text-[length:var(--font-size-xs)]",
|
|
@@ -2477,8 +2833,8 @@ function DeltaIndicator({
|
|
|
2477
2833
|
className
|
|
2478
2834
|
),
|
|
2479
2835
|
children: [
|
|
2480
|
-
label && /* @__PURE__ */
|
|
2481
|
-
/* @__PURE__ */
|
|
2836
|
+
label && /* @__PURE__ */ jsx36("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
|
|
2837
|
+
/* @__PURE__ */ jsx36(IconComponent, { size: 14, "aria-hidden": true }),
|
|
2482
2838
|
valueText
|
|
2483
2839
|
]
|
|
2484
2840
|
}
|
|
@@ -2486,8 +2842,8 @@ function DeltaIndicator({
|
|
|
2486
2842
|
}
|
|
2487
2843
|
|
|
2488
2844
|
// src/components/ProgressBar/ProgressBar.tsx
|
|
2489
|
-
import { twMerge as
|
|
2490
|
-
import { jsx as
|
|
2845
|
+
import { twMerge as twMerge13 } from "tailwind-merge";
|
|
2846
|
+
import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2491
2847
|
var fillStyles = {
|
|
2492
2848
|
brand: "bg-[var(--color-progress-fill)]",
|
|
2493
2849
|
success: "bg-[var(--color-progress-fill-success)]",
|
|
@@ -2510,12 +2866,12 @@ function ProgressBar({
|
|
|
2510
2866
|
className
|
|
2511
2867
|
}) {
|
|
2512
2868
|
const clampedValue = Math.min(100, Math.max(0, value));
|
|
2513
|
-
return /* @__PURE__ */
|
|
2514
|
-
(label || description || showValue) && /* @__PURE__ */
|
|
2515
|
-
/* @__PURE__ */
|
|
2516
|
-
/* @__PURE__ */
|
|
2869
|
+
return /* @__PURE__ */ jsxs26("div", { className: twMerge13("w-full", className), children: [
|
|
2870
|
+
(label || description || showValue) && /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between mb-2", children: [
|
|
2871
|
+
/* @__PURE__ */ jsx37("span", { className: "text-[length:var(--font-size-sm)] font-[number:var(--font-weight-medium)] text-[var(--color-text-primary)]", children: label }),
|
|
2872
|
+
/* @__PURE__ */ jsx37("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)]", children: description ?? (showValue ? `${clampedValue}%` : null) })
|
|
2517
2873
|
] }),
|
|
2518
|
-
/* @__PURE__ */
|
|
2874
|
+
/* @__PURE__ */ jsx37(
|
|
2519
2875
|
"div",
|
|
2520
2876
|
{
|
|
2521
2877
|
role: "progressbar",
|
|
@@ -2523,14 +2879,14 @@ function ProgressBar({
|
|
|
2523
2879
|
"aria-valuemin": 0,
|
|
2524
2880
|
"aria-valuemax": 100,
|
|
2525
2881
|
"aria-label": label ?? "Progress",
|
|
2526
|
-
className:
|
|
2882
|
+
className: twMerge13(
|
|
2527
2883
|
"w-full rounded-[var(--border-radius-full)] bg-[var(--color-progress-track)]",
|
|
2528
2884
|
sizeStyles8[size]
|
|
2529
2885
|
),
|
|
2530
|
-
children: /* @__PURE__ */
|
|
2886
|
+
children: /* @__PURE__ */ jsx37(
|
|
2531
2887
|
"div",
|
|
2532
2888
|
{
|
|
2533
|
-
className:
|
|
2889
|
+
className: twMerge13(
|
|
2534
2890
|
"h-full rounded-[var(--border-radius-full)] transition-all duration-300",
|
|
2535
2891
|
fillStyles[variant]
|
|
2536
2892
|
),
|
|
@@ -2545,17 +2901,17 @@ function ProgressBar({
|
|
|
2545
2901
|
// src/components/Banner/Banner.tsx
|
|
2546
2902
|
import { useState as useState3 } from "react";
|
|
2547
2903
|
import {
|
|
2548
|
-
Info as
|
|
2904
|
+
Info as Info4,
|
|
2549
2905
|
AlertTriangle,
|
|
2550
2906
|
AlertCircle as AlertCircle2,
|
|
2551
2907
|
CheckCircle2,
|
|
2552
2908
|
X as X3
|
|
2553
2909
|
} from "lucide-react";
|
|
2554
|
-
import { twMerge as
|
|
2555
|
-
import { jsx as
|
|
2910
|
+
import { twMerge as twMerge14 } from "tailwind-merge";
|
|
2911
|
+
import { jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2556
2912
|
var variantConfig2 = {
|
|
2557
2913
|
info: {
|
|
2558
|
-
icon:
|
|
2914
|
+
icon: Info4,
|
|
2559
2915
|
containerClass: "bg-[var(--color-banner-info-bg)] border-[var(--color-banner-info-border)] text-[var(--color-banner-info-text)]",
|
|
2560
2916
|
iconClass: "text-[var(--color-banner-info-icon)]",
|
|
2561
2917
|
role: "status"
|
|
@@ -2596,40 +2952,40 @@ function Banner({
|
|
|
2596
2952
|
setDismissed(true);
|
|
2597
2953
|
onDismiss?.();
|
|
2598
2954
|
};
|
|
2599
|
-
return /* @__PURE__ */
|
|
2955
|
+
return /* @__PURE__ */ jsxs27(
|
|
2600
2956
|
"div",
|
|
2601
2957
|
{
|
|
2602
2958
|
role: config.role,
|
|
2603
|
-
className:
|
|
2959
|
+
className: twMerge14(
|
|
2604
2960
|
"flex items-start gap-[var(--spacing-3)] rounded-[var(--border-radius-lg)] border px-[var(--spacing-4)] py-[var(--spacing-3)]",
|
|
2605
2961
|
"text-[length:var(--font-size-sm)]",
|
|
2606
2962
|
config.containerClass,
|
|
2607
2963
|
className
|
|
2608
2964
|
),
|
|
2609
2965
|
children: [
|
|
2610
|
-
/* @__PURE__ */
|
|
2966
|
+
/* @__PURE__ */ jsx38(
|
|
2611
2967
|
IconComponent,
|
|
2612
2968
|
{
|
|
2613
2969
|
size: 20,
|
|
2614
|
-
className:
|
|
2970
|
+
className: twMerge14("shrink-0 mt-0.5", config.iconClass),
|
|
2615
2971
|
"aria-hidden": "true"
|
|
2616
2972
|
}
|
|
2617
2973
|
),
|
|
2618
|
-
/* @__PURE__ */
|
|
2619
|
-
title && /* @__PURE__ */
|
|
2974
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex-1", children: [
|
|
2975
|
+
title && /* @__PURE__ */ jsxs27("span", { className: "font-[number:var(--font-weight-medium)]", children: [
|
|
2620
2976
|
title,
|
|
2621
2977
|
" \u2014 "
|
|
2622
2978
|
] }),
|
|
2623
2979
|
children
|
|
2624
2980
|
] }),
|
|
2625
|
-
dismissible && /* @__PURE__ */
|
|
2981
|
+
dismissible && /* @__PURE__ */ jsx38(
|
|
2626
2982
|
"button",
|
|
2627
2983
|
{
|
|
2628
2984
|
type: "button",
|
|
2629
2985
|
onClick: handleDismiss,
|
|
2630
2986
|
className: "shrink-0 rounded-[var(--border-radius-sm)] p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
|
|
2631
2987
|
"aria-label": "Dismiss",
|
|
2632
|
-
children: /* @__PURE__ */
|
|
2988
|
+
children: /* @__PURE__ */ jsx38(X3, { size: 16, "aria-hidden": "true" })
|
|
2633
2989
|
}
|
|
2634
2990
|
)
|
|
2635
2991
|
]
|
|
@@ -2638,8 +2994,8 @@ function Banner({
|
|
|
2638
2994
|
}
|
|
2639
2995
|
|
|
2640
2996
|
// src/components/MetricCard/MetricCard.tsx
|
|
2641
|
-
import { twMerge as
|
|
2642
|
-
import { Fragment as
|
|
2997
|
+
import { twMerge as twMerge15 } from "tailwind-merge";
|
|
2998
|
+
import { Fragment as Fragment11, jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2643
2999
|
var sizeConfig = {
|
|
2644
3000
|
sm: {
|
|
2645
3001
|
padding: "p-3",
|
|
@@ -2661,30 +3017,209 @@ function MetricCard({
|
|
|
2661
3017
|
className
|
|
2662
3018
|
}) {
|
|
2663
3019
|
const config = sizeConfig[size];
|
|
2664
|
-
const containerClass =
|
|
3020
|
+
const containerClass = twMerge15(
|
|
2665
3021
|
"bg-[var(--color-surface-default)] border border-[var(--color-border-default)] rounded-[var(--border-radius-lg)] shadow-sm",
|
|
2666
3022
|
config.padding,
|
|
2667
3023
|
href && "block transition-shadow hover:shadow-md hover:border-[var(--color-border-focus)] focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
|
|
2668
3024
|
className
|
|
2669
3025
|
);
|
|
2670
|
-
const content = /* @__PURE__ */
|
|
2671
|
-
/* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
3026
|
+
const content = /* @__PURE__ */ jsxs28(Fragment11, { children: [
|
|
3027
|
+
/* @__PURE__ */ jsx39("div", { className: twMerge15(config.labelClass, "text-[var(--color-text-secondary)]"), children: label }),
|
|
3028
|
+
/* @__PURE__ */ jsx39(
|
|
2673
3029
|
"div",
|
|
2674
3030
|
{
|
|
2675
|
-
className:
|
|
3031
|
+
className: twMerge15(
|
|
2676
3032
|
config.valueClass,
|
|
2677
3033
|
"font-[number:var(--font-weight-semibold)] text-[var(--color-text-primary)] mt-1 tabular-nums"
|
|
2678
3034
|
),
|
|
2679
3035
|
children: value
|
|
2680
3036
|
}
|
|
2681
3037
|
),
|
|
2682
|
-
secondary && /* @__PURE__ */
|
|
3038
|
+
secondary && /* @__PURE__ */ jsx39("div", { className: "mt-1 text-sm", children: secondary })
|
|
2683
3039
|
] });
|
|
2684
3040
|
if (href) {
|
|
2685
|
-
return /* @__PURE__ */
|
|
3041
|
+
return /* @__PURE__ */ jsx39("a", { href, className: containerClass, children: content });
|
|
2686
3042
|
}
|
|
2687
|
-
return /* @__PURE__ */
|
|
3043
|
+
return /* @__PURE__ */ jsx39("div", { className: containerClass, children: content });
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
// src/components/SectionHeader/SectionHeader.tsx
|
|
3047
|
+
import { twMerge as twMerge16 } from "tailwind-merge";
|
|
3048
|
+
import { jsx as jsx40, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
3049
|
+
function SectionHeader({
|
|
3050
|
+
title,
|
|
3051
|
+
children,
|
|
3052
|
+
className
|
|
3053
|
+
}) {
|
|
3054
|
+
return /* @__PURE__ */ jsxs29(
|
|
3055
|
+
"div",
|
|
3056
|
+
{
|
|
3057
|
+
className: twMerge16(
|
|
3058
|
+
"flex flex-wrap items-center gap-[var(--spacing-3)] py-[var(--spacing-4)]",
|
|
3059
|
+
className
|
|
3060
|
+
),
|
|
3061
|
+
children: [
|
|
3062
|
+
/* @__PURE__ */ jsx40(H2, { children: title }),
|
|
3063
|
+
children && /* @__PURE__ */ jsx40("div", { className: "ml-auto flex flex-wrap items-center gap-[var(--spacing-2)]", children })
|
|
3064
|
+
]
|
|
3065
|
+
}
|
|
3066
|
+
);
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
// src/components/FormWizard/FormWizard.tsx
|
|
3070
|
+
import { createContext as createContext5, useContext as useContext5, useCallback as useCallback6, useMemo } from "react";
|
|
3071
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
3072
|
+
var FormWizardContext = createContext5({
|
|
3073
|
+
currentStep: 0,
|
|
3074
|
+
totalSteps: 1,
|
|
3075
|
+
canGoBack: false,
|
|
3076
|
+
goBack: () => {
|
|
3077
|
+
},
|
|
3078
|
+
isLastStep: true
|
|
3079
|
+
});
|
|
3080
|
+
function useFormWizard() {
|
|
3081
|
+
return useContext5(FormWizardContext);
|
|
3082
|
+
}
|
|
3083
|
+
function FormWizard({
|
|
3084
|
+
currentStep,
|
|
3085
|
+
totalSteps,
|
|
3086
|
+
onStepChange,
|
|
3087
|
+
children
|
|
3088
|
+
}) {
|
|
3089
|
+
const canGoBack = currentStep > 0;
|
|
3090
|
+
const isLastStep = currentStep >= totalSteps - 1;
|
|
3091
|
+
const goBack = useCallback6(() => {
|
|
3092
|
+
if (currentStep > 0) {
|
|
3093
|
+
onStepChange(currentStep - 1);
|
|
3094
|
+
}
|
|
3095
|
+
}, [currentStep, onStepChange]);
|
|
3096
|
+
const value = useMemo(
|
|
3097
|
+
() => ({
|
|
3098
|
+
currentStep,
|
|
3099
|
+
totalSteps,
|
|
3100
|
+
canGoBack,
|
|
3101
|
+
goBack,
|
|
3102
|
+
isLastStep
|
|
3103
|
+
}),
|
|
3104
|
+
[currentStep, totalSteps, canGoBack, goBack, isLastStep]
|
|
3105
|
+
);
|
|
3106
|
+
return /* @__PURE__ */ jsx41(FormWizardContext.Provider, { value, children });
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
// src/components/FormWizard/FormWizardProgress.tsx
|
|
3110
|
+
import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
3111
|
+
function CheckIcon2() {
|
|
3112
|
+
return /* @__PURE__ */ jsx42(
|
|
3113
|
+
"svg",
|
|
3114
|
+
{
|
|
3115
|
+
"aria-hidden": "true",
|
|
3116
|
+
className: "h-4 w-4 text-[var(--color-text-inverse)]",
|
|
3117
|
+
viewBox: "0 0 16 16",
|
|
3118
|
+
fill: "none",
|
|
3119
|
+
stroke: "currentColor",
|
|
3120
|
+
strokeWidth: "2",
|
|
3121
|
+
strokeLinecap: "round",
|
|
3122
|
+
strokeLinejoin: "round",
|
|
3123
|
+
children: /* @__PURE__ */ jsx42("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
|
|
3124
|
+
}
|
|
3125
|
+
);
|
|
3126
|
+
}
|
|
3127
|
+
function FormWizardProgress({ labels }) {
|
|
3128
|
+
const { currentStep, totalSteps } = useFormWizard();
|
|
3129
|
+
return /* @__PURE__ */ jsx42("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx42("ol", { className: "flex items-start", role: "list", children: labels.map((label, index) => {
|
|
3130
|
+
const isCompleted = index < currentStep;
|
|
3131
|
+
const isCurrent = index === currentStep;
|
|
3132
|
+
const isFuture = index > currentStep;
|
|
3133
|
+
return /* @__PURE__ */ jsxs30(
|
|
3134
|
+
"li",
|
|
3135
|
+
{
|
|
3136
|
+
className: "flex flex-1 flex-col items-center",
|
|
3137
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
3138
|
+
children: [
|
|
3139
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex w-full items-center", children: [
|
|
3140
|
+
index > 0 ? /* @__PURE__ */ jsx42(
|
|
3141
|
+
"div",
|
|
3142
|
+
{
|
|
3143
|
+
"aria-hidden": "true",
|
|
3144
|
+
className: [
|
|
3145
|
+
"h-0.5 flex-1",
|
|
3146
|
+
index <= currentStep ? "bg-[var(--color-brand-primary)]" : "bg-[var(--color-border-default)]"
|
|
3147
|
+
].join(" ")
|
|
3148
|
+
}
|
|
3149
|
+
) : /* @__PURE__ */ jsx42("div", { className: "flex-1", "aria-hidden": "true" }),
|
|
3150
|
+
/* @__PURE__ */ jsx42(
|
|
3151
|
+
"div",
|
|
3152
|
+
{
|
|
3153
|
+
className: [
|
|
3154
|
+
"flex h-8 w-8 shrink-0 items-center justify-center rounded-full",
|
|
3155
|
+
"text-[length:var(--font-size-sm)] font-[number:var(--font-weight-medium)]",
|
|
3156
|
+
"transition-colors",
|
|
3157
|
+
isCompleted ? "bg-[var(--color-brand-primary)] text-[var(--color-text-inverse)]" : "",
|
|
3158
|
+
isCurrent ? "border-2 border-[var(--color-brand-primary)] bg-[var(--color-surface-default)] text-[var(--color-brand-primary)]" : "",
|
|
3159
|
+
isFuture ? "border-2 border-[var(--color-border-default)] bg-[var(--color-surface-default)] text-[var(--color-text-tertiary)]" : ""
|
|
3160
|
+
].join(" "),
|
|
3161
|
+
"aria-hidden": "true",
|
|
3162
|
+
children: isCompleted ? /* @__PURE__ */ jsx42(CheckIcon2, {}) : index + 1
|
|
3163
|
+
}
|
|
3164
|
+
),
|
|
3165
|
+
index < totalSteps - 1 ? /* @__PURE__ */ jsx42(
|
|
3166
|
+
"div",
|
|
3167
|
+
{
|
|
3168
|
+
"aria-hidden": "true",
|
|
3169
|
+
className: [
|
|
3170
|
+
"h-0.5 flex-1",
|
|
3171
|
+
index < currentStep ? "bg-[var(--color-brand-primary)]" : "bg-[var(--color-border-default)]"
|
|
3172
|
+
].join(" ")
|
|
3173
|
+
}
|
|
3174
|
+
) : /* @__PURE__ */ jsx42("div", { className: "flex-1", "aria-hidden": "true" })
|
|
3175
|
+
] }),
|
|
3176
|
+
/* @__PURE__ */ jsx42(
|
|
3177
|
+
"span",
|
|
3178
|
+
{
|
|
3179
|
+
className: [
|
|
3180
|
+
"mt-[var(--spacing-2)] text-center text-[length:var(--font-size-sm)]",
|
|
3181
|
+
isCurrent ? "font-[number:var(--font-weight-semibold)] text-[var(--color-text-primary)]" : "font-[number:var(--font-weight-regular)] text-[var(--color-text-secondary)]"
|
|
3182
|
+
].join(" "),
|
|
3183
|
+
children: label
|
|
3184
|
+
}
|
|
3185
|
+
)
|
|
3186
|
+
]
|
|
3187
|
+
},
|
|
3188
|
+
label
|
|
3189
|
+
);
|
|
3190
|
+
}) }) });
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
// src/components/FormWizard/FormWizardNav.tsx
|
|
3194
|
+
import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3195
|
+
function FormWizardNav({
|
|
3196
|
+
onNext,
|
|
3197
|
+
isSubmitting = false,
|
|
3198
|
+
submitLabel = "Submit"
|
|
3199
|
+
}) {
|
|
3200
|
+
const { canGoBack, goBack, isLastStep } = useFormWizard();
|
|
3201
|
+
return /* @__PURE__ */ jsxs31("div", { className: "flex items-center justify-end gap-[var(--spacing-3)]", children: [
|
|
3202
|
+
canGoBack && /* @__PURE__ */ jsx43(
|
|
3203
|
+
Button,
|
|
3204
|
+
{
|
|
3205
|
+
variant: "secondary",
|
|
3206
|
+
size: "lg",
|
|
3207
|
+
onPress: goBack,
|
|
3208
|
+
isDisabled: isSubmitting,
|
|
3209
|
+
children: "Back"
|
|
3210
|
+
}
|
|
3211
|
+
),
|
|
3212
|
+
/* @__PURE__ */ jsx43(
|
|
3213
|
+
Button,
|
|
3214
|
+
{
|
|
3215
|
+
variant: "primary",
|
|
3216
|
+
size: "lg",
|
|
3217
|
+
onPress: onNext,
|
|
3218
|
+
isLoading: isSubmitting,
|
|
3219
|
+
children: isLastStep ? submitLabel : "Next"
|
|
3220
|
+
}
|
|
3221
|
+
)
|
|
3222
|
+
] });
|
|
2688
3223
|
}
|
|
2689
3224
|
|
|
2690
3225
|
// src/tokens/tokens.ts
|
|
@@ -3081,6 +3616,8 @@ export {
|
|
|
3081
3616
|
EmptyState,
|
|
3082
3617
|
Field,
|
|
3083
3618
|
Fieldset,
|
|
3619
|
+
FileCard,
|
|
3620
|
+
FileIcon,
|
|
3084
3621
|
FontSize2xl,
|
|
3085
3622
|
FontSize3xl,
|
|
3086
3623
|
FontSize4xl,
|
|
@@ -3096,6 +3633,10 @@ export {
|
|
|
3096
3633
|
FontWeightMedium,
|
|
3097
3634
|
FontWeightRegular,
|
|
3098
3635
|
FontWeightSemibold,
|
|
3636
|
+
FormWizard,
|
|
3637
|
+
FormWizardNav,
|
|
3638
|
+
FormWizardProgress,
|
|
3639
|
+
GroupPill,
|
|
3099
3640
|
H1,
|
|
3100
3641
|
H2,
|
|
3101
3642
|
H3,
|
|
@@ -3114,6 +3655,7 @@ export {
|
|
|
3114
3655
|
Link,
|
|
3115
3656
|
Menu,
|
|
3116
3657
|
MetricCard,
|
|
3658
|
+
Pill,
|
|
3117
3659
|
Popover3 as Popover,
|
|
3118
3660
|
PopoverContent,
|
|
3119
3661
|
PopoverTrigger,
|
|
@@ -3123,6 +3665,7 @@ export {
|
|
|
3123
3665
|
RadioGroup,
|
|
3124
3666
|
RouterProvider,
|
|
3125
3667
|
Row,
|
|
3668
|
+
SectionHeader,
|
|
3126
3669
|
SegmentedControl,
|
|
3127
3670
|
SegmentedControlItem,
|
|
3128
3671
|
Select,
|
|
@@ -3153,6 +3696,10 @@ export {
|
|
|
3153
3696
|
TabPanel2 as UnstyledTabPanel,
|
|
3154
3697
|
Tabs2 as UnstyledTabs,
|
|
3155
3698
|
createToastBridge,
|
|
3699
|
+
getFileIcon,
|
|
3700
|
+
getTypeLabel,
|
|
3701
|
+
pillColorFromName,
|
|
3702
|
+
useFormWizard,
|
|
3156
3703
|
useInputGroup,
|
|
3157
3704
|
useToast
|
|
3158
3705
|
};
|