@astralform/ui 0.0.0-stage → 0.3.6
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/DESIGN.md +243 -0
- package/LICENSE +21 -0
- package/README.md +128 -2
- package/dist/components/Alert.d.ts +7 -0
- package/dist/components/Alert.js +40 -0
- package/dist/components/Alert.js.map +1 -0
- package/dist/components/AvatarEditor.d.ts +13 -0
- package/dist/components/AvatarEditor.js +44 -0
- package/dist/components/AvatarEditor.js.map +1 -0
- package/dist/components/Badge.d.ts +16 -0
- package/dist/components/Badge.js +38 -0
- package/dist/components/Badge.js.map +1 -0
- package/dist/components/Button.d.ts +8 -0
- package/dist/components/Button.js +21 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/Card.d.ts +10 -0
- package/dist/components/Card.js +22 -0
- package/dist/components/Card.js.map +1 -0
- package/dist/components/CompactResourceRow.d.ts +34 -0
- package/dist/components/CompactResourceRow.js +11 -0
- package/dist/components/CompactResourceRow.js.map +1 -0
- package/dist/components/ConfirmDialog.d.ts +12 -0
- package/dist/components/ConfirmDialog.js +7 -0
- package/dist/components/ConfirmDialog.js.map +1 -0
- package/dist/components/CookieConsent.d.ts +1 -0
- package/dist/components/CookieConsent.js +42 -0
- package/dist/components/CookieConsent.js.map +1 -0
- package/dist/components/DataTable.d.ts +53 -0
- package/dist/components/DataTable.js +79 -0
- package/dist/components/DataTable.js.map +1 -0
- package/dist/components/DevTools.d.ts +6 -0
- package/dist/components/DevTools.js +59 -0
- package/dist/components/DevTools.js.map +1 -0
- package/dist/components/EmptyState.d.ts +11 -0
- package/dist/components/EmptyState.js +6 -0
- package/dist/components/EmptyState.js.map +1 -0
- package/dist/components/ImageCropModal.d.ts +18 -0
- package/dist/components/ImageCropModal.js +67 -0
- package/dist/components/ImageCropModal.js.map +1 -0
- package/dist/components/InlineBanner.d.ts +20 -0
- package/dist/components/InlineBanner.js +53 -0
- package/dist/components/InlineBanner.js.map +1 -0
- package/dist/components/Input.d.ts +8 -0
- package/dist/components/Input.js +10 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/InventoryCard.d.ts +20 -0
- package/dist/components/InventoryCard.js +22 -0
- package/dist/components/InventoryCard.js.map +1 -0
- package/dist/components/LoadingSpinner.d.ts +26 -0
- package/dist/components/LoadingSpinner.js +32 -0
- package/dist/components/LoadingSpinner.js.map +1 -0
- package/dist/components/Modal.d.ts +10 -0
- package/dist/components/Modal.js +38 -0
- package/dist/components/Modal.js.map +1 -0
- package/dist/components/PageHeader.d.ts +11 -0
- package/dist/components/PageHeader.js +5 -0
- package/dist/components/PageHeader.js.map +1 -0
- package/dist/components/PreviewModal.d.ts +24 -0
- package/dist/components/PreviewModal.js +69 -0
- package/dist/components/PreviewModal.js.map +1 -0
- package/dist/components/ProgressBar.d.ts +8 -0
- package/dist/components/ProgressBar.js +12 -0
- package/dist/components/ProgressBar.js.map +1 -0
- package/dist/components/ProviderIcon.d.ts +7 -0
- package/dist/components/ProviderIcon.js +34 -0
- package/dist/components/ProviderIcon.js.map +1 -0
- package/dist/components/ResizeHandle.d.ts +56 -0
- package/dist/components/ResizeHandle.js +166 -0
- package/dist/components/ResizeHandle.js.map +1 -0
- package/dist/components/SegmentedProgressBar.d.ts +9 -0
- package/dist/components/SegmentedProgressBar.js +23 -0
- package/dist/components/SegmentedProgressBar.js.map +1 -0
- package/dist/components/Select.d.ts +13 -0
- package/dist/components/Select.js +14 -0
- package/dist/components/Select.js.map +1 -0
- package/dist/components/SpotlightButton.d.ts +10 -0
- package/dist/components/SpotlightButton.js +51 -0
- package/dist/components/SpotlightButton.js.map +1 -0
- package/dist/components/StatCard.d.ts +9 -0
- package/dist/components/StatCard.js +8 -0
- package/dist/components/StatCard.js.map +1 -0
- package/dist/components/StatusBadge.d.ts +4 -0
- package/dist/components/StatusBadge.js +10 -0
- package/dist/components/StatusBadge.js.map +1 -0
- package/dist/components/TabNav.d.ts +39 -0
- package/dist/components/TabNav.js +25 -0
- package/dist/components/TabNav.js.map +1 -0
- package/dist/components/TableShell.d.ts +21 -0
- package/dist/components/TableShell.js +19 -0
- package/dist/components/TableShell.js.map +1 -0
- package/dist/components/Textarea.d.ts +7 -0
- package/dist/components/Textarea.js +10 -0
- package/dist/components/Textarea.js.map +1 -0
- package/dist/components/Toggle.d.ts +16 -0
- package/dist/components/Toggle.js +25 -0
- package/dist/components/Toggle.js.map +1 -0
- package/dist/components/Toolbar.d.ts +34 -0
- package/dist/components/Toolbar.js +30 -0
- package/dist/components/Toolbar.js.map +1 -0
- package/dist/components/TypeToConfirmModal.d.ts +15 -0
- package/dist/components/TypeToConfirmModal.js +14 -0
- package/dist/components/TypeToConfirmModal.js.map +1 -0
- package/dist/components/UnsavedChangesModal.d.ts +7 -0
- package/dist/components/UnsavedChangesModal.js +7 -0
- package/dist/components/UnsavedChangesModal.js.map +1 -0
- package/dist/components/UsageCard.d.ts +11 -0
- package/dist/components/UsageCard.js +9 -0
- package/dist/components/UsageCard.js.map +1 -0
- package/dist/components/avatar.d.ts +79 -0
- package/dist/components/avatar.js +88 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge-config.d.ts +16 -0
- package/dist/components/badge-config.js +48 -0
- package/dist/components/badge-config.js.map +1 -0
- package/dist/components/glowing-effect.d.ts +14 -0
- package/dist/components/glowing-effect.js +108 -0
- package/dist/components/glowing-effect.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cookies.d.ts +36 -0
- package/dist/lib/cookies.js +78 -0
- package/dist/lib/cookies.js.map +1 -0
- package/dist/lib/environment.d.ts +24 -0
- package/dist/lib/environment.js +52 -0
- package/dist/lib/environment.js.map +1 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +8 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +89 -4
- package/src/styles/base.css +779 -0
- package/src/styles/fonts.css +25 -0
- package/src/styles/theme-default.css +164 -0
- package/src/styles/tokens/_foundations.css +28 -0
- package/src/styles/tokens/_semantics.css +72 -0
- package/themes/chat.DESIGN.md +197 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/components/Card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAMlC,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAC5B,CAAC,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IACzD,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,EAAE;QACR,EAAE,EAAE,KAAK;QACT,EAAE,EAAE,KAAK;QACT,EAAE,EAAE,KAAK;KACV,CAAC;IAEF,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CACX,mGAAmG,EACnG,QAAQ,CAAC,OAAO,CAAC,EACjB,SAAS,CACV,KACG,KAAK,YAER,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;AAE1B,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAGlC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,cACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CAAC,2BAA2B,EAAE,SAAS,CAAC,KACjD,KAAK,GACT,CACH,CAAC,CAAC;AAEH,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC;AAEtC,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAGjC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAC5C,aAAI,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,KAAM,KAAK,YACjE,QAAQ,GACN,CACN,CAAC,CAAC;AAEH,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAGvC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,YACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAC,CAAC;AAEH,eAAe,CAAC,WAAW,GAAG,iBAAiB,CAAC;AAEhD,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAGnC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAClC,cAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAC/D,CAAC,CAAC;AAEH,WAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Icon } from "@phosphor-icons/react";
|
|
3
|
+
interface CompactResourceRowProps {
|
|
4
|
+
/** URL for icon image */
|
|
5
|
+
iconUrl?: string | null;
|
|
6
|
+
/** Phosphor fallback when no URL is set */
|
|
7
|
+
fallbackIcon: Icon;
|
|
8
|
+
/** Primary label */
|
|
9
|
+
title: string;
|
|
10
|
+
/** Secondary text below title */
|
|
11
|
+
description?: string;
|
|
12
|
+
/** Extra content after title (badges, etc.) */
|
|
13
|
+
badges?: ReactNode;
|
|
14
|
+
/** Extra content below description */
|
|
15
|
+
meta?: ReactNode;
|
|
16
|
+
/** Refresh button */
|
|
17
|
+
onRefresh?: () => void;
|
|
18
|
+
/** Spin animation on refresh icon */
|
|
19
|
+
isRefreshing?: boolean;
|
|
20
|
+
/** Edit button */
|
|
21
|
+
onEdit?: () => void;
|
|
22
|
+
/** Switch component */
|
|
23
|
+
onToggle?: () => void;
|
|
24
|
+
/** Toggle checked state */
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
/** Toggle disabled + opacity */
|
|
27
|
+
isToggling?: boolean;
|
|
28
|
+
/** Delete button */
|
|
29
|
+
onDelete?: () => void;
|
|
30
|
+
/** Show lock icon instead of toggle */
|
|
31
|
+
locked?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function CompactResourceRow({ iconUrl, fallbackIcon: FallbackIcon, title, description, badges, meta, onRefresh, isRefreshing, onEdit, onToggle, enabled, isToggling, onDelete, locked, }: CompactResourceRowProps): import("react").JSX.Element;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import {} from "react";
|
|
3
|
+
import { ArrowsClockwiseIcon, LockSimpleIcon, NotePencilIcon, TrashIcon, } from "@phosphor-icons/react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
import { Toggle } from "./Toggle";
|
|
6
|
+
import { Avatar, iconFallback } from "./avatar";
|
|
7
|
+
export function CompactResourceRow({ iconUrl, fallbackIcon: FallbackIcon, title, description, badges, meta, onRefresh, isRefreshing, onEdit, onToggle, enabled, isToggling, onDelete, locked, }) {
|
|
8
|
+
const hasActions = onRefresh || onEdit || onToggle || onDelete || locked;
|
|
9
|
+
return (_jsxs("div", { className: "flex items-center justify-between p-3 rounded-lg border bg-surface-secondary border-border-secondary", children: [_jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [_jsx(Avatar, { src: iconUrl, size: "md", rounded: "rounded-lg", fallback: iconFallback(FallbackIcon, "accent") }), _jsxs("div", { className: "min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("span", { className: "text-sm font-medium text-text-primary", children: title }), badges] }), description && (_jsx("p", { className: "text-xs text-text-tertiary mt-0.5 truncate max-w-sm", children: description })), meta] })] }), hasActions && (_jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [onRefresh && (_jsx("button", { type: "button", onClick: onRefresh, disabled: isRefreshing, className: "p-2 rounded-md text-text-tertiary hover:text-accent hover:bg-surface-tertiary transition-colors cursor-pointer", "aria-label": `Refresh ${title}`, title: "Refresh", children: _jsx(ArrowsClockwiseIcon, { size: 16, className: cn(isRefreshing && "animate-spin") }) })), onEdit && (_jsx("button", { type: "button", onClick: onEdit, className: "p-2 rounded-md text-text-tertiary hover:text-accent hover:bg-surface-tertiary transition-colors cursor-pointer", "aria-label": `Edit ${title}`, title: "Edit", children: _jsx(NotePencilIcon, { size: 16 }) })), locked ? (_jsx("div", { className: "flex items-center justify-center h-6 w-11", children: _jsx(LockSimpleIcon, { size: 16, className: "text-text-muted" }) })) : (onToggle && (_jsx(Toggle, { checked: !!enabled, onChange: () => onToggle(), disabled: isToggling, label: `${enabled ? "Disable" : "Enable"} ${title}` }))), onDelete && (_jsx("button", { type: "button", onClick: onDelete, className: "p-2 rounded-md text-text-tertiary hover:text-danger hover:bg-surface-tertiary transition-colors cursor-pointer", "aria-label": `Delete ${title}`, title: "Delete", children: _jsx(TrashIcon, { size: 16 }) }))] }))] }));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=CompactResourceRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactResourceRow.js","sourceRoot":"","sources":["../../src/components/CompactResourceRow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,SAAS,GACV,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAkChD,MAAM,UAAU,kBAAkB,CAAC,EACjC,OAAO,EACP,YAAY,EAAE,YAAY,EAC1B,KAAK,EACL,WAAW,EACX,MAAM,EACN,IAAI,EACJ,SAAS,EACT,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,QAAQ,EACR,MAAM,GACkB;IACxB,MAAM,UAAU,GAAG,SAAS,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,IAAI,MAAM,CAAC;IAEzE,OAAO,CACL,eAAK,SAAS,EAAC,sGAAsG,aAEnH,eAAK,SAAS,EAAC,iCAAiC,aAC9C,KAAC,MAAM,IACL,GAAG,EAAE,OAAO,EACZ,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,YAAY,EACpB,QAAQ,EAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,GAC9C,EAGF,eAAK,SAAS,EAAC,SAAS,aACtB,eAAK,SAAS,EAAC,mCAAmC,aAChD,eAAM,SAAS,EAAC,uCAAuC,YACpD,KAAK,GACD,EACN,MAAM,IACH,EACL,WAAW,IAAI,CACd,YAAG,SAAS,EAAC,qDAAqD,YAC/D,WAAW,GACV,CACL,EACA,IAAI,IACD,IACF,EAGL,UAAU,IAAI,CACb,eAAK,SAAS,EAAC,yCAAyC,aACrD,SAAS,IAAI,CACZ,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAC,gHAAgH,gBAC9G,WAAW,KAAK,EAAE,EAC9B,KAAK,EAAC,SAAS,YAEf,KAAC,mBAAmB,IAClB,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,EAAE,CAAC,YAAY,IAAI,cAAc,CAAC,GAC7C,GACK,CACV,EAEA,MAAM,IAAI,CACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,SAAS,EAAC,gHAAgH,gBAC9G,QAAQ,KAAK,EAAE,EAC3B,KAAK,EAAC,MAAM,YAEZ,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,GAAI,GACrB,CACV,EAEA,MAAM,CAAC,CAAC,CAAC,CACR,cAAK,SAAS,EAAC,2CAA2C,YACxD,KAAC,cAAc,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,iBAAiB,GAAG,GACpD,CACP,CAAC,CAAC,CAAC,CACF,QAAQ,IAAI,CACV,KAAC,MAAM,IACL,OAAO,EAAE,CAAC,CAAC,OAAO,EAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,EAC1B,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,KAAK,EAAE,GACnD,CACH,CACF,EAEA,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,gHAAgH,gBAC9G,UAAU,KAAK,EAAE,EAC7B,KAAK,EAAC,QAAQ,YAEd,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,GAChB,CACV,IACG,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ConfirmDialogProps {
|
|
2
|
+
isOpen: boolean;
|
|
3
|
+
onClose: () => void;
|
|
4
|
+
onConfirm: () => void;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
confirmLabel?: string;
|
|
8
|
+
confirmVariant?: "danger" | "primary";
|
|
9
|
+
isLoading?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function ConfirmDialog({ isOpen, onClose, onConfirm, title, description, confirmLabel, confirmVariant, isLoading, }: ConfirmDialogProps): import("react").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Modal } from "./Modal";
|
|
3
|
+
import { Button } from "./Button";
|
|
4
|
+
export function ConfirmDialog({ isOpen, onClose, onConfirm, title, description, confirmLabel = "Confirm", confirmVariant = "danger", isLoading, }) {
|
|
5
|
+
return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, size: "sm", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "type-card-title", children: title }), _jsx("p", { className: "mt-2 text-sm text-text-tertiary", children: description })] }), _jsxs("div", { className: "flex justify-end gap-3 pt-2", children: [_jsx(Button, { variant: "secondary", size: "sm", onClick: onClose, children: "Cancel" }), _jsx(Button, { variant: confirmVariant, size: "sm", onClick: onConfirm, isLoading: isLoading, children: confirmLabel })] })] }) }));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ConfirmDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../src/components/ConfirmDialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAalC,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,YAAY,GAAG,SAAS,EACxB,cAAc,GAAG,QAAQ,EACzB,SAAS,GACU;IACnB,OAAO,CACL,KAAC,KAAK,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAC,IAAI,YAChD,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,aAAI,SAAS,EAAC,iBAAiB,YAAE,KAAK,GAAM,EAC5C,YAAG,SAAS,EAAC,iCAAiC,YAAE,WAAW,GAAK,IAC5D,EACN,eAAK,SAAS,EAAC,6BAA6B,aAC1C,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,OAAO,uBAE7C,EACT,KAAC,MAAM,IACL,OAAO,EAAE,cAAc,EACvB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,SAAS,YAEnB,YAAY,GACN,IACL,IACF,GACA,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function CookieConsent(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
import { Button } from "./Button";
|
|
5
|
+
import { hasConsentChoice, acceptCookies, rejectCookies, } from "../lib/cookies";
|
|
6
|
+
export function CookieConsent() {
|
|
7
|
+
const [bannerState, setBannerState] = useState("hidden");
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const show = () => {
|
|
10
|
+
if (!hasConsentChoice())
|
|
11
|
+
setBannerState("visible");
|
|
12
|
+
};
|
|
13
|
+
const timer = setTimeout(show, 500);
|
|
14
|
+
window.addEventListener("consentChange", show);
|
|
15
|
+
window.addEventListener("consentSettingsChange", show);
|
|
16
|
+
return () => {
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
window.removeEventListener("consentChange", show);
|
|
19
|
+
window.removeEventListener("consentSettingsChange", show);
|
|
20
|
+
};
|
|
21
|
+
}, []);
|
|
22
|
+
const handleAccept = () => {
|
|
23
|
+
setBannerState("animating-out");
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
acceptCookies();
|
|
26
|
+
setBannerState("hidden");
|
|
27
|
+
}, 300);
|
|
28
|
+
};
|
|
29
|
+
const handleReject = () => {
|
|
30
|
+
setBannerState("animating-out");
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
rejectCookies();
|
|
33
|
+
setBannerState("hidden");
|
|
34
|
+
}, 300);
|
|
35
|
+
};
|
|
36
|
+
if (bannerState === "hidden")
|
|
37
|
+
return null;
|
|
38
|
+
return (_jsx("div", { className: `fixed bottom-0 left-0 right-0 z-40 p-4 transition-all duration-[var(--duration-enter)] ease-out ${bannerState === "animating-out"
|
|
39
|
+
? "translate-y-full opacity-0"
|
|
40
|
+
: "translate-y-0 opacity-100"}`, children: _jsx("div", { className: "mx-auto max-w-4xl", children: _jsxs("div", { className: "relative overflow-hidden rounded-2xl bg-surface-secondary shadow-2xl ring-1 ring-border-secondary", children: [_jsx("div", { className: "absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-text-muted to-transparent" }), _jsx("div", { className: "p-6", children: _jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx("span", { className: "text-xl", children: "\uD83C\uDF6A" }), _jsx("h3", { className: "text-base font-semibold text-text-primary", children: "We value your privacy" })] }), _jsxs("p", { className: "text-sm text-text-tertiary leading-relaxed", children: ["We use cookies to enhance your experience, analyze site traffic, and for marketing purposes. By clicking \"Accept\", you consent to our use of cookies. Read our", " ", _jsx(Link, { to: "/privacy", className: "font-medium text-text-primary hover:text-text-secondary underline underline-offset-2", children: "Privacy Policy" }), " ", "to learn more."] })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center shrink-0", children: [_jsx(Button, { variant: "secondary", onClick: handleReject, children: "Reject All" }), _jsx(Button, { variant: "primary", onClick: handleAccept, children: "Accept All" })] })] }) })] }) }) }));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=CookieConsent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CookieConsent.js","sourceRoot":"","sources":["../../src/components/CookieConsent.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,gBAAgB,CAAC;AAIxB,MAAM,UAAU,aAAa;IAC3B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAc,QAAQ,CAAC,CAAC;IAEtE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,IAAI,CAAC,gBAAgB,EAAE;gBAAE,cAAc,CAAC,SAAS,CAAC,CAAC;QACrD,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,gBAAgB,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;QAEvD,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;YAClD,MAAM,CAAC,mBAAmB,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;QAC5D,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,cAAc,CAAC,eAAe,CAAC,CAAC;QAChC,UAAU,CAAC,GAAG,EAAE;YACd,aAAa,EAAE,CAAC;YAChB,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,GAAG,EAAE;QACxB,cAAc,CAAC,eAAe,CAAC,CAAC;QAChC,UAAU,CAAC,GAAG,EAAE;YACd,aAAa,EAAE,CAAC;YAChB,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC;IAEF,IAAI,WAAW,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE1C,OAAO,CACL,cACE,SAAS,EAAE,mGACT,WAAW,KAAK,eAAe;YAC7B,CAAC,CAAC,4BAA4B;YAC9B,CAAC,CAAC,2BACN,EAAE,YAEF,cAAK,SAAS,EAAC,mBAAmB,YAChC,eAAK,SAAS,EAAC,mGAAmG,aAEhH,cAAK,SAAS,EAAC,+FAA+F,GAAG,EAEjH,cAAK,SAAS,EAAC,KAAK,YAClB,eAAK,SAAS,EAAC,oEAAoE,aACjF,eAAK,SAAS,EAAC,QAAQ,aACrB,eAAK,SAAS,EAAC,8BAA8B,aAC3C,eAAM,SAAS,EAAC,SAAS,6BAAU,EACnC,aAAI,SAAS,EAAC,2CAA2C,sCAEpD,IACD,EACN,aAAG,SAAS,EAAC,4CAA4C,iLAGf,GAAG,EAC3C,KAAC,IAAI,IACH,EAAE,EAAC,UAAU,EACb,SAAS,EAAC,sFAAsF,+BAG3F,EAAC,GAAG,sBAET,IACA,EAEN,eAAK,SAAS,EAAC,0DAA0D,aACvE,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,OAAO,EAAE,YAAY,2BAExC,EACT,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,YAAY,2BAEtC,IACL,IACF,GACF,IACF,GACF,GACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type RowData, type SortingState, type OnChangeFn } from "@tanstack/react-table";
|
|
3
|
+
/** Re-export so consumers don't need to import from @tanstack/react-table directly */
|
|
4
|
+
export type { SortingState } from "@tanstack/react-table";
|
|
5
|
+
declare module "@tanstack/react-table" {
|
|
6
|
+
interface ColumnMeta<TData extends RowData, TValue> {
|
|
7
|
+
className?: string;
|
|
8
|
+
cellClassName?: string;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export interface Column<T> {
|
|
12
|
+
header: string;
|
|
13
|
+
accessor: keyof T | ((row: T) => ReactNode);
|
|
14
|
+
/** Applied to both th and td */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Applied only to td cells (overrides className for cells) */
|
|
17
|
+
cellClassName?: string;
|
|
18
|
+
/** Disable sorting for this column (default: sorting enabled) */
|
|
19
|
+
enableSorting?: boolean;
|
|
20
|
+
/** Column ID for sorting — defaults to accessor key or header slug */
|
|
21
|
+
id?: string;
|
|
22
|
+
}
|
|
23
|
+
interface PaginationState {
|
|
24
|
+
page: number;
|
|
25
|
+
pageSize: number;
|
|
26
|
+
total: number;
|
|
27
|
+
}
|
|
28
|
+
interface DataTableProps<T> {
|
|
29
|
+
columns: Column<T>[];
|
|
30
|
+
data: T[];
|
|
31
|
+
keyExtractor: (row: T) => string;
|
|
32
|
+
emptyState?: ReactNode;
|
|
33
|
+
onRowClick?: (row: T) => void;
|
|
34
|
+
/** Compact mode uses tighter padding */
|
|
35
|
+
compact?: boolean;
|
|
36
|
+
/** Wrap table in a Card (default: true). Ignored when toolbar or pagination is used. */
|
|
37
|
+
wrapInCard?: boolean;
|
|
38
|
+
/** Controlled sorting state (for server-side sorting) */
|
|
39
|
+
sorting?: SortingState;
|
|
40
|
+
/** Controlled sorting handler (for server-side sorting) */
|
|
41
|
+
onSortingChange?: OnChangeFn<SortingState>;
|
|
42
|
+
/** Server-side pagination */
|
|
43
|
+
pagination?: PaginationState;
|
|
44
|
+
onPageChange?: (page: number) => void;
|
|
45
|
+
onPageSizeChange?: (pageSize: number) => void;
|
|
46
|
+
paginationInfo?: ReactNode;
|
|
47
|
+
/** Slot above the table (search, filters, actions) */
|
|
48
|
+
toolbar?: ReactNode;
|
|
49
|
+
/** Disabled state (passed to pagination) */
|
|
50
|
+
disabled?: boolean;
|
|
51
|
+
className?: string;
|
|
52
|
+
}
|
|
53
|
+
export declare function DataTable<T>({ columns, data, keyExtractor, emptyState, onRowClick, compact, wrapInCard, sorting: controlledSorting, onSortingChange: controlledOnSortingChange, pagination, onPageChange, onPageSizeChange, paginationInfo, toolbar, disabled, className, }: DataTableProps<T>): import("react").JSX.Element;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table";
|
|
4
|
+
import { ArrowDownIcon, ArrowUpIcon } from "@phosphor-icons/react";
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
import { Card } from "./Card";
|
|
7
|
+
import { TableShell, TablePagination } from "./TableShell";
|
|
8
|
+
/* ------------------------------------------------------------------ */
|
|
9
|
+
/* Component */
|
|
10
|
+
/* ------------------------------------------------------------------ */
|
|
11
|
+
export function DataTable({ columns, data, keyExtractor, emptyState, onRowClick, compact, wrapInCard = true, sorting: controlledSorting, onSortingChange: controlledOnSortingChange, pagination, onPageChange, onPageSizeChange, paginationInfo, toolbar, disabled, className, }) {
|
|
12
|
+
const hasSorting = !!controlledOnSortingChange;
|
|
13
|
+
const hasShell = !!toolbar || !!pagination;
|
|
14
|
+
// Convert Column<T>[] → TanStack ColumnDef<T>[]
|
|
15
|
+
const tanstackColumns = useMemo(() => columns.map((col) => {
|
|
16
|
+
const colId = col.id ??
|
|
17
|
+
(typeof col.accessor === "string"
|
|
18
|
+
? col.accessor
|
|
19
|
+
: col.header.toLowerCase().replace(/\s+/g, "_"));
|
|
20
|
+
const isFunction = typeof col.accessor === "function";
|
|
21
|
+
const accessor = col.accessor;
|
|
22
|
+
return {
|
|
23
|
+
id: colId,
|
|
24
|
+
accessorFn: isFunction
|
|
25
|
+
? (row) => row[colId]
|
|
26
|
+
: (row) => row[accessor],
|
|
27
|
+
header: col.header,
|
|
28
|
+
enableSorting: col.enableSorting ?? hasSorting,
|
|
29
|
+
meta: {
|
|
30
|
+
className: col.className,
|
|
31
|
+
cellClassName: col.cellClassName,
|
|
32
|
+
},
|
|
33
|
+
cell: isFunction
|
|
34
|
+
? ({ row }) => accessor(row.original)
|
|
35
|
+
: ({ getValue }) => getValue(),
|
|
36
|
+
};
|
|
37
|
+
}), [columns]);
|
|
38
|
+
const table = useReactTable({
|
|
39
|
+
data,
|
|
40
|
+
columns: tanstackColumns,
|
|
41
|
+
getRowId: (row) => keyExtractor(row),
|
|
42
|
+
state: { sorting: controlledSorting ?? [] },
|
|
43
|
+
onSortingChange: controlledOnSortingChange,
|
|
44
|
+
getCoreRowModel: getCoreRowModel(),
|
|
45
|
+
manualSorting: true,
|
|
46
|
+
manualPagination: true,
|
|
47
|
+
});
|
|
48
|
+
const hPad = compact ? "px-4 py-3" : "px-6 py-3";
|
|
49
|
+
const cPad = compact ? "px-4 py-3" : "px-6 py-4";
|
|
50
|
+
// Empty state — render before table when no shell
|
|
51
|
+
if (data.length === 0 && emptyState && !hasShell) {
|
|
52
|
+
return _jsx(_Fragment, { children: emptyState });
|
|
53
|
+
}
|
|
54
|
+
const tableEl = (_jsxs("table", { className: "min-w-full divide-y divide-border-primary", children: [_jsx("thead", { className: hasShell ? "bg-surface-secondary" : "bg-transparent", children: table.getHeaderGroups().map((headerGroup) => (_jsx("tr", { className: hasShell ? "" : "border-b border-border-primary", children: headerGroup.headers.map((header) => {
|
|
55
|
+
const canSort = header.column.getCanSort();
|
|
56
|
+
const sorted = header.column.getIsSorted();
|
|
57
|
+
const meta = header.column.columnDef.meta;
|
|
58
|
+
return (_jsx("th", { className: cn(hPad, "text-left text-xs font-medium text-text-tertiary", !hasShell && "uppercase tracking-wider", canSort &&
|
|
59
|
+
"cursor-pointer select-none transition-colors hover:text-text-secondary", meta?.className), onClick: canSort
|
|
60
|
+
? header.column.getToggleSortingHandler()
|
|
61
|
+
: undefined, children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [header.isPlaceholder
|
|
62
|
+
? null
|
|
63
|
+
: flexRender(header.column.columnDef.header, header.getContext()), canSort ? (sorted === "asc" ? (_jsx(ArrowUpIcon, { size: 12, className: "text-text-secondary" })) : sorted === "desc" ? (_jsx(ArrowDownIcon, { size: 12, className: "text-text-secondary" })) : (_jsx(ArrowDownIcon, { size: 12, className: "opacity-0" }))) : null] }) }, header.id));
|
|
64
|
+
}) }, headerGroup.id))) }), _jsx("tbody", { className: "divide-y divide-border-primary", children: table.getRowModel().rows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: tanstackColumns.length, className: "px-4 py-16 text-center", children: emptyState ?? (_jsx("p", { className: "text-sm text-text-disabled", children: "No data" })) }) })) : (table.getRowModel().rows.map((row) => (_jsx("tr", { className: onRowClick ? "cursor-pointer" : "", onClick: () => onRowClick?.(row.original), children: row.getVisibleCells().map((cell) => {
|
|
65
|
+
const meta = cell.column.columnDef.meta;
|
|
66
|
+
return (_jsx("td", { className: cn(cPad, "whitespace-nowrap text-sm align-top", meta?.cellClassName ?? meta?.className), children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
|
|
67
|
+
}) }, row.id)))) })] }));
|
|
68
|
+
// Advanced mode: use TableShell with toolbar/pagination
|
|
69
|
+
if (hasShell) {
|
|
70
|
+
const footer = pagination && onPageChange && onPageSizeChange ? (_jsx(TablePagination, { page: pagination.page, pageSize: pagination.pageSize, total: pagination.total, onPageChange: onPageChange, onPageSizeChange: onPageSizeChange, info: paginationInfo, disabled: disabled })) : null;
|
|
71
|
+
return (_jsx(TableShell, { toolbar: toolbar, footer: footer, className: className, children: tableEl }));
|
|
72
|
+
}
|
|
73
|
+
// Simple mode: optional Card wrap
|
|
74
|
+
if (wrapInCard) {
|
|
75
|
+
return (_jsx(Card, { padding: "none", className: className, children: _jsx("div", { className: "overflow-x-auto", children: tableEl }) }));
|
|
76
|
+
}
|
|
77
|
+
return _jsx("div", { className: cn("overflow-x-auto", className), children: tableEl });
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=DataTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../src/components/DataTable.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev Tools floating panel - only visible in non-production environments.
|
|
3
|
+
* Provides tools for developers like production UI preview toggle.
|
|
4
|
+
* Extensible design for adding more dev tools in the future.
|
|
5
|
+
*/
|
|
6
|
+
export declare function DevTools(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { getActualEnvironment, isPreviewModeEnabled, setPreviewMode, } from "../lib/environment";
|
|
4
|
+
import { isDevIgnoreConsentEnabled, setDevIgnoreConsent, resetConsent, } from "../lib/cookies";
|
|
5
|
+
import { WrenchIcon } from "@phosphor-icons/react";
|
|
6
|
+
/**
|
|
7
|
+
* Dev Tools floating panel - only visible in non-production environments.
|
|
8
|
+
* Provides tools for developers like production UI preview toggle.
|
|
9
|
+
* Extensible design for adding more dev tools in the future.
|
|
10
|
+
*/
|
|
11
|
+
export function DevTools() {
|
|
12
|
+
const actualEnv = getActualEnvironment();
|
|
13
|
+
const [previewMode, setPreviewModeState] = useState(isPreviewModeEnabled);
|
|
14
|
+
const [ignoreConsent, setIgnoreConsentState] = useState(isDevIgnoreConsentEnabled);
|
|
15
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
16
|
+
// Listen for preview mode changes from other components
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const handleChange = (e) => {
|
|
19
|
+
setPreviewModeState(e.detail);
|
|
20
|
+
};
|
|
21
|
+
window.addEventListener("previewModeChange", handleChange);
|
|
22
|
+
return () => {
|
|
23
|
+
window.removeEventListener("previewModeChange", handleChange);
|
|
24
|
+
};
|
|
25
|
+
}, []);
|
|
26
|
+
// Hide in actual production
|
|
27
|
+
if (actualEnv === "production") {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const handlePreviewToggle = (newValue) => {
|
|
31
|
+
setPreviewModeState(newValue);
|
|
32
|
+
setPreviewMode(newValue);
|
|
33
|
+
// Delay reload to show toggle animation
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
window.location.reload();
|
|
36
|
+
}, 250);
|
|
37
|
+
};
|
|
38
|
+
const handleIgnoreConsentToggle = (newValue) => {
|
|
39
|
+
setIgnoreConsentState(newValue);
|
|
40
|
+
setDevIgnoreConsent(newValue);
|
|
41
|
+
if (newValue) {
|
|
42
|
+
// Reset consent to show banner
|
|
43
|
+
resetConsent();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const toggleButtonClass = previewMode || ignoreConsent
|
|
47
|
+
? "bg-white text-text-inverse"
|
|
48
|
+
: "bg-surface-secondary text-text-tertiary border border-border-secondary hover:bg-surface-tertiary hover:text-text-primary";
|
|
49
|
+
const switchClass = previewMode ? "bg-white" : "bg-surface-inset";
|
|
50
|
+
const switchKnobClass = previewMode
|
|
51
|
+
? "translate-x-[22px] bg-surface-base"
|
|
52
|
+
: "translate-x-[2px] bg-zinc-400";
|
|
53
|
+
const indicatorClass = previewMode ? "bg-white" : "bg-success-muted";
|
|
54
|
+
const indicatorText = previewMode
|
|
55
|
+
? "Previewing Production"
|
|
56
|
+
: "Local Development";
|
|
57
|
+
return (_jsxs(_Fragment, { children: [isExpanded && (_jsxs("div", { className: "fixed bottom-16 right-4 z-50 bg-surface-secondary rounded-xl shadow-lg border border-border-secondary overflow-hidden", children: [_jsx("div", { className: "px-4 py-2.5 bg-surface-tertiary border-b border-border-secondary", children: _jsx("h3", { className: "text-xs font-semibold text-text-secondary uppercase tracking-wider", children: "Dev Tools" }) }), _jsxs("div", { className: "p-4 space-y-4 min-w-[220px]", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-xs font-medium text-text-tertiary", children: "Production Preview" }), _jsx("button", { role: "switch", "aria-checked": previewMode, onClick: () => handlePreviewToggle(!previewMode), className: `${switchClass} relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-surface-secondary`, children: _jsx("span", { className: `${switchKnobClass} pointer-events-none inline-block h-5 w-5 rounded-full shadow-md transition-all duration-200 ease-in-out` }) })] }), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("span", { className: "text-xs font-medium text-text-tertiary", children: "Show Cookie Banner" }), _jsx("button", { role: "switch", "aria-checked": ignoreConsent, onClick: () => handleIgnoreConsentToggle(!ignoreConsent), className: `${ignoreConsent ? "bg-white" : "bg-surface-inset"} relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-surface-secondary`, children: _jsx("span", { className: `${ignoreConsent ? "translate-x-[22px] bg-surface-base" : "translate-x-[2px] bg-zinc-400"} pointer-events-none inline-block h-5 w-5 rounded-full shadow-md transition-all duration-200 ease-in-out` }) })] })] }), _jsx("div", { className: "px-4 py-2 bg-surface-tertiary border-t border-border-secondary", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: `h-2 w-2 rounded-full ${indicatorClass}` }), _jsx("span", { className: "text-xs text-text-muted", children: indicatorText })] }) })] })), _jsx("button", { onClick: () => setIsExpanded(!isExpanded), className: `fixed bottom-4 right-4 z-50 flex items-center justify-center h-10 w-10 rounded-full shadow-lg transition-colors duration-200 ${toggleButtonClass}`, title: "Dev Tools", children: _jsx(WrenchIcon, { size: 20 }) })] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=DevTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevTools.js","sourceRoot":"","sources":["../../src/components/DevTools.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { Icon } from "@phosphor-icons/react";
|
|
3
|
+
interface EmptyStateProps {
|
|
4
|
+
icon: Icon;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
action?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function EmptyState({ icon: IconComp, title, description, action, className, }: EmptyStateProps): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Card } from "./Card";
|
|
3
|
+
export function EmptyState({ icon: IconComp, title, description, action, className, }) {
|
|
4
|
+
return (_jsx(Card, { className: className, children: _jsxs("div", { className: "text-center py-12", children: [_jsx(IconComp, { size: 48, className: "mx-auto text-text-disabled" }), _jsx("h3", { className: "mt-2 text-sm font-medium text-text-primary", children: title }), _jsx("p", { className: "mt-1 text-sm text-text-tertiary", children: description }), action && _jsx("div", { className: "mt-6", children: action })] }) }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=EmptyState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../src/components/EmptyState.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAU9B,MAAM,UAAU,UAAU,CAAC,EACzB,IAAI,EAAE,QAAQ,EACd,KAAK,EACL,WAAW,EACX,MAAM,EACN,SAAS,GACO;IAChB,OAAO,CACL,KAAC,IAAI,IAAC,SAAS,EAAE,SAAS,YACxB,eAAK,SAAS,EAAC,mBAAmB,aAChC,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,4BAA4B,GAAG,EAC7D,aAAI,SAAS,EAAC,4CAA4C,YAAE,KAAK,GAAM,EACvE,YAAG,SAAS,EAAC,iCAAiC,YAAE,WAAW,GAAK,EAC/D,MAAM,IAAI,cAAK,SAAS,EAAC,MAAM,YAAE,MAAM,GAAO,IAC3C,GACD,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface ImageCropModalProps {
|
|
2
|
+
/** The source file selected by the user. Pass `null` to hide the modal. */
|
|
3
|
+
file: File | null;
|
|
4
|
+
/** Called with the cropped blob when user confirms. */
|
|
5
|
+
onCrop: (blob: Blob) => void;
|
|
6
|
+
/** Called when the modal is dismissed without cropping. */
|
|
7
|
+
onCancel: () => void;
|
|
8
|
+
/** Crop shape — `"round"` for avatars, `"rect"` for general images. */
|
|
9
|
+
cropShape?: "round" | "rect";
|
|
10
|
+
/** Aspect ratio (width / height). Default `1` (square). */
|
|
11
|
+
aspect?: number;
|
|
12
|
+
/** Output pixel size (both dimensions). Default `256`. */
|
|
13
|
+
outputSize?: number;
|
|
14
|
+
/** Modal title. Default `"Crop Image"`. */
|
|
15
|
+
title?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function ImageCropModal({ file, onCrop, onCancel, cropShape, aspect, outputSize, title, }: ImageCropModalProps): import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useMemo, useEffect } from "react";
|
|
3
|
+
import Cropper from "react-easy-crop";
|
|
4
|
+
import { Modal } from "./Modal";
|
|
5
|
+
import { Button } from "./Button";
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Canvas-based crop utility
|
|
8
|
+
// =============================================================================
|
|
9
|
+
function createImage(url) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const img = new Image();
|
|
12
|
+
img.addEventListener("load", () => resolve(img));
|
|
13
|
+
img.addEventListener("error", (err) => reject(err));
|
|
14
|
+
img.crossOrigin = "anonymous";
|
|
15
|
+
img.src = url;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
async function getCroppedBlob(imageSrc, pixelCrop, outputSize = 256) {
|
|
19
|
+
const image = await createImage(imageSrc);
|
|
20
|
+
const canvas = document.createElement("canvas");
|
|
21
|
+
canvas.width = outputSize;
|
|
22
|
+
canvas.height = outputSize;
|
|
23
|
+
const ctx = canvas.getContext("2d");
|
|
24
|
+
if (!ctx)
|
|
25
|
+
throw new Error("Canvas 2D context unavailable");
|
|
26
|
+
ctx.drawImage(image, pixelCrop.x, pixelCrop.y, pixelCrop.width, pixelCrop.height, 0, 0, outputSize, outputSize);
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
canvas.toBlob((blob) => (blob ? resolve(blob) : reject(new Error("Crop failed"))), "image/webp", 0.85);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function ImageCropModal({ file, onCrop, onCancel, cropShape = "round", aspect = 1, outputSize = 256, title = "Crop Image", }) {
|
|
32
|
+
const [crop, setCrop] = useState({ x: 0, y: 0 });
|
|
33
|
+
const [zoom, setZoom] = useState(1);
|
|
34
|
+
const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);
|
|
35
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
36
|
+
// Stable object URL that gets revoked on file change or unmount
|
|
37
|
+
const imageSrc = useMemo(() => (file ? URL.createObjectURL(file) : ""), [file]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
return () => {
|
|
40
|
+
if (imageSrc)
|
|
41
|
+
URL.revokeObjectURL(imageSrc);
|
|
42
|
+
};
|
|
43
|
+
}, [imageSrc]);
|
|
44
|
+
const onCropComplete = useCallback((_, pixels) => {
|
|
45
|
+
setCroppedAreaPixels(pixels);
|
|
46
|
+
}, []);
|
|
47
|
+
const handleSave = async () => {
|
|
48
|
+
if (!croppedAreaPixels || !imageSrc)
|
|
49
|
+
return;
|
|
50
|
+
setIsSaving(true);
|
|
51
|
+
try {
|
|
52
|
+
const blob = await getCroppedBlob(imageSrc, croppedAreaPixels, outputSize);
|
|
53
|
+
onCrop(blob);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
setIsSaving(false);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const handleClose = () => {
|
|
60
|
+
setCrop({ x: 0, y: 0 });
|
|
61
|
+
setZoom(1);
|
|
62
|
+
setCroppedAreaPixels(null);
|
|
63
|
+
onCancel();
|
|
64
|
+
};
|
|
65
|
+
return (_jsx(Modal, { isOpen: !!file, onClose: handleClose, title: title, size: "md", children: _jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "relative w-full h-64 bg-surface-primary rounded-lg overflow-hidden", children: imageSrc && (_jsx(Cropper, { image: imageSrc, crop: crop, zoom: zoom, aspect: aspect, cropShape: cropShape, showGrid: false, onCropChange: setCrop, onCropComplete: onCropComplete, onZoomChange: setZoom })) }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-xs text-text-muted w-10 shrink-0", children: "Zoom" }), _jsx("input", { type: "range", min: 1, max: 3, step: 0.05, value: zoom, onChange: (e) => setZoom(Number(e.target.value)), className: "flex-1 accent-accent-muted h-1.5 bg-surface-inset rounded-full appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-accent-muted" })] }), _jsxs("div", { className: "flex justify-end gap-3", children: [_jsx(Button, { variant: "secondary", onClick: handleClose, children: "Cancel" }), _jsx(Button, { onClick: handleSave, isLoading: isSaving, children: "Save" })] })] }) }));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ImageCropModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageCropModal.js","sourceRoot":"","sources":["../../src/components/ImageCropModal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
export interface InlineBannerProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
variant?: "success" | "warning" | "error" | "info" | "neutral";
|
|
4
|
+
/** Override the variant's default icon; pass `null` to hide it entirely. */
|
|
5
|
+
icon?: ReactNode | null;
|
|
6
|
+
/** Right-side affordance — a retry button, dismiss control, or link. */
|
|
7
|
+
action?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Compact contextual banner for inline feedback inside content flows (chat
|
|
11
|
+
* message streams, form footers, list rows) — where the page-level `Alert`
|
|
12
|
+
* would shout. Same status token scales as `Alert`, but alpha-stepped down
|
|
13
|
+
* (translucent surface + hairline border) so the banner reads as a tint on
|
|
14
|
+
* the canvas rather than a solid block, in every theme.
|
|
15
|
+
*
|
|
16
|
+
* Token-only: recolors purely from the active theme's `*-surface` / `*-dim` /
|
|
17
|
+
* status hues; `neutral` reuses the surface/border/text tiers for recoverable,
|
|
18
|
+
* not-a-problem notes.
|
|
19
|
+
*/
|
|
20
|
+
export declare const InlineBanner: import("react").ForwardRefExoticComponent<InlineBannerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
import { CheckCircleIcon, InfoIcon, WarningIcon, XCircleIcon, } from "@phosphor-icons/react";
|
|
5
|
+
/**
|
|
6
|
+
* Compact contextual banner for inline feedback inside content flows (chat
|
|
7
|
+
* message streams, form footers, list rows) — where the page-level `Alert`
|
|
8
|
+
* would shout. Same status token scales as `Alert`, but alpha-stepped down
|
|
9
|
+
* (translucent surface + hairline border) so the banner reads as a tint on
|
|
10
|
+
* the canvas rather than a solid block, in every theme.
|
|
11
|
+
*
|
|
12
|
+
* Token-only: recolors purely from the active theme's `*-surface` / `*-dim` /
|
|
13
|
+
* status hues; `neutral` reuses the surface/border/text tiers for recoverable,
|
|
14
|
+
* not-a-problem notes.
|
|
15
|
+
*/
|
|
16
|
+
export const InlineBanner = forwardRef(({ className, variant = "info", icon, action, children, ...props }, ref) => {
|
|
17
|
+
const variants = {
|
|
18
|
+
success: {
|
|
19
|
+
container: "bg-success-surface/40 border-success-dim/40",
|
|
20
|
+
text: "text-success",
|
|
21
|
+
Icon: CheckCircleIcon,
|
|
22
|
+
},
|
|
23
|
+
warning: {
|
|
24
|
+
container: "bg-warning-surface/40 border-warning-dim/40",
|
|
25
|
+
text: "text-warning",
|
|
26
|
+
Icon: WarningIcon,
|
|
27
|
+
},
|
|
28
|
+
error: {
|
|
29
|
+
container: "bg-danger-surface/40 border-danger-dim/40",
|
|
30
|
+
text: "text-danger",
|
|
31
|
+
Icon: XCircleIcon,
|
|
32
|
+
},
|
|
33
|
+
info: {
|
|
34
|
+
container: "bg-info-surface/40 border-info-dim/40",
|
|
35
|
+
text: "text-info",
|
|
36
|
+
Icon: InfoIcon,
|
|
37
|
+
},
|
|
38
|
+
neutral: {
|
|
39
|
+
container: "bg-surface-secondary/40 border-border-primary",
|
|
40
|
+
text: "text-text-tertiary",
|
|
41
|
+
Icon: InfoIcon,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const { container, text, Icon } = variants[variant];
|
|
45
|
+
const resolvedIcon = icon === undefined ? (_jsx(Icon, { size: 14, weight: "fill", "aria-hidden": "true" })) : (icon);
|
|
46
|
+
return (_jsxs("div", { ref: ref, role: variant === "error"
|
|
47
|
+
? "alert"
|
|
48
|
+
: variant === "warning" || variant === "success"
|
|
49
|
+
? "status"
|
|
50
|
+
: undefined, className: cn("flex items-start gap-2 rounded-alert border px-3 py-2.5", container, className), ...props, children: [resolvedIcon && (_jsx("span", { className: cn("mt-0.5 shrink-0", text), children: resolvedIcon })), _jsx("div", { className: cn("min-w-0 flex-1 text-xs leading-5", text), children: children }), action && _jsx("div", { className: "ml-2 shrink-0", children: action })] }));
|
|
51
|
+
});
|
|
52
|
+
InlineBanner.displayName = "InlineBanner";
|
|
53
|
+
//# sourceMappingURL=InlineBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineBanner.js","sourceRoot":"","sources":["../../src/components/InlineBanner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EACL,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAU/B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CACpC,CACE,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EACjE,GAAG,EACH,EAAE;IACF,MAAM,QAAQ,GAAG;QACf,OAAO,EAAE;YACP,SAAS,EAAE,6CAA6C;YACxD,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,eAAe;SACtB;QACD,OAAO,EAAE;YACP,SAAS,EAAE,6CAA6C;YACxD,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,WAAW;SAClB;QACD,KAAK,EAAE;YACL,SAAS,EAAE,2CAA2C;YACtD,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,WAAW;SAClB;QACD,IAAI,EAAE;YACJ,SAAS,EAAE,uCAAuC;YAClD,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;SACf;QACD,OAAO,EAAE;YACP,SAAS,EAAE,+CAA+C;YAC1D,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,QAAQ;SACf;KACF,CAAC;IAEF,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,YAAY,GAChB,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACnB,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,MAAM,EAAC,MAAM,iBAAa,MAAM,GAAG,CACpD,CAAC,CAAC,CAAC,CACF,IAAI,CACL,CAAC;IAEJ,OAAO,CACL,eACE,GAAG,EAAE,GAAG,EACR,IAAI,EACF,OAAO,KAAK,OAAO;YACjB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;gBAC9C,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,SAAS,EAEjB,SAAS,EAAE,EAAE,CACX,yDAAyD,EACzD,SAAS,EACT,SAAS,CACV,KACG,KAAK,aAER,YAAY,IAAI,CACf,eAAM,SAAS,EAAE,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,YAAG,YAAY,GAAQ,CACpE,EACD,cAAK,SAAS,EAAE,EAAE,CAAC,kCAAkC,EAAE,IAAI,CAAC,YACzD,QAAQ,GACL,EACL,MAAM,IAAI,cAAK,SAAS,EAAC,eAAe,YAAE,MAAM,GAAO,IACpD,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,YAAY,CAAC,WAAW,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
3
|
+
label?: ReactNode;
|
|
4
|
+
error?: string;
|
|
5
|
+
hint?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
export const Input = forwardRef(({ className, label, error, hint, id, ...props }, ref) => {
|
|
5
|
+
return (_jsxs("div", { className: "w-full", children: [label && (_jsx("label", { htmlFor: id, className: "block type-label mb-1", children: label })), _jsx("input", { ref: ref, id: id, className: cn("block w-full rounded-input border px-3 py-2 text-sm text-text-primary bg-surface-secondary shadow-[var(--shadow-input)]", "placeholder:text-text-muted", "focus:outline-none focus:ring-2 focus:ring-white/30 focus:border-border-focus", error
|
|
6
|
+
? "border-danger-muted focus:ring-danger-muted/30 focus:border-danger-muted"
|
|
7
|
+
: "border-border-secondary", className), ...props }), error && _jsx("p", { className: "mt-1 text-sm text-status-error", children: error }), hint && !error && (_jsx("p", { className: "mt-1 text-xs text-text-muted", children: hint }))] }));
|
|
8
|
+
});
|
|
9
|
+
Input.displayName = "Input";
|
|
10
|
+
//# sourceMappingURL=Input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/components/Input.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAC7B,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE;IACvD,OAAO,CACL,eAAK,SAAS,EAAC,QAAQ,aACpB,KAAK,IAAI,CACR,gBAAO,OAAO,EAAE,EAAE,EAAE,SAAS,EAAC,uBAAuB,YAClD,KAAK,GACA,CACT,EACD,gBACE,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,EAAE,CACX,yHAAyH,EACzH,6BAA6B,EAC7B,+EAA+E,EAC/E,KAAK;oBACH,CAAC,CAAC,0EAA0E;oBAC5E,CAAC,CAAC,yBAAyB,EAC7B,SAAS,CACV,KACG,KAAK,GACT,EACD,KAAK,IAAI,YAAG,SAAS,EAAC,gCAAgC,YAAE,KAAK,GAAK,EAClE,IAAI,IAAI,CAAC,KAAK,IAAI,CACjB,YAAG,SAAS,EAAC,8BAA8B,YAAE,IAAI,GAAK,CACvD,IACG,CACP,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC"}
|