pixelize-design-library 2.4.2-beta.58 → 2.4.2-beta.60

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 (244) hide show
  1. package/CHANGELOG.md +149 -5
  2. package/COMPONENT-GOTCHAS.md +205 -18
  3. package/DESIGN-GUIDE.md +43 -9
  4. package/dist/Components/AppSwitcher/AppSwitcher.js +5 -1
  5. package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +2 -0
  6. package/dist/Components/AppSwitcher/AppSwitcherProps.js +7 -4
  7. package/dist/Components/AudioRecorder/AudioRecorder.d.ts +8 -0
  8. package/dist/Components/AudioRecorder/AudioRecorder.js +169 -0
  9. package/dist/Components/AudioRecorder/AudioRecorderProps.d.ts +20 -0
  10. package/dist/Components/AudioRecorder/AudioRecorderProps.js +2 -0
  11. package/dist/Components/Breadcrumbs/Breadcrumbs.d.ts +1 -1
  12. package/dist/Components/Breadcrumbs/Breadcrumbs.js +33 -10
  13. package/dist/Components/Breadcrumbs/BreadcrumbsProps.d.ts +16 -2
  14. package/dist/Components/BulkSelectionBar/BulkSelectionBar.d.ts +3 -0
  15. package/dist/Components/BulkSelectionBar/BulkSelectionBar.js +43 -0
  16. package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.d.ts +35 -0
  17. package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.js +2 -0
  18. package/dist/Components/BulkSelectionBar/index.d.ts +2 -0
  19. package/dist/Components/BulkSelectionBar/index.js +8 -0
  20. package/dist/Components/CalendarGrid/CalendarGrid.d.ts +3 -0
  21. package/dist/Components/CalendarGrid/CalendarGrid.js +173 -0
  22. package/dist/Components/CalendarGrid/CalendarGridProps.d.ts +54 -0
  23. package/dist/Components/CalendarGrid/CalendarGridProps.js +2 -0
  24. package/dist/Components/CalendarGrid/calendarMath.d.ts +49 -0
  25. package/dist/Components/CalendarGrid/calendarMath.js +178 -0
  26. package/dist/Components/Card/Card.d.ts +3 -1
  27. package/dist/Components/Card/Card.js +12 -2
  28. package/dist/Components/Card/CardProps.d.ts +5 -1
  29. package/dist/Components/CircularProgress/CircularProgress.d.ts +4 -0
  30. package/dist/Components/CircularProgress/CircularProgress.js +39 -0
  31. package/dist/Components/CircularProgress/CircularProgressProps.d.ts +22 -0
  32. package/dist/Components/CircularProgress/CircularProgressProps.js +2 -0
  33. package/dist/Components/CircularProgress/arc.d.ts +12 -0
  34. package/dist/Components/CircularProgress/arc.js +16 -0
  35. package/dist/Components/Common/fieldStyles.d.ts +1 -0
  36. package/dist/Components/Common/fieldStyles.js +2 -1
  37. package/dist/Components/Drawer/Drawer.d.ts +1 -1
  38. package/dist/Components/Drawer/Drawer.js +4 -2
  39. package/dist/Components/Drawer/DrawerProps.d.ts +3 -1
  40. package/dist/Components/Editor/Editor.js +50 -2
  41. package/dist/Components/Editor/EditorFieldBar.d.ts +15 -0
  42. package/dist/Components/Editor/EditorFieldBar.js +19 -0
  43. package/dist/Components/Editor/EditorProps.d.ts +74 -1
  44. package/dist/Components/Editor/MakeDynamicDialog.d.ts +12 -0
  45. package/dist/Components/Editor/MakeDynamicDialog.js +59 -0
  46. package/dist/Components/Editor/editorLabels.d.ts +4 -0
  47. package/dist/Components/Editor/editorLabels.js +24 -0
  48. package/dist/Components/Editor/editorTokenStyles.d.ts +28 -0
  49. package/dist/Components/Editor/editorTokenStyles.js +30 -0
  50. package/dist/Components/Editor/editorTokens.d.ts +26 -0
  51. package/dist/Components/Editor/editorTokens.js +134 -0
  52. package/dist/Components/Editor/useEditorBridge.d.ts +40 -0
  53. package/dist/Components/Editor/useEditorBridge.js +141 -0
  54. package/dist/Components/EmptyState/EmptyState.js +2 -1
  55. package/dist/Components/EmptyState/EmptyStateProps.d.ts +2 -2
  56. package/dist/Components/FormDrawer/FormDrawer.d.ts +2 -0
  57. package/dist/Components/FormDrawer/FormDrawer.js +97 -0
  58. package/dist/Components/FormDrawer/FormDrawerProps.d.ts +55 -0
  59. package/dist/Components/FormDrawer/FormDrawerProps.js +2 -0
  60. package/dist/Components/Kbd/Kbd.d.ts +6 -0
  61. package/dist/Components/Kbd/Kbd.js +33 -0
  62. package/dist/Components/Kbd/KbdProps.d.ts +17 -0
  63. package/dist/Components/Kbd/KbdProps.js +2 -0
  64. package/dist/Components/LauncherTrigger/LauncherTrigger.d.ts +4 -0
  65. package/dist/Components/LauncherTrigger/LauncherTrigger.js +48 -0
  66. package/dist/Components/LauncherTrigger/LauncherTriggerProps.d.ts +18 -0
  67. package/dist/Components/LauncherTrigger/LauncherTriggerProps.js +2 -0
  68. package/dist/Components/Modal/Modal.d.ts +1 -1
  69. package/dist/Components/Modal/Modal.js +4 -2
  70. package/dist/Components/Modal/ModalProps.d.ts +3 -1
  71. package/dist/Components/Modal/warnDroppedSlotChildren.d.ts +2 -0
  72. package/dist/Components/Modal/warnDroppedSlotChildren.js +45 -0
  73. package/dist/Components/NavLauncher/NavLauncher.d.ts +3 -0
  74. package/dist/Components/NavLauncher/NavLauncher.js +452 -0
  75. package/dist/Components/NavLauncher/NavLauncherProps.d.ts +187 -0
  76. package/dist/Components/NavLauncher/NavLauncherProps.js +2 -0
  77. package/dist/Components/NavLauncher/NewTabLink.d.ts +3 -0
  78. package/dist/Components/NavLauncher/NewTabLink.js +14 -0
  79. package/dist/Components/NavLauncher/PinToggle.d.ts +3 -0
  80. package/dist/Components/NavLauncher/PinToggle.js +21 -0
  81. package/dist/Components/NavLauncher/launcherParts.d.ts +152 -0
  82. package/dist/Components/NavLauncher/launcherParts.js +212 -0
  83. package/dist/Components/NavLauncher/match.d.ts +53 -0
  84. package/dist/Components/NavLauncher/match.js +178 -0
  85. package/dist/Components/NavLauncher/revealStyles.d.ts +4 -0
  86. package/dist/Components/NavLauncher/revealStyles.js +19 -0
  87. package/dist/Components/NavigationBar/NavigationBar.d.ts +1 -1
  88. package/dist/Components/NavigationBar/NavigationBar.js +2 -2
  89. package/dist/Components/NavigationBar/NavigationBarProps.d.ts +2 -0
  90. package/dist/Components/PageHeader/PageHeader.d.ts +1 -1
  91. package/dist/Components/PageHeader/PageHeader.js +9 -2
  92. package/dist/Components/PageHeader/PageHeaderProps.d.ts +8 -0
  93. package/dist/Components/PdfViewer/PdfViewer.d.ts +21 -4
  94. package/dist/Components/PdfViewer/PdfViewer.js +124 -3
  95. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
  96. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewerProps.d.ts +1 -1
  97. package/dist/Components/QueryState/QueryStateBoundary.d.ts +2 -2
  98. package/dist/Components/QueryState/QueryStateBoundary.js +9 -3
  99. package/dist/Components/QueryState/QueryStateProps.d.ts +19 -2
  100. package/dist/Components/Search/Search.js +2 -1
  101. package/dist/Components/SectionRail/SectionRail.d.ts +3 -0
  102. package/dist/Components/SectionRail/SectionRail.js +49 -0
  103. package/dist/Components/SectionRail/SectionRailProps.d.ts +23 -0
  104. package/dist/Components/SectionRail/SectionRailProps.js +2 -0
  105. package/dist/Components/SectionRail/index.d.ts +2 -0
  106. package/dist/Components/SectionRail/index.js +8 -0
  107. package/dist/Components/SegmentedControl/SegmentedControl.js +9 -14
  108. package/dist/Components/SegmentedControl/segmentedInk.d.ts +0 -2
  109. package/dist/Components/SegmentedControl/segmentedInk.js +1 -5
  110. package/dist/Components/SideBar/SecondaryBar.js +4 -3
  111. package/dist/Components/SideBar/SideBar.d.ts +1 -1
  112. package/dist/Components/SideBar/SideBar.js +30 -9
  113. package/dist/Components/SideBar/SideBarProps.d.ts +32 -0
  114. package/dist/Components/SideBar/components/MenuItemBox.d.ts +6 -0
  115. package/dist/Components/SideBar/components/MenuItemBox.js +8 -4
  116. package/dist/Components/SideBar/components/MenuPopoverContent.js +3 -2
  117. package/dist/Components/SideBar/components/OtherApps.js +2 -1
  118. package/dist/Components/SideBar/components/PinnedSection.d.ts +17 -0
  119. package/dist/Components/SideBar/components/PinnedSection.js +98 -0
  120. package/dist/Components/SideBar/sidebarFocus.d.ts +23 -0
  121. package/dist/Components/SideBar/sidebarFocus.js +20 -0
  122. package/dist/Components/StageProgress/StageProgress.js +2 -2
  123. package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
  124. package/dist/Components/StageProgress/StepperStage.js +5 -2
  125. package/dist/Components/StatCard/StatCard.d.ts +1 -1
  126. package/dist/Components/StatCard/StatCard.js +6 -2
  127. package/dist/Components/StatCard/StatCardProps.d.ts +3 -0
  128. package/dist/Components/StatusTag/StatusTag.d.ts +4 -0
  129. package/dist/Components/StatusTag/StatusTag.js +24 -0
  130. package/dist/Components/StatusTag/StatusTagProps.d.ts +20 -0
  131. package/dist/Components/StatusTag/StatusTagProps.js +2 -0
  132. package/dist/Components/Table/Table.d.ts +1 -1
  133. package/dist/Components/Table/Table.js +6 -2
  134. package/dist/Components/Table/TableProps.d.ts +20 -0
  135. package/dist/Components/Table/components/TableBody.d.ts +1 -1
  136. package/dist/Components/Table/components/TableBody.js +43 -18
  137. package/dist/Components/Table/components/TableHeader.d.ts +1 -1
  138. package/dist/Components/Table/components/TableHeader.js +7 -5
  139. package/dist/Components/Table/components/rowDetail.d.ts +32 -0
  140. package/dist/Components/Table/components/rowDetail.js +20 -0
  141. package/dist/Components/Table/hooks/useRowExpansion.d.ts +7 -0
  142. package/dist/Components/Table/hooks/useRowExpansion.js +27 -0
  143. package/dist/Components/Tabs/Tabs.d.ts +1 -1
  144. package/dist/Components/Tabs/Tabs.js +15 -2
  145. package/dist/Components/Tabs/TabsProps.d.ts +6 -2
  146. package/dist/Components/Tabs/components/Tab.js +4 -33
  147. package/dist/Components/Tabs/components/TabLinkList.d.ts +7 -0
  148. package/dist/Components/Tabs/components/TabLinkList.js +34 -0
  149. package/dist/Components/Tabs/useTabAppearance.d.ts +17 -0
  150. package/dist/Components/Tabs/useTabAppearance.js +67 -0
  151. package/dist/Components/Tag/Tag.js +11 -1
  152. package/dist/Components/Tag/TagProps.d.ts +4 -0
  153. package/dist/Components/Tag/tagDot.d.ts +3 -0
  154. package/dist/Components/Tag/tagDot.js +21 -0
  155. package/dist/Components/WizardDialog/WizardDialog.d.ts +9 -0
  156. package/dist/Components/WizardDialog/WizardDialog.js +102 -0
  157. package/dist/Components/WizardDialog/WizardDialogProps.d.ts +48 -0
  158. package/dist/Components/WizardDialog/WizardDialogProps.js +2 -0
  159. package/dist/Components/WizardDialog/useWizardFlow.d.ts +22 -0
  160. package/dist/Components/WizardDialog/useWizardFlow.js +47 -0
  161. package/dist/Components/WizardDialog/wizardSteps.d.ts +31 -0
  162. package/dist/Components/WizardDialog/wizardSteps.js +40 -0
  163. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +2 -1
  164. package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +5 -3
  165. package/dist/esm/Components/AudioRecorder/AudioRecorder.js +161 -0
  166. package/dist/esm/Components/AudioRecorder/AudioRecorderProps.js +1 -0
  167. package/dist/esm/Components/Breadcrumbs/Breadcrumbs.js +35 -12
  168. package/dist/esm/Components/BulkSelectionBar/BulkSelectionBar.js +38 -0
  169. package/dist/esm/Components/BulkSelectionBar/BulkSelectionBarProps.js +1 -0
  170. package/dist/esm/Components/BulkSelectionBar/index.js +1 -0
  171. package/dist/esm/Components/CalendarGrid/CalendarGrid.js +168 -0
  172. package/dist/esm/Components/CalendarGrid/CalendarGridProps.js +1 -0
  173. package/dist/esm/Components/CalendarGrid/calendarMath.js +155 -0
  174. package/dist/esm/Components/Card/Card.js +12 -2
  175. package/dist/esm/Components/CircularProgress/CircularProgress.js +37 -0
  176. package/dist/esm/Components/CircularProgress/CircularProgressProps.js +1 -0
  177. package/dist/esm/Components/CircularProgress/arc.js +11 -0
  178. package/dist/esm/Components/Common/fieldStyles.js +2 -1
  179. package/dist/esm/Components/Drawer/Drawer.js +4 -2
  180. package/dist/esm/Components/Editor/Editor.js +48 -3
  181. package/dist/esm/Components/Editor/EditorFieldBar.js +13 -0
  182. package/dist/esm/Components/Editor/MakeDynamicDialog.js +20 -0
  183. package/dist/esm/Components/Editor/editorLabels.js +20 -0
  184. package/dist/esm/Components/Editor/editorTokenStyles.js +25 -0
  185. package/dist/esm/Components/Editor/editorTokens.js +121 -0
  186. package/dist/esm/Components/Editor/useEditorBridge.js +138 -0
  187. package/dist/esm/Components/EmptyState/EmptyState.js +2 -1
  188. package/dist/esm/Components/FormDrawer/FormDrawer.js +58 -0
  189. package/dist/esm/Components/FormDrawer/FormDrawerProps.js +1 -0
  190. package/dist/esm/Components/Kbd/Kbd.js +28 -0
  191. package/dist/esm/Components/Kbd/KbdProps.js +1 -0
  192. package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +41 -0
  193. package/dist/esm/Components/LauncherTrigger/LauncherTriggerProps.js +1 -0
  194. package/dist/esm/Components/Modal/Modal.js +4 -2
  195. package/dist/esm/Components/Modal/warnDroppedSlotChildren.js +38 -0
  196. package/dist/esm/Components/NavLauncher/NavLauncher.js +413 -0
  197. package/dist/esm/Components/NavLauncher/NavLauncherProps.js +1 -0
  198. package/dist/esm/Components/NavLauncher/NewTabLink.js +11 -0
  199. package/dist/esm/Components/NavLauncher/PinToggle.js +18 -0
  200. package/dist/esm/Components/NavLauncher/launcherParts.js +187 -0
  201. package/dist/esm/Components/NavLauncher/match.js +172 -0
  202. package/dist/esm/Components/NavLauncher/revealStyles.js +15 -0
  203. package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
  204. package/dist/esm/Components/PageHeader/PageHeader.js +9 -2
  205. package/dist/esm/Components/PdfViewer/PdfViewer.js +123 -2
  206. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
  207. package/dist/esm/Components/QueryState/QueryStateBoundary.js +10 -4
  208. package/dist/esm/Components/Search/Search.js +3 -2
  209. package/dist/esm/Components/SectionRail/SectionRail.js +44 -0
  210. package/dist/esm/Components/SectionRail/SectionRailProps.js +1 -0
  211. package/dist/esm/Components/SectionRail/index.js +1 -0
  212. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +11 -16
  213. package/dist/esm/Components/SegmentedControl/segmentedInk.js +0 -3
  214. package/dist/esm/Components/SideBar/SecondaryBar.js +4 -3
  215. package/dist/esm/Components/SideBar/SideBar.js +31 -10
  216. package/dist/esm/Components/SideBar/components/MenuItemBox.js +4 -2
  217. package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +3 -2
  218. package/dist/esm/Components/SideBar/components/OtherApps.js +2 -1
  219. package/dist/esm/Components/SideBar/components/PinnedSection.js +92 -0
  220. package/dist/esm/Components/SideBar/sidebarFocus.js +15 -0
  221. package/dist/esm/Components/StageProgress/StageProgress.js +2 -2
  222. package/dist/esm/Components/StageProgress/StepperStage.js +5 -2
  223. package/dist/esm/Components/StatCard/StatCard.js +6 -2
  224. package/dist/esm/Components/StatusTag/StatusTag.js +19 -0
  225. package/dist/esm/Components/StatusTag/StatusTagProps.js +1 -0
  226. package/dist/esm/Components/Table/Table.js +7 -3
  227. package/dist/esm/Components/Table/components/TableBody.js +43 -18
  228. package/dist/esm/Components/Table/components/TableHeader.js +7 -5
  229. package/dist/esm/Components/Table/components/rowDetail.js +14 -0
  230. package/dist/esm/Components/Table/hooks/useRowExpansion.js +23 -0
  231. package/dist/esm/Components/Tabs/Tabs.js +15 -2
  232. package/dist/esm/Components/Tabs/components/Tab.js +4 -33
  233. package/dist/esm/Components/Tabs/components/TabLinkList.js +29 -0
  234. package/dist/esm/Components/Tabs/useTabAppearance.js +63 -0
  235. package/dist/esm/Components/Tag/Tag.js +12 -2
  236. package/dist/esm/Components/Tag/tagDot.js +17 -0
  237. package/dist/esm/Components/WizardDialog/WizardDialog.js +58 -0
  238. package/dist/esm/Components/WizardDialog/WizardDialogProps.js +1 -0
  239. package/dist/esm/Components/WizardDialog/useWizardFlow.js +44 -0
  240. package/dist/esm/Components/WizardDialog/wizardSteps.js +35 -0
  241. package/dist/esm/index.js +14 -0
  242. package/dist/index.d.ts +35 -6
  243. package/dist/index.js +38 -4
  244. package/package.json +1 -1
@@ -54,6 +54,7 @@ const rowMetrics_1 = require("./rowMetrics");
54
54
  const columnLabel_1 = require("../columnLabel");
55
55
  const motion_1 = require("../../../Theme/tokens/primitives/motion");
56
56
  const motion_2 = require("../../../Theme/chakra/motion");
57
+ const rowDetail_1 = require("./rowDetail");
57
58
  const getRowId = (row) => row.id;
58
59
  const getRowContent = (row) => typeof row.content === "function"
59
60
  ? row.content
@@ -87,20 +88,26 @@ const StatusCell = ({ value, onSolid, align, }) => ((0, jsx_runtime_1.jsx)(react
87
88
  // the group header already uses, so an override hex behaves identically in both.
88
89
  const StatusPill = ({ value, soft, ink, radius, }) => ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "inline-flex", alignItems: "center", maxW: "100%", px: "0.5rem", py: "0.125rem", borderRadius: radius, bg: soft, color: ink, fontSize: "0.75rem", fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: value }));
89
90
  const EMPTY_HOVER = {};
90
- const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, isContent, isLink, isCheckbox, isLoading, isActionFreeze, columns, leftOffsets, noBorders, freezedBgColor, freezedTextColor, theme, borderStyle, selectedBg, selectedFrozenBg, hoverStyle, rowHeight, cellPy, palette, accentColor, isStriped, ariaRowIndex, handleCheckbox, onRowClick, toggleRowExpansion, onMeasure, }) => {
91
+ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, isContent, isLink, isCheckbox, isLoading, isActionFreeze, columns, leftOffsets, noBorders, freezedBgColor, freezedTextColor, theme, borderStyle, selectedBg, selectedFrozenBg, hoverStyle, rowHeight, cellPy, palette, accentColor, isStriped, rowDetail, isDetailOpen = false, detailLeft = 0, detailColSpan = 0, ariaRowIndex, handleCheckbox, onRowClick, toggleRowExpansion, onMeasure, }) => {
91
92
  // Measured-height virtualization: report this row's real height (main + any
92
93
  // expanded panel) so the windower can place variable/expandable rows exactly.
93
94
  const mainRowRef = (0, react_2.useRef)(null);
94
95
  const expandedRowRef = (0, react_2.useRef)(null);
96
+ const detailRowRef = (0, react_2.useRef)(null);
95
97
  const hasContent = !!getRowContent(row);
98
+ const detailNode = rowDetail ? rowDetail.render(row) : null;
99
+ const hasDetail = detailNode !== null && detailNode !== undefined;
100
+ const detailOpen = isDetailOpen && hasDetail;
101
+ const detailIds = rowDetail ? (0, rowDetail_1.detailDomIds)(rowDetail.idPrefix, getRowId(row)) : null;
96
102
  (0, react_2.useLayoutEffect)(() => {
97
103
  if (!onMeasure)
98
104
  return;
99
105
  const measure = () => {
100
- var _a, _b, _c, _d;
106
+ var _a, _b, _c, _d, _e, _f;
101
107
  const main = (_b = (_a = mainRowRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 0;
102
108
  const exp = isExpanded && hasContent ? (_d = (_c = expandedRowRef.current) === null || _c === void 0 ? void 0 : _c.offsetHeight) !== null && _d !== void 0 ? _d : 0 : 0;
103
- const h = main + exp;
109
+ const det = detailOpen ? (_f = (_e = detailRowRef.current) === null || _e === void 0 ? void 0 : _e.offsetHeight) !== null && _f !== void 0 ? _f : 0 : 0;
110
+ const h = main + exp + det;
104
111
  if (h > 0)
105
112
  onMeasure(getRowId(row), h);
106
113
  };
@@ -113,12 +120,14 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
113
120
  ro.observe(mainRowRef.current);
114
121
  if (expandedRowRef.current)
115
122
  ro.observe(expandedRowRef.current);
123
+ if (detailRowRef.current)
124
+ ro.observe(detailRowRef.current);
116
125
  }
117
126
  return () => {
118
127
  cancelAnimationFrame(raf);
119
128
  ro === null || ro === void 0 ? void 0 : ro.disconnect();
120
129
  };
121
- }, [onMeasure, isExpanded, hasContent, row]);
130
+ }, [onMeasure, isExpanded, hasContent, detailOpen, row]);
122
131
  const handleCellClick = (0, react_2.useCallback)((header) => {
123
132
  if (!header.node && onRowClick) {
124
133
  onRowClick(row, {
@@ -148,6 +157,10 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
148
157
  "& .table-slot-index": { opacity: isChecked ? 0 : 1 },
149
158
  "&:hover .table-slot-box, &:focus-within .table-slot-box": { opacity: 1 },
150
159
  "&:hover .table-slot-index, &:focus-within .table-slot-index": { opacity: 0 },
160
+ "@media (pointer: coarse)": {
161
+ "& .table-slot-box": { opacity: 1 },
162
+ "& .table-slot-index": { opacity: 0 },
163
+ },
151
164
  }
152
165
  : {}),
153
166
  };
@@ -159,12 +172,12 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
159
172
  const chromeHoverable = rowStyle ? "false" : "true";
160
173
  const rowContent = getRowContent(row);
161
174
  const restBg = isStriped ? variant.row.stripeBg : theme.colors.background[50];
162
- return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: (0, motion_1.transitionFor)(["opacity"], "base"), sx: { ...rowSx, ...(0, motion_2.reducedMotionSx)() }, children: [isContent && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: "6", p: 0, fontSize: 14, background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { fontSize: 16 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { fontSize: 16 })), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: 14, fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: (0, motion_1.transitionFor)(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...(0, motion_2.reducedMotionSx)() }, children: rowIndex + 1 })), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: (0, motion_1.transitionFor)(["opacity"]), sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), columns.map((header, headerIndex) => {
175
+ return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Tr, { ref: mainRowRef, "aria-rowindex": ariaRowIndex, opacity: isLoading ? 0.4 : 1, pointerEvents: isLoading ? "none" : "auto", transition: (0, motion_1.transitionFor)(["opacity"], "base"), sx: { ...rowSx, ...(0, motion_2.reducedMotionSx)() }, children: [isContent && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: "6", p: 0, fontSize: 14, background: isChecked ? selectedFrozenBg : frozenCellBg, color: freezedTextColor, position: "sticky", borderBottom: borderStyle, boxShadow: leadSx, boxSizing: "border-box", "data-hoverable": chromeHoverable, left: "0px", zIndex: 1, className: "columns sticky-columns", children: hasContent && ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": isExpanded ? "Collapse row" : "Expand row", color: theme.colors.textMuted, icon: isExpanded ? ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { fontSize: 16 })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { fontSize: 16 })), _hover: { transform: "scale(1.1)" }, size: "sm", onClick: () => toggleRowExpansion(rowIndex), variant: "ghost" })) })), isCheckbox && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: variant.slot.width, minW: variant.slot.width, px: variant.slot.centered ? 0 : undefined, textAlign: variant.slot.centered ? "center" : undefined, fontSize: 14, fontWeight: 600, color: theme.colors.background[50], textTransform: "capitalize", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: "0px", zIndex: 1, className: "columns sticky-columns", children: (0, jsx_runtime_1.jsxs)(react_1.Box, { display: restsOnIndex ? "grid" : undefined, placeItems: "center", children: [restsOnIndex && ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: "table-slot-index", gridArea: "1 / 1", color: variant.slot.indexInk, fontSize: "0.6875rem", fontWeight: 500, transition: (0, motion_1.transitionFor)(["opacity"]), sx: { fontVariantNumeric: "tabular-nums", ...(0, motion_2.reducedMotionSx)() }, children: rowIndex + 1 })), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", className: restsOnIndex ? "table-slot-box" : undefined, gridArea: restsOnIndex ? "1 / 1" : undefined, display: "flex", alignItems: "center", justifyContent: "center", transition: (0, motion_1.transitionFor)(["opacity"]), sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { "aria-label": `Select row ${rowIndex + 1}`, onChange: () => handleCheckbox(getRowId(row)), isChecked: isChecked }) })] }) })), rowDetail && detailIds && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: `${rowDetail_1.DETAIL_SLOT_PX}px`, minW: `${rowDetail_1.DETAIL_SLOT_PX}px`, maxW: `${rowDetail_1.DETAIL_SLOT_PX}px`, p: 0, textAlign: "center", background: isChecked ? selectedFrozenBg : frozenCellBg, position: "sticky", borderBottom: borderStyle, boxShadow: !isContent && !isCheckbox ? leadSx : undefined, "data-hoverable": chromeHoverable, boxSizing: "border-box", left: `${detailLeft}px`, zIndex: 1, className: "columns sticky-columns", children: hasDetail && ((0, jsx_runtime_1.jsx)(rowDetail_1.RowDetailToggle, { isOpen: detailOpen, detailId: detailIds.detailId, color: theme.colors.textMuted, theme: theme, onToggle: () => rowDetail.toggle(getRowId(row)) })) })), columns.map((header, headerIndex) => {
163
176
  var _a, _b, _c, _d;
164
177
  if (header.isHidden)
165
178
  return null;
166
179
  const isFrozen = header.isFreeze;
167
- const isFirstDataCell = !isContent && !isCheckbox && headerIndex === firstDataColIndex;
180
+ const isFirstDataCell = !isContent && !isCheckbox && !rowDetail && headerIndex === firstDataColIndex;
168
181
  const isStatus = header.type === "status" && !header.node;
169
182
  const rawStatus = String((_a = row[header.id]) !== null && _a !== void 0 ? _a : "");
170
183
  const statusColor = isStatus
@@ -174,7 +187,7 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
174
187
  const bleedBg = statusColor === null || statusColor === void 0 ? void 0 : statusColor.soft;
175
188
  const bleedInk = statusColor === null || statusColor === void 0 ? void 0 : statusColor.text;
176
189
  const canHover = !isBleed && !((cellStyles === null || cellStyles === void 0 ? void 0 : cellStyles[header.id]) || rowStyle);
177
- return ((0, jsx_runtime_1.jsx)(react_1.Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? `${leftOffsets[headerIndex]}px` : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? bleedBg : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : restBg, textAlign: isBleed ? undefined : header.align, textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
190
+ return ((0, jsx_runtime_1.jsx)(react_1.Td, { maxWidth: 500, minWidth: 120, height: `${rowHeight}px`, py: isBleed ? 0 : cellPy, px: isBleed ? 0 : undefined, id: hasDetail && headerIndex === firstDataColIndex ? detailIds === null || detailIds === void 0 ? void 0 : detailIds.cellId : undefined, onClick: () => handleCellClick(header), fontSize: 14, fontWeight: 400, position: isFrozen ? "sticky" : undefined, left: isFrozen ? `${leftOffsets[headerIndex]}px` : undefined, zIndex: isFrozen ? 1 : 0, background: isBleed ? bleedBg : isChecked ? (isFrozen ? selectedFrozenBg : selectedBg) : isFrozen ? frozenCellBg : restBg, textAlign: isBleed ? undefined : header.align, textOverflow: "ellipsis", boxShadow: isFirstDataCell ? leadSx : undefined, borderBottom: noBorders
178
191
  ? "none"
179
192
  : `0.063rem solid ${isFrozen || isChecked
180
193
  ? variant.row.frozenRuleColor
@@ -184,7 +197,7 @@ const TableRow = react_2.default.memo(({ row, rowIndex, isChecked, isExpanded, i
184
197
  }), isLink && ((0, jsx_runtime_1.jsx)(react_1.Td, { w: 2, p: 0, fontSize: 14, background: isChecked ? (isActionFreeze ? selectedFrozenBg : selectedBg) : isActionFreeze ? frozenCellBg : restBg, color: freezedTextColor, position: isActionFreeze ? "sticky" : "relative", borderBottom: borderStyle, boxSizing: "border-box", right: 0, zIndex: 1, className: `columns sticky-columns${isActionFreeze ? "-right" : ""}`, children: (row.onLink || row.onEdit || row.onDelete) ? ((0, jsx_runtime_1.jsx)(TableActions_1.default, { row: row })) : null }))] }), rowContent && isExpanded && ((0, jsx_runtime_1.jsx)(react_1.Tr, { ref: expandedRowRef, children: (0, jsx_runtime_1.jsx)(react_1.Td, { colSpan: columns.length +
185
198
  (isCheckbox ? 1 : 0) +
186
199
  (isContent ? 1 : 0) +
187
- (isLink ? 1 : 0), p: 2, children: (0, jsx_runtime_1.jsx)(react_1.Box, { p: 2, bg: theme.colors.background[50], borderRadius: "lg", children: rowContent(row) }) }) }))] }));
200
+ (isLink ? 1 : 0), p: 2, children: (0, jsx_runtime_1.jsx)(react_1.Box, { p: 2, bg: theme.colors.background[50], borderRadius: "lg", children: rowContent(row) }) }) })), detailOpen && detailIds && ((0, jsx_runtime_1.jsx)(rowDetail_1.RowDetailRow, { ref: detailRowRef, id: detailIds.detailId, labelledBy: detailIds.cellId, colSpan: detailColSpan, bg: theme.colors.backgroundColor.secondary, borderColor: variant.row.ruleColor, noBorders: noBorders, children: detailNode }))] }));
188
201
  });
189
202
  const isStructuredEmpty = (value) => !!value && typeof value === "object" && !react_2.default.isValidElement(value);
190
203
  const TableEmpty = ({ emptyState }) => {
@@ -195,7 +208,7 @@ const TableEmpty = ({ emptyState }) => {
195
208
  return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: emptyState });
196
209
  return ((0, jsx_runtime_1.jsx)(EmptyState_1.default, { size: "sm", minH: `${rowMetrics_1.EMPTY_STATE_HEIGHT}px`, title: structured === null || structured === void 0 ? void 0 : structured.title, description: structured === null || structured === void 0 ? void 0 : structured.description, icon: icon }));
197
210
  };
198
- const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWidths, slotWidth, freezedBgColor, freezedTextColor, noBorders, handleCheckbox, selections, isLoading, onRowClick, isContent, isLink, isActionFreeze, loadingSkeletonRows, scrollContainerRef, density, stripe = false, accentColors, groups, onAddItem, emptyState, }) => {
211
+ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWidths, slotWidth, freezedBgColor, freezedTextColor, noBorders, handleCheckbox, selections, isLoading, onRowClick, isContent, isLink, isActionFreeze, loadingSkeletonRows, scrollContainerRef, density, stripe = false, accentColors, groups, onAddItem, emptyState, rowDetail, expandedIds, }) => {
199
212
  var _a;
200
213
  const theme = (0, useCustomTheme_1.useCustomTheme)();
201
214
  const variant = (0, TableVariantContext_1.useTableVariant)();
@@ -222,6 +235,8 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
222
235
  const OVERSCAN = 6;
223
236
  const VIRTUALIZE_THRESHOLD = 30;
224
237
  const ESTIMATED_EXPAND = 120; // assumed extra height for an expanded-but-not-yet-measured row
238
+ const detailWidth = rowDetail ? rowDetail_1.DETAIL_SLOT_PX : 0;
239
+ const detailLeft = isCheckbox ? slotWidth : 0;
225
240
  const shouldVirtualize = data.length > VIRTUALIZE_THRESHOLD;
226
241
  // Grouped mode has no pager, so it virtualizes too (when no expandable rows):
227
242
  // group headers + rows form one flat sequence that we window over.
@@ -293,11 +308,12 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
293
308
  const measured = measuredHeights.get(id);
294
309
  const h = measured != null
295
310
  ? measured
296
- : ROW_HEIGHT + (expandedRows.has(startRow + i) ? ESTIMATED_EXPAND : 0);
311
+ : ROW_HEIGHT +
312
+ (expandedRows.has(startRow + i) || (expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.has(id)) ? ESTIMATED_EXPAND : 0);
297
313
  acc[i + 1] = acc[i] + h;
298
314
  }
299
315
  return acc;
300
- }, [shouldVirtualize, groups, total, data, measuredHeights, expandedRows, startRow, ROW_HEIGHT, ESTIMATED_EXPAND]);
316
+ }, [shouldVirtualize, groups, total, data, measuredHeights, expandedRows, expandedIds, startRow, ROW_HEIGHT, ESTIMATED_EXPAND]);
301
317
  let firstIndex = 0;
302
318
  let lastIndex = total;
303
319
  let topPad = 0;
@@ -340,11 +356,12 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
340
356
  const totalVisibleColumns = (0, react_2.useMemo)(() => columns.filter((o) => !o.isHidden).length +
341
357
  (isCheckbox ? 1 : 0) +
342
358
  (isContent ? 1 : 0) +
343
- (isLink ? 1 : 0), [columns, isCheckbox, isContent, isLink]);
359
+ (rowDetail ? 1 : 0) +
360
+ (isLink ? 1 : 0), [columns, isCheckbox, isContent, isLink, rowDetail]);
344
361
  const leftOffsets = (0, react_2.useMemo)(() => {
345
- const checkboxOffset = isCheckbox ? slotWidth : 0;
362
+ const checkboxOffset = (isCheckbox ? slotWidth : 0) + detailWidth;
346
363
  return columnWidths.map((_, idx) => columnWidths.slice(0, idx).reduce((sum, w) => sum + w, 0) + checkboxOffset);
347
- }, [columnWidths, isCheckbox, slotWidth]);
364
+ }, [columnWidths, isCheckbox, slotWidth, detailWidth]);
348
365
  const borderStyle = (0, react_2.useMemo)(() => noBorders ? "none" : `0.063rem solid ${variant.row.ruleColor}`, [noBorders, variant.row.ruleColor]);
349
366
  // Selected-row tint applied per-cell (NOT a blanket `& td` override) so status
350
367
  // cells keep their solid color + white text instead of white-on-tint.
@@ -372,7 +389,15 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
372
389
  const groupMetrics = (0, react_2.useMemo)(() => {
373
390
  if (!groupItems || !groupVirtualize)
374
391
  return null;
375
- const heights = groupItems.map((it) => (it.kind === "header" ? rowMetrics_1.GROUP_HEADER_HEIGHT : rowHeight));
392
+ const heights = groupItems.map((it) => {
393
+ var _a;
394
+ if (it.kind === "header")
395
+ return rowMetrics_1.GROUP_HEADER_HEIGHT;
396
+ if (!rowDetail)
397
+ return rowHeight;
398
+ const id = getRowId(it.row);
399
+ return (_a = measuredHeights.get(id)) !== null && _a !== void 0 ? _a : rowHeight + ((expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.has(id)) ? ESTIMATED_EXPAND : 0);
400
+ });
376
401
  const offsets = [];
377
402
  let acc = 0;
378
403
  for (const h of heights) {
@@ -380,7 +405,7 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
380
405
  acc += h;
381
406
  }
382
407
  return { heights, offsets, totalH: acc };
383
- }, [groupItems, groupVirtualize, rowHeight]);
408
+ }, [groupItems, groupVirtualize, rowHeight, rowDetail, measuredHeights, expandedIds, ESTIMATED_EXPAND]);
384
409
  // Clamp scrollTop back when a shorter data set leaves it past the new content height.
385
410
  (0, react_2.useEffect)(() => {
386
411
  const totalH = shouldVirtualize && offsets ? offsets[total] : groupVirtualize && groupMetrics ? groupMetrics.totalH : null;
@@ -447,7 +472,7 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
447
472
  const windowItems = groupVirtualize ? items.slice(firstI, lastI) : items;
448
473
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [gTopPad > 0 && ((0, jsx_runtime_1.jsx)("tr", { "aria-hidden": "true", style: { height: gTopPad }, children: (0, jsx_runtime_1.jsx)("td", { colSpan: totalVisibleColumns, style: { padding: 0, border: "none", height: gTopPad } }) })), windowItems.map((it, k) => {
449
474
  var _a;
450
- return it.kind === "header" ? ((0, jsx_runtime_1.jsx)(TableGroupRow_1.default, { label: it.g.label, value: it.g.value, count: it.g.rows.length, color: it.g.color, collapsed: collapsedGroups.has(it.g.value), colSpan: totalVisibleColumns, ariaRowIndex: firstI + k + 2, onToggle: () => toggleGroup(it.g.value), onAddItem: onAddItem }, `h-${it.g.value}`)) : ((0, jsx_runtime_1.jsx)(TableRow, { row: it.row, rowIndex: firstI + k, isChecked: selectionsSet.has(getRowId(it.row)), isExpanded: expandedRows.has(firstI + k), isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, selectedBg: selectedBg, selectedFrozenBg: selectedFrozenBg, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: it.g.color.solid, isStriped: stripe && it.pos % 2 === 1, ariaRowIndex: firstI + k + 2, handleCheckbox: handleCheckbox, onRowClick: rowClickHandler, toggleRowExpansion: toggleRowExpansion }, (_a = getRowId(it.row)) !== null && _a !== void 0 ? _a : `r-${firstI + k}`));
475
+ return it.kind === "header" ? ((0, jsx_runtime_1.jsx)(TableGroupRow_1.default, { label: it.g.label, value: it.g.value, count: it.g.rows.length, color: it.g.color, collapsed: collapsedGroups.has(it.g.value), colSpan: totalVisibleColumns, ariaRowIndex: firstI + k + 2, onToggle: () => toggleGroup(it.g.value), onAddItem: onAddItem }, `h-${it.g.value}`)) : ((0, jsx_runtime_1.jsx)(TableRow, { row: it.row, rowIndex: firstI + k, isChecked: selectionsSet.has(getRowId(it.row)), isExpanded: expandedRows.has(firstI + k), isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, selectedBg: selectedBg, selectedFrozenBg: selectedFrozenBg, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: it.g.color.solid, isStriped: stripe && it.pos % 2 === 1, rowDetail: rowDetail, isDetailOpen: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.has(getRowId(it.row))), detailLeft: detailLeft, detailColSpan: totalVisibleColumns, ariaRowIndex: firstI + k + 2, handleCheckbox: handleCheckbox, onRowClick: rowClickHandler, toggleRowExpansion: toggleRowExpansion, onMeasure: groupVirtualize && rowDetail ? reportHeight : undefined }, (_a = getRowId(it.row)) !== null && _a !== void 0 ? _a : `r-${firstI + k}`));
451
476
  }), gBottomPad > 0 && ((0, jsx_runtime_1.jsx)("tr", { "aria-hidden": "true", style: { height: gBottomPad }, children: (0, jsx_runtime_1.jsx)("td", { colSpan: totalVisibleColumns, style: { padding: 0, border: "none", height: gBottomPad } }) }))] }));
452
477
  }
453
478
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isLoading && data.length > 0 && ((0, jsx_runtime_1.jsx)(react_1.Tr, { children: (0, jsx_runtime_1.jsx)(react_1.Td, { colSpan: totalVisibleColumns, p: 0, border: "none", position: "relative", height: 0, children: (0, jsx_runtime_1.jsx)(react_1.Box, { position: "absolute", top: 4, left: "50%", transform: "translateX(-50%)", zIndex: 10, children: (0, jsx_runtime_1.jsx)(react_1.Spinner, { size: "sm", color: theme.colors.accentText }) }) }) })), shouldVirtualize && topPad > 0 && ((0, jsx_runtime_1.jsx)("tr", { "aria-hidden": "true", style: { height: topPad }, children: (0, jsx_runtime_1.jsx)("td", { colSpan: totalVisibleColumns, style: { padding: 0, border: "none", height: topPad } }) })), visibleRows.map((row, i) => {
@@ -456,7 +481,7 @@ const TableBody = ({ data, isCheckbox, columns, startRow, rowsPerPage, columnWid
456
481
  const rowIndex = startRow + index;
457
482
  const isExpanded = expandedRows.has(rowIndex);
458
483
  const isChecked = selectionsSet.has(getRowId(row));
459
- return ((0, jsx_runtime_1.jsx)(TableRow, { row: row, rowIndex: rowIndex, isChecked: isChecked, isExpanded: isExpanded, isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, selectedBg: selectedBg, selectedFrozenBg: selectedFrozenBg, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: accentColors === null || accentColors === void 0 ? void 0 : accentColors[getRowId(row)], isStriped: stripe && index % 2 === 1, ariaRowIndex: index + 2, handleCheckbox: handleCheckbox, onRowClick: rowClickHandler, toggleRowExpansion: toggleRowExpansion, onMeasure: shouldVirtualize ? reportHeight : undefined }, (_a = getRowId(row)) !== null && _a !== void 0 ? _a : rowIndex));
484
+ return ((0, jsx_runtime_1.jsx)(TableRow, { row: row, rowIndex: rowIndex, isChecked: isChecked, isExpanded: isExpanded, isContent: isContent, isLink: isLink, isCheckbox: isCheckbox, isLoading: isLoading, isActionFreeze: isActionFreeze, columns: columns, leftOffsets: leftOffsets, noBorders: noBorders, freezedBgColor: freezedBgColor, freezedTextColor: freezedTextColor, theme: theme, borderStyle: borderStyle, selectedBg: selectedBg, selectedFrozenBg: selectedFrozenBg, hoverStyle: hoverStyle, rowHeight: rowHeight, cellPy: cellPy, palette: palette, accentColor: accentColors === null || accentColors === void 0 ? void 0 : accentColors[getRowId(row)], isStriped: stripe && index % 2 === 1, rowDetail: rowDetail, isDetailOpen: !!(expandedIds === null || expandedIds === void 0 ? void 0 : expandedIds.has(getRowId(row))), detailLeft: detailLeft, detailColSpan: totalVisibleColumns, ariaRowIndex: index + 2, handleCheckbox: handleCheckbox, onRowClick: rowClickHandler, toggleRowExpansion: toggleRowExpansion, onMeasure: shouldVirtualize ? reportHeight : undefined }, (_a = getRowId(row)) !== null && _a !== void 0 ? _a : rowIndex));
460
485
  }), shouldVirtualize && bottomPad > 0 && ((0, jsx_runtime_1.jsx)("tr", { "aria-hidden": "true", style: { height: bottomPad }, children: (0, jsx_runtime_1.jsx)("td", { colSpan: totalVisibleColumns, style: { padding: 0, border: "none", height: bottomPad } }) }))] }));
461
486
  };
462
487
  exports.default = TableBody;
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { TableHeaderPageProps } from "../TableProps";
3
- declare const _default: React.MemoExoticComponent<({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }: TableHeaderPageProps) => import("react/jsx-runtime").JSX.Element>;
3
+ declare const _default: React.MemoExoticComponent<({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, hasDetail, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }: TableHeaderPageProps) => import("react/jsx-runtime").JSX.Element>;
4
4
  export default _default;
@@ -17,13 +17,15 @@ const TableVariantContext_1 = require("../variants/TableVariantContext");
17
17
  const motion_1 = require("../../../Theme/tokens/primitives/motion");
18
18
  const motion_2 = require("../../../Theme/chakra/motion");
19
19
  const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
20
+ const rowDetail_1 = require("./rowDetail");
20
21
  const LABEL_JUSTIFY = { start: "space-between", center: "center", end: "flex-start" };
21
- const TableHeader = ({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }) => {
22
+ const TableHeader = ({ columns, isCheckbox, handleSort, headerRefs, columnWidths, slotRef, slotWidth, columnsSort, freezedTextColor, noBorders, handleCheckbox, checked, isLoading, isContent, isLink, hasDetail = false, isActionFreeze, setColumnsSearch, columnsSearch, isSelecting, }) => {
22
23
  const [openFilterId, setOpenFilterId] = (0, react_2.useState)(null);
23
- return ((0, jsx_runtime_1.jsxs)(react_1.Tr, { pr: 0, "aria-rowindex": 1, children: [isContent && (0, jsx_runtime_1.jsx)(ContentSpacerCell, { noBorders: noBorders }), isCheckbox && ((0, jsx_runtime_1.jsx)(SelectAllCell, { slotRef: slotRef, freezedTextColor: freezedTextColor, noBorders: noBorders, isSelecting: isSelecting, isLoading: isLoading, checked: checked, handleCheckbox: handleCheckbox })), columns.map((header, index) => {
24
+ const variant = (0, TableVariantContext_1.useTableVariant)();
25
+ return ((0, jsx_runtime_1.jsxs)(react_1.Tr, { pr: 0, "aria-rowindex": 1, children: [isContent && (0, jsx_runtime_1.jsx)(ContentSpacerCell, { noBorders: noBorders }), isCheckbox && ((0, jsx_runtime_1.jsx)(SelectAllCell, { slotRef: slotRef, freezedTextColor: freezedTextColor, noBorders: noBorders, isSelecting: isSelecting, isLoading: isLoading, checked: checked, handleCheckbox: handleCheckbox })), hasDetail && ((0, jsx_runtime_1.jsx)(rowDetail_1.RowDetailHeaderCell, { left: isCheckbox ? slotWidth : 0, bg: variant.header.bg, ruleColor: variant.header.ruleColor, noBorders: noBorders })), columns.map((header, index) => {
24
26
  if (header === null || header === void 0 ? void 0 : header.isHidden)
25
27
  return null;
26
- return ((0, jsx_runtime_1.jsx)(ColumnHeader, { header: header, index: index, columnWidths: columnWidths, slotWidth: slotWidth, handleSort: handleSort, isCheckbox: isCheckbox, noBorders: noBorders, columnsSort: columnsSort, headerRefs: headerRefs, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch, openFilterId: openFilterId, setOpenFilterId: setOpenFilterId }, (0, columnLabel_1.columnLabelText)(header)));
28
+ return ((0, jsx_runtime_1.jsx)(ColumnHeader, { header: header, index: index, columnWidths: columnWidths, slotWidth: slotWidth, detailWidth: hasDetail ? rowDetail_1.DETAIL_SLOT_PX : 0, handleSort: handleSort, isCheckbox: isCheckbox, noBorders: noBorders, columnsSort: columnsSort, headerRefs: headerRefs, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch, openFilterId: openFilterId, setOpenFilterId: setOpenFilterId }, (0, columnLabel_1.columnLabelText)(header)));
27
29
  }), isLink && (0, jsx_runtime_1.jsx)(ViewSpacerCell, { noBorders: noBorders, isActionFreeze: isActionFreeze })] }));
28
30
  };
29
31
  exports.default = (0, react_2.memo)(TableHeader);
@@ -48,7 +50,7 @@ const SortingIcon = (0, react_2.memo)(({ label, sortState, isVisible, handleSort
48
50
  color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, variant.header.bg),
49
51
  }, children: [sortState === "none" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsUpDown, { size: 14 }), sortState === "asc" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronUp, { size: 14 }), sortState === "desc" && (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 14 })] }));
50
52
  });
51
- const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, slotWidth, isCheckbox, noBorders, columnsSort, headerRefs, columnsSearch, setColumnsSearch, handleSort, openFilterId, setOpenFilterId, }) => {
53
+ const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, slotWidth, detailWidth = 0, isCheckbox, noBorders, columnsSort, headerRefs, columnsSearch, setColumnsSearch, handleSort, openFilterId, setOpenFilterId, }) => {
52
54
  var _a, _b;
53
55
  const [isHovered, setIsHovered] = (0, react_2.useState)(false);
54
56
  const theme = (0, useCustomTheme_1.useCustomTheme)();
@@ -56,7 +58,7 @@ const ColumnHeader = (0, react_2.memo)(({ header, index, columnWidths, slotWidth
56
58
  const isFrozen = header.isFreeze;
57
59
  const align = (_a = header.align) !== null && _a !== void 0 ? _a : "start";
58
60
  const leftOffset = isFrozen
59
- ? (0, table_1.calculateLeftOffset)(columnWidths, index) + (isCheckbox ? slotWidth : 0)
61
+ ? (0, table_1.calculateLeftOffset)(columnWidths, index) + (isCheckbox ? slotWidth : 0) + detailWidth
60
62
  : undefined;
61
63
  const isSorting = header.isSort
62
64
  ? columnsSort.find((o) => o.column === header.id)
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import type { CustomThemeProps } from "../../../Theme/themeProps";
3
+ export declare const DETAIL_SLOT_PX = 40;
4
+ export declare const detailDomIds: (prefix: string, rowId: string | number) => {
5
+ cellId: string;
6
+ detailId: string;
7
+ };
8
+ export declare const RowDetailHeaderCell: ({ left, bg, ruleColor, noBorders, }: {
9
+ left: number;
10
+ bg: string;
11
+ ruleColor: string;
12
+ noBorders?: boolean;
13
+ }) => import("react/jsx-runtime").JSX.Element;
14
+ type ToggleProps = {
15
+ isOpen: boolean;
16
+ detailId: string;
17
+ color: string;
18
+ theme: CustomThemeProps;
19
+ onToggle: () => void;
20
+ };
21
+ export declare const RowDetailToggle: ({ isOpen, detailId, color, theme, onToggle }: ToggleProps) => import("react/jsx-runtime").JSX.Element;
22
+ type DetailRowProps = {
23
+ id: string;
24
+ labelledBy: string;
25
+ colSpan: number;
26
+ bg: string;
27
+ borderColor: string;
28
+ noBorders?: boolean;
29
+ children: React.ReactNode;
30
+ };
31
+ export declare const RowDetailRow: React.ForwardRefExoticComponent<DetailRowProps & React.RefAttributes<HTMLTableRowElement>>;
32
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowDetailRow = exports.RowDetailToggle = exports.RowDetailHeaderCell = exports.detailDomIds = exports.DETAIL_SLOT_PX = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_2 = require("@chakra-ui/react");
7
+ const lucide_react_1 = require("lucide-react");
8
+ const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
9
+ exports.DETAIL_SLOT_PX = 40;
10
+ const detailDomIds = (prefix, rowId) => {
11
+ const safe = `${prefix}-${rowId}`.replace(/\s+/g, "_");
12
+ return { cellId: `${safe}-cell`, detailId: `${safe}-detail` };
13
+ };
14
+ exports.detailDomIds = detailDomIds;
15
+ const RowDetailHeaderCell = ({ left, bg, ruleColor, noBorders, }) => ((0, jsx_runtime_1.jsx)(react_2.Th, { scope: "col", w: `${exports.DETAIL_SLOT_PX}px`, minW: `${exports.DETAIL_SLOT_PX}px`, maxW: `${exports.DETAIL_SLOT_PX}px`, p: 0, boxSizing: "border-box", backgroundColor: bg, position: "sticky", left: `${left}px`, zIndex: 9, className: "columns sticky-columns", borderBottom: noBorders ? "none" : `0.063rem solid ${ruleColor}`, children: (0, jsx_runtime_1.jsx)(react_2.VisuallyHidden, { children: "Row details" }) }));
16
+ exports.RowDetailHeaderCell = RowDetailHeaderCell;
17
+ const RowDetailToggle = ({ isOpen, detailId, color, theme, onToggle }) => ((0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": isOpen ? "Collapse row details" : "Expand row details", "aria-expanded": isOpen, "aria-controls": detailId, icon: isOpen ? (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: 16 }) : (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 16 }), color: color, size: "sm", variant: "ghost", onClick: onToggle, _focusVisible: (0, focusRing_styles_1.focusVisibleRing)(theme.colors) }));
18
+ exports.RowDetailToggle = RowDetailToggle;
19
+ exports.RowDetailRow = (0, react_1.forwardRef)(({ id, labelledBy, colSpan, bg, borderColor, noBorders, children }, ref) => ((0, jsx_runtime_1.jsx)(react_2.Tr, { ref: ref, id: id, "aria-labelledby": labelledBy, children: (0, jsx_runtime_1.jsx)(react_2.Td, { colSpan: colSpan, p: 0, bg: bg, borderBottom: noBorders ? "none" : `0.063rem solid ${borderColor}`, children: (0, jsx_runtime_1.jsx)(react_2.Box, { px: 4, py: 3, children: children }) }) })));
20
+ exports.RowDetailRow.displayName = "RowDetailRow";
@@ -0,0 +1,7 @@
1
+ type RowId = string | number;
2
+ /** Expanded-row ids, controlled when `controlled` is given and uncontrolled otherwise. */
3
+ export declare const useRowExpansion: (controlled: RowId[] | undefined, onChange: ((ids: RowId[]) => void) | undefined) => {
4
+ expandedIds: Set<RowId>;
5
+ toggle: (id: RowId) => void;
6
+ };
7
+ export {};
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRowExpansion = void 0;
4
+ const react_1 = require("react");
5
+ /** Expanded-row ids, controlled when `controlled` is given and uncontrolled otherwise. */
6
+ const useRowExpansion = (controlled, onChange) => {
7
+ const [internal, setInternal] = (0, react_1.useState)([]);
8
+ const isControlled = controlled !== undefined;
9
+ const current = isControlled ? controlled : internal;
10
+ const currentRef = (0, react_1.useRef)(current);
11
+ currentRef.current = current;
12
+ const isControlledRef = (0, react_1.useRef)(isControlled);
13
+ isControlledRef.current = isControlled;
14
+ const onChangeRef = (0, react_1.useRef)(onChange);
15
+ onChangeRef.current = onChange;
16
+ const toggle = (0, react_1.useCallback)((id) => {
17
+ var _a;
18
+ const prev = currentRef.current;
19
+ const next = prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id];
20
+ if (!isControlledRef.current)
21
+ setInternal(next);
22
+ (_a = onChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onChangeRef, next);
23
+ }, []);
24
+ const expandedIds = (0, react_1.useMemo)(() => new Set(current), [current]);
25
+ return { expandedIds, toggle };
26
+ };
27
+ exports.useRowExpansion = useRowExpansion;
@@ -1,3 +1,3 @@
1
1
  import type { TabsProps } from "./TabsProps";
2
- declare const Tabs: ({ items, children, value, defaultValue, onChange, variant, size, colorScheme, orientation, activationMode, isLazy, isFitted, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, }: TabsProps) => import("react/jsx-runtime").JSX.Element;
2
+ declare const Tabs: ({ items, children, value, defaultValue, onChange, variant, size, colorScheme, orientation, activationMode, isLazy, isFitted, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, linkAs, }: TabsProps) => import("react/jsx-runtime").JSX.Element;
3
3
  export default Tabs;
@@ -11,11 +11,21 @@ const TabList_1 = __importDefault(require("./components/TabList"));
11
11
  const Tab_1 = __importDefault(require("./components/Tab"));
12
12
  const TabPanels_1 = __importDefault(require("./components/TabPanels"));
13
13
  const TabPanel_1 = __importDefault(require("./components/TabPanel"));
14
- const Tabs = ({ items, children, value, defaultValue, onChange, variant = "line", size = "sm", colorScheme = "primary", orientation = "horizontal", activationMode = "automatic", isLazy = false, isFitted = false, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, }) => {
14
+ const TabLinkList_1 = __importDefault(require("./components/TabLinkList"));
15
+ const Tabs = ({ items, children, value, defaultValue, onChange, variant = "line", size = "sm", colorScheme = "primary", orientation = "horizontal", activationMode = "automatic", isLazy = false, isFitted = false, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, linkAs = "a", }) => {
16
+ var _a;
15
17
  const generatedId = (0, react_1.useId)();
16
18
  const baseId = id !== null && id !== void 0 ? id : generatedId;
17
19
  const isControlled = value !== undefined;
18
- const [internalValue, setInternalValue] = (0, react_1.useState)(() => { var _a; return defaultValue !== null && defaultValue !== void 0 ? defaultValue : (_a = items === null || items === void 0 ? void 0 : items.find((item) => !item.isDisabled)) === null || _a === void 0 ? void 0 : _a.id; });
20
+ const linkCount = (_a = items === null || items === void 0 ? void 0 : items.filter((item) => item.href !== undefined).length) !== null && _a !== void 0 ? _a : 0;
21
+ const isLinkMode = !children && !!(items === null || items === void 0 ? void 0 : items.length) && linkCount === items.length;
22
+ const isMixed = !children && linkCount > 0 && !isLinkMode;
23
+ (0, react_1.useEffect)(() => {
24
+ if (isMixed && process.env.NODE_ENV !== "production") {
25
+ console.warn("Tabs: some items have `href` and some do not. Link mode needs `href` on every item; rendering a tablist and ignoring `href`.");
26
+ }
27
+ }, [isMixed]);
28
+ const [internalValue, setInternalValue] = (0, react_1.useState)(() => { var _a; return defaultValue !== null && defaultValue !== void 0 ? defaultValue : (isLinkMode ? undefined : (_a = items === null || items === void 0 ? void 0 : items.find((item) => !item.isDisabled)) === null || _a === void 0 ? void 0 : _a.id); });
19
29
  const selectedId = isControlled ? value : internalValue;
20
30
  const [focusedId, setFocusedId] = (0, react_1.useState)(selectedId);
21
31
  const [hasPanels, setHasPanels] = (0, react_1.useState)(() => !!(items === null || items === void 0 ? void 0 : items.some((item) => item.content !== undefined)));
@@ -64,6 +74,9 @@ const Tabs = ({ items, children, value, defaultValue, onChange, variant = "line"
64
74
  if (children) {
65
75
  return (0, jsx_runtime_1.jsx)(TabsContext_1.TabsContext.Provider, { value: contextValue, children: children });
66
76
  }
77
+ if (isLinkMode) {
78
+ return ((0, jsx_runtime_1.jsx)(TabsContext_1.TabsContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsx)(TabLinkList_1.default, { items: items, linkAs: linkAs, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) }));
79
+ }
67
80
  const hasContent = !!(items === null || items === void 0 ? void 0 : items.some((item) => item.content !== undefined));
68
81
  return ((0, jsx_runtime_1.jsx)(TabsContext_1.TabsContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", flexDirection: orientation === "vertical" ? "row" : "column", alignItems: orientation === "vertical" ? "flex-start" : undefined, gap: orientation === "vertical" ? 4 : 2, children: [(0, jsx_runtime_1.jsx)(TabList_1.default, { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, children: items === null || items === void 0 ? void 0 : items.map((item) => ((0, jsx_runtime_1.jsx)(Tab_1.default, { value: item.id, icon: item.icon, count: item.count, isDisabled: item.isDisabled, children: item.label }, item.id))) }), hasContent ? ((0, jsx_runtime_1.jsx)(TabPanels_1.default, { children: items === null || items === void 0 ? void 0 : items.filter((item) => item.content !== undefined).map((item) => ((0, jsx_runtime_1.jsx)(TabPanel_1.default, { value: item.id, children: item.content }, item.id))) })) : null] }) }));
69
82
  };
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from "react";
1
+ import type { ElementType, ReactNode } from "react";
2
2
  import type { ControlSize } from "../../Theme/tokens/primitives/controlSizes";
3
3
  /** Visual treatment; follows the repo's solid/subtle/outline/ghost/line vocabulary. Defaults to "line". */
4
4
  export type TabsVariant = "solid" | "subtle" | "outline" | "ghost" | "line";
@@ -8,7 +8,7 @@ export type TabsOrientation = "horizontal" | "vertical";
8
8
  export type TabActivationMode = "automatic" | "manual";
9
9
  /** Category colour for the selected tab's ink/fill and its count badge. */
10
10
  export type TabsColorScheme = "primary" | "secondary" | "tertiary" | "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink";
11
- /** One entry in the declarative `items` API; omit `content` when panels are rendered elsewhere (e.g. a route). */
11
+ /** One entry in the declarative `items` API; omit `content` when panels are rendered elsewhere (e.g. a route). With `href` on every item it is a navigation link, not a tab. */
12
12
  export interface TabItem {
13
13
  id: string;
14
14
  label: ReactNode;
@@ -19,6 +19,8 @@ export interface TabItem {
19
19
  isDisabled?: boolean;
20
20
  /** Panel body for this tab; if no item in `items` sets one, no panel container is rendered at all. */
21
21
  content?: ReactNode;
22
+ /** Makes the item a link. When every item has one, `Tabs` renders a `<nav>` of links instead of a tablist. */
23
+ href?: string;
22
24
  }
23
25
  /** Themed, accessible tabs. Pass `items` for the declarative API, or `children` (TabList/Tab/TabPanels/TabPanel) to compose by hand. */
24
26
  export interface TabsProps {
@@ -45,6 +47,8 @@ export interface TabsProps {
45
47
  id?: string;
46
48
  "aria-label"?: string;
47
49
  "aria-labelledby"?: string;
50
+ /** Anchor-like component for `href` items, e.g. a router link. Defaults to "a"; link mode only. */
51
+ linkAs?: ElementType;
48
52
  }
49
53
  /** Composed-API tablist wrapper; renders `Tab` children and owns keyboard navigation + overflow scroll. */
50
54
  export interface TabListProps {
@@ -6,45 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const react_1 = require("react");
8
8
  const react_2 = require("@chakra-ui/react");
9
- const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
10
- const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
11
- const outlineRung_1 = require("../../../Theme/tokens/builders/outlineRung");
12
- const color_1 = require("../../../Theme/tokens/builders/color");
13
- const motion_1 = require("../../../Theme/tokens/primitives/motion");
14
- const motion_2 = require("../../../Theme/chakra/motion");
15
- const controlSizes_1 = require("../../../Theme/tokens/primitives/controlSizes");
16
- const iconBox_1 = require("../../Common/iconBox");
17
- const tabStyles_1 = require("../tabStyles");
18
9
  const TabsContext_1 = require("../TabsContext");
10
+ const useTabAppearance_1 = require("../useTabAppearance");
19
11
  const CountBadge_1 = __importDefault(require("./CountBadge"));
20
12
  const Tab = ({ value, children, icon, count, isDisabled }) => {
21
- var _a, _b, _c, _d;
22
- const { colors } = (0, useCustomTheme_1.useCustomTheme)();
13
+ var _a;
23
14
  const ctx = (0, TabsContext_1.useTabsContext)();
24
15
  const ref = (0, react_1.useRef)(null);
25
16
  const isSelected = ctx.selectedId === value;
26
17
  const isFocusTarget = ((_a = ctx.focusedId) !== null && _a !== void 0 ? _a : ctx.selectedId) === value;
27
- const isVertical = ctx.orientation === "vertical";
28
- const isLine = ctx.variant === "line";
29
- const canvas = colors.backgroundColor.main;
30
- const scale = (0, tabStyles_1.scaleForColorScheme)(colors, ctx.colorScheme);
31
- const style = (0, tabStyles_1.resolveTabStyle)(colors, scale, canvas, ctx.variant, isSelected);
32
- const spec = controlSizes_1.BUTTON_SIZES[ctx.size];
33
- // The list scrolls on both axes, so an outer ring is clipped into arcs; a negative offset draws it
34
- // inside the tab, clear of its own border rather than thickening it.
35
- const focusRing = {
36
- outline: `1px solid ${(0, outlineRung_1.liftToContrast)(colors.primary[500],
37
- // subtle/ghost fills are translucent tints; contrast has no meaning until they are flattened.
38
- style.bg === "transparent" ? canvas : (0, color_1.compositeOver)(style.bg, canvas), outlineRung_1.AA_NON_TEXT)}`,
39
- outlineOffset: "-2px",
40
- };
41
- const borderProps = ctx.variant === "outline"
42
- ? { border: "1px solid", borderColor: (_b = style.border) !== null && _b !== void 0 ? _b : "transparent" }
43
- : isLine
44
- ? isVertical
45
- ? { borderLeft: "0.125rem solid", borderLeftColor: (_c = style.indicator) !== null && _c !== void 0 ? _c : "transparent" }
46
- : { borderBottom: "0.125rem solid", borderBottomColor: (_d = style.indicator) !== null && _d !== void 0 ? _d : "transparent" }
47
- : {};
48
- return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: ref, role: "tab", id: (0, TabsContext_1.tabId)(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? (0, TabsContext_1.panelId)(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), display: "flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flexShrink: 0, flex: ctx.isFitted ? 1 : undefined, w: isVertical ? "100%" : undefined, h: isVertical ? "auto" : spec.height, minH: spec.height, py: isVertical ? "0.5rem" : undefined, px: spec.paddingX, fontSize: spec.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, borderRadius: isLine ? "none" : "lg", bg: style.bg, color: style.color, ...borderProps, transition: (0, motion_1.transitionFor)(["background-color", "color", "border-color"]), sx: { _focusVisible: focusRing, [focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: focusRing, ...(0, motion_2.reducedMotionSx)() }, _hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor } : undefined, children: [icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true, boxSize: `${spec.iconSize}px`, sx: (0, iconBox_1.iconBoxSx)(spec.iconSize), children: icon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", children: children }), count !== undefined ? ((0, jsx_runtime_1.jsx)(CountBadge_1.default, { count: count, colors: colors, scale: scale, surface: ctx.variant === "solid" && isSelected ? style.bg : canvas, size: ctx.size })) : null] }));
18
+ const { colors, canvas, scale, style, iconSize, iconSx, boxProps } = (0, useTabAppearance_1.useTabAppearance)(isSelected, isDisabled);
19
+ return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: ref, role: "tab", id: (0, TabsContext_1.tabId)(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? (0, TabsContext_1.panelId)(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), ...boxProps, children: [icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true, boxSize: `${iconSize}px`, sx: iconSx, children: icon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", children: children }), count !== undefined ? ((0, jsx_runtime_1.jsx)(CountBadge_1.default, { count: count, colors: colors, scale: scale, surface: ctx.variant === "solid" && isSelected ? style.bg : canvas, size: ctx.size })) : null] }));
49
20
  };
50
21
  exports.default = Tab;
@@ -0,0 +1,7 @@
1
+ import type { ElementType } from "react";
2
+ import type { TabsProps } from "../TabsProps";
3
+ type TabLinkListProps = Pick<TabsProps, "items" | "aria-label" | "aria-labelledby"> & {
4
+ linkAs: ElementType;
5
+ };
6
+ declare const TabLinkList: ({ items, linkAs, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }: TabLinkListProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default TabLinkList;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("@chakra-ui/react");
8
+ const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
9
+ const scrollbar_1 = require("../../../Theme/tokens/builders/scrollbar");
10
+ const TabsContext_1 = require("../TabsContext");
11
+ const useTabAppearance_1 = require("../useTabAppearance");
12
+ const CountBadge_1 = __importDefault(require("./CountBadge"));
13
+ const isPlainPrimaryClick = (event) => event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
14
+ const TabLink = ({ item, linkAs }) => {
15
+ const ctx = (0, TabsContext_1.useTabsContext)();
16
+ const isSelected = ctx.selectedId === item.id;
17
+ const { colors, canvas, scale, style, iconSize, iconSx, boxProps } = (0, useTabAppearance_1.useTabAppearance)(isSelected, item.isDisabled);
18
+ const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.icon ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": true, boxSize: `${iconSize}px`, sx: iconSx, children: item.icon })) : null, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", children: item.label }), item.count !== undefined ? ((0, jsx_runtime_1.jsx)(CountBadge_1.default, { count: item.count, colors: colors, scale: scale, surface: ctx.variant === "solid" && isSelected ? style.bg : canvas, size: ctx.size })) : null] }));
19
+ if (item.isDisabled) {
20
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-disabled": "true", "data-value": item.id, ...boxProps, children: content }));
21
+ }
22
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: linkAs, href: item.href, "aria-current": isSelected ? "page" : undefined, "data-value": item.id, onClick: (event) => {
23
+ if (!event.defaultPrevented && isPlainPrimaryClick(event))
24
+ ctx.select(item.id);
25
+ }, ...boxProps, children: content }));
26
+ };
27
+ const TabLinkList = ({ items, linkAs, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }) => {
28
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
29
+ const ctx = (0, TabsContext_1.useTabsContext)();
30
+ const isVertical = ctx.orientation === "vertical";
31
+ const isLine = ctx.variant === "line";
32
+ return ((0, jsx_runtime_1.jsx)(react_1.Flex, { as: "nav", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, direction: isVertical ? "column" : "row", flexShrink: 0, minW: isVertical ? "10rem" : undefined, overflowX: isVertical ? undefined : "auto", overflowY: isVertical ? "auto" : undefined, flexWrap: "nowrap", gap: isLine ? 1 : 1.5, borderBottom: isLine && !isVertical ? "1px solid" : undefined, borderBottomColor: isLine && !isVertical ? colors.boxborder[200] : undefined, borderRight: isLine && isVertical ? "1px solid" : undefined, borderRightColor: isLine && isVertical ? colors.boxborder[200] : undefined, sx: (0, scrollbar_1.scrollbarStyles)(colors, "hover"), children: items === null || items === void 0 ? void 0 : items.map((item) => ((0, jsx_runtime_1.jsx)(TabLink, { item: item, linkAs: linkAs }, item.id))) }));
33
+ };
34
+ exports.default = TabLinkList;
@@ -0,0 +1,17 @@
1
+ import type { BoxProps } from "@chakra-ui/react";
2
+ import { useCustomTheme } from "../../Theme/useCustomTheme";
3
+ import { iconBoxSx } from "../Common/iconBox";
4
+ import { resolveTabStyle, scaleForColorScheme } from "./tabStyles";
5
+ import { useTabsContext } from "./TabsContext";
6
+ type TabAppearance = {
7
+ ctx: ReturnType<typeof useTabsContext>;
8
+ colors: ReturnType<typeof useCustomTheme>["colors"];
9
+ canvas: string;
10
+ scale: ReturnType<typeof scaleForColorScheme>;
11
+ style: ReturnType<typeof resolveTabStyle>;
12
+ iconSize: number | string;
13
+ iconSx: ReturnType<typeof iconBoxSx>;
14
+ boxProps: BoxProps;
15
+ };
16
+ export declare const useTabAppearance: (isSelected: boolean, isDisabled?: boolean) => TabAppearance;
17
+ export {};