@astralform/ui 0.0.0-stage → 0.3.7-next.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.
Files changed (140) hide show
  1. package/DESIGN.md +243 -0
  2. package/LICENSE +21 -0
  3. package/README.md +128 -2
  4. package/dist/components/Alert.d.ts +7 -0
  5. package/dist/components/Alert.js +40 -0
  6. package/dist/components/Alert.js.map +1 -0
  7. package/dist/components/AvatarEditor.d.ts +13 -0
  8. package/dist/components/AvatarEditor.js +44 -0
  9. package/dist/components/AvatarEditor.js.map +1 -0
  10. package/dist/components/Badge.d.ts +16 -0
  11. package/dist/components/Badge.js +38 -0
  12. package/dist/components/Badge.js.map +1 -0
  13. package/dist/components/Button.d.ts +8 -0
  14. package/dist/components/Button.js +21 -0
  15. package/dist/components/Button.js.map +1 -0
  16. package/dist/components/Card.d.ts +10 -0
  17. package/dist/components/Card.js +22 -0
  18. package/dist/components/Card.js.map +1 -0
  19. package/dist/components/CompactResourceRow.d.ts +34 -0
  20. package/dist/components/CompactResourceRow.js +11 -0
  21. package/dist/components/CompactResourceRow.js.map +1 -0
  22. package/dist/components/ConfirmDialog.d.ts +12 -0
  23. package/dist/components/ConfirmDialog.js +7 -0
  24. package/dist/components/ConfirmDialog.js.map +1 -0
  25. package/dist/components/CookieConsent.d.ts +1 -0
  26. package/dist/components/CookieConsent.js +42 -0
  27. package/dist/components/CookieConsent.js.map +1 -0
  28. package/dist/components/DataTable.d.ts +53 -0
  29. package/dist/components/DataTable.js +79 -0
  30. package/dist/components/DataTable.js.map +1 -0
  31. package/dist/components/DevTools.d.ts +6 -0
  32. package/dist/components/DevTools.js +59 -0
  33. package/dist/components/DevTools.js.map +1 -0
  34. package/dist/components/EmptyState.d.ts +11 -0
  35. package/dist/components/EmptyState.js +6 -0
  36. package/dist/components/EmptyState.js.map +1 -0
  37. package/dist/components/ImageCropModal.d.ts +18 -0
  38. package/dist/components/ImageCropModal.js +67 -0
  39. package/dist/components/ImageCropModal.js.map +1 -0
  40. package/dist/components/InlineBanner.d.ts +20 -0
  41. package/dist/components/InlineBanner.js +53 -0
  42. package/dist/components/InlineBanner.js.map +1 -0
  43. package/dist/components/Input.d.ts +8 -0
  44. package/dist/components/Input.js +10 -0
  45. package/dist/components/Input.js.map +1 -0
  46. package/dist/components/InventoryCard.d.ts +20 -0
  47. package/dist/components/InventoryCard.js +22 -0
  48. package/dist/components/InventoryCard.js.map +1 -0
  49. package/dist/components/LoadingSpinner.d.ts +26 -0
  50. package/dist/components/LoadingSpinner.js +32 -0
  51. package/dist/components/LoadingSpinner.js.map +1 -0
  52. package/dist/components/Modal.d.ts +10 -0
  53. package/dist/components/Modal.js +38 -0
  54. package/dist/components/Modal.js.map +1 -0
  55. package/dist/components/PageHeader.d.ts +11 -0
  56. package/dist/components/PageHeader.js +5 -0
  57. package/dist/components/PageHeader.js.map +1 -0
  58. package/dist/components/PreviewModal.d.ts +24 -0
  59. package/dist/components/PreviewModal.js +69 -0
  60. package/dist/components/PreviewModal.js.map +1 -0
  61. package/dist/components/ProgressBar.d.ts +8 -0
  62. package/dist/components/ProgressBar.js +12 -0
  63. package/dist/components/ProgressBar.js.map +1 -0
  64. package/dist/components/ProviderIcon.d.ts +7 -0
  65. package/dist/components/ProviderIcon.js +34 -0
  66. package/dist/components/ProviderIcon.js.map +1 -0
  67. package/dist/components/ResizeHandle.d.ts +56 -0
  68. package/dist/components/ResizeHandle.js +166 -0
  69. package/dist/components/ResizeHandle.js.map +1 -0
  70. package/dist/components/SegmentedProgressBar.d.ts +9 -0
  71. package/dist/components/SegmentedProgressBar.js +23 -0
  72. package/dist/components/SegmentedProgressBar.js.map +1 -0
  73. package/dist/components/Select.d.ts +13 -0
  74. package/dist/components/Select.js +14 -0
  75. package/dist/components/Select.js.map +1 -0
  76. package/dist/components/SpotlightButton.d.ts +10 -0
  77. package/dist/components/SpotlightButton.js +51 -0
  78. package/dist/components/SpotlightButton.js.map +1 -0
  79. package/dist/components/StatCard.d.ts +9 -0
  80. package/dist/components/StatCard.js +8 -0
  81. package/dist/components/StatCard.js.map +1 -0
  82. package/dist/components/StatusBadge.d.ts +4 -0
  83. package/dist/components/StatusBadge.js +10 -0
  84. package/dist/components/StatusBadge.js.map +1 -0
  85. package/dist/components/TabNav.d.ts +39 -0
  86. package/dist/components/TabNav.js +25 -0
  87. package/dist/components/TabNav.js.map +1 -0
  88. package/dist/components/TableShell.d.ts +21 -0
  89. package/dist/components/TableShell.js +19 -0
  90. package/dist/components/TableShell.js.map +1 -0
  91. package/dist/components/Textarea.d.ts +7 -0
  92. package/dist/components/Textarea.js +10 -0
  93. package/dist/components/Textarea.js.map +1 -0
  94. package/dist/components/Toggle.d.ts +16 -0
  95. package/dist/components/Toggle.js +25 -0
  96. package/dist/components/Toggle.js.map +1 -0
  97. package/dist/components/Toolbar.d.ts +34 -0
  98. package/dist/components/Toolbar.js +30 -0
  99. package/dist/components/Toolbar.js.map +1 -0
  100. package/dist/components/TypeToConfirmModal.d.ts +15 -0
  101. package/dist/components/TypeToConfirmModal.js +14 -0
  102. package/dist/components/TypeToConfirmModal.js.map +1 -0
  103. package/dist/components/UnsavedChangesModal.d.ts +7 -0
  104. package/dist/components/UnsavedChangesModal.js +7 -0
  105. package/dist/components/UnsavedChangesModal.js.map +1 -0
  106. package/dist/components/UsageCard.d.ts +11 -0
  107. package/dist/components/UsageCard.js +9 -0
  108. package/dist/components/UsageCard.js.map +1 -0
  109. package/dist/components/avatar.d.ts +79 -0
  110. package/dist/components/avatar.js +88 -0
  111. package/dist/components/avatar.js.map +1 -0
  112. package/dist/components/badge-config.d.ts +16 -0
  113. package/dist/components/badge-config.js +48 -0
  114. package/dist/components/badge-config.js.map +1 -0
  115. package/dist/components/glowing-effect.d.ts +14 -0
  116. package/dist/components/glowing-effect.js +108 -0
  117. package/dist/components/glowing-effect.js.map +1 -0
  118. package/dist/index.d.ts +39 -0
  119. package/dist/index.js +42 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/lib/cookies.d.ts +36 -0
  122. package/dist/lib/cookies.js +78 -0
  123. package/dist/lib/cookies.js.map +1 -0
  124. package/dist/lib/environment.d.ts +24 -0
  125. package/dist/lib/environment.js +52 -0
  126. package/dist/lib/environment.js.map +1 -0
  127. package/dist/lib/utils.d.ts +4 -0
  128. package/dist/lib/utils.js +8 -0
  129. package/dist/lib/utils.js.map +1 -0
  130. package/dist/types.d.ts +12 -0
  131. package/dist/types.js +12 -0
  132. package/dist/types.js.map +1 -0
  133. package/package.json +89 -4
  134. package/src/styles/base.css +779 -0
  135. package/src/styles/fonts.css +25 -0
  136. package/src/styles/theme-default.css +164 -0
  137. package/src/styles/theme-default.generated.css +79 -0
  138. package/src/styles/tokens/_foundations.css +28 -0
  139. package/src/styles/tokens/_semantics.css +72 -0
  140. 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"}