@timbal-ai/timbal-react 1.5.0 → 1.6.1
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/CHANGELOG.md +32 -1
- package/README.md +33 -0
- package/dist/app.cjs +884 -642
- package/dist/app.d.cts +4 -4
- package/dist/app.d.ts +4 -4
- package/dist/app.esm.js +6 -6
- package/dist/{chart-artifact-2OTDTRwM.d.ts → chart-artifact-BYl5C-dk.d.ts} +90 -29
- package/dist/{chart-artifact-CS3qyGIY.d.cts → chart-artifact-Dpt4t5sf.d.cts} +90 -29
- package/dist/{chat-ClmzWzCX.d.cts → chat-DDsp-Vzz.d.cts} +1 -1
- package/dist/{chat-ClmzWzCX.d.ts → chat-DDsp-Vzz.d.ts} +1 -1
- package/dist/chat.cjs +26 -26
- package/dist/chat.d.cts +3 -3
- package/dist/chat.d.ts +3 -3
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-TZI3ID3C.esm.js → chunk-24B4I4XC.esm.js} +3 -3
- package/dist/{chunk-QIABF4KB.esm.js → chunk-ELEY66OH.esm.js} +2 -2
- package/dist/{chunk-WMKPT5BV.esm.js → chunk-HSL36SJ4.esm.js} +6 -6
- package/dist/chunk-JJOO4PR5.esm.js +391 -0
- package/dist/{chunk-AZL2WANO.esm.js → chunk-MBS7XHV2.esm.js} +28 -28
- package/dist/{chunk-5ECRZ5O7.esm.js → chunk-NO5AWNWT.esm.js} +224 -57
- package/dist/{chunk-ZNYAETFD.esm.js → chunk-R4RQT2XQ.esm.js} +2 -2
- package/dist/{chunk-JYDJRGDE.esm.js → chunk-TMP7RIA7.esm.js} +2 -2
- package/dist/{chunk-SZDYIRMB.esm.js → chunk-UVPXH4MB.esm.js} +647 -532
- package/dist/{chunk-IGHBLJV3.esm.js → chunk-WQIQW7EM.esm.js} +3 -2
- package/dist/{chunk-B4XAC4G7.esm.js → chunk-YYEI6XME.esm.js} +361 -527
- package/dist/{circular-progress-CDsJwIPF.d.cts → circular-progress-B9nnwzCu.d.cts} +1 -1
- package/dist/{circular-progress-CDsJwIPF.d.ts → circular-progress-B9nnwzCu.d.ts} +1 -1
- package/dist/cli/timbal-ui-lint.mjs +503 -0
- package/dist/index.cjs +1358 -856
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.esm.js +40 -20
- package/dist/{kanban-U5xNe9py.d.cts → kanban-FFBeaZPS.d.cts} +4 -4
- package/dist/{kanban-U5xNe9py.d.ts → kanban-FFBeaZPS.d.ts} +4 -4
- package/dist/{layout-B8r6Jbat.d.ts → layout-CuKeSY74.d.ts} +1 -1
- package/dist/{layout-Cu7Ijn04.d.cts → layout-PzVwkJyL.d.cts} +1 -1
- package/dist/site.cjs +71 -0
- package/dist/site.d.cts +15 -1
- package/dist/site.d.ts +15 -1
- package/dist/site.esm.js +12 -311
- package/dist/studio.cjs +31 -31
- package/dist/studio.d.cts +2 -2
- package/dist/studio.d.ts +2 -2
- package/dist/studio.esm.js +7 -7
- package/dist/{timbal-v2-button-B7vPs7gg.d.ts → timbal-v2-button-DCAZNyUx.d.cts} +1 -1
- package/dist/{timbal-v2-button-B7vPs7gg.d.cts → timbal-v2-button-DCAZNyUx.d.ts} +1 -1
- package/dist/ui.cjs +77 -77
- package/dist/ui.d.cts +3 -3
- package/dist/ui.d.ts +3 -3
- package/dist/ui.esm.js +15 -15
- package/dist/{welcome-NXZlcihe.d.cts → welcome-B00oH5Io.d.cts} +1 -1
- package/dist/{welcome-DduQAC4K.d.ts → welcome-DU-4NTjZ.d.ts} +1 -1
- package/package.json +13 -3
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ __export(index_exports, {
|
|
|
38
38
|
AccordionContent: () => AccordionContent,
|
|
39
39
|
AccordionItem: () => AccordionItem,
|
|
40
40
|
AccordionTrigger: () => AccordionTrigger,
|
|
41
|
-
ActionBarPrimitive: () =>
|
|
41
|
+
ActionBarPrimitive: () => import_react84.ActionBarPrimitive,
|
|
42
42
|
Alert: () => Alert,
|
|
43
43
|
AlertDescription: () => AlertDescription,
|
|
44
44
|
AlertDialog: () => AlertDialog,
|
|
@@ -63,8 +63,8 @@ __export(index_exports, {
|
|
|
63
63
|
ArtifactRegistryProvider: () => ArtifactRegistryProvider,
|
|
64
64
|
ArtifactView: () => ArtifactView,
|
|
65
65
|
AspectRatio: () => AspectRatio,
|
|
66
|
-
AssistantRuntimeProvider: () =>
|
|
67
|
-
AuiIf: () =>
|
|
66
|
+
AssistantRuntimeProvider: () => import_react84.AssistantRuntimeProvider,
|
|
67
|
+
AuiIf: () => import_react84.AuiIf,
|
|
68
68
|
AuthGuard: () => AuthGuard,
|
|
69
69
|
Avatar: () => Avatar,
|
|
70
70
|
AvatarFallback: () => AvatarFallback,
|
|
@@ -121,7 +121,7 @@ __export(index_exports, {
|
|
|
121
121
|
CommandSeparator: () => CommandSeparator,
|
|
122
122
|
CommandShortcut: () => CommandShortcut,
|
|
123
123
|
Composer: () => Composer,
|
|
124
|
-
ComposerPrimitive: () =>
|
|
124
|
+
ComposerPrimitive: () => import_react84.ComposerPrimitive,
|
|
125
125
|
ConnectionRow: () => ConnectionRow,
|
|
126
126
|
ConnectionRowList: () => ConnectionRowList,
|
|
127
127
|
ContextMenu: () => ContextMenu,
|
|
@@ -140,6 +140,7 @@ __export(index_exports, {
|
|
|
140
140
|
ContextMenuTrigger: () => ContextMenuTrigger,
|
|
141
141
|
CopyButton: () => CopyButton,
|
|
142
142
|
DEFAULT_UPLOAD_ACCEPT: () => DEFAULT_UPLOAD_ACCEPT,
|
|
143
|
+
DURATION: () => DURATION,
|
|
143
144
|
DangerZone: () => DangerZone,
|
|
144
145
|
DangerZoneAction: () => DangerZoneAction,
|
|
145
146
|
DataTable: () => DataTable,
|
|
@@ -173,6 +174,7 @@ __export(index_exports, {
|
|
|
173
174
|
DropdownMenuSubContent: () => DropdownMenuSubContent,
|
|
174
175
|
DropdownMenuSubTrigger: () => DropdownMenuSubTrigger,
|
|
175
176
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
177
|
+
EASE: () => EASE,
|
|
176
178
|
EmptyState: () => EmptyState,
|
|
177
179
|
ExpandableSection: () => ExpandableSection,
|
|
178
180
|
Field: () => Field,
|
|
@@ -218,7 +220,9 @@ __export(index_exports, {
|
|
|
218
220
|
KbdGroup: () => KbdGroup,
|
|
219
221
|
Label: () => Label3,
|
|
220
222
|
LineAreaChart: () => LineAreaChart,
|
|
223
|
+
Magnetic: () => Magnetic,
|
|
221
224
|
MarkdownText: () => MarkdownText,
|
|
225
|
+
Marquee: () => Marquee,
|
|
222
226
|
MemoPillSegmentedTabs: () => MemoPillSegmentedTabs,
|
|
223
227
|
Menubar: () => Menubar,
|
|
224
228
|
MenubarCheckboxItem: () => MenubarCheckboxItem,
|
|
@@ -234,7 +238,7 @@ __export(index_exports, {
|
|
|
234
238
|
MenubarSubContent: () => MenubarSubContent,
|
|
235
239
|
MenubarSubTrigger: () => MenubarSubTrigger,
|
|
236
240
|
MenubarTrigger: () => MenubarTrigger,
|
|
237
|
-
MessagePrimitive: () =>
|
|
241
|
+
MessagePrimitive: () => import_react84.MessagePrimitive,
|
|
238
242
|
MetricChartCard: () => MetricChartCard,
|
|
239
243
|
MetricRow: () => MetricRow,
|
|
240
244
|
MetricTile: () => MetricTile,
|
|
@@ -257,6 +261,7 @@ __export(index_exports, {
|
|
|
257
261
|
PaginationLink: () => PaginationLink,
|
|
258
262
|
PaginationNext: () => PaginationNext,
|
|
259
263
|
PaginationPrevious: () => PaginationPrevious,
|
|
264
|
+
Parallax: () => Parallax,
|
|
260
265
|
PieChart: () => PieChart,
|
|
261
266
|
PillSegmentedTabs: () => PillSegmentedTabs,
|
|
262
267
|
PlanBadge: () => PlanBadge,
|
|
@@ -273,8 +278,11 @@ __export(index_exports, {
|
|
|
273
278
|
RadioGroupItem: () => RadioGroupItem,
|
|
274
279
|
Rating: () => Rating,
|
|
275
280
|
ResourceCard: () => ResourceCard,
|
|
281
|
+
Reveal: () => Reveal,
|
|
276
282
|
SEMANTIC_COLOR_TOKENS: () => SEMANTIC_COLOR_TOKENS,
|
|
283
|
+
SITE_AGENT_INSTRUCTIONS: () => SITE_AGENT_INSTRUCTIONS,
|
|
277
284
|
SLOP_BUDGETS: () => SLOP_BUDGETS,
|
|
285
|
+
SPRING: () => SPRING,
|
|
278
286
|
STUDIO_NAV_MODE: () => STUDIO_NAV_MODE,
|
|
279
287
|
ScrollArea: () => ScrollArea,
|
|
280
288
|
ScrollBar: () => ScrollBar,
|
|
@@ -334,9 +342,10 @@ __export(index_exports, {
|
|
|
334
342
|
TableHeader: () => TableHeader,
|
|
335
343
|
TableRow: () => TableRow,
|
|
336
344
|
TagInput: () => TagInput,
|
|
345
|
+
TextReveal: () => TextReveal,
|
|
337
346
|
Textarea: () => Textarea,
|
|
338
347
|
Thread: () => Thread,
|
|
339
|
-
ThreadPrimitive: () =>
|
|
348
|
+
ThreadPrimitive: () => import_react84.ThreadPrimitive,
|
|
340
349
|
TimbalChat: () => TimbalChat,
|
|
341
350
|
TimbalChatShell: () => TimbalChatShell,
|
|
342
351
|
TimbalMark: () => TimbalMark,
|
|
@@ -435,15 +444,15 @@ __export(index_exports, {
|
|
|
435
444
|
useAppShellChat: () => useAppShellChat,
|
|
436
445
|
useAppShellNav: () => useAppShellNav,
|
|
437
446
|
useArtifactRegistry: () => useArtifactRegistry,
|
|
438
|
-
useComposerRuntime: () =>
|
|
447
|
+
useComposerRuntime: () => import_react84.useComposerRuntime,
|
|
439
448
|
useInterval: () => useInterval,
|
|
440
449
|
useLiveQuery: () => useLiveQuery,
|
|
441
|
-
useMessageRuntime: () =>
|
|
450
|
+
useMessageRuntime: () => import_react84.useMessageRuntime,
|
|
442
451
|
useOptionalSession: () => useOptionalSession,
|
|
443
452
|
useResolvedSuggestions: () => useResolvedSuggestions,
|
|
444
453
|
useSession: () => useSession,
|
|
445
|
-
useThread: () =>
|
|
446
|
-
useThreadRuntime: () =>
|
|
454
|
+
useThread: () => import_react84.useThread,
|
|
455
|
+
useThreadRuntime: () => import_react84.useThreadRuntime,
|
|
447
456
|
useTimbalRuntime: () => useTimbalRuntime,
|
|
448
457
|
useTimbalStream: () => useTimbalStream,
|
|
449
458
|
useToast: () => useToast,
|
|
@@ -1413,22 +1422,22 @@ var TIMBAL_V2_MODAL_SURFACE = cn(
|
|
|
1413
1422
|
);
|
|
1414
1423
|
var TIMBAL_V2_PRIMARY_GRADIENT = "bg-gradient-to-b from-primary-fill-from to-primary-fill-to";
|
|
1415
1424
|
var TIMBAL_V2_SIZE_HEIGHT = {
|
|
1416
|
-
xs: "min-h-
|
|
1417
|
-
sm: "min-h-
|
|
1418
|
-
md: "min-h-
|
|
1419
|
-
lg: "min-h-
|
|
1425
|
+
xs: "min-h-7 h-7",
|
|
1426
|
+
sm: "min-h-8 h-8",
|
|
1427
|
+
md: "min-h-9 h-9",
|
|
1428
|
+
lg: "min-h-10 h-10"
|
|
1420
1429
|
};
|
|
1421
1430
|
var TIMBAL_V2_SIZE_ICON = {
|
|
1422
|
-
xs: "min-h-
|
|
1431
|
+
xs: "min-h-7 min-w-7 size-7",
|
|
1423
1432
|
sm: "min-h-8 min-w-8 size-8",
|
|
1424
|
-
md: "min-h-
|
|
1425
|
-
lg: "min-h-
|
|
1433
|
+
md: "min-h-9 min-w-9 size-9",
|
|
1434
|
+
lg: "min-h-10 min-w-10 size-10"
|
|
1426
1435
|
};
|
|
1427
1436
|
var TIMBAL_V2_SIZE_LABEL_PX = {
|
|
1428
|
-
xs: "px-
|
|
1429
|
-
sm: "px-
|
|
1430
|
-
md: "px-5",
|
|
1431
|
-
lg: "px-
|
|
1437
|
+
xs: "px-2.5",
|
|
1438
|
+
sm: "px-3",
|
|
1439
|
+
md: "px-3.5",
|
|
1440
|
+
lg: "px-4.5"
|
|
1432
1441
|
};
|
|
1433
1442
|
var TIMBAL_V2_FILL = {
|
|
1434
1443
|
primary: [
|
|
@@ -1595,7 +1604,7 @@ function DialogContent({
|
|
|
1595
1604
|
"data-slot": "dialog-content",
|
|
1596
1605
|
className: cn(
|
|
1597
1606
|
TIMBAL_V2_MODAL_SURFACE,
|
|
1598
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[70] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl p-
|
|
1607
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[70] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl p-5 duration-200 outline-none sm:max-w-lg",
|
|
1599
1608
|
className
|
|
1600
1609
|
),
|
|
1601
1610
|
...props,
|
|
@@ -1692,9 +1701,9 @@ function avatarChartVariantClass(_seed) {
|
|
|
1692
1701
|
return AVATAR_PRIMARY_FALLBACK_CLASS;
|
|
1693
1702
|
}
|
|
1694
1703
|
var AVATAR_SIZE_CLASS = {
|
|
1695
|
-
default: "size-
|
|
1696
|
-
sm: "size-
|
|
1697
|
-
lg: "size-
|
|
1704
|
+
default: "size-7",
|
|
1705
|
+
sm: "size-5",
|
|
1706
|
+
lg: "size-9"
|
|
1698
1707
|
};
|
|
1699
1708
|
function Avatar({
|
|
1700
1709
|
className,
|
|
@@ -3875,16 +3884,16 @@ var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
|
3875
3884
|
)
|
|
3876
3885
|
},
|
|
3877
3886
|
size: {
|
|
3878
|
-
xs: "h-
|
|
3879
|
-
sm: "h-
|
|
3880
|
-
md: "h-
|
|
3881
|
-
lg: "h-
|
|
3882
|
-
xl: "h-
|
|
3883
|
-
default: "h-
|
|
3884
|
-
icon: "h-
|
|
3885
|
-
"icon-xs": "h-
|
|
3886
|
-
"icon-sm": "h-
|
|
3887
|
-
"icon-lg": "h-
|
|
3887
|
+
xs: "h-7 gap-1 rounded-md px-2 text-xs",
|
|
3888
|
+
sm: "h-8 gap-1 rounded-md px-2.5 text-xs",
|
|
3889
|
+
md: "h-9 gap-1.5 rounded-lg px-3 text-sm",
|
|
3890
|
+
lg: "h-10 gap-1.5 rounded-lg px-3.5 text-sm",
|
|
3891
|
+
xl: "h-11 gap-2 rounded-lg px-4 text-base",
|
|
3892
|
+
default: "h-9 gap-1.5 rounded-lg px-3 text-sm",
|
|
3893
|
+
icon: "h-9 w-9 rounded-lg",
|
|
3894
|
+
"icon-xs": "h-7 w-7 rounded-md",
|
|
3895
|
+
"icon-sm": "h-8 w-8 rounded-md",
|
|
3896
|
+
"icon-lg": "h-10 w-10 rounded-lg"
|
|
3888
3897
|
},
|
|
3889
3898
|
shape: {
|
|
3890
3899
|
pill: "rounded-full!",
|
|
@@ -4141,7 +4150,7 @@ var BadgeNode = ({ node }) => {
|
|
|
4141
4150
|
"span",
|
|
4142
4151
|
{
|
|
4143
4152
|
className: cn(
|
|
4144
|
-
"aui-ui-badge inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
|
|
4153
|
+
"aui-ui-badge inline-flex w-fit shrink-0 items-center rounded-full px-2 py-0.5 text-xs font-medium",
|
|
4145
4154
|
BADGE_TONE[node.tone ?? "default"],
|
|
4146
4155
|
node.className
|
|
4147
4156
|
),
|
|
@@ -5790,8 +5799,8 @@ var import_lucide_react9 = require("lucide-react");
|
|
|
5790
5799
|
|
|
5791
5800
|
// src/design/control-surface.ts
|
|
5792
5801
|
var CONTROL_SIZE = {
|
|
5793
|
-
sm: "h-
|
|
5794
|
-
default: "h-
|
|
5802
|
+
sm: "h-8 px-2.5",
|
|
5803
|
+
default: "h-9 px-3"
|
|
5795
5804
|
};
|
|
5796
5805
|
var CONTROL_SHAPE = {
|
|
5797
5806
|
field: "rounded-lg",
|
|
@@ -5819,7 +5828,7 @@ var overlayListPanelClass = cn(
|
|
|
5819
5828
|
overlaySurfaceClass,
|
|
5820
5829
|
"overflow-hidden rounded-lg p-0 outline-hidden"
|
|
5821
5830
|
);
|
|
5822
|
-
var overlayItemClass = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1
|
|
5831
|
+
var overlayItemClass = "relative flex cursor-default items-center gap-2 rounded-md px-2 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
|
|
5823
5832
|
|
|
5824
5833
|
// src/chat/workforce-selector.tsx
|
|
5825
5834
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
@@ -5944,8 +5953,8 @@ var SIDEBAR_MOBILE_PX = 272;
|
|
|
5944
5953
|
var SIDEBAR_GAP_PX = 12;
|
|
5945
5954
|
var SIDEBAR_CONTENT_GAP_PX = 8;
|
|
5946
5955
|
var TOPBAR_GAP_PX = 8;
|
|
5947
|
-
var TOPBAR_HEIGHT_PX =
|
|
5948
|
-
var PILL_HEIGHT_PX =
|
|
5956
|
+
var TOPBAR_HEIGHT_PX = 44;
|
|
5957
|
+
var PILL_HEIGHT_PX = 36;
|
|
5949
5958
|
var SIDEBAR_INSET_PX_EXPANDED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
5950
5959
|
var SIDEBAR_INSET_PX_COLLAPSED = SIDEBAR_GAP_PX + SIDEBAR_WIDTH_COLLAPSED_PX + SIDEBAR_CONTENT_GAP_PX;
|
|
5951
5960
|
var px = (n) => `${n / 16}rem`;
|
|
@@ -6526,7 +6535,7 @@ function DropdownMenuCheckboxItem({
|
|
|
6526
6535
|
import_radix_ui6.DropdownMenu.CheckboxItem,
|
|
6527
6536
|
{
|
|
6528
6537
|
"data-slot": "dropdown-menu-checkbox-item",
|
|
6529
|
-
className: cn(overlayItemClass, "py-1
|
|
6538
|
+
className: cn(overlayItemClass, "py-1 pr-2 pl-8", className),
|
|
6530
6539
|
checked,
|
|
6531
6540
|
...props,
|
|
6532
6541
|
children: [
|
|
@@ -6556,7 +6565,7 @@ function DropdownMenuRadioItem({
|
|
|
6556
6565
|
import_radix_ui6.DropdownMenu.RadioItem,
|
|
6557
6566
|
{
|
|
6558
6567
|
"data-slot": "dropdown-menu-radio-item",
|
|
6559
|
-
className: cn(overlayItemClass, "py-1
|
|
6568
|
+
className: cn(overlayItemClass, "py-1 pr-2 pl-8", className),
|
|
6560
6569
|
...props,
|
|
6561
6570
|
children: [
|
|
6562
6571
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_radix_ui6.DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react10.CircleIcon, { className: "size-2 fill-current" }) }) }),
|
|
@@ -7810,10 +7819,10 @@ var pillSegmentedTrackFlushClass = cn(
|
|
|
7810
7819
|
"h-[var(--studio-chrome-pill-height)] items-center gap-0.5 overflow-visible p-0.5"
|
|
7811
7820
|
);
|
|
7812
7821
|
var pillSegmentedSegmentClass = cn(
|
|
7813
|
-
"relative flex items-center gap-1.5 rounded-full px-
|
|
7822
|
+
"relative flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-normal transition-colors"
|
|
7814
7823
|
);
|
|
7815
7824
|
var pillSegmentedFlushSegmentClass = cn(
|
|
7816
|
-
"relative box-border inline-flex h-
|
|
7825
|
+
"relative box-border inline-flex h-8 min-h-8 items-center justify-center gap-1.5 rounded-full px-3 py-0",
|
|
7817
7826
|
"text-sm font-normal leading-tight transition-colors"
|
|
7818
7827
|
);
|
|
7819
7828
|
var pillSegmentedActiveIndicatorClass = cn(
|
|
@@ -8123,7 +8132,11 @@ var HOUSE_RULES = [
|
|
|
8123
8132
|
{
|
|
8124
8133
|
id: "compose-from-blocks",
|
|
8125
8134
|
rule: "Build from premade blocks (MetricRow, MetricChartCard, DataTable, IntegrationCard). Drop to raw primitives only when no block fits.",
|
|
8126
|
-
why: "Slop appears the moment generation falls below the curated block layer."
|
|
8135
|
+
why: "Slop appears the moment generation falls below the curated block layer.",
|
|
8136
|
+
// "Should have used a block" is a judgement about absence, not a textual
|
|
8137
|
+
// pattern — no high-precision deterministic check exists, so this stays
|
|
8138
|
+
// prompt-only rather than risk false-positives blocking valid UIs.
|
|
8139
|
+
enforcement: "prompt-only"
|
|
8127
8140
|
},
|
|
8128
8141
|
{
|
|
8129
8142
|
id: "use-kit-controls",
|
|
@@ -8204,7 +8217,7 @@ The content region is a **padded scroll area** by default \u2014 great for stack
|
|
|
8204
8217
|
- Give the filling child **\`min-h-0 flex-1\`** (or \`h-full\`) so its own scroll/footer resolves \u2014 e.g. \`<TimbalChat className="min-h-0 flex-1" />\`, or a two-pane row where each pane is \`min-h-0 overflow-y-auto\`.
|
|
8205
8218
|
|
|
8206
8219
|
\`\`\`tsx
|
|
8207
|
-
<AppShell contentFill topbar
|
|
8220
|
+
<AppShell contentFill> {/* no global topbar / theme switch */}
|
|
8208
8221
|
<Page fill> {/* headerless: omit title */}
|
|
8209
8222
|
<TimbalChat workforceId="\u2026" className="min-h-0 flex-1" />
|
|
8210
8223
|
</Page>
|
|
@@ -8224,7 +8237,7 @@ Presentational groups \u2014 import from the package root, not from these paths:
|
|
|
8224
8237
|
|
|
8225
8238
|
| Folder | Components |
|
|
8226
8239
|
|--------|------------|
|
|
8227
|
-
| \`data/\` | \`MetricRow\`, \`MetricChartCard\`, \`MetricTile\`, \`DataTable\`, \`FilterBar\`, \`FilterField\`, \`ChartPanel\` |
|
|
8240
|
+
| \`data/\` | \`MetricRow\`, \`MetricChartCard\`, \`MetricTile\`, \`DataTable\`, \`FilterBar\`, \`FilterField\`, \`FilterDropdown\`, \`ChartPanel\` |
|
|
8228
8241
|
| \`integrations/\` | \`IntegrationCard\`, \`ConnectionRow\`, \`ConnectionRowList\`, \`IntegrationsEmptyState\`, \`PlanBadge\` |
|
|
8229
8242
|
| \`settings/\` | \`SettingsSection\`, \`FieldRow\`, \`DangerZone\`, \`FloatingUnsavedChangesBar\` |
|
|
8230
8243
|
| \`surfaces/\` | \`StatTile\`, \`InfoCard\`, \`AlertCard\`, \`CatalogCard\`, \`ResourceCard\`, \`DescriptionList\`, \`ExpandableSection\`, \`StatusDot\`, \`StatusBadge\`, \`EmptyState\` |
|
|
@@ -8293,6 +8306,7 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
|
|
|
8293
8306
|
| \`StatusBadge\` | Status pill: \`tone\` (\`default\`\\|\`primary\`\\|\`success\`\\|\`warn\`\\|\`danger\`\\|\`muted\`), children. Use \`danger\` for critical/error severity. |
|
|
8294
8307
|
| \`FilterBar\` | Horizontal filter row \u2014 bottom-aligns controls. Mix \`SearchInput\` with labeled \`FilterField\` + \`Select\` (or \`Field\` + \`Select\`); labels sit above, control baselines match. |
|
|
8295
8308
|
| \`FilterField\` | Optional label wrapper for a filter control inside \`FilterBar\` (severity, status, \u2026). Omit \`label\` for search-only fields. |
|
|
8309
|
+
| \`FilterDropdown\` | Single-button **multi-facet** filter popover for dense list/table views \u2014 **data-driven**: pass \`fields\` describing your **actual columns** (each \`{ id, label, type }\` where \`type\` is \`multiselect\` \\| \`text\` \\| \`daterange\` \\| \`numeric\`; \`multiselect\` takes \`options: [{ value, label, hint?, icon? }]\`). State is keyed by field \`id\` \u2014 controlled (\`value\` + \`onChange\`) or uncontrolled (\`defaultValue\`). Renders **removable active-filter pills** next to the trigger by default (\`showActiveChips\`); wire \`onChange\` to actually filter your rows. **Always derive \`fields\` from the table's columns/data; never ship the default example facets.** Use when one \`FilterBar\` row isn't enough. |
|
|
8296
8310
|
| \`SearchInput\` | Filter field with consistent app styling. |
|
|
8297
8311
|
| \`DataTable\` | Sortable table: \`columns\`, \`rows\`, \`getRowKey\`, optional \`sort\` / \`onSortChange\`, \`emptyTitle\`, \`showRowCount\`, \`caption\`, \`truncate: true\` on columns with long text. **Scales:** \`pageSize\` (built-in client pager), \`selectable\` + \`onSelectionChange\` (checkbox column for bulk actions), \`loading\` (skeleton rows). \`onRowClick\` for row \u2192 detail (open a \`Sheet\`). |
|
|
8298
8312
|
| \`Avatar\` / \`AvatarFallback\` | User initials: \`variant="secondary"\` (or \`primary\` / \`chart\` alias) on **both** \`Avatar\` and \`AvatarFallback\` \u2014 same chrome as catalog **Action** buttons (\`Button variant="secondary"\`: elevated gradient, \`border-border\`, \`shadow-card\`, \`text-foreground\`). Never dark primary CTA fill or raw \`bg-blue-600\`. |
|
|
@@ -8307,6 +8321,8 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
|
|
|
8307
8321
|
|
|
8308
8322
|
Charts run on **recharts** with shadcn \`ChartContainer\` / \`ChartTooltipContent\` chrome (see \`src/ui/chart.tsx\`). Series colors default to \`--chart-1..6\`; override those CSS tokens to rebrand every chart.
|
|
8309
8323
|
|
|
8324
|
+
> **React 19 requirement \u2014 do not hand-roll SVG charts to work around this.** recharts under React 19 crashes (\`Cannot assign to read only property 'lanes'\`, blank route) when \`immer\` resolves to **11.0.0**. The fix is a dependency override in the app's \`package.json\` \u2014 \`"overrides": { "immer": ">=11.0.1" }\` (Yarn: \`"resolutions"\`) \u2014 **not** a code change. Always keep using \`LineAreaChart\` / \`PieChart\` / \`ChartPanel\`; never replace them with raw SVG/CSS charts.
|
|
8325
|
+
|
|
8310
8326
|
| Component | Use for |
|
|
8311
8327
|
|-----------|---------|
|
|
8312
8328
|
| \`LineAreaChart\` | Cartesian engine (shadcn-style chrome). Bar fills use theme gradients automatically. Props: \`data\`, \`xKey\`, \`series: [{ dataKey, label?, color? }]\`, \`variant\` (\`area\`\\|\`line\`\\|\`bar\`), \`orientation\` (\`horizontal\` for horizontal bars), \`stacked\`, \`curve\`, \`dots\`, \`gridLines\`, \`tooltipIndicator\`, \`layout\` (\`flush\` \u2014 hides axes by default; category + values on hover tooltip), \`showXAxis\` / \`showYAxis\` to opt back in, \`clipTicks\` (truncates long axis labels when axes are on), \`height\`, \`showLegend\`, \`formatX\`, \`formatValue\`, \`ariaLabel\`. |
|
|
@@ -8351,6 +8367,21 @@ Charts run on **recharts** with shadcn \`ChartContainer\` / \`ChartTooltipConten
|
|
|
8351
8367
|
| \`Banner\` | Page-level announcement bar: \`tone\` (\`default\`\\|\`primary\`\\|\`success\`\\|\`warn\`\\|\`danger\`), \`icon\`, \`title\`, body as children, right-aligned \`actions\`, \`onDismiss\` (renders the dismiss X). For in-form/field messages use \`InfoCard\` or \`Alert\` instead. |
|
|
8352
8368
|
| \`Timeline\` | Vertical event log: \`items: [{ id, title, description?, meta?, tone?, icon? }]\`. Presentational \u2014 pass already-formatted timestamps in \`meta\`. |
|
|
8353
8369
|
|
|
8370
|
+
#### More \`/ui\` primitives (import from \`/ui\` or the package root)
|
|
8371
|
+
|
|
8372
|
+
These ship in the same design system but aren't re-exported from \`/app\`. Reach for them before hand-rolling \u2014 they're all dependency-free and on the shared tokens / control surface.
|
|
8373
|
+
|
|
8374
|
+
| Component | Use for |
|
|
8375
|
+
|-----------|---------|
|
|
8376
|
+
| \`Stepper\` | Ordered step indicator for wizards / onboarding (horizontal or vertical; complete / active / upcoming states). |
|
|
8377
|
+
| \`Rating\` | Star rating \u2014 interactive (keyboard + hover preview) or \`readOnly\`; controlled or uncontrolled. |
|
|
8378
|
+
| \`NumberField\` | Numeric input with \u2212/+ steppers on the control surface; clamps to \`min\`/\`max\`, steps by \`step\`. |
|
|
8379
|
+
| \`TagInput\` | Chips / token input; commits on Enter/comma, removes on Backspace, optional \`dedupe\`/\`max\`. |
|
|
8380
|
+
| \`AvatarGroup\` | Overlapping avatar stack with an optional \`+N\` overflow chip (\`max\`, \`spacing\`). |
|
|
8381
|
+
| \`CircularProgress\` | Lightweight SVG progress ring \u2014 determinate (optional center label) or indeterminate. |
|
|
8382
|
+
| \`CopyButton\` | Click-to-copy with a transient check confirmation; icon-only or with a label. |
|
|
8383
|
+
| \`Snippet\` | Single-line code / command on the elevated surface with a built-in copy button. |
|
|
8384
|
+
|
|
8354
8385
|
Studio chrome (\`StudioSidebar\`, \`ModeToggle\`, \u2026) lives in \`@timbal-ai/timbal-react/studio\` \u2014 optional, not required for every dashboard.
|
|
8355
8386
|
|
|
8356
8387
|
### Block recipes \u2014 compose these (don't clone wholesale)
|
|
@@ -8417,6 +8448,7 @@ import {
|
|
|
8417
8448
|
DataTable,
|
|
8418
8449
|
FilterBar,
|
|
8419
8450
|
FilterField,
|
|
8451
|
+
FilterDropdown,
|
|
8420
8452
|
AlertCard,
|
|
8421
8453
|
CatalogCard,
|
|
8422
8454
|
} from "@timbal-ai/timbal-react/app";
|
|
@@ -8471,6 +8503,8 @@ var GRADIENT_DIRECTIONS = /* @__PURE__ */ new Set([
|
|
|
8471
8503
|
var ICON_IMPORT_RE = /from\s+["']lucide-react["']/;
|
|
8472
8504
|
var RAW_CONTROL_SURFACE_RE = /\bborder-input\b/;
|
|
8473
8505
|
var COLORED_HOVER_RE = /\bhover:(?:bg|from|to|via)-(?:primary|destructive|success|warn|danger|blue|emerald|green|amber|red|indigo|violet|purple|pink|rose|sky|cyan|teal|lime|yellow|orange|fuchsia)\b/;
|
|
8506
|
+
var TREND_CONTEXT_RE = /\b(?:trend|delta|TrendingUp|TrendingDown|ArrowUp|ArrowDown|ArrowUpRight|ArrowDownRight|MoveUp|MoveDown)\b|[+\-]\d+(?:\.\d+)?\s*%/;
|
|
8507
|
+
var TREND_COLOR_RE = /\b(?:text|bg|border)-(?:success|destructive|emerald|green|lime|teal|red|rose|orange|amber)(?:-\d{2,3})?(?:\/\d{1,3})?\b/;
|
|
8474
8508
|
var RESERVED_GRADIENT_SET = new Set(RESERVED_GRADIENT_TOKENS);
|
|
8475
8509
|
function stripVariants(util) {
|
|
8476
8510
|
return util.replace(/^(?:[a-z-]+:)*/, "");
|
|
@@ -8514,6 +8548,16 @@ function lintGeneratedUi(source, options = {}) {
|
|
|
8514
8548
|
if (cardMatch) {
|
|
8515
8549
|
const isSelfClosing = /\/>/.test(line) && line.indexOf(cardMatch[0]) < line.indexOf("/>");
|
|
8516
8550
|
if (!isSelfClosing) {
|
|
8551
|
+
if (openCards.length > 0) {
|
|
8552
|
+
const parentCard = openCards[openCards.length - 1];
|
|
8553
|
+
findings.push({
|
|
8554
|
+
rule: "no-card-in-card",
|
|
8555
|
+
severity: "warn",
|
|
8556
|
+
line: lineNo,
|
|
8557
|
+
message: `Card inside card. A <${cardMatch[1]}> is nested inside the <${parentCard.type}> opened on L${parentCard.line}. Double borders/shadows add no information \u2014 group with spacing or a <Section> instead.`,
|
|
8558
|
+
snippet: line.trim().slice(0, 120)
|
|
8559
|
+
});
|
|
8560
|
+
}
|
|
8517
8561
|
openCards.push({ type: cardMatch[1], line: lineNo });
|
|
8518
8562
|
}
|
|
8519
8563
|
}
|
|
@@ -8586,6 +8630,15 @@ function lintGeneratedUi(source, options = {}) {
|
|
|
8586
8630
|
snippet: line.trim().slice(0, 120)
|
|
8587
8631
|
});
|
|
8588
8632
|
}
|
|
8633
|
+
if (TREND_CONTEXT_RE.test(line) && TREND_COLOR_RE.test(line)) {
|
|
8634
|
+
findings.push({
|
|
8635
|
+
rule: "neutral-trend",
|
|
8636
|
+
severity: "warn",
|
|
8637
|
+
line: lineNo,
|
|
8638
|
+
message: "Colored trend indicator. House style: don't tint deltas green/red on every metric \u2014 show a trend only when the change is the point, and keep it muted (text-muted-foreground).",
|
|
8639
|
+
snippet: line.trim().slice(0, 120)
|
|
8640
|
+
});
|
|
8641
|
+
}
|
|
8589
8642
|
if (BOLD_VALUE_RE.test(line)) {
|
|
8590
8643
|
findings.push({
|
|
8591
8644
|
rule: "bold-metric",
|
|
@@ -9612,30 +9665,36 @@ var Sparkline = ({
|
|
|
9612
9665
|
height = 28,
|
|
9613
9666
|
strokeWidth = 1.5,
|
|
9614
9667
|
className,
|
|
9615
|
-
ariaLabel = "Trend"
|
|
9668
|
+
ariaLabel = "Trend",
|
|
9669
|
+
interactive = false,
|
|
9670
|
+
labels,
|
|
9671
|
+
formatValue
|
|
9616
9672
|
}) => {
|
|
9617
9673
|
const uid = (0, import_react57.useId)();
|
|
9674
|
+
const containerRef = (0, import_react57.useRef)(null);
|
|
9675
|
+
const [activeIndex, setActiveIndex] = (0, import_react57.useState)(null);
|
|
9618
9676
|
const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
|
|
9619
9677
|
if (values.length === 0) {
|
|
9620
9678
|
return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: cn("inline-block", className), style: { width, height } });
|
|
9621
9679
|
}
|
|
9622
|
-
const
|
|
9680
|
+
const padX = 0;
|
|
9681
|
+
const padY = strokeWidth + 1;
|
|
9623
9682
|
const min = Math.min(...values);
|
|
9624
9683
|
const max = Math.max(...values);
|
|
9625
9684
|
const range = max - min || 1;
|
|
9626
|
-
const innerW = width -
|
|
9627
|
-
const innerH = height -
|
|
9685
|
+
const innerW = width - padX * 2;
|
|
9686
|
+
const innerH = height - padY * 2;
|
|
9628
9687
|
const points = values.map((v, i) => ({
|
|
9629
|
-
x:
|
|
9630
|
-
y:
|
|
9688
|
+
x: padX + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
|
|
9689
|
+
y: padY + innerH - (v - min) / range * innerH
|
|
9631
9690
|
}));
|
|
9632
|
-
|
|
9691
|
+
const svg = /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
9633
9692
|
"svg",
|
|
9634
9693
|
{
|
|
9635
9694
|
width,
|
|
9636
9695
|
height,
|
|
9637
9696
|
viewBox: `0 0 ${width} ${height}`,
|
|
9638
|
-
className: cn("block", className),
|
|
9697
|
+
className: cn("block", interactive ? "h-full w-full" : className),
|
|
9639
9698
|
role: "img",
|
|
9640
9699
|
"aria-label": ariaLabel,
|
|
9641
9700
|
preserveAspectRatio: "none",
|
|
@@ -9645,7 +9704,7 @@ var Sparkline = ({
|
|
|
9645
9704
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
|
|
9646
9705
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
|
|
9647
9706
|
] }) }),
|
|
9648
|
-
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("path", { d: monotoneAreaPath(points, height -
|
|
9707
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("path", { d: monotoneAreaPath(points, height - padY), fill: `url(#${uid}-spark)` })
|
|
9649
9708
|
] }),
|
|
9650
9709
|
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
9651
9710
|
"path",
|
|
@@ -9657,7 +9716,81 @@ var Sparkline = ({
|
|
|
9657
9716
|
strokeLinecap: "round",
|
|
9658
9717
|
strokeLinejoin: "round"
|
|
9659
9718
|
}
|
|
9660
|
-
)
|
|
9719
|
+
),
|
|
9720
|
+
interactive && activeIndex != null && points[activeIndex] ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
9721
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
9722
|
+
"line",
|
|
9723
|
+
{
|
|
9724
|
+
x1: points[activeIndex].x,
|
|
9725
|
+
x2: points[activeIndex].x,
|
|
9726
|
+
y1: 0,
|
|
9727
|
+
y2: height,
|
|
9728
|
+
stroke: color,
|
|
9729
|
+
strokeWidth: 1,
|
|
9730
|
+
strokeOpacity: 0.3,
|
|
9731
|
+
vectorEffect: "non-scaling-stroke"
|
|
9732
|
+
}
|
|
9733
|
+
),
|
|
9734
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
|
|
9735
|
+
"circle",
|
|
9736
|
+
{
|
|
9737
|
+
cx: points[activeIndex].x,
|
|
9738
|
+
cy: points[activeIndex].y,
|
|
9739
|
+
r: 2.75,
|
|
9740
|
+
fill: color,
|
|
9741
|
+
stroke: "var(--background, #fff)",
|
|
9742
|
+
strokeWidth: 1.5,
|
|
9743
|
+
vectorEffect: "non-scaling-stroke"
|
|
9744
|
+
}
|
|
9745
|
+
)
|
|
9746
|
+
] }) : null
|
|
9747
|
+
]
|
|
9748
|
+
}
|
|
9749
|
+
);
|
|
9750
|
+
if (!interactive) return svg;
|
|
9751
|
+
const onMove = (e) => {
|
|
9752
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
9753
|
+
if (rect.width === 0) return;
|
|
9754
|
+
const fraction = (e.clientX - rect.left) / rect.width;
|
|
9755
|
+
const index = Math.max(
|
|
9756
|
+
0,
|
|
9757
|
+
Math.min(values.length - 1, Math.round(fraction * (values.length - 1)))
|
|
9758
|
+
);
|
|
9759
|
+
setActiveIndex(index);
|
|
9760
|
+
};
|
|
9761
|
+
const active = activeIndex != null ? points[activeIndex] : null;
|
|
9762
|
+
const formattedValue = activeIndex != null ? formatValue ? formatValue(values[activeIndex], activeIndex) : formatCompact(values[activeIndex]) : null;
|
|
9763
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
9764
|
+
"span",
|
|
9765
|
+
{
|
|
9766
|
+
ref: containerRef,
|
|
9767
|
+
className: cn("relative block touch-none", className),
|
|
9768
|
+
style: { width: "100%", height: "100%" },
|
|
9769
|
+
onPointerMove: onMove,
|
|
9770
|
+
onPointerLeave: () => setActiveIndex(null),
|
|
9771
|
+
children: [
|
|
9772
|
+
svg,
|
|
9773
|
+
active ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
9774
|
+
"span",
|
|
9775
|
+
{
|
|
9776
|
+
"aria-hidden": true,
|
|
9777
|
+
className: cn(
|
|
9778
|
+
"pointer-events-none absolute z-30 -translate-x-1/2 -translate-y-full whitespace-nowrap",
|
|
9779
|
+
"rounded-xl border px-3 py-2 text-[11px] font-medium leading-none tabular-nums shadow-[0_12px_40px_-10px_rgba(0,0,0,0.55)]",
|
|
9780
|
+
"border-white/10 bg-gradient-to-b from-neutral-800 to-neutral-950 text-white",
|
|
9781
|
+
"dark:border-black/10 dark:from-white dark:to-neutral-100 dark:text-neutral-900"
|
|
9782
|
+
),
|
|
9783
|
+
style: {
|
|
9784
|
+
left: `${active.x / width * 100}%`,
|
|
9785
|
+
top: `${active.y / height * 100}%`,
|
|
9786
|
+
marginTop: -8
|
|
9787
|
+
},
|
|
9788
|
+
children: [
|
|
9789
|
+
labels?.[activeIndex] != null ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "mr-1.5 text-neutral-300 dark:text-neutral-500", children: labels[activeIndex] }) : null,
|
|
9790
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: formattedValue })
|
|
9791
|
+
]
|
|
9792
|
+
}
|
|
9793
|
+
) : null
|
|
9661
9794
|
]
|
|
9662
9795
|
}
|
|
9663
9796
|
);
|
|
@@ -9675,6 +9808,15 @@ var inlineTrendToneClass = {
|
|
|
9675
9808
|
down: "text-rose-500/90 dark:text-rose-400/95 font-medium",
|
|
9676
9809
|
neutral: "text-muted-foreground/80"
|
|
9677
9810
|
};
|
|
9811
|
+
var sparklineToneColor = {
|
|
9812
|
+
up: "var(--primary, #3b82f6)",
|
|
9813
|
+
down: "var(--destructive, #f43f5e)",
|
|
9814
|
+
neutral: "var(--muted-foreground, #64748b)"
|
|
9815
|
+
};
|
|
9816
|
+
var sparklineBandBleed = {
|
|
9817
|
+
default: "-mx-4 -mb-3 h-10",
|
|
9818
|
+
compact: "-mx-3 -mb-2 h-8"
|
|
9819
|
+
};
|
|
9678
9820
|
var activeToneClass = {
|
|
9679
9821
|
default: "bg-foreground dark:bg-white",
|
|
9680
9822
|
primary: "bg-primary",
|
|
@@ -9704,8 +9846,10 @@ var MetricTile = ({
|
|
|
9704
9846
|
ariaLabel,
|
|
9705
9847
|
className
|
|
9706
9848
|
}) => {
|
|
9849
|
+
const density = useAppDensity();
|
|
9707
9850
|
const metricTileBaseClass = useAppDensityClass("metricTile");
|
|
9708
9851
|
const hasSparkline = Boolean(sparkline || sparklineData);
|
|
9852
|
+
const bandBleed = sparklineBandBleed[density === "compact" ? "compact" : "default"];
|
|
9709
9853
|
const content = /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)(import_jsx_runtime61.Fragment, { children: [
|
|
9710
9854
|
active ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
9711
9855
|
"span",
|
|
@@ -9717,17 +9861,6 @@ var MetricTile = ({
|
|
|
9717
9861
|
)
|
|
9718
9862
|
}
|
|
9719
9863
|
) : null,
|
|
9720
|
-
hasSparkline ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "absolute inset-x-0 bottom-0.5 h-9 w-full overflow-hidden pointer-events-none z-0 opacity-45 dark:opacity-35 select-none", children: sparkline ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
9721
|
-
Sparkline,
|
|
9722
|
-
{
|
|
9723
|
-
data: sparklineData,
|
|
9724
|
-
width: 160,
|
|
9725
|
-
height: 36,
|
|
9726
|
-
className: "w-full h-full",
|
|
9727
|
-
color: trendTone === "up" ? "var(--primary, #3b82f6)" : trendTone === "down" ? "var(--destructive, #f43f5e)" : "var(--muted-foreground, #64748b)",
|
|
9728
|
-
...sparklineConfig
|
|
9729
|
-
}
|
|
9730
|
-
) }) : null,
|
|
9731
9864
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "relative z-10 flex flex-col gap-1 w-full text-left", children: [
|
|
9732
9865
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "text-xs font-semibold text-muted-foreground/80 tracking-tight", children: label }),
|
|
9733
9866
|
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
@@ -9746,7 +9879,28 @@ var MetricTile = ({
|
|
|
9746
9879
|
}
|
|
9747
9880
|
) : null
|
|
9748
9881
|
] })
|
|
9749
|
-
] })
|
|
9882
|
+
] }),
|
|
9883
|
+
hasSparkline ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
9884
|
+
"div",
|
|
9885
|
+
{
|
|
9886
|
+
className: cn(
|
|
9887
|
+
"relative z-10 mt-2",
|
|
9888
|
+
bandBleed
|
|
9889
|
+
),
|
|
9890
|
+
children: sparkline ?? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
|
|
9891
|
+
Sparkline,
|
|
9892
|
+
{
|
|
9893
|
+
data: sparklineData,
|
|
9894
|
+
width: 160,
|
|
9895
|
+
height: 40,
|
|
9896
|
+
interactive: true,
|
|
9897
|
+
className: "h-full w-full opacity-90",
|
|
9898
|
+
color: sparklineToneColor[trendTone],
|
|
9899
|
+
...sparklineConfig
|
|
9900
|
+
}
|
|
9901
|
+
)
|
|
9902
|
+
}
|
|
9903
|
+
) : null
|
|
9750
9904
|
] });
|
|
9751
9905
|
const divider = showDivider ? metricCellDividerClass : void 0;
|
|
9752
9906
|
if (onSelect) {
|
|
@@ -10447,7 +10601,7 @@ var StatusBadge = ({
|
|
|
10447
10601
|
"span",
|
|
10448
10602
|
{
|
|
10449
10603
|
className: cn(
|
|
10450
|
-
"aui-app-status-badge inline-flex items-center gap-1.5 rounded-full px-2 py-0.5",
|
|
10604
|
+
"aui-app-status-badge inline-flex w-fit shrink-0 items-center gap-1.5 rounded-full px-2 py-0.5",
|
|
10451
10605
|
"text-xs font-medium leading-none ring-1 ring-inset",
|
|
10452
10606
|
statusBadgeToneClass[tone],
|
|
10453
10607
|
className
|
|
@@ -10861,7 +11015,7 @@ function CopyButton({
|
|
|
10861
11015
|
"inline-flex items-center justify-center gap-1.5 rounded-md text-sm font-medium text-muted-foreground transition-colors",
|
|
10862
11016
|
"hover:bg-accent hover:text-foreground data-[copied=true]:text-emerald-600 dark:data-[copied=true]:text-emerald-400",
|
|
10863
11017
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15",
|
|
10864
|
-
children ? "h-
|
|
11018
|
+
children ? "h-7 px-1.5" : "size-7",
|
|
10865
11019
|
className
|
|
10866
11020
|
),
|
|
10867
11021
|
...props,
|
|
@@ -11592,7 +11746,7 @@ var FilterField = ({
|
|
|
11592
11746
|
|
|
11593
11747
|
// src/app/data/FilterDropdown.tsx
|
|
11594
11748
|
var import_react73 = require("react");
|
|
11595
|
-
var
|
|
11749
|
+
var import_lucide_react25 = require("lucide-react");
|
|
11596
11750
|
|
|
11597
11751
|
// src/ui/checkbox.tsx
|
|
11598
11752
|
var import_radix_ui7 = require("radix-ui");
|
|
@@ -11625,23 +11779,178 @@ function Checkbox({
|
|
|
11625
11779
|
);
|
|
11626
11780
|
}
|
|
11627
11781
|
|
|
11628
|
-
// src/ui/
|
|
11782
|
+
// src/ui/select.tsx
|
|
11629
11783
|
var import_radix_ui8 = require("radix-ui");
|
|
11784
|
+
var import_lucide_react24 = require("lucide-react");
|
|
11630
11785
|
var import_jsx_runtime105 = require("react/jsx-runtime");
|
|
11786
|
+
function Select({
|
|
11787
|
+
...props
|
|
11788
|
+
}) {
|
|
11789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.Root, { "data-slot": "select", ...props });
|
|
11790
|
+
}
|
|
11791
|
+
function SelectGroup({
|
|
11792
|
+
...props
|
|
11793
|
+
}) {
|
|
11794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.Group, { "data-slot": "select-group", ...props });
|
|
11795
|
+
}
|
|
11796
|
+
function SelectValue({
|
|
11797
|
+
...props
|
|
11798
|
+
}) {
|
|
11799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.Value, { "data-slot": "select-value", ...props });
|
|
11800
|
+
}
|
|
11801
|
+
function SelectTrigger({
|
|
11802
|
+
className,
|
|
11803
|
+
size = "default",
|
|
11804
|
+
children,
|
|
11805
|
+
...props
|
|
11806
|
+
}) {
|
|
11807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
|
|
11808
|
+
import_radix_ui8.Select.Trigger,
|
|
11809
|
+
{
|
|
11810
|
+
"data-slot": "select-trigger",
|
|
11811
|
+
"data-size": size,
|
|
11812
|
+
className: cn(
|
|
11813
|
+
controlClass({ size }),
|
|
11814
|
+
"flex w-fit items-center justify-between gap-2 whitespace-nowrap *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
11815
|
+
className
|
|
11816
|
+
),
|
|
11817
|
+
...props,
|
|
11818
|
+
children: [
|
|
11819
|
+
children,
|
|
11820
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_lucide_react24.ChevronDownIcon, { className: "size-4 opacity-50" }) })
|
|
11821
|
+
]
|
|
11822
|
+
}
|
|
11823
|
+
);
|
|
11824
|
+
}
|
|
11825
|
+
function SelectContent({
|
|
11826
|
+
className,
|
|
11827
|
+
children,
|
|
11828
|
+
position = "popper",
|
|
11829
|
+
...props
|
|
11830
|
+
}) {
|
|
11831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
|
|
11832
|
+
import_radix_ui8.Select.Content,
|
|
11833
|
+
{
|
|
11834
|
+
"data-slot": "select-content",
|
|
11835
|
+
className: cn(
|
|
11836
|
+
overlayListPanelClass,
|
|
11837
|
+
"relative max-h-[var(--radix-select-content-available-height)] min-w-[8rem] origin-[var(--radix-select-content-transform-origin)] overflow-x-hidden overflow-y-auto",
|
|
11838
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
11839
|
+
className
|
|
11840
|
+
),
|
|
11841
|
+
position,
|
|
11842
|
+
...props,
|
|
11843
|
+
children: [
|
|
11844
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(SelectScrollUpButton, {}),
|
|
11845
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
11846
|
+
import_radix_ui8.Select.Viewport,
|
|
11847
|
+
{
|
|
11848
|
+
className: cn(
|
|
11849
|
+
"p-1",
|
|
11850
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
11851
|
+
),
|
|
11852
|
+
children
|
|
11853
|
+
}
|
|
11854
|
+
),
|
|
11855
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(SelectScrollDownButton, {})
|
|
11856
|
+
]
|
|
11857
|
+
}
|
|
11858
|
+
) });
|
|
11859
|
+
}
|
|
11860
|
+
function SelectLabel({
|
|
11861
|
+
className,
|
|
11862
|
+
...props
|
|
11863
|
+
}) {
|
|
11864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
11865
|
+
import_radix_ui8.Select.Label,
|
|
11866
|
+
{
|
|
11867
|
+
"data-slot": "select-label",
|
|
11868
|
+
className: cn("px-2 py-1.5 text-xs font-medium text-muted-foreground", className),
|
|
11869
|
+
...props
|
|
11870
|
+
}
|
|
11871
|
+
);
|
|
11872
|
+
}
|
|
11873
|
+
function SelectItem({
|
|
11874
|
+
className,
|
|
11875
|
+
children,
|
|
11876
|
+
...props
|
|
11877
|
+
}) {
|
|
11878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
|
|
11879
|
+
import_radix_ui8.Select.Item,
|
|
11880
|
+
{
|
|
11881
|
+
"data-slot": "select-item",
|
|
11882
|
+
className: cn(
|
|
11883
|
+
overlayItemClass,
|
|
11884
|
+
"w-full py-1 pr-8 pl-2 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
11885
|
+
className
|
|
11886
|
+
),
|
|
11887
|
+
...props,
|
|
11888
|
+
children: [
|
|
11889
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_lucide_react24.CheckIcon, { className: "size-4" }) }) }),
|
|
11890
|
+
/* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_radix_ui8.Select.ItemText, { children })
|
|
11891
|
+
]
|
|
11892
|
+
}
|
|
11893
|
+
);
|
|
11894
|
+
}
|
|
11895
|
+
function SelectSeparator({
|
|
11896
|
+
className,
|
|
11897
|
+
...props
|
|
11898
|
+
}) {
|
|
11899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
11900
|
+
import_radix_ui8.Select.Separator,
|
|
11901
|
+
{
|
|
11902
|
+
"data-slot": "select-separator",
|
|
11903
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
11904
|
+
...props
|
|
11905
|
+
}
|
|
11906
|
+
);
|
|
11907
|
+
}
|
|
11908
|
+
function SelectScrollUpButton({
|
|
11909
|
+
className,
|
|
11910
|
+
...props
|
|
11911
|
+
}) {
|
|
11912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
11913
|
+
import_radix_ui8.Select.ScrollUpButton,
|
|
11914
|
+
{
|
|
11915
|
+
"data-slot": "select-scroll-up-button",
|
|
11916
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
11917
|
+
...props,
|
|
11918
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_lucide_react24.ChevronUpIcon, { className: "size-4" })
|
|
11919
|
+
}
|
|
11920
|
+
);
|
|
11921
|
+
}
|
|
11922
|
+
function SelectScrollDownButton({
|
|
11923
|
+
className,
|
|
11924
|
+
...props
|
|
11925
|
+
}) {
|
|
11926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
|
|
11927
|
+
import_radix_ui8.Select.ScrollDownButton,
|
|
11928
|
+
{
|
|
11929
|
+
"data-slot": "select-scroll-down-button",
|
|
11930
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
11931
|
+
...props,
|
|
11932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(import_lucide_react24.ChevronDownIcon, { className: "size-4" })
|
|
11933
|
+
}
|
|
11934
|
+
);
|
|
11935
|
+
}
|
|
11936
|
+
|
|
11937
|
+
// src/ui/popover.tsx
|
|
11938
|
+
var import_radix_ui9 = require("radix-ui");
|
|
11939
|
+
var import_jsx_runtime106 = require("react/jsx-runtime");
|
|
11631
11940
|
function Popover({
|
|
11632
11941
|
...props
|
|
11633
11942
|
}) {
|
|
11634
|
-
return /* @__PURE__ */ (0,
|
|
11943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_radix_ui9.Popover.Root, { "data-slot": "popover", ...props });
|
|
11635
11944
|
}
|
|
11636
11945
|
function PopoverTrigger({
|
|
11637
11946
|
...props
|
|
11638
11947
|
}) {
|
|
11639
|
-
return /* @__PURE__ */ (0,
|
|
11948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_radix_ui9.Popover.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
11640
11949
|
}
|
|
11641
11950
|
function PopoverAnchor({
|
|
11642
11951
|
...props
|
|
11643
11952
|
}) {
|
|
11644
|
-
return /* @__PURE__ */ (0,
|
|
11953
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_radix_ui9.Popover.Anchor, { "data-slot": "popover-anchor", ...props });
|
|
11645
11954
|
}
|
|
11646
11955
|
function PopoverContent({
|
|
11647
11956
|
className,
|
|
@@ -11650,8 +11959,8 @@ function PopoverContent({
|
|
|
11650
11959
|
variant = "default",
|
|
11651
11960
|
...props
|
|
11652
11961
|
}) {
|
|
11653
|
-
return /* @__PURE__ */ (0,
|
|
11654
|
-
|
|
11962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_radix_ui9.Popover.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11963
|
+
import_radix_ui9.Popover.Content,
|
|
11655
11964
|
{
|
|
11656
11965
|
"data-slot": "popover-content",
|
|
11657
11966
|
"data-variant": variant,
|
|
@@ -11663,7 +11972,7 @@ function PopoverContent({
|
|
|
11663
11972
|
"min-w-[8rem] origin-[var(--radix-popover-content-transform-origin)]"
|
|
11664
11973
|
) : cn(
|
|
11665
11974
|
overlaySurfaceClass,
|
|
11666
|
-
"w-72 origin-[var(--radix-popover-content-transform-origin)] rounded-xl p-
|
|
11975
|
+
"w-72 origin-[var(--radix-popover-content-transform-origin)] rounded-xl p-3 outline-hidden"
|
|
11667
11976
|
),
|
|
11668
11977
|
className
|
|
11669
11978
|
),
|
|
@@ -11673,499 +11982,471 @@ function PopoverContent({
|
|
|
11673
11982
|
}
|
|
11674
11983
|
|
|
11675
11984
|
// src/app/data/FilterDropdown.tsx
|
|
11676
|
-
var
|
|
11677
|
-
var
|
|
11678
|
-
{ id: "
|
|
11679
|
-
{ id: "
|
|
11680
|
-
{ id: "
|
|
11985
|
+
var import_jsx_runtime107 = require("react/jsx-runtime");
|
|
11986
|
+
var DEFAULT_PRESETS = [
|
|
11987
|
+
{ id: "last_7_days", label: "Last 7 days" },
|
|
11988
|
+
{ id: "last_30_days", label: "Last 30 days" },
|
|
11989
|
+
{ id: "last_90_days", label: "Last 90 days" },
|
|
11990
|
+
{ id: "this_month", label: "This month" },
|
|
11991
|
+
{ id: "this_year", label: "This year" },
|
|
11992
|
+
{ id: "custom", label: "Custom range" }
|
|
11681
11993
|
];
|
|
11682
|
-
var
|
|
11683
|
-
{ id: "
|
|
11684
|
-
{ id: "
|
|
11685
|
-
{ id: "
|
|
11994
|
+
var DEFAULT_OPERATORS = [
|
|
11995
|
+
{ id: "gt", label: "Greater than" },
|
|
11996
|
+
{ id: "lt", label: "Less than" },
|
|
11997
|
+
{ id: "eq", label: "Equals" }
|
|
11686
11998
|
];
|
|
11999
|
+
function asArray(v) {
|
|
12000
|
+
return Array.isArray(v) ? v : [];
|
|
12001
|
+
}
|
|
12002
|
+
function asText(v) {
|
|
12003
|
+
return typeof v === "string" ? v : "";
|
|
12004
|
+
}
|
|
12005
|
+
function asDate(v) {
|
|
12006
|
+
return v && !Array.isArray(v) && typeof v === "object" && "preset" in v ? v : { preset: null };
|
|
12007
|
+
}
|
|
12008
|
+
function asNumeric(v) {
|
|
12009
|
+
return v && !Array.isArray(v) && typeof v === "object" && "operator" in v ? v : { operator: "gt", value: "" };
|
|
12010
|
+
}
|
|
12011
|
+
var OPERATOR_SYMBOL = {
|
|
12012
|
+
gt: ">",
|
|
12013
|
+
lt: "<",
|
|
12014
|
+
eq: "="
|
|
12015
|
+
};
|
|
11687
12016
|
function FilterDropdown({
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
12017
|
+
fields,
|
|
12018
|
+
value,
|
|
12019
|
+
defaultValue,
|
|
12020
|
+
onChange,
|
|
12021
|
+
label = "Filter",
|
|
12022
|
+
align = "start",
|
|
12023
|
+
showActiveChips = true,
|
|
11692
12024
|
className
|
|
11693
12025
|
}) {
|
|
11694
12026
|
const [isOpen, setIsOpen] = (0, import_react73.useState)(false);
|
|
11695
|
-
const [
|
|
12027
|
+
const [activeId, setActiveId] = (0, import_react73.useState)(fields[0]?.id ?? null);
|
|
11696
12028
|
const [isMobile, setIsMobile] = (0, import_react73.useState)(false);
|
|
12029
|
+
const isControlled = value !== void 0;
|
|
12030
|
+
const [internal, setInternal] = (0, import_react73.useState)(defaultValue ?? {});
|
|
12031
|
+
const values = isControlled ? value : internal;
|
|
11697
12032
|
(0, import_react73.useEffect)(() => {
|
|
11698
12033
|
const checkMobile = () => setIsMobile(window.innerWidth < 768);
|
|
11699
12034
|
checkMobile();
|
|
11700
12035
|
window.addEventListener("resize", checkMobile);
|
|
11701
12036
|
return () => window.removeEventListener("resize", checkMobile);
|
|
11702
12037
|
}, []);
|
|
11703
|
-
const [selectedContacts, setSelectedContacts] = (0, import_react73.useState)(
|
|
11704
|
-
filters?.contacts ?? initialFilters?.contacts ?? []
|
|
11705
|
-
);
|
|
11706
|
-
const [walletInput, setWalletInput] = (0, import_react73.useState)(filters?.walletAddress ?? initialFilters?.walletAddress ?? "");
|
|
11707
|
-
const [appliedWallet, setAppliedWallet] = (0, import_react73.useState)(filters?.walletAddress ?? initialFilters?.walletAddress ?? "");
|
|
11708
|
-
const [selectedDatePreset, setSelectedDatePreset] = (0, import_react73.useState)(
|
|
11709
|
-
filters?.lastInvoiceDate ?? initialFilters?.lastInvoiceDate ?? null
|
|
11710
|
-
);
|
|
11711
|
-
const [customDateFrom, setCustomDateFrom] = (0, import_react73.useState)(
|
|
11712
|
-
filters?.customDateRange?.from ?? initialFilters?.customDateRange?.from ?? ""
|
|
11713
|
-
);
|
|
11714
|
-
const [customDateTo, setCustomDateTo] = (0, import_react73.useState)(
|
|
11715
|
-
filters?.customDateRange?.to ?? initialFilters?.customDateRange?.to ?? ""
|
|
11716
|
-
);
|
|
11717
|
-
const [ltvOperator, setLtvOperator] = (0, import_react73.useState)(
|
|
11718
|
-
filters?.lifetimeValue?.operator ?? initialFilters?.lifetimeValue?.operator ?? "greater_than"
|
|
11719
|
-
);
|
|
11720
|
-
const [ltvValue, setLtvValue] = (0, import_react73.useState)(filters?.lifetimeValue?.value ?? initialFilters?.lifetimeValue?.value ?? "");
|
|
11721
|
-
const [isLtvOperatorOpen, setLtvOperatorOpen] = (0, import_react73.useState)(false);
|
|
11722
|
-
const [outstandingOperator, setOutstandingOperator] = (0, import_react73.useState)(
|
|
11723
|
-
filters?.outstanding?.operator ?? initialFilters?.outstanding?.operator ?? "greater_than"
|
|
11724
|
-
);
|
|
11725
|
-
const [outstandingValue, setOutstandingValue] = (0, import_react73.useState)(filters?.outstanding?.value ?? initialFilters?.outstanding?.value ?? "");
|
|
11726
|
-
const [isOutstandingOperatorOpen, setOutstandingOperatorOpen] = (0, import_react73.useState)(false);
|
|
11727
12038
|
(0, import_react73.useEffect)(() => {
|
|
11728
|
-
if (
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
setLtvValue(filters.lifetimeValue?.value ?? "");
|
|
11737
|
-
setOutstandingOperator(filters.outstanding?.operator ?? "greater_than");
|
|
11738
|
-
setOutstandingValue(filters.outstanding?.value ?? "");
|
|
11739
|
-
}
|
|
11740
|
-
}, [filters]);
|
|
11741
|
-
const [contactSearch, setContactSearch] = (0, import_react73.useState)("");
|
|
11742
|
-
const [walletSearch, setWalletSearch] = (0, import_react73.useState)("");
|
|
11743
|
-
const refDate = (0, import_react73.useMemo)(() => new Date(2026, 5, 26), []);
|
|
11744
|
-
const presets = (0, import_react73.useMemo)(() => {
|
|
11745
|
-
const year = refDate.getFullYear();
|
|
11746
|
-
const month = refDate.getMonth();
|
|
11747
|
-
const lastMonthDate = new Date(year, month - 1, 1);
|
|
11748
|
-
const lastMonthLabel = lastMonthDate.toLocaleDateString("en-US", { month: "short", year: "numeric" });
|
|
11749
|
-
const thisMonthLabel = refDate.toLocaleDateString("en-US", { month: "short", year: "numeric" });
|
|
11750
|
-
const thisQuarter = Math.floor(month / 3) + 1;
|
|
11751
|
-
const thisQuarterLabel = `Q${thisQuarter} ${year}`;
|
|
11752
|
-
const lastQuarter = thisQuarter === 1 ? 4 : thisQuarter - 1;
|
|
11753
|
-
const lastQuarterYear = thisQuarter === 1 ? year - 1 : year;
|
|
11754
|
-
const lastQuarterLabel = `Q${lastQuarter} ${lastQuarterYear}`;
|
|
11755
|
-
const thisYearLabel = `${year}`;
|
|
11756
|
-
const last30 = new Date(refDate);
|
|
11757
|
-
last30.setDate(refDate.getDate() - 30);
|
|
11758
|
-
const formatDate = (d) => d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
11759
|
-
const last30Label = `${formatDate(last30)} - ${formatDate(refDate)}`;
|
|
11760
|
-
const last90 = new Date(refDate);
|
|
11761
|
-
last90.setDate(refDate.getDate() - 90);
|
|
11762
|
-
const last90Label = `${formatDate(last90)} - ${formatDate(refDate)}`;
|
|
11763
|
-
return [
|
|
11764
|
-
{ id: "last_month", label: "Last month", date: lastMonthLabel },
|
|
11765
|
-
{ id: "this_month", label: "This month", date: thisMonthLabel },
|
|
11766
|
-
{ id: "this_quarter", label: "This quarter", date: thisQuarterLabel },
|
|
11767
|
-
{ id: "last_quarter", label: "Last quarter", date: lastQuarterLabel },
|
|
11768
|
-
{ id: "this_year", label: "This year", date: thisYearLabel },
|
|
11769
|
-
{ id: "last_30_days", label: "Last 30 days", date: last30Label },
|
|
11770
|
-
{ id: "last_90_days", label: "Last 90 days", date: last90Label },
|
|
11771
|
-
{ id: "custom", label: "Custom range", date: "" }
|
|
11772
|
-
];
|
|
11773
|
-
}, [refDate]);
|
|
11774
|
-
const filteredContacts = (0, import_react73.useMemo)(() => {
|
|
11775
|
-
if (!contactSearch) return contacts;
|
|
11776
|
-
const query = contactSearch.toLowerCase();
|
|
11777
|
-
return contacts.filter(
|
|
11778
|
-
(c) => c.name.toLowerCase().includes(query) || c.email.toLowerCase().includes(query)
|
|
11779
|
-
);
|
|
11780
|
-
}, [contacts, contactSearch]);
|
|
11781
|
-
const handleContactToggle = (contactName) => {
|
|
11782
|
-
const next = selectedContacts.includes(contactName) ? selectedContacts.filter((name) => name !== contactName) : [...selectedContacts, contactName];
|
|
11783
|
-
setSelectedContacts(next);
|
|
11784
|
-
notifyChanges({ contacts: next });
|
|
11785
|
-
setIsOpen(false);
|
|
11786
|
-
};
|
|
11787
|
-
const handleWalletApply = () => {
|
|
11788
|
-
setAppliedWallet(walletInput);
|
|
11789
|
-
notifyChanges({ walletAddress: walletInput });
|
|
11790
|
-
setIsOpen(false);
|
|
11791
|
-
};
|
|
11792
|
-
const handleWalletClear = () => {
|
|
11793
|
-
setWalletInput("");
|
|
11794
|
-
setAppliedWallet("");
|
|
11795
|
-
notifyChanges({ walletAddress: "" });
|
|
11796
|
-
setIsOpen(false);
|
|
11797
|
-
};
|
|
11798
|
-
const handleDatePresetSelect = (presetId) => {
|
|
11799
|
-
setSelectedDatePreset(presetId);
|
|
11800
|
-
if (presetId !== "custom") {
|
|
11801
|
-
notifyChanges({ lastInvoiceDate: presetId, customDateRange: void 0 });
|
|
11802
|
-
setIsOpen(false);
|
|
11803
|
-
}
|
|
11804
|
-
};
|
|
11805
|
-
const handleCustomDateApply = () => {
|
|
11806
|
-
notifyChanges({
|
|
11807
|
-
lastInvoiceDate: "custom",
|
|
11808
|
-
customDateRange: { from: customDateFrom, to: customDateTo }
|
|
11809
|
-
});
|
|
11810
|
-
setIsOpen(false);
|
|
11811
|
-
};
|
|
11812
|
-
const handleLtvApply = () => {
|
|
11813
|
-
notifyChanges({
|
|
11814
|
-
lifetimeValue: ltvValue ? { operator: ltvOperator, value: ltvValue } : null
|
|
11815
|
-
});
|
|
11816
|
-
setIsOpen(false);
|
|
11817
|
-
};
|
|
11818
|
-
const handleLtvClear = () => {
|
|
11819
|
-
setLtvValue("");
|
|
11820
|
-
notifyChanges({ lifetimeValue: null });
|
|
11821
|
-
setIsOpen(false);
|
|
11822
|
-
};
|
|
11823
|
-
const handleOutstandingApply = () => {
|
|
11824
|
-
notifyChanges({
|
|
11825
|
-
outstanding: outstandingValue ? { operator: outstandingOperator, value: outstandingValue } : null
|
|
11826
|
-
});
|
|
11827
|
-
setIsOpen(false);
|
|
12039
|
+
if (!fields.some((f) => f.id === activeId)) {
|
|
12040
|
+
setActiveId(fields[0]?.id ?? null);
|
|
12041
|
+
}
|
|
12042
|
+
}, [fields, activeId]);
|
|
12043
|
+
const commit = (id, next) => {
|
|
12044
|
+
const merged = { ...values, [id]: next };
|
|
12045
|
+
if (!isControlled) setInternal(merged);
|
|
12046
|
+
onChange?.(merged);
|
|
11828
12047
|
};
|
|
11829
|
-
const
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
setIsOpen(false);
|
|
12048
|
+
const clearAll = () => {
|
|
12049
|
+
if (!isControlled) setInternal({});
|
|
12050
|
+
onChange?.({});
|
|
11833
12051
|
};
|
|
11834
|
-
const
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
{ id: "wallet", label: "Wallet address", icon: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.WalletIcon, { className: "size-4" }) },
|
|
11849
|
-
{ id: "date", label: "Last invoice date", icon: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.CalendarIcon, { className: "size-4" }) },
|
|
11850
|
-
{ id: "ltv", label: "Lifetime value", icon: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.TrendingUpIcon, { className: "size-4" }) },
|
|
11851
|
-
{ id: "outstanding", label: "Outstanding", icon: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.CircleDollarSignIcon, { className: "size-4" }) }
|
|
11852
|
-
];
|
|
11853
|
-
const activeIdx = menuItems.findIndex((item) => item.id === activeMenu);
|
|
11854
|
-
return /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: cn("inline-block", className), children: /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
11855
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11856
|
-
Button,
|
|
11857
|
-
{
|
|
11858
|
-
variant: "outline",
|
|
11859
|
-
size: "sm",
|
|
11860
|
-
shape: "pill",
|
|
11861
|
-
className: "border-dashed font-medium text-muted-foreground hover:text-foreground",
|
|
11862
|
-
iconLeading: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.ListFilterIcon, { className: "size-4" }),
|
|
11863
|
-
children: "Filter"
|
|
12052
|
+
const activeIdx = fields.findIndex((f) => f.id === activeId);
|
|
12053
|
+
const activeField = activeIdx >= 0 ? fields[activeIdx] : void 0;
|
|
12054
|
+
const chips = [];
|
|
12055
|
+
for (const field of fields) {
|
|
12056
|
+
const v = values[field.id];
|
|
12057
|
+
if (field.type === "multiselect") {
|
|
12058
|
+
const selected = asArray(v);
|
|
12059
|
+
for (const optionValue of selected) {
|
|
12060
|
+
const opt = field.options?.find((o) => o.value === optionValue);
|
|
12061
|
+
chips.push({
|
|
12062
|
+
id: `${field.id}:${optionValue}`,
|
|
12063
|
+
label: `${field.label}: ${opt?.label ?? optionValue}`,
|
|
12064
|
+
remove: () => commit(field.id, selected.filter((x) => x !== optionValue))
|
|
12065
|
+
});
|
|
11864
12066
|
}
|
|
11865
|
-
)
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
|
|
11898
|
-
|
|
11899
|
-
|
|
11900
|
-
|
|
11901
|
-
|
|
11902
|
-
|
|
11903
|
-
|
|
11904
|
-
|
|
11905
|
-
|
|
11906
|
-
|
|
11907
|
-
|
|
11908
|
-
|
|
11909
|
-
|
|
11910
|
-
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(Avatar, { variant: "secondary", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(AvatarFallback, { children: contact.initials }) }),
|
|
11931
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "text-sm font-medium text-foreground", children: contact.name })
|
|
11932
|
-
]
|
|
11933
|
-
},
|
|
11934
|
-
contact.id
|
|
11935
|
-
);
|
|
11936
|
-
}) })
|
|
11937
|
-
] }),
|
|
11938
|
-
activeMenu === "wallet" && /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
11939
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "relative flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11940
|
-
"input",
|
|
11941
|
-
{
|
|
11942
|
-
type: "text",
|
|
11943
|
-
placeholder: "Search by wallet...",
|
|
11944
|
-
value: walletInput,
|
|
11945
|
-
onChange: (e) => setWalletInput(e.target.value),
|
|
11946
|
-
className: "w-full rounded-lg border border-border bg-background px-3 py-1.5 text-sm outline-none placeholder:text-muted-foreground/60"
|
|
11947
|
-
}
|
|
11948
|
-
) }),
|
|
11949
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex items-center justify-end gap-2 pt-1 border-t border-border/40", children: [
|
|
11950
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11951
|
-
Button,
|
|
11952
|
-
{
|
|
11953
|
-
variant: "ghost",
|
|
11954
|
-
size: "sm",
|
|
11955
|
-
onClick: handleWalletClear,
|
|
11956
|
-
className: "text-muted-foreground hover:text-foreground h-8 px-3",
|
|
11957
|
-
children: "Clear"
|
|
11958
|
-
}
|
|
11959
|
-
),
|
|
11960
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11961
|
-
Button,
|
|
11962
|
-
{
|
|
11963
|
-
color: "primary",
|
|
11964
|
-
size: "sm",
|
|
11965
|
-
onClick: handleWalletApply,
|
|
11966
|
-
className: "h-8 px-3",
|
|
11967
|
-
children: "Apply"
|
|
11968
|
-
}
|
|
11969
|
-
)
|
|
11970
|
-
] })
|
|
11971
|
-
] }),
|
|
11972
|
-
activeMenu === "date" && /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
11973
|
-
presets.map((preset) => {
|
|
11974
|
-
const isSelected = selectedDatePreset === preset.id;
|
|
11975
|
-
return /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(
|
|
11976
|
-
"button",
|
|
11977
|
-
{
|
|
11978
|
-
type: "button",
|
|
11979
|
-
onClick: () => handleDatePresetSelect(preset.id),
|
|
11980
|
-
className: cn(
|
|
11981
|
-
"flex w-full items-center justify-between rounded-lg px-2.5 py-1.5 text-sm text-left transition-colors outline-none",
|
|
11982
|
-
isSelected ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
|
|
11983
|
-
),
|
|
11984
|
-
children: [
|
|
11985
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { children: preset.label }),
|
|
11986
|
-
preset.date && /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "text-xs text-muted-foreground/70", children: preset.date })
|
|
11987
|
-
]
|
|
11988
|
-
},
|
|
11989
|
-
preset.id
|
|
11990
|
-
);
|
|
11991
|
-
}),
|
|
11992
|
-
selectedDatePreset === "custom" && /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex flex-col gap-2 mt-2 pt-2 border-t border-border/40", children: [
|
|
11993
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
11994
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
11995
|
-
"input",
|
|
11996
|
-
{
|
|
11997
|
-
type: "date",
|
|
11998
|
-
value: customDateFrom,
|
|
11999
|
-
onChange: (e) => setCustomDateFrom(e.target.value),
|
|
12000
|
-
className: "w-full rounded-lg border border-border bg-background px-2 py-1 text-xs outline-none"
|
|
12001
|
-
}
|
|
12002
|
-
),
|
|
12003
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { className: "text-xs text-muted-foreground", children: "to" }),
|
|
12004
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12005
|
-
"input",
|
|
12006
|
-
{
|
|
12007
|
-
type: "date",
|
|
12008
|
-
value: customDateTo,
|
|
12009
|
-
onChange: (e) => setCustomDateTo(e.target.value),
|
|
12010
|
-
className: "w-full rounded-lg border border-border bg-background px-2 py-1 text-xs outline-none"
|
|
12011
|
-
}
|
|
12012
|
-
)
|
|
12013
|
-
] }),
|
|
12014
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "flex justify-end gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12015
|
-
Button,
|
|
12016
|
-
{
|
|
12017
|
-
color: "primary",
|
|
12018
|
-
size: "sm",
|
|
12019
|
-
onClick: handleCustomDateApply,
|
|
12020
|
-
className: "h-7 text-xs px-2.5",
|
|
12021
|
-
children: "Apply"
|
|
12022
|
-
}
|
|
12023
|
-
) })
|
|
12024
|
-
] })
|
|
12025
|
-
] }),
|
|
12026
|
-
activeMenu === "ltv" && /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
12027
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12028
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "relative shrink-0", children: [
|
|
12029
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(
|
|
12030
|
-
"button",
|
|
12031
|
-
{
|
|
12032
|
-
type: "button",
|
|
12033
|
-
onClick: () => setLtvOperatorOpen(!isLtvOperatorOpen),
|
|
12034
|
-
className: "flex h-9 items-center gap-1 rounded-lg border border-border bg-background px-2.5 text-xs font-normal text-muted-foreground hover:bg-muted/50 hover:text-foreground outline-none whitespace-nowrap",
|
|
12035
|
-
children: [
|
|
12036
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { children: OPERATORS.find((op) => op.id === ltvOperator)?.label.replace("...", "") }),
|
|
12037
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.ChevronDownIcon, { className: "size-3" })
|
|
12038
|
-
]
|
|
12039
|
-
}
|
|
12040
|
-
),
|
|
12041
|
-
isLtvOperatorOpen && /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "absolute left-0 top-full z-50 mt-1 w-32 rounded-lg border border-border bg-popover p-1 shadow-md", children: OPERATORS.map((op) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12042
|
-
"button",
|
|
12043
|
-
{
|
|
12044
|
-
type: "button",
|
|
12045
|
-
onClick: () => {
|
|
12046
|
-
setLtvOperator(op.id);
|
|
12047
|
-
setLtvOperatorOpen(false);
|
|
12048
|
-
},
|
|
12049
|
-
className: "w-full rounded-md px-2 py-1 text-left text-xs text-foreground hover:bg-muted outline-none",
|
|
12050
|
-
children: op.label
|
|
12051
|
-
},
|
|
12052
|
-
op.id
|
|
12053
|
-
)) })
|
|
12054
|
-
] }),
|
|
12055
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12056
|
-
"input",
|
|
12057
|
-
{
|
|
12058
|
-
type: "text",
|
|
12059
|
-
placeholder: "0.00",
|
|
12060
|
-
value: ltvValue,
|
|
12061
|
-
onChange: (e) => setLtvValue(e.target.value),
|
|
12062
|
-
className: "h-9 flex-1 min-w-0 rounded-lg border border-border bg-background px-3 py-1 text-sm outline-none placeholder:text-muted-foreground/60"
|
|
12063
|
-
}
|
|
12064
|
-
)
|
|
12065
|
-
] }),
|
|
12066
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex items-center justify-end gap-2 pt-1 border-t border-border/40", children: [
|
|
12067
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12068
|
-
Button,
|
|
12069
|
-
{
|
|
12070
|
-
variant: "ghost",
|
|
12071
|
-
size: "sm",
|
|
12072
|
-
onClick: handleLtvClear,
|
|
12073
|
-
className: "text-muted-foreground hover:text-foreground h-8 px-3",
|
|
12074
|
-
children: "Clear"
|
|
12075
|
-
}
|
|
12076
|
-
),
|
|
12077
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12078
|
-
Button,
|
|
12079
|
-
{
|
|
12080
|
-
color: "primary",
|
|
12081
|
-
size: "sm",
|
|
12082
|
-
onClick: handleLtvApply,
|
|
12083
|
-
className: "h-8 px-3",
|
|
12084
|
-
children: "Apply"
|
|
12085
|
-
}
|
|
12086
|
-
)
|
|
12087
|
-
] })
|
|
12088
|
-
] }),
|
|
12089
|
-
activeMenu === "outstanding" && /* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
12090
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12091
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)("div", { className: "relative shrink-0", children: [
|
|
12092
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsxs)(
|
|
12093
|
-
"button",
|
|
12094
|
-
{
|
|
12095
|
-
type: "button",
|
|
12096
|
-
onClick: () => setOutstandingOperatorOpen(!isOutstandingOperatorOpen),
|
|
12097
|
-
className: "flex h-9 items-center gap-1 rounded-lg border border-border bg-background px-2.5 text-xs font-normal text-muted-foreground hover:bg-muted/50 hover:text-foreground outline-none whitespace-nowrap",
|
|
12098
|
-
children: [
|
|
12099
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)("span", { children: OPERATORS.find((op) => op.id === outstandingOperator)?.label.replace("...", "") }),
|
|
12100
|
-
/* @__PURE__ */ (0, import_jsx_runtime106.jsx)(import_lucide_react24.ChevronDownIcon, { className: "size-3" })
|
|
12101
|
-
]
|
|
12102
|
-
}
|
|
12103
|
-
),
|
|
12104
|
-
isOutstandingOperatorOpen && /* @__PURE__ */ (0, import_jsx_runtime106.jsx)("div", { className: "absolute left-0 top-full z-50 mt-1 w-32 rounded-lg border border-border bg-popover p-1 shadow-md", children: OPERATORS.map((op) => /* @__PURE__ */ (0, import_jsx_runtime106.jsx)(
|
|
12105
|
-
"button",
|
|
12106
|
-
{
|
|
12107
|
-
type: "button",
|
|
12108
|
-
onClick: () => {
|
|
12109
|
-
setOutstandingOperator(op.id);
|
|
12110
|
-
setOutstandingOperatorOpen(false);
|
|
12111
|
-
},
|
|
12112
|
-
className: "w-full rounded-md px-2 py-1 text-left text-xs text-foreground hover:bg-muted outline-none",
|
|
12113
|
-
children: op.label
|
|
12114
|
-
},
|
|
12115
|
-
op.id
|
|
12116
|
-
)) })
|
|
12067
|
+
} else if (field.type === "text") {
|
|
12068
|
+
const text = asText(v);
|
|
12069
|
+
if (text) {
|
|
12070
|
+
chips.push({
|
|
12071
|
+
id: field.id,
|
|
12072
|
+
label: `${field.label}: ${text}`,
|
|
12073
|
+
remove: () => commit(field.id, "")
|
|
12074
|
+
});
|
|
12075
|
+
}
|
|
12076
|
+
} else if (field.type === "numeric") {
|
|
12077
|
+
const n = asNumeric(v);
|
|
12078
|
+
if (n.value) {
|
|
12079
|
+
chips.push({
|
|
12080
|
+
id: field.id,
|
|
12081
|
+
label: `${field.label} ${OPERATOR_SYMBOL[n.operator]} ${n.value}`,
|
|
12082
|
+
remove: () => commit(field.id, null)
|
|
12083
|
+
});
|
|
12084
|
+
}
|
|
12085
|
+
} else if (field.type === "daterange") {
|
|
12086
|
+
const d = asDate(v);
|
|
12087
|
+
if (d.preset) {
|
|
12088
|
+
const presetLabel = d.preset === "custom" ? `${d.from || "\u2026"} \u2013 ${d.to || "\u2026"}` : (field.presets ?? DEFAULT_PRESETS).find((p) => p.id === d.preset)?.label ?? d.preset;
|
|
12089
|
+
chips.push({
|
|
12090
|
+
id: field.id,
|
|
12091
|
+
label: `${field.label}: ${presetLabel}`,
|
|
12092
|
+
remove: () => commit(field.id, { preset: null })
|
|
12093
|
+
});
|
|
12094
|
+
}
|
|
12095
|
+
}
|
|
12096
|
+
}
|
|
12097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [
|
|
12098
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
12099
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12100
|
+
Button,
|
|
12101
|
+
{
|
|
12102
|
+
variant: "outline",
|
|
12103
|
+
size: "sm",
|
|
12104
|
+
className: "border-dashed font-medium text-muted-foreground hover:text-foreground",
|
|
12105
|
+
iconLeading: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(import_lucide_react25.ListFilterIcon, { className: "size-4" }),
|
|
12106
|
+
children: label
|
|
12107
|
+
}
|
|
12108
|
+
) }),
|
|
12109
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12110
|
+
PopoverContent,
|
|
12111
|
+
{
|
|
12112
|
+
variant: "list",
|
|
12113
|
+
align,
|
|
12114
|
+
className: "overflow-visible border-none bg-transparent p-0 shadow-none max-w-[calc(100vw-32px)] md:max-w-none",
|
|
12115
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "relative flex flex-col md:flex-row items-stretch md:items-start w-[calc(100vw-32px)] max-w-[340px] md:w-auto md:max-w-none", children: [
|
|
12116
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "w-full md:w-56 rounded-xl border border-border bg-popover p-1.5 shadow-lg", children: fields.map((field) => {
|
|
12117
|
+
const isActive = activeId === field.id;
|
|
12118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
|
|
12119
|
+
"button",
|
|
12120
|
+
{
|
|
12121
|
+
type: "button",
|
|
12122
|
+
className: cn(
|
|
12123
|
+
"flex w-full items-center justify-between rounded-lg px-3 py-2 text-sm text-left transition-colors outline-none",
|
|
12124
|
+
isActive ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
|
|
12125
|
+
),
|
|
12126
|
+
onMouseEnter: () => !isMobile && setActiveId(field.id),
|
|
12127
|
+
onClick: () => setActiveId(field.id),
|
|
12128
|
+
children: [
|
|
12129
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "flex items-center gap-2", children: [
|
|
12130
|
+
field.icon,
|
|
12131
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { children: field.label })
|
|
12117
12132
|
] }),
|
|
12118
|
-
/* @__PURE__ */ (0,
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12127
|
-
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12133
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(import_lucide_react25.ChevronRightIcon, { className: "size-4 text-muted-foreground/50" })
|
|
12134
|
+
]
|
|
12135
|
+
},
|
|
12136
|
+
field.id
|
|
12137
|
+
);
|
|
12138
|
+
}) }),
|
|
12139
|
+
activeField && /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12140
|
+
"div",
|
|
12141
|
+
{
|
|
12142
|
+
className: "relative left-0 mt-2 w-full md:absolute md:left-[calc(100%+6px)] md:w-80 rounded-xl border border-border bg-popover p-3 shadow-lg transition-all duration-150 md:mt-0",
|
|
12143
|
+
style: isMobile ? {} : { top: `${activeIdx * 36 + 6}px` },
|
|
12144
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12145
|
+
FilterFieldControl,
|
|
12146
|
+
{
|
|
12147
|
+
field: activeField,
|
|
12148
|
+
value: values[activeField.id],
|
|
12149
|
+
onChange: (next) => commit(activeField.id, next),
|
|
12150
|
+
onClose: () => setIsOpen(false)
|
|
12151
|
+
}
|
|
12152
|
+
)
|
|
12153
|
+
}
|
|
12154
|
+
)
|
|
12155
|
+
] })
|
|
12156
|
+
}
|
|
12157
|
+
)
|
|
12158
|
+
] }),
|
|
12159
|
+
showActiveChips && chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(FilterChip, { label: chip.label, onRemove: chip.remove }, chip.id)),
|
|
12160
|
+
showActiveChips && chips.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12161
|
+
"button",
|
|
12162
|
+
{
|
|
12163
|
+
type: "button",
|
|
12164
|
+
onClick: clearAll,
|
|
12165
|
+
className: "rounded-full px-3 py-1 text-sm font-medium text-muted-foreground outline-none transition-colors hover:text-foreground",
|
|
12166
|
+
children: "Clear all"
|
|
12167
|
+
}
|
|
12168
|
+
)
|
|
12169
|
+
] });
|
|
12170
|
+
}
|
|
12171
|
+
function FilterChip({ label, onRemove }) {
|
|
12172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "inline-flex h-9 items-center gap-1.5 rounded-full border border-border bg-muted/40 pl-3 pr-1.5 text-sm font-medium text-foreground", children: [
|
|
12173
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "truncate", children: label }),
|
|
12174
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12175
|
+
"button",
|
|
12176
|
+
{
|
|
12177
|
+
type: "button",
|
|
12178
|
+
onClick: onRemove,
|
|
12179
|
+
"aria-label": `Remove ${label}`,
|
|
12180
|
+
className: "flex size-5 items-center justify-center rounded-full text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground",
|
|
12181
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(import_lucide_react25.XIcon, { className: "size-3.5" })
|
|
12182
|
+
}
|
|
12183
|
+
)
|
|
12184
|
+
] });
|
|
12185
|
+
}
|
|
12186
|
+
function FilterFieldControl({
|
|
12187
|
+
field,
|
|
12188
|
+
value,
|
|
12189
|
+
onChange,
|
|
12190
|
+
onClose
|
|
12191
|
+
}) {
|
|
12192
|
+
switch (field.type) {
|
|
12193
|
+
case "multiselect":
|
|
12194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(MultiSelectControl, { field, value: asArray(value), onChange });
|
|
12195
|
+
case "text":
|
|
12196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(TextControl, { field, value: asText(value), onChange, onClose });
|
|
12197
|
+
case "daterange":
|
|
12198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(DateRangeControl, { field, value: asDate(value), onChange, onClose });
|
|
12199
|
+
case "numeric":
|
|
12200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(NumericControl, { field, value: asNumeric(value), onChange, onClose });
|
|
12201
|
+
default:
|
|
12202
|
+
return null;
|
|
12203
|
+
}
|
|
12204
|
+
}
|
|
12205
|
+
function MultiSelectControl({
|
|
12206
|
+
field,
|
|
12207
|
+
value,
|
|
12208
|
+
onChange
|
|
12209
|
+
}) {
|
|
12210
|
+
const options = field.options ?? [];
|
|
12211
|
+
const [search, setSearch] = (0, import_react73.useState)("");
|
|
12212
|
+
const searchable = field.searchable ?? options.length > 8;
|
|
12213
|
+
const filtered = (0, import_react73.useMemo)(() => {
|
|
12214
|
+
if (!search) return options;
|
|
12215
|
+
const q = search.toLowerCase();
|
|
12216
|
+
return options.filter(
|
|
12217
|
+
(o) => o.label.toLowerCase().includes(q) || o.hint?.toLowerCase().includes(q)
|
|
12218
|
+
);
|
|
12219
|
+
}, [options, search]);
|
|
12220
|
+
const toggle = (optionValue) => {
|
|
12221
|
+
onChange(
|
|
12222
|
+
value.includes(optionValue) ? value.filter((v) => v !== optionValue) : [...value, optionValue]
|
|
12223
|
+
);
|
|
12224
|
+
};
|
|
12225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
12226
|
+
searchable && /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12227
|
+
SearchInput,
|
|
12228
|
+
{
|
|
12229
|
+
placeholder: field.searchPlaceholder ?? "Search\u2026",
|
|
12230
|
+
value: search,
|
|
12231
|
+
onChange: (e) => setSearch(e.target.value),
|
|
12232
|
+
className: "w-full min-w-0"
|
|
12233
|
+
}
|
|
12234
|
+
),
|
|
12235
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "flex max-h-48 flex-col gap-1 overflow-y-auto pr-1", children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("p", { className: "py-4 text-center text-xs text-muted-foreground", children: "No options found" }) : filtered.map((option) => /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
|
|
12236
|
+
"label",
|
|
12237
|
+
{
|
|
12238
|
+
className: "flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 transition-colors hover:bg-muted/50",
|
|
12239
|
+
children: [
|
|
12240
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12241
|
+
Checkbox,
|
|
12242
|
+
{
|
|
12243
|
+
checked: value.includes(option.value),
|
|
12244
|
+
onCheckedChange: () => toggle(option.value)
|
|
12153
12245
|
}
|
|
12154
|
-
)
|
|
12155
|
-
|
|
12246
|
+
),
|
|
12247
|
+
option.icon,
|
|
12248
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("span", { className: "flex min-w-0 flex-col", children: [
|
|
12249
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "truncate text-sm font-medium text-foreground", children: option.label }),
|
|
12250
|
+
option.hint && /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: option.hint })
|
|
12251
|
+
] })
|
|
12252
|
+
]
|
|
12253
|
+
},
|
|
12254
|
+
option.value
|
|
12255
|
+
)) })
|
|
12256
|
+
] });
|
|
12257
|
+
}
|
|
12258
|
+
function TextControl({
|
|
12259
|
+
field,
|
|
12260
|
+
value,
|
|
12261
|
+
onChange,
|
|
12262
|
+
onClose
|
|
12263
|
+
}) {
|
|
12264
|
+
const [draft, setDraft] = (0, import_react73.useState)(value);
|
|
12265
|
+
(0, import_react73.useEffect)(() => setDraft(value), [value]);
|
|
12266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
12267
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12268
|
+
"input",
|
|
12269
|
+
{
|
|
12270
|
+
type: "text",
|
|
12271
|
+
placeholder: field.placeholder ?? "Type a value\u2026",
|
|
12272
|
+
value: draft,
|
|
12273
|
+
onChange: (e) => setDraft(e.target.value),
|
|
12274
|
+
onKeyDown: (e) => {
|
|
12275
|
+
if (e.key === "Enter") {
|
|
12276
|
+
onChange(draft);
|
|
12277
|
+
onClose();
|
|
12278
|
+
}
|
|
12279
|
+
},
|
|
12280
|
+
className: controlClass({ size: "sm" }, "w-full")
|
|
12281
|
+
}
|
|
12282
|
+
),
|
|
12283
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12284
|
+
ApplyClear,
|
|
12285
|
+
{
|
|
12286
|
+
onClear: () => {
|
|
12287
|
+
setDraft("");
|
|
12288
|
+
onChange("");
|
|
12289
|
+
onClose();
|
|
12290
|
+
},
|
|
12291
|
+
onApply: () => {
|
|
12292
|
+
onChange(draft);
|
|
12293
|
+
onClose();
|
|
12294
|
+
}
|
|
12156
12295
|
}
|
|
12157
12296
|
)
|
|
12158
|
-
] })
|
|
12297
|
+
] });
|
|
12298
|
+
}
|
|
12299
|
+
function DateRangeControl({
|
|
12300
|
+
field,
|
|
12301
|
+
value,
|
|
12302
|
+
onChange,
|
|
12303
|
+
onClose
|
|
12304
|
+
}) {
|
|
12305
|
+
const presets = field.presets ?? DEFAULT_PRESETS;
|
|
12306
|
+
const [from, setFrom] = (0, import_react73.useState)(value.from ?? "");
|
|
12307
|
+
const [to, setTo] = (0, import_react73.useState)(value.to ?? "");
|
|
12308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
12309
|
+
presets.map((preset) => {
|
|
12310
|
+
const isSelected = value.preset === preset.id;
|
|
12311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(
|
|
12312
|
+
"button",
|
|
12313
|
+
{
|
|
12314
|
+
type: "button",
|
|
12315
|
+
onClick: () => {
|
|
12316
|
+
if (preset.id === "custom") {
|
|
12317
|
+
onChange({ preset: "custom", from, to });
|
|
12318
|
+
} else {
|
|
12319
|
+
onChange({ preset: preset.id });
|
|
12320
|
+
onClose();
|
|
12321
|
+
}
|
|
12322
|
+
},
|
|
12323
|
+
className: cn(
|
|
12324
|
+
"flex w-full items-center justify-between rounded-lg px-2.5 py-1.5 text-left text-sm transition-colors outline-none",
|
|
12325
|
+
isSelected ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/50 hover:text-foreground"
|
|
12326
|
+
),
|
|
12327
|
+
children: [
|
|
12328
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { children: preset.label }),
|
|
12329
|
+
preset.hint && /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "text-xs text-muted-foreground/70", children: preset.hint })
|
|
12330
|
+
]
|
|
12331
|
+
},
|
|
12332
|
+
preset.id
|
|
12333
|
+
);
|
|
12334
|
+
}),
|
|
12335
|
+
value.preset === "custom" && /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "mt-2 flex flex-col gap-2 border-t border-border/40 pt-2", children: [
|
|
12336
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12337
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12338
|
+
"input",
|
|
12339
|
+
{
|
|
12340
|
+
type: "date",
|
|
12341
|
+
value: from,
|
|
12342
|
+
onChange: (e) => setFrom(e.target.value),
|
|
12343
|
+
className: controlClass({ size: "sm" }, "w-full text-xs")
|
|
12344
|
+
}
|
|
12345
|
+
),
|
|
12346
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("span", { className: "text-xs text-muted-foreground", children: "to" }),
|
|
12347
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12348
|
+
"input",
|
|
12349
|
+
{
|
|
12350
|
+
type: "date",
|
|
12351
|
+
value: to,
|
|
12352
|
+
onChange: (e) => setTo(e.target.value),
|
|
12353
|
+
className: controlClass({ size: "sm" }, "w-full text-xs")
|
|
12354
|
+
}
|
|
12355
|
+
)
|
|
12356
|
+
] }),
|
|
12357
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12358
|
+
Button,
|
|
12359
|
+
{
|
|
12360
|
+
color: "primary",
|
|
12361
|
+
size: "sm",
|
|
12362
|
+
className: "h-8 px-3",
|
|
12363
|
+
onClick: () => {
|
|
12364
|
+
onChange({ preset: "custom", from, to });
|
|
12365
|
+
onClose();
|
|
12366
|
+
},
|
|
12367
|
+
children: "Apply"
|
|
12368
|
+
}
|
|
12369
|
+
) })
|
|
12370
|
+
] })
|
|
12371
|
+
] });
|
|
12372
|
+
}
|
|
12373
|
+
function NumericControl({
|
|
12374
|
+
field,
|
|
12375
|
+
value,
|
|
12376
|
+
onChange,
|
|
12377
|
+
onClose
|
|
12378
|
+
}) {
|
|
12379
|
+
const operators = field.operators ?? DEFAULT_OPERATORS;
|
|
12380
|
+
const [operator, setOperator] = (0, import_react73.useState)(value.operator);
|
|
12381
|
+
const [draft, setDraft] = (0, import_react73.useState)(value.value);
|
|
12382
|
+
(0, import_react73.useEffect)(() => {
|
|
12383
|
+
setOperator(value.operator);
|
|
12384
|
+
setDraft(value.value);
|
|
12385
|
+
}, [value.operator, value.value]);
|
|
12386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex flex-col gap-2.5", children: [
|
|
12387
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12388
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsxs)(Select, { value: operator, onValueChange: (v) => setOperator(v), children: [
|
|
12389
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(SelectTrigger, { size: "sm", className: "shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(SelectValue, {}) }),
|
|
12390
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(SelectContent, { children: operators.map((op) => /* @__PURE__ */ (0, import_jsx_runtime107.jsx)(SelectItem, { value: op.id, children: op.label }, op.id)) })
|
|
12391
|
+
] }),
|
|
12392
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12393
|
+
"input",
|
|
12394
|
+
{
|
|
12395
|
+
type: "text",
|
|
12396
|
+
inputMode: "decimal",
|
|
12397
|
+
placeholder: field.placeholder ?? "0.00",
|
|
12398
|
+
value: draft,
|
|
12399
|
+
onChange: (e) => setDraft(e.target.value),
|
|
12400
|
+
onKeyDown: (e) => {
|
|
12401
|
+
if (e.key === "Enter") {
|
|
12402
|
+
onChange(draft ? { operator, value: draft } : null);
|
|
12403
|
+
onClose();
|
|
12404
|
+
}
|
|
12405
|
+
},
|
|
12406
|
+
className: controlClass({ size: "sm" }, "min-w-0 flex-1")
|
|
12407
|
+
}
|
|
12408
|
+
)
|
|
12409
|
+
] }),
|
|
12410
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12411
|
+
ApplyClear,
|
|
12412
|
+
{
|
|
12413
|
+
onClear: () => {
|
|
12414
|
+
setDraft("");
|
|
12415
|
+
onChange(null);
|
|
12416
|
+
onClose();
|
|
12417
|
+
},
|
|
12418
|
+
onApply: () => {
|
|
12419
|
+
onChange(draft ? { operator, value: draft } : null);
|
|
12420
|
+
onClose();
|
|
12421
|
+
}
|
|
12422
|
+
}
|
|
12423
|
+
)
|
|
12424
|
+
] });
|
|
12425
|
+
}
|
|
12426
|
+
function ApplyClear({ onClear, onApply }) {
|
|
12427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime107.jsxs)("div", { className: "flex items-center justify-end gap-2 border-t border-border/40 pt-1", children: [
|
|
12428
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(
|
|
12429
|
+
Button,
|
|
12430
|
+
{
|
|
12431
|
+
variant: "ghost",
|
|
12432
|
+
size: "sm",
|
|
12433
|
+
onClick: onClear,
|
|
12434
|
+
className: "h-8 px-3 text-muted-foreground hover:text-foreground",
|
|
12435
|
+
children: "Clear"
|
|
12436
|
+
}
|
|
12437
|
+
),
|
|
12438
|
+
/* @__PURE__ */ (0, import_jsx_runtime107.jsx)(Button, { color: "primary", size: "sm", onClick: onApply, className: "h-8 px-3", children: "Apply" })
|
|
12439
|
+
] });
|
|
12159
12440
|
}
|
|
12160
12441
|
|
|
12161
12442
|
// src/app/data/DataTable.tsx
|
|
12162
12443
|
var import_react74 = require("react");
|
|
12163
|
-
var
|
|
12444
|
+
var import_lucide_react26 = require("lucide-react");
|
|
12164
12445
|
|
|
12165
12446
|
// src/ui/skeleton.tsx
|
|
12166
|
-
var
|
|
12447
|
+
var import_jsx_runtime108 = require("react/jsx-runtime");
|
|
12167
12448
|
function Skeleton({ className, ...props }) {
|
|
12168
|
-
return /* @__PURE__ */ (0,
|
|
12449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(
|
|
12169
12450
|
"div",
|
|
12170
12451
|
{
|
|
12171
12452
|
"data-slot": "skeleton",
|
|
@@ -12176,7 +12457,7 @@ function Skeleton({ className, ...props }) {
|
|
|
12176
12457
|
}
|
|
12177
12458
|
|
|
12178
12459
|
// src/app/data/DataTable.tsx
|
|
12179
|
-
var
|
|
12460
|
+
var import_jsx_runtime109 = require("react/jsx-runtime");
|
|
12180
12461
|
var shellClass2 = "w-full";
|
|
12181
12462
|
var tableClass = "w-full border-separate border-spacing-0 bg-transparent text-sm";
|
|
12182
12463
|
var headRowClass = "";
|
|
@@ -12219,12 +12500,12 @@ function SortIndicator({
|
|
|
12219
12500
|
}) {
|
|
12220
12501
|
const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
|
|
12221
12502
|
if (!active) {
|
|
12222
|
-
return /* @__PURE__ */ (0,
|
|
12503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(import_lucide_react26.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
|
|
12223
12504
|
}
|
|
12224
12505
|
if (direction === "desc") {
|
|
12225
|
-
return /* @__PURE__ */ (0,
|
|
12506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(import_lucide_react26.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
|
|
12226
12507
|
}
|
|
12227
|
-
return /* @__PURE__ */ (0,
|
|
12508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(import_lucide_react26.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
|
|
12228
12509
|
}
|
|
12229
12510
|
function DataTable({
|
|
12230
12511
|
columns,
|
|
@@ -12322,7 +12603,7 @@ function DataTable({
|
|
|
12322
12603
|
const headPad = dense ? "px-3 py-2" : void 0;
|
|
12323
12604
|
const colSpan = columns.length + (selectable ? 1 : 0);
|
|
12324
12605
|
if (!loading && rows.length === 0 && emptyMode === "replace") {
|
|
12325
|
-
return /* @__PURE__ */ (0,
|
|
12606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(EmptyState, { title: emptyTitle, description: emptyDescription, className });
|
|
12326
12607
|
}
|
|
12327
12608
|
const allKeys = sortedRows.map(getRowKey);
|
|
12328
12609
|
const allSelected = allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));
|
|
@@ -12347,10 +12628,10 @@ function DataTable({
|
|
|
12347
12628
|
const hasPager = paginated && !loading && sortedRows.length > 0;
|
|
12348
12629
|
const hasFoot = (showRowCount || footer || hasPager) && (loading || sortedRows.length > 0);
|
|
12349
12630
|
const skeletonCount = loadingRows ?? pageSize ?? 5;
|
|
12350
|
-
return /* @__PURE__ */ (0,
|
|
12351
|
-
caption ? /* @__PURE__ */ (0,
|
|
12352
|
-
/* @__PURE__ */ (0,
|
|
12353
|
-
selectable ? /* @__PURE__ */ (0,
|
|
12631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("table", { className: tableClass, children: [
|
|
12632
|
+
caption ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("caption", { className: "sr-only", children: caption }) : null,
|
|
12633
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)("thead", { className: cn(headRowClass, stickyHeader && stickyHeadClass), children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("tr", { children: [
|
|
12634
|
+
selectable ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("th", { scope: "col", className: cn(selectCellClass, headPad), children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12354
12635
|
Checkbox,
|
|
12355
12636
|
{
|
|
12356
12637
|
checked: headerCheckedState,
|
|
@@ -12362,19 +12643,19 @@ function DataTable({
|
|
|
12362
12643
|
columns.map((col) => {
|
|
12363
12644
|
const isSorted = sort?.columnId === col.id;
|
|
12364
12645
|
const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
|
|
12365
|
-
const headerContent = col.sortable ? /* @__PURE__ */ (0,
|
|
12646
|
+
const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
|
|
12366
12647
|
"button",
|
|
12367
12648
|
{
|
|
12368
12649
|
type: "button",
|
|
12369
12650
|
className: sortButtonClass,
|
|
12370
12651
|
onClick: () => setSort(nextSort(sort, col.id)),
|
|
12371
12652
|
children: [
|
|
12372
|
-
/* @__PURE__ */ (0,
|
|
12373
|
-
/* @__PURE__ */ (0,
|
|
12653
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)("span", { className: "truncate", children: col.header }),
|
|
12654
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
|
|
12374
12655
|
]
|
|
12375
12656
|
}
|
|
12376
12657
|
) : col.header;
|
|
12377
|
-
return /* @__PURE__ */ (0,
|
|
12658
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12378
12659
|
"th",
|
|
12379
12660
|
{
|
|
12380
12661
|
scope: "col",
|
|
@@ -12391,9 +12672,9 @@ function DataTable({
|
|
|
12391
12672
|
);
|
|
12392
12673
|
})
|
|
12393
12674
|
] }) }),
|
|
12394
|
-
/* @__PURE__ */ (0,
|
|
12395
|
-
selectable ? /* @__PURE__ */ (0,
|
|
12396
|
-
columns.map((col) => /* @__PURE__ */ (0,
|
|
12675
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: loading ? Array.from({ length: skeletonCount }).map((_, rowIdx) => /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("tr", { className: rowClass, "aria-hidden": true, children: [
|
|
12676
|
+
selectable ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("td", { className: cn(selectCellClass, cellPad), children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(Skeleton, { className: "size-4 rounded-[4px]" }) }) : null,
|
|
12677
|
+
columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12397
12678
|
"td",
|
|
12398
12679
|
{
|
|
12399
12680
|
className: cn(
|
|
@@ -12402,17 +12683,17 @@ function DataTable({
|
|
|
12402
12683
|
col.align && alignClass[col.align],
|
|
12403
12684
|
col.className
|
|
12404
12685
|
),
|
|
12405
|
-
children: /* @__PURE__ */ (0,
|
|
12686
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(Skeleton, { className: "h-4 w-[60%]" })
|
|
12406
12687
|
},
|
|
12407
12688
|
col.id
|
|
12408
12689
|
))
|
|
12409
|
-
] }, `skeleton-${rowIdx}`)) : visibleRows.length === 0 ? /* @__PURE__ */ (0,
|
|
12410
|
-
/* @__PURE__ */ (0,
|
|
12411
|
-
emptyDescription ? /* @__PURE__ */ (0,
|
|
12690
|
+
] }, `skeleton-${rowIdx}`)) : visibleRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("td", { colSpan, className: emptyCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
|
|
12691
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)("p", { className: "font-medium text-foreground", children: emptyTitle }),
|
|
12692
|
+
emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
|
|
12412
12693
|
] }) }) }) : visibleRows.map((row) => {
|
|
12413
12694
|
const key = getRowKey(row);
|
|
12414
12695
|
const isSelected = selectedSet.has(key);
|
|
12415
|
-
return /* @__PURE__ */ (0,
|
|
12696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
|
|
12416
12697
|
"tr",
|
|
12417
12698
|
{
|
|
12418
12699
|
className: rowClass,
|
|
@@ -12428,12 +12709,12 @@ function DataTable({
|
|
|
12428
12709
|
tabIndex: onRowClick ? 0 : void 0,
|
|
12429
12710
|
role: onRowClick ? "button" : void 0,
|
|
12430
12711
|
children: [
|
|
12431
|
-
selectable ? /* @__PURE__ */ (0,
|
|
12712
|
+
selectable ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12432
12713
|
"td",
|
|
12433
12714
|
{
|
|
12434
12715
|
className: cn(selectCellClass, cellPad),
|
|
12435
12716
|
onClick: (event) => event.stopPropagation(),
|
|
12436
|
-
children: /* @__PURE__ */ (0,
|
|
12717
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12437
12718
|
Checkbox,
|
|
12438
12719
|
{
|
|
12439
12720
|
checked: isSelected,
|
|
@@ -12443,7 +12724,7 @@ function DataTable({
|
|
|
12443
12724
|
)
|
|
12444
12725
|
}
|
|
12445
12726
|
) : null,
|
|
12446
|
-
columns.map((col) => /* @__PURE__ */ (0,
|
|
12727
|
+
columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12447
12728
|
"td",
|
|
12448
12729
|
{
|
|
12449
12730
|
className: cn(
|
|
@@ -12453,7 +12734,7 @@ function DataTable({
|
|
|
12453
12734
|
col.align && alignClass[col.align],
|
|
12454
12735
|
col.className
|
|
12455
12736
|
),
|
|
12456
|
-
children: col.truncate ? /* @__PURE__ */ (0,
|
|
12737
|
+
children: col.truncate ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("div", { className: "truncate", children: col.cell(row) }) : col.cell(row)
|
|
12457
12738
|
},
|
|
12458
12739
|
col.id
|
|
12459
12740
|
))
|
|
@@ -12462,7 +12743,7 @@ function DataTable({
|
|
|
12462
12743
|
key
|
|
12463
12744
|
);
|
|
12464
12745
|
}) }),
|
|
12465
|
-
hasFoot ? /* @__PURE__ */ (0,
|
|
12746
|
+
hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("tfoot", { children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)("td", { colSpan, className: footCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)(
|
|
12466
12747
|
"div",
|
|
12467
12748
|
{
|
|
12468
12749
|
className: cn(
|
|
@@ -12470,18 +12751,18 @@ function DataTable({
|
|
|
12470
12751
|
(showRowCount || footer || hasPager) && "justify-between"
|
|
12471
12752
|
),
|
|
12472
12753
|
children: [
|
|
12473
|
-
/* @__PURE__ */ (0,
|
|
12474
|
-
showRowCount ? /* @__PURE__ */ (0,
|
|
12754
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: footInnerClass, children: [
|
|
12755
|
+
showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("span", { children: [
|
|
12475
12756
|
rowCountText,
|
|
12476
12757
|
selectable && selectedSet.size > 0 ? ` \xB7 ${selectedSet.size} selected` : null
|
|
12477
|
-
] }) : selectable && selectedSet.size > 0 ? /* @__PURE__ */ (0,
|
|
12758
|
+
] }) : selectable && selectedSet.size > 0 ? /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("span", { children: [
|
|
12478
12759
|
selectedSet.size,
|
|
12479
12760
|
" selected"
|
|
12480
12761
|
] }) : null,
|
|
12481
12762
|
footer
|
|
12482
12763
|
] }),
|
|
12483
|
-
hasPager ? /* @__PURE__ */ (0,
|
|
12484
|
-
/* @__PURE__ */ (0,
|
|
12764
|
+
hasPager ? /* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12765
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("span", { className: "tabular-nums", children: [
|
|
12485
12766
|
pageIndex * pageSize + 1,
|
|
12486
12767
|
"\u2013",
|
|
12487
12768
|
Math.min(
|
|
@@ -12492,8 +12773,8 @@ function DataTable({
|
|
|
12492
12773
|
"of ",
|
|
12493
12774
|
sortedRows.length
|
|
12494
12775
|
] }),
|
|
12495
|
-
/* @__PURE__ */ (0,
|
|
12496
|
-
/* @__PURE__ */ (0,
|
|
12776
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
12777
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12497
12778
|
"button",
|
|
12498
12779
|
{
|
|
12499
12780
|
type: "button",
|
|
@@ -12501,10 +12782,10 @@ function DataTable({
|
|
|
12501
12782
|
onClick: () => setPage(pageIndex - 1),
|
|
12502
12783
|
disabled: pageIndex <= 0,
|
|
12503
12784
|
"aria-label": "Previous page",
|
|
12504
|
-
children: /* @__PURE__ */ (0,
|
|
12785
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(import_lucide_react26.ChevronLeftIcon, { className: "size-4", "aria-hidden": true })
|
|
12505
12786
|
}
|
|
12506
12787
|
),
|
|
12507
|
-
/* @__PURE__ */ (0,
|
|
12788
|
+
/* @__PURE__ */ (0, import_jsx_runtime109.jsx)(
|
|
12508
12789
|
"button",
|
|
12509
12790
|
{
|
|
12510
12791
|
type: "button",
|
|
@@ -12512,7 +12793,7 @@ function DataTable({
|
|
|
12512
12793
|
onClick: () => setPage(pageIndex + 1),
|
|
12513
12794
|
disabled: pageIndex >= pageCount - 1,
|
|
12514
12795
|
"aria-label": "Next page",
|
|
12515
|
-
children: /* @__PURE__ */ (0,
|
|
12796
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime109.jsx)(import_lucide_react26.ChevronRightIcon, { className: "size-4", "aria-hidden": true })
|
|
12516
12797
|
}
|
|
12517
12798
|
)
|
|
12518
12799
|
] })
|
|
@@ -12525,7 +12806,7 @@ function DataTable({
|
|
|
12525
12806
|
|
|
12526
12807
|
// src/app/data/ChartPanel.tsx
|
|
12527
12808
|
var import_react75 = require("react");
|
|
12528
|
-
var
|
|
12809
|
+
var import_jsx_runtime110 = require("react/jsx-runtime");
|
|
12529
12810
|
var ChartPanel = ({
|
|
12530
12811
|
title,
|
|
12531
12812
|
description,
|
|
@@ -12543,14 +12824,14 @@ var ChartPanel = ({
|
|
|
12543
12824
|
const titleId = (0, import_react75.useId)();
|
|
12544
12825
|
const resolvedTitle = title ?? artifact?.title;
|
|
12545
12826
|
const hasHeader = Boolean(resolvedTitle || description || actions);
|
|
12546
|
-
const body = loading ? /* @__PURE__ */ (0,
|
|
12547
|
-
return /* @__PURE__ */ (0,
|
|
12827
|
+
const body = loading ? /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(Skeleton, { className: "w-full rounded-lg", style: { height }, "aria-hidden": true }) : children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(ChartArtifactView, { artifact, embedded: true, height }) : null);
|
|
12828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime110.jsxs)(
|
|
12548
12829
|
"section",
|
|
12549
12830
|
{
|
|
12550
12831
|
className: cn(metricCardShellClass, "aui-app-chart-panel", className),
|
|
12551
12832
|
"aria-labelledby": resolvedTitle ? titleId : void 0,
|
|
12552
12833
|
children: [
|
|
12553
|
-
/* @__PURE__ */ (0,
|
|
12834
|
+
/* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
|
|
12554
12835
|
MetricCardHeader,
|
|
12555
12836
|
{
|
|
12556
12837
|
title: resolvedTitle,
|
|
@@ -12559,14 +12840,14 @@ var ChartPanel = ({
|
|
|
12559
12840
|
actions
|
|
12560
12841
|
}
|
|
12561
12842
|
),
|
|
12562
|
-
/* @__PURE__ */ (0,
|
|
12843
|
+
/* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
|
|
12563
12844
|
"div",
|
|
12564
12845
|
{
|
|
12565
12846
|
className: cn(
|
|
12566
12847
|
"relative min-h-0 w-full",
|
|
12567
12848
|
hasHeader ? metricChartPlotRegionClass : chartPanelBodyClass
|
|
12568
12849
|
),
|
|
12569
|
-
children: body ?? /* @__PURE__ */ (0,
|
|
12850
|
+
children: body ?? /* @__PURE__ */ (0, import_jsx_runtime110.jsx)(
|
|
12570
12851
|
"div",
|
|
12571
12852
|
{
|
|
12572
12853
|
className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
|
|
@@ -12584,7 +12865,7 @@ var ChartPanel = ({
|
|
|
12584
12865
|
|
|
12585
12866
|
// src/app/data/MetricRow.tsx
|
|
12586
12867
|
var import_react76 = require("react");
|
|
12587
|
-
var
|
|
12868
|
+
var import_jsx_runtime111 = require("react/jsx-runtime");
|
|
12588
12869
|
var MetricRow = ({
|
|
12589
12870
|
title,
|
|
12590
12871
|
titleTag,
|
|
@@ -12610,13 +12891,13 @@ var MetricRow = ({
|
|
|
12610
12891
|
onMetricChange?.(id);
|
|
12611
12892
|
};
|
|
12612
12893
|
const hasHeader = Boolean(title || titleTag || description || actions);
|
|
12613
|
-
return /* @__PURE__ */ (0,
|
|
12894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
|
|
12614
12895
|
"section",
|
|
12615
12896
|
{
|
|
12616
12897
|
className: cn(metricCardShellClass, className),
|
|
12617
12898
|
"aria-labelledby": title ? titleId : void 0,
|
|
12618
12899
|
children: [
|
|
12619
|
-
/* @__PURE__ */ (0,
|
|
12900
|
+
/* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
|
|
12620
12901
|
MetricCardHeader,
|
|
12621
12902
|
{
|
|
12622
12903
|
title,
|
|
@@ -12626,7 +12907,7 @@ var MetricRow = ({
|
|
|
12626
12907
|
actions
|
|
12627
12908
|
}
|
|
12628
12909
|
),
|
|
12629
|
-
/* @__PURE__ */ (0,
|
|
12910
|
+
/* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
|
|
12630
12911
|
"div",
|
|
12631
12912
|
{
|
|
12632
12913
|
role: selectable ? "group" : void 0,
|
|
@@ -12637,18 +12918,18 @@ var MetricRow = ({
|
|
|
12637
12918
|
metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
|
|
12638
12919
|
hasHeader && "mt-3.5 border-t border-border/40"
|
|
12639
12920
|
),
|
|
12640
|
-
children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ (0,
|
|
12921
|
+
children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsxs)(
|
|
12641
12922
|
"div",
|
|
12642
12923
|
{
|
|
12643
12924
|
className: cn("flex min-w-0 flex-1 flex-col gap-2", metricTileClass),
|
|
12644
12925
|
"aria-hidden": true,
|
|
12645
12926
|
children: [
|
|
12646
|
-
/* @__PURE__ */ (0,
|
|
12647
|
-
/* @__PURE__ */ (0,
|
|
12927
|
+
/* @__PURE__ */ (0, import_jsx_runtime111.jsx)(Skeleton, { className: "h-3 w-20" }),
|
|
12928
|
+
/* @__PURE__ */ (0, import_jsx_runtime111.jsx)(Skeleton, { className: "h-7 w-24" })
|
|
12648
12929
|
]
|
|
12649
12930
|
},
|
|
12650
12931
|
`skeleton-${index}`
|
|
12651
|
-
)) : metrics.map((m, index) => /* @__PURE__ */ (0,
|
|
12932
|
+
)) : metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime111.jsx)(
|
|
12652
12933
|
MetricTile,
|
|
12653
12934
|
{
|
|
12654
12935
|
label: m.label,
|
|
@@ -12676,7 +12957,7 @@ var MetricRow = ({
|
|
|
12676
12957
|
|
|
12677
12958
|
// src/app/data/MetricChartCard.tsx
|
|
12678
12959
|
var import_react77 = require("react");
|
|
12679
|
-
var
|
|
12960
|
+
var import_jsx_runtime112 = require("react/jsx-runtime");
|
|
12680
12961
|
var MetricChartCard = ({
|
|
12681
12962
|
title,
|
|
12682
12963
|
titleTag,
|
|
@@ -12712,13 +12993,13 @@ var MetricChartCard = ({
|
|
|
12712
12993
|
};
|
|
12713
12994
|
const hasHeader = Boolean(title || titleTag || description || actions);
|
|
12714
12995
|
const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
|
|
12715
|
-
return /* @__PURE__ */ (0,
|
|
12996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime112.jsxs)(
|
|
12716
12997
|
"section",
|
|
12717
12998
|
{
|
|
12718
12999
|
className: cn(metricCardShellClass, className),
|
|
12719
13000
|
"aria-labelledby": title ? titleId : void 0,
|
|
12720
13001
|
children: [
|
|
12721
|
-
/* @__PURE__ */ (0,
|
|
13002
|
+
/* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12722
13003
|
MetricCardHeader,
|
|
12723
13004
|
{
|
|
12724
13005
|
title,
|
|
@@ -12728,7 +13009,7 @@ var MetricChartCard = ({
|
|
|
12728
13009
|
titleId
|
|
12729
13010
|
}
|
|
12730
13011
|
),
|
|
12731
|
-
/* @__PURE__ */ (0,
|
|
13012
|
+
/* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12732
13013
|
"div",
|
|
12733
13014
|
{
|
|
12734
13015
|
role: "group",
|
|
@@ -12739,18 +13020,18 @@ var MetricChartCard = ({
|
|
|
12739
13020
|
metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
|
|
12740
13021
|
hasHeader && "mt-3.5 border-t border-border/40"
|
|
12741
13022
|
),
|
|
12742
|
-
children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ (0,
|
|
13023
|
+
children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime112.jsxs)(
|
|
12743
13024
|
"div",
|
|
12744
13025
|
{
|
|
12745
13026
|
className: cn("flex min-w-0 flex-1 flex-col gap-2", metricTileClass),
|
|
12746
13027
|
"aria-hidden": true,
|
|
12747
13028
|
children: [
|
|
12748
|
-
/* @__PURE__ */ (0,
|
|
12749
|
-
/* @__PURE__ */ (0,
|
|
13029
|
+
/* @__PURE__ */ (0, import_jsx_runtime112.jsx)(Skeleton, { className: "h-3 w-20" }),
|
|
13030
|
+
/* @__PURE__ */ (0, import_jsx_runtime112.jsx)(Skeleton, { className: "h-7 w-24" })
|
|
12750
13031
|
]
|
|
12751
13032
|
},
|
|
12752
13033
|
`skeleton-${index}`
|
|
12753
|
-
)) : metrics.map((m, index) => /* @__PURE__ */ (0,
|
|
13034
|
+
)) : metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12754
13035
|
MetricTile,
|
|
12755
13036
|
{
|
|
12756
13037
|
label: m.label,
|
|
@@ -12771,14 +13052,14 @@ var MetricChartCard = ({
|
|
|
12771
13052
|
))
|
|
12772
13053
|
}
|
|
12773
13054
|
),
|
|
12774
|
-
/* @__PURE__ */ (0,
|
|
13055
|
+
/* @__PURE__ */ (0, import_jsx_runtime112.jsx)("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12775
13056
|
Skeleton,
|
|
12776
13057
|
{
|
|
12777
13058
|
className: "w-full rounded-lg",
|
|
12778
13059
|
style: { height },
|
|
12779
13060
|
"aria-hidden": true
|
|
12780
13061
|
}
|
|
12781
|
-
) : active?.data && active.data.length > 0 ? /* @__PURE__ */ (0,
|
|
13062
|
+
) : active?.data && active.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12782
13063
|
LineAreaChart,
|
|
12783
13064
|
{
|
|
12784
13065
|
data: active.data,
|
|
@@ -12798,7 +13079,7 @@ var MetricChartCard = ({
|
|
|
12798
13079
|
ariaLabel: chartAriaLabel
|
|
12799
13080
|
},
|
|
12800
13081
|
active.id
|
|
12801
|
-
) : /* @__PURE__ */ (0,
|
|
13082
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime112.jsx)(
|
|
12802
13083
|
"div",
|
|
12803
13084
|
{
|
|
12804
13085
|
className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
|
|
@@ -12904,8 +13185,8 @@ function useLiveQuery(fetcher, options = {}) {
|
|
|
12904
13185
|
|
|
12905
13186
|
// src/ui/untitled-button.tsx
|
|
12906
13187
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
12907
|
-
var
|
|
12908
|
-
var
|
|
13188
|
+
var import_radix_ui10 = require("radix-ui");
|
|
13189
|
+
var import_jsx_runtime113 = require("react/jsx-runtime");
|
|
12909
13190
|
var SOLID_SKEUOMORPHIC_SHADOW2 = "shadow-skeuomorphic-solid";
|
|
12910
13191
|
var BORDERED_SKEUOMORPHIC_SHADOW2 = "shadow-skeuomorphic-bordered";
|
|
12911
13192
|
var untitledButtonVariants = (0, import_class_variance_authority2.cva)(
|
|
@@ -12988,10 +13269,10 @@ var untitledButtonVariants = (0, import_class_variance_authority2.cva)(
|
|
|
12988
13269
|
)
|
|
12989
13270
|
},
|
|
12990
13271
|
size: {
|
|
12991
|
-
sm: "h-
|
|
12992
|
-
md: "h-
|
|
12993
|
-
lg: "h-
|
|
12994
|
-
xl: "h-
|
|
13272
|
+
sm: "h-8 gap-1 rounded-md px-2.5 text-xs",
|
|
13273
|
+
md: "h-9 gap-1.5 rounded-lg px-3 text-sm",
|
|
13274
|
+
lg: "h-10 gap-1.5 rounded-lg px-3.5 text-sm",
|
|
13275
|
+
xl: "h-11 gap-2 rounded-lg px-4 text-base"
|
|
12995
13276
|
}
|
|
12996
13277
|
},
|
|
12997
13278
|
defaultVariants: {
|
|
@@ -13016,8 +13297,8 @@ function UntitledButton({
|
|
|
13016
13297
|
const isDisabled = disabled || isLoading;
|
|
13017
13298
|
const classes = cn(untitledButtonVariants({ color, size }), className);
|
|
13018
13299
|
if (asChild) {
|
|
13019
|
-
return /* @__PURE__ */ (0,
|
|
13020
|
-
|
|
13300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
|
|
13301
|
+
import_radix_ui10.Slot.Root,
|
|
13021
13302
|
{
|
|
13022
13303
|
className: classes,
|
|
13023
13304
|
"aria-disabled": isDisabled ? true : void 0,
|
|
@@ -13027,7 +13308,7 @@ function UntitledButton({
|
|
|
13027
13308
|
}
|
|
13028
13309
|
);
|
|
13029
13310
|
}
|
|
13030
|
-
return /* @__PURE__ */ (0,
|
|
13311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime113.jsxs)(
|
|
13031
13312
|
"button",
|
|
13032
13313
|
{
|
|
13033
13314
|
type,
|
|
@@ -13036,7 +13317,7 @@ function UntitledButton({
|
|
|
13036
13317
|
className: classes,
|
|
13037
13318
|
...props,
|
|
13038
13319
|
children: [
|
|
13039
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
13320
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime113.jsx)(
|
|
13040
13321
|
"span",
|
|
13041
13322
|
{
|
|
13042
13323
|
"aria-hidden": true,
|
|
@@ -13051,8 +13332,8 @@ function UntitledButton({
|
|
|
13051
13332
|
}
|
|
13052
13333
|
|
|
13053
13334
|
// src/ui/banner.tsx
|
|
13054
|
-
var
|
|
13055
|
-
var
|
|
13335
|
+
var import_lucide_react27 = require("lucide-react");
|
|
13336
|
+
var import_jsx_runtime114 = require("react/jsx-runtime");
|
|
13056
13337
|
var bannerSoftClass = {
|
|
13057
13338
|
default: "border-border/50 bg-muted/30 text-foreground/90 dark:bg-muted/15",
|
|
13058
13339
|
primary: "border-primary/15 bg-primary/5 text-primary-800 dark:text-primary-200 [&_[data-banner-icon]]:text-primary",
|
|
@@ -13097,7 +13378,7 @@ function Banner({
|
|
|
13097
13378
|
}) {
|
|
13098
13379
|
const isSolid = variant === "solid";
|
|
13099
13380
|
const isSingleLine = !title;
|
|
13100
|
-
return /* @__PURE__ */ (0,
|
|
13381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime114.jsxs)(
|
|
13101
13382
|
"div",
|
|
13102
13383
|
{
|
|
13103
13384
|
"data-slot": "banner",
|
|
@@ -13112,7 +13393,7 @@ function Banner({
|
|
|
13112
13393
|
),
|
|
13113
13394
|
...props,
|
|
13114
13395
|
children: [
|
|
13115
|
-
icon ? /* @__PURE__ */ (0,
|
|
13396
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
|
|
13116
13397
|
"span",
|
|
13117
13398
|
{
|
|
13118
13399
|
"data-banner-icon": true,
|
|
@@ -13123,9 +13404,9 @@ function Banner({
|
|
|
13123
13404
|
children: icon
|
|
13124
13405
|
}
|
|
13125
13406
|
) : null,
|
|
13126
|
-
/* @__PURE__ */ (0,
|
|
13127
|
-
title ? /* @__PURE__ */ (0,
|
|
13128
|
-
children ? /* @__PURE__ */ (0,
|
|
13407
|
+
/* @__PURE__ */ (0, import_jsx_runtime114.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
13408
|
+
title ? /* @__PURE__ */ (0, import_jsx_runtime114.jsx)("p", { className: "font-medium tracking-tight", children: title }) : null,
|
|
13409
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
|
|
13129
13410
|
"div",
|
|
13130
13411
|
{
|
|
13131
13412
|
className: cn(
|
|
@@ -13136,8 +13417,8 @@ function Banner({
|
|
|
13136
13417
|
}
|
|
13137
13418
|
) : null
|
|
13138
13419
|
] }),
|
|
13139
|
-
actions ? /* @__PURE__ */ (0,
|
|
13140
|
-
onDismiss ? /* @__PURE__ */ (0,
|
|
13420
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime114.jsx)("div", { className: "flex shrink-0 items-center gap-2", children: actions }) : null,
|
|
13421
|
+
onDismiss ? /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(
|
|
13141
13422
|
"button",
|
|
13142
13423
|
{
|
|
13143
13424
|
type: "button",
|
|
@@ -13148,7 +13429,7 @@ function Banner({
|
|
|
13148
13429
|
isSingleLine ? "self-center" : "-mt-0.5",
|
|
13149
13430
|
isSolid ? "opacity-80 hover:bg-background/15 hover:opacity-100" : "text-muted-foreground hover:bg-foreground/10 hover:text-foreground"
|
|
13150
13431
|
),
|
|
13151
|
-
children: /* @__PURE__ */ (0,
|
|
13432
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime114.jsx)(import_lucide_react27.XIcon, { className: "size-4", "aria-hidden": true })
|
|
13152
13433
|
}
|
|
13153
13434
|
) : null
|
|
13154
13435
|
]
|
|
@@ -13157,7 +13438,7 @@ function Banner({
|
|
|
13157
13438
|
}
|
|
13158
13439
|
|
|
13159
13440
|
// src/ui/timeline.tsx
|
|
13160
|
-
var
|
|
13441
|
+
var import_jsx_runtime115 = require("react/jsx-runtime");
|
|
13161
13442
|
var timelineRowGap = {
|
|
13162
13443
|
sm: "pb-4",
|
|
13163
13444
|
default: "pb-6"
|
|
@@ -13190,16 +13471,16 @@ var toneStyles = {
|
|
|
13190
13471
|
}
|
|
13191
13472
|
};
|
|
13192
13473
|
function Timeline({ items, size = "default", className, ...props }) {
|
|
13193
|
-
return /* @__PURE__ */ (0,
|
|
13474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime115.jsx)("ol", { "data-slot": "timeline", className: cn("flex flex-col", className), ...props, children: items.map((item, index) => {
|
|
13194
13475
|
const last = index === items.length - 1;
|
|
13195
13476
|
const tone = item.tone ?? "default";
|
|
13196
13477
|
const styles = toneStyles[tone];
|
|
13197
|
-
return /* @__PURE__ */ (0,
|
|
13478
|
+
return /* @__PURE__ */ (0, import_jsx_runtime115.jsxs)(
|
|
13198
13479
|
"li",
|
|
13199
13480
|
{
|
|
13200
13481
|
className: cn("relative flex gap-3.5 last:pb-0", timelineRowGap[size]),
|
|
13201
13482
|
children: [
|
|
13202
|
-
!last ? /* @__PURE__ */ (0,
|
|
13483
|
+
!last ? /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(
|
|
13203
13484
|
"span",
|
|
13204
13485
|
{
|
|
13205
13486
|
"aria-hidden": true,
|
|
@@ -13209,7 +13490,7 @@ function Timeline({ items, size = "default", className, ...props }) {
|
|
|
13209
13490
|
)
|
|
13210
13491
|
}
|
|
13211
13492
|
) : null,
|
|
13212
|
-
/* @__PURE__ */ (0,
|
|
13493
|
+
/* @__PURE__ */ (0, import_jsx_runtime115.jsx)("div", { className: "relative flex w-5 shrink-0 justify-center pt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(
|
|
13213
13494
|
"span",
|
|
13214
13495
|
{
|
|
13215
13496
|
className: cn(
|
|
@@ -13217,7 +13498,7 @@ function Timeline({ items, size = "default", className, ...props }) {
|
|
|
13217
13498
|
styles.border,
|
|
13218
13499
|
item.icon ? "size-6" : "size-4"
|
|
13219
13500
|
),
|
|
13220
|
-
children: item.icon ? /* @__PURE__ */ (0,
|
|
13501
|
+
children: item.icon ? /* @__PURE__ */ (0, import_jsx_runtime115.jsx)("div", { className: cn("text-xs", styles.icon), children: item.icon }) : /* @__PURE__ */ (0, import_jsx_runtime115.jsx)(
|
|
13221
13502
|
"span",
|
|
13222
13503
|
{
|
|
13223
13504
|
className: cn(
|
|
@@ -13228,12 +13509,12 @@ function Timeline({ items, size = "default", className, ...props }) {
|
|
|
13228
13509
|
)
|
|
13229
13510
|
}
|
|
13230
13511
|
) }),
|
|
13231
|
-
/* @__PURE__ */ (0,
|
|
13232
|
-
/* @__PURE__ */ (0,
|
|
13233
|
-
/* @__PURE__ */ (0,
|
|
13234
|
-
item.meta ? /* @__PURE__ */ (0,
|
|
13512
|
+
/* @__PURE__ */ (0, import_jsx_runtime115.jsxs)("div", { className: "min-w-0 flex-1 pb-0.5", children: [
|
|
13513
|
+
/* @__PURE__ */ (0, import_jsx_runtime115.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
|
|
13514
|
+
/* @__PURE__ */ (0, import_jsx_runtime115.jsx)("p", { className: "text-sm font-normal text-foreground", children: item.title }),
|
|
13515
|
+
item.meta ? /* @__PURE__ */ (0, import_jsx_runtime115.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: item.meta }) : null
|
|
13235
13516
|
] }),
|
|
13236
|
-
item.description ? /* @__PURE__ */ (0,
|
|
13517
|
+
item.description ? /* @__PURE__ */ (0, import_jsx_runtime115.jsx)("p", { className: "mt-0.5 text-[13px] leading-relaxed text-muted-foreground", children: item.description }) : null
|
|
13237
13518
|
] })
|
|
13238
13519
|
]
|
|
13239
13520
|
},
|
|
@@ -13247,8 +13528,8 @@ var React6 = __toESM(require("react"), 1);
|
|
|
13247
13528
|
var import_core2 = require("@dnd-kit/core");
|
|
13248
13529
|
var import_sortable = require("@dnd-kit/sortable");
|
|
13249
13530
|
var import_utilities = require("@dnd-kit/utilities");
|
|
13250
|
-
var
|
|
13251
|
-
var
|
|
13531
|
+
var import_lucide_react28 = require("lucide-react");
|
|
13532
|
+
var import_jsx_runtime116 = require("react/jsx-runtime");
|
|
13252
13533
|
var columnTitleToneClass = {
|
|
13253
13534
|
default: "text-foreground",
|
|
13254
13535
|
primary: "text-blue-600 dark:text-blue-400",
|
|
@@ -13310,7 +13591,7 @@ function SortableCard({
|
|
|
13310
13591
|
transition
|
|
13311
13592
|
};
|
|
13312
13593
|
const dragHandleProps = disabled ? void 0 : { ...attributes, ...listeners2 };
|
|
13313
|
-
return /* @__PURE__ */ (0,
|
|
13594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)(
|
|
13314
13595
|
"div",
|
|
13315
13596
|
{
|
|
13316
13597
|
ref: setNodeRef,
|
|
@@ -13325,7 +13606,7 @@ function SortableCard({
|
|
|
13325
13606
|
className
|
|
13326
13607
|
),
|
|
13327
13608
|
children: [
|
|
13328
|
-
!disabled && dragHandle === "auto" ? /* @__PURE__ */ (0,
|
|
13609
|
+
!disabled && dragHandle === "auto" ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13329
13610
|
"button",
|
|
13330
13611
|
{
|
|
13331
13612
|
type: "button",
|
|
@@ -13333,7 +13614,7 @@ function SortableCard({
|
|
|
13333
13614
|
className: "absolute right-1.5 top-1.5 z-10 grid size-6 cursor-grab touch-none place-items-center rounded-md text-muted-foreground/40 opacity-0 transition hover:bg-foreground/5 hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 group-hover/kanban-card:opacity-100 active:cursor-grabbing",
|
|
13334
13615
|
...attributes,
|
|
13335
13616
|
...listeners2,
|
|
13336
|
-
children: /* @__PURE__ */ (0,
|
|
13617
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_lucide_react28.GripVerticalIcon, { className: "size-4", "aria-hidden": true })
|
|
13337
13618
|
}
|
|
13338
13619
|
) : null,
|
|
13339
13620
|
renderCard(card, { column, isDragging, isOverlay: false, dragHandleProps })
|
|
@@ -13357,7 +13638,7 @@ function KanbanColumnView({
|
|
|
13357
13638
|
}) {
|
|
13358
13639
|
const tone = column.tone ?? "default";
|
|
13359
13640
|
const { setNodeRef, isOver } = (0, import_core2.useDroppable)({ id: column.id, disabled });
|
|
13360
|
-
return /* @__PURE__ */ (0,
|
|
13641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)(
|
|
13361
13642
|
"div",
|
|
13362
13643
|
{
|
|
13363
13644
|
"data-slot": "kanban-column",
|
|
@@ -13367,9 +13648,9 @@ function KanbanColumnView({
|
|
|
13367
13648
|
className
|
|
13368
13649
|
),
|
|
13369
13650
|
children: [
|
|
13370
|
-
renderColumnHeader ? renderColumnHeader(column) : /* @__PURE__ */ (0,
|
|
13371
|
-
/* @__PURE__ */ (0,
|
|
13372
|
-
/* @__PURE__ */ (0,
|
|
13651
|
+
renderColumnHeader ? renderColumnHeader(column) : /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)("div", { className: "flex flex-col gap-0.5 px-1 pb-0.5", children: [
|
|
13652
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
13653
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13373
13654
|
"h3",
|
|
13374
13655
|
{
|
|
13375
13656
|
className: cn(
|
|
@@ -13379,12 +13660,12 @@ function KanbanColumnView({
|
|
|
13379
13660
|
children: column.title
|
|
13380
13661
|
}
|
|
13381
13662
|
),
|
|
13382
|
-
/* @__PURE__ */ (0,
|
|
13383
|
-
column.action ? /* @__PURE__ */ (0,
|
|
13663
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsx)("span", { className: "shrink-0 text-xs font-normal tabular-nums text-muted-foreground/60", children: column.cards.length }),
|
|
13664
|
+
column.action ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)("div", { className: "shrink-0", children: column.action }) : null
|
|
13384
13665
|
] }),
|
|
13385
|
-
column.description ? /* @__PURE__ */ (0,
|
|
13666
|
+
column.description ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)("p", { className: "truncate text-xs text-muted-foreground", children: column.description }) : null
|
|
13386
13667
|
] }),
|
|
13387
|
-
/* @__PURE__ */ (0,
|
|
13668
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_sortable.SortableContext, { items: cardIds, strategy: import_sortable.verticalListSortingStrategy, children: /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13388
13669
|
"div",
|
|
13389
13670
|
{
|
|
13390
13671
|
ref: setNodeRef,
|
|
@@ -13394,9 +13675,9 @@ function KanbanColumnView({
|
|
|
13394
13675
|
densityListClass[density],
|
|
13395
13676
|
isOver && "bg-muted/50"
|
|
13396
13677
|
),
|
|
13397
|
-
children: column.cards.length === 0 ? /* @__PURE__ */ (0,
|
|
13678
|
+
children: column.cards.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)("div", { className: "flex flex-1 items-center justify-center rounded-xl border border-dashed border-border/60 px-2 py-8 text-center text-xs text-muted-foreground/70", children: emptyColumnLabel ?? "Drop here" }) : column.cards.map((card) => {
|
|
13398
13679
|
const id = getCardId(card);
|
|
13399
|
-
return /* @__PURE__ */ (0,
|
|
13680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13400
13681
|
SortableCard,
|
|
13401
13682
|
{
|
|
13402
13683
|
card,
|
|
@@ -13414,7 +13695,7 @@ function KanbanColumnView({
|
|
|
13414
13695
|
})
|
|
13415
13696
|
}
|
|
13416
13697
|
) }),
|
|
13417
|
-
column.footer ? /* @__PURE__ */ (0,
|
|
13698
|
+
column.footer ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)("div", { className: "px-0.5 pt-0.5", children: column.footer }) : null
|
|
13418
13699
|
]
|
|
13419
13700
|
}
|
|
13420
13701
|
);
|
|
@@ -13553,7 +13834,7 @@ function Kanban({
|
|
|
13553
13834
|
onColumnsChange?.(next);
|
|
13554
13835
|
}
|
|
13555
13836
|
};
|
|
13556
|
-
return /* @__PURE__ */ (0,
|
|
13837
|
+
return /* @__PURE__ */ (0, import_jsx_runtime116.jsxs)(
|
|
13557
13838
|
import_core2.DndContext,
|
|
13558
13839
|
{
|
|
13559
13840
|
sensors,
|
|
@@ -13567,7 +13848,7 @@ function Kanban({
|
|
|
13567
13848
|
if (isControlled) setInternal(cloneColumns(columnsProp));
|
|
13568
13849
|
},
|
|
13569
13850
|
children: [
|
|
13570
|
-
/* @__PURE__ */ (0,
|
|
13851
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13571
13852
|
"div",
|
|
13572
13853
|
{
|
|
13573
13854
|
"data-slot": "kanban",
|
|
@@ -13578,7 +13859,7 @@ function Kanban({
|
|
|
13578
13859
|
density === "compact" ? "gap-3" : "gap-4",
|
|
13579
13860
|
className
|
|
13580
13861
|
),
|
|
13581
|
-
children: columns.map((column) => /* @__PURE__ */ (0,
|
|
13862
|
+
children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13582
13863
|
KanbanColumnView,
|
|
13583
13864
|
{
|
|
13584
13865
|
column,
|
|
@@ -13598,7 +13879,7 @@ function Kanban({
|
|
|
13598
13879
|
))
|
|
13599
13880
|
}
|
|
13600
13881
|
),
|
|
13601
|
-
/* @__PURE__ */ (0,
|
|
13882
|
+
/* @__PURE__ */ (0, import_jsx_runtime116.jsx)(import_core2.DragOverlay, { children: activeCard ? /* @__PURE__ */ (0, import_jsx_runtime116.jsx)(
|
|
13602
13883
|
"div",
|
|
13603
13884
|
{
|
|
13604
13885
|
"data-slot": "kanban-card-overlay",
|
|
@@ -13747,8 +14028,8 @@ When you call a tool that returns an artifact (\`make_chart\`, \`ask_question\`,
|
|
|
13747
14028
|
`.trim();
|
|
13748
14029
|
|
|
13749
14030
|
// src/auth/guard.tsx
|
|
13750
|
-
var
|
|
13751
|
-
var
|
|
14031
|
+
var import_lucide_react29 = require("lucide-react");
|
|
14032
|
+
var import_jsx_runtime117 = require("react/jsx-runtime");
|
|
13752
14033
|
var AuthGuard = ({
|
|
13753
14034
|
children,
|
|
13754
14035
|
requireAuth = false,
|
|
@@ -13759,7 +14040,7 @@ var AuthGuard = ({
|
|
|
13759
14040
|
return children;
|
|
13760
14041
|
}
|
|
13761
14042
|
if (loading) {
|
|
13762
|
-
return /* @__PURE__ */ (0,
|
|
14043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)("div", { className: "flex items-center justify-center h-screen", children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_lucide_react29.Loader2, { className: "w-8 h-8 animate-spin" }) });
|
|
13763
14044
|
}
|
|
13764
14045
|
if (requireAuth && !isAuthenticated && !isEmbedded) {
|
|
13765
14046
|
const returnTo = encodeURIComponent(
|
|
@@ -13772,162 +14053,7 @@ var AuthGuard = ({
|
|
|
13772
14053
|
};
|
|
13773
14054
|
|
|
13774
14055
|
// src/index.ts
|
|
13775
|
-
var
|
|
13776
|
-
|
|
13777
|
-
// src/ui/select.tsx
|
|
13778
|
-
var import_radix_ui10 = require("radix-ui");
|
|
13779
|
-
var import_lucide_react29 = require("lucide-react");
|
|
13780
|
-
var import_jsx_runtime117 = require("react/jsx-runtime");
|
|
13781
|
-
function Select({
|
|
13782
|
-
...props
|
|
13783
|
-
}) {
|
|
13784
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.Root, { "data-slot": "select", ...props });
|
|
13785
|
-
}
|
|
13786
|
-
function SelectGroup({
|
|
13787
|
-
...props
|
|
13788
|
-
}) {
|
|
13789
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.Group, { "data-slot": "select-group", ...props });
|
|
13790
|
-
}
|
|
13791
|
-
function SelectValue({
|
|
13792
|
-
...props
|
|
13793
|
-
}) {
|
|
13794
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.Value, { "data-slot": "select-value", ...props });
|
|
13795
|
-
}
|
|
13796
|
-
function SelectTrigger({
|
|
13797
|
-
className,
|
|
13798
|
-
size = "default",
|
|
13799
|
-
children,
|
|
13800
|
-
...props
|
|
13801
|
-
}) {
|
|
13802
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)(
|
|
13803
|
-
import_radix_ui10.Select.Trigger,
|
|
13804
|
-
{
|
|
13805
|
-
"data-slot": "select-trigger",
|
|
13806
|
-
"data-size": size,
|
|
13807
|
-
className: cn(
|
|
13808
|
-
controlClass({ size }),
|
|
13809
|
-
"flex w-fit items-center justify-between gap-2 whitespace-nowrap *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
13810
|
-
className
|
|
13811
|
-
),
|
|
13812
|
-
...props,
|
|
13813
|
-
children: [
|
|
13814
|
-
children,
|
|
13815
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_lucide_react29.ChevronDownIcon, { className: "size-4 opacity-50" }) })
|
|
13816
|
-
]
|
|
13817
|
-
}
|
|
13818
|
-
);
|
|
13819
|
-
}
|
|
13820
|
-
function SelectContent({
|
|
13821
|
-
className,
|
|
13822
|
-
children,
|
|
13823
|
-
position = "popper",
|
|
13824
|
-
...props
|
|
13825
|
-
}) {
|
|
13826
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)(
|
|
13827
|
-
import_radix_ui10.Select.Content,
|
|
13828
|
-
{
|
|
13829
|
-
"data-slot": "select-content",
|
|
13830
|
-
className: cn(
|
|
13831
|
-
overlayListPanelClass,
|
|
13832
|
-
"relative max-h-[var(--radix-select-content-available-height)] min-w-[8rem] origin-[var(--radix-select-content-transform-origin)] overflow-x-hidden overflow-y-auto",
|
|
13833
|
-
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
13834
|
-
className
|
|
13835
|
-
),
|
|
13836
|
-
position,
|
|
13837
|
-
...props,
|
|
13838
|
-
children: [
|
|
13839
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(SelectScrollUpButton, {}),
|
|
13840
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
13841
|
-
import_radix_ui10.Select.Viewport,
|
|
13842
|
-
{
|
|
13843
|
-
className: cn(
|
|
13844
|
-
"p-1",
|
|
13845
|
-
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
13846
|
-
),
|
|
13847
|
-
children
|
|
13848
|
-
}
|
|
13849
|
-
),
|
|
13850
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(SelectScrollDownButton, {})
|
|
13851
|
-
]
|
|
13852
|
-
}
|
|
13853
|
-
) });
|
|
13854
|
-
}
|
|
13855
|
-
function SelectLabel({
|
|
13856
|
-
className,
|
|
13857
|
-
...props
|
|
13858
|
-
}) {
|
|
13859
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
13860
|
-
import_radix_ui10.Select.Label,
|
|
13861
|
-
{
|
|
13862
|
-
"data-slot": "select-label",
|
|
13863
|
-
className: cn("px-2 py-1.5 text-xs font-medium text-muted-foreground", className),
|
|
13864
|
-
...props
|
|
13865
|
-
}
|
|
13866
|
-
);
|
|
13867
|
-
}
|
|
13868
|
-
function SelectItem({
|
|
13869
|
-
className,
|
|
13870
|
-
children,
|
|
13871
|
-
...props
|
|
13872
|
-
}) {
|
|
13873
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsxs)(
|
|
13874
|
-
import_radix_ui10.Select.Item,
|
|
13875
|
-
{
|
|
13876
|
-
"data-slot": "select-item",
|
|
13877
|
-
className: cn(
|
|
13878
|
-
overlayItemClass,
|
|
13879
|
-
"w-full py-1.5 pr-8 pl-2 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
13880
|
-
className
|
|
13881
|
-
),
|
|
13882
|
-
...props,
|
|
13883
|
-
children: [
|
|
13884
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_lucide_react29.CheckIcon, { className: "size-4" }) }) }),
|
|
13885
|
-
/* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_radix_ui10.Select.ItemText, { children })
|
|
13886
|
-
]
|
|
13887
|
-
}
|
|
13888
|
-
);
|
|
13889
|
-
}
|
|
13890
|
-
function SelectSeparator({
|
|
13891
|
-
className,
|
|
13892
|
-
...props
|
|
13893
|
-
}) {
|
|
13894
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
13895
|
-
import_radix_ui10.Select.Separator,
|
|
13896
|
-
{
|
|
13897
|
-
"data-slot": "select-separator",
|
|
13898
|
-
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
13899
|
-
...props
|
|
13900
|
-
}
|
|
13901
|
-
);
|
|
13902
|
-
}
|
|
13903
|
-
function SelectScrollUpButton({
|
|
13904
|
-
className,
|
|
13905
|
-
...props
|
|
13906
|
-
}) {
|
|
13907
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
13908
|
-
import_radix_ui10.Select.ScrollUpButton,
|
|
13909
|
-
{
|
|
13910
|
-
"data-slot": "select-scroll-up-button",
|
|
13911
|
-
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
13912
|
-
...props,
|
|
13913
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_lucide_react29.ChevronUpIcon, { className: "size-4" })
|
|
13914
|
-
}
|
|
13915
|
-
);
|
|
13916
|
-
}
|
|
13917
|
-
function SelectScrollDownButton({
|
|
13918
|
-
className,
|
|
13919
|
-
...props
|
|
13920
|
-
}) {
|
|
13921
|
-
return /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(
|
|
13922
|
-
import_radix_ui10.Select.ScrollDownButton,
|
|
13923
|
-
{
|
|
13924
|
-
"data-slot": "select-scroll-down-button",
|
|
13925
|
-
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
13926
|
-
...props,
|
|
13927
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime117.jsx)(import_lucide_react29.ChevronDownIcon, { className: "size-4" })
|
|
13928
|
-
}
|
|
13929
|
-
);
|
|
13930
|
-
}
|
|
14056
|
+
var import_react84 = require("@assistant-ui/react");
|
|
13931
14057
|
|
|
13932
14058
|
// src/ui/input.tsx
|
|
13933
14059
|
var import_jsx_runtime118 = require("react/jsx-runtime");
|
|
@@ -13961,7 +14087,7 @@ function Textarea({ className, ...props }) {
|
|
|
13961
14087
|
"data-slot": "textarea",
|
|
13962
14088
|
className: cn(
|
|
13963
14089
|
controlSurfaceClass,
|
|
13964
|
-
"min-h-16 w-full resize-y rounded-lg px-
|
|
14090
|
+
"min-h-16 w-full resize-y rounded-lg px-2.5 py-1.5 leading-relaxed",
|
|
13965
14091
|
className
|
|
13966
14092
|
),
|
|
13967
14093
|
...props
|
|
@@ -14220,7 +14346,7 @@ function BreadcrumbEllipsis({
|
|
|
14220
14346
|
"data-slot": "breadcrumb-ellipsis",
|
|
14221
14347
|
role: "presentation",
|
|
14222
14348
|
"aria-hidden": "true",
|
|
14223
|
-
className: cn("flex size-
|
|
14349
|
+
className: cn("flex size-8 items-center justify-center", className),
|
|
14224
14350
|
...props,
|
|
14225
14351
|
children: [
|
|
14226
14352
|
/* @__PURE__ */ (0, import_jsx_runtime125.jsx)(import_lucide_react31.MoreHorizontalIcon, { className: "size-4" }),
|
|
@@ -14356,7 +14482,7 @@ function ToolbarButton({
|
|
|
14356
14482
|
{
|
|
14357
14483
|
"data-slot": "toolbar-button",
|
|
14358
14484
|
className: cn(
|
|
14359
|
-
"inline-flex h-
|
|
14485
|
+
"inline-flex h-7 min-w-7 items-center justify-center rounded-md px-1.5 text-sm font-medium text-foreground outline-none transition-colors",
|
|
14360
14486
|
"hover:bg-muted focus-visible:ring-2 focus-visible:ring-foreground/10 disabled:pointer-events-none disabled:opacity-50",
|
|
14361
14487
|
className
|
|
14362
14488
|
),
|
|
@@ -14399,7 +14525,7 @@ function ToolbarToggleItem({
|
|
|
14399
14525
|
{
|
|
14400
14526
|
"data-slot": "toolbar-toggle-item",
|
|
14401
14527
|
className: cn(
|
|
14402
|
-
"inline-flex h-
|
|
14528
|
+
"inline-flex h-7 min-w-7 items-center justify-center rounded-md px-1.5 text-sm outline-none transition-colors",
|
|
14403
14529
|
"hover:bg-muted focus-visible:ring-2 focus-visible:ring-foreground/10",
|
|
14404
14530
|
"data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
|
|
14405
14531
|
className
|
|
@@ -14417,7 +14543,7 @@ function ToolbarLink({
|
|
|
14417
14543
|
{
|
|
14418
14544
|
"data-slot": "toolbar-link",
|
|
14419
14545
|
className: cn(
|
|
14420
|
-
"inline-flex h-
|
|
14546
|
+
"inline-flex h-7 items-center rounded-md px-1.5 text-sm text-foreground outline-none transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-foreground/10",
|
|
14421
14547
|
className
|
|
14422
14548
|
),
|
|
14423
14549
|
...props
|
|
@@ -14438,7 +14564,7 @@ function Menubar({
|
|
|
14438
14564
|
{
|
|
14439
14565
|
"data-slot": "menubar",
|
|
14440
14566
|
className: cn(
|
|
14441
|
-
"flex h-
|
|
14567
|
+
"flex h-8 items-center gap-1 rounded-lg border border-border bg-gradient-to-b from-elevated-from to-elevated-to p-1 shadow-card",
|
|
14442
14568
|
className
|
|
14443
14569
|
),
|
|
14444
14570
|
...props
|
|
@@ -14459,7 +14585,7 @@ function MenubarTrigger({
|
|
|
14459
14585
|
{
|
|
14460
14586
|
"data-slot": "menubar-trigger",
|
|
14461
14587
|
className: cn(
|
|
14462
|
-
"flex cursor-default items-center rounded-md px-2 py-
|
|
14588
|
+
"flex cursor-default items-center rounded-md px-2 py-0.5 text-sm font-medium outline-none select-none",
|
|
14463
14589
|
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
14464
14590
|
className
|
|
14465
14591
|
),
|
|
@@ -14521,7 +14647,7 @@ function MenubarCheckboxItem({
|
|
|
14521
14647
|
import_radix_ui18.Menubar.CheckboxItem,
|
|
14522
14648
|
{
|
|
14523
14649
|
"data-slot": "menubar-checkbox-item",
|
|
14524
|
-
className: cn(overlayItemClass, "py-1
|
|
14650
|
+
className: cn(overlayItemClass, "py-1 pr-2 pl-8", className),
|
|
14525
14651
|
checked,
|
|
14526
14652
|
...props,
|
|
14527
14653
|
children: [
|
|
@@ -14545,7 +14671,7 @@ function MenubarRadioItem({
|
|
|
14545
14671
|
import_radix_ui18.Menubar.RadioItem,
|
|
14546
14672
|
{
|
|
14547
14673
|
"data-slot": "menubar-radio-item",
|
|
14548
|
-
className: cn(overlayItemClass, "py-1
|
|
14674
|
+
className: cn(overlayItemClass, "py-1 pr-2 pl-8", className),
|
|
14549
14675
|
...props,
|
|
14550
14676
|
children: [
|
|
14551
14677
|
/* @__PURE__ */ (0, import_jsx_runtime128.jsx)("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime128.jsx)(import_radix_ui18.Menubar.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime128.jsx)(import_lucide_react33.CircleIcon, { className: "size-2 fill-current" }) }) }),
|
|
@@ -14831,7 +14957,7 @@ function CommandDialog({
|
|
|
14831
14957
|
{
|
|
14832
14958
|
className: cn("overflow-hidden p-0", className),
|
|
14833
14959
|
showCloseButton,
|
|
14834
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime130.jsx)(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1
|
|
14960
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime130.jsx)(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:size-4 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-1.5 [&_[cmdk-item]_svg]:size-4", children })
|
|
14835
14961
|
}
|
|
14836
14962
|
)
|
|
14837
14963
|
] });
|
|
@@ -14844,7 +14970,7 @@ function CommandInput({
|
|
|
14844
14970
|
"div",
|
|
14845
14971
|
{
|
|
14846
14972
|
"data-slot": "command-input-wrapper",
|
|
14847
|
-
className: "flex h-
|
|
14973
|
+
className: "flex h-9 items-center gap-2 border-b border-border px-2.5",
|
|
14848
14974
|
children: [
|
|
14849
14975
|
/* @__PURE__ */ (0, import_jsx_runtime130.jsx)(import_lucide_react35.SearchIcon, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
14850
14976
|
/* @__PURE__ */ (0, import_jsx_runtime130.jsx)(
|
|
@@ -14852,7 +14978,7 @@ function CommandInput({
|
|
|
14852
14978
|
{
|
|
14853
14979
|
"data-slot": "command-input",
|
|
14854
14980
|
className: cn(
|
|
14855
|
-
"flex h-
|
|
14981
|
+
"flex h-9 w-full rounded-md bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground/70 disabled:cursor-not-allowed disabled:opacity-50",
|
|
14856
14982
|
className
|
|
14857
14983
|
),
|
|
14858
14984
|
...props
|
|
@@ -14882,7 +15008,7 @@ function CommandEmpty({
|
|
|
14882
15008
|
import_cmdk.Command.Empty,
|
|
14883
15009
|
{
|
|
14884
15010
|
"data-slot": "command-empty",
|
|
14885
|
-
className: "py-
|
|
15011
|
+
className: "py-4 text-center text-sm text-muted-foreground",
|
|
14886
15012
|
...props
|
|
14887
15013
|
}
|
|
14888
15014
|
);
|
|
@@ -14896,7 +15022,7 @@ function CommandGroup({
|
|
|
14896
15022
|
{
|
|
14897
15023
|
"data-slot": "command-group",
|
|
14898
15024
|
className: cn(
|
|
14899
|
-
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1
|
|
15025
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
14900
15026
|
className
|
|
14901
15027
|
),
|
|
14902
15028
|
...props
|
|
@@ -14978,12 +15104,12 @@ function Calendar({
|
|
|
14978
15104
|
button_previous: cn(navButtonClass, defaults.button_previous),
|
|
14979
15105
|
button_next: cn(navButtonClass, defaults.button_next),
|
|
14980
15106
|
month_caption: cn(
|
|
14981
|
-
"flex h-
|
|
15107
|
+
"flex h-9 items-center justify-center",
|
|
14982
15108
|
defaults.month_caption
|
|
14983
15109
|
),
|
|
14984
15110
|
caption_label: cn("text-sm font-semibold", defaults.caption_label),
|
|
14985
15111
|
dropdowns: cn(
|
|
14986
|
-
"flex h-
|
|
15112
|
+
"flex h-9 items-center justify-center gap-1.5 text-sm font-semibold",
|
|
14987
15113
|
defaults.dropdowns
|
|
14988
15114
|
),
|
|
14989
15115
|
dropdown_root: cn(
|
|
@@ -14994,17 +15120,17 @@ function Calendar({
|
|
|
14994
15120
|
month_grid: cn("border-separate border-spacing-y-1", defaults.month_grid),
|
|
14995
15121
|
weekdays: cn(defaults.weekdays),
|
|
14996
15122
|
weekday: cn(
|
|
14997
|
-
"size-
|
|
15123
|
+
"size-9 pb-2 text-xs font-medium text-muted-foreground",
|
|
14998
15124
|
defaults.weekday
|
|
14999
15125
|
),
|
|
15000
15126
|
week: cn(defaults.week),
|
|
15001
|
-
week_number_header: cn("size-
|
|
15127
|
+
week_number_header: cn("size-9", defaults.week_number_header),
|
|
15002
15128
|
week_number: cn(
|
|
15003
15129
|
"text-xs text-muted-foreground",
|
|
15004
15130
|
defaults.week_number
|
|
15005
15131
|
),
|
|
15006
15132
|
day: cn(
|
|
15007
|
-
"relative size-
|
|
15133
|
+
"relative size-9 p-0 text-center text-sm focus-within:relative focus-within:z-10",
|
|
15008
15134
|
defaults.day
|
|
15009
15135
|
),
|
|
15010
15136
|
range_start: cn("rounded-l-md", defaults.range_start),
|
|
@@ -15302,7 +15428,7 @@ function InputOTPSlot({
|
|
|
15302
15428
|
"data-slot": "input-otp-slot",
|
|
15303
15429
|
className: cn(
|
|
15304
15430
|
controlSurfaceClass,
|
|
15305
|
-
"relative size-
|
|
15431
|
+
"relative size-8 rounded-none text-center text-sm tabular-nums",
|
|
15306
15432
|
"-ms-px first:ms-0 first:rounded-s-lg last:rounded-e-lg",
|
|
15307
15433
|
"focus-visible:z-10",
|
|
15308
15434
|
className
|
|
@@ -15503,7 +15629,7 @@ function AccordionTrigger({
|
|
|
15503
15629
|
{
|
|
15504
15630
|
"data-slot": "accordion-trigger",
|
|
15505
15631
|
className: cn(
|
|
15506
|
-
"flex flex-1 items-center justify-between gap-4 rounded-md py-
|
|
15632
|
+
"flex flex-1 items-center justify-between gap-4 rounded-md py-3 text-left text-sm font-medium outline-none transition-all",
|
|
15507
15633
|
"focus-visible:ring-2 focus-visible:ring-foreground/10 disabled:pointer-events-none disabled:opacity-50",
|
|
15508
15634
|
"hover:underline [&[data-state=open]>svg]:rotate-180",
|
|
15509
15635
|
className
|
|
@@ -15527,7 +15653,7 @@ function AccordionContent({
|
|
|
15527
15653
|
"data-slot": "accordion-content",
|
|
15528
15654
|
className: "overflow-hidden text-sm text-muted-foreground data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
|
15529
15655
|
...props,
|
|
15530
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime138.jsx)("div", { className: cn("pt-0 pb-
|
|
15656
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime138.jsx)("div", { className: cn("pt-0 pb-3", className), children })
|
|
15531
15657
|
}
|
|
15532
15658
|
);
|
|
15533
15659
|
}
|
|
@@ -15728,10 +15854,10 @@ var sheetContentVariants = (0, import_class_variance_authority5.cva)(
|
|
|
15728
15854
|
{
|
|
15729
15855
|
variants: {
|
|
15730
15856
|
side: {
|
|
15731
|
-
top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top fixed top-4 inset-x-4 mx-auto w-[calc(100vw-2rem)] sm:max-w-lg rounded-2xl p-
|
|
15732
|
-
bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom fixed bottom-4 inset-x-4 mx-auto w-[calc(100vw-2rem)] sm:max-w-lg rounded-2xl p-
|
|
15733
|
-
left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left fixed top-4 bottom-4 left-4 w-[calc(100vw-2rem)] rounded-2xl p-
|
|
15734
|
-
right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right fixed top-4 bottom-4 right-4 w-[calc(100vw-2rem)] rounded-2xl p-
|
|
15857
|
+
top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top fixed top-4 inset-x-4 mx-auto w-[calc(100vw-2rem)] sm:max-w-lg rounded-2xl p-5",
|
|
15858
|
+
bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom fixed bottom-4 inset-x-4 mx-auto w-[calc(100vw-2rem)] sm:max-w-lg rounded-2xl p-5",
|
|
15859
|
+
left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left fixed top-4 bottom-4 left-4 w-[calc(100vw-2rem)] rounded-2xl p-5",
|
|
15860
|
+
right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right fixed top-4 bottom-4 right-4 w-[calc(100vw-2rem)] rounded-2xl p-5"
|
|
15735
15861
|
},
|
|
15736
15862
|
size: {
|
|
15737
15863
|
default: "",
|
|
@@ -16375,7 +16501,7 @@ function ContextMenuSubContent({
|
|
|
16375
16501
|
var import_class_variance_authority7 = require("class-variance-authority");
|
|
16376
16502
|
var import_jsx_runtime151 = require("react/jsx-runtime");
|
|
16377
16503
|
var alertVariants = (0, import_class_variance_authority7.cva)(
|
|
16378
|
-
"relative grid w-full gap-1 rounded-xl border px-
|
|
16504
|
+
"relative grid w-full gap-1 rounded-xl border px-3.5 py-2.5 text-sm [&>svg]:absolute [&>svg]:top-3 [&>svg]:left-3.5 [&>svg]:size-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-10",
|
|
16379
16505
|
{
|
|
16380
16506
|
variants: {
|
|
16381
16507
|
variant: {
|
|
@@ -16433,7 +16559,7 @@ function Card({ className, ...props }) {
|
|
|
16433
16559
|
"data-slot": "card",
|
|
16434
16560
|
className: cn(
|
|
16435
16561
|
TIMBAL_V2_ELEVATED_SURFACE,
|
|
16436
|
-
"flex flex-col gap-
|
|
16562
|
+
"flex flex-col gap-3 rounded-xl py-3 text-card-foreground",
|
|
16437
16563
|
className
|
|
16438
16564
|
),
|
|
16439
16565
|
...props
|
|
@@ -16445,7 +16571,7 @@ function CardHeader({ className, ...props }) {
|
|
|
16445
16571
|
"div",
|
|
16446
16572
|
{
|
|
16447
16573
|
"data-slot": "card-header",
|
|
16448
|
-
className: cn("flex flex-col gap-1.5 px-
|
|
16574
|
+
className: cn("flex flex-col gap-1.5 px-3.5", className),
|
|
16449
16575
|
...props
|
|
16450
16576
|
}
|
|
16451
16577
|
);
|
|
@@ -16471,14 +16597,14 @@ function CardDescription({ className, ...props }) {
|
|
|
16471
16597
|
);
|
|
16472
16598
|
}
|
|
16473
16599
|
function CardContent({ className, ...props }) {
|
|
16474
|
-
return /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { "data-slot": "card-content", className: cn("px-
|
|
16600
|
+
return /* @__PURE__ */ (0, import_jsx_runtime152.jsx)("div", { "data-slot": "card-content", className: cn("px-3.5", className), ...props });
|
|
16475
16601
|
}
|
|
16476
16602
|
function CardFooter({ className, ...props }) {
|
|
16477
16603
|
return /* @__PURE__ */ (0, import_jsx_runtime152.jsx)(
|
|
16478
16604
|
"div",
|
|
16479
16605
|
{
|
|
16480
16606
|
"data-slot": "card-footer",
|
|
16481
|
-
className: cn("flex items-center px-
|
|
16607
|
+
className: cn("flex items-center px-3.5", className),
|
|
16482
16608
|
...props
|
|
16483
16609
|
}
|
|
16484
16610
|
);
|
|
@@ -16548,7 +16674,7 @@ function TableHead({ className, ...props }) {
|
|
|
16548
16674
|
{
|
|
16549
16675
|
"data-slot": "table-head",
|
|
16550
16676
|
className: cn(
|
|
16551
|
-
"h-
|
|
16677
|
+
"h-8 px-2.5 text-left align-middle text-xs font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
16552
16678
|
className
|
|
16553
16679
|
),
|
|
16554
16680
|
...props
|
|
@@ -16561,7 +16687,7 @@ function TableCell({ className, ...props }) {
|
|
|
16561
16687
|
{
|
|
16562
16688
|
"data-slot": "table-cell",
|
|
16563
16689
|
className: cn(
|
|
16564
|
-
"
|
|
16690
|
+
"py-2 px-2.5 align-middle text-sm [&:has([role=checkbox])]:pr-0",
|
|
16565
16691
|
className
|
|
16566
16692
|
),
|
|
16567
16693
|
...props
|
|
@@ -16615,7 +16741,7 @@ function Toast({
|
|
|
16615
16741
|
"data-slot": "toast",
|
|
16616
16742
|
className: cn(
|
|
16617
16743
|
TIMBAL_V2_ELEVATED_SURFACE,
|
|
16618
|
-
"group pointer-events-auto relative flex w-full items-center justify-between gap-3 overflow-hidden rounded-xl p-
|
|
16744
|
+
"group pointer-events-auto relative flex w-full items-center justify-between gap-3 overflow-hidden rounded-xl p-3 pr-7 shadow-card-elevated transition-all",
|
|
16619
16745
|
"data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full data-[state=closed]:slide-out-to-right-full",
|
|
16620
16746
|
variant === "destructive" && "border-destructive/45 bg-destructive/10 text-destructive",
|
|
16621
16747
|
className
|
|
@@ -16936,7 +17062,7 @@ function Rating({
|
|
|
16936
17062
|
const value = isControlled ? valueProp : uncontrolled;
|
|
16937
17063
|
const [hover, setHover] = React11.useState(null);
|
|
16938
17064
|
const interactive = !readOnly && !disabled;
|
|
16939
|
-
const
|
|
17065
|
+
const shown2 = hover ?? value;
|
|
16940
17066
|
const set = (next) => {
|
|
16941
17067
|
if (!interactive) return;
|
|
16942
17068
|
if (!isControlled) setUncontrolled(next);
|
|
@@ -16974,7 +17100,7 @@ function Rating({
|
|
|
16974
17100
|
onMouseLeave: () => setHover(null),
|
|
16975
17101
|
children: Array.from({ length: max }, (_, i) => {
|
|
16976
17102
|
const unit = i + 1;
|
|
16977
|
-
const filled = unit <=
|
|
17103
|
+
const filled = unit <= shown2;
|
|
16978
17104
|
return /* @__PURE__ */ (0, import_jsx_runtime158.jsx)(
|
|
16979
17105
|
"button",
|
|
16980
17106
|
{
|
|
@@ -17107,8 +17233,8 @@ var React13 = __toESM(require("react"), 1);
|
|
|
17107
17233
|
var import_lucide_react47 = require("lucide-react");
|
|
17108
17234
|
var import_jsx_runtime160 = require("react/jsx-runtime");
|
|
17109
17235
|
var tagInputSizeClass = {
|
|
17110
|
-
sm: "min-h-
|
|
17111
|
-
default: "min-h-
|
|
17236
|
+
sm: "min-h-8 gap-1 px-1.5 py-0.5",
|
|
17237
|
+
default: "min-h-9 gap-1 px-2 py-1"
|
|
17112
17238
|
};
|
|
17113
17239
|
function TagInput({
|
|
17114
17240
|
value: valueProp,
|
|
@@ -17216,8 +17342,8 @@ var snippetVariantClass = {
|
|
|
17216
17342
|
ghost: "border-transparent bg-foreground/[0.04]"
|
|
17217
17343
|
};
|
|
17218
17344
|
var snippetSizeClass = {
|
|
17219
|
-
sm: "gap-1.5 py-
|
|
17220
|
-
default: "gap-2 py-1
|
|
17345
|
+
sm: "gap-1.5 py-0.5 pl-2 pr-0.5 text-xs",
|
|
17346
|
+
default: "gap-2 py-1 pl-2.5 pr-1 text-sm"
|
|
17221
17347
|
};
|
|
17222
17348
|
function Snippet({
|
|
17223
17349
|
children,
|
|
@@ -17333,6 +17459,373 @@ function CircularProgress({
|
|
|
17333
17459
|
}
|
|
17334
17460
|
);
|
|
17335
17461
|
}
|
|
17462
|
+
|
|
17463
|
+
// src/site/Reveal.tsx
|
|
17464
|
+
var React14 = __toESM(require("react"), 1);
|
|
17465
|
+
var import_react79 = require("motion/react");
|
|
17466
|
+
|
|
17467
|
+
// src/site/easing.ts
|
|
17468
|
+
var EASE = {
|
|
17469
|
+
/** Strong slow-out — the workhorse for entrances and reveals. */
|
|
17470
|
+
out: [0.16, 1, 0.3, 1],
|
|
17471
|
+
/** Symmetric in-out for loops and continuous motion. */
|
|
17472
|
+
inOut: [0.65, 0, 0.35, 1],
|
|
17473
|
+
/** Gentle in-out, good for parallax / large translations. */
|
|
17474
|
+
soft: [0.4, 0, 0.2, 1]
|
|
17475
|
+
};
|
|
17476
|
+
var DURATION = {
|
|
17477
|
+
fast: 0.4,
|
|
17478
|
+
base: 0.7,
|
|
17479
|
+
slow: 1.1
|
|
17480
|
+
};
|
|
17481
|
+
var SPRING = {
|
|
17482
|
+
/** Tight, responsive follow. */
|
|
17483
|
+
snappy: { stiffness: 350, damping: 30, mass: 0.4 },
|
|
17484
|
+
/** Looser, more elastic follow. */
|
|
17485
|
+
smooth: { stiffness: 150, damping: 20, mass: 0.6 }
|
|
17486
|
+
};
|
|
17487
|
+
|
|
17488
|
+
// src/site/Reveal.tsx
|
|
17489
|
+
var import_jsx_runtime163 = require("react/jsx-runtime");
|
|
17490
|
+
function hidden(variant, distance) {
|
|
17491
|
+
switch (variant) {
|
|
17492
|
+
case "fade":
|
|
17493
|
+
return { opacity: 0 };
|
|
17494
|
+
case "fade-up":
|
|
17495
|
+
return { opacity: 0, y: distance };
|
|
17496
|
+
case "fade-down":
|
|
17497
|
+
return { opacity: 0, y: -distance };
|
|
17498
|
+
case "fade-left":
|
|
17499
|
+
return { opacity: 0, x: distance };
|
|
17500
|
+
case "fade-right":
|
|
17501
|
+
return { opacity: 0, x: -distance };
|
|
17502
|
+
case "blur":
|
|
17503
|
+
return { opacity: 0, filter: "blur(12px)" };
|
|
17504
|
+
case "scale":
|
|
17505
|
+
return { opacity: 0, scale: 0.94 };
|
|
17506
|
+
case "mask-up":
|
|
17507
|
+
return { y: "110%" };
|
|
17508
|
+
}
|
|
17509
|
+
}
|
|
17510
|
+
function shown(variant) {
|
|
17511
|
+
if (variant === "mask-up") return { y: "0%" };
|
|
17512
|
+
if (variant === "blur") return { opacity: 1, filter: "blur(0px)" };
|
|
17513
|
+
if (variant === "scale") return { opacity: 1, scale: 1 };
|
|
17514
|
+
return { opacity: 1, x: 0, y: 0 };
|
|
17515
|
+
}
|
|
17516
|
+
var Reveal = React14.forwardRef(function Reveal2({
|
|
17517
|
+
variant = "fade-up",
|
|
17518
|
+
delay = 0,
|
|
17519
|
+
duration = DURATION.base,
|
|
17520
|
+
distance = 28,
|
|
17521
|
+
amount = 0.3,
|
|
17522
|
+
repeat = false,
|
|
17523
|
+
as = "div",
|
|
17524
|
+
className,
|
|
17525
|
+
children,
|
|
17526
|
+
...rest
|
|
17527
|
+
}, ref) {
|
|
17528
|
+
const reduce = (0, import_react79.useReducedMotion)();
|
|
17529
|
+
const isMask = variant === "mask-up";
|
|
17530
|
+
if (reduce) {
|
|
17531
|
+
const Tag = as;
|
|
17532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime163.jsx)(Tag, { ref, className: cn(isMask && "overflow-hidden", className), ...rest, children });
|
|
17533
|
+
}
|
|
17534
|
+
const variants = {
|
|
17535
|
+
hidden: hidden(variant, distance),
|
|
17536
|
+
shown: shown(variant)
|
|
17537
|
+
};
|
|
17538
|
+
const MotionTag = import_react79.motion[as] ?? import_react79.motion.div;
|
|
17539
|
+
const inner = /* @__PURE__ */ (0, import_jsx_runtime163.jsx)(
|
|
17540
|
+
MotionTag,
|
|
17541
|
+
{
|
|
17542
|
+
ref,
|
|
17543
|
+
className,
|
|
17544
|
+
variants,
|
|
17545
|
+
initial: "hidden",
|
|
17546
|
+
whileInView: "shown",
|
|
17547
|
+
viewport: { once: !repeat, amount },
|
|
17548
|
+
transition: { duration, delay, ease: EASE.out },
|
|
17549
|
+
...rest,
|
|
17550
|
+
children
|
|
17551
|
+
}
|
|
17552
|
+
);
|
|
17553
|
+
if (isMask) {
|
|
17554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime163.jsx)("span", { className: "block overflow-hidden", children: inner });
|
|
17555
|
+
}
|
|
17556
|
+
return inner;
|
|
17557
|
+
});
|
|
17558
|
+
|
|
17559
|
+
// src/site/TextReveal.tsx
|
|
17560
|
+
var React15 = __toESM(require("react"), 1);
|
|
17561
|
+
var import_react80 = require("motion/react");
|
|
17562
|
+
var import_jsx_runtime164 = require("react/jsx-runtime");
|
|
17563
|
+
var tokenVariants = {
|
|
17564
|
+
hidden: { y: "115%" },
|
|
17565
|
+
shown: { y: "0%" }
|
|
17566
|
+
};
|
|
17567
|
+
function TextReveal({
|
|
17568
|
+
children,
|
|
17569
|
+
splitBy = "words",
|
|
17570
|
+
stagger = 0.06,
|
|
17571
|
+
delay = 0,
|
|
17572
|
+
duration = DURATION.base,
|
|
17573
|
+
repeat = false,
|
|
17574
|
+
amount = 0.4,
|
|
17575
|
+
as = "span",
|
|
17576
|
+
className,
|
|
17577
|
+
...rest
|
|
17578
|
+
}) {
|
|
17579
|
+
const reduce = (0, import_react80.useReducedMotion)();
|
|
17580
|
+
const Tag = as;
|
|
17581
|
+
const tokens = React15.useMemo(() => {
|
|
17582
|
+
if (splitBy === "lines") return children.split("\n");
|
|
17583
|
+
return children.split(/(\s+)/).filter((t) => t.length > 0);
|
|
17584
|
+
}, [children, splitBy]);
|
|
17585
|
+
if (reduce) {
|
|
17586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(Tag, { className, ...rest, children });
|
|
17587
|
+
}
|
|
17588
|
+
const containerVariants = {
|
|
17589
|
+
hidden: {},
|
|
17590
|
+
shown: { transition: { staggerChildren: stagger, delayChildren: delay } }
|
|
17591
|
+
};
|
|
17592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(
|
|
17593
|
+
import_react80.motion.span,
|
|
17594
|
+
{
|
|
17595
|
+
variants: containerVariants,
|
|
17596
|
+
initial: "hidden",
|
|
17597
|
+
whileInView: "shown",
|
|
17598
|
+
viewport: { once: !repeat, amount },
|
|
17599
|
+
className: cn(as === "span" ? "inline" : "block", className),
|
|
17600
|
+
...rest,
|
|
17601
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(Tag, { className: as === "span" ? "inline" : "block", children: tokens.map(
|
|
17602
|
+
(token, i) => /^\s+$/.test(token) && splitBy === "words" ? /* @__PURE__ */ (0, import_jsx_runtime164.jsx)("span", { children: " " }, i) : /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(
|
|
17603
|
+
"span",
|
|
17604
|
+
{
|
|
17605
|
+
className: cn(
|
|
17606
|
+
"overflow-hidden",
|
|
17607
|
+
splitBy === "lines" ? "block" : "inline-block align-bottom"
|
|
17608
|
+
),
|
|
17609
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime164.jsx)(
|
|
17610
|
+
import_react80.motion.span,
|
|
17611
|
+
{
|
|
17612
|
+
className: "inline-block",
|
|
17613
|
+
variants: tokenVariants,
|
|
17614
|
+
transition: { duration, ease: EASE.out },
|
|
17615
|
+
children: token
|
|
17616
|
+
}
|
|
17617
|
+
)
|
|
17618
|
+
},
|
|
17619
|
+
i
|
|
17620
|
+
)
|
|
17621
|
+
) })
|
|
17622
|
+
}
|
|
17623
|
+
);
|
|
17624
|
+
}
|
|
17625
|
+
|
|
17626
|
+
// src/site/Parallax.tsx
|
|
17627
|
+
var React16 = __toESM(require("react"), 1);
|
|
17628
|
+
var import_react81 = require("motion/react");
|
|
17629
|
+
var import_jsx_runtime165 = require("react/jsx-runtime");
|
|
17630
|
+
var Parallax = React16.forwardRef(function Parallax2({ speed = 0.2, axis = "y", smooth = true, className, children, style, ...rest }, forwardedRef) {
|
|
17631
|
+
const reduce = (0, import_react81.useReducedMotion)();
|
|
17632
|
+
const innerRef = React16.useRef(null);
|
|
17633
|
+
React16.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
17634
|
+
const { scrollYProgress } = (0, import_react81.useScroll)({
|
|
17635
|
+
target: innerRef,
|
|
17636
|
+
offset: ["start end", "end start"]
|
|
17637
|
+
});
|
|
17638
|
+
const range = 100 * speed;
|
|
17639
|
+
const raw = (0, import_react81.useTransform)(scrollYProgress, [0, 1], [range, -range]);
|
|
17640
|
+
const smoothed = (0, import_react81.useSpring)(raw, { stiffness: 120, damping: 30, mass: 0.4 });
|
|
17641
|
+
const value = smooth ? smoothed : raw;
|
|
17642
|
+
if (reduce) {
|
|
17643
|
+
return /* @__PURE__ */ (0, import_jsx_runtime165.jsx)("div", { ref: innerRef, className, style, ...rest, children });
|
|
17644
|
+
}
|
|
17645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime165.jsx)(
|
|
17646
|
+
import_react81.motion.div,
|
|
17647
|
+
{
|
|
17648
|
+
ref: innerRef,
|
|
17649
|
+
className: cn("will-change-transform", className),
|
|
17650
|
+
style: { ...style, [axis]: value },
|
|
17651
|
+
...rest,
|
|
17652
|
+
children
|
|
17653
|
+
}
|
|
17654
|
+
);
|
|
17655
|
+
});
|
|
17656
|
+
|
|
17657
|
+
// src/site/Marquee.tsx
|
|
17658
|
+
var React17 = __toESM(require("react"), 1);
|
|
17659
|
+
var import_react82 = require("motion/react");
|
|
17660
|
+
var import_jsx_runtime166 = require("react/jsx-runtime");
|
|
17661
|
+
var Marquee = React17.forwardRef(function Marquee2({ speed = 60, direction = "left", pauseOnHover = true, gap = "3rem", className, children, ...rest }, ref) {
|
|
17662
|
+
const reduce = (0, import_react82.useReducedMotion)();
|
|
17663
|
+
const x = (0, import_react82.useMotionValue)(0);
|
|
17664
|
+
const setWidthRef = React17.useRef(0);
|
|
17665
|
+
const groupRef = React17.useRef(null);
|
|
17666
|
+
const [paused, setPaused] = React17.useState(false);
|
|
17667
|
+
React17.useEffect(() => {
|
|
17668
|
+
const el = groupRef.current;
|
|
17669
|
+
if (!el) return;
|
|
17670
|
+
const measure = () => {
|
|
17671
|
+
const gapPx = parseFloat(getComputedStyle(el.parentElement).columnGap || "0") || 0;
|
|
17672
|
+
setWidthRef.current = el.offsetWidth + gapPx;
|
|
17673
|
+
};
|
|
17674
|
+
measure();
|
|
17675
|
+
const ro = new ResizeObserver(measure);
|
|
17676
|
+
ro.observe(el);
|
|
17677
|
+
return () => ro.disconnect();
|
|
17678
|
+
}, []);
|
|
17679
|
+
(0, import_react82.useAnimationFrame)((_, delta) => {
|
|
17680
|
+
if (reduce || paused || setWidthRef.current === 0) return;
|
|
17681
|
+
const dir = direction === "left" ? -1 : 1;
|
|
17682
|
+
const moveBy = speed * delta / 1e3;
|
|
17683
|
+
let next = x.get() + dir * moveBy;
|
|
17684
|
+
const w = setWidthRef.current;
|
|
17685
|
+
if (next <= -w) next += w;
|
|
17686
|
+
else if (next >= w) next -= w;
|
|
17687
|
+
x.set(next);
|
|
17688
|
+
});
|
|
17689
|
+
if (reduce) {
|
|
17690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime166.jsx)(
|
|
17691
|
+
"div",
|
|
17692
|
+
{
|
|
17693
|
+
ref,
|
|
17694
|
+
className: cn("flex w-full items-center overflow-x-auto", className),
|
|
17695
|
+
style: { columnGap: gap },
|
|
17696
|
+
...rest,
|
|
17697
|
+
children
|
|
17698
|
+
}
|
|
17699
|
+
);
|
|
17700
|
+
}
|
|
17701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime166.jsx)(
|
|
17702
|
+
"div",
|
|
17703
|
+
{
|
|
17704
|
+
ref,
|
|
17705
|
+
className: cn("w-full overflow-hidden", className),
|
|
17706
|
+
onMouseEnter: pauseOnHover ? () => setPaused(true) : void 0,
|
|
17707
|
+
onMouseLeave: pauseOnHover ? () => setPaused(false) : void 0,
|
|
17708
|
+
...rest,
|
|
17709
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime166.jsxs)(import_react82.motion.div, { className: "flex w-max flex-nowrap items-center", style: { x, columnGap: gap }, children: [
|
|
17710
|
+
/* @__PURE__ */ (0, import_jsx_runtime166.jsx)("div", { ref: groupRef, className: "flex flex-nowrap items-center", style: { columnGap: gap }, children }),
|
|
17711
|
+
/* @__PURE__ */ (0, import_jsx_runtime166.jsx)("div", { className: "flex flex-nowrap items-center", style: { columnGap: gap }, "aria-hidden": true, children })
|
|
17712
|
+
] })
|
|
17713
|
+
}
|
|
17714
|
+
);
|
|
17715
|
+
});
|
|
17716
|
+
|
|
17717
|
+
// src/site/Magnetic.tsx
|
|
17718
|
+
var React18 = __toESM(require("react"), 1);
|
|
17719
|
+
var import_react83 = require("motion/react");
|
|
17720
|
+
var import_jsx_runtime167 = require("react/jsx-runtime");
|
|
17721
|
+
var Magnetic = React18.forwardRef(function Magnetic2({ strength = 0.35, max = 24, spring = "snappy", className, children, ...rest }, forwardedRef) {
|
|
17722
|
+
const reduce = (0, import_react83.useReducedMotion)();
|
|
17723
|
+
const innerRef = React18.useRef(null);
|
|
17724
|
+
React18.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
17725
|
+
const mvx = (0, import_react83.useMotionValue)(0);
|
|
17726
|
+
const mvy = (0, import_react83.useMotionValue)(0);
|
|
17727
|
+
const x = (0, import_react83.useSpring)(mvx, SPRING[spring]);
|
|
17728
|
+
const y = (0, import_react83.useSpring)(mvy, SPRING[spring]);
|
|
17729
|
+
const clamp3 = (v) => Math.max(-max, Math.min(max, v));
|
|
17730
|
+
function handleMove(e) {
|
|
17731
|
+
if (reduce) return;
|
|
17732
|
+
const el = innerRef.current;
|
|
17733
|
+
if (!el) return;
|
|
17734
|
+
const rect = el.getBoundingClientRect();
|
|
17735
|
+
const cx = rect.left + rect.width / 2;
|
|
17736
|
+
const cy = rect.top + rect.height / 2;
|
|
17737
|
+
mvx.set(clamp3((e.clientX - cx) * strength));
|
|
17738
|
+
mvy.set(clamp3((e.clientY - cy) * strength));
|
|
17739
|
+
}
|
|
17740
|
+
function reset() {
|
|
17741
|
+
mvx.set(0);
|
|
17742
|
+
mvy.set(0);
|
|
17743
|
+
}
|
|
17744
|
+
if (reduce) {
|
|
17745
|
+
return /* @__PURE__ */ (0, import_jsx_runtime167.jsx)("div", { ref: innerRef, className: cn("inline-block", className), ...rest, children });
|
|
17746
|
+
}
|
|
17747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime167.jsx)(
|
|
17748
|
+
import_react83.motion.div,
|
|
17749
|
+
{
|
|
17750
|
+
ref: innerRef,
|
|
17751
|
+
className: cn("inline-block", className),
|
|
17752
|
+
style: { x, y },
|
|
17753
|
+
onMouseMove: handleMove,
|
|
17754
|
+
onMouseLeave: reset,
|
|
17755
|
+
...rest,
|
|
17756
|
+
children
|
|
17757
|
+
}
|
|
17758
|
+
);
|
|
17759
|
+
});
|
|
17760
|
+
|
|
17761
|
+
// src/site/agent-instructions.ts
|
|
17762
|
+
var SITE_AGENT_INSTRUCTIONS = `
|
|
17763
|
+
## Site kit (@timbal-ai/timbal-react/site)
|
|
17764
|
+
|
|
17765
|
+
Expressive **motion & interaction primitives** for marketing, brand, landing, and editorial pages \u2014 the counterpart to \`/app\` (which is for dashboards and operations UIs). Import from \`@timbal-ai/timbal-react/site\` (or the package root).
|
|
17766
|
+
|
|
17767
|
+
These are **mechanics, not art direction**: they animate whatever you put inside them. Compose them under a chosen aesthetic; they do not impose colors, type, or layout.
|
|
17768
|
+
|
|
17769
|
+
### When to use \`/site\` (and when not to)
|
|
17770
|
+
|
|
17771
|
+
- **Do** use \`/site\` for landing pages, hero sections, feature walkthroughs, logo walls, pricing pages, and editorial/brand storytelling.
|
|
17772
|
+
- **Do not** use \`/site\` inside dashboards, settings, tables, or in-thread chat artifacts \u2014 those stay on \`/app\` and \`/artifacts\`. Animated dashboard chrome reads as slop.
|
|
17773
|
+
- Every primitive is **reduced-motion-aware** (collapses to static, no-transform output under \`prefers-reduced-motion\`) and **SSR-safe** (no layout shift \u2014 elements occupy their space from first paint). You never need to guard them yourself.
|
|
17774
|
+
- Built on the \`motion\` engine the package already bundles \u2014 **no extra dependencies**.
|
|
17775
|
+
|
|
17776
|
+
### Dosing (anti-overuse \u2014 read this)
|
|
17777
|
+
|
|
17778
|
+
The failure mode is animating *everything*. Restraint is the brand signal.
|
|
17779
|
+
|
|
17780
|
+
- Pick **one** signature motion per section (e.g. a \`TextReveal\` headline **or** a \`Parallax\` hero image, not both stacked).
|
|
17781
|
+
- Stagger entrances down the page; do not fire ten reveals at once on first paint.
|
|
17782
|
+
- Reserve \`Magnetic\` for **primary** CTAs / nav, not every button.
|
|
17783
|
+
- Keep \`Parallax\` \`speed\` subtle (\`0.15\`\u2013\`0.35\`); large values look gimmicky.
|
|
17784
|
+
- Default durations are intentionally slow and weighted (\`DURATION.base\` = 0.7s) \u2014 that confident pacing is the point. Don't speed everything up to app-kit's 150ms.
|
|
17785
|
+
|
|
17786
|
+
### Component menu
|
|
17787
|
+
|
|
17788
|
+
| Component | Use for | Key props |
|
|
17789
|
+
|-----------|---------|-----------|
|
|
17790
|
+
| \`Reveal\` | Fade/slide a block in as it scrolls into view (headings, cards, images, list items). | \`variant\` (\`fade\` \\| \`fade-up\` \\| \`fade-down\` \\| \`fade-left\` \\| \`fade-right\` \\| \`blur\` \\| \`scale\` \\| \`mask-up\`, default \`fade-up\`), \`delay\`, \`duration\`, \`distance\` (px, default 28), \`amount\` (visibility fraction 0\u20131 / \`"some"\` / \`"all"\`, default 0.3), \`repeat\` (replay on re-enter), \`as\` (render element, e.g. \`"section"\`/\`"li"\`). |
|
|
17791
|
+
| \`TextReveal\` | Signature editorial headline entrance \u2014 text rides up token-by-token from a clip on a stagger. | \`children\` (**plain string only**), \`splitBy\` (\`words\` default \\| \`lines\`), \`stagger\` (default 0.06), \`delay\`, \`duration\`, \`amount\` (default 0.4), \`repeat\`, \`as\` (\`span\` default \\| \`h1\`\u2013\`h4\` \\| \`p\`). |
|
|
17792
|
+
| \`Parallax\` | Depth \u2014 translate a layer relative to scroll (hero images, background art). | \`speed\` (-0.6\u20260.6, positive = lags behind scroll, default 0.2), \`axis\` (\`y\` default \\| \`x\`), \`smooth\` (spring-damped, default true). |
|
|
17793
|
+
| \`Marquee\` | Seamless infinite scrolling row (logo walls, testimonials, ticker). Duplicates children internally \u2014 no visible seam. | \`speed\` (px/s, default 60), \`direction\` (\`left\` default \\| \`right\`), \`pauseOnHover\` (default true), \`gap\` (CSS length, default \`"3rem"\`). |
|
|
17794
|
+
| \`Magnetic\` | Pointer-following "magnetic" affordance for a **single** interactive child (primary CTA, nav link). | \`strength\` (fraction of cursor offset, default 0.35), \`max\` (px clamp, default 24), \`spring\` (\`"snappy"\` default \\| \`"smooth"\`). Wrap one button/link. |
|
|
17795
|
+
|
|
17796
|
+
### Motion tokens
|
|
17797
|
+
|
|
17798
|
+
\`EASE\` (cubic-bezier tuples: \`out\` / \`inOut\` / \`soft\`), \`DURATION\` (\`fast\` 0.4s / \`base\` 0.7s / \`slow\` 1.1s), and \`SPRING\` (\`snappy\` / \`smooth\`) are exported for custom \`motion\` work that should match the kit's feel. Prefer the component defaults; reach for tokens only when hand-rolling a bespoke animation.
|
|
17799
|
+
|
|
17800
|
+
### Example imports
|
|
17801
|
+
|
|
17802
|
+
\`\`\`tsx
|
|
17803
|
+
import { Reveal, TextReveal, Parallax, Marquee, Magnetic } from "@timbal-ai/timbal-react/site";
|
|
17804
|
+
\`\`\`
|
|
17805
|
+
|
|
17806
|
+
\`\`\`tsx
|
|
17807
|
+
<Reveal variant="fade-up" delay={0.1}>
|
|
17808
|
+
<TextReveal as="h1" className="text-6xl font-semibold">
|
|
17809
|
+
Built for the long run
|
|
17810
|
+
</TextReveal>
|
|
17811
|
+
</Reveal>
|
|
17812
|
+
|
|
17813
|
+
<Parallax speed={0.3}>
|
|
17814
|
+
<img src={hero} alt="" className="h-full w-full object-cover" />
|
|
17815
|
+
</Parallax>
|
|
17816
|
+
|
|
17817
|
+
<Magnetic strength={0.4}>
|
|
17818
|
+
<Button>Get started</Button>
|
|
17819
|
+
</Magnetic>
|
|
17820
|
+
\`\`\`
|
|
17821
|
+
|
|
17822
|
+
### Rules
|
|
17823
|
+
|
|
17824
|
+
- \`/site\` is for the **marketing/brand surface**, not the product app shell (\`/app\`) or in-chat widgets (\`/artifacts\`).
|
|
17825
|
+
- \`TextReveal\` takes a **string** child only \u2014 it splits internally; do not pass JSX.
|
|
17826
|
+
- \`Magnetic\` wraps a **single** interactive child; don't wrap whole layouts.
|
|
17827
|
+
- Trust the reduced-motion / SSR handling \u2014 never add your own \`prefers-reduced-motion\` guards around these.
|
|
17828
|
+
`.trim();
|
|
17336
17829
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17337
17830
|
0 && (module.exports = {
|
|
17338
17831
|
APP_KIT_AGENT_INSTRUCTIONS,
|
|
@@ -17445,6 +17938,7 @@ function CircularProgress({
|
|
|
17445
17938
|
ContextMenuTrigger,
|
|
17446
17939
|
CopyButton,
|
|
17447
17940
|
DEFAULT_UPLOAD_ACCEPT,
|
|
17941
|
+
DURATION,
|
|
17448
17942
|
DangerZone,
|
|
17449
17943
|
DangerZoneAction,
|
|
17450
17944
|
DataTable,
|
|
@@ -17478,6 +17972,7 @@ function CircularProgress({
|
|
|
17478
17972
|
DropdownMenuSubContent,
|
|
17479
17973
|
DropdownMenuSubTrigger,
|
|
17480
17974
|
DropdownMenuTrigger,
|
|
17975
|
+
EASE,
|
|
17481
17976
|
EmptyState,
|
|
17482
17977
|
ExpandableSection,
|
|
17483
17978
|
Field,
|
|
@@ -17523,7 +18018,9 @@ function CircularProgress({
|
|
|
17523
18018
|
KbdGroup,
|
|
17524
18019
|
Label,
|
|
17525
18020
|
LineAreaChart,
|
|
18021
|
+
Magnetic,
|
|
17526
18022
|
MarkdownText,
|
|
18023
|
+
Marquee,
|
|
17527
18024
|
MemoPillSegmentedTabs,
|
|
17528
18025
|
Menubar,
|
|
17529
18026
|
MenubarCheckboxItem,
|
|
@@ -17562,6 +18059,7 @@ function CircularProgress({
|
|
|
17562
18059
|
PaginationLink,
|
|
17563
18060
|
PaginationNext,
|
|
17564
18061
|
PaginationPrevious,
|
|
18062
|
+
Parallax,
|
|
17565
18063
|
PieChart,
|
|
17566
18064
|
PillSegmentedTabs,
|
|
17567
18065
|
PlanBadge,
|
|
@@ -17578,8 +18076,11 @@ function CircularProgress({
|
|
|
17578
18076
|
RadioGroupItem,
|
|
17579
18077
|
Rating,
|
|
17580
18078
|
ResourceCard,
|
|
18079
|
+
Reveal,
|
|
17581
18080
|
SEMANTIC_COLOR_TOKENS,
|
|
18081
|
+
SITE_AGENT_INSTRUCTIONS,
|
|
17582
18082
|
SLOP_BUDGETS,
|
|
18083
|
+
SPRING,
|
|
17583
18084
|
STUDIO_NAV_MODE,
|
|
17584
18085
|
ScrollArea,
|
|
17585
18086
|
ScrollBar,
|
|
@@ -17639,6 +18140,7 @@ function CircularProgress({
|
|
|
17639
18140
|
TableHeader,
|
|
17640
18141
|
TableRow,
|
|
17641
18142
|
TagInput,
|
|
18143
|
+
TextReveal,
|
|
17642
18144
|
Textarea,
|
|
17643
18145
|
Thread,
|
|
17644
18146
|
ThreadPrimitive,
|