@inf-monkeys-tech/monkeys-design 0.4.32 → 0.4.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +226 -226
  3. package/dist/components/base/index.d.mts +2 -2
  4. package/dist/components/base/index.d.ts +2 -2
  5. package/dist/components/base/index.js +990 -28
  6. package/dist/components/base/index.js.map +1 -1
  7. package/dist/components/base/index.mjs +987 -30
  8. package/dist/components/base/index.mjs.map +1 -1
  9. package/dist/components/data-explorer/index.js.map +1 -1
  10. package/dist/components/data-explorer/index.mjs.map +1 -1
  11. package/dist/components/layout/index.js.map +1 -1
  12. package/dist/components/layout/index.mjs.map +1 -1
  13. package/dist/components/login/index.js.map +1 -1
  14. package/dist/components/login/index.mjs.map +1 -1
  15. package/dist/components/toolbar/index.js.map +1 -1
  16. package/dist/components/toolbar/index.mjs.map +1 -1
  17. package/dist/components/workbench/index.d.mts +193 -2
  18. package/dist/components/workbench/index.d.ts +193 -2
  19. package/dist/components/workbench/index.js +2164 -585
  20. package/dist/components/workbench/index.js.map +1 -1
  21. package/dist/components/workbench/index.mjs +2367 -813
  22. package/dist/components/workbench/index.mjs.map +1 -1
  23. package/dist/icons/oauth/index.js.map +1 -1
  24. package/dist/icons/oauth/index.mjs.map +1 -1
  25. package/dist/index.d.mts +3 -3
  26. package/dist/index.d.ts +3 -3
  27. package/dist/index.js +1958 -170
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +1950 -172
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/palette/index.js.map +1 -1
  32. package/dist/palette/index.mjs.map +1 -1
  33. package/dist/registry/index.js.map +1 -1
  34. package/dist/registry/index.mjs.map +1 -1
  35. package/dist/styles/artist-login.scss +374 -374
  36. package/dist/styles/global.scss +21 -21
  37. package/dist/styles/workflow-board.scss +440 -440
  38. package/dist/styles/workflow-nodes.css +340 -340
  39. package/dist/{theme-CvbotXXr.d.ts → theme-Clm5dVb0.d.mts} +10 -3
  40. package/dist/{theme-6RDum855.d.mts → theme-sIoU5-YC.d.ts} +10 -3
  41. package/dist/theme-system/index.d.mts +1 -1
  42. package/dist/theme-system/index.d.ts +1 -1
  43. package/dist/theme-system/index.js +842 -18
  44. package/dist/theme-system/index.js.map +1 -1
  45. package/dist/theme-system/index.mjs +843 -19
  46. package/dist/theme-system/index.mjs.map +1 -1
  47. package/dist/themes/artist/index.js.map +1 -1
  48. package/dist/themes/artist/index.mjs.map +1 -1
  49. package/dist/themes/bsd/index.js.map +1 -1
  50. package/dist/themes/bsd/index.mjs.map +1 -1
  51. package/dist/themes/concept/index.js.map +1 -1
  52. package/dist/themes/concept/index.mjs.map +1 -1
  53. package/dist/themes/default/index.js.map +1 -1
  54. package/dist/themes/default/index.mjs.map +1 -1
  55. package/dist/{types-BgEEUqSm.d.mts → types-Bn6PEDsX.d.mts} +163 -1
  56. package/dist/{types-BgEEUqSm.d.ts → types-Bn6PEDsX.d.ts} +163 -1
  57. package/package.json +139 -138
@@ -2,7 +2,28 @@
2
2
 
3
3
  var react = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- require('@radix-ui/react-context-menu');
5
+ var ContextMenu = require('@radix-ui/react-context-menu');
6
+ var core = require('@dnd-kit/core');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var ContextMenu__namespace = /*#__PURE__*/_interopNamespace(ContextMenu);
6
27
 
7
28
  // src/components/workbench/WorkbenchResizableSidebar.tsx
8
29
 
@@ -709,7 +730,41 @@ var baseSlots = {
709
730
  tableEmptyActions: "mt-4 flex flex-wrap items-center justify-center gap-2",
710
731
  tableLoadingRow: "border-b border-border/60",
711
732
  tableLoadingCell: "px-3 py-2",
712
- tableLoadingSkeleton: "h-4 w-full rounded-md bg-muted/70"
733
+ tableLoadingSkeleton: "h-4 w-full rounded-md bg-muted/70",
734
+ layoutRoot: cn(
735
+ "grid min-w-0 overflow-hidden grid-rows-[auto_minmax(0,1fr)_auto] gap-3 rounded-lg border border-border/70 bg-background p-3 text-foreground",
736
+ motionBase
737
+ ),
738
+ layoutRootFull: "h-full min-h-0",
739
+ layoutHeader: "min-w-0",
740
+ layoutBody: "grid min-h-0 min-w-0 overflow-hidden gap-3",
741
+ layoutSidebar: "min-h-0 min-w-0 overflow-hidden",
742
+ layoutMain: "min-h-0 min-w-0 overflow-hidden",
743
+ layoutAside: "min-h-0 min-w-0 overflow-hidden",
744
+ layoutFooter: "min-w-0",
745
+ layoutPane: cn(
746
+ "h-full max-h-full min-h-0 min-w-0 overflow-hidden rounded-lg bg-background text-foreground",
747
+ motionBase
748
+ ),
749
+ layoutPaneScrollable: "overflow-auto",
750
+ layoutPaneBordered: "border border-border/70",
751
+ layoutPaneMuted: "bg-muted/25",
752
+ layoutPaneSoft: "bg-background/95 shadow-sm",
753
+ layoutPaneTransparent: "bg-transparent shadow-none",
754
+ layoutSplitRoot: "grid min-h-0 min-w-0 overflow-hidden",
755
+ layoutSplitHorizontal: "grid-flow-col",
756
+ layoutSplitVertical: "grid-flow-row",
757
+ layoutSplitPane: "min-h-0 min-w-0 overflow-hidden",
758
+ layoutSplitPrimary: "",
759
+ layoutSplitSecondary: "",
760
+ layoutResizeHandle: cn(
761
+ "group/resize relative z-10 flex shrink-0 items-center justify-center bg-transparent text-muted-foreground hover:bg-border/60 active:bg-border/70 focus-visible:bg-border/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
762
+ motionInteractive
763
+ ),
764
+ layoutResizeHandleHorizontal: "w-2 cursor-col-resize",
765
+ layoutResizeHandleVertical: "h-2 cursor-row-resize",
766
+ layoutResizeHandleDisabled: "cursor-default opacity-60",
767
+ layoutResizeHandleIndicator: "rounded-full bg-muted-foreground/45 group-hover/resize:bg-primary/70"
713
768
  };
714
769
  var densitySlots = {
715
770
  compact: {
@@ -783,7 +838,12 @@ var densitySlots = {
783
838
  tableCell: "px-2 py-1.5 text-xs",
784
839
  tableHeadLabel: "text-[11px]",
785
840
  tableHeadDescription: "text-[10px] leading-3",
786
- tableLoadingCell: "px-2 py-1.5"
841
+ tableLoadingCell: "px-2 py-1.5",
842
+ layoutRoot: "gap-2 p-2",
843
+ layoutBody: "gap-2",
844
+ layoutPane: "rounded-md text-xs",
845
+ layoutResizeHandleHorizontal: "w-1.5",
846
+ layoutResizeHandleVertical: "h-1.5"
787
847
  },
788
848
  default: {
789
849
  buttonBase: "h-9"
@@ -834,7 +894,12 @@ var densitySlots = {
834
894
  menuSubTrigger: "min-h-9 px-3 py-2",
835
895
  tableHead: "h-12 px-4 py-3",
836
896
  tableCell: "px-4 py-3",
837
- tableLoadingCell: "px-4 py-3"
897
+ tableLoadingCell: "px-4 py-3",
898
+ layoutRoot: "gap-4 p-4",
899
+ layoutBody: "gap-4",
900
+ layoutPane: "rounded-xl",
901
+ layoutResizeHandleHorizontal: "w-2.5",
902
+ layoutResizeHandleVertical: "h-2.5"
838
903
  }
839
904
  };
840
905
  var radiusSlots = {
@@ -878,7 +943,9 @@ var radiusSlots = {
878
943
  menuSubContent: "rounded-none",
879
944
  tableContainer: "rounded-none",
880
945
  tableEmptyIcon: "rounded-none",
881
- tableLoadingSkeleton: "rounded-none"
946
+ tableLoadingSkeleton: "rounded-none",
947
+ layoutRoot: "rounded-none",
948
+ layoutPane: "rounded-none"
882
949
  },
883
950
  sm: {
884
951
  buttonBase: "rounded-sm",
@@ -920,7 +987,9 @@ var radiusSlots = {
920
987
  menuSubContent: "rounded-sm",
921
988
  tableContainer: "rounded-sm",
922
989
  tableEmptyIcon: "rounded-sm",
923
- tableLoadingSkeleton: "rounded-sm"
990
+ tableLoadingSkeleton: "rounded-sm",
991
+ layoutRoot: "rounded-sm",
992
+ layoutPane: "rounded-sm"
924
993
  },
925
994
  md: {},
926
995
  lg: {
@@ -957,7 +1026,9 @@ var radiusSlots = {
957
1026
  menuSubContent: "rounded-lg",
958
1027
  tableContainer: "rounded-xl",
959
1028
  tableEmptyIcon: "rounded-xl",
960
- tableLoadingSkeleton: "rounded-lg"
1029
+ tableLoadingSkeleton: "rounded-lg",
1030
+ layoutRoot: "rounded-xl",
1031
+ layoutPane: "rounded-xl"
961
1032
  },
962
1033
  xl: {
963
1034
  buttonBase: "rounded-xl",
@@ -995,7 +1066,9 @@ var radiusSlots = {
995
1066
  menuSubContent: "rounded-xl",
996
1067
  tableContainer: "rounded-2xl",
997
1068
  tableEmptyIcon: "rounded-2xl",
998
- tableLoadingSkeleton: "rounded-xl"
1069
+ tableLoadingSkeleton: "rounded-xl",
1070
+ layoutRoot: "rounded-2xl",
1071
+ layoutPane: "rounded-2xl"
999
1072
  },
1000
1073
  full: {
1001
1074
  buttonBase: "rounded-full",
@@ -1037,7 +1110,9 @@ var radiusSlots = {
1037
1110
  menuSubContent: "rounded-2xl",
1038
1111
  tableContainer: "rounded-2xl",
1039
1112
  tableEmptyIcon: "rounded-full",
1040
- tableLoadingSkeleton: "rounded-full"
1113
+ tableLoadingSkeleton: "rounded-full",
1114
+ layoutRoot: "rounded-2xl",
1115
+ layoutPane: "rounded-2xl"
1041
1116
  }
1042
1117
  };
1043
1118
  var borderSlots = {
@@ -1079,7 +1154,10 @@ var borderSlots = {
1079
1154
  tableFooterBarAttached: "border-t border-transparent",
1080
1155
  tableRow: "border-transparent",
1081
1156
  tableEmptyRow: "border-transparent",
1082
- tableLoadingRow: "border-transparent"
1157
+ tableLoadingRow: "border-transparent",
1158
+ layoutRoot: "border-transparent",
1159
+ layoutPaneBordered: "border-transparent",
1160
+ layoutResizeHandle: "bg-transparent hover:bg-transparent active:bg-transparent focus-visible:bg-transparent"
1083
1161
  },
1084
1162
  subtle: {
1085
1163
  buttonDefault: "border-border/60",
@@ -1119,7 +1197,9 @@ var borderSlots = {
1119
1197
  tableFooterBarAttached: "border-t border-border/60",
1120
1198
  tableRow: "border-border/50",
1121
1199
  tableEmptyRow: "border-border/50",
1122
- tableLoadingRow: "border-border/50"
1200
+ tableLoadingRow: "border-border/50",
1201
+ layoutRoot: "border-border/60",
1202
+ layoutPaneBordered: "border-border/60"
1123
1203
  },
1124
1204
  solid: {},
1125
1205
  strong: {
@@ -1160,7 +1240,10 @@ var borderSlots = {
1160
1240
  tableFooterBarAttached: "border-t border-foreground/20",
1161
1241
  tableRow: "border-foreground/15",
1162
1242
  tableEmptyRow: "border-foreground/15",
1163
- tableLoadingRow: "border-foreground/15"
1243
+ tableLoadingRow: "border-foreground/15",
1244
+ layoutRoot: "border-foreground/20",
1245
+ layoutPaneBordered: "border-foreground/20",
1246
+ layoutResizeHandle: "hover:bg-foreground/15 active:bg-foreground/20 focus-visible:bg-foreground/15"
1164
1247
  }
1165
1248
  };
1166
1249
  var backgroundSlots = {
@@ -1202,7 +1285,11 @@ var backgroundSlots = {
1202
1285
  tableFooter: "bg-muted/35",
1203
1286
  tableFooterBar: "bg-muted/30 shadow-none",
1204
1287
  tableRowInteractive: "cursor-pointer hover:bg-muted/45",
1205
- tableLoadingSkeleton: "bg-muted"
1288
+ tableLoadingSkeleton: "bg-muted",
1289
+ layoutRoot: "bg-card",
1290
+ layoutPane: "bg-card",
1291
+ layoutPaneMuted: "bg-muted/35",
1292
+ layoutResizeHandle: "hover:bg-border/70 active:bg-border/80 focus-visible:bg-border/70"
1206
1293
  },
1207
1294
  soft: {
1208
1295
  buttonDefault: "bg-muted/30 hover:bg-muted/55",
@@ -1238,7 +1325,10 @@ var backgroundSlots = {
1238
1325
  tableFooter: "bg-muted/25",
1239
1326
  tableFooterBar: "bg-muted/25 shadow-none",
1240
1327
  tableRowInteractive: "cursor-pointer hover:bg-muted/35",
1241
- tableLoadingSkeleton: "bg-muted/65"
1328
+ tableLoadingSkeleton: "bg-muted/65",
1329
+ layoutRoot: "bg-background/95 shadow-sm",
1330
+ layoutPane: "bg-background/95 shadow-sm",
1331
+ layoutPaneSoft: "bg-background/95 shadow-md"
1242
1332
  },
1243
1333
  glass: {
1244
1334
  buttonBase: "backdrop-blur-md",
@@ -1299,7 +1389,13 @@ var backgroundSlots = {
1299
1389
  tableRow: "border-white/10",
1300
1390
  tableRowInteractive: "cursor-pointer hover:bg-white/[0.08]",
1301
1391
  tableHeadLabel: "text-foreground",
1302
- tableLoadingSkeleton: "bg-white/[0.16]"
1392
+ tableLoadingSkeleton: "bg-white/[0.16]",
1393
+ layoutRoot: "border-white/10 bg-white/[0.05] shadow-none backdrop-blur-md",
1394
+ layoutPane: "border-white/10 bg-white/[0.06] shadow-none backdrop-blur-md",
1395
+ layoutPaneMuted: "bg-white/[0.08]",
1396
+ layoutPaneSoft: "bg-white/[0.10] shadow-none backdrop-blur-md",
1397
+ layoutResizeHandle: "text-foreground/65 hover:bg-white/10 active:bg-white/15 focus-visible:bg-white/10",
1398
+ layoutResizeHandleIndicator: "bg-white/45 group-hover/resize:bg-white/75"
1303
1399
  },
1304
1400
  dark: {
1305
1401
  buttonBase: "border-white/15 text-white shadow-lg backdrop-blur",
@@ -1428,7 +1524,13 @@ var backgroundSlots = {
1428
1524
  menuSubTrigger: "text-white focus:bg-white/[0.10] focus:text-white data-[highlighted]:bg-white/[0.10] data-[highlighted]:text-white data-[state=open]:bg-white/[0.12]",
1429
1525
  menuSubTriggerIcon: "text-white/55",
1430
1526
  menuSubContent: "border-white/10 bg-slate-950 text-white shadow-2xl",
1431
- tableLoadingSkeleton: "bg-white/[0.14]"
1527
+ tableLoadingSkeleton: "bg-white/[0.14]",
1528
+ layoutRoot: "border-white/10 bg-slate-950 text-white shadow-none",
1529
+ layoutPane: "border-white/10 bg-slate-950 text-white shadow-none",
1530
+ layoutPaneMuted: "bg-white/[0.06]",
1531
+ layoutPaneSoft: "bg-white/[0.08] shadow-none",
1532
+ layoutResizeHandle: "text-white/65 hover:bg-white/10 active:bg-white/15 focus-visible:bg-white/10",
1533
+ layoutResizeHandleIndicator: "bg-white/45 group-hover/resize:bg-white/75"
1432
1534
  }
1433
1535
  };
1434
1536
  var presetDefaults = {
@@ -1581,6 +1683,16 @@ function getBaseButtonToneClassName(theme, tone = "default", active = false) {
1581
1683
  active && theme.slots.buttonActive
1582
1684
  );
1583
1685
  }
1686
+ function getBaseMenuItemToneClassName(theme, tone = "default") {
1687
+ return cn(
1688
+ tone === "default" && theme.slots.menuItemDefault,
1689
+ tone === "primary" && theme.slots.menuItemPrimary,
1690
+ tone === "success" && theme.slots.menuItemSuccess,
1691
+ tone === "warning" && theme.slots.menuItemWarning,
1692
+ tone === "danger" && theme.slots.menuItemDanger,
1693
+ tone === "muted" && theme.slots.menuItemMuted
1694
+ );
1695
+ }
1584
1696
  function LoadingIcon() {
1585
1697
  return /* @__PURE__ */ jsxRuntime.jsxs(
1586
1698
  "svg",
@@ -1801,6 +1913,198 @@ var BaseCheckbox = react.forwardRef(
1801
1913
  );
1802
1914
  }
1803
1915
  );
1916
+ function renderItemContent({
1917
+ label,
1918
+ icon,
1919
+ shortcut,
1920
+ children,
1921
+ classNames,
1922
+ inset,
1923
+ indicator
1924
+ }) {
1925
+ const resolvedLabel = children ?? label;
1926
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1927
+ indicator ? indicator : null,
1928
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.icon), children: icon }) : inset ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }) : null,
1929
+ hasRenderableNode(resolvedLabel) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.label), children: resolvedLabel }) : null,
1930
+ hasRenderableNode(shortcut) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(classNames?.shortcut), children: shortcut }) : null
1931
+ ] });
1932
+ }
1933
+ function BaseContextMenu({
1934
+ children,
1935
+ trigger,
1936
+ content,
1937
+ disabled = false,
1938
+ modal = true,
1939
+ dir,
1940
+ appearance,
1941
+ className,
1942
+ classNames,
1943
+ onOpenChange
1944
+ }) {
1945
+ const theme = resolveBaseAppearance(appearance);
1946
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1947
+ ContextMenu__namespace.Root,
1948
+ {
1949
+ onOpenChange,
1950
+ modal,
1951
+ dir,
1952
+ children: [
1953
+ trigger ? /* @__PURE__ */ jsxRuntime.jsx(
1954
+ ContextMenu__namespace.Trigger,
1955
+ {
1956
+ disabled,
1957
+ className: cn(
1958
+ theme.slots.menuTrigger,
1959
+ disabled && theme.slots.menuItemDisabled,
1960
+ classNames?.trigger,
1961
+ className
1962
+ ),
1963
+ children: trigger
1964
+ }
1965
+ ) : null,
1966
+ content ? /* @__PURE__ */ jsxRuntime.jsx(BaseContextMenuContent, { appearance, className: classNames?.content, children: content }) : null,
1967
+ children
1968
+ ]
1969
+ }
1970
+ );
1971
+ }
1972
+ function BaseContextMenuTrigger({
1973
+ children,
1974
+ disabled = false,
1975
+ asChild = false,
1976
+ appearance,
1977
+ className,
1978
+ style,
1979
+ ...triggerProps
1980
+ }) {
1981
+ const theme = resolveBaseAppearance(appearance);
1982
+ return /* @__PURE__ */ jsxRuntime.jsx(
1983
+ ContextMenu__namespace.Trigger,
1984
+ {
1985
+ ...triggerProps,
1986
+ asChild,
1987
+ disabled,
1988
+ className: cn(
1989
+ !asChild && theme.slots.menuTrigger,
1990
+ disabled && !asChild && theme.slots.menuItemDisabled,
1991
+ className
1992
+ ),
1993
+ style,
1994
+ children
1995
+ }
1996
+ );
1997
+ }
1998
+ function BaseContextMenuContent({
1999
+ children,
2000
+ appearance,
2001
+ className,
2002
+ classNames,
2003
+ style,
2004
+ ...contentProps
2005
+ }) {
2006
+ const theme = resolveBaseAppearance(appearance);
2007
+ return /* @__PURE__ */ jsxRuntime.jsx(ContextMenu__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
2008
+ ContextMenu__namespace.Content,
2009
+ {
2010
+ ...contentProps,
2011
+ className: cn(theme.slots.menuContent, classNames?.root, className),
2012
+ style: {
2013
+ ...theme.styles.menuContent,
2014
+ ...style
2015
+ },
2016
+ children
2017
+ }
2018
+ ) });
2019
+ }
2020
+ function BaseContextMenuLabel({
2021
+ children,
2022
+ appearance,
2023
+ className,
2024
+ style,
2025
+ ...labelProps
2026
+ }) {
2027
+ const theme = resolveBaseAppearance(appearance);
2028
+ return /* @__PURE__ */ jsxRuntime.jsx(
2029
+ ContextMenu__namespace.Label,
2030
+ {
2031
+ ...labelProps,
2032
+ className: cn(theme.slots.menuLabel, className),
2033
+ style,
2034
+ children
2035
+ }
2036
+ );
2037
+ }
2038
+ function BaseContextMenuSeparator({
2039
+ appearance,
2040
+ className,
2041
+ style,
2042
+ ...separatorProps
2043
+ }) {
2044
+ const theme = resolveBaseAppearance(appearance);
2045
+ return /* @__PURE__ */ jsxRuntime.jsx(
2046
+ ContextMenu__namespace.Separator,
2047
+ {
2048
+ ...separatorProps,
2049
+ className: cn(theme.slots.menuSeparator, className),
2050
+ style
2051
+ }
2052
+ );
2053
+ }
2054
+ function BaseContextMenuItem({
2055
+ children,
2056
+ label,
2057
+ icon,
2058
+ shortcut,
2059
+ tone,
2060
+ disabled = false,
2061
+ inset = false,
2062
+ appearance,
2063
+ className,
2064
+ classNames,
2065
+ style,
2066
+ onSelect,
2067
+ ...itemProps
2068
+ }) {
2069
+ const theme = resolveBaseAppearance(appearance);
2070
+ return /* @__PURE__ */ jsxRuntime.jsx(
2071
+ ContextMenu__namespace.Item,
2072
+ {
2073
+ ...itemProps,
2074
+ disabled,
2075
+ className: cn(
2076
+ theme.slots.menuItem,
2077
+ getBaseMenuItemToneClassName(theme, tone),
2078
+ disabled && theme.slots.menuItemDisabled,
2079
+ classNames?.root,
2080
+ className
2081
+ ),
2082
+ style: {
2083
+ ...theme.styles.menuItem,
2084
+ ...style
2085
+ },
2086
+ onSelect: (event) => {
2087
+ if (disabled) {
2088
+ event.preventDefault();
2089
+ return;
2090
+ }
2091
+ onSelect?.(event);
2092
+ },
2093
+ children: renderItemContent({
2094
+ children,
2095
+ label,
2096
+ icon,
2097
+ shortcut,
2098
+ inset,
2099
+ classNames: {
2100
+ icon: cn(theme.slots.menuItemIcon, classNames?.icon),
2101
+ label: cn(theme.slots.menuItemLabel, classNames?.label),
2102
+ shortcut: cn(theme.slots.menuItemShortcut, classNames?.shortcut)
2103
+ }
2104
+ })
2105
+ }
2106
+ );
2107
+ }
1804
2108
  var columnClassNames = {
1805
2109
  1: "grid-cols-1",
1806
2110
  2: "md:grid-cols-2",
@@ -1993,84 +2297,131 @@ var BaseInput = react.forwardRef(
1993
2297
  );
1994
2298
  }
1995
2299
  );
1996
- function findOption(options, value) {
1997
- if (value === void 0) return void 0;
1998
- return options.find((option) => option.value === value);
1999
- }
2000
- function getInitialValue(options, defaultValue) {
2001
- if (typeof defaultValue === "string") {
2002
- return defaultValue;
2003
- }
2004
- return "";
2300
+ function normalizeValues(values) {
2301
+ const nextValues = [];
2302
+ const seen = /* @__PURE__ */ new Set();
2303
+ values?.forEach((value) => {
2304
+ if (seen.has(value)) return;
2305
+ seen.add(value);
2306
+ nextValues.push(value);
2307
+ });
2308
+ return nextValues;
2005
2309
  }
2006
2310
  function getNextEnabledIndex(options, currentIndex, direction) {
2007
2311
  if (!options.length) return -1;
2312
+ const startIndex = currentIndex >= 0 ? currentIndex : 0;
2008
2313
  for (let offset = 1; offset <= options.length; offset += 1) {
2009
- const nextIndex = (currentIndex + offset * direction + options.length) % options.length;
2314
+ const nextIndex = (startIndex + offset * direction + options.length) % options.length;
2010
2315
  if (!options[nextIndex]?.disabled) {
2011
2316
  return nextIndex;
2012
2317
  }
2013
2318
  }
2014
2319
  return -1;
2015
2320
  }
2016
- var BaseSelect = react.forwardRef(
2017
- function BaseSelect2({
2321
+ function getFirstEnabledIndex(options) {
2322
+ return options.findIndex((option) => !option.disabled);
2323
+ }
2324
+ function getSafeTagCount(maxTagCount, total) {
2325
+ if (maxTagCount === void 0) return total;
2326
+ if (!Number.isFinite(maxTagCount)) return total;
2327
+ return Math.max(0, Math.min(total, Math.floor(maxTagCount)));
2328
+ }
2329
+ function getDefaultRemoveLabel(option) {
2330
+ return `Remove ${option.value}`;
2331
+ }
2332
+ react.forwardRef(
2333
+ function BaseMultiSelect2({
2018
2334
  options,
2019
- placeholder,
2335
+ value,
2336
+ defaultValue,
2337
+ name,
2338
+ placeholder = "Select options",
2020
2339
  icon,
2021
2340
  invalid = false,
2022
2341
  disabled = false,
2342
+ required = false,
2023
2343
  openForPreview = false,
2344
+ maxTagCount,
2345
+ removeLabel = getDefaultRemoveLabel,
2346
+ emptyLabel = "No options",
2024
2347
  appearance,
2025
2348
  className,
2026
2349
  classNames,
2027
2350
  style,
2028
- children,
2029
- value,
2030
- defaultValue,
2031
- onChange,
2032
- name,
2033
2351
  id,
2034
- required,
2035
2352
  "aria-invalid": nativeAriaInvalid,
2036
2353
  "aria-label": nativeAriaLabel,
2037
2354
  "aria-labelledby": nativeAriaLabelledBy,
2038
- ...selectProps
2355
+ onValueChange,
2356
+ ...rootProps
2039
2357
  }, ref) {
2040
2358
  const theme = resolveBaseAppearance(appearance);
2041
2359
  const generatedId = react.useId();
2042
- const selectId = id ?? generatedId;
2043
- const listboxId = `${selectId}-listbox`;
2360
+ const multiSelectId = id ?? generatedId;
2361
+ const controlId = `${multiSelectId}-control`;
2362
+ const listboxId = `${multiSelectId}-listbox`;
2044
2363
  const rootRef = react.useRef(null);
2045
- const selectRef = react.useRef(null);
2046
2364
  const optionList = options ?? [];
2047
- const isCustomSelect = optionList.length > 0;
2048
2365
  const forceOpen = openForPreview;
2049
2366
  const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
2050
2367
  const open = forceOpen || uncontrolledOpen;
2051
2368
  const [uncontrolledValue, setUncontrolledValue] = react.useState(
2052
- () => getInitialValue(optionList, defaultValue)
2369
+ () => normalizeValues(defaultValue)
2370
+ );
2371
+ const [activeIndex, setActiveIndex] = react.useState(
2372
+ () => getFirstEnabledIndex(optionList)
2053
2373
  );
2054
2374
  const isControlled = value !== void 0;
2055
- const selectedValue = String(isControlled ? value : uncontrolledValue);
2056
- const selectedOption = findOption(optionList, selectedValue);
2057
- const activeIndex = react.useMemo(() => {
2058
- const selectedIndex = optionList.findIndex(
2059
- (option) => option.value === selectedValue && !option.disabled
2060
- );
2061
- if (selectedIndex >= 0) return selectedIndex;
2062
- return optionList.findIndex((option) => !option.disabled);
2063
- }, [optionList, selectedValue]);
2064
- const visibleLabel = selectedOption?.label ?? placeholder;
2065
- const isPlaceholder = !selectedOption;
2066
- const setSelectRef = (node) => {
2067
- selectRef.current = node;
2375
+ const selectedValues = react.useMemo(
2376
+ () => normalizeValues(isControlled ? value : uncontrolledValue),
2377
+ [isControlled, uncontrolledValue, value]
2378
+ );
2379
+ const selectedValueSet = react.useMemo(
2380
+ () => new Set(selectedValues),
2381
+ [selectedValues]
2382
+ );
2383
+ const optionByValue = react.useMemo(() => {
2384
+ const map = /* @__PURE__ */ new Map();
2385
+ optionList.forEach((option) => {
2386
+ if (!map.has(option.value)) {
2387
+ map.set(option.value, option);
2388
+ }
2389
+ });
2390
+ return map;
2391
+ }, [optionList]);
2392
+ const selectedOptions = react.useMemo(
2393
+ () => selectedValues.map((selectedValue) => optionByValue.get(selectedValue)).filter(
2394
+ (option) => option !== void 0
2395
+ ),
2396
+ [optionByValue, selectedValues]
2397
+ );
2398
+ const firstEnabledIndex = react.useMemo(
2399
+ () => getFirstEnabledIndex(optionList),
2400
+ [optionList]
2401
+ );
2402
+ const resolvedActiveIndex = activeIndex >= 0 && !optionList[activeIndex]?.disabled ? activeIndex : firstEnabledIndex;
2403
+ const visibleTagCount = getSafeTagCount(
2404
+ maxTagCount,
2405
+ selectedOptions.length
2406
+ );
2407
+ const visibleOptions = selectedOptions.slice(0, visibleTagCount);
2408
+ const overflowCount = selectedOptions.length - visibleOptions.length;
2409
+ const isPlaceholder = selectedOptions.length === 0;
2410
+ const setRootRef = (node) => {
2411
+ rootRef.current = node;
2068
2412
  if (typeof ref === "function") {
2069
2413
  ref(node);
2070
2414
  } else if (ref) {
2071
2415
  ref.current = node;
2072
2416
  }
2073
2417
  };
2418
+ const setOpen = (nextOpen) => {
2419
+ if (disabled || forceOpen) return;
2420
+ setUncontrolledOpen(nextOpen);
2421
+ if (nextOpen) {
2422
+ setActiveIndex(resolvedActiveIndex);
2423
+ }
2424
+ };
2074
2425
  react.useEffect(() => {
2075
2426
  if (!open || forceOpen) return void 0;
2076
2427
  const handlePointerDown = (event) => {
@@ -2083,31 +2434,37 @@ var BaseSelect = react.forwardRef(
2083
2434
  document.removeEventListener("pointerdown", handlePointerDown);
2084
2435
  };
2085
2436
  }, [forceOpen, open]);
2086
- const notifyChange = (nextValue) => {
2087
- const selectElement = selectRef.current;
2088
- if (!selectElement) return;
2089
- const valueSetter = Object.getOwnPropertyDescriptor(
2090
- HTMLSelectElement.prototype,
2091
- "value"
2092
- )?.set;
2093
- valueSetter?.call(selectElement, nextValue);
2094
- selectElement.dispatchEvent(new Event("change", { bubbles: true }));
2095
- };
2096
- const commitValue = (nextValue, optionDisabled) => {
2097
- if (optionDisabled || disabled) return;
2098
- if (!isControlled) {
2099
- setUncontrolledValue(nextValue);
2437
+ react.useEffect(() => {
2438
+ if (resolvedActiveIndex >= 0 && resolvedActiveIndex !== activeIndex) {
2439
+ setActiveIndex(resolvedActiveIndex);
2100
2440
  }
2101
- notifyChange(nextValue);
2102
- if (!forceOpen) {
2103
- setUncontrolledOpen(false);
2441
+ }, [activeIndex, resolvedActiveIndex]);
2442
+ const commitValues = (nextValues) => {
2443
+ const normalizedValues = normalizeValues(nextValues);
2444
+ if (!isControlled) {
2445
+ setUncontrolledValue(normalizedValues);
2104
2446
  }
2447
+ onValueChange?.(normalizedValues);
2448
+ };
2449
+ const toggleOption = (option) => {
2450
+ if (!option || option.disabled || disabled) return;
2451
+ const nextValues = selectedValueSet.has(option.value) ? selectedValues.filter((selectedValue) => selectedValue !== option.value) : [...selectedValues, option.value];
2452
+ commitValues(nextValues);
2453
+ };
2454
+ const removeOption = (option) => {
2455
+ if (disabled) return;
2456
+ commitValues(
2457
+ selectedValues.filter((selectedValue) => selectedValue !== option.value)
2458
+ );
2105
2459
  };
2106
2460
  const focusOption = (direction) => {
2107
- const currentIndex = activeIndex >= 0 ? activeIndex : 0;
2108
- const nextIndex = getNextEnabledIndex(optionList, currentIndex, direction);
2461
+ const nextIndex = getNextEnabledIndex(
2462
+ optionList,
2463
+ resolvedActiveIndex,
2464
+ direction
2465
+ );
2109
2466
  if (nextIndex >= 0) {
2110
- commitValue(optionList[nextIndex].value, optionList[nextIndex].disabled);
2467
+ setActiveIndex(nextIndex);
2111
2468
  }
2112
2469
  };
2113
2470
  const handleKeyDown = (event) => {
@@ -2115,77 +2472,49 @@ var BaseSelect = react.forwardRef(
2115
2472
  if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2116
2473
  event.preventDefault();
2117
2474
  if (!open) {
2118
- setUncontrolledOpen(true);
2475
+ setOpen(true);
2476
+ setActiveIndex(firstEnabledIndex);
2119
2477
  return;
2120
2478
  }
2121
2479
  focusOption(event.key === "ArrowDown" ? 1 : -1);
2122
2480
  return;
2123
2481
  }
2482
+ if (event.key === "Home") {
2483
+ event.preventDefault();
2484
+ setOpen(true);
2485
+ setActiveIndex(firstEnabledIndex);
2486
+ return;
2487
+ }
2488
+ if (event.key === "End") {
2489
+ event.preventDefault();
2490
+ setOpen(true);
2491
+ for (let index = optionList.length - 1; index >= 0; index -= 1) {
2492
+ if (!optionList[index]?.disabled) {
2493
+ setActiveIndex(index);
2494
+ break;
2495
+ }
2496
+ }
2497
+ return;
2498
+ }
2124
2499
  if (event.key === "Enter" || event.key === " ") {
2125
2500
  event.preventDefault();
2126
- if (!forceOpen) {
2127
- setUncontrolledOpen((current) => !current);
2501
+ if (!open) {
2502
+ setOpen(true);
2503
+ return;
2128
2504
  }
2505
+ toggleOption(optionList[resolvedActiveIndex]);
2129
2506
  return;
2130
2507
  }
2131
2508
  if (event.key === "Escape") {
2132
- setUncontrolledOpen(false);
2509
+ setOpen(false);
2133
2510
  }
2134
2511
  };
2135
- if (!isCustomSelect) {
2136
- return /* @__PURE__ */ jsxRuntime.jsxs(
2137
- "div",
2138
- {
2139
- className: cn(
2140
- theme.slots.controlWrapper,
2141
- invalid && theme.slots.controlInvalid,
2142
- disabled && theme.slots.controlDisabled,
2143
- classNames?.root,
2144
- className
2145
- ),
2146
- style: {
2147
- ...theme.styles.control,
2148
- ...invalid ? theme.styles.controlInvalid : void 0,
2149
- ...disabled ? theme.styles.controlDisabled : void 0,
2150
- ...style
2151
- },
2152
- children: [
2153
- hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2154
- /* @__PURE__ */ jsxRuntime.jsxs(
2155
- "select",
2156
- {
2157
- ...selectProps,
2158
- id,
2159
- ref,
2160
- name,
2161
- value,
2162
- defaultValue,
2163
- required,
2164
- disabled,
2165
- "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2166
- "aria-label": nativeAriaLabel,
2167
- "aria-labelledby": nativeAriaLabelledBy,
2168
- onChange,
2169
- className: cn(
2170
- theme.slots.controlBase,
2171
- theme.slots.controlSelect,
2172
- classNames?.control
2173
- ),
2174
- children: [
2175
- hasRenderableNode(placeholder) ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }) : null,
2176
- children
2177
- ]
2178
- }
2179
- ),
2180
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.slots.selectChevron })
2181
- ]
2182
- }
2183
- );
2184
- }
2185
2512
  return /* @__PURE__ */ jsxRuntime.jsxs(
2186
2513
  "div",
2187
2514
  {
2188
- ref: rootRef,
2515
+ ...rootProps,
2516
+ id,
2517
+ ref: setRootRef,
2189
2518
  className: cn(
2190
2519
  theme.slots.controlWrapper,
2191
2520
  "overflow-visible",
@@ -2204,38 +2533,105 @@ var BaseSelect = react.forwardRef(
2204
2533
  children: [
2205
2534
  hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2206
2535
  /* @__PURE__ */ jsxRuntime.jsx(
2207
- "button",
2536
+ "div",
2208
2537
  {
2209
- type: "button",
2210
- id: `${selectId}-button`,
2211
- disabled,
2538
+ id: controlId,
2539
+ role: "combobox",
2540
+ tabIndex: disabled ? -1 : 0,
2212
2541
  "aria-haspopup": "listbox",
2213
2542
  "aria-expanded": open,
2214
2543
  "aria-controls": listboxId,
2544
+ "aria-disabled": disabled || void 0,
2545
+ "aria-required": required || void 0,
2215
2546
  "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2216
2547
  "aria-label": nativeAriaLabel,
2217
2548
  "aria-labelledby": nativeAriaLabelledBy,
2218
2549
  className: cn(
2219
2550
  theme.slots.controlBase,
2220
- theme.slots.controlSelect,
2221
- "flex items-center text-left",
2551
+ "flex min-h-9 cursor-pointer flex-wrap items-center gap-1.5 py-1.5 pr-9 text-left",
2552
+ disabled && "!cursor-not-allowed",
2222
2553
  classNames?.control
2223
2554
  ),
2224
- onClick: () => {
2225
- if (!forceOpen) {
2226
- setUncontrolledOpen((current) => !current);
2227
- }
2228
- },
2555
+ onClick: () => setOpen(!open),
2229
2556
  onKeyDown: handleKeyDown,
2230
- children: /* @__PURE__ */ jsxRuntime.jsx(
2557
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2231
2558
  "span",
2232
2559
  {
2233
2560
  className: cn(
2234
- "min-w-0 flex-1 truncate",
2235
- isPlaceholder && theme.slots.selectPlaceholder,
2236
- isPlaceholder && classNames?.placeholder
2561
+ "flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
2562
+ classNames?.tagList
2237
2563
  ),
2238
- children: visibleLabel
2564
+ children: [
2565
+ visibleOptions.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
2566
+ "span",
2567
+ {
2568
+ className: cn(
2569
+ "inline-flex max-w-full items-center gap-1 rounded-full border border-border/70 bg-muted/65 px-2 py-0.5 text-xs font-medium text-foreground",
2570
+ classNames?.tag
2571
+ ),
2572
+ children: [
2573
+ /* @__PURE__ */ jsxRuntime.jsx(
2574
+ "span",
2575
+ {
2576
+ className: cn(
2577
+ "max-w-40 truncate",
2578
+ classNames?.tagLabel
2579
+ ),
2580
+ children: option.label
2581
+ }
2582
+ ),
2583
+ /* @__PURE__ */ jsxRuntime.jsx(
2584
+ "button",
2585
+ {
2586
+ type: "button",
2587
+ "aria-label": removeLabel(option),
2588
+ disabled,
2589
+ className: cn(
2590
+ "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-muted-foreground hover:bg-background/80 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:!cursor-not-allowed",
2591
+ classNames?.tagRemove
2592
+ ),
2593
+ onClick: (event) => {
2594
+ event.preventDefault();
2595
+ event.stopPropagation();
2596
+ removeOption(option);
2597
+ },
2598
+ onMouseDown: (event) => {
2599
+ event.preventDefault();
2600
+ event.stopPropagation();
2601
+ },
2602
+ onKeyDown: (event) => event.stopPropagation(),
2603
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "x" })
2604
+ }
2605
+ )
2606
+ ]
2607
+ },
2608
+ option.value
2609
+ )),
2610
+ overflowCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
2611
+ "span",
2612
+ {
2613
+ className: cn(
2614
+ "inline-flex max-w-full items-center rounded-full border border-border/70 bg-muted/45 px-2 py-0.5 text-xs font-medium text-muted-foreground",
2615
+ classNames?.tag
2616
+ ),
2617
+ children: [
2618
+ "+",
2619
+ overflowCount
2620
+ ]
2621
+ }
2622
+ ) : null,
2623
+ isPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
2624
+ "span",
2625
+ {
2626
+ className: cn(
2627
+ "min-w-0 truncate",
2628
+ theme.slots.selectPlaceholder,
2629
+ classNames?.placeholder
2630
+ ),
2631
+ children: placeholder
2632
+ }
2633
+ ) : null
2634
+ ]
2239
2635
  }
2240
2636
  )
2241
2637
  }
@@ -2245,50 +2641,34 @@ var BaseSelect = react.forwardRef(
2245
2641
  {
2246
2642
  className: cn(
2247
2643
  theme.slots.selectChevron,
2248
- open && "rotate-[225deg]"
2644
+ open && "rotate-[225deg]",
2645
+ classNames?.chevron
2249
2646
  )
2250
2647
  }
2251
2648
  ),
2252
- /* @__PURE__ */ jsxRuntime.jsxs(
2253
- "select",
2649
+ name ? selectedValues.map((selectedValue) => /* @__PURE__ */ jsxRuntime.jsx(
2650
+ "input",
2254
2651
  {
2255
- ...selectProps,
2256
- ref: setSelectRef,
2257
- id,
2652
+ type: "hidden",
2258
2653
  name,
2259
2654
  value: selectedValue,
2260
- required,
2261
- disabled,
2262
- "aria-hidden": "true",
2263
- tabIndex: -1,
2264
- className: theme.slots.selectNative,
2265
- onChange,
2266
- children: [
2267
- hasRenderableNode(placeholder) ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }) : null,
2268
- optionList.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
2269
- "option",
2270
- {
2271
- value: option.value,
2272
- disabled: option.disabled,
2273
- children: typeof option.label === "string" ? option.label : option.value
2274
- },
2275
- option.value
2276
- ))
2277
- ]
2278
- }
2279
- ),
2655
+ className: classNames?.hiddenInput
2656
+ },
2657
+ selectedValue
2658
+ )) : null,
2280
2659
  open ? /* @__PURE__ */ jsxRuntime.jsx(
2281
2660
  "div",
2282
2661
  {
2283
2662
  id: listboxId,
2284
2663
  role: "listbox",
2285
- "aria-labelledby": `${selectId}-button`,
2664
+ "aria-multiselectable": "true",
2665
+ "aria-labelledby": controlId,
2286
2666
  className: cn(theme.slots.selectMenu, classNames?.menu),
2287
2667
  style: theme.styles.selectMenu,
2288
- children: optionList.map((option, index) => {
2289
- const selected = option.value === selectedValue;
2290
- const active = index === activeIndex;
2291
- return /* @__PURE__ */ jsxRuntime.jsx(
2668
+ children: optionList.length > 0 ? optionList.map((option, index) => {
2669
+ const selected = selectedValueSet.has(option.value);
2670
+ const active = index === resolvedActiveIndex;
2671
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2292
2672
  "button",
2293
2673
  {
2294
2674
  type: "button",
@@ -2297,6 +2677,7 @@ var BaseSelect = react.forwardRef(
2297
2677
  disabled: option.disabled,
2298
2678
  className: cn(
2299
2679
  theme.slots.selectOption,
2680
+ "gap-2",
2300
2681
  active && theme.slots.selectOptionActive,
2301
2682
  selected && theme.slots.selectOptionSelected,
2302
2683
  option.disabled && theme.slots.selectOptionDisabled,
@@ -2307,13 +2688,50 @@ var BaseSelect = react.forwardRef(
2307
2688
  ...active ? theme.styles.selectOptionActive : void 0,
2308
2689
  ...selected ? theme.styles.selectOptionSelected : void 0
2309
2690
  },
2691
+ onMouseEnter: () => {
2692
+ if (!option.disabled) {
2693
+ setActiveIndex(index);
2694
+ }
2695
+ },
2310
2696
  onMouseDown: (event) => event.preventDefault(),
2311
- onClick: () => commitValue(option.value, option.disabled),
2312
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: option.label })
2697
+ onClick: () => toggleOption(option),
2698
+ children: [
2699
+ /* @__PURE__ */ jsxRuntime.jsx(
2700
+ "span",
2701
+ {
2702
+ "aria-hidden": "true",
2703
+ className: cn(
2704
+ "inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border border-border/70 text-[10px]",
2705
+ selected && "border-primary/40 bg-primary text-primary-foreground",
2706
+ classNames?.optionIndicator
2707
+ ),
2708
+ children: selected ? "\u2713" : null
2709
+ }
2710
+ ),
2711
+ /* @__PURE__ */ jsxRuntime.jsx(
2712
+ "span",
2713
+ {
2714
+ className: cn(
2715
+ "min-w-0 flex-1 truncate",
2716
+ classNames?.optionLabel
2717
+ ),
2718
+ children: option.label
2719
+ }
2720
+ )
2721
+ ]
2313
2722
  },
2314
2723
  option.value
2315
2724
  );
2316
- })
2725
+ }) : /* @__PURE__ */ jsxRuntime.jsx(
2726
+ "div",
2727
+ {
2728
+ className: cn(
2729
+ "px-2.5 py-2 text-sm text-muted-foreground",
2730
+ classNames?.empty
2731
+ ),
2732
+ children: emptyLabel
2733
+ }
2734
+ )
2317
2735
  }
2318
2736
  ) : null
2319
2737
  ]
@@ -2321,185 +2739,513 @@ var BaseSelect = react.forwardRef(
2321
2739
  );
2322
2740
  }
2323
2741
  );
2324
- function getInitialSegmentValue(options, defaultValue) {
2325
- if (defaultValue && options?.some((option) => option.value === defaultValue)) {
2326
- const defaultOption = options.find((option) => option.value === defaultValue);
2327
- if (!defaultOption?.disabled) {
2328
- return defaultValue;
2329
- }
2742
+ function findOption(options, value) {
2743
+ if (value === void 0) return void 0;
2744
+ return options.find((option) => option.value === value);
2745
+ }
2746
+ function getInitialValue(options, defaultValue) {
2747
+ if (typeof defaultValue === "string") {
2748
+ return defaultValue;
2330
2749
  }
2331
- return options?.find((option) => !option.disabled)?.value ?? options?.[0]?.value;
2750
+ return "";
2332
2751
  }
2333
- function BaseSegmentedControl({
2334
- options = [],
2335
- value,
2336
- defaultValue,
2337
- appearance,
2338
- className,
2339
- classNames,
2340
- style,
2341
- onValueChange,
2342
- ...controlProps
2343
- }) {
2344
- const theme = resolveBaseAppearance(appearance);
2345
- const [uncontrolledValue, setUncontrolledValue] = react.useState(
2346
- () => getInitialSegmentValue(options, defaultValue)
2347
- );
2348
- const isControlled = value !== void 0;
2349
- const selectedValue = isControlled ? value : uncontrolledValue;
2350
- const handleSelect = (nextValue, disabled) => {
2351
- if (disabled) return;
2352
- if (!isControlled) {
2353
- setUncontrolledValue(nextValue);
2354
- }
2355
- onValueChange?.(nextValue);
2356
- };
2357
- return /* @__PURE__ */ jsxRuntime.jsx(
2358
- "div",
2359
- {
2360
- ...controlProps,
2361
- role: "radiogroup",
2362
- className: cn(theme.slots.segmentedRoot, classNames?.root, className),
2363
- style: {
2364
- ...theme.styles.segmentedRoot,
2365
- ...style
2366
- },
2367
- children: options.map((option) => {
2368
- const selected = option.value === selectedValue;
2369
- return /* @__PURE__ */ jsxRuntime.jsxs(
2370
- "button",
2371
- {
2372
- type: "button",
2373
- role: "radio",
2374
- "aria-checked": selected,
2375
- disabled: option.disabled,
2376
- className: cn(
2377
- theme.slots.segmentedItem,
2378
- selected && theme.slots.segmentedItemActive,
2379
- option.disabled && theme.slots.segmentedItemDisabled,
2380
- classNames?.item
2381
- ),
2382
- style: theme.styles.segmentedItem,
2383
- onClick: () => handleSelect(option.value, option.disabled),
2384
- children: [
2385
- hasRenderableNode(option.icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex h-4 w-4 shrink-0", classNames?.icon), children: option.icon }) : null,
2386
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", classNames?.label), children: option.label })
2387
- ]
2388
- },
2389
- option.value
2390
- );
2391
- })
2752
+ function getNextEnabledIndex2(options, currentIndex, direction) {
2753
+ if (!options.length) return -1;
2754
+ for (let offset = 1; offset <= options.length; offset += 1) {
2755
+ const nextIndex = (currentIndex + offset * direction + options.length) % options.length;
2756
+ if (!options[nextIndex]?.disabled) {
2757
+ return nextIndex;
2392
2758
  }
2393
- );
2759
+ }
2760
+ return -1;
2394
2761
  }
2395
- react.forwardRef(
2396
- function BaseSwitch2({
2397
- label,
2398
- description,
2762
+ var BaseSelect = react.forwardRef(
2763
+ function BaseSelect2({
2764
+ options,
2765
+ placeholder,
2766
+ icon,
2767
+ invalid = false,
2399
2768
  disabled = false,
2769
+ openForPreview = false,
2400
2770
  appearance,
2401
2771
  className,
2402
2772
  classNames,
2403
2773
  style,
2404
- checked,
2405
- defaultChecked,
2774
+ children,
2775
+ value,
2776
+ defaultValue,
2406
2777
  onChange,
2407
- ...switchProps
2778
+ name,
2779
+ id,
2780
+ required,
2781
+ "aria-invalid": nativeAriaInvalid,
2782
+ "aria-label": nativeAriaLabel,
2783
+ "aria-labelledby": nativeAriaLabelledBy,
2784
+ ...selectProps
2408
2785
  }, ref) {
2409
2786
  const theme = resolveBaseAppearance(appearance);
2410
- const [uncontrolledChecked, setUncontrolledChecked] = react.useState(
2411
- defaultChecked ?? false
2787
+ const generatedId = react.useId();
2788
+ const selectId = id ?? generatedId;
2789
+ const listboxId = `${selectId}-listbox`;
2790
+ const rootRef = react.useRef(null);
2791
+ const selectRef = react.useRef(null);
2792
+ const optionList = options ?? [];
2793
+ const isCustomSelect = optionList.length > 0;
2794
+ const forceOpen = openForPreview;
2795
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
2796
+ const open = forceOpen || uncontrolledOpen;
2797
+ const [uncontrolledValue, setUncontrolledValue] = react.useState(
2798
+ () => getInitialValue(optionList, defaultValue)
2412
2799
  );
2413
- const isControlled = checked !== void 0;
2414
- const resolvedChecked = isControlled ? checked : uncontrolledChecked;
2415
- const handleChange = (event) => {
2416
- if (!isControlled) {
2417
- setUncontrolledChecked(event.currentTarget.checked);
2800
+ const isControlled = value !== void 0;
2801
+ const selectedValue = String(isControlled ? value : uncontrolledValue);
2802
+ const selectedOption = findOption(optionList, selectedValue);
2803
+ const activeIndex = react.useMemo(() => {
2804
+ const selectedIndex = optionList.findIndex(
2805
+ (option) => option.value === selectedValue && !option.disabled
2806
+ );
2807
+ if (selectedIndex >= 0) return selectedIndex;
2808
+ return optionList.findIndex((option) => !option.disabled);
2809
+ }, [optionList, selectedValue]);
2810
+ const visibleLabel = selectedOption?.label ?? placeholder;
2811
+ const isPlaceholder = !selectedOption;
2812
+ const setSelectRef = (node) => {
2813
+ selectRef.current = node;
2814
+ if (typeof ref === "function") {
2815
+ ref(node);
2816
+ } else if (ref) {
2817
+ ref.current = node;
2418
2818
  }
2419
- onChange?.(event);
2420
2819
  };
2421
- return /* @__PURE__ */ jsxRuntime.jsxs(
2422
- "label",
2423
- {
2424
- className: cn(
2425
- theme.slots.switchRoot,
2426
- disabled && theme.slots.switchDisabled,
2427
- classNames?.root,
2428
- className
2429
- ),
2430
- style: {
2431
- ...theme.styles.switchRoot,
2432
- ...style
2433
- },
2434
- children: [
2435
- /* @__PURE__ */ jsxRuntime.jsxs(
2436
- "span",
2437
- {
2820
+ react.useEffect(() => {
2821
+ if (!open || forceOpen) return void 0;
2822
+ const handlePointerDown = (event) => {
2823
+ if (!rootRef.current?.contains(event.target)) {
2824
+ setUncontrolledOpen(false);
2825
+ }
2826
+ };
2827
+ document.addEventListener("pointerdown", handlePointerDown);
2828
+ return () => {
2829
+ document.removeEventListener("pointerdown", handlePointerDown);
2830
+ };
2831
+ }, [forceOpen, open]);
2832
+ const notifyChange = (nextValue) => {
2833
+ const selectElement = selectRef.current;
2834
+ if (!selectElement) return;
2835
+ const valueSetter = Object.getOwnPropertyDescriptor(
2836
+ HTMLSelectElement.prototype,
2837
+ "value"
2838
+ )?.set;
2839
+ valueSetter?.call(selectElement, nextValue);
2840
+ selectElement.dispatchEvent(new Event("change", { bubbles: true }));
2841
+ };
2842
+ const commitValue = (nextValue, optionDisabled) => {
2843
+ if (optionDisabled || disabled) return;
2844
+ if (!isControlled) {
2845
+ setUncontrolledValue(nextValue);
2846
+ }
2847
+ notifyChange(nextValue);
2848
+ if (!forceOpen) {
2849
+ setUncontrolledOpen(false);
2850
+ }
2851
+ };
2852
+ const focusOption = (direction) => {
2853
+ const currentIndex = activeIndex >= 0 ? activeIndex : 0;
2854
+ const nextIndex = getNextEnabledIndex2(optionList, currentIndex, direction);
2855
+ if (nextIndex >= 0) {
2856
+ commitValue(optionList[nextIndex].value, optionList[nextIndex].disabled);
2857
+ }
2858
+ };
2859
+ const handleKeyDown = (event) => {
2860
+ if (disabled) return;
2861
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2862
+ event.preventDefault();
2863
+ if (!open) {
2864
+ setUncontrolledOpen(true);
2865
+ return;
2866
+ }
2867
+ focusOption(event.key === "ArrowDown" ? 1 : -1);
2868
+ return;
2869
+ }
2870
+ if (event.key === "Enter" || event.key === " ") {
2871
+ event.preventDefault();
2872
+ if (!forceOpen) {
2873
+ setUncontrolledOpen((current) => !current);
2874
+ }
2875
+ return;
2876
+ }
2877
+ if (event.key === "Escape") {
2878
+ setUncontrolledOpen(false);
2879
+ }
2880
+ };
2881
+ if (!isCustomSelect) {
2882
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2883
+ "div",
2884
+ {
2885
+ className: cn(
2886
+ theme.slots.controlWrapper,
2887
+ invalid && theme.slots.controlInvalid,
2888
+ disabled && theme.slots.controlDisabled,
2889
+ classNames?.root,
2890
+ className
2891
+ ),
2892
+ style: {
2893
+ ...theme.styles.control,
2894
+ ...invalid ? theme.styles.controlInvalid : void 0,
2895
+ ...disabled ? theme.styles.controlDisabled : void 0,
2896
+ ...style
2897
+ },
2898
+ children: [
2899
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2900
+ /* @__PURE__ */ jsxRuntime.jsxs(
2901
+ "select",
2902
+ {
2903
+ ...selectProps,
2904
+ id,
2905
+ ref,
2906
+ name,
2907
+ value,
2908
+ defaultValue,
2909
+ required,
2910
+ disabled,
2911
+ "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2912
+ "aria-label": nativeAriaLabel,
2913
+ "aria-labelledby": nativeAriaLabelledBy,
2914
+ onChange,
2915
+ className: cn(
2916
+ theme.slots.controlBase,
2917
+ theme.slots.controlSelect,
2918
+ classNames?.control
2919
+ ),
2920
+ children: [
2921
+ hasRenderableNode(placeholder) ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }) : null,
2922
+ children
2923
+ ]
2924
+ }
2925
+ ),
2926
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: theme.slots.selectChevron })
2927
+ ]
2928
+ }
2929
+ );
2930
+ }
2931
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2932
+ "div",
2933
+ {
2934
+ ref: rootRef,
2935
+ className: cn(
2936
+ theme.slots.controlWrapper,
2937
+ "overflow-visible",
2938
+ open && "z-50",
2939
+ invalid && theme.slots.controlInvalid,
2940
+ disabled && theme.slots.controlDisabled,
2941
+ classNames?.root,
2942
+ className
2943
+ ),
2944
+ style: {
2945
+ ...theme.styles.control,
2946
+ ...invalid ? theme.styles.controlInvalid : void 0,
2947
+ ...disabled ? theme.styles.controlDisabled : void 0,
2948
+ ...style
2949
+ },
2950
+ children: [
2951
+ hasRenderableNode(icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.controlIcon, classNames?.icon), children: icon }) : null,
2952
+ /* @__PURE__ */ jsxRuntime.jsx(
2953
+ "button",
2954
+ {
2955
+ type: "button",
2956
+ id: `${selectId}-button`,
2957
+ disabled,
2958
+ "aria-haspopup": "listbox",
2959
+ "aria-expanded": open,
2960
+ "aria-controls": listboxId,
2961
+ "aria-invalid": nativeAriaInvalid ?? (invalid || void 0),
2962
+ "aria-label": nativeAriaLabel,
2963
+ "aria-labelledby": nativeAriaLabelledBy,
2438
2964
  className: cn(
2439
- theme.slots.switchTrack,
2440
- resolvedChecked && theme.slots.switchChecked,
2441
- classNames?.track
2965
+ theme.slots.controlBase,
2966
+ theme.slots.controlSelect,
2967
+ "flex items-center text-left",
2968
+ classNames?.control
2442
2969
  ),
2443
- style: theme.styles.switchTrack,
2970
+ onClick: () => {
2971
+ if (!forceOpen) {
2972
+ setUncontrolledOpen((current) => !current);
2973
+ }
2974
+ },
2975
+ onKeyDown: handleKeyDown,
2976
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2977
+ "span",
2978
+ {
2979
+ className: cn(
2980
+ "min-w-0 flex-1 truncate",
2981
+ isPlaceholder && theme.slots.selectPlaceholder,
2982
+ isPlaceholder && classNames?.placeholder
2983
+ ),
2984
+ children: visibleLabel
2985
+ }
2986
+ )
2987
+ }
2988
+ ),
2989
+ /* @__PURE__ */ jsxRuntime.jsx(
2990
+ "span",
2991
+ {
2992
+ className: cn(
2993
+ theme.slots.selectChevron,
2994
+ open && "rotate-[225deg]"
2995
+ )
2996
+ }
2997
+ ),
2998
+ /* @__PURE__ */ jsxRuntime.jsxs(
2999
+ "select",
3000
+ {
3001
+ ...selectProps,
3002
+ ref: setSelectRef,
3003
+ id,
3004
+ name,
3005
+ value: selectedValue,
3006
+ required,
3007
+ disabled,
3008
+ "aria-hidden": "true",
3009
+ tabIndex: -1,
3010
+ className: theme.slots.selectNative,
3011
+ onChange,
2444
3012
  children: [
2445
- /* @__PURE__ */ jsxRuntime.jsx(
2446
- "input",
2447
- {
2448
- ...switchProps,
2449
- ref,
2450
- type: "checkbox",
2451
- disabled,
2452
- checked,
2453
- defaultChecked,
2454
- onChange: handleChange,
2455
- className: cn(theme.slots.switchInput, classNames?.input)
2456
- }
2457
- ),
2458
- /* @__PURE__ */ jsxRuntime.jsx(
2459
- "span",
3013
+ hasRenderableNode(placeholder) ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: placeholder }) : null,
3014
+ optionList.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
3015
+ "option",
2460
3016
  {
2461
- className: cn(
2462
- theme.slots.switchThumb,
2463
- resolvedChecked && "translate-x-5",
2464
- classNames?.thumb
2465
- ),
2466
- style: theme.styles.switchThumb
2467
- }
2468
- )
3017
+ value: option.value,
3018
+ disabled: option.disabled,
3019
+ children: typeof option.label === "string" ? option.label : option.value
3020
+ },
3021
+ option.value
3022
+ ))
2469
3023
  ]
2470
3024
  }
2471
3025
  ),
2472
- hasRenderableNode(label) || hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(theme.slots.switchContent, classNames?.content), children: [
2473
- hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.switchLabel, classNames?.label), children: label }) : null,
2474
- hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
2475
- "span",
2476
- {
2477
- className: cn(
2478
- theme.slots.switchDescription,
2479
- classNames?.description
2480
- ),
2481
- children: description
2482
- }
2483
- ) : null
2484
- ] }) : null
2485
- ]
2486
- }
2487
- );
2488
- }
2489
- );
2490
- var DATA_TRANSFER_COLUMN_TYPE = "application/x-monkeys-base-table-column";
2491
- var BaseTableContext = react.createContext(null);
2492
- function useBaseTableContext(appearance) {
2493
- const context = react.useContext(BaseTableContext);
2494
- if (context) {
2495
- return {
2496
- ...context,
2497
- theme: appearance ? resolveBaseAppearance(appearance) : context.theme,
2498
- appearance: appearance ?? context.appearance
2499
- };
2500
- }
2501
- const theme = resolveBaseAppearance(appearance);
2502
- return {
3026
+ open ? /* @__PURE__ */ jsxRuntime.jsx(
3027
+ "div",
3028
+ {
3029
+ id: listboxId,
3030
+ role: "listbox",
3031
+ "aria-labelledby": `${selectId}-button`,
3032
+ className: cn(theme.slots.selectMenu, classNames?.menu),
3033
+ style: theme.styles.selectMenu,
3034
+ children: optionList.map((option, index) => {
3035
+ const selected = option.value === selectedValue;
3036
+ const active = index === activeIndex;
3037
+ return /* @__PURE__ */ jsxRuntime.jsx(
3038
+ "button",
3039
+ {
3040
+ type: "button",
3041
+ role: "option",
3042
+ "aria-selected": selected,
3043
+ disabled: option.disabled,
3044
+ className: cn(
3045
+ theme.slots.selectOption,
3046
+ active && theme.slots.selectOptionActive,
3047
+ selected && theme.slots.selectOptionSelected,
3048
+ option.disabled && theme.slots.selectOptionDisabled,
3049
+ classNames?.option
3050
+ ),
3051
+ style: {
3052
+ ...theme.styles.selectOption,
3053
+ ...active ? theme.styles.selectOptionActive : void 0,
3054
+ ...selected ? theme.styles.selectOptionSelected : void 0
3055
+ },
3056
+ onMouseDown: (event) => event.preventDefault(),
3057
+ onClick: () => commitValue(option.value, option.disabled),
3058
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: option.label })
3059
+ },
3060
+ option.value
3061
+ );
3062
+ })
3063
+ }
3064
+ ) : null
3065
+ ]
3066
+ }
3067
+ );
3068
+ }
3069
+ );
3070
+ function getInitialSegmentValue(options, defaultValue) {
3071
+ if (defaultValue && options?.some((option) => option.value === defaultValue)) {
3072
+ const defaultOption = options.find((option) => option.value === defaultValue);
3073
+ if (!defaultOption?.disabled) {
3074
+ return defaultValue;
3075
+ }
3076
+ }
3077
+ return options?.find((option) => !option.disabled)?.value ?? options?.[0]?.value;
3078
+ }
3079
+ function BaseSegmentedControl({
3080
+ options = [],
3081
+ value,
3082
+ defaultValue,
3083
+ appearance,
3084
+ className,
3085
+ classNames,
3086
+ style,
3087
+ onValueChange,
3088
+ ...controlProps
3089
+ }) {
3090
+ const theme = resolveBaseAppearance(appearance);
3091
+ const [uncontrolledValue, setUncontrolledValue] = react.useState(
3092
+ () => getInitialSegmentValue(options, defaultValue)
3093
+ );
3094
+ const isControlled = value !== void 0;
3095
+ const selectedValue = isControlled ? value : uncontrolledValue;
3096
+ const handleSelect = (nextValue, disabled) => {
3097
+ if (disabled) return;
3098
+ if (!isControlled) {
3099
+ setUncontrolledValue(nextValue);
3100
+ }
3101
+ onValueChange?.(nextValue);
3102
+ };
3103
+ return /* @__PURE__ */ jsxRuntime.jsx(
3104
+ "div",
3105
+ {
3106
+ ...controlProps,
3107
+ role: "radiogroup",
3108
+ className: cn(theme.slots.segmentedRoot, classNames?.root, className),
3109
+ style: {
3110
+ ...theme.styles.segmentedRoot,
3111
+ ...style
3112
+ },
3113
+ children: options.map((option) => {
3114
+ const selected = option.value === selectedValue;
3115
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3116
+ "button",
3117
+ {
3118
+ type: "button",
3119
+ role: "radio",
3120
+ "aria-checked": selected,
3121
+ disabled: option.disabled,
3122
+ className: cn(
3123
+ theme.slots.segmentedItem,
3124
+ selected && theme.slots.segmentedItemActive,
3125
+ option.disabled && theme.slots.segmentedItemDisabled,
3126
+ classNames?.item
3127
+ ),
3128
+ style: theme.styles.segmentedItem,
3129
+ onClick: () => handleSelect(option.value, option.disabled),
3130
+ children: [
3131
+ hasRenderableNode(option.icon) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex h-4 w-4 shrink-0", classNames?.icon), children: option.icon }) : null,
3132
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("min-w-0 truncate", classNames?.label), children: option.label })
3133
+ ]
3134
+ },
3135
+ option.value
3136
+ );
3137
+ })
3138
+ }
3139
+ );
3140
+ }
3141
+ react.forwardRef(
3142
+ function BaseSwitch2({
3143
+ label,
3144
+ description,
3145
+ disabled = false,
3146
+ appearance,
3147
+ className,
3148
+ classNames,
3149
+ style,
3150
+ checked,
3151
+ defaultChecked,
3152
+ onChange,
3153
+ ...switchProps
3154
+ }, ref) {
3155
+ const theme = resolveBaseAppearance(appearance);
3156
+ const [uncontrolledChecked, setUncontrolledChecked] = react.useState(
3157
+ defaultChecked ?? false
3158
+ );
3159
+ const isControlled = checked !== void 0;
3160
+ const resolvedChecked = isControlled ? checked : uncontrolledChecked;
3161
+ const handleChange = (event) => {
3162
+ if (!isControlled) {
3163
+ setUncontrolledChecked(event.currentTarget.checked);
3164
+ }
3165
+ onChange?.(event);
3166
+ };
3167
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3168
+ "label",
3169
+ {
3170
+ className: cn(
3171
+ theme.slots.switchRoot,
3172
+ disabled && theme.slots.switchDisabled,
3173
+ classNames?.root,
3174
+ className
3175
+ ),
3176
+ style: {
3177
+ ...theme.styles.switchRoot,
3178
+ ...style
3179
+ },
3180
+ children: [
3181
+ /* @__PURE__ */ jsxRuntime.jsxs(
3182
+ "span",
3183
+ {
3184
+ className: cn(
3185
+ theme.slots.switchTrack,
3186
+ resolvedChecked && theme.slots.switchChecked,
3187
+ classNames?.track
3188
+ ),
3189
+ style: theme.styles.switchTrack,
3190
+ children: [
3191
+ /* @__PURE__ */ jsxRuntime.jsx(
3192
+ "input",
3193
+ {
3194
+ ...switchProps,
3195
+ ref,
3196
+ type: "checkbox",
3197
+ disabled,
3198
+ checked,
3199
+ defaultChecked,
3200
+ onChange: handleChange,
3201
+ className: cn(theme.slots.switchInput, classNames?.input)
3202
+ }
3203
+ ),
3204
+ /* @__PURE__ */ jsxRuntime.jsx(
3205
+ "span",
3206
+ {
3207
+ className: cn(
3208
+ theme.slots.switchThumb,
3209
+ resolvedChecked && "translate-x-5",
3210
+ classNames?.thumb
3211
+ ),
3212
+ style: theme.styles.switchThumb
3213
+ }
3214
+ )
3215
+ ]
3216
+ }
3217
+ ),
3218
+ hasRenderableNode(label) || hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(theme.slots.switchContent, classNames?.content), children: [
3219
+ hasRenderableNode(label) ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(theme.slots.switchLabel, classNames?.label), children: label }) : null,
3220
+ hasRenderableNode(description) ? /* @__PURE__ */ jsxRuntime.jsx(
3221
+ "span",
3222
+ {
3223
+ className: cn(
3224
+ theme.slots.switchDescription,
3225
+ classNames?.description
3226
+ ),
3227
+ children: description
3228
+ }
3229
+ ) : null
3230
+ ] }) : null
3231
+ ]
3232
+ }
3233
+ );
3234
+ }
3235
+ );
3236
+ var DATA_TRANSFER_COLUMN_TYPE = "application/x-monkeys-base-table-column";
3237
+ var BaseTableContext = react.createContext(null);
3238
+ function useBaseTableContext(appearance) {
3239
+ const context = react.useContext(BaseTableContext);
3240
+ if (context) {
3241
+ return {
3242
+ ...context,
3243
+ theme: appearance ? resolveBaseAppearance(appearance) : context.theme,
3244
+ appearance: appearance ?? context.appearance
3245
+ };
3246
+ }
3247
+ const theme = resolveBaseAppearance(appearance);
3248
+ return {
2503
3249
  appearance,
2504
3250
  theme,
2505
3251
  setDraggingColumnId: () => {
@@ -2699,7 +3445,7 @@ function BaseTableRow({
2699
3445
  }
2700
3446
  );
2701
3447
  }
2702
- function BaseTableHead({
3448
+ var BaseTableHead = react.forwardRef(function BaseTableHead2({
2703
3449
  columnId,
2704
3450
  align = "left",
2705
3451
  icon,
@@ -2727,10 +3473,18 @@ function BaseTableHead({
2727
3473
  onDragOver,
2728
3474
  onDrop,
2729
3475
  ...headProps
2730
- }) {
3476
+ }, forwardedRef) {
2731
3477
  const tableContext = useBaseTableContext(appearance);
2732
3478
  const { theme } = tableContext;
2733
3479
  const headRef = react.useRef(null);
3480
+ const setHeadRef = (node) => {
3481
+ headRef.current = node;
3482
+ if (typeof forwardedRef === "function") {
3483
+ forwardedRef(node);
3484
+ } else if (forwardedRef) {
3485
+ forwardedRef.current = node;
3486
+ }
3487
+ };
2734
3488
  const controlledWidth = columnId && tableContext.columnSizes?.[columnId] !== void 0 ? tableContext.columnSizes[columnId] : width;
2735
3489
  const canDrag = Boolean(
2736
3490
  columnId && draggable !== false && (draggable || tableContext.columnDragEnabled) && tableContext.columnOrder && tableContext.onColumnOrderChange
@@ -2885,7 +3639,7 @@ function BaseTableHead({
2885
3639
  "th",
2886
3640
  {
2887
3641
  ...headProps,
2888
- ref: headRef,
3642
+ ref: setHeadRef,
2889
3643
  scope: headProps.scope ?? "col",
2890
3644
  "aria-sort": ariaSort,
2891
3645
  className: cn(
@@ -2920,7 +3674,7 @@ function BaseTableHead({
2920
3674
  ]
2921
3675
  }
2922
3676
  );
2923
- }
3677
+ });
2924
3678
  function BaseTableCell({
2925
3679
  align = "left",
2926
3680
  appearance,
@@ -3978,340 +4732,993 @@ var WorkbenchDetailSidebar = react.forwardRef(
3978
4732
  classNames?.root,
3979
4733
  className
3980
4734
  ),
3981
- style: {
3982
- ...resolveWidthStyle(open, width),
3983
- ...style
3984
- },
3985
- ...props,
3986
- children: [
3987
- resizeHandle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(classNames?.resizeHandle, resizeHandleClassName), children: resizeHandle }) : null,
3988
- header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 border-b border-border/40 px-4 py-3 dark:border-border/30", classNames?.header, headerClassName), children: header }) : null,
3989
- renderBodyWrapper ? /* @__PURE__ */ jsxRuntime.jsx(
3990
- BodyComponent,
3991
- {
3992
- className: cn("min-h-0 flex-1 overflow-y-auto", classNames?.body, bodyClassName, bodyPropsClassName),
3993
- ...restBodyProps,
3994
- children: autoContent
3995
- }
3996
- ) : autoContent,
3997
- footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 border-t border-border/40 px-4 py-3 dark:border-border/30", classNames?.footer, footerClassName), children: footer }) : null
3998
- ]
3999
- }
4000
- );
4001
- }
4002
- );
4003
- function isWorkbenchIconComponent(icon) {
4004
- if (typeof icon === "function") return true;
4005
- return typeof icon === "object" && icon !== null && !react.isValidElement(icon) && "$$typeof" in icon;
4735
+ style: {
4736
+ ...resolveWidthStyle(open, width),
4737
+ ...style
4738
+ },
4739
+ ...props,
4740
+ children: [
4741
+ resizeHandle ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(classNames?.resizeHandle, resizeHandleClassName), children: resizeHandle }) : null,
4742
+ header ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 border-b border-border/40 px-4 py-3 dark:border-border/30", classNames?.header, headerClassName), children: header }) : null,
4743
+ renderBodyWrapper ? /* @__PURE__ */ jsxRuntime.jsx(
4744
+ BodyComponent,
4745
+ {
4746
+ className: cn("min-h-0 flex-1 overflow-y-auto", classNames?.body, bodyClassName, bodyPropsClassName),
4747
+ ...restBodyProps,
4748
+ children: autoContent
4749
+ }
4750
+ ) : autoContent,
4751
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 border-t border-border/40 px-4 py-3 dark:border-border/30", classNames?.footer, footerClassName), children: footer }) : null
4752
+ ]
4753
+ }
4754
+ );
4755
+ }
4756
+ );
4757
+ function isWorkbenchIconComponent(icon) {
4758
+ if (typeof icon === "function") return true;
4759
+ return typeof icon === "object" && icon !== null && !react.isValidElement(icon) && "$$typeof" in icon;
4760
+ }
4761
+ function renderWorkbenchIcon(icon, className) {
4762
+ if (!icon) return null;
4763
+ if (react.isValidElement(icon)) return icon;
4764
+ if (isWorkbenchIconComponent(icon)) {
4765
+ const Icon = icon;
4766
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon, { className });
4767
+ }
4768
+ return icon;
4769
+ }
4770
+ function getWorkbenchIconComponent(icon) {
4771
+ if (!icon || !isWorkbenchIconComponent(icon)) return null;
4772
+ return icon;
4773
+ }
4774
+ function toCssSize2(value) {
4775
+ if (value === void 0) return void 0;
4776
+ return typeof value === "number" ? `${value}px` : value;
4777
+ }
4778
+ function defaultFormatLabel(value) {
4779
+ if (value === void 0 || value === null || value === false) return null;
4780
+ return value;
4781
+ }
4782
+ function toTitle(value) {
4783
+ if (typeof value === "string" || typeof value === "number") return String(value);
4784
+ return void 0;
4785
+ }
4786
+ function defaultGetRowKey(row, rowIndex) {
4787
+ return row?.id ?? row?.key ?? row?.linkKey ?? rowIndex;
4788
+ }
4789
+ function defaultGetRowSelectionKey(row) {
4790
+ return row?.linkKey ?? row?.id ?? row?.key;
4791
+ }
4792
+ function getOrderedColumns(columns, columnOrder) {
4793
+ if (!columnOrder?.length) return columns;
4794
+ const columnMap = new Map(columns.map((column) => [column.key, column]));
4795
+ const orderedColumns = columnOrder.map((columnKey) => columnMap.get(columnKey)).filter(Boolean);
4796
+ const orderedKeySet = new Set(orderedColumns.map((column) => column.key));
4797
+ const remainingColumns = columns.filter((column) => !orderedKeySet.has(column.key));
4798
+ return [...orderedColumns, ...remainingColumns];
4799
+ }
4800
+ function normalizeColumnOrder(columnKeys, columnOrder) {
4801
+ const validColumnKeys = new Set(columnKeys);
4802
+ const orderedKeys = (columnOrder || []).filter((columnKey) => validColumnKeys.has(columnKey));
4803
+ const orderedKeySet = new Set(orderedKeys);
4804
+ const remainingKeys = columnKeys.filter((columnKey) => !orderedKeySet.has(columnKey));
4805
+ return [...orderedKeys, ...remainingKeys];
4806
+ }
4807
+ function WorkbenchTableHeaderHelper({
4808
+ helperText,
4809
+ className
4810
+ }) {
4811
+ if (!hasRenderableNode(helperText)) return null;
4812
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("group relative inline-flex items-center", className), children: [
4813
+ /* @__PURE__ */ jsxRuntime.jsx(
4814
+ "button",
4815
+ {
4816
+ type: "button",
4817
+ title: toTitle(helperText),
4818
+ "aria-label": toTitle(helperText) || "Field help",
4819
+ className: "inline-flex h-4 w-4 items-center justify-center rounded-full border border-border/60 bg-background text-[10px] font-semibold normal-case tracking-normal text-muted-foreground shadow-sm transition-colors hover:border-primary/40 hover:text-primary focus-visible:border-primary/40 focus-visible:text-primary focus-visible:outline-none",
4820
+ onClick: (event) => event.stopPropagation(),
4821
+ children: "?"
4822
+ }
4823
+ ),
4824
+ /* @__PURE__ */ jsxRuntime.jsx(
4825
+ "span",
4826
+ {
4827
+ role: "tooltip",
4828
+ className: "pointer-events-none absolute left-1/2 top-full z-40 mt-2 hidden w-72 -translate-x-1/2 whitespace-pre-line rounded-lg border border-border/60 bg-card px-3 py-2 text-[11px] font-normal normal-case leading-5 tracking-normal text-foreground shadow-sm backdrop-blur-sm group-hover:block group-focus-within:block",
4829
+ children: helperText
4830
+ }
4831
+ )
4832
+ ] });
4833
+ }
4834
+ function WorkbenchTableView({
4835
+ rows = [],
4836
+ columns = [],
4837
+ onRowClick,
4838
+ selectedRowKey,
4839
+ selectedLinkKey,
4840
+ activePrimaryColumn,
4841
+ activeTablePrimaryColumn,
4842
+ renderedRowCount,
4843
+ totalRowCount,
4844
+ tableMinWidth,
4845
+ minWidth,
4846
+ bodyMaxHeight = "min(58vh, 38rem)",
4847
+ stickyFirstColumn = true,
4848
+ appearance,
4849
+ columnOrder,
4850
+ columnSizes,
4851
+ columnDragEnabled,
4852
+ columnResizeEnabled,
4853
+ className,
4854
+ tableClassName,
4855
+ rowClassName,
4856
+ classNames,
4857
+ style,
4858
+ renderCell,
4859
+ renderFieldValue,
4860
+ renderColumnHeader,
4861
+ onColumnOrderChange,
4862
+ onColumnSizeChange,
4863
+ onSort,
4864
+ formatLabel = defaultFormatLabel,
4865
+ getColumnDataType,
4866
+ getColumnIcon,
4867
+ getColumnTypeIcon,
4868
+ getRowKey = defaultGetRowKey,
4869
+ getRowSelectionKey = defaultGetRowSelectionKey,
4870
+ isActionColumn,
4871
+ isActionField,
4872
+ isRowDisabled,
4873
+ isWorkbenchPlaceholderRow,
4874
+ emptyState = "-",
4875
+ hiddenRowsMessage
4876
+ }) {
4877
+ const columnKeySignature = columns.map((column) => column.key).join("");
4878
+ const defaultColumnOrder = react.useMemo(() => columnKeySignature ? columnKeySignature.split("") : [], [columnKeySignature]);
4879
+ const [internalColumnOrder, setInternalColumnOrder] = react.useState(defaultColumnOrder);
4880
+ const [internalColumnSizes, setInternalColumnSizes] = react.useState({});
4881
+ react.useEffect(() => {
4882
+ setInternalColumnOrder((current) => normalizeColumnOrder(defaultColumnOrder, current));
4883
+ }, [defaultColumnOrder]);
4884
+ const resolvedColumnOrder = columnOrder ? normalizeColumnOrder(defaultColumnOrder, columnOrder) : internalColumnOrder;
4885
+ const resolvedColumnSizes = columnSizes ?? internalColumnSizes;
4886
+ const handleColumnOrderChange = react.useCallback((nextOrder, detail) => {
4887
+ const normalizedOrder = normalizeColumnOrder(defaultColumnOrder, nextOrder);
4888
+ if (!columnOrder) {
4889
+ setInternalColumnOrder(normalizedOrder);
4890
+ }
4891
+ onColumnOrderChange?.(normalizedOrder, detail);
4892
+ }, [columnOrder, defaultColumnOrder, onColumnOrderChange]);
4893
+ const handleColumnSizeChange = react.useCallback((columnId, width, detail) => {
4894
+ if (!columnSizes) {
4895
+ setInternalColumnSizes((current) => ({
4896
+ ...current,
4897
+ [columnId]: width
4898
+ }));
4899
+ }
4900
+ onColumnSizeChange?.(columnId, width, detail);
4901
+ }, [columnSizes, onColumnSizeChange]);
4902
+ const resolvedSelectedKey = selectedRowKey ?? selectedLinkKey;
4903
+ const resolvedActivePrimaryColumn = activePrimaryColumn ?? activeTablePrimaryColumn;
4904
+ const orderedColumns = getOrderedColumns(columns, resolvedColumnOrder);
4905
+ const hiddenRowCount = Math.max(0, Number(totalRowCount || rows.length) - Number(renderedRowCount || rows.length));
4906
+ const resolvedMinWidth = tableMinWidth ?? minWidth ?? Math.max(760, Math.min(orderedColumns.length * 112, 1440));
4907
+ const renderValue = renderCell ?? renderFieldValue ?? ((column, row) => row?.[column.key]);
4908
+ const isAction = isActionColumn ?? isActionField ?? (() => false);
4909
+ const isDisabled = isRowDisabled ?? isWorkbenchPlaceholderRow ?? (() => false);
4910
+ const resolveColumnIcon = getColumnIcon ?? getColumnTypeIcon;
4911
+ const footer = hiddenRowCount > 0 && hiddenRowsMessage ? typeof hiddenRowsMessage === "function" ? hiddenRowsMessage(hiddenRowCount, renderedRowCount || rows.length, totalRowCount || rows.length) : hiddenRowsMessage : null;
4912
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4913
+ BaseTableContainer,
4914
+ {
4915
+ appearance,
4916
+ className: cn("w-full overflow-hidden rounded-lg border border-border/40 bg-muted/15 dark:border-border/35 dark:bg-muted/10", classNames?.root, className),
4917
+ style,
4918
+ children: [
4919
+ /* @__PURE__ */ jsxRuntime.jsx(
4920
+ "div",
4921
+ {
4922
+ className: cn("w-full overflow-auto", classNames?.scrollArea),
4923
+ style: { maxHeight: toCssSize2(bodyMaxHeight) },
4924
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4925
+ BaseTable,
4926
+ {
4927
+ appearance,
4928
+ columnOrder: resolvedColumnOrder,
4929
+ columnSizes: resolvedColumnSizes,
4930
+ columnDragEnabled,
4931
+ columnResizeEnabled,
4932
+ onColumnOrderChange: handleColumnOrderChange,
4933
+ onColumnSizeChange: handleColumnSizeChange,
4934
+ className: cn("w-full table-auto text-left text-xs", classNames?.table, tableClassName),
4935
+ style: { minWidth: resolvedMinWidth },
4936
+ children: [
4937
+ /* @__PURE__ */ jsxRuntime.jsx(BaseTableHeader, { appearance, className: cn("text-[10px] font-mono uppercase tracking-wide text-muted-foreground", classNames?.header), children: /* @__PURE__ */ jsxRuntime.jsx(BaseTableRow, { className: cn("hover:bg-transparent", classNames?.headerRow), children: orderedColumns.map((column, columnIndex) => {
4938
+ const columnType = column.renderType || column.type || getColumnDataType?.(column.key, rows, column);
4939
+ const columnIcon = renderWorkbenchIcon(
4940
+ resolveColumnIcon?.(columnType, column),
4941
+ "h-3.5 w-3.5 shrink-0 text-primary"
4942
+ );
4943
+ const previousColumn = orderedColumns[columnIndex - 1];
4944
+ const followsRecordIcon = previousColumn?.renderType === "icon" && column.key === resolvedActivePrimaryColumn?.key;
4945
+ const headerContent = renderColumnHeader ? renderColumnHeader(column, { column, columnIndex, columns: orderedColumns, rows, columnType }) : formatLabel(column.label, { column });
4946
+ const headerTrailing = !renderColumnHeader && (hasRenderableNode(column.trailing) || hasRenderableNode(column.helperText)) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
4947
+ hasRenderableNode(column.trailing) ? formatLabel(column.trailing, { column }) : null,
4948
+ /* @__PURE__ */ jsxRuntime.jsx(WorkbenchTableHeaderHelper, { helperText: formatLabel(column.helperText, { column }), className: classNames?.helper })
4949
+ ] }) : void 0;
4950
+ const sortable = Boolean(column.sortable);
4951
+ const handleSort = sortable && onSort ? () => onSort(column.key, column) : void 0;
4952
+ return /* @__PURE__ */ jsxRuntime.jsx(
4953
+ BaseTableHead,
4954
+ {
4955
+ appearance,
4956
+ columnId: column.key,
4957
+ align: column.align,
4958
+ icon: renderColumnHeader ? void 0 : columnIcon,
4959
+ label: headerContent,
4960
+ description: renderColumnHeader ? void 0 : formatLabel(column.description, { column }),
4961
+ meta: renderColumnHeader ? void 0 : formatLabel(column.meta, { column }),
4962
+ actions: renderColumnHeader ? void 0 : column.actions,
4963
+ trailing: headerTrailing,
4964
+ sortable,
4965
+ sortDirection: column.sortDirection,
4966
+ sortLabel: column.sortLabel,
4967
+ onSort: handleSort,
4968
+ draggable: column.draggable,
4969
+ dragLabel: column.dragLabel,
4970
+ resizable: column.resizable,
4971
+ resizeLabel: column.resizeLabel,
4972
+ width: column.width,
4973
+ minWidth: typeof column.minWidth === "number" ? column.minWidth : void 0,
4974
+ maxWidth: typeof column.maxWidth === "number" ? column.maxWidth : void 0,
4975
+ className: cn(
4976
+ "sticky top-0 z-20 h-auto whitespace-nowrap bg-card/95 px-4 py-3 font-medium backdrop-blur-sm supports-[backdrop-filter]:bg-card/90",
4977
+ stickyFirstColumn && columnIndex === 0 && "left-0 z-30 shadow-[1px_0_0_0_hsl(var(--border)/0.35)]",
4978
+ column.compactHeaderClassName,
4979
+ column.headerClassName,
4980
+ column.renderType === "icon" && "pl-3 pr-1",
4981
+ followsRecordIcon && "pl-2",
4982
+ classNames?.headerCell
4983
+ ),
4984
+ style: {
4985
+ minWidth: typeof column.minWidth === "string" ? column.minWidth : void 0,
4986
+ maxWidth: typeof column.maxWidth === "string" ? column.maxWidth : void 0
4987
+ }
4988
+ },
4989
+ column.key
4990
+ );
4991
+ }) }) }),
4992
+ /* @__PURE__ */ jsxRuntime.jsx(BaseTableBody, { appearance, className: cn("divide-y divide-border/35 dark:divide-border/30", classNames?.body), children: rows.length ? rows.map((row, rowIndex) => {
4993
+ const key = getRowKey(row, rowIndex);
4994
+ const disabled = isDisabled(row, rowIndex);
4995
+ const selectionKey = getRowSelectionKey(row, rowIndex);
4996
+ const selected = Boolean(resolvedSelectedKey && String(selectionKey) === String(resolvedSelectedKey));
4997
+ const resolvedRowClassName = typeof rowClassName === "function" ? rowClassName(row, rowIndex) : rowClassName;
4998
+ return /* @__PURE__ */ jsxRuntime.jsx(
4999
+ BaseTableRow,
5000
+ {
5001
+ appearance,
5002
+ interactive: Boolean(onRowClick) && !disabled,
5003
+ selected,
5004
+ disabled,
5005
+ onClick: () => {
5006
+ if (!disabled) {
5007
+ onRowClick?.(row, rowIndex);
5008
+ }
5009
+ },
5010
+ className: cn(
5011
+ onRowClick && !disabled ? "cursor-pointer" : "cursor-default",
5012
+ selected ? "bg-primary/10 hover:bg-primary/15" : disabled ? "" : "hover:bg-muted/25 dark:hover:bg-muted/15",
5013
+ classNames?.row,
5014
+ resolvedRowClassName
5015
+ ),
5016
+ children: orderedColumns.map((column, columnIndex) => {
5017
+ const shouldWrap = isAction(column) || column.wrap === true;
5018
+ const previousColumn = orderedColumns[columnIndex - 1];
5019
+ const followsRecordIcon = previousColumn?.renderType === "icon" && column.key === resolvedActivePrimaryColumn?.key;
5020
+ return /* @__PURE__ */ jsxRuntime.jsx(
5021
+ BaseTableCell,
5022
+ {
5023
+ appearance,
5024
+ align: column.align,
5025
+ className: cn(
5026
+ shouldWrap ? "align-top whitespace-normal" : "whitespace-nowrap",
5027
+ "px-4 py-3 text-muted-foreground",
5028
+ stickyFirstColumn && columnIndex === 0 && "sticky left-0 z-10 bg-card/95 text-foreground shadow-[1px_0_0_0_hsl(var(--border)/0.3)]",
5029
+ column.compactCellClassName,
5030
+ column.cellClassName,
5031
+ column.renderType === "icon" && "pl-3 pr-1",
5032
+ followsRecordIcon && "pl-2",
5033
+ classNames?.cell
5034
+ ),
5035
+ children: renderValue(column, row, {
5036
+ row,
5037
+ rowIndex,
5038
+ column,
5039
+ columnIndex,
5040
+ compact: true,
5041
+ surface: "list"
5042
+ })
5043
+ },
5044
+ `${key}-${column.key}`
5045
+ );
5046
+ })
5047
+ },
5048
+ key
5049
+ );
5050
+ }) : /* @__PURE__ */ jsxRuntime.jsx(
5051
+ BaseTableEmpty,
5052
+ {
5053
+ appearance,
5054
+ colSpan: Math.max(orderedColumns.length, 1),
5055
+ classNames: { cell: "px-4 py-10 text-center text-sm text-muted-foreground" },
5056
+ children: emptyState
5057
+ }
5058
+ ) })
5059
+ ]
5060
+ }
5061
+ )
5062
+ }
5063
+ ),
5064
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border-t border-border/40 px-4 py-2 text-[11px] text-muted-foreground dark:border-border/30", classNames?.footer), children: footer }) : null
5065
+ ]
5066
+ }
5067
+ );
4006
5068
  }
4007
- function renderWorkbenchIcon(icon, className) {
4008
- if (!icon) return null;
4009
- if (react.isValidElement(icon)) return icon;
4010
- if (isWorkbenchIconComponent(icon)) {
4011
- const Icon = icon;
4012
- return /* @__PURE__ */ jsxRuntime.jsx(Icon, { className });
5069
+ function toCssSize3(value) {
5070
+ if (value === void 0) return void 0;
5071
+ return typeof value === "number" ? `${value}px` : value;
5072
+ }
5073
+ function isBrowser() {
5074
+ return typeof window !== "undefined";
5075
+ }
5076
+ function defaultGetRowKey2(row, rowIndex) {
5077
+ return row?.id ?? row?.key ?? rowIndex;
5078
+ }
5079
+ function getColumnDefaultSize(column) {
5080
+ if (typeof column.width === "number") return column.width;
5081
+ if (typeof column.minWidth === "number") return column.minWidth;
5082
+ return 160;
5083
+ }
5084
+ function buildDefaultColumnSizes(columns, explicit) {
5085
+ return columns.reduce((acc, column) => {
5086
+ acc[column.key] = explicit?.[column.key] ?? getColumnDefaultSize(column);
5087
+ return acc;
5088
+ }, {});
5089
+ }
5090
+ function loadStoredColumnSizes(storageKey, defaults) {
5091
+ if (!storageKey || !isBrowser()) return defaults;
5092
+ try {
5093
+ const parsed = JSON.parse(window.localStorage.getItem(storageKey) || "{}");
5094
+ return Object.keys(defaults).reduce((acc, key) => {
5095
+ const value = Number(parsed?.[key]);
5096
+ acc[key] = Number.isFinite(value) ? value : defaults[key];
5097
+ return acc;
5098
+ }, {});
5099
+ } catch {
5100
+ return defaults;
4013
5101
  }
4014
- return icon;
4015
5102
  }
4016
- function getWorkbenchIconComponent(icon) {
4017
- if (!icon || !isWorkbenchIconComponent(icon)) return null;
4018
- return icon;
5103
+ function persistColumnSizes(storageKey, sizes) {
5104
+ if (!storageKey || !isBrowser()) return;
5105
+ window.localStorage.setItem(storageKey, JSON.stringify(sizes));
4019
5106
  }
4020
- function toCssSize2(value) {
4021
- if (value === void 0) return void 0;
4022
- return typeof value === "number" ? `${value}px` : value;
5107
+ function getFrozenColumnStorageKey(storageKey) {
5108
+ return storageKey ? `${storageKey}.frozenColumnCount` : void 0;
4023
5109
  }
4024
- function defaultFormatLabel(value) {
4025
- if (value === void 0 || value === null || value === false) return null;
4026
- return value;
5110
+ function getFrozenEndColumnStorageKey(storageKey) {
5111
+ return storageKey ? `${storageKey}.frozenEndColumnCount` : void 0;
4027
5112
  }
4028
- function toTitle(value) {
4029
- if (typeof value === "string" || typeof value === "number") return String(value);
4030
- return void 0;
5113
+ function clampFrozenColumnCount(count, columnCount) {
5114
+ if (!Number.isFinite(count)) return 0;
5115
+ return Math.max(0, Math.min(Math.round(count), columnCount));
4031
5116
  }
4032
- function defaultGetRowKey(row, rowIndex) {
4033
- return row?.id ?? row?.key ?? row?.linkKey ?? rowIndex;
5117
+ function normalizeFrozenColumnCounts(startCount, endCount, columnCount) {
5118
+ const normalizedStartCount = clampFrozenColumnCount(startCount, columnCount);
5119
+ const normalizedEndCount = clampFrozenColumnCount(endCount, Math.max(0, columnCount - normalizedStartCount));
5120
+ return {
5121
+ startCount: normalizedStartCount,
5122
+ endCount: normalizedEndCount
5123
+ };
4034
5124
  }
4035
- function defaultGetRowSelectionKey(row) {
4036
- return row?.linkKey ?? row?.id ?? row?.key;
5125
+ function loadStoredFrozenColumnCount(storageKey, defaultCount, columnCount) {
5126
+ const fallback = clampFrozenColumnCount(defaultCount, columnCount);
5127
+ const frozenStorageKey = getFrozenColumnStorageKey(storageKey);
5128
+ if (!frozenStorageKey || !isBrowser()) return fallback;
5129
+ try {
5130
+ const storedValue = window.localStorage.getItem(frozenStorageKey);
5131
+ if (storedValue === null) return fallback;
5132
+ const value = Number(storedValue);
5133
+ return Number.isFinite(value) ? clampFrozenColumnCount(value, columnCount) : fallback;
5134
+ } catch {
5135
+ return fallback;
5136
+ }
4037
5137
  }
4038
- function getOrderedColumns(columns, columnOrder) {
4039
- if (!columnOrder?.length) return columns;
4040
- const columnMap = new Map(columns.map((column) => [column.key, column]));
4041
- const orderedColumns = columnOrder.map((columnKey) => columnMap.get(columnKey)).filter(Boolean);
4042
- const orderedKeySet = new Set(orderedColumns.map((column) => column.key));
4043
- const remainingColumns = columns.filter((column) => !orderedKeySet.has(column.key));
4044
- return [...orderedColumns, ...remainingColumns];
5138
+ function persistFrozenColumnCount(storageKey, count) {
5139
+ const frozenStorageKey = getFrozenColumnStorageKey(storageKey);
5140
+ if (!frozenStorageKey || !isBrowser()) return;
5141
+ window.localStorage.setItem(frozenStorageKey, String(count));
4045
5142
  }
4046
- function normalizeColumnOrder(columnKeys, columnOrder) {
5143
+ function loadStoredFrozenEndColumnCount(storageKey, defaultCount, columnCount) {
5144
+ const fallback = clampFrozenColumnCount(defaultCount, columnCount);
5145
+ const frozenStorageKey = getFrozenEndColumnStorageKey(storageKey);
5146
+ if (!frozenStorageKey || !isBrowser()) return fallback;
5147
+ try {
5148
+ const storedValue = window.localStorage.getItem(frozenStorageKey);
5149
+ if (storedValue === null) return fallback;
5150
+ const value = Number(storedValue);
5151
+ return Number.isFinite(value) ? clampFrozenColumnCount(value, columnCount) : fallback;
5152
+ } catch {
5153
+ return fallback;
5154
+ }
5155
+ }
5156
+ function persistFrozenEndColumnCount(storageKey, count) {
5157
+ const frozenStorageKey = getFrozenEndColumnStorageKey(storageKey);
5158
+ if (!frozenStorageKey || !isBrowser()) return;
5159
+ window.localStorage.setItem(frozenStorageKey, String(count));
5160
+ }
5161
+ function normalizeColumnOrder2(columnKeys, columnOrder) {
4047
5162
  const validColumnKeys = new Set(columnKeys);
4048
5163
  const orderedKeys = (columnOrder || []).filter((columnKey) => validColumnKeys.has(columnKey));
4049
5164
  const orderedKeySet = new Set(orderedKeys);
4050
5165
  const remainingKeys = columnKeys.filter((columnKey) => !orderedKeySet.has(columnKey));
4051
5166
  return [...orderedKeys, ...remainingKeys];
4052
5167
  }
4053
- function WorkbenchTableHeaderHelper({
4054
- helperText,
4055
- className
5168
+ function getOrderedColumns2(columns, columnOrder) {
5169
+ const normalizedOrder = normalizeColumnOrder2(columns.map((column) => column.key), columnOrder);
5170
+ const columnMap = new Map(columns.map((column) => [column.key, column]));
5171
+ return normalizedOrder.map((columnKey) => columnMap.get(columnKey)).filter(Boolean);
5172
+ }
5173
+ function getColumnNumericWidth(column, columnSizes) {
5174
+ const controlledWidth = columnSizes[column.key];
5175
+ if (typeof controlledWidth === "number") return controlledWidth;
5176
+ return getColumnDefaultSize(column);
5177
+ }
5178
+ function buildFrozenOffsets(columns, columnSizes, frozenColumnCount) {
5179
+ const offsets = /* @__PURE__ */ new Map();
5180
+ let left = 0;
5181
+ columns.slice(0, Math.max(0, frozenColumnCount)).forEach((column) => {
5182
+ offsets.set(column.key, left);
5183
+ left += getColumnNumericWidth(column, columnSizes);
5184
+ });
5185
+ return offsets;
5186
+ }
5187
+ function buildFrozenEndOffsets(columns, columnSizes, frozenEndColumnCount) {
5188
+ const offsets = /* @__PURE__ */ new Map();
5189
+ let right = 0;
5190
+ columns.slice(Math.max(0, columns.length - frozenEndColumnCount)).reverse().forEach((column) => {
5191
+ offsets.set(column.key, right);
5192
+ right += getColumnNumericWidth(column, columnSizes);
5193
+ });
5194
+ return offsets;
5195
+ }
5196
+ function resolveRowClassName(rowClassName, row, rowIndex) {
5197
+ return typeof rowClassName === "function" ? rowClassName(row, rowIndex) : rowClassName;
5198
+ }
5199
+ function renderDefaultCell(column, row) {
5200
+ const value = row?.[column.key];
5201
+ if (value === void 0 || value === null || value === "") return "\u2014";
5202
+ return String(value);
5203
+ }
5204
+ function InteractiveTableCellContent({
5205
+ children,
5206
+ wrap
4056
5207
  }) {
4057
- if (!hasRenderableNode(helperText)) return null;
4058
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("group relative inline-flex items-center", className), children: [
4059
- /* @__PURE__ */ jsxRuntime.jsx(
4060
- "button",
4061
- {
4062
- type: "button",
4063
- title: toTitle(helperText),
4064
- "aria-label": toTitle(helperText) || "Field help",
4065
- className: "inline-flex h-4 w-4 items-center justify-center rounded-full border border-border/60 bg-background text-[10px] font-semibold normal-case tracking-normal text-muted-foreground shadow-sm transition-colors hover:border-primary/40 hover:text-primary focus-visible:border-primary/40 focus-visible:text-primary focus-visible:outline-none",
4066
- onClick: (event) => event.stopPropagation(),
4067
- children: "?"
4068
- }
4069
- ),
4070
- /* @__PURE__ */ jsxRuntime.jsx(
4071
- "span",
4072
- {
4073
- role: "tooltip",
4074
- className: "pointer-events-none absolute left-1/2 top-full z-40 mt-2 hidden w-72 -translate-x-1/2 whitespace-pre-line rounded-lg border border-border/60 bg-card px-3 py-2 text-[11px] font-normal normal-case leading-5 tracking-normal text-foreground shadow-sm backdrop-blur-sm group-hover:block group-focus-within:block",
4075
- children: helperText
4076
- }
4077
- )
4078
- ] });
5208
+ return /* @__PURE__ */ jsxRuntime.jsx(
5209
+ "div",
5210
+ {
5211
+ className: cn(
5212
+ "min-w-0 max-w-full overflow-auto overscroll-contain [scrollbar-width:thin]",
5213
+ wrap ? "max-h-20 whitespace-pre-wrap break-words leading-5" : "whitespace-nowrap"
5214
+ ),
5215
+ children
5216
+ }
5217
+ );
4079
5218
  }
4080
- function WorkbenchTableView({
5219
+ function PinIcon({ className }) {
5220
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5221
+ "svg",
5222
+ {
5223
+ "aria-hidden": "true",
5224
+ viewBox: "0 0 16 16",
5225
+ className,
5226
+ fill: "none",
5227
+ stroke: "currentColor",
5228
+ strokeLinecap: "round",
5229
+ strokeLinejoin: "round",
5230
+ strokeWidth: "1.75",
5231
+ children: [
5232
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.25 2.75h5.5" }),
5233
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.25 2.75v4L4.5 9.25h7L9.75 6.75v-4" }),
5234
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 9.25v4" })
5235
+ ]
5236
+ }
5237
+ );
5238
+ }
5239
+ function InteractiveTable({
4081
5240
  rows = [],
4082
5241
  columns = [],
5242
+ pinnedTopRows = [],
5243
+ getRowKey = defaultGetRowKey2,
5244
+ getPinnedTopRowKey = defaultGetRowKey2,
5245
+ renderCell,
5246
+ renderPinnedTopCell,
5247
+ renderColumnHeader,
4083
5248
  onRowClick,
4084
- selectedRowKey,
4085
- selectedLinkKey,
4086
- activePrimaryColumn,
4087
- activeTablePrimaryColumn,
4088
- renderedRowCount,
4089
- totalRowCount,
4090
- tableMinWidth,
4091
- minWidth,
4092
- bodyMaxHeight = "min(58vh, 38rem)",
4093
- stickyFirstColumn = true,
4094
- appearance,
5249
+ getRowState,
5250
+ rowClassName,
5251
+ pinnedTopRowClassName,
5252
+ emptyState = "\u2014",
5253
+ columnMenuLabels,
5254
+ columnStorageKey,
4095
5255
  columnOrder,
4096
5256
  columnSizes,
4097
- columnDragEnabled,
4098
- columnResizeEnabled,
5257
+ defaultColumnSizes,
5258
+ columnDragEnabled = false,
5259
+ columnResizeEnabled = true,
5260
+ frozenColumnCount = 0,
5261
+ frozenEndColumnCount = 0,
5262
+ tableMinWidth,
5263
+ bodyMaxHeight = "min(60vh, 42rem)",
5264
+ appearance,
4099
5265
  className,
4100
5266
  tableClassName,
4101
- rowClassName,
4102
5267
  classNames,
4103
5268
  style,
4104
- renderCell,
4105
- renderFieldValue,
4106
- renderColumnHeader,
4107
5269
  onColumnOrderChange,
4108
5270
  onColumnSizeChange,
4109
- onSort,
4110
- formatLabel = defaultFormatLabel,
4111
- getColumnDataType,
4112
- getColumnIcon,
4113
- getColumnTypeIcon,
4114
- getRowKey = defaultGetRowKey,
4115
- getRowSelectionKey = defaultGetRowSelectionKey,
4116
- isActionColumn,
4117
- isActionField,
4118
- isRowDisabled,
4119
- isWorkbenchPlaceholderRow,
4120
- emptyState = "-",
4121
- hiddenRowsMessage
5271
+ onResetColumnSizes,
5272
+ onFrozenColumnCountChange,
5273
+ onFrozenEndColumnCountChange,
5274
+ onSort
4122
5275
  }) {
4123
5276
  const columnKeySignature = columns.map((column) => column.key).join("");
4124
- const defaultColumnOrder = react.useMemo(() => columnKeySignature ? columnKeySignature.split("") : [], [columnKeySignature]);
4125
- const [internalColumnOrder, setInternalColumnOrder] = react.useState(defaultColumnOrder);
4126
- const [internalColumnSizes, setInternalColumnSizes] = react.useState({});
5277
+ const defaultOrder = react.useMemo(
5278
+ () => columnKeySignature ? columnKeySignature.split("") : [],
5279
+ [columnKeySignature]
5280
+ );
5281
+ const defaultSizes = react.useMemo(
5282
+ () => buildDefaultColumnSizes(columns, defaultColumnSizes),
5283
+ [columns, defaultColumnSizes]
5284
+ );
5285
+ const [internalColumnOrder, setInternalColumnOrder] = react.useState(defaultOrder);
5286
+ const [internalColumnSizes, setInternalColumnSizes] = react.useState(() => loadStoredColumnSizes(columnStorageKey, defaultSizes));
5287
+ const [internalFrozenColumnCount, setInternalFrozenColumnCount] = react.useState(() => loadStoredFrozenColumnCount(columnStorageKey, frozenColumnCount, columns.length));
5288
+ const [internalFrozenEndColumnCount, setInternalFrozenEndColumnCount] = react.useState(() => loadStoredFrozenEndColumnCount(columnStorageKey, frozenEndColumnCount, columns.length));
4127
5289
  react.useEffect(() => {
4128
- setInternalColumnOrder((current) => normalizeColumnOrder(defaultColumnOrder, current));
4129
- }, [defaultColumnOrder]);
4130
- const resolvedColumnOrder = columnOrder ? normalizeColumnOrder(defaultColumnOrder, columnOrder) : internalColumnOrder;
5290
+ setInternalColumnOrder((current) => normalizeColumnOrder2(defaultOrder, current));
5291
+ }, [defaultOrder]);
5292
+ react.useEffect(() => {
5293
+ if (columnSizes) return;
5294
+ setInternalColumnSizes(loadStoredColumnSizes(columnStorageKey, defaultSizes));
5295
+ }, [columnSizes, columnStorageKey, defaultSizes]);
5296
+ react.useEffect(() => {
5297
+ setInternalFrozenColumnCount(loadStoredFrozenColumnCount(columnStorageKey, frozenColumnCount, columns.length));
5298
+ }, [columnStorageKey, columns.length, frozenColumnCount]);
5299
+ react.useEffect(() => {
5300
+ setInternalFrozenEndColumnCount(loadStoredFrozenEndColumnCount(columnStorageKey, frozenEndColumnCount, columns.length));
5301
+ }, [columnStorageKey, columns.length, frozenEndColumnCount]);
5302
+ const resolvedColumnOrder = columnOrder ? normalizeColumnOrder2(defaultOrder, columnOrder) : internalColumnOrder;
4131
5303
  const resolvedColumnSizes = columnSizes ?? internalColumnSizes;
5304
+ const orderedColumns = getOrderedColumns2(columns, resolvedColumnOrder);
5305
+ const {
5306
+ startCount: resolvedFrozenColumnCount,
5307
+ endCount: resolvedFrozenEndColumnCount
5308
+ } = normalizeFrozenColumnCounts(internalFrozenColumnCount, internalFrozenEndColumnCount, orderedColumns.length);
5309
+ const frozenOffsets = buildFrozenOffsets(orderedColumns, resolvedColumnSizes, resolvedFrozenColumnCount);
5310
+ const frozenEndOffsets = buildFrozenEndOffsets(orderedColumns, resolvedColumnSizes, resolvedFrozenEndColumnCount);
5311
+ const resolvedMinWidth = tableMinWidth ?? Math.max(760, orderedColumns.reduce((total, column) => total + getColumnNumericWidth(column, resolvedColumnSizes), 0));
5312
+ const labels = {
5313
+ columnActions: columnMenuLabels?.columnActions ?? "Column actions",
5314
+ freezeColumn: columnMenuLabels?.freezeColumn ?? "Freeze to left",
5315
+ freezeEndColumn: columnMenuLabels?.freezeEndColumn ?? "Freeze to right",
5316
+ unfreezeColumn: columnMenuLabels?.unfreezeColumn ?? "Unfreeze from left",
5317
+ unfreezeEndColumn: columnMenuLabels?.unfreezeEndColumn ?? "Unfreeze from right",
5318
+ unfreezeAllColumns: columnMenuLabels?.unfreezeAllColumns ?? "Unfreeze all columns",
5319
+ resetColumnWidth: columnMenuLabels?.resetColumnWidth ?? "Reset column width",
5320
+ frozenColumnTitle: columnMenuLabels?.frozenColumnTitle ?? "Frozen column"
5321
+ };
4132
5322
  const handleColumnOrderChange = react.useCallback((nextOrder, detail) => {
4133
- const normalizedOrder = normalizeColumnOrder(defaultColumnOrder, nextOrder);
5323
+ const normalizedOrder = normalizeColumnOrder2(defaultOrder, nextOrder);
4134
5324
  if (!columnOrder) {
4135
5325
  setInternalColumnOrder(normalizedOrder);
4136
5326
  }
4137
5327
  onColumnOrderChange?.(normalizedOrder, detail);
4138
- }, [columnOrder, defaultColumnOrder, onColumnOrderChange]);
5328
+ }, [columnOrder, defaultOrder, onColumnOrderChange]);
4139
5329
  const handleColumnSizeChange = react.useCallback((columnId, width, detail) => {
5330
+ const column = columns.find((item) => item.key === columnId);
5331
+ const minWidth = column?.minWidth;
5332
+ const maxWidth = column?.maxWidth;
5333
+ const nextWidth = Math.max(
5334
+ typeof minWidth === "number" ? minWidth : 0,
5335
+ Math.min(width, typeof maxWidth === "number" ? maxWidth : Number.POSITIVE_INFINITY)
5336
+ );
5337
+ const nextSizes = {
5338
+ ...resolvedColumnSizes,
5339
+ [columnId]: nextWidth
5340
+ };
4140
5341
  if (!columnSizes) {
4141
- setInternalColumnSizes((current) => ({
4142
- ...current,
4143
- [columnId]: width
4144
- }));
5342
+ setInternalColumnSizes(nextSizes);
4145
5343
  }
4146
- onColumnSizeChange?.(columnId, width, detail);
4147
- }, [columnSizes, onColumnSizeChange]);
4148
- const resolvedSelectedKey = selectedRowKey ?? selectedLinkKey;
4149
- const resolvedActivePrimaryColumn = activePrimaryColumn ?? activeTablePrimaryColumn;
4150
- const orderedColumns = getOrderedColumns(columns, resolvedColumnOrder);
4151
- const hiddenRowCount = Math.max(0, Number(totalRowCount || rows.length) - Number(renderedRowCount || rows.length));
4152
- const resolvedMinWidth = tableMinWidth ?? minWidth ?? Math.max(760, Math.min(orderedColumns.length * 112, 1440));
4153
- const renderValue = renderCell ?? renderFieldValue ?? ((column, row) => row?.[column.key]);
4154
- const isAction = isActionColumn ?? isActionField ?? (() => false);
4155
- const isDisabled = isRowDisabled ?? isWorkbenchPlaceholderRow ?? (() => false);
4156
- const resolveColumnIcon = getColumnIcon ?? getColumnTypeIcon;
4157
- const footer = hiddenRowCount > 0 && hiddenRowsMessage ? typeof hiddenRowsMessage === "function" ? hiddenRowsMessage(hiddenRowCount, renderedRowCount || rows.length, totalRowCount || rows.length) : hiddenRowsMessage : null;
4158
- return /* @__PURE__ */ jsxRuntime.jsxs(
5344
+ persistColumnSizes(columnStorageKey, nextSizes);
5345
+ onColumnSizeChange?.(columnId, nextWidth, detail);
5346
+ }, [columnSizes, columnStorageKey, columns, onColumnSizeChange, resolvedColumnSizes]);
5347
+ const handleResetColumnSize = react.useCallback((column) => {
5348
+ const nextWidth = defaultSizes[column.key] ?? getColumnDefaultSize(column);
5349
+ const previousWidth = getColumnNumericWidth(column, resolvedColumnSizes);
5350
+ const nextSizes = {
5351
+ ...resolvedColumnSizes,
5352
+ [column.key]: nextWidth
5353
+ };
5354
+ if (!columnSizes) {
5355
+ setInternalColumnSizes(nextSizes);
5356
+ }
5357
+ persistColumnSizes(columnStorageKey, nextSizes);
5358
+ onColumnSizeChange?.(column.key, nextWidth, {
5359
+ columnId: column.key,
5360
+ previousWidth,
5361
+ minWidth: column.minWidth,
5362
+ maxWidth: column.maxWidth
5363
+ });
5364
+ onResetColumnSizes?.(nextSizes);
5365
+ }, [columnSizes, columnStorageKey, defaultSizes, onColumnSizeChange, onResetColumnSizes, resolvedColumnSizes]);
5366
+ const setFrozenColumnCount = react.useCallback((nextCount) => {
5367
+ const normalizedCount = clampFrozenColumnCount(nextCount, Math.max(0, orderedColumns.length - resolvedFrozenEndColumnCount));
5368
+ setInternalFrozenColumnCount(normalizedCount);
5369
+ persistFrozenColumnCount(columnStorageKey, normalizedCount);
5370
+ onFrozenColumnCountChange?.(normalizedCount);
5371
+ }, [columnStorageKey, onFrozenColumnCountChange, orderedColumns.length, resolvedFrozenEndColumnCount]);
5372
+ const setFrozenEndColumnCount = react.useCallback((nextCount) => {
5373
+ const normalizedCount = clampFrozenColumnCount(nextCount, Math.max(0, orderedColumns.length - resolvedFrozenColumnCount));
5374
+ setInternalFrozenEndColumnCount(normalizedCount);
5375
+ persistFrozenEndColumnCount(columnStorageKey, normalizedCount);
5376
+ onFrozenEndColumnCountChange?.(normalizedCount);
5377
+ }, [columnStorageKey, onFrozenEndColumnCountChange, orderedColumns.length, resolvedFrozenColumnCount]);
5378
+ const getFrozenPosition = (columnIndex) => {
5379
+ if (columnIndex < resolvedFrozenColumnCount) return "start";
5380
+ if (columnIndex >= orderedColumns.length - resolvedFrozenEndColumnCount) return "end";
5381
+ return void 0;
5382
+ };
5383
+ const getFrozenClassName = (column, columnIndex, isHeader = false) => {
5384
+ const position = getFrozenPosition(columnIndex);
5385
+ if (!position) return void 0;
5386
+ return cn(
5387
+ "sticky",
5388
+ position === "start" ? "shadow-[1px_0_0_0_hsl(var(--border)/0.45)]" : "shadow-[-1px_0_0_0_hsl(var(--border)/0.45)]",
5389
+ isHeader ? "bg-muted/60" : "bg-inherit",
5390
+ isHeader ? "z-40" : "z-20",
5391
+ (columnIndex === 0 || columnIndex === orderedColumns.length - 1) && (isHeader ? "z-50" : "z-30")
5392
+ );
5393
+ };
5394
+ const getFrozenStyle = (column, columnIndex) => {
5395
+ const position = getFrozenPosition(columnIndex);
5396
+ if (position === "start") return { left: frozenOffsets.get(column.key) ?? 0 };
5397
+ if (position === "end") return { right: frozenEndOffsets.get(column.key) ?? 0 };
5398
+ return void 0;
5399
+ };
5400
+ return /* @__PURE__ */ jsxRuntime.jsx(
4159
5401
  BaseTableContainer,
4160
5402
  {
4161
5403
  appearance,
4162
- className: cn("w-full overflow-hidden rounded-lg border border-border/40 bg-muted/15 dark:border-border/35 dark:bg-muted/10", classNames?.root, className),
5404
+ className: cn("flex h-full min-h-0 flex-col overflow-hidden rounded-lg border border-border/60 bg-card", classNames?.root, className),
4163
5405
  style,
4164
- children: [
4165
- /* @__PURE__ */ jsxRuntime.jsx(
4166
- "div",
4167
- {
4168
- className: cn("w-full overflow-auto", classNames?.scrollArea),
4169
- style: { maxHeight: toCssSize2(bodyMaxHeight) },
4170
- children: /* @__PURE__ */ jsxRuntime.jsxs(
4171
- BaseTable,
4172
- {
4173
- appearance,
4174
- columnOrder: resolvedColumnOrder,
4175
- columnSizes: resolvedColumnSizes,
4176
- columnDragEnabled,
4177
- columnResizeEnabled,
4178
- onColumnOrderChange: handleColumnOrderChange,
4179
- onColumnSizeChange: handleColumnSizeChange,
4180
- className: cn("w-full table-auto text-left text-xs", classNames?.table, tableClassName),
4181
- style: { minWidth: resolvedMinWidth },
4182
- children: [
4183
- /* @__PURE__ */ jsxRuntime.jsx(BaseTableHeader, { appearance, className: cn("text-[10px] font-mono uppercase tracking-wide text-muted-foreground", classNames?.header), children: /* @__PURE__ */ jsxRuntime.jsx(BaseTableRow, { className: cn("hover:bg-transparent", classNames?.headerRow), children: orderedColumns.map((column, columnIndex) => {
4184
- const columnType = column.renderType || column.type || getColumnDataType?.(column.key, rows, column);
4185
- const columnIcon = renderWorkbenchIcon(
4186
- resolveColumnIcon?.(columnType, column),
4187
- "h-3.5 w-3.5 shrink-0 text-primary"
4188
- );
4189
- const previousColumn = orderedColumns[columnIndex - 1];
4190
- const followsRecordIcon = previousColumn?.renderType === "icon" && column.key === resolvedActivePrimaryColumn?.key;
4191
- const headerContent = renderColumnHeader ? renderColumnHeader(column, { column, columnIndex, columns: orderedColumns, rows, columnType }) : formatLabel(column.label, { column });
4192
- const headerTrailing = !renderColumnHeader && (hasRenderableNode(column.trailing) || hasRenderableNode(column.helperText)) ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
4193
- hasRenderableNode(column.trailing) ? formatLabel(column.trailing, { column }) : null,
4194
- /* @__PURE__ */ jsxRuntime.jsx(WorkbenchTableHeaderHelper, { helperText: formatLabel(column.helperText, { column }), className: classNames?.helper })
4195
- ] }) : void 0;
4196
- const sortable = Boolean(column.sortable);
4197
- const handleSort = sortable && onSort ? () => onSort(column.key, column) : void 0;
4198
- return /* @__PURE__ */ jsxRuntime.jsx(
5406
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5407
+ "div",
5408
+ {
5409
+ className: cn("min-h-0 flex-1 overflow-auto", classNames?.scrollArea),
5410
+ style: { maxHeight: toCssSize3(bodyMaxHeight) },
5411
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
5412
+ BaseTable,
5413
+ {
5414
+ appearance,
5415
+ columnOrder: resolvedColumnOrder,
5416
+ columnSizes: resolvedColumnSizes,
5417
+ columnDragEnabled,
5418
+ columnResizeEnabled,
5419
+ onColumnOrderChange: handleColumnOrderChange,
5420
+ onColumnSizeChange: handleColumnSizeChange,
5421
+ className: cn("w-full table-fixed text-left text-xs", classNames?.table, tableClassName),
5422
+ style: { minWidth: resolvedMinWidth },
5423
+ children: [
5424
+ /* @__PURE__ */ jsxRuntime.jsx("colgroup", { children: orderedColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
5425
+ "col",
5426
+ {
5427
+ style: {
5428
+ width: toCssSize3(resolvedColumnSizes[column.key] ?? column.width),
5429
+ minWidth: toCssSize3(column.minWidth)
5430
+ }
5431
+ },
5432
+ column.key
5433
+ )) }),
5434
+ /* @__PURE__ */ jsxRuntime.jsx(BaseTableHeader, { appearance, className: cn("border-b border-border/60 bg-muted/60 text-[11px] font-medium text-muted-foreground", classNames?.tableHeader), children: /* @__PURE__ */ jsxRuntime.jsx(BaseTableRow, { appearance, className: cn("hover:bg-transparent", classNames?.headerRow), children: orderedColumns.map((column, columnIndex) => {
5435
+ const headerContent = renderColumnHeader ? renderColumnHeader(column, { column, columnIndex, columns: orderedColumns, rows }) : column.label;
5436
+ const sortable = Boolean(column.sortable);
5437
+ const handleSort = sortable && onSort ? () => onSort(column.key, column) : void 0;
5438
+ const isFrozenStart = columnIndex < resolvedFrozenColumnCount;
5439
+ const isFrozenEnd = columnIndex >= orderedColumns.length - resolvedFrozenEndColumnCount;
5440
+ const isFrozen = isFrozenStart || isFrozenEnd;
5441
+ const isColumnAtDefaultWidth = getColumnNumericWidth(column, resolvedColumnSizes) === (defaultSizes[column.key] ?? getColumnDefaultSize(column));
5442
+ return /* @__PURE__ */ jsxRuntime.jsxs(BaseContextMenu, { modal: false, children: [
5443
+ /* @__PURE__ */ jsxRuntime.jsx(BaseContextMenuTrigger, { asChild: true, appearance, children: /* @__PURE__ */ jsxRuntime.jsx(
4199
5444
  BaseTableHead,
4200
5445
  {
4201
5446
  appearance,
4202
5447
  columnId: column.key,
4203
5448
  align: column.align,
4204
- icon: renderColumnHeader ? void 0 : columnIcon,
4205
5449
  label: headerContent,
4206
- description: renderColumnHeader ? void 0 : formatLabel(column.description, { column }),
4207
- meta: renderColumnHeader ? void 0 : formatLabel(column.meta, { column }),
4208
- actions: renderColumnHeader ? void 0 : column.actions,
4209
- trailing: headerTrailing,
5450
+ description: column.description,
5451
+ trailing: isFrozen ? /* @__PURE__ */ jsxRuntime.jsx("span", { title: labels.frozenColumnTitle, className: "inline-flex h-5 w-5 items-center justify-center rounded text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(PinIcon, { className: "h-3.5 w-3.5" }) }) : null,
4210
5452
  sortable,
4211
5453
  sortDirection: column.sortDirection,
4212
5454
  sortLabel: column.sortLabel,
4213
5455
  onSort: handleSort,
4214
5456
  draggable: column.draggable,
4215
- dragLabel: column.dragLabel,
4216
5457
  resizable: column.resizable,
4217
- resizeLabel: column.resizeLabel,
4218
5458
  width: column.width,
4219
- minWidth: typeof column.minWidth === "number" ? column.minWidth : void 0,
4220
- maxWidth: typeof column.maxWidth === "number" ? column.maxWidth : void 0,
5459
+ minWidth: column.minWidth,
5460
+ maxWidth: column.maxWidth,
4221
5461
  className: cn(
4222
- "sticky top-0 z-20 h-auto whitespace-nowrap bg-card/95 px-4 py-3 font-medium backdrop-blur-sm supports-[backdrop-filter]:bg-card/90",
4223
- stickyFirstColumn && columnIndex === 0 && "left-0 z-30 shadow-[1px_0_0_0_hsl(var(--border)/0.35)]",
4224
- column.compactHeaderClassName,
5462
+ "sticky top-0 h-9 whitespace-nowrap border-r border-border/50 bg-muted/60 px-2.5 py-2 backdrop-blur",
5463
+ getFrozenClassName(column, columnIndex, true),
4225
5464
  column.headerClassName,
4226
- column.renderType === "icon" && "pl-3 pr-1",
4227
- followsRecordIcon && "pl-2",
5465
+ column.className,
4228
5466
  classNames?.headerCell
4229
5467
  ),
4230
- style: {
4231
- minWidth: typeof column.minWidth === "string" ? column.minWidth : void 0,
4232
- maxWidth: typeof column.maxWidth === "string" ? column.maxWidth : void 0
5468
+ style: getFrozenStyle(column, columnIndex)
5469
+ }
5470
+ ) }),
5471
+ /* @__PURE__ */ jsxRuntime.jsxs(BaseContextMenuContent, { appearance, alignOffset: -4, className: "min-w-44", children: [
5472
+ /* @__PURE__ */ jsxRuntime.jsx(BaseContextMenuLabel, { appearance, children: labels.columnActions }),
5473
+ isFrozen ? /* @__PURE__ */ jsxRuntime.jsx(
5474
+ BaseContextMenuItem,
5475
+ {
5476
+ appearance,
5477
+ onSelect: () => {
5478
+ if (isFrozenEnd) setFrozenEndColumnCount(orderedColumns.length - columnIndex - 1);
5479
+ else setFrozenColumnCount(columnIndex);
5480
+ },
5481
+ children: isFrozenEnd ? labels.unfreezeEndColumn : labels.unfreezeColumn
5482
+ }
5483
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
5484
+ BaseContextMenuItem,
5485
+ {
5486
+ appearance,
5487
+ onSelect: () => setFrozenColumnCount(columnIndex + 1),
5488
+ children: labels.freezeColumn
5489
+ }
5490
+ ),
5491
+ !isFrozen ? /* @__PURE__ */ jsxRuntime.jsx(
5492
+ BaseContextMenuItem,
5493
+ {
5494
+ appearance,
5495
+ onSelect: () => setFrozenEndColumnCount(orderedColumns.length - columnIndex),
5496
+ children: labels.freezeEndColumn
5497
+ }
5498
+ ) : null,
5499
+ /* @__PURE__ */ jsxRuntime.jsx(
5500
+ BaseContextMenuItem,
5501
+ {
5502
+ appearance,
5503
+ disabled: resolvedFrozenColumnCount === 0 && resolvedFrozenEndColumnCount === 0,
5504
+ onSelect: () => {
5505
+ setFrozenColumnCount(0);
5506
+ setFrozenEndColumnCount(0);
5507
+ },
5508
+ children: labels.unfreezeAllColumns
4233
5509
  }
5510
+ ),
5511
+ /* @__PURE__ */ jsxRuntime.jsx(BaseContextMenuSeparator, { appearance }),
5512
+ /* @__PURE__ */ jsxRuntime.jsx(
5513
+ BaseContextMenuItem,
5514
+ {
5515
+ appearance,
5516
+ disabled: isColumnAtDefaultWidth,
5517
+ onSelect: () => handleResetColumnSize(column),
5518
+ children: labels.resetColumnWidth
5519
+ }
5520
+ )
5521
+ ] })
5522
+ ] }, column.key);
5523
+ }) }) }),
5524
+ /* @__PURE__ */ jsxRuntime.jsxs(BaseTableBody, { appearance, className: cn("divide-y divide-border/50", classNames?.body), children: [
5525
+ pinnedTopRows.map((row, rowIndex) => {
5526
+ const key = getPinnedTopRowKey(row, rowIndex);
5527
+ const resolvedRowClassName = resolveRowClassName(pinnedTopRowClassName, row, rowIndex);
5528
+ return /* @__PURE__ */ jsxRuntime.jsx(
5529
+ BaseTableRow,
5530
+ {
5531
+ appearance,
5532
+ className: cn("bg-card/95", classNames?.pinnedTopRow, resolvedRowClassName),
5533
+ children: orderedColumns.map((column, columnIndex) => /* @__PURE__ */ jsxRuntime.jsx(
5534
+ BaseTableCell,
5535
+ {
5536
+ appearance,
5537
+ align: column.align,
5538
+ className: cn(
5539
+ "h-[52px] border-r border-border/50 px-2.5 py-1.5 align-middle",
5540
+ column.wrap ? "whitespace-normal" : "whitespace-nowrap",
5541
+ getFrozenClassName(column, columnIndex),
5542
+ column.cellClassName,
5543
+ classNames?.cell
5544
+ ),
5545
+ style: getFrozenStyle(column, columnIndex),
5546
+ children: /* @__PURE__ */ jsxRuntime.jsx(InteractiveTableCellContent, { wrap: column.wrap, children: renderPinnedTopCell ? renderPinnedTopCell(column, row, { row, rowIndex, column, columnIndex, isPinnedTopRow: true }) : renderDefaultCell(column, row) })
5547
+ },
5548
+ `pinned-${key}-${column.key}`
5549
+ ))
4234
5550
  },
4235
- column.key
5551
+ `pinned-${key}`
4236
5552
  );
4237
- }) }) }),
4238
- /* @__PURE__ */ jsxRuntime.jsx(BaseTableBody, { appearance, className: cn("divide-y divide-border/35 dark:divide-border/30", classNames?.body), children: rows.length ? rows.map((row, rowIndex) => {
5553
+ }),
5554
+ rows.length ? rows.map((row, rowIndex) => {
4239
5555
  const key = getRowKey(row, rowIndex);
4240
- const disabled = isDisabled(row, rowIndex);
4241
- const selectionKey = getRowSelectionKey(row, rowIndex);
4242
- const selected = Boolean(resolvedSelectedKey && String(selectionKey) === String(resolvedSelectedKey));
4243
- const resolvedRowClassName = typeof rowClassName === "function" ? rowClassName(row, rowIndex) : rowClassName;
5556
+ const state = getRowState?.(row, rowIndex) || {};
5557
+ const resolvedRowClassName = resolveRowClassName(rowClassName, row, rowIndex);
4244
5558
  return /* @__PURE__ */ jsxRuntime.jsx(
4245
5559
  BaseTableRow,
4246
5560
  {
4247
5561
  appearance,
4248
- interactive: Boolean(onRowClick) && !disabled,
4249
- selected,
4250
- disabled,
5562
+ interactive: Boolean(onRowClick) && !state.disabled,
5563
+ selected: state.selected,
5564
+ disabled: state.disabled,
4251
5565
  onClick: () => {
4252
- if (!disabled) {
4253
- onRowClick?.(row, rowIndex);
4254
- }
5566
+ if (!state.disabled) onRowClick?.(row, rowIndex);
4255
5567
  },
4256
5568
  className: cn(
4257
- onRowClick && !disabled ? "cursor-pointer" : "cursor-default",
4258
- selected ? "bg-primary/10 hover:bg-primary/15" : disabled ? "" : "hover:bg-muted/25 dark:hover:bg-muted/15",
5569
+ "min-h-[52px] bg-card transition-colors",
5570
+ state.saving && "bg-primary/5",
5571
+ state.pending && "opacity-80",
5572
+ onRowClick && !state.disabled ? "cursor-pointer hover:bg-muted/30" : "hover:bg-muted/30",
4259
5573
  classNames?.row,
4260
5574
  resolvedRowClassName
4261
5575
  ),
4262
- children: orderedColumns.map((column, columnIndex) => {
4263
- const shouldWrap = isAction(column) || column.wrap === true;
4264
- const previousColumn = orderedColumns[columnIndex - 1];
4265
- const followsRecordIcon = previousColumn?.renderType === "icon" && column.key === resolvedActivePrimaryColumn?.key;
4266
- return /* @__PURE__ */ jsxRuntime.jsx(
4267
- BaseTableCell,
4268
- {
4269
- appearance,
4270
- align: column.align,
4271
- className: cn(
4272
- shouldWrap ? "align-top whitespace-normal" : "whitespace-nowrap",
4273
- "px-4 py-3 text-muted-foreground",
4274
- stickyFirstColumn && columnIndex === 0 && "sticky left-0 z-10 bg-card/95 text-foreground shadow-[1px_0_0_0_hsl(var(--border)/0.3)]",
4275
- column.compactCellClassName,
4276
- column.cellClassName,
4277
- column.renderType === "icon" && "pl-3 pr-1",
4278
- followsRecordIcon && "pl-2",
4279
- classNames?.cell
4280
- ),
4281
- children: renderValue(column, row, {
4282
- row,
4283
- rowIndex,
4284
- column,
4285
- columnIndex,
4286
- compact: true,
4287
- surface: "list"
4288
- })
4289
- },
4290
- `${key}-${column.key}`
4291
- );
4292
- })
5576
+ children: orderedColumns.map((column, columnIndex) => /* @__PURE__ */ jsxRuntime.jsx(
5577
+ BaseTableCell,
5578
+ {
5579
+ appearance,
5580
+ align: column.align,
5581
+ className: cn(
5582
+ "h-[52px] border-r border-border/50 px-2.5 py-1.5 align-middle",
5583
+ column.wrap ? "whitespace-normal" : "whitespace-nowrap",
5584
+ getFrozenClassName(column, columnIndex),
5585
+ column.cellClassName,
5586
+ classNames?.cell
5587
+ ),
5588
+ style: getFrozenStyle(column, columnIndex),
5589
+ children: /* @__PURE__ */ jsxRuntime.jsx(InteractiveTableCellContent, { wrap: column.wrap, children: renderCell ? renderCell(column, row, { row, rowIndex, column, columnIndex, isPinnedTopRow: false }) : renderDefaultCell(column, row) })
5590
+ },
5591
+ `${key}-${column.key}`
5592
+ ))
4293
5593
  },
4294
5594
  key
4295
5595
  );
4296
- }) : /* @__PURE__ */ jsxRuntime.jsx(
5596
+ }) : pinnedTopRows.length ? null : /* @__PURE__ */ jsxRuntime.jsx(
4297
5597
  BaseTableEmpty,
4298
5598
  {
4299
5599
  appearance,
4300
5600
  colSpan: Math.max(orderedColumns.length, 1),
4301
- classNames: { cell: "px-4 py-10 text-center text-sm text-muted-foreground" },
5601
+ className: classNames?.empty,
4302
5602
  children: emptyState
4303
5603
  }
4304
- ) })
4305
- ]
4306
- }
4307
- )
5604
+ )
5605
+ ] })
5606
+ ]
5607
+ }
5608
+ )
5609
+ }
5610
+ )
5611
+ }
5612
+ );
5613
+ }
5614
+ function InteractiveTableEditableTextCell({
5615
+ value,
5616
+ placeholder,
5617
+ disabled,
5618
+ multiline = false,
5619
+ commitOnBlur = true,
5620
+ className,
5621
+ inputClassName,
5622
+ onCommit
5623
+ }) {
5624
+ const initialValue = String(value || "");
5625
+ const [draft, setDraft] = react.useState(initialValue);
5626
+ react.useEffect(() => {
5627
+ setDraft(initialValue);
5628
+ }, [initialValue]);
5629
+ const commit = react.useCallback(async () => {
5630
+ const nextValue = String(draft || "").trim();
5631
+ const previousValue = String(initialValue || "").trim();
5632
+ if (nextValue === previousValue) return;
5633
+ try {
5634
+ await onCommit?.(nextValue);
5635
+ } catch {
5636
+ setDraft(initialValue);
5637
+ }
5638
+ }, [draft, initialValue, onCommit]);
5639
+ const controlClassName = cn(
5640
+ "w-full resize-none rounded-sm border border-transparent bg-transparent px-1.5 py-1 text-xs text-foreground outline-none transition-colors",
5641
+ "placeholder:text-muted-foreground/70 hover:border-border/60 hover:bg-background focus:border-primary/45 focus:bg-background",
5642
+ multiline ? "min-h-[42px] leading-5" : "h-8",
5643
+ disabled && "cursor-not-allowed text-muted-foreground hover:border-transparent hover:bg-transparent",
5644
+ inputClassName
5645
+ );
5646
+ if (multiline) {
5647
+ return /* @__PURE__ */ jsxRuntime.jsx(
5648
+ "textarea",
5649
+ {
5650
+ className: cn(controlClassName, className),
5651
+ disabled,
5652
+ value: draft,
5653
+ placeholder,
5654
+ onChange: (event) => setDraft(event.target.value),
5655
+ onBlur: () => {
5656
+ if (commitOnBlur) void commit();
5657
+ },
5658
+ onKeyDown: (event) => {
5659
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
5660
+ event.currentTarget.blur();
4308
5661
  }
4309
- ),
4310
- footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border-t border-border/40 px-4 py-2 text-[11px] text-muted-foreground dark:border-border/30", classNames?.footer), children: footer }) : null
4311
- ]
5662
+ if (event.key === "Escape") {
5663
+ setDraft(initialValue);
5664
+ event.currentTarget.blur();
5665
+ }
5666
+ }
5667
+ }
5668
+ );
5669
+ }
5670
+ return /* @__PURE__ */ jsxRuntime.jsx(
5671
+ "input",
5672
+ {
5673
+ className: cn(controlClassName, className),
5674
+ disabled,
5675
+ value: draft,
5676
+ placeholder,
5677
+ onChange: (event) => setDraft(event.target.value),
5678
+ onBlur: () => {
5679
+ if (commitOnBlur) void commit();
5680
+ },
5681
+ onKeyDown: (event) => {
5682
+ if (event.key === "Enter") event.currentTarget.blur();
5683
+ if (event.key === "Escape") {
5684
+ setDraft(initialValue);
5685
+ event.currentTarget.blur();
5686
+ }
5687
+ }
4312
5688
  }
4313
5689
  );
4314
5690
  }
5691
+ function InteractiveTableReadonlyCell({
5692
+ children,
5693
+ mono = false,
5694
+ className
5695
+ }) {
5696
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-w-0 text-xs text-muted-foreground", mono && "font-mono", className), children: hasRenderableNode(children) ? children : "\u2014" });
5697
+ }
5698
+ function InteractiveTableSelectCell({
5699
+ value,
5700
+ options,
5701
+ disabled,
5702
+ ariaLabel,
5703
+ children,
5704
+ className,
5705
+ onChange
5706
+ }) {
5707
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative flex w-full items-center", className), children: [
5708
+ children,
5709
+ /* @__PURE__ */ jsxRuntime.jsx(
5710
+ "select",
5711
+ {
5712
+ "aria-label": ariaLabel,
5713
+ disabled,
5714
+ value,
5715
+ onChange: (event) => onChange?.(event.target.value),
5716
+ className: "absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed",
5717
+ children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value))
5718
+ }
5719
+ )
5720
+ ] });
5721
+ }
4315
5722
  var imageExtPattern = /\.(png|jpe?g|webp|gif|svg|bmp|avif)$/i;
4316
5723
  var audioExtPattern = /\.(wav|mp3|ogg|m4a|flac|aac)$/i;
4317
5724
  var isLikelyUrl = (value) => /^https?:\/\//i.test(String(value || ""));
@@ -5498,7 +6905,178 @@ function WorkbenchGalleryView({
5498
6905
  }
5499
6906
  );
5500
6907
  }
6908
+ function toCssSize4(value) {
6909
+ if (value === void 0) return void 0;
6910
+ return typeof value === "number" ? `${value}px` : value;
6911
+ }
6912
+ function defaultGetRowId(row, rowIndex) {
6913
+ return String(row?.id ?? row?.key ?? rowIndex);
6914
+ }
6915
+ function defaultGetColumnId(row) {
6916
+ return String(row?.columnId ?? row?.status ?? "");
6917
+ }
6918
+ function defaultRenderCard(row) {
6919
+ const value = row?.title ?? row?.name ?? row?.id ?? "Untitled";
6920
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-border/70 bg-card px-3 py-2 text-sm text-foreground shadow-sm", children: String(value) });
6921
+ }
6922
+ function WorkbenchLaneDraggableCard({
6923
+ row,
6924
+ rowId,
6925
+ rowIndex,
6926
+ column,
6927
+ classNames,
6928
+ renderCard
6929
+ }) {
6930
+ const { attributes, listeners, setNodeRef, isDragging } = core.useDraggable({ id: rowId });
6931
+ return /* @__PURE__ */ jsxRuntime.jsx(
6932
+ "div",
6933
+ {
6934
+ ref: setNodeRef,
6935
+ ...listeners,
6936
+ ...attributes,
6937
+ className: cn("touch-none", classNames?.cardWrapper),
6938
+ children: renderCard(row, { row, rowIndex, column, isDragging, isOverlay: false })
6939
+ }
6940
+ );
6941
+ }
6942
+ function WorkbenchLaneColumnView({
6943
+ column,
6944
+ columnRows,
6945
+ columnWidth,
6946
+ columnMinHeight,
6947
+ emptyColumn,
6948
+ classNames,
6949
+ renderCard
6950
+ }) {
6951
+ const { setNodeRef, isOver } = core.useDroppable({ id: column.id });
6952
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6953
+ "section",
6954
+ {
6955
+ className: cn(
6956
+ "flex shrink-0 flex-col rounded-xl border border-border/60 bg-card p-2 shadow-sm",
6957
+ classNames?.column,
6958
+ column.className
6959
+ ),
6960
+ style: { width: toCssSize4(columnWidth) ?? "280px" },
6961
+ children: [
6962
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-10 items-center gap-2 px-1", classNames?.columnHeader, column.headerClassName), children: [
6963
+ column.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex h-4 w-4 items-center justify-center text-muted-foreground", classNames?.columnIcon, column.iconClassName), children: column.icon }) : null,
6964
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("inline-flex items-center rounded px-2 py-0.5 text-xs font-semibold bg-muted text-muted-foreground", classNames?.columnBadge, column.badgeClassName), children: column.label ?? column.id }),
6965
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs text-muted-foreground", classNames?.columnCount), children: columnRows.length })
6966
+ ] }),
6967
+ /* @__PURE__ */ jsxRuntime.jsx(
6968
+ "div",
6969
+ {
6970
+ ref: setNodeRef,
6971
+ className: cn(
6972
+ "mt-1 flex min-h-[200px] flex-1 flex-col gap-2 overflow-y-auto rounded-lg p-1 transition-colors [scrollbar-width:thin]",
6973
+ isOver && "bg-accent/60",
6974
+ classNames?.columnBody,
6975
+ column.bodyClassName
6976
+ ),
6977
+ style: { minHeight: toCssSize4(columnMinHeight) },
6978
+ children: columnRows.length ? columnRows.map(({ row, rowIndex, rowId }) => /* @__PURE__ */ jsxRuntime.jsx(
6979
+ WorkbenchLaneDraggableCard,
6980
+ {
6981
+ row,
6982
+ rowId,
6983
+ rowIndex,
6984
+ column,
6985
+ classNames,
6986
+ renderCard
6987
+ },
6988
+ rowId
6989
+ )) : emptyColumn ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex min-h-24 items-center justify-center rounded-lg border border-dashed border-border/60 px-3 py-4 text-xs text-muted-foreground", classNames?.emptyColumn), children: emptyColumn }) : null
6990
+ }
6991
+ )
6992
+ ]
6993
+ }
6994
+ );
6995
+ }
6996
+ function WorkbenchLaneView({
6997
+ rows = [],
6998
+ columns = [],
6999
+ getRowId = defaultGetRowId,
7000
+ getColumnId = defaultGetColumnId,
7001
+ renderCard = defaultRenderCard,
7002
+ renderOverlayCard,
7003
+ onMoveRow,
7004
+ emptyColumn,
7005
+ activationDistance = 5,
7006
+ columnWidth = 280,
7007
+ columnMinHeight,
7008
+ className,
7009
+ classNames,
7010
+ style
7011
+ }) {
7012
+ const [activeRowId, setActiveRowId] = react.useState(null);
7013
+ const sensors = core.useSensors(core.useSensor(core.PointerSensor, { activationConstraint: { distance: activationDistance } }));
7014
+ const columnMap = react.useMemo(() => new Map(columns.map((column) => [column.id, column])), [columns]);
7015
+ const rowEntries = react.useMemo(() => rows.map((row, rowIndex) => ({
7016
+ row,
7017
+ rowIndex,
7018
+ rowId: getRowId(row, rowIndex),
7019
+ columnId: getColumnId(row, rowIndex)
7020
+ })), [getColumnId, getRowId, rows]);
7021
+ const activeEntry = activeRowId ? rowEntries.find((entry) => entry.rowId === activeRowId) : void 0;
7022
+ const rowsByColumn = react.useMemo(() => {
7023
+ const next = /* @__PURE__ */ new Map();
7024
+ columns.forEach((column) => next.set(column.id, []));
7025
+ rowEntries.forEach(({ row, rowIndex, rowId, columnId }) => {
7026
+ next.get(columnId)?.push({ row, rowIndex, rowId });
7027
+ });
7028
+ return next;
7029
+ }, [columns, rowEntries]);
7030
+ const activeColumn = activeEntry ? columnMap.get(activeEntry.columnId) : void 0;
7031
+ const handleDragStart = react.useCallback((event) => {
7032
+ setActiveRowId(String(event.active.id));
7033
+ }, []);
7034
+ const handleDragEnd = react.useCallback((event) => {
7035
+ setActiveRowId(null);
7036
+ const rowId = String(event.active.id);
7037
+ const nextColumnId = String(event.over?.id ?? "");
7038
+ const activeRow = rowEntries.find((entry) => entry.rowId === rowId);
7039
+ if (!activeRow || !columnMap.has(nextColumnId) || activeRow.columnId === nextColumnId) return;
7040
+ onMoveRow?.(rowId, nextColumnId, activeRow.row);
7041
+ }, [columnMap, onMoveRow, rowEntries]);
7042
+ const handleDragCancel = react.useCallback(() => {
7043
+ setActiveRowId(null);
7044
+ }, []);
7045
+ return /* @__PURE__ */ jsxRuntime.jsxs(core.DndContext, { sensors, onDragStart: handleDragStart, onDragEnd: handleDragEnd, onDragCancel: handleDragCancel, children: [
7046
+ /* @__PURE__ */ jsxRuntime.jsx(
7047
+ "div",
7048
+ {
7049
+ className: cn("flex min-h-0 flex-1 gap-4 overflow-x-auto p-4 [scrollbar-width:thin]", classNames?.root, className),
7050
+ style,
7051
+ children: columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
7052
+ WorkbenchLaneColumnView,
7053
+ {
7054
+ column,
7055
+ columnRows: rowsByColumn.get(column.id) || [],
7056
+ columnWidth,
7057
+ columnMinHeight,
7058
+ emptyColumn,
7059
+ classNames,
7060
+ renderCard
7061
+ },
7062
+ column.id
7063
+ ))
7064
+ }
7065
+ ),
7066
+ /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { children: activeEntry && activeColumn ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(classNames?.overlayWrapper), children: (renderOverlayCard || renderCard)(activeEntry.row, {
7067
+ row: activeEntry.row,
7068
+ rowIndex: activeEntry.rowIndex,
7069
+ column: activeColumn,
7070
+ isDragging: false,
7071
+ isOverlay: true
7072
+ }) }) : null })
7073
+ ] });
7074
+ }
5501
7075
 
7076
+ exports.InteractiveTable = InteractiveTable;
7077
+ exports.InteractiveTableEditableTextCell = InteractiveTableEditableTextCell;
7078
+ exports.InteractiveTableReadonlyCell = InteractiveTableReadonlyCell;
7079
+ exports.InteractiveTableSelectCell = InteractiveTableSelectCell;
5502
7080
  exports.WorkbenchContentPane = WorkbenchContentPane;
5503
7081
  exports.WorkbenchContentToolbar = WorkbenchContentToolbar;
5504
7082
  exports.WorkbenchDetailSidebar = WorkbenchDetailSidebar;
@@ -5506,6 +7084,7 @@ exports.WorkbenchGalleryCard = WorkbenchGalleryCard;
5506
7084
  exports.WorkbenchGallerySettingsButton = WorkbenchGallerySettingsButton;
5507
7085
  exports.WorkbenchGallerySettingsPanel = WorkbenchGallerySettingsPanel;
5508
7086
  exports.WorkbenchGalleryView = WorkbenchGalleryView;
7087
+ exports.WorkbenchLaneView = WorkbenchLaneView;
5509
7088
  exports.WorkbenchMasonryLayout = WorkbenchMasonryLayout;
5510
7089
  exports.WorkbenchResizableSidebar = WorkbenchResizableSidebar;
5511
7090
  exports.WorkbenchTableView = WorkbenchTableView;