@variocube/app-ui 1.15.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/esm/AppShell/AppShell.js +12 -12
  2. package/esm/AppShell/AppShell.js.map +1 -1
  3. package/esm/AppShell/index.js.map +1 -1
  4. package/esm/Input/ActionsMenu.js +1 -1
  5. package/esm/Input/ActionsMenu.js.map +1 -1
  6. package/esm/Input/EmailSenderField.js +3 -3
  7. package/esm/Input/EmailSenderField.js.map +1 -1
  8. package/esm/Input/Selector.js +2 -2
  9. package/esm/Input/Selector.js.map +1 -1
  10. package/esm/Paging/Paging.d.ts +1 -1
  11. package/esm/Paging/Paging.js +5 -5
  12. package/esm/Paging/Paging.js.map +1 -1
  13. package/esm/Paging/index.d.ts +2 -1
  14. package/esm/Paging/index.js.map +1 -1
  15. package/esm/VCThemeProvider/JetbrainsMonoFont.js +8 -8
  16. package/esm/VCThemeProvider/JetbrainsMonoFont.js.map +1 -1
  17. package/esm/VCThemeProvider/RobotoFont.js +8 -8
  18. package/esm/VCThemeProvider/RobotoFont.js.map +1 -1
  19. package/esm/VCThemeProvider/ThemeModeSwitcher.js +5 -5
  20. package/esm/VCThemeProvider/ThemeModeSwitcher.js.map +1 -1
  21. package/esm/VCThemeProvider/VCThemeProvider.d.ts +1 -1
  22. package/esm/VCThemeProvider/VCThemeProvider.js +21 -21
  23. package/esm/VCThemeProvider/VCThemeProvider.js.map +1 -1
  24. package/esm/audit/AuditChanges.js +9 -5
  25. package/esm/audit/AuditChanges.js.map +1 -1
  26. package/esm/audit/AuditTimeline.js +1 -1
  27. package/esm/audit/AuditTimeline.js.map +1 -1
  28. package/esm/audit/AuditTimelineItem.js +3 -3
  29. package/esm/audit/AuditTimelineItem.js.map +1 -1
  30. package/esm/audit/index.d.ts +1 -1
  31. package/esm/audit/index.js +1 -1
  32. package/esm/audit/index.js.map +1 -1
  33. package/esm/breadcrumbs.d.ts +2 -2
  34. package/esm/breadcrumbs.js +3 -3
  35. package/esm/breadcrumbs.js.map +1 -1
  36. package/esm/code/CodeBlock.d.ts +1 -1
  37. package/esm/code/CodeBlock.js +1 -1
  38. package/esm/code/CodeBlock.js.map +1 -1
  39. package/esm/confirm/ConfirmButton.js.map +1 -1
  40. package/esm/confirm/ConfirmDialog.js +1 -1
  41. package/esm/confirm/ConfirmDialog.js.map +1 -1
  42. package/esm/confirm/ConfirmMenuItem.js +1 -1
  43. package/esm/confirm/ConfirmMenuItem.js.map +1 -1
  44. package/esm/container/ContainerLayout.d.ts +1 -1
  45. package/esm/container/ContainerLayout.js +5 -5
  46. package/esm/container/ContainerLayout.js.map +1 -1
  47. package/esm/container/ContainerSettingsContext.d.ts +2 -2
  48. package/esm/container/ContainerSettingsContext.js +6 -6
  49. package/esm/container/ContainerSettingsContext.js.map +1 -1
  50. package/esm/container/ContainerWidthControl.js +2 -2
  51. package/esm/container/ContainerWidthControl.js.map +1 -1
  52. package/esm/container/index.d.ts +1 -1
  53. package/esm/container/index.js +1 -1
  54. package/esm/container/index.js.map +1 -1
  55. package/esm/content-table/ContentTable.d.ts +1 -1
  56. package/esm/content-table/ContentTable.js +26 -19
  57. package/esm/content-table/ContentTable.js.map +1 -1
  58. package/esm/content-table/UndrawEmpty.js.map +1 -1
  59. package/esm/content-table/index.js.map +1 -1
  60. package/esm/country/country-select.js.map +1 -1
  61. package/esm/country/index.d.ts +3 -3
  62. package/esm/country/index.js +3 -3
  63. package/esm/country/index.js.map +1 -1
  64. package/esm/country/locale-select.js +1 -1
  65. package/esm/country/locale-select.js.map +1 -1
  66. package/esm/country/locales.js +1 -1
  67. package/esm/country/locales.js.map +1 -1
  68. package/esm/country/phone-prefix-select.js +1 -1
  69. package/esm/country/phone-prefix-select.js.map +1 -1
  70. package/esm/cube/accessibility.js +2 -1
  71. package/esm/cube/accessibility.js.map +1 -1
  72. package/esm/data-table/DataTableColumnSettings.d.ts +1 -1
  73. package/esm/data-table/DataTableColumnSettings.js +2 -2
  74. package/esm/data-table/DataTableColumnSettings.js.map +1 -1
  75. package/esm/data-table/DataTableHeader.js +1 -1
  76. package/esm/data-table/DataTableHeader.js.map +1 -1
  77. package/esm/data-table/DataTableToolbar.js +1 -1
  78. package/esm/data-table/DataTableToolbar.js.map +1 -1
  79. package/esm/data-table/index.d.ts +4 -4
  80. package/esm/data-table/index.js +4 -4
  81. package/esm/data-table/index.js.map +1 -1
  82. package/esm/data-table/useDataTableColumnStorage.d.ts +9 -1
  83. package/esm/data-table/useDataTableColumnStorage.js +12 -5
  84. package/esm/data-table/useDataTableColumnStorage.js.map +1 -1
  85. package/esm/data-table/useDataTableStorage.d.ts +31 -6
  86. package/esm/data-table/useDataTableStorage.js +25 -5
  87. package/esm/data-table/useDataTableStorage.js.map +1 -1
  88. package/esm/date-pickers/PlainAdapterCommon.d.ts +1 -1
  89. package/esm/date-pickers/PlainAdapterCommon.js.map +1 -1
  90. package/esm/date-pickers/PlainDateAdapter.js.map +1 -1
  91. package/esm/date-pickers/PlainDatePicker.js +1 -1
  92. package/esm/date-pickers/PlainDatePicker.js.map +1 -1
  93. package/esm/date-pickers/PlainDatePicker.spec.js +2 -2
  94. package/esm/date-pickers/PlainDatePicker.spec.js.map +1 -1
  95. package/esm/date-pickers/PlainDateTimeAdapter.js.map +1 -1
  96. package/esm/date-pickers/PlainDateTimePicker.js +2 -2
  97. package/esm/date-pickers/PlainDateTimePicker.js.map +1 -1
  98. package/esm/date-pickers/PlainDateTimePicker.spec.js +2 -2
  99. package/esm/date-pickers/PlainDateTimePicker.spec.js.map +1 -1
  100. package/esm/date-pickers/PlainTimeAdapter.js.map +1 -1
  101. package/esm/date-pickers/PlainTimePicker.js +2 -2
  102. package/esm/date-pickers/PlainTimePicker.js.map +1 -1
  103. package/esm/date-pickers/PlainTimePicker.spec.js +2 -2
  104. package/esm/date-pickers/PlainTimePicker.spec.js.map +1 -1
  105. package/esm/date-pickers/TemporalAdapter.d.ts +1 -1
  106. package/esm/date-pickers/TemporalAdapter.js +1 -1
  107. package/esm/date-pickers/TemporalAdapter.js.map +1 -1
  108. package/esm/date-pickers/TimezoneSelect.js +348 -348
  109. package/esm/date-pickers/TimezoneSelect.js.map +1 -1
  110. package/esm/date-pickers/getFormatString.js.map +1 -1
  111. package/esm/date-pickers/index.d.ts +2 -1
  112. package/esm/date-pickers/index.js +1 -1
  113. package/esm/date-pickers/index.js.map +1 -1
  114. package/esm/date-pickers/parse.js.map +1 -1
  115. package/esm/date-pickers/timeframe-picker.js +7 -7
  116. package/esm/date-pickers/timeframe-picker.js.map +1 -1
  117. package/esm/date-pickers/useLocale.js.map +1 -1
  118. package/esm/date-pickers/useRenderInput.js +5 -3
  119. package/esm/date-pickers/useRenderInput.js.map +1 -1
  120. package/esm/formats/CompactFormat.js +1 -1
  121. package/esm/formats/CompactFormat.js.map +1 -1
  122. package/esm/formats/CompactFormat.spec.js +1 -1
  123. package/esm/formats/CompactFormat.spec.js.map +1 -1
  124. package/esm/formats/CurrencyFormat.js +1 -1
  125. package/esm/formats/CurrencyFormat.js.map +1 -1
  126. package/esm/formats/CurrencyFormat.spec.js +1 -1
  127. package/esm/formats/CurrencyFormat.spec.js.map +1 -1
  128. package/esm/formats/DecimalFormat.js +1 -1
  129. package/esm/formats/DecimalFormat.js.map +1 -1
  130. package/esm/formats/DecimalFormat.spec.js +1 -1
  131. package/esm/formats/DecimalFormat.spec.js.map +1 -1
  132. package/esm/formats/DurationFormat.js +2 -2
  133. package/esm/formats/DurationFormat.js.map +1 -1
  134. package/esm/formats/DurationFormat.spec.js +2 -2
  135. package/esm/formats/DurationFormat.spec.js.map +1 -1
  136. package/esm/formats/TemporalFormat.spec.js +2 -2
  137. package/esm/formats/TemporalFormat.spec.js.map +1 -1
  138. package/esm/formats/TemporalRangeFormat.js +1 -1
  139. package/esm/formats/TemporalRangeFormat.js.map +1 -1
  140. package/esm/formats/TemporalRangeFormat.spec.js +2 -2
  141. package/esm/formats/TemporalRangeFormat.spec.js.map +1 -1
  142. package/esm/formats/useDateTimeFormat.js +5 -2
  143. package/esm/formats/useDateTimeFormat.js.map +1 -1
  144. package/esm/formats/useNumberFormat.js +1 -1
  145. package/esm/formats/useNumberFormat.js.map +1 -1
  146. package/esm/formats/useRelativeTimeFormat.js +4 -2
  147. package/esm/formats/useRelativeTimeFormat.js.map +1 -1
  148. package/esm/forms/SearchForm.js +1 -1
  149. package/esm/forms/SearchForm.js.map +1 -1
  150. package/esm/getNavigatorLanguages.js.map +1 -1
  151. package/esm/getSupportedFormatLocale.js.map +1 -1
  152. package/esm/help/HelpDrawer.js +12 -8
  153. package/esm/help/HelpDrawer.js.map +1 -1
  154. package/esm/help/index.d.ts +1 -1
  155. package/esm/help/index.js +1 -1
  156. package/esm/help/index.js.map +1 -1
  157. package/esm/icons.d.ts +13 -13
  158. package/esm/icons.js +13 -13
  159. package/esm/icons.js.map +1 -1
  160. package/esm/layout/ErrorBoundary.js +36 -36
  161. package/esm/layout/ErrorBoundary.js.map +1 -1
  162. package/esm/layout/NotFound.js +6 -6
  163. package/esm/layout/NotFound.js.map +1 -1
  164. package/esm/layout/NotFoundSvg.js.map +1 -1
  165. package/esm/layout/UserNav.js +18 -18
  166. package/esm/layout/UserNav.js.map +1 -1
  167. package/esm/layout/index.d.ts +2 -2
  168. package/esm/layout/index.js +2 -2
  169. package/esm/layout/index.js.map +1 -1
  170. package/esm/logo/Logo.js +2 -2
  171. package/esm/logo/Logo.js.map +1 -1
  172. package/esm/logo/VCAppLogo.js +1 -1
  173. package/esm/logo/VCAppLogo.js.map +1 -1
  174. package/esm/logo/index.d.ts +3 -3
  175. package/esm/logo/index.js +3 -3
  176. package/esm/logo/index.js.map +1 -1
  177. package/esm/splash/index.js +2 -2
  178. package/esm/splash/index.js.map +1 -1
  179. package/esm/storage/MemoryStorage.d.ts +6 -4
  180. package/esm/storage/MemoryStorage.js +13 -4
  181. package/esm/storage/MemoryStorage.js.map +1 -1
  182. package/esm/storage/index.d.ts +2 -1
  183. package/esm/storage/index.js +1 -1
  184. package/esm/storage/index.js.map +1 -1
  185. package/esm/storage/storage.d.ts +6 -4
  186. package/esm/storage/storage.js +35 -15
  187. package/esm/storage/storage.js.map +1 -1
  188. package/esm/storage/types.d.ts +6 -0
  189. package/esm/storage/types.js +2 -0
  190. package/esm/storage/types.js.map +1 -0
  191. package/esm/storage/useStorage.d.ts +10 -1
  192. package/esm/storage/useStorage.js +30 -7
  193. package/esm/storage/useStorage.js.map +1 -1
  194. package/esm/tabs/Tabs.d.ts +2 -2
  195. package/esm/tabs/Tabs.js +15 -15
  196. package/esm/tabs/Tabs.js.map +1 -1
  197. package/esm/tabs/index.js.map +1 -1
  198. package/esm/temporal/index.d.ts +1 -1
  199. package/esm/temporal/index.js +1 -1
  200. package/esm/temporal/index.js.map +1 -1
  201. package/esm/temporal/parse.js.map +1 -1
  202. package/esm/temporal/polyfill.d.ts +1 -1
  203. package/esm/temporal/polyfill.js +3 -3
  204. package/esm/temporal/polyfill.js.map +1 -1
  205. package/esm/utils/defined.js.map +1 -1
  206. package/esm/utils/index.d.ts +1 -1
  207. package/esm/utils/index.js +1 -1
  208. package/esm/utils/index.js.map +1 -1
  209. package/esm/utils/useFlag.js.map +1 -1
  210. package/esm/utils/useIsMounted.js.map +1 -1
  211. package/package.json +8 -9
  212. package/src/AppShell/AppShell.tsx +147 -140
  213. package/src/AppShell/index.tsx +1 -1
  214. package/src/Input/ActionsMenu.tsx +70 -73
  215. package/src/Input/EmailSenderField.tsx +59 -52
  216. package/src/Input/Selector.tsx +15 -15
  217. package/src/LanguageSwitcher/index.ts +1 -1
  218. package/src/Paging/Paging.ts +56 -57
  219. package/src/Paging/index.ts +2 -1
  220. package/src/VCThemeProvider/JetbrainsMonoFont.tsx +52 -42
  221. package/src/VCThemeProvider/RobotoFont.tsx +47 -39
  222. package/src/VCThemeProvider/ThemeModeSwitcher.tsx +17 -17
  223. package/src/VCThemeProvider/VCThemeProvider.tsx +149 -145
  224. package/src/audit/AuditChanges.tsx +18 -12
  225. package/src/audit/AuditTimeline.tsx +16 -17
  226. package/src/audit/AuditTimelineItem.tsx +58 -61
  227. package/src/audit/index.ts +2 -2
  228. package/src/audit/types.ts +27 -28
  229. package/src/breadcrumbs.tsx +11 -15
  230. package/src/code/CodeBlock.tsx +10 -10
  231. package/src/confirm/ConfirmButton.tsx +56 -56
  232. package/src/confirm/ConfirmDialog.tsx +54 -54
  233. package/src/confirm/ConfirmMenuItem.tsx +51 -53
  234. package/src/container/ContainerLayout.tsx +7 -8
  235. package/src/container/ContainerSettingsContext.tsx +49 -46
  236. package/src/container/ContainerWidthControl.tsx +11 -9
  237. package/src/container/index.ts +8 -3
  238. package/src/content-table/ContentTable.tsx +235 -197
  239. package/src/content-table/UndrawEmpty.tsx +281 -281
  240. package/src/content-table/index.ts +1 -1
  241. package/src/country/country-select.tsx +0 -1
  242. package/src/country/index.ts +3 -3
  243. package/src/country/locale-select.tsx +36 -36
  244. package/src/country/locales.ts +185 -187
  245. package/src/country/phone-prefix-select.tsx +4 -5
  246. package/src/cube/accessibility.tsx +2 -1
  247. package/src/data-table/DataTableColumnSettings.tsx +181 -181
  248. package/src/data-table/DataTableHeader.tsx +6 -6
  249. package/src/data-table/DataTableToolbar.tsx +6 -6
  250. package/src/data-table/index.tsx +4 -4
  251. package/src/data-table/useDataTableColumnStorage.ts +30 -19
  252. package/src/data-table/useDataTableStorage.spec.ts +108 -0
  253. package/src/data-table/useDataTableStorage.ts +91 -36
  254. package/src/date-pickers/PlainAdapterCommon.ts +118 -120
  255. package/src/date-pickers/PlainDateAdapter.spec.ts +44 -46
  256. package/src/date-pickers/PlainDateAdapter.ts +130 -132
  257. package/src/date-pickers/PlainDatePicker.spec.tsx +17 -18
  258. package/src/date-pickers/PlainDatePicker.tsx +33 -36
  259. package/src/date-pickers/PlainDateTimeAdapter.spec.ts +44 -46
  260. package/src/date-pickers/PlainDateTimeAdapter.ts +141 -134
  261. package/src/date-pickers/PlainDateTimePicker.spec.tsx +17 -18
  262. package/src/date-pickers/PlainDateTimePicker.tsx +35 -36
  263. package/src/date-pickers/PlainTimeAdapter.ts +219 -221
  264. package/src/date-pickers/PlainTimePicker.spec.tsx +17 -18
  265. package/src/date-pickers/PlainTimePicker.tsx +35 -34
  266. package/src/date-pickers/TemporalAdapter.ts +110 -111
  267. package/src/date-pickers/TimezoneSelect.tsx +375 -375
  268. package/src/date-pickers/getFormatString.ts +29 -29
  269. package/src/date-pickers/index.ts +6 -5
  270. package/src/date-pickers/parse.spec.ts +37 -40
  271. package/src/date-pickers/parse.ts +44 -47
  272. package/src/date-pickers/timeframe-picker.tsx +16 -17
  273. package/src/date-pickers/useLocale.ts +1 -1
  274. package/src/date-pickers/useRenderInput.tsx +24 -15
  275. package/src/formats/CompactFormat.spec.tsx +18 -20
  276. package/src/formats/CompactFormat.tsx +30 -30
  277. package/src/formats/CurrencyFormat.spec.tsx +18 -20
  278. package/src/formats/CurrencyFormat.tsx +52 -52
  279. package/src/formats/DecimalFormat.spec.tsx +18 -20
  280. package/src/formats/DecimalFormat.tsx +47 -47
  281. package/src/formats/DurationFormat.spec.tsx +48 -49
  282. package/src/formats/DurationFormat.tsx +51 -51
  283. package/src/formats/TemporalFormat.spec.tsx +93 -95
  284. package/src/formats/TemporalRangeFormat.spec.tsx +143 -144
  285. package/src/formats/TemporalRangeFormat.tsx +54 -54
  286. package/src/formats/types.ts +1 -3
  287. package/src/formats/useDateTimeFormat.ts +5 -2
  288. package/src/formats/useNumberFormat.ts +3 -3
  289. package/src/formats/useRelativeTimeFormat.ts +5 -3
  290. package/src/forms/SearchForm.tsx +37 -38
  291. package/src/getNavigatorLanguages.ts +4 -5
  292. package/src/getSupportedFormatLocale.ts +10 -10
  293. package/src/help/HelpDrawer.tsx +76 -55
  294. package/src/help/index.ts +3 -3
  295. package/src/icons.ts +21 -21
  296. package/src/layout/ErrorBoundary.tsx +226 -215
  297. package/src/layout/NotFound.tsx +36 -39
  298. package/src/layout/NotFoundSvg.tsx +193 -169
  299. package/src/layout/UserNav.tsx +98 -98
  300. package/src/layout/index.ts +3 -3
  301. package/src/logo/Logo.tsx +6 -7
  302. package/src/logo/VCAppLogo.tsx +22 -20
  303. package/src/logo/index.tsx +3 -3
  304. package/src/splash/index.tsx +25 -25
  305. package/src/storage/MemoryStorage.ts +22 -15
  306. package/src/storage/index.ts +2 -1
  307. package/src/storage/storage.spec.ts +184 -0
  308. package/src/storage/storage.ts +37 -15
  309. package/src/storage/types.ts +6 -0
  310. package/src/storage/useStorage.ts +32 -7
  311. package/src/tabs/Tabs.tsx +172 -170
  312. package/src/tabs/index.ts +1 -1
  313. package/src/temporal/index.ts +1 -1
  314. package/src/temporal/parse.ts +1 -2
  315. package/src/temporal/polyfill.ts +11 -11
  316. package/src/utils/defined.ts +2 -3
  317. package/src/utils/index.ts +1 -1
  318. package/src/utils/useFlag.ts +5 -5
  319. package/src/utils/useIsMounted.ts +9 -9
@@ -1,204 +1,204 @@
1
- import {DataTableColumn} from "./DataTable";
2
- import React, {Fragment, useState} from "react";
3
1
  import {
4
- Avatar,
5
- Dialog,
6
- DialogActions,
7
- DialogTitle,
8
- IconButton,
9
- List,
10
- ListItemAvatar,
11
- ListItemButton,
12
- ListItemText,
13
- ListSubheader,
14
- Menu,
15
- Stack,
2
+ Avatar,
3
+ Dialog,
4
+ DialogActions,
5
+ DialogTitle,
6
+ IconButton,
7
+ List,
8
+ ListItemAvatar,
9
+ ListItemButton,
10
+ ListItemText,
11
+ ListSubheader,
12
+ Menu,
13
+ Stack,
16
14
  } from "@mui/material";
15
+ import React, {Fragment, useState} from "react";
17
16
  import {AddCircleIcon, CloseIcon, MoveDownCircleIcon, MoveUpCircleIcon, RemoveCircleIcon, TuningIcon} from "../icons";
18
- import {useFlag} from "../utils";
19
17
  import {Labels} from "../localization";
18
+ import {useFlag} from "../utils";
19
+ import {DataTableColumn} from "./DataTable";
20
20
 
21
21
  export interface DataTableColumnButtonProps<T> {
22
- columns: ReadonlyArray<DataTableColumn<T>>;
23
- selected: ReadonlyArray<DataTableColumn<T>>;
24
- onChange: (selected: ReadonlyArray<DataTableColumn<T>>) => any;
25
- labels: Labels<"title" | "close" | "add" | "remove" | "moveUp" | "moveDown">;
22
+ columns: ReadonlyArray<DataTableColumn<T>>;
23
+ selected: ReadonlyArray<DataTableColumn<T>>;
24
+ onChange: (selected: ReadonlyArray<DataTableColumn<T>>) => any;
25
+ labels: Labels<"title" | "close" | "add" | "remove" | "moveUp" | "moveDown">;
26
26
  }
27
27
 
28
28
  function groupColumns<T>(available: ReadonlyArray<DataTableColumn<T>>) {
29
- const groups: Record<string, Array<DataTableColumn<T>>> = {};
30
- const other: Array<DataTableColumn<T>> = [];
31
- for (const column of available) {
32
- const group = column.group;
33
- if (group) {
34
- if (!groups[group]) {
35
- groups[group] = [column]
36
- } else {
37
- groups[group].push(column);
38
- }
39
- } else {
40
- other.push(column);
41
- }
42
- }
43
- return {groups, other};
29
+ const groups: Record<string, Array<DataTableColumn<T>>> = {};
30
+ const other: Array<DataTableColumn<T>> = [];
31
+ for (const column of available) {
32
+ const group = column.group;
33
+ if (group) {
34
+ if (!groups[group]) {
35
+ groups[group] = [column];
36
+ } else {
37
+ groups[group].push(column);
38
+ }
39
+ } else {
40
+ other.push(column);
41
+ }
42
+ }
43
+ return {groups, other};
44
44
  }
45
45
 
46
46
  export function DataTableColumnSettings<T>(props: DataTableColumnButtonProps<T>) {
47
- const {
48
- columns,
49
- selected,
50
- onChange,
51
- labels,
52
- } = props;
47
+ const {
48
+ columns,
49
+ selected,
50
+ onChange,
51
+ labels,
52
+ } = props;
53
53
 
54
- const [open, setOpen, clearOpen] = useFlag(false);
55
- const [focus, setFocus] = useState<string>();
56
- const [addMenu, setAddMenu, clearAddMenu] = useFlag(false);
57
- const [addAnchor, setAddAnchor] = useState<HTMLElement | null>(null);
54
+ const [open, setOpen, clearOpen] = useFlag(false);
55
+ const [focus, setFocus] = useState<string>();
56
+ const [addMenu, setAddMenu, clearAddMenu] = useFlag(false);
57
+ const [addAnchor, setAddAnchor] = useState<HTMLElement | null>(null);
58
58
 
59
- const available = columns.filter(column => !selected.find(s => s.field == column.field));
60
- const {groups, other} = groupColumns(available);
59
+ const available = columns.filter(column => !selected.find(s => s.field == column.field));
60
+ const {groups, other} = groupColumns(available);
61
61
 
62
- function move(sourceIndex: number, targetIndex: number) {
63
- const newSelected = [...selected];
64
- const temp = newSelected[targetIndex];
65
- newSelected[targetIndex] = newSelected[sourceIndex];
66
- newSelected[sourceIndex] = temp;
67
- onChange(newSelected);
68
- }
62
+ function move(sourceIndex: number, targetIndex: number) {
63
+ const newSelected = [...selected];
64
+ const temp = newSelected[targetIndex];
65
+ newSelected[targetIndex] = newSelected[sourceIndex];
66
+ newSelected[sourceIndex] = temp;
67
+ onChange(newSelected);
68
+ }
69
69
 
70
- function moveUp() {
71
- const index = selected.findIndex(s => s.field == focus);
72
- if (index >= 1) {
73
- move(index, index - 1);
74
- }
75
- }
70
+ function moveUp() {
71
+ const index = selected.findIndex(s => s.field == focus);
72
+ if (index >= 1) {
73
+ move(index, index - 1);
74
+ }
75
+ }
76
76
 
77
- function moveDown() {
78
- const index = selected.findIndex(s => s.field == focus);
79
- if (index >= 0 && index + 1 < selected.length) {
80
- move(index, index + 1);
81
- }
82
- }
77
+ function moveDown() {
78
+ const index = selected.findIndex(s => s.field == focus);
79
+ if (index >= 0 && index + 1 < selected.length) {
80
+ move(index, index + 1);
81
+ }
82
+ }
83
83
 
84
- function remove() {
85
- onChange(selected.filter(c => c.field != focus));
86
- setFocus(undefined);
87
- }
84
+ function remove() {
85
+ onChange(selected.filter(c => c.field != focus));
86
+ setFocus(undefined);
87
+ }
88
88
 
89
- function add(column: DataTableColumn<T>) {
90
- onChange([...selected, column]);
91
- clearAddMenu();
92
- }
89
+ function add(column: DataTableColumn<T>) {
90
+ onChange([...selected, column]);
91
+ clearAddMenu();
92
+ }
93
93
 
94
- function changeFocus(column: DataTableColumn<T>) {
95
- setFocus(focus != column.field ? column.field : undefined)
96
- }
94
+ function changeFocus(column: DataTableColumn<T>) {
95
+ setFocus(focus != column.field ? column.field : undefined);
96
+ }
97
97
 
98
- function renderSelectListItems(columns: ReadonlyArray<DataTableColumn<T>>) {
99
- return columns.map(column => (
100
- <ListItemButton key={column.field} onClick={() => add(column)}>
101
- <ListItemText primary={column.label}/>
102
- </ListItemButton>
103
- ));
104
- }
98
+ function renderSelectListItems(columns: ReadonlyArray<DataTableColumn<T>>) {
99
+ return columns.map(column => (
100
+ <ListItemButton key={column.field} onClick={() => add(column)}>
101
+ <ListItemText primary={column.label} />
102
+ </ListItemButton>
103
+ ));
104
+ }
105
105
 
106
- return (
107
- <Fragment>
108
- <IconButton onClick={setOpen} title={labels("title")}>
109
- <TuningIcon/>
110
- </IconButton>
111
- <Dialog open={open} onClose={clearOpen} fullWidth maxWidth="xs">
112
- <DialogTitle>
113
- {labels("title")}
114
- </DialogTitle>
115
- <IconButton
116
- aria-label={labels("close")}
117
- title={labels("close")}
118
- onClick={clearOpen}
119
- sx={{
120
- position: 'absolute',
121
- right: 8,
122
- top: 8,
123
- }}
124
- >
125
- <CloseIcon/>
126
- </IconButton>
127
- <List sx={{flex: 1, overflowY: "scroll"}}>
128
- {selected.map((column, index) => (
129
- <ListItemButton
130
- key={column.field}
131
- onClick={() => changeFocus(column)}
132
- selected={focus == column.field}
133
- >
134
- <ListItemAvatar>
135
- <Avatar>{index + 1}</Avatar>
136
- </ListItemAvatar>
137
- <ListItemText
138
- primary={column.label}
139
- secondary={column.group}
140
- />
141
- </ListItemButton>
142
- ))}
143
- </List>
144
- <DialogActions>
145
- <Stack spacing={2} direction="row" justifyContent="space-between" flex={1}>
146
- <IconButton
147
- onClick={setAddMenu}
148
- ref={setAddAnchor}
149
- disabled={available.length == 0}
150
- color="primary"
151
- title={labels("add")}
152
- size="large"
153
- >
154
- <AddCircleIcon fontSize="large"/>
155
- </IconButton>
156
- <Stack spacing={2} direction="row" justifyContent="center">
157
- <IconButton
158
- onClick={moveUp}
159
- disabled={!focus}
160
- color="secondary"
161
- title={labels("moveUp")}
162
- size="large"
163
- >
164
- <MoveUpCircleIcon fontSize="large"/>
165
- </IconButton>
166
- <IconButton
167
- onClick={moveDown}
168
- disabled={!focus}
169
- color="secondary"
170
- title={labels("moveDown")}
171
- size="large"
172
- >
173
- <MoveDownCircleIcon fontSize="large"/>
174
- </IconButton>
175
- </Stack>
176
- <IconButton
177
- onClick={remove}
178
- disabled={!focus}
179
- color="error"
180
- title={labels("remove")}
181
- size="large"
182
- >
183
- <RemoveCircleIcon fontSize="large"/>
184
- </IconButton>
185
- </Stack>
186
- </DialogActions>
106
+ return (
107
+ <Fragment>
108
+ <IconButton onClick={setOpen} title={labels("title")}>
109
+ <TuningIcon />
110
+ </IconButton>
111
+ <Dialog open={open} onClose={clearOpen} fullWidth maxWidth="xs">
112
+ <DialogTitle>
113
+ {labels("title")}
114
+ </DialogTitle>
115
+ <IconButton
116
+ aria-label={labels("close")}
117
+ title={labels("close")}
118
+ onClick={clearOpen}
119
+ sx={{
120
+ position: "absolute",
121
+ right: 8,
122
+ top: 8,
123
+ }}
124
+ >
125
+ <CloseIcon />
126
+ </IconButton>
127
+ <List sx={{flex: 1, overflowY: "scroll"}}>
128
+ {selected.map((column, index) => (
129
+ <ListItemButton
130
+ key={column.field}
131
+ onClick={() => changeFocus(column)}
132
+ selected={focus == column.field}
133
+ >
134
+ <ListItemAvatar>
135
+ <Avatar>{index + 1}</Avatar>
136
+ </ListItemAvatar>
137
+ <ListItemText
138
+ primary={column.label}
139
+ secondary={column.group}
140
+ />
141
+ </ListItemButton>
142
+ ))}
143
+ </List>
144
+ <DialogActions>
145
+ <Stack spacing={2} direction="row" justifyContent="space-between" flex={1}>
146
+ <IconButton
147
+ onClick={setAddMenu}
148
+ ref={setAddAnchor}
149
+ disabled={available.length == 0}
150
+ color="primary"
151
+ title={labels("add")}
152
+ size="large"
153
+ >
154
+ <AddCircleIcon fontSize="large" />
155
+ </IconButton>
156
+ <Stack spacing={2} direction="row" justifyContent="center">
157
+ <IconButton
158
+ onClick={moveUp}
159
+ disabled={!focus}
160
+ color="secondary"
161
+ title={labels("moveUp")}
162
+ size="large"
163
+ >
164
+ <MoveUpCircleIcon fontSize="large" />
165
+ </IconButton>
166
+ <IconButton
167
+ onClick={moveDown}
168
+ disabled={!focus}
169
+ color="secondary"
170
+ title={labels("moveDown")}
171
+ size="large"
172
+ >
173
+ <MoveDownCircleIcon fontSize="large" />
174
+ </IconButton>
175
+ </Stack>
176
+ <IconButton
177
+ onClick={remove}
178
+ disabled={!focus}
179
+ color="error"
180
+ title={labels("remove")}
181
+ size="large"
182
+ >
183
+ <RemoveCircleIcon fontSize="large" />
184
+ </IconButton>
185
+ </Stack>
186
+ </DialogActions>
187
187
 
188
- <Menu
189
- open={addMenu}
190
- anchorEl={addAnchor}
191
- onClose={clearAddMenu}
192
- >
193
- {Object.entries(groups).map(([group, columns]) => (
194
- <Fragment>
195
- <ListSubheader>{group}</ListSubheader>
196
- {renderSelectListItems(columns)}
197
- </Fragment>
198
- ))}
199
- {renderSelectListItems(other)}
200
- </Menu>
201
- </Dialog>
202
- </Fragment>
203
- )
204
- }
188
+ <Menu
189
+ open={addMenu}
190
+ anchorEl={addAnchor}
191
+ onClose={clearAddMenu}
192
+ >
193
+ {Object.entries(groups).map(([group, columns]) => (
194
+ <Fragment>
195
+ <ListSubheader>{group}</ListSubheader>
196
+ {renderSelectListItems(columns)}
197
+ </Fragment>
198
+ ))}
199
+ {renderSelectListItems(other)}
200
+ </Menu>
201
+ </Dialog>
202
+ </Fragment>
203
+ );
204
+ }
@@ -1,10 +1,10 @@
1
- import React, {PropsWithChildren} from "react";
2
1
  import {Box} from "@mui/material";
2
+ import React, {PropsWithChildren} from "react";
3
3
 
4
4
  export function DataTableHeader({children}: PropsWithChildren<{}>) {
5
- return (
6
- <Box p={2} display="flex" alignItems="center">
7
- {children}
8
- </Box>
9
- )
5
+ return (
6
+ <Box p={2} display="flex" alignItems="center">
7
+ {children}
8
+ </Box>
9
+ );
10
10
  }
@@ -1,10 +1,10 @@
1
- import React, {PropsWithChildren} from "react";
2
1
  import {Stack} from "@mui/material";
2
+ import React, {PropsWithChildren} from "react";
3
3
 
4
4
  export function DataTableToolbar({children}: PropsWithChildren<{}>) {
5
- return (
6
- <Stack spacing={1} pl={1} minHeight="52px" direction="row" alignItems="center">
7
- {children}
8
- </Stack>
9
- )
5
+ return (
6
+ <Stack spacing={1} pl={1} minHeight="52px" direction="row" alignItems="center">
7
+ {children}
8
+ </Stack>
9
+ );
10
10
  }
@@ -1,8 +1,8 @@
1
1
  export * from "./DataTable";
2
- export * from "./useDataTableStorage";
3
- export * from "./useDataTableColumnStorage";
4
- export * from "./useSpringPageable";
5
- export * from "./useSpringPage";
6
2
  export * from "./DataTableColumnSettings";
7
3
  export * from "./DataTableHeader";
8
4
  export * from "./DataTableToolbar";
5
+ export * from "./useDataTableColumnStorage";
6
+ export * from "./useDataTableStorage";
7
+ export * from "./useSpringPage";
8
+ export * from "./useSpringPageable";
@@ -1,26 +1,37 @@
1
- import {useStorage} from "../storage";
2
1
  import {useCallback, useMemo} from "react";
3
- import {DataTableColumn} from "./DataTable";
2
+ import {StorageType, useStorage} from "../storage";
4
3
  import {defined} from "../utils";
4
+ import {DataTableColumn} from "./DataTable";
5
5
 
6
- export function useDataTableColumnStorage<T>(key: string, availableColumns: ReadonlyArray<DataTableColumn<T>>) {
7
-
8
- const defaultColumns = useMemo(() => availableColumns
9
- .filter(c => c.default)
10
- .map(c => c.field), [availableColumns]);
6
+ /**
7
+ * Hook for persisting DataTable column visibility to browser storage.
8
+ *
9
+ * @param key - Unique storage key for column settings
10
+ * @param availableColumns - All available columns for this DataTable
11
+ * @param storageType - Optional storage type ('local' or 'session'). Defaults to 'local'.
12
+ */
13
+ export function useDataTableColumnStorage<T>(
14
+ key: string,
15
+ availableColumns: ReadonlyArray<DataTableColumn<T>>,
16
+ storageType?: StorageType,
17
+ ) {
18
+ const defaultColumns = useMemo(() =>
19
+ availableColumns
20
+ .filter(c => c.default)
21
+ .map(c => c.field), [availableColumns]);
11
22
 
12
- const [storage, setStorage] = useStorage(key, defaultColumns);
23
+ const [storage, setStorage] = useStorage(key, defaultColumns, storageType);
13
24
 
14
- const columns = storage
15
- .map(c => availableColumns.find(a => a.field == c))
16
- .filter(defined);
25
+ const columns = storage
26
+ .map(c => availableColumns.find(a => a.field == c))
27
+ .filter(defined);
17
28
 
18
- const setColumns = useCallback((columns: ReadonlyArray<DataTableColumn<T>>) => {
19
- setStorage(columns.map(c => c.field));
20
- }, []);
29
+ const setColumns = useCallback((columns: ReadonlyArray<DataTableColumn<T>>) => {
30
+ setStorage(columns.map(c => c.field));
31
+ }, [setStorage]);
21
32
 
22
- return {
23
- columns,
24
- setColumns
25
- }
26
- }
33
+ return {
34
+ columns,
35
+ setColumns,
36
+ };
37
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+
5
+ import {DataTableStorage, DataTableStorageOptions} from "./useDataTableStorage";
6
+
7
+ // Test the type guard function logic
8
+ function isDataTableStorageOptions(value: unknown): value is DataTableStorageOptions {
9
+ return typeof value === "object" && value !== null && ("defaults" in value || "storageType" in value);
10
+ }
11
+
12
+ describe("useDataTableStorage parameter parsing", () => {
13
+ describe("isDataTableStorageOptions type guard", () => {
14
+ test("returns false for undefined", () => {
15
+ expect(isDataTableStorageOptions(undefined)).toBe(false);
16
+ });
17
+
18
+ test("returns false for null", () => {
19
+ expect(isDataTableStorageOptions(null)).toBe(false);
20
+ });
21
+
22
+ test("returns false for string (StorageType)", () => {
23
+ expect(isDataTableStorageOptions("local")).toBe(false);
24
+ expect(isDataTableStorageOptions("session")).toBe(false);
25
+ });
26
+
27
+ test("returns false for DataTableStorage (backwards compat object)", () => {
28
+ const defaults: DataTableStorage = {pageSize: 25, pageIndex: 0};
29
+ expect(isDataTableStorageOptions(defaults)).toBe(false);
30
+ });
31
+
32
+ test("returns true for object with defaults property", () => {
33
+ const options: DataTableStorageOptions = {defaults: {pageSize: 25}};
34
+ expect(isDataTableStorageOptions(options)).toBe(true);
35
+ });
36
+
37
+ test("returns true for object with storageType property", () => {
38
+ const options: DataTableStorageOptions = {storageType: "session"};
39
+ expect(isDataTableStorageOptions(options)).toBe(true);
40
+ });
41
+
42
+ test("returns true for object with both defaults and storageType", () => {
43
+ const options: DataTableStorageOptions = {
44
+ defaults: {pageSize: 25},
45
+ storageType: "session",
46
+ };
47
+ expect(isDataTableStorageOptions(options)).toBe(true);
48
+ });
49
+ });
50
+
51
+ describe("parameter normalization logic", () => {
52
+ // Test the normalization logic that's used in useDataTableStorage
53
+ function normalizeParams(optionsOrDefaultsOrType?: string | DataTableStorage | DataTableStorageOptions) {
54
+ let defaults: DataTableStorage = {};
55
+ let storageType: string | undefined;
56
+
57
+ if (typeof optionsOrDefaultsOrType === "string") {
58
+ storageType = optionsOrDefaultsOrType;
59
+ } else if (isDataTableStorageOptions(optionsOrDefaultsOrType)) {
60
+ defaults = optionsOrDefaultsOrType.defaults ?? {};
61
+ storageType = optionsOrDefaultsOrType.storageType;
62
+ } else if (optionsOrDefaultsOrType) {
63
+ defaults = optionsOrDefaultsOrType;
64
+ }
65
+
66
+ return {defaults, storageType};
67
+ }
68
+
69
+ test("no second parameter returns empty defaults and undefined storageType", () => {
70
+ const result = normalizeParams();
71
+ expect(result.defaults).toEqual({});
72
+ expect(result.storageType).toBeUndefined();
73
+ });
74
+
75
+ test("string parameter is treated as storageType", () => {
76
+ const result = normalizeParams("session");
77
+ expect(result.defaults).toEqual({});
78
+ expect(result.storageType).toBe("session");
79
+ });
80
+
81
+ test("DataTableStorage object is treated as defaults (backwards compat)", () => {
82
+ const result = normalizeParams({pageSize: 25, sortField: "name"});
83
+ expect(result.defaults).toEqual({pageSize: 25, sortField: "name"});
84
+ expect(result.storageType).toBeUndefined();
85
+ });
86
+
87
+ test("DataTableStorageOptions with defaults only", () => {
88
+ const result = normalizeParams({defaults: {pageSize: 50}});
89
+ expect(result.defaults).toEqual({pageSize: 50});
90
+ expect(result.storageType).toBeUndefined();
91
+ });
92
+
93
+ test("DataTableStorageOptions with storageType only", () => {
94
+ const result = normalizeParams({storageType: "session"});
95
+ expect(result.defaults).toEqual({});
96
+ expect(result.storageType).toBe("session");
97
+ });
98
+
99
+ test("DataTableStorageOptions with both defaults and storageType", () => {
100
+ const result = normalizeParams({
101
+ defaults: {pageSize: 100, sortDirection: "desc"},
102
+ storageType: "local",
103
+ });
104
+ expect(result.defaults).toEqual({pageSize: 100, sortDirection: "desc"});
105
+ expect(result.storageType).toBe("local");
106
+ });
107
+ });
108
+ });