@arbidocs/react 0.3.100 → 0.3.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,20 @@
1
- import { createContext, useMemo, useContext, useState, useCallback, useRef, useEffect } from 'react';
1
+ import * as React from 'react';
2
+ import React__default, { createContext, forwardRef, useMemo, useContext, useState, useCallback, useEffect, useRef } from 'react';
2
3
  import { Arbi, resolveCitations, summarizeCitations } from '@arbidocs/sdk/browser';
3
4
  export { Arbi, ArbiError } from '@arbidocs/sdk/browser';
4
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
6
  import { useQuery, useMutation, QueryClient, QueryClientProvider } from '@tanstack/react-query';
7
+ import { createPortal } from 'react-dom';
8
+ import { clsx } from 'clsx';
9
+ import { twMerge } from 'tailwind-merge';
10
+ import * as AvatarPrimitive from '@radix-ui/react-avatar';
11
+ import { cva } from 'class-variance-authority';
12
+ import { Slot } from '@radix-ui/react-slot';
13
+ import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
14
+ import { MoreVertical, Eye, FolderOpen, Bot, Calendar, Search, Folder, StickyNote, Hash, List, SquareCheckBig, Package } from 'lucide-react';
15
+ import { AgGridReact } from 'ag-grid-react';
16
+ import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community';
17
+ import { create } from 'zustand';
6
18
 
7
19
  // src/ArbiProvider.tsx
8
20
  var ArbiContext = createContext(null);
@@ -590,7 +602,10 @@ var arbiQueryKeys = {
590
602
  tags: (workspaceId) => ["arbi", "tags", workspaceId],
591
603
  agents: () => ["arbi", "agents"],
592
604
  sessions: () => ["arbi", "sessions"],
593
- health: () => ["arbi", "health"]
605
+ health: () => ["arbi", "health"],
606
+ tasks: () => ["arbi", "tasks"],
607
+ memories: (workspaceId) => ["arbi", "memories", workspaceId],
608
+ configs: () => ["arbi", "configs"]
594
609
  };
595
610
  function useWorkspaces(options) {
596
611
  const arbi = useArbi();
@@ -660,6 +675,30 @@ function useHealth(options) {
660
675
  enabled: options?.enabled
661
676
  });
662
677
  }
678
+ function useTasks(options) {
679
+ const arbi = useArbi();
680
+ return useQuery({
681
+ queryKey: arbiQueryKeys.tasks(),
682
+ queryFn: () => arbi.tasks.list(),
683
+ enabled: options?.enabled ?? arbi.isLoggedIn
684
+ });
685
+ }
686
+ function useMemories(workspaceId, options) {
687
+ const arbi = useArbi();
688
+ return useQuery({
689
+ queryKey: arbiQueryKeys.memories(workspaceId ?? ""),
690
+ queryFn: () => arbi.memory.list({ pinnedOnly: options?.pinnedOnly }),
691
+ enabled: (options?.enabled ?? true) && !!workspaceId && arbi.hasWorkspace
692
+ });
693
+ }
694
+ function useConfigs(options) {
695
+ const arbi = useArbi();
696
+ return useQuery({
697
+ queryKey: arbiQueryKeys.configs(),
698
+ queryFn: () => arbi.agentConfig.list(),
699
+ enabled: options?.enabled ?? arbi.isLoggedIn
700
+ });
701
+ }
663
702
  function WorkspaceScreen({ theme, labels, onSelect }) {
664
703
  const arbi = useArbi();
665
704
  const { data: workspaces, isLoading } = useWorkspaces();
@@ -1079,18 +1118,23 @@ function ChatWidget({ theme, labels, initialWorkspaceId, width, height }) {
1079
1118
  const arbi = useArbi();
1080
1119
  const [screen, setScreen] = useState("auth");
1081
1120
  const [workspaceId, setWorkspaceId] = useState(initialWorkspaceId);
1082
- const handleLogin = useCallback(async () => {
1121
+ const resolveWorkspace = useCallback(async () => {
1083
1122
  if (initialWorkspaceId) {
1084
1123
  try {
1085
1124
  await arbi.selectWorkspace(initialWorkspaceId);
1086
1125
  setScreen("chat");
1126
+ return;
1087
1127
  } catch {
1088
1128
  setScreen("workspace");
1129
+ return;
1089
1130
  }
1090
- } else {
1091
- setScreen("workspace");
1092
1131
  }
1132
+ setScreen("workspace");
1093
1133
  }, [arbi, initialWorkspaceId]);
1134
+ const handleLogin = useCallback(() => resolveWorkspace(), [resolveWorkspace]);
1135
+ useEffect(() => {
1136
+ if (arbi.isLoggedIn) void resolveWorkspace();
1137
+ }, [arbi, resolveWorkspace]);
1094
1138
  const handleWorkspaceSelect = useCallback((id) => {
1095
1139
  setWorkspaceId(id);
1096
1140
  setScreen("chat");
@@ -1124,6 +1168,26 @@ function ChatWidget({ theme, labels, initialWorkspaceId, width, height }) {
1124
1168
  ] })
1125
1169
  ] });
1126
1170
  }
1171
+ function ArbiChatPanel({
1172
+ workspaceId,
1173
+ theme: themeOverrides,
1174
+ labels: labelOverrides,
1175
+ width = "100%",
1176
+ height = "100%"
1177
+ }) {
1178
+ const theme = useMemo(() => getTheme(themeOverrides), [themeOverrides]);
1179
+ const labels = useMemo(() => getLabels(labelOverrides), [labelOverrides]);
1180
+ return /* @__PURE__ */ jsx(
1181
+ ChatWidget,
1182
+ {
1183
+ theme,
1184
+ labels,
1185
+ initialWorkspaceId: workspaceId,
1186
+ width,
1187
+ height
1188
+ }
1189
+ );
1190
+ }
1127
1191
  function ArbiChat({
1128
1192
  url,
1129
1193
  workspaceId,
@@ -1141,20 +1205,1263 @@ function ArbiChat({
1141
1205
  }),
1142
1206
  []
1143
1207
  );
1144
- const theme = useMemo(() => getTheme(themeOverrides), [themeOverrides]);
1145
- const labels = useMemo(() => getLabels(labelOverrides), [labelOverrides]);
1146
1208
  return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx(ArbiProvider, { url, children: /* @__PURE__ */ jsx(
1147
- ChatWidget,
1209
+ ArbiChatPanel,
1148
1210
  {
1149
- theme,
1150
- labels,
1151
- initialWorkspaceId: workspaceId,
1211
+ workspaceId,
1212
+ theme: themeOverrides,
1213
+ labels: labelOverrides,
1152
1214
  width,
1153
1215
  height
1154
1216
  }
1155
1217
  ) }) });
1156
1218
  }
1219
+ function cn(...inputs) {
1220
+ return twMerge(clsx(inputs));
1221
+ }
1222
+ var TooltipContext = React.createContext(null);
1223
+ var TooltipProvider = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
1224
+ function Tooltip({ children, delayDuration = 300 }) {
1225
+ const [open, setOpen] = React.useState(false);
1226
+ const triggerRef = React.useRef(null);
1227
+ const timer = React.useRef(null);
1228
+ const contentId = React.useId();
1229
+ const clearTimer = () => {
1230
+ if (timer.current) {
1231
+ clearTimeout(timer.current);
1232
+ timer.current = null;
1233
+ }
1234
+ };
1235
+ const show = React.useCallback(() => {
1236
+ clearTimer();
1237
+ timer.current = setTimeout(() => setOpen(true), delayDuration);
1238
+ }, [delayDuration]);
1239
+ const hide = React.useCallback(() => {
1240
+ clearTimer();
1241
+ setOpen(false);
1242
+ }, []);
1243
+ const setTrigger = React.useCallback((el) => {
1244
+ triggerRef.current = el;
1245
+ }, []);
1246
+ React.useEffect(() => () => clearTimer(), []);
1247
+ const value = React.useMemo(
1248
+ () => ({ open, show, hide, setTrigger, triggerRef, contentId }),
1249
+ [open, show, hide, setTrigger, contentId]
1250
+ );
1251
+ return /* @__PURE__ */ jsx(TooltipContext.Provider, { value, children });
1252
+ }
1253
+ function TooltipTrigger({ asChild, children, ...props }) {
1254
+ const ctx = React.useContext(TooltipContext);
1255
+ if (!ctx) return /* @__PURE__ */ jsx(Fragment, { children });
1256
+ const triggerHandlers = {
1257
+ onPointerEnter: (e) => {
1258
+ props.onPointerEnter?.(e);
1259
+ ctx.show();
1260
+ },
1261
+ onPointerLeave: (e) => {
1262
+ props.onPointerLeave?.(e);
1263
+ ctx.hide();
1264
+ },
1265
+ onFocus: (e) => {
1266
+ props.onFocus?.(e);
1267
+ ctx.show();
1268
+ },
1269
+ onBlur: (e) => {
1270
+ props.onBlur?.(e);
1271
+ ctx.hide();
1272
+ },
1273
+ "aria-describedby": ctx.open ? ctx.contentId : void 0,
1274
+ "data-state": ctx.open ? "open" : "closed"
1275
+ };
1276
+ if (asChild && React.isValidElement(children)) {
1277
+ const child = children;
1278
+ return React.cloneElement(child, {
1279
+ ...props,
1280
+ ...triggerHandlers,
1281
+ ref: ctx.setTrigger
1282
+ });
1283
+ }
1284
+ return /* @__PURE__ */ jsx(
1285
+ "button",
1286
+ {
1287
+ type: "button",
1288
+ ...props,
1289
+ ...triggerHandlers,
1290
+ ref: ctx.setTrigger,
1291
+ children
1292
+ }
1293
+ );
1294
+ }
1295
+ var TRANSFORM_BY_SIDE = {
1296
+ top: "translate(-50%, -100%)",
1297
+ bottom: "translate(-50%, 0)",
1298
+ left: "translate(-100%, -50%)",
1299
+ right: "translate(0, -50%)"
1300
+ };
1301
+ var TooltipContent = React.forwardRef(
1302
+ ({ className, side = "top", sideOffset = 4, style, ...props }, ref) => {
1303
+ const ctx = React.useContext(TooltipContext);
1304
+ const innerRef = React.useRef(null);
1305
+ const [coords, setCoords] = React.useState(null);
1306
+ React.useLayoutEffect(() => {
1307
+ if (!ctx?.open || !ctx.triggerRef.current) {
1308
+ setCoords(null);
1309
+ return;
1310
+ }
1311
+ const r = ctx.triggerRef.current.getBoundingClientRect();
1312
+ const c = innerRef.current?.getBoundingClientRect();
1313
+ const ch = c?.height ?? 0;
1314
+ const cw = c?.width ?? 0;
1315
+ const vh = window.innerHeight;
1316
+ const vw = window.innerWidth;
1317
+ let s = side;
1318
+ if (s === "top" && r.top - sideOffset - ch < 0) s = "bottom";
1319
+ else if (s === "bottom" && r.bottom + sideOffset + ch > vh) s = "top";
1320
+ else if (s === "left" && r.left - sideOffset - cw < 0) s = "right";
1321
+ else if (s === "right" && r.right + sideOffset + cw > vw) s = "left";
1322
+ setCoords({
1323
+ top: s === "top" ? r.top - sideOffset : s === "bottom" ? r.bottom + sideOffset : r.top + r.height / 2,
1324
+ left: s === "left" ? r.left - sideOffset : s === "right" ? r.right + sideOffset : r.left + r.width / 2,
1325
+ transform: TRANSFORM_BY_SIDE[s]
1326
+ });
1327
+ }, [ctx?.open, side, sideOffset, ctx?.triggerRef]);
1328
+ if (!ctx?.open) return null;
1329
+ const setRefs = (node) => {
1330
+ innerRef.current = node;
1331
+ if (typeof ref === "function") ref(node);
1332
+ else if (ref) ref.current = node;
1333
+ };
1334
+ return createPortal(
1335
+ /* @__PURE__ */ jsx(
1336
+ "div",
1337
+ {
1338
+ ref: setRefs,
1339
+ id: ctx.contentId,
1340
+ role: "tooltip",
1341
+ className: cn("tooltip-content pointer-events-none", className),
1342
+ style: {
1343
+ position: "fixed",
1344
+ top: coords?.top ?? -9999,
1345
+ left: coords?.left ?? -9999,
1346
+ transform: coords?.transform ?? TRANSFORM_BY_SIDE[side],
1347
+ opacity: coords ? void 0 : 0,
1348
+ zIndex: 9999,
1349
+ ...style
1350
+ },
1351
+ ...props
1352
+ }
1353
+ ),
1354
+ document.body
1355
+ );
1356
+ }
1357
+ );
1358
+ TooltipContent.displayName = "TooltipContent";
1359
+ var Avatar = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1360
+ AvatarPrimitive.Root,
1361
+ {
1362
+ ref,
1363
+ className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
1364
+ ...props
1365
+ }
1366
+ ));
1367
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
1368
+ var AvatarImage = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1369
+ AvatarPrimitive.Image,
1370
+ {
1371
+ ref,
1372
+ className: cn("aspect-square h-full w-full", className),
1373
+ ...props
1374
+ }
1375
+ ));
1376
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
1377
+ var AvatarFallback = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
1378
+ AvatarPrimitive.Fallback,
1379
+ {
1380
+ ref,
1381
+ className: cn(
1382
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
1383
+ className
1384
+ ),
1385
+ ...props
1386
+ }
1387
+ ));
1388
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
1389
+ var badgeVariants = cva(
1390
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 text-sm font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
1391
+ {
1392
+ variants: {
1393
+ variant: {
1394
+ default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
1395
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
1396
+ destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
1397
+ outline: "text-foreground"
1398
+ }
1399
+ },
1400
+ defaultVariants: {
1401
+ variant: "default"
1402
+ }
1403
+ }
1404
+ );
1405
+ function Badge({ className, variant, ...props }) {
1406
+ return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
1407
+ }
1408
+ var buttonVariants = cva(
1409
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
1410
+ {
1411
+ variants: {
1412
+ variant: {
1413
+ default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
1414
+ destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
1415
+ outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
1416
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
1417
+ ghost: "hover:bg-accent hover:text-accent-foreground",
1418
+ link: "text-primary underline-offset-4 hover:underline"
1419
+ },
1420
+ size: {
1421
+ default: "h-9 px-4 py-2",
1422
+ sm: "h-8 rounded-md px-3",
1423
+ lg: "h-10 rounded-md px-8",
1424
+ icon: "h-9 w-9"
1425
+ }
1426
+ },
1427
+ defaultVariants: {
1428
+ variant: "default",
1429
+ size: "default"
1430
+ }
1431
+ }
1432
+ );
1433
+ var Button = React.forwardRef(
1434
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
1435
+ const Comp = asChild ? Slot : "button";
1436
+ return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
1437
+ }
1438
+ );
1439
+ Button.displayName = "Button";
1440
+ var HoverCard = HoverCardPrimitive.Root;
1441
+ var HoverCardTrigger = HoverCardPrimitive.Trigger;
1442
+ var HoverCardContent = React.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(HoverCardPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1443
+ HoverCardPrimitive.Content,
1444
+ {
1445
+ ref,
1446
+ align,
1447
+ sideOffset,
1448
+ className: cn(
1449
+ "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
1450
+ className
1451
+ ),
1452
+ ...props
1453
+ }
1454
+ ) }));
1455
+ HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
1456
+
1457
+ // src/icons/colors.ts
1458
+ var NEUTRAL_GRAY = "#64748b";
1459
+ var FILE_TYPE_COLORS = {
1460
+ pdf: "#ef4444",
1461
+ // red
1462
+ img: "#8b5cf6",
1463
+ // violet-500 (images)
1464
+ vid: "#10b981",
1465
+ // emerald-500 (video)
1466
+ aud: "#f59e0b",
1467
+ // amber-500 (audio)
1468
+ eml: "#0d9488",
1469
+ // teal-600 (email)
1470
+ generic: NEUTRAL_GRAY,
1471
+ // gray (unknown)
1472
+ white: "#ffffff"
1473
+ // for strokes/text on colored backgrounds
1474
+ };
1475
+ var PdfIcon = ({ size = 16, className = "" }) => {
1476
+ return /* @__PURE__ */ jsxs(
1477
+ "svg",
1478
+ {
1479
+ width: size,
1480
+ height: size,
1481
+ viewBox: "0 0 24 24",
1482
+ fill: "none",
1483
+ xmlns: "http://www.w3.org/2000/svg",
1484
+ className,
1485
+ children: [
1486
+ /* @__PURE__ */ jsx(
1487
+ "path",
1488
+ {
1489
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1490
+ fill: FILE_TYPE_COLORS.pdf,
1491
+ stroke: FILE_TYPE_COLORS.pdf,
1492
+ strokeWidth: "1",
1493
+ strokeLinecap: "round",
1494
+ strokeLinejoin: "round"
1495
+ }
1496
+ ),
1497
+ /* @__PURE__ */ jsx(
1498
+ "path",
1499
+ {
1500
+ d: "M14 2v6h6",
1501
+ fill: "none",
1502
+ stroke: FILE_TYPE_COLORS.white,
1503
+ strokeWidth: "1",
1504
+ strokeLinecap: "round",
1505
+ strokeLinejoin: "round"
1506
+ }
1507
+ ),
1508
+ /* @__PURE__ */ jsx(
1509
+ "text",
1510
+ {
1511
+ x: "12",
1512
+ y: "16",
1513
+ fontSize: "6",
1514
+ fill: "white",
1515
+ textAnchor: "middle",
1516
+ fontWeight: "bold",
1517
+ fontFamily: "Arial, sans-serif",
1518
+ children: "PDF"
1519
+ }
1520
+ )
1521
+ ]
1522
+ }
1523
+ );
1524
+ };
1525
+ var AudIcon = ({ size = 16, className = "" }) => {
1526
+ return /* @__PURE__ */ jsxs(
1527
+ "svg",
1528
+ {
1529
+ width: size,
1530
+ height: size,
1531
+ viewBox: "0 0 24 24",
1532
+ fill: "none",
1533
+ xmlns: "http://www.w3.org/2000/svg",
1534
+ className,
1535
+ children: [
1536
+ /* @__PURE__ */ jsx(
1537
+ "path",
1538
+ {
1539
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1540
+ fill: FILE_TYPE_COLORS.aud,
1541
+ stroke: FILE_TYPE_COLORS.aud,
1542
+ strokeWidth: "1",
1543
+ strokeLinecap: "round",
1544
+ strokeLinejoin: "round"
1545
+ }
1546
+ ),
1547
+ /* @__PURE__ */ jsx(
1548
+ "path",
1549
+ {
1550
+ d: "M14 2v6h6",
1551
+ fill: "none",
1552
+ stroke: FILE_TYPE_COLORS.white,
1553
+ strokeWidth: "1",
1554
+ strokeLinecap: "round",
1555
+ strokeLinejoin: "round"
1556
+ }
1557
+ ),
1558
+ /* @__PURE__ */ jsx(
1559
+ "text",
1560
+ {
1561
+ x: "12",
1562
+ y: "16",
1563
+ fontSize: "6",
1564
+ fill: "white",
1565
+ textAnchor: "middle",
1566
+ fontWeight: "bold",
1567
+ fontFamily: "Arial, sans-serif",
1568
+ children: "AUD"
1569
+ }
1570
+ )
1571
+ ]
1572
+ }
1573
+ );
1574
+ };
1575
+ var ImgIcon = ({ size = 16, className = "" }) => {
1576
+ return /* @__PURE__ */ jsxs(
1577
+ "svg",
1578
+ {
1579
+ width: size,
1580
+ height: size,
1581
+ viewBox: "0 0 24 24",
1582
+ fill: "none",
1583
+ xmlns: "http://www.w3.org/2000/svg",
1584
+ className,
1585
+ children: [
1586
+ /* @__PURE__ */ jsx(
1587
+ "path",
1588
+ {
1589
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1590
+ fill: FILE_TYPE_COLORS.img,
1591
+ stroke: FILE_TYPE_COLORS.img,
1592
+ strokeWidth: "1",
1593
+ strokeLinecap: "round",
1594
+ strokeLinejoin: "round"
1595
+ }
1596
+ ),
1597
+ /* @__PURE__ */ jsx(
1598
+ "path",
1599
+ {
1600
+ d: "M14 2v6h6",
1601
+ fill: "none",
1602
+ stroke: FILE_TYPE_COLORS.white,
1603
+ strokeWidth: "1",
1604
+ strokeLinecap: "round",
1605
+ strokeLinejoin: "round"
1606
+ }
1607
+ ),
1608
+ /* @__PURE__ */ jsx(
1609
+ "text",
1610
+ {
1611
+ x: "12",
1612
+ y: "16",
1613
+ fontSize: "6",
1614
+ fill: "white",
1615
+ textAnchor: "middle",
1616
+ fontWeight: "bold",
1617
+ fontFamily: "Arial, sans-serif",
1618
+ children: "IMG"
1619
+ }
1620
+ )
1621
+ ]
1622
+ }
1623
+ );
1624
+ };
1625
+ var VidIcon = ({ size = 16, className = "" }) => {
1626
+ return /* @__PURE__ */ jsxs(
1627
+ "svg",
1628
+ {
1629
+ width: size,
1630
+ height: size,
1631
+ viewBox: "0 0 24 24",
1632
+ fill: "none",
1633
+ xmlns: "http://www.w3.org/2000/svg",
1634
+ className,
1635
+ children: [
1636
+ /* @__PURE__ */ jsx(
1637
+ "path",
1638
+ {
1639
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1640
+ fill: FILE_TYPE_COLORS.vid,
1641
+ stroke: FILE_TYPE_COLORS.vid,
1642
+ strokeWidth: "1",
1643
+ strokeLinecap: "round",
1644
+ strokeLinejoin: "round"
1645
+ }
1646
+ ),
1647
+ /* @__PURE__ */ jsx(
1648
+ "path",
1649
+ {
1650
+ d: "M14 2v6h6",
1651
+ fill: "none",
1652
+ stroke: FILE_TYPE_COLORS.white,
1653
+ strokeWidth: "1",
1654
+ strokeLinecap: "round",
1655
+ strokeLinejoin: "round"
1656
+ }
1657
+ ),
1658
+ /* @__PURE__ */ jsx(
1659
+ "text",
1660
+ {
1661
+ x: "12",
1662
+ y: "16",
1663
+ fontSize: "6",
1664
+ fill: "white",
1665
+ textAnchor: "middle",
1666
+ fontWeight: "bold",
1667
+ fontFamily: "Arial, sans-serif",
1668
+ children: "VID"
1669
+ }
1670
+ )
1671
+ ]
1672
+ }
1673
+ );
1674
+ };
1675
+ var EmlIcon = ({ size = 16, className = "" }) => {
1676
+ return /* @__PURE__ */ jsxs(
1677
+ "svg",
1678
+ {
1679
+ width: size,
1680
+ height: size,
1681
+ viewBox: "0 0 24 24",
1682
+ fill: "none",
1683
+ xmlns: "http://www.w3.org/2000/svg",
1684
+ className,
1685
+ children: [
1686
+ /* @__PURE__ */ jsx(
1687
+ "path",
1688
+ {
1689
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1690
+ fill: FILE_TYPE_COLORS.eml,
1691
+ stroke: FILE_TYPE_COLORS.eml,
1692
+ strokeWidth: "1",
1693
+ strokeLinecap: "round",
1694
+ strokeLinejoin: "round"
1695
+ }
1696
+ ),
1697
+ /* @__PURE__ */ jsx(
1698
+ "path",
1699
+ {
1700
+ d: "M14 2v6h6",
1701
+ fill: "none",
1702
+ stroke: FILE_TYPE_COLORS.white,
1703
+ strokeWidth: "1",
1704
+ strokeLinecap: "round",
1705
+ strokeLinejoin: "round"
1706
+ }
1707
+ ),
1708
+ /* @__PURE__ */ jsx(
1709
+ "rect",
1710
+ {
1711
+ x: "7",
1712
+ y: "12",
1713
+ width: "10",
1714
+ height: "7",
1715
+ rx: "1",
1716
+ fill: "none",
1717
+ stroke: "white",
1718
+ strokeWidth: "1.2"
1719
+ }
1720
+ ),
1721
+ /* @__PURE__ */ jsx("path", { d: "M7 13l5 3 5-3", fill: "none", stroke: "white", strokeWidth: "1.2", strokeLinejoin: "round" })
1722
+ ]
1723
+ }
1724
+ );
1725
+ };
1726
+ var FileIcon = ({ size = 16, className = "" }) => {
1727
+ return /* @__PURE__ */ jsxs(
1728
+ "svg",
1729
+ {
1730
+ width: size,
1731
+ height: size,
1732
+ viewBox: "0 0 24 24",
1733
+ fill: "none",
1734
+ xmlns: "http://www.w3.org/2000/svg",
1735
+ className,
1736
+ children: [
1737
+ /* @__PURE__ */ jsx(
1738
+ "path",
1739
+ {
1740
+ d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
1741
+ fill: FILE_TYPE_COLORS.generic,
1742
+ stroke: FILE_TYPE_COLORS.generic,
1743
+ strokeWidth: "1",
1744
+ strokeLinecap: "round",
1745
+ strokeLinejoin: "round"
1746
+ }
1747
+ ),
1748
+ /* @__PURE__ */ jsx(
1749
+ "path",
1750
+ {
1751
+ d: "M14 2v6h6",
1752
+ fill: "none",
1753
+ stroke: FILE_TYPE_COLORS.white,
1754
+ strokeWidth: "1",
1755
+ strokeLinecap: "round",
1756
+ strokeLinejoin: "round"
1757
+ }
1758
+ ),
1759
+ /* @__PURE__ */ jsx(
1760
+ "text",
1761
+ {
1762
+ x: "12",
1763
+ y: "17",
1764
+ fontSize: "10",
1765
+ fill: "white",
1766
+ textAnchor: "middle",
1767
+ fontWeight: "bold",
1768
+ fontFamily: "Arial, sans-serif",
1769
+ children: "?"
1770
+ }
1771
+ )
1772
+ ]
1773
+ }
1774
+ );
1775
+ };
1776
+ var EntityPill = forwardRef(function EntityPill2({
1777
+ icon,
1778
+ label,
1779
+ secondaryText,
1780
+ size = "sm",
1781
+ shape = "rounded",
1782
+ className,
1783
+ labelMaxWidth = "max-w-[320px]",
1784
+ fullWidth = false,
1785
+ highlight = false,
1786
+ onClick,
1787
+ onIconClick,
1788
+ onMoreClick,
1789
+ moreContent,
1790
+ href,
1791
+ disabled = false,
1792
+ tooltipContent,
1793
+ tooltipSide = "bottom",
1794
+ "data-testid": testId
1795
+ }, ref) {
1796
+ const shapeClass = shape === "pill" ? "rounded-full" : "rounded-md";
1797
+ const sizeClasses = size === "base" ? "gap-1.5 px-1.5 py-0.5" : "gap-1 px-1";
1798
+ const textSizeClass = size === "base" ? "text-base" : "text-sm";
1799
+ const baseClasses = cn(
1800
+ "group/pill items-center",
1801
+ fullWidth ? "flex w-full" : "inline-flex",
1802
+ sizeClasses,
1803
+ shapeClass,
1804
+ "bg-muted",
1805
+ "border border-border",
1806
+ "transition-all",
1807
+ className
1808
+ );
1809
+ const interactiveClasses = "cursor-pointer hover:bg-muted/80";
1810
+ const disabledClasses = "cursor-default opacity-60";
1811
+ const highlightClasses = "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground";
1812
+ const mainContent = /* @__PURE__ */ jsxs(Fragment, { children: [
1813
+ onIconClick ? /* @__PURE__ */ jsx(
1814
+ "span",
1815
+ {
1816
+ role: "button",
1817
+ tabIndex: 0,
1818
+ className: "flex-shrink-0 cursor-pointer hover:opacity-70 transition-opacity",
1819
+ onClick: (e) => {
1820
+ e.stopPropagation();
1821
+ onIconClick(e);
1822
+ },
1823
+ children: icon
1824
+ }
1825
+ ) : icon,
1826
+ /* @__PURE__ */ jsx(
1827
+ "span",
1828
+ {
1829
+ className: cn(textSizeClass, "font-medium truncate leading-tight min-w-0", labelMaxWidth),
1830
+ children: label
1831
+ }
1832
+ ),
1833
+ secondaryText && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground flex-shrink-0 leading-none", children: secondaryText })
1834
+ ] });
1835
+ const tooltipWrap = (content, tip, side = tooltipSide, triggerClassName, triggerProps) => /* @__PURE__ */ jsxs(Tooltip, { children: [
1836
+ /* @__PURE__ */ jsx(
1837
+ TooltipTrigger,
1838
+ {
1839
+ onFocusCapture: (e) => e.stopPropagation(),
1840
+ className: triggerClassName,
1841
+ ...triggerProps,
1842
+ children: content
1843
+ }
1844
+ ),
1845
+ /* @__PURE__ */ jsx(TooltipContent, { side, className: "p-2", children: tip })
1846
+ ] });
1847
+ const mainAreaClass = cn("inline-flex items-center gap-1", fullWidth && "min-w-0 flex-1");
1848
+ if (onMoreClick || moreContent) {
1849
+ let mainArea;
1850
+ if (tooltipContent) {
1851
+ mainArea = tooltipWrap(
1852
+ mainContent,
1853
+ tooltipContent,
1854
+ tooltipSide,
1855
+ cn(mainAreaClass, disabled && "opacity-60"),
1856
+ {
1857
+ type: "button",
1858
+ onClick: href ? onClick : disabled ? void 0 : onClick,
1859
+ disabled: disabled || void 0
1860
+ }
1861
+ );
1862
+ } else if (href) {
1863
+ mainArea = /* @__PURE__ */ jsx(
1864
+ "a",
1865
+ {
1866
+ href,
1867
+ target: "_blank",
1868
+ rel: "noopener noreferrer",
1869
+ className: mainAreaClass,
1870
+ onClick,
1871
+ children: mainContent
1872
+ }
1873
+ );
1874
+ } else if (onClick) {
1875
+ mainArea = /* @__PURE__ */ jsx(
1876
+ "button",
1877
+ {
1878
+ type: "button",
1879
+ onClick: disabled ? void 0 : onClick,
1880
+ disabled,
1881
+ className: cn("inline-flex items-center gap-1", disabled && "opacity-60"),
1882
+ children: mainContent
1883
+ }
1884
+ );
1885
+ } else {
1886
+ mainArea = /* @__PURE__ */ jsx("span", { className: mainAreaClass, children: mainContent });
1887
+ }
1888
+ const moreArea = moreContent ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 leading-none", children: moreContent }) : tooltipWrap(
1889
+ /* @__PURE__ */ jsx(MoreVertical, { className: "w-3.5 h-3.5" }),
1890
+ "Click for more",
1891
+ tooltipSide,
1892
+ "flex-shrink-0 leading-none text-muted-foreground hover:text-foreground",
1893
+ {
1894
+ type: "button",
1895
+ onClick: (e) => {
1896
+ e.stopPropagation();
1897
+ onMoreClick?.(e);
1898
+ }
1899
+ }
1900
+ );
1901
+ return /* @__PURE__ */ jsxs(
1902
+ "span",
1903
+ {
1904
+ ref,
1905
+ className: cn(
1906
+ baseClasses,
1907
+ (onClick || href) && !disabled && interactiveClasses,
1908
+ highlight && highlightClasses
1909
+ ),
1910
+ "data-testid": testId,
1911
+ children: [
1912
+ mainArea,
1913
+ moreArea
1914
+ ]
1915
+ }
1916
+ );
1917
+ }
1918
+ if (tooltipContent) {
1919
+ if (href) {
1920
+ return tooltipWrap(
1921
+ /* @__PURE__ */ jsx(
1922
+ "a",
1923
+ {
1924
+ href,
1925
+ target: "_blank",
1926
+ rel: "noopener noreferrer",
1927
+ className: mainAreaClass,
1928
+ onClick,
1929
+ children: mainContent
1930
+ }
1931
+ ),
1932
+ tooltipContent,
1933
+ tooltipSide,
1934
+ cn(baseClasses, interactiveClasses),
1935
+ { "data-testid": testId }
1936
+ );
1937
+ }
1938
+ return tooltipWrap(
1939
+ mainContent,
1940
+ tooltipContent,
1941
+ tooltipSide,
1942
+ cn(
1943
+ baseClasses,
1944
+ onClick && !disabled ? interactiveClasses : "",
1945
+ disabled ? disabledClasses : "",
1946
+ highlight && highlightClasses
1947
+ ),
1948
+ {
1949
+ type: "button",
1950
+ ref,
1951
+ onClick: onClick && !disabled ? onClick : void 0,
1952
+ disabled: disabled || void 0,
1953
+ "data-testid": testId
1954
+ }
1955
+ );
1956
+ }
1957
+ if (href) {
1958
+ return /* @__PURE__ */ jsx(
1959
+ "a",
1960
+ {
1961
+ ref,
1962
+ href,
1963
+ target: "_blank",
1964
+ rel: "noopener noreferrer",
1965
+ className: cn(baseClasses, interactiveClasses),
1966
+ "data-testid": testId,
1967
+ onClick,
1968
+ children: mainContent
1969
+ }
1970
+ );
1971
+ }
1972
+ if (onClick) {
1973
+ return /* @__PURE__ */ jsx(
1974
+ "button",
1975
+ {
1976
+ ref,
1977
+ type: "button",
1978
+ onClick: disabled ? void 0 : onClick,
1979
+ disabled,
1980
+ className: cn(
1981
+ baseClasses,
1982
+ disabled ? disabledClasses : interactiveClasses,
1983
+ highlight && highlightClasses
1984
+ ),
1985
+ "data-testid": testId,
1986
+ children: mainContent
1987
+ }
1988
+ );
1989
+ }
1990
+ return /* @__PURE__ */ jsx(
1991
+ "span",
1992
+ {
1993
+ ref,
1994
+ className: cn(baseClasses, highlight && highlightClasses),
1995
+ "data-testid": testId,
1996
+ children: mainContent
1997
+ }
1998
+ );
1999
+ });
2000
+ function getDocumentTitle(document2, defaultValue = "") {
2001
+ if (!document2) return defaultValue;
2002
+ return document2.doc_metadata?.title || document2.file_name || defaultValue;
2003
+ }
2004
+ var MAX_LABEL_CHARS = 30;
2005
+ function clampLabel(text) {
2006
+ return text.length > MAX_LABEL_CHARS ? `${text.slice(0, MAX_LABEL_CHARS).trimEnd()}\u2026` : text;
2007
+ }
2008
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp"]);
2009
+ var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set(["mp4", "mpeg", "mpg", "webm", "mov", "avi", "mkv"]);
2010
+ var AUDIO_EXTENSIONS = /* @__PURE__ */ new Set(["mp3", "wav", "m4a", "aac", "ogg", "flac"]);
2011
+ var EMAIL_EXTENSIONS = /* @__PURE__ */ new Set(["eml", "msg"]);
2012
+ function getDocIcon(fileName, iconSize = 14) {
2013
+ const ext = fileName?.split(".").pop()?.toLowerCase();
2014
+ if (ext && VIDEO_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(VidIcon, { size: iconSize, className: "flex-shrink-0" });
2015
+ if (ext && AUDIO_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(AudIcon, { size: iconSize, className: "flex-shrink-0" });
2016
+ if (ext && IMAGE_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(ImgIcon, { size: iconSize, className: "flex-shrink-0" });
2017
+ if (ext && EMAIL_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(EmlIcon, { size: iconSize, className: "flex-shrink-0" });
2018
+ return /* @__PURE__ */ jsx(PdfIcon, { size: iconSize, className: "flex-shrink-0" });
2019
+ }
2020
+ function DocumentEntity({
2021
+ doc,
2022
+ icon,
2023
+ size = "sm",
2024
+ labelMaxWidth,
2025
+ onClick,
2026
+ onIconClick,
2027
+ showHoverEye,
2028
+ viewing,
2029
+ iconBadge,
2030
+ actions,
2031
+ tooltipContent,
2032
+ className,
2033
+ fullWidth
2034
+ }) {
2035
+ const title = getDocumentTitle(doc);
2036
+ const ext = doc.file_name?.split(".").pop()?.toLowerCase();
2037
+ const iconSize = size === "base" ? 16 : 14;
2038
+ const eyeSizeClass = size === "base" ? "h-4 w-4" : "h-3.5 w-3.5";
2039
+ const baseIcon = icon ?? getDocIcon(doc.file_name, iconSize);
2040
+ const showEye = showHoverEye || viewing;
2041
+ const displayIcon = showEye || iconBadge ? /* @__PURE__ */ jsxs("span", { className: "relative inline-flex flex-shrink-0 items-center justify-center", children: [
2042
+ showEye ? /* @__PURE__ */ jsxs(Fragment, { children: [
2043
+ /* @__PURE__ */ jsx(
2044
+ "span",
2045
+ {
2046
+ className: cn(
2047
+ "transition-opacity",
2048
+ viewing ? "opacity-0" : "group-hover/pill:opacity-0 group-has-[[data-state=open]]/pill:opacity-0"
2049
+ ),
2050
+ children: baseIcon
2051
+ }
2052
+ ),
2053
+ /* @__PURE__ */ jsx(
2054
+ Eye,
2055
+ {
2056
+ className: cn(
2057
+ "absolute inset-0 m-auto transition-opacity",
2058
+ eyeSizeClass,
2059
+ viewing ? "text-primary-foreground opacity-100" : "text-primary opacity-0 group-hover/pill:opacity-100 group-has-[[data-state=open]]/pill:opacity-100"
2060
+ )
2061
+ }
2062
+ )
2063
+ ] }) : baseIcon,
2064
+ iconBadge
2065
+ ] }) : baseIcon;
2066
+ const defaultTooltip = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-xs max-w-[300px]", children: [
2067
+ doc.folder && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5 text-muted-foreground", children: [
2068
+ /* @__PURE__ */ jsx(FolderOpen, { className: "h-3 w-3 text-yellow-600 shrink-0" }),
2069
+ doc.folder.split("/").map((part, i, arr) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5 shrink-0", children: [
2070
+ i > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/50 mx-0.5", children: "/" }),
2071
+ /* @__PURE__ */ jsx("span", { className: i < arr.length - 1 ? "text-muted-foreground/70" : "", children: part })
2072
+ ] }, i))
2073
+ ] }),
2074
+ /* @__PURE__ */ jsxs("span", { className: "font-medium break-words", children: [
2075
+ title,
2076
+ ext ? `.${ext}` : ""
2077
+ ] })
2078
+ ] });
2079
+ return /* @__PURE__ */ jsx(
2080
+ EntityPill,
2081
+ {
2082
+ icon: displayIcon,
2083
+ size,
2084
+ label: fullWidth ? title : clampLabel(title),
2085
+ labelMaxWidth: labelMaxWidth ?? "max-w-[140px]",
2086
+ fullWidth,
2087
+ onClick,
2088
+ onIconClick,
2089
+ moreContent: actions,
2090
+ className,
2091
+ highlight: viewing,
2092
+ tooltipContent: tooltipContent ?? defaultTooltip
2093
+ }
2094
+ );
2095
+ }
2096
+ var BASE_COLORS = {
2097
+ "0": "#10b981",
2098
+ "1": "#3b82f6",
2099
+ "2": "#8b5cf6",
2100
+ "3": "#f43f5e",
2101
+ "4": "#f59e0b",
2102
+ "5": "#84cc16",
2103
+ "6": "#a855f7",
2104
+ "7": "#06b6d4",
2105
+ "8": "#f97316",
2106
+ "9": "#14b8a6",
2107
+ a: "#ef4444",
2108
+ b: "#6366f1",
2109
+ c: "#ec4899",
2110
+ d: "#22c55e",
2111
+ e: "#eab308",
2112
+ f: "#0ea5e9"
2113
+ };
2114
+ function getEntityColor(entityId) {
2115
+ return BASE_COLORS[entityId[4]] || BASE_COLORS["0"];
2116
+ }
2117
+ var TAG_TYPE_LABELS = {
2118
+ checkbox: "Checkbox",
2119
+ select: "Select",
2120
+ number: "Number",
2121
+ text: "Text",
2122
+ folder: "Folder",
2123
+ search: "Saved Search",
2124
+ date: "Date",
2125
+ assistant: "AI Assistant"
2126
+ };
2127
+ var TAG_TYPE_ICONS = {
2128
+ checkbox: SquareCheckBig,
2129
+ select: List,
2130
+ number: Hash,
2131
+ text: StickyNote,
2132
+ folder: Folder,
2133
+ search: Search,
2134
+ date: Calendar,
2135
+ assistant: Bot
2136
+ };
2137
+ function TagEntity({
2138
+ tag,
2139
+ size = "md",
2140
+ className = "",
2141
+ onClick,
2142
+ showTooltip = true
2143
+ }) {
2144
+ const tagType = tag.tag_type?.type ?? "text";
2145
+ const iconSize = size === "sm" ? 12 : size === "md" ? 14 : 16;
2146
+ const Icon = TAG_TYPE_ICONS[tagType] || StickyNote;
2147
+ const sizeClasses = {
2148
+ sm: "p-0.5",
2149
+ md: "p-1",
2150
+ lg: "p-1.5"
2151
+ };
2152
+ const tagColor = tag.color ?? getEntityColor(tag.external_id);
2153
+ const iconElement = /* @__PURE__ */ jsx(
2154
+ "span",
2155
+ {
2156
+ className: `inline-flex items-center justify-center rounded-md text-white flex-shrink-0 ${sizeClasses[size]}`,
2157
+ style: { backgroundColor: tagColor },
2158
+ children: /* @__PURE__ */ jsx(Icon, { size: iconSize, className: "flex-shrink-0" })
2159
+ }
2160
+ );
2161
+ const pillSize = size === "lg" ? "base" : "sm";
2162
+ const tooltipContent = showTooltip ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
2163
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2164
+ /* @__PURE__ */ jsx(
2165
+ "span",
2166
+ {
2167
+ className: "inline-flex items-center justify-center rounded-md text-white p-1",
2168
+ style: { backgroundColor: tagColor },
2169
+ children: /* @__PURE__ */ jsx(Icon, { size: 16 })
2170
+ }
2171
+ ),
2172
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: tag.name })
2173
+ ] }),
2174
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 text-sm", children: [
2175
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2176
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Type:" }),
2177
+ /* @__PURE__ */ jsx("span", { children: TAG_TYPE_LABELS[tagType] || tagType })
2178
+ ] }),
2179
+ tag.doctag_count != null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2180
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Documents:" }),
2181
+ /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "h-5 min-w-[20px] justify-center", children: tag.doctag_count ?? 0 })
2182
+ ] }),
2183
+ tag.shared != null && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: tag.shared ? "Shared" : "Private" }) })
2184
+ ] })
2185
+ ] }) : void 0;
2186
+ return /* @__PURE__ */ jsx(
2187
+ EntityPill,
2188
+ {
2189
+ icon: iconElement,
2190
+ label: tag.name,
2191
+ size: pillSize,
2192
+ shape: "rounded",
2193
+ labelMaxWidth: "max-w-[180px]",
2194
+ tooltipContent,
2195
+ onClick,
2196
+ className,
2197
+ "data-testid": `tag-entity-${tag.external_id}`
2198
+ }
2199
+ );
2200
+ }
2201
+ var VARIANT_STYLES = {
2202
+ "mine-paid": {
2203
+ pill: "bg-primary text-primary-foreground border-transparent",
2204
+ icon: "text-primary-foreground"
2205
+ },
2206
+ other: {
2207
+ pill: "bg-secondary text-secondary-foreground border-transparent",
2208
+ icon: "text-secondary-foreground"
2209
+ },
2210
+ "mine-free": {
2211
+ pill: "bg-muted-foreground text-background border-transparent",
2212
+ icon: "text-background"
2213
+ },
2214
+ common: {
2215
+ pill: "",
2216
+ icon: "text-muted-foreground"
2217
+ }
2218
+ };
2219
+ function resolveVariant(relation, paid, hasCollaborators) {
2220
+ if (relation === "common") return "common";
2221
+ if (relation === "other") return "other";
2222
+ if (relation === "mine") return paid ? "mine-paid" : "mine-free";
2223
+ if (paid) return hasCollaborators ? "other" : "mine-paid";
2224
+ return "mine-free";
2225
+ }
2226
+ function ProjectEntity({
2227
+ name,
2228
+ label,
2229
+ icon,
2230
+ subscription = "none",
2231
+ hasCollaborators = false,
2232
+ size = "sm",
2233
+ className,
2234
+ onClick,
2235
+ relation,
2236
+ isPaid,
2237
+ tooltipContent
2238
+ }) {
2239
+ const paid = isPaid ?? (subscription === "active" || subscription === "past_due" || subscription === "dev");
2240
+ const variant = resolveVariant(relation, paid, hasCollaborators);
2241
+ const { pill, icon: iconClass } = VARIANT_STYLES[variant];
2242
+ const iconSizeClass = size === "base" ? "h-4 w-4" : "h-3.5 w-3.5";
2243
+ const iconNode = icon ?? /* @__PURE__ */ jsx(Package, { className: cn(iconSizeClass, iconClass) });
2244
+ return /* @__PURE__ */ jsx(
2245
+ EntityPill,
2246
+ {
2247
+ icon: iconNode,
2248
+ label: label ?? name,
2249
+ size,
2250
+ shape: "pill",
2251
+ className: cn(pill, className),
2252
+ onClick,
2253
+ tooltipContent
2254
+ }
2255
+ );
2256
+ }
2257
+ var useArbiUiStore = create((set) => ({
2258
+ selectedDocIds: [],
2259
+ setSelectedDocIds: (ids) => set({ selectedDocIds: ids }),
2260
+ viewingDocId: null,
2261
+ setViewingDocId: (id) => set({ viewingDocId: id })
2262
+ }));
2263
+ ModuleRegistry.registerModules([AllCommunityModule]);
2264
+ function formatBytes(bytes) {
2265
+ if (bytes == null || Number.isNaN(bytes)) return "\u2014";
2266
+ if (bytes < 1024) return `${bytes} B`;
2267
+ const units = ["KB", "MB", "GB", "TB"];
2268
+ let value = bytes / 1024;
2269
+ let i = 0;
2270
+ while (value >= 1024 && i < units.length - 1) {
2271
+ value /= 1024;
2272
+ i++;
2273
+ }
2274
+ return `${value.toFixed(value >= 10 || i === 0 ? 0 : 1)} ${units[i]}`;
2275
+ }
2276
+ var STATUS_VARIANTS = {
2277
+ completed: "default",
2278
+ empty: "secondary",
2279
+ "low-content": "secondary",
2280
+ processing: "outline",
2281
+ queued: "outline",
2282
+ failed: "destructive",
2283
+ skipped: "destructive"
2284
+ };
2285
+ function DocumentTable({
2286
+ workspaceId,
2287
+ documents,
2288
+ onOpenDocument,
2289
+ selectedIds,
2290
+ onSelectionChange,
2291
+ height = 480,
2292
+ className
2293
+ }) {
2294
+ const query = useDocuments(workspaceId, { enabled: !documents });
2295
+ const rows = documents ?? query.data ?? [];
2296
+ const isLoading = !documents && query.isLoading;
2297
+ const tagsQuery = useTags(workspaceId);
2298
+ const tagNameById = React__default.useMemo(() => {
2299
+ const map = /* @__PURE__ */ new Map();
2300
+ for (const t of tagsQuery.data ?? []) {
2301
+ if (t.external_id) map.set(t.external_id, t.name ?? t.external_id.slice(0, 8));
2302
+ }
2303
+ return map;
2304
+ }, [tagsQuery.data]);
2305
+ const storeSelected = useArbiUiStore((s) => s.selectedDocIds);
2306
+ const storeSetSelected = useArbiUiStore((s) => s.setSelectedDocIds);
2307
+ const viewingDocId = useArbiUiStore((s) => s.viewingDocId);
2308
+ const setViewingDocId = useArbiUiStore((s) => s.setViewingDocId);
2309
+ const effectiveSelected = selectedIds ?? storeSelected;
2310
+ const emitSelection = onSelectionChange ?? storeSetSelected;
2311
+ const gridApiRef = React__default.useRef(null);
2312
+ const openDocument = React__default.useCallback(
2313
+ (id) => {
2314
+ setViewingDocId(id);
2315
+ onOpenDocument?.(id);
2316
+ },
2317
+ [onOpenDocument, setViewingDocId]
2318
+ );
2319
+ const applySelection = React__default.useCallback(() => {
2320
+ const api = gridApiRef.current;
2321
+ if (!api) return;
2322
+ const wanted = new Set(effectiveSelected);
2323
+ api.forEachNode((node) => {
2324
+ const id = node.data?.external_id;
2325
+ const shouldSelect = !!id && wanted.has(id);
2326
+ if (node.isSelected() !== shouldSelect) node.setSelected(shouldSelect);
2327
+ });
2328
+ }, [effectiveSelected]);
2329
+ React__default.useEffect(() => {
2330
+ applySelection();
2331
+ }, [applySelection]);
2332
+ const columnDefs = React__default.useMemo(
2333
+ () => [
2334
+ {
2335
+ colId: "select",
2336
+ headerName: "",
2337
+ width: 44,
2338
+ pinned: "left",
2339
+ checkboxSelection: true,
2340
+ headerCheckboxSelection: true,
2341
+ sortable: false,
2342
+ filter: false,
2343
+ resizable: false,
2344
+ suppressMovable: true
2345
+ },
2346
+ {
2347
+ colId: "title",
2348
+ headerName: "Document Name",
2349
+ flex: 3,
2350
+ minWidth: 240,
2351
+ sortable: true,
2352
+ valueGetter: (p) => p.data?.doc_metadata?.title || p.data?.file_name || "",
2353
+ cellRenderer: (p) => {
2354
+ const doc = p.data;
2355
+ if (!doc) return null;
2356
+ return /* @__PURE__ */ jsx(
2357
+ DocumentEntity,
2358
+ {
2359
+ doc,
2360
+ size: "base",
2361
+ fullWidth: true,
2362
+ showHoverEye: true,
2363
+ viewing: viewingDocId === doc.external_id,
2364
+ onClick: (e) => {
2365
+ e.stopPropagation();
2366
+ if (doc.external_id) openDocument(doc.external_id);
2367
+ }
2368
+ }
2369
+ );
2370
+ }
2371
+ },
2372
+ {
2373
+ colId: "status",
2374
+ headerName: "Status",
2375
+ width: 140,
2376
+ sortable: true,
2377
+ field: "status",
2378
+ cellRenderer: (p) => {
2379
+ const status = p.data?.status;
2380
+ if (!status) return null;
2381
+ return /* @__PURE__ */ jsx(Badge, { variant: STATUS_VARIANTS[status.toLowerCase()] ?? "secondary", children: status });
2382
+ }
2383
+ },
2384
+ {
2385
+ colId: "all_tags",
2386
+ headerName: "Labels",
2387
+ flex: 1,
2388
+ minWidth: 160,
2389
+ sortable: false,
2390
+ filter: false,
2391
+ cellRenderer: (p) => {
2392
+ const doctags = p.data?.doctags ?? [];
2393
+ if (doctags.length === 0) return null;
2394
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-1 py-1", children: doctags.map((dt) => /* @__PURE__ */ jsx(
2395
+ TagEntity,
2396
+ {
2397
+ size: "sm",
2398
+ tag: {
2399
+ external_id: dt.tag_ext_id,
2400
+ name: tagNameById.get(dt.tag_ext_id) ?? dt.tag_ext_id.slice(0, 8)
2401
+ }
2402
+ },
2403
+ dt.tag_ext_id
2404
+ )) });
2405
+ }
2406
+ },
2407
+ {
2408
+ colId: "file_size",
2409
+ headerName: "Size",
2410
+ width: 110,
2411
+ sortable: true,
2412
+ field: "file_size",
2413
+ valueFormatter: (p) => formatBytes(p.value)
2414
+ },
2415
+ {
2416
+ colId: "folder",
2417
+ headerName: "Folder",
2418
+ flex: 1,
2419
+ minWidth: 140,
2420
+ sortable: true,
2421
+ field: "folder",
2422
+ valueFormatter: (p) => p.value || "\u2014"
2423
+ }
2424
+ ],
2425
+ [openDocument, viewingDocId, tagNameById]
2426
+ );
2427
+ const handleGridReady = (e) => {
2428
+ gridApiRef.current = e.api;
2429
+ applySelection();
2430
+ };
2431
+ const handleSelectionChanged = (e) => {
2432
+ const ids = e.api.getSelectedRows().map((r) => r.external_id).filter((id) => !!id);
2433
+ emitSelection(ids);
2434
+ };
2435
+ const handleRowClicked = (e) => {
2436
+ const id = e.data?.external_id;
2437
+ if (id) openDocument(id);
2438
+ };
2439
+ const getRowId = React__default.useCallback((params) => params.data.external_id, []);
2440
+ const autoHeight = height === "auto";
2441
+ const style = autoHeight ? {} : { height: typeof height === "number" ? `${height}px` : height, width: "100%" };
2442
+ if (isLoading) {
2443
+ return /* @__PURE__ */ jsx("div", { className, style, children: /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center p-8 text-sm text-muted-foreground", children: "Loading documents\u2026" }) });
2444
+ }
2445
+ if (rows.length === 0) {
2446
+ return /* @__PURE__ */ jsx("div", { className, style, children: /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center p-8 text-sm text-muted-foreground", children: "No documents" }) });
2447
+ }
2448
+ return /* @__PURE__ */ jsx("div", { className, style, children: /* @__PURE__ */ jsx(
2449
+ AgGridReact,
2450
+ {
2451
+ columnDefs,
2452
+ rowData: rows,
2453
+ getRowId,
2454
+ rowSelection: "multiple",
2455
+ suppressRowClickSelection: true,
2456
+ domLayout: autoHeight ? "autoHeight" : "normal",
2457
+ rowHeight: 44,
2458
+ onGridReady: handleGridReady,
2459
+ onSelectionChanged: handleSelectionChanged,
2460
+ onRowClicked: handleRowClicked
2461
+ }
2462
+ ) });
2463
+ }
1157
2464
 
1158
- export { ArbiChat, ArbiProvider, arbiQueryKeys, useAgents, useArbi, useAssistantQuery, useConversations, useDeleteAgents, useDocuments, useHealth, useSessions, useTags, useWorkspaces };
2465
+ export { ArbiChat, ArbiChatPanel, ArbiProvider, AudIcon, Avatar, AvatarFallback, AvatarImage, Badge, Button, DocumentEntity, DocumentTable, EmlIcon, EntityPill, FILE_TYPE_COLORS, FileIcon, HoverCard, HoverCardContent, HoverCardTrigger, ImgIcon, PdfIcon, ProjectEntity, TagEntity, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, VidIcon, arbiQueryKeys, badgeVariants, buttonVariants, cn, useAgents, useArbi, useArbiUiStore, useAssistantQuery, useConfigs, useConversations, useDeleteAgents, useDocuments, useHealth, useMemories, useSessions, useTags, useTasks, useWorkspaces };
1159
2466
  //# sourceMappingURL=index.js.map
1160
2467
  //# sourceMappingURL=index.js.map