@dbcdk/react-components 0.0.4 → 0.0.6

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 (299) hide show
  1. package/dist/assets/logo.js +2 -85
  2. package/dist/components/__stories__/_data/table.d.ts +15 -0
  3. package/dist/components/__stories__/_data/table.js +49 -0
  4. package/dist/components/__stories__/story-components/Colors.d.ts +11 -0
  5. package/dist/components/__stories__/story-components/Colors.js +96 -0
  6. package/dist/components/__stories__/story-components/Colors.module.css +27 -0
  7. package/dist/components/__stories__/story-components/Spacing.d.ts +2 -0
  8. package/dist/components/__stories__/story-components/Spacing.js +76 -0
  9. package/dist/components/__stories__/story-components/Spacing.module.css +154 -0
  10. package/dist/components/app-header/AppHeader.d.ts +4 -3
  11. package/dist/components/app-header/AppHeader.js +3 -6
  12. package/dist/components/app-header/AppHeader.module.css +10 -15
  13. package/dist/components/attribute-chip/AttributeChip.d.ts +9 -0
  14. package/dist/components/attribute-chip/AttributeChip.js +5 -0
  15. package/dist/components/attribute-chip/AttributeChip.module.css +65 -0
  16. package/dist/components/avatar/Avatar.d.ts +5 -3
  17. package/dist/components/avatar/Avatar.js +37 -37
  18. package/dist/components/avatar/Avatar.module.css +27 -0
  19. package/dist/components/breadcrumbs/Breadcrumbs.d.ts +4 -4
  20. package/dist/components/breadcrumbs/Breadcrumbs.js +4 -14
  21. package/dist/components/breadcrumbs/Breadcrumbs.module.css +19 -22
  22. package/dist/components/button/Button.d.ts +6 -2
  23. package/dist/components/button/Button.js +56 -50
  24. package/dist/components/button/Button.module.css +119 -56
  25. package/dist/components/card/Card.d.ts +23 -7
  26. package/dist/components/card/Card.js +20 -21
  27. package/dist/components/card/Card.module.css +148 -44
  28. package/dist/components/card-container/CardContainer.d.ts +6 -3
  29. package/dist/components/card-container/CardContainer.js +4 -15
  30. package/dist/components/card-container/CardContainer.module.css +40 -0
  31. package/dist/components/chip/Chip.d.ts +7 -5
  32. package/dist/components/chip/Chip.js +14 -37
  33. package/dist/components/chip/Chip.module.css +50 -27
  34. package/dist/components/circle/Circle.d.ts +3 -2
  35. package/dist/components/circle/Circle.js +3 -10
  36. package/dist/components/circle/Circle.module.css +11 -11
  37. package/dist/components/clear-button/ClearButton.d.ts +2 -1
  38. package/dist/components/clear-button/ClearButton.js +6 -17
  39. package/dist/components/clear-button/ClearButton.module.css +8 -7
  40. package/dist/components/code-block/CodeBlock.d.ts +7 -0
  41. package/dist/components/code-block/CodeBlock.js +6 -0
  42. package/dist/components/code-block/CodeBlock.module.css +60 -0
  43. package/dist/components/copy-button/CopyButton.d.ts +10 -0
  44. package/dist/components/copy-button/CopyButton.js +22 -0
  45. package/dist/components/copy-button/CopyButton.module.css +6 -0
  46. package/dist/components/datetime-picker/DateTimePicker.d.ts +42 -0
  47. package/dist/components/datetime-picker/DateTimePicker.js +403 -0
  48. package/dist/components/datetime-picker/DateTimePicker.module.css +144 -0
  49. package/dist/components/filter-field/FilterField.d.ts +6 -3
  50. package/dist/components/filter-field/FilterField.js +130 -158
  51. package/dist/components/filter-field/FilterField.module.css +35 -25
  52. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.d.ts +36 -0
  53. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.js +53 -0
  54. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.module.css +60 -0
  55. package/dist/components/forms/checkbox/Checkbox.d.ts +31 -0
  56. package/dist/components/forms/checkbox/Checkbox.js +27 -0
  57. package/dist/components/{checkbox → forms/checkbox}/Checkbox.module.css +10 -11
  58. package/dist/components/forms/checkbox-group/CheckboxGroup.d.ts +47 -0
  59. package/dist/components/forms/checkbox-group/CheckboxGroup.js +75 -0
  60. package/dist/components/forms/checkbox-group/CheckboxGroup.module.css +115 -0
  61. package/dist/components/forms/input/Input.d.ts +22 -0
  62. package/dist/components/forms/input/Input.js +70 -0
  63. package/dist/components/forms/input/Input.module.css +160 -0
  64. package/dist/components/forms/input-container/InputContainer.d.ts +15 -0
  65. package/dist/components/forms/input-container/InputContainer.js +15 -0
  66. package/dist/components/forms/input-container/InputContainer.module.css +34 -0
  67. package/dist/components/forms/multi-select/MultiSelect.d.ts +20 -0
  68. package/dist/components/forms/multi-select/MultiSelect.js +19 -0
  69. package/dist/components/forms/select/Select.d.ts +21 -0
  70. package/dist/components/forms/select/Select.js +94 -0
  71. package/dist/components/forms/text-area/Textarea.d.ts +17 -0
  72. package/dist/components/forms/text-area/Textarea.js +33 -0
  73. package/dist/components/forms/text-area/Textarea.module.css +26 -0
  74. package/dist/components/headline/Headline.d.ts +9 -1
  75. package/dist/components/headline/Headline.js +18 -37
  76. package/dist/components/headline/Headline.module.css +32 -7
  77. package/dist/components/hyperlink/Hyperlink.d.ts +9 -0
  78. package/dist/components/hyperlink/Hyperlink.js +11 -0
  79. package/dist/components/hyperlink/Hyperlink.module.css +23 -0
  80. package/dist/components/icon/Icon.d.ts +4 -3
  81. package/dist/components/icon/Icon.js +11 -17
  82. package/dist/components/icon/Icon.module.css +10 -9
  83. package/dist/components/menu/Menu.js +25 -67
  84. package/dist/components/menu/Menu.module.css +10 -32
  85. package/dist/components/meta-bar/MetaBar.d.ts +11 -0
  86. package/dist/components/meta-bar/MetaBar.js +9 -0
  87. package/dist/components/meta-bar/MetaBar.module.css +12 -0
  88. package/dist/components/nav-bar/NavBar.d.ts +5 -5
  89. package/dist/components/nav-bar/NavBar.js +15 -45
  90. package/dist/components/nav-bar/NavBar.module.css +11 -16
  91. package/dist/components/overlay/modal/Modal.d.ts +23 -0
  92. package/dist/components/overlay/modal/Modal.js +92 -0
  93. package/dist/components/overlay/modal/Modal.module.css +66 -0
  94. package/dist/components/overlay/modal/provider/ModalProvider.d.ts +20 -0
  95. package/dist/components/overlay/modal/provider/ModalProvider.js +70 -0
  96. package/dist/components/overlay/side-panel/SidePanel.d.ts +16 -0
  97. package/dist/components/overlay/side-panel/SidePanel.js +10 -0
  98. package/dist/components/overlay/side-panel/SidePanel.module.css +56 -0
  99. package/dist/components/overlay/side-panel/useSidePanel.d.ts +5 -0
  100. package/dist/components/overlay/side-panel/useSidePanel.js +11 -0
  101. package/dist/components/overlay/tooltip/Tooltip.d.ts +13 -0
  102. package/dist/components/overlay/tooltip/Tooltip.js +17 -0
  103. package/dist/components/overlay/tooltip/Tooltip.module.css +106 -0
  104. package/dist/components/overlay/tooltip/TooltipProvider.d.ts +20 -0
  105. package/dist/components/overlay/tooltip/TooltipProvider.js +244 -0
  106. package/dist/components/overlay/tooltip/useTooltipTrigger.d.ts +24 -0
  107. package/dist/components/overlay/tooltip/useTooltipTrigger.js +108 -0
  108. package/dist/components/page/Page.d.ts +7 -6
  109. package/dist/components/page/Page.js +4 -21
  110. package/dist/components/page/Page.module.css +2 -2
  111. package/dist/components/page-layout/PageLayout.d.ts +12 -20
  112. package/dist/components/page-layout/PageLayout.js +35 -88
  113. package/dist/components/page-layout/PageLayout.module.css +4 -80
  114. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.d.ts +11 -0
  115. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.js +7 -0
  116. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.module.css +84 -0
  117. package/dist/components/pagination/Pagination.d.ts +4 -1
  118. package/dist/components/pagination/Pagination.js +38 -105
  119. package/dist/components/pagination/Pagination.module.css +11 -3
  120. package/dist/components/panel/Panel.d.ts +4 -3
  121. package/dist/components/panel/Panel.js +5 -10
  122. package/dist/components/panel/Panel.module.css +5 -7
  123. package/dist/components/popover/Popover.d.ts +3 -1
  124. package/dist/components/popover/Popover.js +116 -124
  125. package/dist/components/popover/Popover.module.css +4 -6
  126. package/dist/components/search-box/SearchBox.d.ts +11 -8
  127. package/dist/components/search-box/SearchBox.js +112 -149
  128. package/dist/components/search-box/SearchBox.module.css +0 -1
  129. package/dist/components/segmented-progress-bar/SegmentedProgressBar.d.ts +1 -1
  130. package/dist/components/segmented-progress-bar/SegmentedProgressBar.js +47 -88
  131. package/dist/components/segmented-progress-bar/SegmentedProgressBar.module.css +5 -1
  132. package/dist/components/sidebar/Sidebar.d.ts +3 -1
  133. package/dist/components/sidebar/Sidebar.js +5 -29
  134. package/dist/components/sidebar/components/SidebarItem.js +6 -12
  135. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +4 -2
  136. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +48 -62
  137. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.module.css +9 -38
  138. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.d.ts +9 -0
  139. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +13 -0
  140. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +155 -0
  141. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +3 -1
  142. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +4 -18
  143. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +25 -12
  144. package/dist/components/sidebar/components/sidebar-items/SidebarItems.d.ts +1 -1
  145. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +9 -22
  146. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.js +20 -18
  147. package/dist/components/sidebar/providers/SidebarProvider.d.ts +9 -4
  148. package/dist/components/sidebar/providers/SidebarProvider.js +188 -73
  149. package/dist/components/skeleton-loader/SkeletonLoader.js +68 -266
  150. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +11 -34
  151. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.module.css +0 -12
  152. package/dist/components/split-button/SplitButton.d.ts +7 -5
  153. package/dist/components/split-button/SplitButton.js +4 -27
  154. package/dist/components/split-pane/SplitPane.d.ts +34 -0
  155. package/dist/components/split-pane/SplitPane.js +78 -0
  156. package/dist/components/split-pane/SplitPane.module.css +106 -0
  157. package/dist/components/split-pane/provider/SplitPaneContext.d.ts +23 -0
  158. package/dist/components/split-pane/provider/SplitPaneContext.js +85 -0
  159. package/dist/components/table/Table.d.ts +28 -10
  160. package/dist/components/table/Table.js +117 -172
  161. package/dist/components/table/Table.module.css +78 -47
  162. package/dist/components/table/components/column-resizer/ColumnResizer.js +4 -15
  163. package/dist/components/table/components/empty-state/EmptyState.d.ts +41 -0
  164. package/dist/components/table/components/empty-state/EmptyState.js +27 -0
  165. package/dist/components/table/components/empty-state/EmptyState.module.css +16 -0
  166. package/dist/components/table/components/table-settings/TableSettings.d.ts +8 -0
  167. package/dist/components/table/components/table-settings/TableSettings.js +12 -0
  168. package/dist/components/table/tanstack.d.ts +14 -0
  169. package/dist/components/table/tanstack.js +162 -0
  170. package/dist/components/tabs/Tabs.d.ts +7 -3
  171. package/dist/components/tabs/Tabs.js +32 -65
  172. package/dist/components/tabs/Tabs.module.css +9 -9
  173. package/dist/components/toast/Toast.d.ts +14 -0
  174. package/dist/components/toast/Toast.js +8 -0
  175. package/dist/components/toast/Toast.module.css +102 -0
  176. package/dist/components/toast/provider/ToastProvider.d.ts +23 -0
  177. package/dist/components/toast/provider/ToastProvider.js +64 -0
  178. package/dist/components/user-display/UserDisplay.d.ts +2 -1
  179. package/dist/components/user-display/UserDisplay.js +4 -20
  180. package/dist/components/user-display/UserDisplay.module.css +2 -2
  181. package/dist/constants/severity.d.ts +1 -1
  182. package/dist/constants/severity.js +14 -16
  183. package/dist/constants/severity.types.d.ts +1 -1
  184. package/dist/constants/severity.types.js +1 -1
  185. package/dist/constants/sizes.d.ts +1 -1
  186. package/dist/constants/sizes.js +6 -7
  187. package/dist/hooks/usePagination.d.ts +33 -0
  188. package/dist/hooks/usePagination.js +79 -0
  189. package/dist/hooks/useSorting.d.ts +49 -0
  190. package/dist/hooks/useSorting.js +118 -0
  191. package/dist/hooks/useTableData.d.ts +40 -0
  192. package/dist/hooks/useTableData.js +45 -0
  193. package/dist/hooks/useTableSelection.d.ts +25 -0
  194. package/dist/hooks/useTableSelection.js +128 -0
  195. package/dist/hooks/useTableSettings.d.ts +7 -0
  196. package/dist/hooks/useTableSettings.js +24 -0
  197. package/dist/hooks/useTheme.d.ts +3 -7
  198. package/dist/hooks/useTheme.js +52 -47
  199. package/dist/hooks/useTimeDuration.d.ts +22 -0
  200. package/dist/hooks/useTimeDuration.js +36 -0
  201. package/dist/hooks/useViewportFill.d.ts +3 -2
  202. package/dist/hooks/useViewportFill.js +55 -48
  203. package/dist/index.d.ts +32 -6
  204. package/dist/index.js +33 -6
  205. package/dist/src/styles/styles.css +101 -8
  206. package/dist/styles/css-helper-classes/flex.css +101 -0
  207. package/dist/styles/css-helper-classes/typography.css +7 -0
  208. package/dist/styles/styles.css +101 -8
  209. package/dist/styles/themes/dbc/dark.css +207 -100
  210. package/dist/styles/themes/dbc/light.css +185 -90
  211. package/dist/styles/themes/forfatterweb/light.css +1 -1
  212. package/dist/styles/themes/types.js +1 -1
  213. package/dist/types/a11y-props.types.d.ts +5 -5
  214. package/dist/types/a11y-props.types.js +1 -1
  215. package/dist/types/sizes.types.d.ts +2 -2
  216. package/dist/types/sizes.types.js +1 -1
  217. package/dist/utils/arrays/nested-filtering.js +43 -33
  218. package/dist/utils/date/formatDate.js +25 -16
  219. package/package.json +33 -18
  220. package/dist/assets/logo.cjs +0 -87
  221. package/dist/components/app-header/AppHeader.cjs +0 -14
  222. package/dist/components/avatar/Avatar.cjs +0 -67
  223. package/dist/components/breadcrumbs/Breadcrumbs.cjs +0 -23
  224. package/dist/components/button/Button.cjs +0 -79
  225. package/dist/components/card/Card.cjs +0 -29
  226. package/dist/components/card-container/CardContainer.cjs +0 -23
  227. package/dist/components/checkbox/Checkbox.cjs +0 -43
  228. package/dist/components/checkbox/Checkbox.d.ts +0 -12
  229. package/dist/components/checkbox/Checkbox.js +0 -37
  230. package/dist/components/chip/Chip.cjs +0 -49
  231. package/dist/components/circle/Circle.cjs +0 -18
  232. package/dist/components/clear-button/ClearButton.cjs +0 -26
  233. package/dist/components/data-summary/DataSummary.cjs +0 -49
  234. package/dist/components/data-summary/DataSummary.d.ts +0 -19
  235. package/dist/components/data-summary/DataSummary.js +0 -43
  236. package/dist/components/data-summary/DataSummary.module.css +0 -51
  237. package/dist/components/filter-field/FilterField.cjs +0 -174
  238. package/dist/components/headline/Headline.cjs +0 -47
  239. package/dist/components/icon/Icon.cjs +0 -27
  240. package/dist/components/input/Input.cjs +0 -48
  241. package/dist/components/input/Input.d.ts +0 -13
  242. package/dist/components/input/Input.js +0 -42
  243. package/dist/components/input/Input.module.css +0 -112
  244. package/dist/components/menu/Menu.cjs +0 -96
  245. package/dist/components/multi-select/MultiSelect.cjs +0 -48
  246. package/dist/components/multi-select/MultiSelect.d.ts +0 -18
  247. package/dist/components/multi-select/MultiSelect.js +0 -46
  248. package/dist/components/nav-bar/NavBar.cjs +0 -55
  249. package/dist/components/page/Page.cjs +0 -30
  250. package/dist/components/page-layout/PageLayout.cjs +0 -101
  251. package/dist/components/pagination/Pagination.cjs +0 -117
  252. package/dist/components/panel/Panel.cjs +0 -18
  253. package/dist/components/popover/Popover.cjs +0 -132
  254. package/dist/components/search-box/SearchBox.cjs +0 -162
  255. package/dist/components/segmented-progress-bar/SegmentedProgressBar.cjs +0 -97
  256. package/dist/components/select/Select.cjs +0 -52
  257. package/dist/components/select/Select.d.ts +0 -11
  258. package/dist/components/select/Select.js +0 -50
  259. package/dist/components/sidebar/Sidebar.cjs +0 -38
  260. package/dist/components/sidebar/Sidebar.module.css +0 -66
  261. package/dist/components/sidebar/components/SidebarItem.cjs +0 -16
  262. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +0 -74
  263. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +0 -27
  264. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +0 -28
  265. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.cjs +0 -25
  266. package/dist/components/sidebar/providers/SidebarProvider.cjs +0 -81
  267. package/dist/components/skeleton-loader/SkeletonLoader.cjs +0 -270
  268. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.cjs +0 -42
  269. package/dist/components/split-button/SplitButton.cjs +0 -37
  270. package/dist/components/table/Table.cjs +0 -181
  271. package/dist/components/table/components/column-resizer/ColumnResizer.cjs +0 -22
  272. package/dist/components/tabs/Tabs.cjs +0 -74
  273. package/dist/components/text-area/Textarea.cjs +0 -62
  274. package/dist/components/text-area/Textarea.d.ts +0 -14
  275. package/dist/components/text-area/Textarea.js +0 -56
  276. package/dist/components/text-area/Textarea.module.css +0 -3
  277. package/dist/components/tooltip/Tooltip.cjs +0 -78
  278. package/dist/components/tooltip/Tooltip.d.ts +0 -11
  279. package/dist/components/tooltip/Tooltip.js +0 -72
  280. package/dist/components/tooltip/Tooltip.module.css +0 -84
  281. package/dist/components/user-display/UserDisplay.cjs +0 -28
  282. package/dist/constants/severity.cjs +0 -21
  283. package/dist/constants/severity.types.cjs +0 -2
  284. package/dist/constants/sizes.cjs +0 -10
  285. package/dist/hooks/useTheme.cjs +0 -58
  286. package/dist/hooks/useViewportFill.cjs +0 -52
  287. package/dist/index.cjs +0 -264
  288. package/dist/styles/themes/types.cjs +0 -2
  289. package/dist/tanstack.cjs +0 -231
  290. package/dist/tanstack.d.ts +0 -25
  291. package/dist/tanstack.js +0 -206
  292. package/dist/types/a11y-props.types.cjs +0 -2
  293. package/dist/types/assets.d.cjs +0 -2
  294. package/dist/types/assets.d.js +0 -1
  295. package/dist/types/css.d.cjs +0 -2
  296. package/dist/types/css.d.js +0 -1
  297. package/dist/types/sizes.types.cjs +0 -2
  298. package/dist/utils/arrays/nested-filtering.cjs +0 -40
  299. package/dist/utils/date/formatDate.cjs +0 -19
@@ -0,0 +1,118 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ function defaultCompare(a, b, dir, nulls) {
4
+ const aNull = a == null;
5
+ const bNull = b == null;
6
+ if (aNull || bNull) {
7
+ if (aNull && bNull)
8
+ return 0;
9
+ const order = nulls === 'first' ? -1 : 1;
10
+ return aNull ? order : -order;
11
+ }
12
+ // Dates
13
+ if (a instanceof Date && b instanceof Date) {
14
+ const diff = a.getTime() - b.getTime();
15
+ return dir === 'asc' ? diff : -diff;
16
+ }
17
+ // Numbers
18
+ if (typeof a === 'number' && typeof b === 'number') {
19
+ const diff = a - b;
20
+ return dir === 'asc' ? diff : -diff;
21
+ }
22
+ // Booleans
23
+ if (typeof a === 'boolean' && typeof b === 'boolean') {
24
+ const diff = Number(a) - Number(b);
25
+ return dir === 'asc' ? diff : -diff;
26
+ }
27
+ // Strings (locale-aware-ish)
28
+ const aStr = String(a);
29
+ const bStr = String(b);
30
+ const diff = aStr.localeCompare(bStr, undefined, { numeric: true, sensitivity: 'base' });
31
+ return dir === 'asc' ? diff : -diff;
32
+ }
33
+ // Stable sort (decorate-sort-undecorate)
34
+ function stableSort(arr, cmp) {
35
+ return arr
36
+ .map((item, idx) => ({ item, idx }))
37
+ .sort((x, y) => {
38
+ const c = cmp(x.item, y.item);
39
+ return c !== 0 ? c : x.idx - y.idx;
40
+ })
41
+ .map(x => x.item);
42
+ }
43
+ export function useSorting({ data = [], sortBy = null, sortDirection = 'asc', state, onStateChange, columnComparators = {}, nulls = 'last', allowUnsort = true, resetOnDataChange = false, }) {
44
+ const isControlled = state != null;
45
+ const [uncontrolled, setUncontrolled] = useState(() => ({
46
+ sortBy,
47
+ sortDirection,
48
+ }));
49
+ const sortState = (isControlled ? state : uncontrolled);
50
+ const setSort = useCallback((next) => {
51
+ var _a, _b;
52
+ const normalized = {
53
+ sortBy: (_a = next.sortBy) !== null && _a !== void 0 ? _a : null,
54
+ sortDirection: (_b = next.sortDirection) !== null && _b !== void 0 ? _b : null,
55
+ };
56
+ if (isControlled)
57
+ onStateChange === null || onStateChange === void 0 ? void 0 : onStateChange(normalized);
58
+ else
59
+ setUncontrolled(normalized);
60
+ }, [isControlled, onStateChange]);
61
+ const clearSort = useCallback(() => setSort({ sortBy: null, sortDirection: null }), [setSort]);
62
+ const onSortChange = useCallback((e) => {
63
+ var _a, _b;
64
+ const nextSortBy = ((_a = e.sortBy) !== null && _a !== void 0 ? _a : null);
65
+ setSort(sortState);
66
+ const current = sortState;
67
+ if (nextSortBy == null) {
68
+ return clearSort();
69
+ }
70
+ // Same column toggling
71
+ if (current.sortBy === nextSortBy) {
72
+ const nextDir = current.sortDirection === 'asc' ? 'desc' : allowUnsort ? null : 'asc';
73
+ return setSort({ sortBy: nextSortBy, sortDirection: nextDir });
74
+ }
75
+ // New column: default to provided direction or asc
76
+ return setSort({
77
+ sortBy: nextSortBy,
78
+ sortDirection: (_b = e.sortDirection) !== null && _b !== void 0 ? _b : 'asc',
79
+ });
80
+ }, [allowUnsort, clearSort, setSort, sortState]);
81
+ // Optional reset on data ref change
82
+ const didInitRef = useRef(false);
83
+ useEffect(() => {
84
+ if (!resetOnDataChange)
85
+ return;
86
+ if (!didInitRef.current) {
87
+ didInitRef.current = true;
88
+ return;
89
+ }
90
+ clearSort();
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ }, [resetOnDataChange, data]);
93
+ const sortedData = useMemo(() => {
94
+ const { sortBy: sb, sortDirection: dir } = sortState;
95
+ if (!sb || !dir)
96
+ return data;
97
+ const custom = columnComparators[sb];
98
+ const cmp = (a, b) => {
99
+ if (custom)
100
+ return custom(a, b, dir);
101
+ const av = a[sb];
102
+ const bv = b[sb];
103
+ return defaultCompare(av, bv, dir, nulls);
104
+ };
105
+ // Don’t mutate input
106
+ return stableSort(data, cmp);
107
+ }, [data, sortState, columnComparators, nulls]);
108
+ // Helper: support functional updates in uncontrolled mode (optional nicety)
109
+ const setSortRef = useRef(setSort);
110
+ setSortRef.current = setSort;
111
+ return {
112
+ sortedData,
113
+ sortState,
114
+ onSortChange,
115
+ setSort,
116
+ clearSort,
117
+ };
118
+ }
@@ -0,0 +1,40 @@
1
+ import type { PageChangeEvent } from '../components/pagination/Pagination';
2
+ import { type PaginationState } from './usePagination';
3
+ import { type SortDirection, type SortState, type ColumnComparators } from './useSorting';
4
+ export interface UseTableDataProps<T> {
5
+ data?: readonly T[];
6
+ pagination?: {
7
+ skip?: number;
8
+ take?: number;
9
+ state?: PaginationState;
10
+ onStateChange?: (next: PaginationState) => void;
11
+ };
12
+ sorting?: {
13
+ sortBy?: keyof T | null;
14
+ direction?: SortDirection;
15
+ state?: SortState<T>;
16
+ onStateChange?: (next: SortState<T>) => void;
17
+ columnComparators?: ColumnComparators<T>;
18
+ nulls?: 'first' | 'last';
19
+ allowUnsort?: boolean;
20
+ };
21
+ /**
22
+ * Resets to page 1 whenever sorting changes (typical UX).
23
+ */
24
+ resetPageOnSortChange?: boolean;
25
+ }
26
+ export interface UseTableDataResult<T> {
27
+ rows: T[];
28
+ totalCount: number;
29
+ pagination: {
30
+ state: PaginationState;
31
+ onPageChange: (e: PageChangeEvent) => void;
32
+ resetPage: () => void;
33
+ };
34
+ sorting: {
35
+ state: SortState<T>;
36
+ onSortChange: (next: Partial<SortState<T>>) => void;
37
+ clearSort: () => void;
38
+ };
39
+ }
40
+ export declare function useTableData<T extends Record<string, any>>({ data, pagination, sorting, resetPageOnSortChange, }: UseTableDataProps<T>): UseTableDataResult<T>;
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+ import { useEffect, useMemo } from 'react';
3
+ import { usePagination } from './usePagination';
4
+ import { useSorting, } from './useSorting';
5
+ export function useTableData({ data = [], pagination, sorting, resetPageOnSortChange = true, }) {
6
+ var _a, _b, _c, _d, _e, _f;
7
+ const s = useSorting({
8
+ data,
9
+ sortBy: (_a = sorting === null || sorting === void 0 ? void 0 : sorting.sortBy) !== null && _a !== void 0 ? _a : null,
10
+ sortDirection: (_b = sorting === null || sorting === void 0 ? void 0 : sorting.direction) !== null && _b !== void 0 ? _b : null,
11
+ state: sorting === null || sorting === void 0 ? void 0 : sorting.state,
12
+ onStateChange: sorting === null || sorting === void 0 ? void 0 : sorting.onStateChange,
13
+ columnComparators: sorting === null || sorting === void 0 ? void 0 : sorting.columnComparators,
14
+ nulls: (_c = sorting === null || sorting === void 0 ? void 0 : sorting.nulls) !== null && _c !== void 0 ? _c : 'last',
15
+ allowUnsort: (_d = sorting === null || sorting === void 0 ? void 0 : sorting.allowUnsort) !== null && _d !== void 0 ? _d : true,
16
+ });
17
+ const p = usePagination({
18
+ data: s.sortedData,
19
+ skip: (_e = pagination === null || pagination === void 0 ? void 0 : pagination.skip) !== null && _e !== void 0 ? _e : 0,
20
+ take: (_f = pagination === null || pagination === void 0 ? void 0 : pagination.take) !== null && _f !== void 0 ? _f : 10,
21
+ state: pagination === null || pagination === void 0 ? void 0 : pagination.state,
22
+ onStateChange: pagination === null || pagination === void 0 ? void 0 : pagination.onStateChange,
23
+ });
24
+ useEffect(() => {
25
+ if (!resetPageOnSortChange)
26
+ return;
27
+ p.resetPage();
28
+ // eslint-disable-next-line react-hooks/exhaustive-deps
29
+ }, [resetPageOnSortChange, s.sortState.sortBy, s.sortState.sortDirection]);
30
+ const rows = useMemo(() => p.paginatedData, [p.paginatedData]);
31
+ return {
32
+ rows,
33
+ totalCount: s.sortedData.length,
34
+ pagination: {
35
+ state: p.paginationState,
36
+ onPageChange: p.onPageChange,
37
+ resetPage: p.resetPage,
38
+ },
39
+ sorting: {
40
+ state: s.sortState,
41
+ onSortChange: s.onSortChange,
42
+ clearSort: s.clearSort,
43
+ },
44
+ };
45
+ }
@@ -0,0 +1,25 @@
1
+ type Id = string | number;
2
+ interface Props<T> {
3
+ storageKey: string;
4
+ items: T[];
5
+ getId: (item: T) => Id;
6
+ initialSelectedIds?: Set<Id>;
7
+ onSelectionChange?: (args: {
8
+ selectedIds: Set<Id>;
9
+ selectedItems: T[];
10
+ }) => void;
11
+ totalItems?: number;
12
+ selectionMode?: 'single' | 'multiple';
13
+ }
14
+ export declare function useTableSelection<T>({ storageKey, items, getId, initialSelectedIds, totalItems, onSelectionChange, selectionMode, }: Props<T>): {
15
+ selectedIds: Set<Id>;
16
+ selectedItems: T[];
17
+ selectedItemMap: Map<Id, T>;
18
+ toggleItem: (item: T) => void;
19
+ toggleId: (id: Id) => void;
20
+ clearSelection: () => void;
21
+ allSelected: boolean;
22
+ anySelected: boolean;
23
+ toggleAll: (selected: boolean) => void;
24
+ };
25
+ export {};
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useMemo, useState } from 'react';
3
+ export function useTableSelection({ storageKey, items, getId, initialSelectedIds = new Set(), totalItems, onSelectionChange, selectionMode = 'single', }) {
4
+ // Selected IDs are persisted and are your primary lookup structure
5
+ const [selectedIds, setSelectedIds] = useState(initialSelectedIds);
6
+ // Keep the actual selected items keyed by id for O(1) access
7
+ const [selectedItemMap, setSelectedItemMap] = useState(() => new Map());
8
+ // Build a fast lookup of current items by id (for hydration + reconciliation)
9
+ const itemsById = useMemo(() => {
10
+ const m = new Map();
11
+ for (const item of items)
12
+ m.set(getId(item), item);
13
+ return m;
14
+ }, [items, getId]);
15
+ // Hydrate selectedIds from localStorage on mount / storageKey change
16
+ useEffect(() => {
17
+ const stored = window.localStorage.getItem(storageKey);
18
+ if (!stored) {
19
+ setSelectedIds(initialSelectedIds);
20
+ return;
21
+ }
22
+ try {
23
+ const parsed = JSON.parse(stored);
24
+ setSelectedIds(new Set(parsed));
25
+ }
26
+ catch {
27
+ setSelectedIds(initialSelectedIds);
28
+ }
29
+ // eslint-disable-next-line react-hooks/exhaustive-deps
30
+ }, [storageKey]);
31
+ // Reconcile selectedItemMap whenever selectedIds or items change.
32
+ // This makes sure selectedItems stay up to date without scanning the full items list on every render.
33
+ useEffect(() => {
34
+ setSelectedItemMap(prev => {
35
+ const next = new Map();
36
+ // Keep only ids that still exist in itemsById (if list changed)
37
+ for (const id of selectedIds) {
38
+ const item = itemsById.get(id);
39
+ if (item !== undefined)
40
+ next.set(id, item);
41
+ }
42
+ // If nothing changed, return prev to avoid re-renders
43
+ if (next.size === prev.size) {
44
+ let same = true;
45
+ for (const [id, item] of next) {
46
+ if (prev.get(id) !== item) {
47
+ same = false;
48
+ break;
49
+ }
50
+ }
51
+ if (same)
52
+ return prev;
53
+ }
54
+ return next;
55
+ });
56
+ }, [selectedIds, itemsById]);
57
+ const selectedItems = useMemo(() => Array.from(selectedItemMap.values()), [selectedItemMap]);
58
+ const allSelected = useMemo(() => {
59
+ if (typeof totalItems !== 'number')
60
+ return false;
61
+ return totalItems > 0 && selectedIds.size === totalItems;
62
+ }, [selectedIds, totalItems]);
63
+ const anySelected = useMemo(() => selectedIds.size > 0, [selectedIds]);
64
+ useEffect(() => {
65
+ window.localStorage.setItem(storageKey, JSON.stringify(Array.from(selectedIds)));
66
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange({ selectedIds, selectedItems });
67
+ }, [selectedIds, selectedItems, storageKey, onSelectionChange]);
68
+ const toggleId = useCallback((id) => {
69
+ setSelectedIds(prevIds => {
70
+ const nextIds = new Set(prevIds);
71
+ const isSelected = nextIds.has(id);
72
+ if (isSelected) {
73
+ nextIds.delete(id);
74
+ }
75
+ else {
76
+ if (selectionMode === 'single')
77
+ nextIds.clear();
78
+ nextIds.add(id);
79
+ }
80
+ return nextIds;
81
+ });
82
+ // Update selectedItemMap in the same interaction for snappy UI
83
+ setSelectedItemMap(prevMap => {
84
+ const nextMap = new Map(prevMap);
85
+ const isSelected = nextMap.has(id);
86
+ if (isSelected) {
87
+ nextMap.delete(id);
88
+ }
89
+ else {
90
+ if (selectionMode === 'single')
91
+ nextMap.clear();
92
+ const item = itemsById.get(id);
93
+ if (item !== undefined)
94
+ nextMap.set(id, item);
95
+ }
96
+ return nextMap;
97
+ });
98
+ }, [itemsById, selectionMode]);
99
+ const toggleItem = useCallback((item) => {
100
+ toggleId(getId(item));
101
+ }, [toggleId, getId]);
102
+ const clearSelection = useCallback(() => {
103
+ setSelectedIds(new Set());
104
+ setSelectedItemMap(new Map());
105
+ }, []);
106
+ const toggleAll = useCallback((selected) => {
107
+ if (!selected) {
108
+ clearSelection();
109
+ return;
110
+ }
111
+ const nextIds = new Set();
112
+ for (const item of items) {
113
+ nextIds.add(getId(item));
114
+ }
115
+ setSelectedIds(nextIds);
116
+ }, [clearSelection, getId, items]);
117
+ return {
118
+ selectedIds,
119
+ selectedItems,
120
+ selectedItemMap,
121
+ toggleItem,
122
+ toggleId,
123
+ clearSelection,
124
+ allSelected,
125
+ anySelected,
126
+ toggleAll,
127
+ };
128
+ }
@@ -0,0 +1,7 @@
1
+ export type ViewMode = 'compact' | 'comfortable';
2
+ interface TableSettings {
3
+ viewMode: ViewMode;
4
+ toggleViewMode: () => void;
5
+ }
6
+ export declare function useTableSettings(storageKey?: string): TableSettings;
7
+ export {};
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ export function useTableSettings(storageKey) {
4
+ const [viewMode, setViewMode] = useState('compact');
5
+ useEffect(() => {
6
+ if (typeof window !== 'undefined' && storageKey) {
7
+ const storedMode = window.localStorage.getItem(`dbc-table-settings:${storageKey}`);
8
+ if (storedMode === 'compact' || storedMode === 'comfortable') {
9
+ setViewMode(storedMode);
10
+ }
11
+ }
12
+ }, [storageKey]);
13
+ const toggleViewMode = useCallback(() => {
14
+ if (typeof window !== 'undefined' && storageKey) {
15
+ const newMode = viewMode === 'comfortable' ? 'compact' : 'comfortable';
16
+ window.localStorage.setItem(`dbc-table-settings:${storageKey}`, newMode);
17
+ }
18
+ setViewMode(prevMode => (prevMode === 'comfortable' ? 'compact' : 'comfortable'));
19
+ }, [storageKey, viewMode]);
20
+ return {
21
+ viewMode,
22
+ toggleViewMode,
23
+ };
24
+ }
@@ -1,9 +1,5 @@
1
- export type ThemeId = string;
2
- export type ThemeUrls = Record<ThemeId, string>;
3
- export declare const LINK_ID = "dbc-theme-link";
4
- export type ThemeVariant = "light" | "dark";
1
+ export type ThemeVariant = 'light' | 'dark';
5
2
  export declare function useTheme(initialTheme?: ThemeVariant): {
6
- theme: ThemeId | null;
7
- switchTheme: (id: ThemeId) => string;
8
- linkId: string;
3
+ theme: ThemeVariant | null;
4
+ switchTheme: (id: ThemeVariant) => ThemeVariant;
9
5
  };
@@ -1,55 +1,60 @@
1
- import { useState, useEffect, useCallback } from 'react';
2
-
3
- const LINK_ID = "dbc-theme-link";
4
- const STORAGE_KEY = "dbc_theme";
5
- function createLinkElement() {
6
- if (typeof document === "undefined") return null;
7
- let el = document.getElementById(LINK_ID);
8
- if (!el) {
9
- el = document.createElement("link");
10
- el.id = LINK_ID;
11
- el.rel = "stylesheet";
12
- document.head.appendChild(el);
13
- }
14
- return el;
1
+ 'use client';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+ const THEME_VARIANTS = ['light', 'dark'];
4
+ const STORAGE_KEY = 'dbc_theme';
5
+ function isThemeVariant(x) {
6
+ return !!x && THEME_VARIANTS.includes(x);
15
7
  }
16
- function setLinkHref(href) {
17
- const el = createLinkElement();
18
- if (el && el.getAttribute("href") !== href) el.setAttribute("href", href);
8
+ function getCookie(name) {
9
+ const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
10
+ return match ? decodeURIComponent(match[1]) : null;
19
11
  }
20
- function useTheme(initialTheme = "light") {
21
- const [theme, setTheme] = useState(null);
22
- useEffect(() => {
23
- let stored = initialTheme;
12
+ function persistTheme(id) {
24
13
  try {
25
- stored = localStorage.getItem(STORAGE_KEY);
26
- console.log("Restored theme from localStorage:", stored);
27
- } catch {
14
+ localStorage.setItem(STORAGE_KEY, id);
28
15
  }
29
- if (stored) {
30
- setLinkHref(`/themes/${stored}.css`);
31
- setTheme(stored);
32
- try {
33
- localStorage.setItem(STORAGE_KEY, stored);
34
- } catch {
35
- }
16
+ catch {
17
+ console.error('Failed to access localStorage');
36
18
  }
37
- }, []);
38
- const switchTheme = useCallback((id) => {
39
- const href = `/themes/${id}.css`;
40
- if (!href) return "";
41
- setLinkHref(href);
42
- setTheme(id);
43
19
  try {
44
- localStorage.setItem(STORAGE_KEY, id);
45
- document.cookie = `${STORAGE_KEY}=${encodeURIComponent(
46
- id
47
- )}; Path=/; Max-Age=${60 * 60 * 24 * 365}`;
48
- } catch {
20
+ document.cookie = `${STORAGE_KEY}=${encodeURIComponent(id)}; Path=/; Max-Age=${60 * 60 * 24 * 365}`;
49
21
  }
50
- return id;
51
- }, []);
52
- return { theme, switchTheme, linkId: LINK_ID };
22
+ catch {
23
+ console.error('Failed to set theme cookie');
24
+ }
25
+ }
26
+ function applyTheme(id) {
27
+ document.documentElement.dataset.theme = id;
28
+ }
29
+ export function useTheme(initialTheme = 'light') {
30
+ const [theme, setTheme] = useState(null);
31
+ useEffect(() => {
32
+ let resolved = initialTheme;
33
+ // Prefer cookie (SSR + client consistency)
34
+ const fromCookie = getCookie(STORAGE_KEY);
35
+ if (isThemeVariant(fromCookie)) {
36
+ resolved = fromCookie;
37
+ }
38
+ else {
39
+ // fallback to localStorage
40
+ try {
41
+ const fromStorage = localStorage.getItem(STORAGE_KEY);
42
+ if (isThemeVariant(fromStorage))
43
+ resolved = fromStorage;
44
+ }
45
+ catch {
46
+ console.error('Failed to access localStorage');
47
+ }
48
+ }
49
+ applyTheme(resolved);
50
+ setTheme(resolved);
51
+ persistTheme(resolved);
52
+ }, [initialTheme]);
53
+ const switchTheme = useCallback((id) => {
54
+ applyTheme(id);
55
+ setTheme(id);
56
+ persistTheme(id);
57
+ return id;
58
+ }, []);
59
+ return { theme, switchTheme };
53
60
  }
54
-
55
- export { LINK_ID, useTheme };
@@ -0,0 +1,22 @@
1
+ export type useTimeDurationReturn = {
2
+ /** Formatted start date (hydration-safe) */
3
+ started: string;
4
+ /** Formatted end date (hydration-safe) */
5
+ ended: string;
6
+ /** Formatted duration (hydration-safe) */
7
+ duration: string;
8
+ /** Whether client hydration has completed */
9
+ hydrated: boolean;
10
+ };
11
+ type useTimeDurationArgs = {
12
+ start?: Date;
13
+ end?: Date;
14
+ /** Intl options for started/ended formatting */
15
+ dateFormat?: Intl.DateTimeFormatOptions;
16
+ /** Placeholder shown before hydration or when date is missing */
17
+ fallback?: string;
18
+ /** Custom duration formatter if you don’t want the default "1t 2m 3s" */
19
+ formatDuration?: (ms: number) => string;
20
+ };
21
+ export declare function useTimeDuration({ start, end, dateFormat, fallback, formatDuration, }: useTimeDurationArgs): useTimeDurationReturn;
22
+ export {};
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ function defaultDuration(ms) {
4
+ if (!Number.isFinite(ms) || ms < 0)
5
+ return '—';
6
+ const sec = Math.floor(ms / 1000) % 60;
7
+ const min = Math.floor(ms / (1000 * 60)) % 60;
8
+ const hr = Math.floor(ms / (1000 * 60 * 60));
9
+ return hr > 0 ? `${hr}t ${min}m ${sec}s` : `${min}m ${sec}s`;
10
+ }
11
+ export function useTimeDuration({ start, end, dateFormat = { dateStyle: 'short', timeStyle: 'medium' }, fallback = '—', formatDuration = defaultDuration, }) {
12
+ const [hydrated, setHydrated] = useState(false);
13
+ useEffect(() => setHydrated(true), []);
14
+ const started = useMemo(() => {
15
+ if (!start)
16
+ return fallback;
17
+ if (!hydrated)
18
+ return fallback;
19
+ return new Intl.DateTimeFormat(undefined, dateFormat).format(start);
20
+ }, [start, hydrated, fallback, dateFormat]);
21
+ const ended = useMemo(() => {
22
+ if (!end)
23
+ return fallback;
24
+ if (!hydrated)
25
+ return fallback;
26
+ return new Intl.DateTimeFormat(undefined, dateFormat).format(end);
27
+ }, [end, hydrated, fallback, dateFormat]);
28
+ const duration = useMemo(() => {
29
+ if (!start || !end)
30
+ return fallback;
31
+ if (!hydrated)
32
+ return fallback;
33
+ return formatDuration(end.getTime() - start.getTime());
34
+ }, [start, end, hydrated, fallback, formatDuration]);
35
+ return { started, ended, duration, hydrated };
36
+ }
@@ -1,3 +1,4 @@
1
+ import { CSSProperties, RefObject } from 'react';
1
2
  type Options = {
2
3
  bottomOffset?: number;
3
4
  min?: number;
@@ -7,9 +8,9 @@ type Options = {
7
8
  * Computes the remaining viewport space below the element and returns a style
8
9
  * with `maxHeight` + `overflow: auto`.
9
10
  */
10
- export declare function useViewportFill<T extends HTMLElement>(ref: React.RefObject<T>, { bottomOffset, min, includeMarginTop }?: Options): {
11
+ export declare function useViewportFill<T extends HTMLElement>(ref: RefObject<T>, { bottomOffset, min, includeMarginTop }?: Options): {
11
12
  maxHeight: number;
12
- style: React.CSSProperties;
13
+ style: CSSProperties;
13
14
  recompute: () => void;
14
15
  };
15
16
  export {};