@addev-be/ui 2.5.17 → 2.6.0

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 (286) hide show
  1. package/assets/icons/arrow-down-1-9.svg +1 -1
  2. package/assets/icons/arrow-down-a-z.svg +1 -1
  3. package/assets/icons/arrow-up-z-a.svg +1 -1
  4. package/assets/icons/check.svg +1 -1
  5. package/assets/icons/circle-check.svg +1 -1
  6. package/assets/icons/down.svg +1 -1
  7. package/assets/icons/filter-full.svg +1 -1
  8. package/assets/icons/filter.svg +1 -1
  9. package/assets/icons/hashtag.svg +1 -1
  10. package/assets/icons/image-slash.svg +1 -1
  11. package/assets/icons/left.svg +1 -1
  12. package/assets/icons/magnifier.svg +1 -1
  13. package/assets/icons/phone.svg +1 -1
  14. package/assets/icons/right.svg +1 -1
  15. package/assets/icons/sort-calendar-ascending.svg +5 -5
  16. package/assets/icons/spinner-third.svg +1 -1
  17. package/assets/icons/table-columns.svg +1 -1
  18. package/assets/icons/table-footer-slash.svg +4 -4
  19. package/assets/icons/table-footer.svg +3 -3
  20. package/assets/icons/table.svg +1 -1
  21. package/assets/icons/up.svg +1 -1
  22. package/assets/icons/user-tie.svg +1 -1
  23. package/assets/icons/x-bar.svg +3 -3
  24. package/dist/components/data/AdvancedRequestDataGrid/helpers/advancedRequests.d.ts +14 -0
  25. package/dist/components/data/AdvancedRequestDataGrid/helpers/advancedRequests.js +77 -0
  26. package/dist/components/data/AdvancedRequestDataGrid/helpers/columns.d.ts +22 -0
  27. package/dist/components/data/AdvancedRequestDataGrid/helpers/columns.js +105 -0
  28. package/dist/components/data/AdvancedRequestDataGrid/helpers/index.d.ts +2 -0
  29. package/dist/components/data/AdvancedRequestDataGrid/helpers/index.js +18 -0
  30. package/dist/components/data/AdvancedRequestDataGrid/index.d.ts +2 -0
  31. package/dist/components/data/AdvancedRequestDataGrid/index.js +215 -0
  32. package/dist/components/data/AdvancedRequestDataGrid/types.d.ts +21 -0
  33. package/dist/components/data/AdvancedRequestDataGrid/types.js +2 -0
  34. package/dist/components/data/DataGrid/AdvancedRequestDataGrid.d.ts +10 -0
  35. package/dist/components/data/DataGrid/AdvancedRequestDataGrid.js +173 -0
  36. package/dist/components/data/DataGrid/DataGridEditableCell.d.ts +2 -0
  37. package/dist/components/data/DataGrid/DataGridEditableCell.js +27 -0
  38. package/dist/components/data/DataGrid/FilterValuesScroller.d.ts +13 -0
  39. package/dist/components/data/DataGrid/FilterValuesScroller.js +73 -0
  40. package/dist/components/data/DataGrid/VirtualScroller.d.ts +11 -0
  41. package/dist/components/data/DataGrid/VirtualScroller.js +41 -0
  42. package/dist/components/data/DataGrid/helpers/advancedRequests.d.ts +12 -0
  43. package/dist/components/data/DataGrid/helpers/advancedRequests.js +53 -0
  44. package/dist/components/data/DataGrid/helpers.d.ts +28 -0
  45. package/dist/components/data/DataGrid/helpers.js +436 -0
  46. package/dist/components/data/SmartQueryDataGrid/helpers/columns.d.ts +20 -0
  47. package/dist/components/data/SmartQueryDataGrid/helpers/columns.js +160 -0
  48. package/dist/components/data/SmartQueryDataGrid/helpers/hooks.d.ts +5 -0
  49. package/dist/components/data/SmartQueryDataGrid/helpers/hooks.js +41 -0
  50. package/dist/components/data/SmartQueryDataGrid/helpers/index.d.ts +2 -0
  51. package/dist/components/data/SmartQueryDataGrid/helpers/index.js +18 -0
  52. package/dist/components/data/SmartQueryDataGrid/helpers/smartQueries.d.ts +3 -0
  53. package/dist/components/data/SmartQueryDataGrid/helpers/smartQueries.js +15 -0
  54. package/dist/components/data/SmartQueryDataGrid/hooks.d.ts +9 -0
  55. package/dist/components/data/SmartQueryDataGrid/hooks.js +63 -0
  56. package/dist/components/data/SmartQueryDataGrid/index.d.ts +12 -0
  57. package/dist/components/data/SmartQueryDataGrid/index.js +242 -0
  58. package/dist/components/data/SmartQueryDataGrid/types.d.ts +22 -0
  59. package/dist/components/data/SmartQueryDataGrid/types.js +2 -0
  60. package/dist/components/data/SqlRequestDataGrid/SqlRequestForeignListEditableCell.d.ts +2 -1
  61. package/dist/components/data/SqlRequestDataGrid/SqlRequestForeignListEditableCell.js +2 -3
  62. package/dist/components/forms/BillitIdentifier/index.d.ts +6 -0
  63. package/dist/components/forms/BillitIdentifier/index.js +71 -0
  64. package/dist/components/forms/BillitIdentifier/styles.d.ts +2 -0
  65. package/dist/components/forms/BillitIdentifier/styles.js +15 -0
  66. package/dist/components/forms/Form/FormGroup.d.ts +1 -0
  67. package/dist/components/forms/Form/FormGroup.js +2 -2
  68. package/dist/components/forms/Form/InputWithLabel.d.ts +2 -0
  69. package/dist/components/forms/Form/InputWithLabel.js +10 -0
  70. package/dist/components/forms/Form/Row.js +1 -1
  71. package/dist/components/forms/Form/Select.d.ts +3 -1
  72. package/dist/components/forms/Form/Select.js +19 -10
  73. package/dist/components/forms/Form/index.d.ts +4 -1
  74. package/dist/components/forms/Form/styles.d.ts +5 -3
  75. package/dist/components/forms/Form/styles.js +19 -14
  76. package/dist/components/forms/Form/types.d.ts +7 -0
  77. package/dist/components/forms/Form/types.js +2 -0
  78. package/dist/components/forms/styles.js +1 -1
  79. package/dist/components/ui/Card/index.d.ts +2 -1
  80. package/dist/components/ui/Card/styles.d.ts +2 -1
  81. package/dist/components/ui/Card/styles.js +2 -1
  82. package/dist/components/ui/TabsView/TabsList.d.ts +1 -0
  83. package/dist/components/ui/TabsView/TabsList.js +4 -2
  84. package/dist/components/ui/TabsView/TabsView.d.ts +3 -1
  85. package/dist/components/ui/TabsView/TabsView.js +2 -2
  86. package/dist/components/ui/TabsView/styles.js +4 -4
  87. package/dist/config/types.d.ts +11 -0
  88. package/dist/config/types.js +2 -0
  89. package/dist/helpers/react.d.ts +2 -0
  90. package/dist/helpers/react.js +8 -0
  91. package/dist/helpers/styled/index.d.ts +1 -0
  92. package/dist/helpers/styled/index.js +17 -0
  93. package/dist/hooks/useMutableState.d.ts +5 -3
  94. package/dist/hooks/useMutableState.js +9 -2
  95. package/dist/hooks/useMutableState.test.d.ts +4 -0
  96. package/dist/hooks/useMutableState.test.js +320 -0
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.js +1 -0
  99. package/dist/providers/ThemeProvider/defaultTheme.js +1 -0
  100. package/dist/providers/ThemeProvider/helpers.d.ts +1 -1
  101. package/dist/providers/ThemeProvider/index.js +1 -1
  102. package/dist/providers/ThemeProvider/types.d.ts +1 -1
  103. package/dist/services/index.js +17 -7
  104. package/dist/services/requests/userPermissions.d.ts +4 -0
  105. package/dist/services/requests/userPermissions.js +20 -0
  106. package/dist/services/sqlRequests.d.ts +1 -1
  107. package/eslint.config.js +3 -3
  108. package/package.json +11 -4
  109. package/src/Icons.tsx +138 -138
  110. package/src/components/auth/LoginForm.tsx +86 -86
  111. package/src/components/auth/LoginPage.tsx +32 -32
  112. package/src/components/auth/PasswordRecoveryForm.tsx +53 -53
  113. package/src/components/auth/PasswordResetForm.tsx +112 -112
  114. package/src/components/auth/styles.ts +14 -14
  115. package/src/components/data/DataGrid/DataGridCell.tsx +81 -81
  116. package/src/components/data/DataGrid/DataGridColumnsModal/helpers.ts +9 -9
  117. package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +59 -59
  118. package/src/components/data/DataGrid/DataGridColumnsModal/index.tsx +182 -182
  119. package/src/components/data/DataGrid/DataGridColumnsModal/styles.ts +104 -104
  120. package/src/components/data/DataGrid/DataGridEditableCell/CheckboxEditableCell.tsx +37 -37
  121. package/src/components/data/DataGrid/DataGridEditableCell/DateEditableCell.tsx +38 -38
  122. package/src/components/data/DataGrid/DataGridEditableCell/NumberEditableCell.tsx +71 -71
  123. package/src/components/data/DataGrid/DataGridEditableCell/TextEditableCell.tsx +37 -37
  124. package/src/components/data/DataGrid/DataGridEditableCell/index.tsx +106 -106
  125. package/src/components/data/DataGrid/DataGridEditableCell/styles.ts +35 -35
  126. package/src/components/data/DataGrid/DataGridEditableCell/types.ts +18 -18
  127. package/src/components/data/DataGrid/DataGridFilterMenu/FilterValuesScroller.tsx +129 -129
  128. package/src/components/data/DataGrid/DataGridFilterMenu/helpers.ts +23 -23
  129. package/src/components/data/DataGrid/DataGridFilterMenu/hooks.tsx +81 -81
  130. package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +370 -370
  131. package/src/components/data/DataGrid/DataGridFilterMenu/styles.ts +97 -97
  132. package/src/components/data/DataGrid/DataGridFooter.tsx +47 -47
  133. package/src/components/data/DataGrid/DataGridHeader.tsx +74 -74
  134. package/src/components/data/DataGrid/DataGridHeaderCell.tsx +112 -112
  135. package/src/components/data/DataGrid/DataGridRowTemplate.tsx +83 -83
  136. package/src/components/data/DataGrid/DataGridToolbar.tsx +134 -134
  137. package/src/components/data/DataGrid/FilterModalContent/index.tsx +137 -137
  138. package/src/components/data/DataGrid/FilterModalContent/styles.ts +22 -22
  139. package/src/components/data/DataGrid/constants.ts +6 -6
  140. package/src/components/data/DataGrid/helpers/columns.tsx +449 -449
  141. package/src/components/data/DataGrid/helpers/filters.ts +287 -287
  142. package/src/components/data/DataGrid/helpers/index.ts +2 -2
  143. package/src/components/data/DataGrid/hooks/index.ts +29 -29
  144. package/src/components/data/DataGrid/hooks/useDataGrid.tsx +383 -383
  145. package/src/components/data/DataGrid/hooks/useDataGridChangedRows.ts +97 -97
  146. package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +174 -174
  147. package/src/components/data/DataGrid/hooks/useDataGridSettings.ts +48 -48
  148. package/src/components/data/DataGrid/hooks/useRefreshModal.tsx +48 -48
  149. package/src/components/data/DataGrid/index.tsx +111 -111
  150. package/src/components/data/DataGrid/styles.ts +434 -434
  151. package/src/components/data/DataGrid/types.ts +380 -380
  152. package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +526 -526
  153. package/src/components/data/SqlRequestDataGrid/helpers/index.ts +2 -2
  154. package/src/components/data/SqlRequestDataGrid/helpers/rows.ts +24 -24
  155. package/src/components/data/SqlRequestDataGrid/helpers/sqlRequests.ts +17 -17
  156. package/src/components/data/SqlRequestDataGrid/index.tsx +417 -417
  157. package/src/components/data/SqlRequestDataGrid/styles.ts +15 -15
  158. package/src/components/data/SqlRequestDataGrid/types.ts +74 -74
  159. package/src/components/data/SqlRequestForeignList/index.tsx +254 -254
  160. package/src/components/data/SqlRequestForeignList/styles.ts +43 -43
  161. package/src/components/data/SqlRequestForeignList/types.ts +32 -32
  162. package/src/components/data/SqlRequestGrid/filters/FiltersSidebar.tsx +108 -108
  163. package/src/components/data/SqlRequestGrid/filters/styles.ts +88 -88
  164. package/src/components/data/SqlRequestGrid/helpers/index.ts +1 -1
  165. package/src/components/data/SqlRequestGrid/helpers/sqlRequests.ts +16 -16
  166. package/src/components/data/SqlRequestGrid/index.tsx +304 -304
  167. package/src/components/data/SqlRequestGrid/styles.ts +20 -20
  168. package/src/components/data/SqlRequestGrid/types.ts +73 -73
  169. package/src/components/data/VirtualScroller/hooks.ts +71 -71
  170. package/src/components/data/VirtualScroller/index.tsx +89 -89
  171. package/src/components/data/VirtualScroller/styles.ts +57 -57
  172. package/src/components/data/VirtualScroller/types.ts +10 -10
  173. package/src/components/forms/AutoTextArea.tsx +48 -48
  174. package/src/components/forms/BillitIdentifier/index.tsx +78 -0
  175. package/src/components/forms/BillitIdentifier/styles.tsx +43 -0
  176. package/src/components/forms/Button.tsx +132 -132
  177. package/src/components/forms/Form/Checkbox.tsx +12 -12
  178. package/src/components/forms/Form/CustomSelect.tsx +86 -86
  179. package/src/components/forms/Form/FormGroup.tsx +33 -31
  180. package/src/components/forms/Form/Input.tsx +16 -16
  181. package/src/components/forms/Form/Row.tsx +28 -32
  182. package/src/components/forms/Form/Select.tsx +99 -82
  183. package/src/components/forms/Form/TextArea.tsx +17 -17
  184. package/src/components/forms/Form/index.tsx +48 -48
  185. package/src/components/forms/Form/styles.ts +148 -184
  186. package/src/components/forms/IconButton.tsx +61 -61
  187. package/src/components/forms/IndeterminateCheckbox.tsx +46 -46
  188. package/src/components/forms/NumberInput.tsx +53 -53
  189. package/src/components/forms/Select.tsx +34 -34
  190. package/src/components/forms/VerticalLabel.tsx +20 -20
  191. package/src/components/forms/styles.ts +42 -42
  192. package/src/components/layout/Columns.ts +28 -28
  193. package/src/components/layout/Dropdown/index.tsx +113 -113
  194. package/src/components/layout/Dropdown/styles.ts +53 -53
  195. package/src/components/layout/Flexbox.ts +21 -21
  196. package/src/components/layout/Grid/index.tsx +8 -8
  197. package/src/components/layout/Grid/styles.ts +34 -34
  198. package/src/components/layout/Loading/index.tsx +29 -29
  199. package/src/components/layout/Loading/styles.ts +29 -29
  200. package/src/components/layout/Masonry/index.tsx +29 -29
  201. package/src/components/layout/Masonry/styles.ts +20 -20
  202. package/src/components/layout/Modal/index.tsx +51 -51
  203. package/src/components/layout/Modal/styles.ts +125 -125
  204. package/src/components/search/HighlightedText.tsx +41 -41
  205. package/src/components/search/QuickSearchBar.tsx +102 -102
  206. package/src/components/search/QuickSearchResults.tsx +86 -86
  207. package/src/components/search/styles.ts +96 -96
  208. package/src/components/search/types.ts +29 -29
  209. package/src/components/ui/Avatar/index.tsx +54 -54
  210. package/src/components/ui/Avatar/styles.ts +61 -61
  211. package/src/components/ui/Card/index.tsx +16 -14
  212. package/src/components/ui/Card/styles.ts +41 -37
  213. package/src/components/ui/ContextMenu/index.tsx +79 -79
  214. package/src/components/ui/ContextMenu/styles.ts +119 -119
  215. package/src/components/ui/Ellipsis.tsx +33 -33
  216. package/src/components/ui/Label.tsx +93 -93
  217. package/src/components/ui/Message/index.tsx +57 -57
  218. package/src/components/ui/Message/styles.ts +44 -44
  219. package/src/components/ui/TabsView/TabsList.tsx +49 -44
  220. package/src/components/ui/TabsView/TabsView.tsx +42 -38
  221. package/src/components/ui/TabsView/index.ts +3 -3
  222. package/src/components/ui/TabsView/styles.ts +84 -76
  223. package/src/components/ui/TabsView/types.ts +15 -15
  224. package/src/config/index.ts +10 -10
  225. package/src/helpers/components.ts +9 -9
  226. package/src/helpers/dates.ts +17 -17
  227. package/src/helpers/getScrollbarSize.ts +14 -14
  228. package/src/helpers/numbers.ts +63 -63
  229. package/src/helpers/responsive.ts +83 -83
  230. package/src/helpers/styled/space.ts +114 -114
  231. package/src/helpers/styled/typography.ts +25 -25
  232. package/src/helpers/text.ts +13 -13
  233. package/src/helpers/types.ts +9 -9
  234. package/src/hooks/useContainerMediaQuery.ts +7 -7
  235. package/src/hooks/useElementSize.ts +24 -24
  236. package/src/hooks/useMediaQuery.ts +9 -9
  237. package/src/hooks/useMediaQueryForWidth.ts +35 -35
  238. package/src/hooks/useMutableState.test.ts +410 -0
  239. package/src/hooks/useMutableState.ts +39 -25
  240. package/src/hooks/useShowArchived.ts +28 -28
  241. package/src/hooks/useWindowSize.ts +20 -20
  242. package/src/index.ts +103 -102
  243. package/src/providers/AuthenticationProvider/helpers.ts +3 -3
  244. package/src/providers/AuthenticationProvider/index.tsx +303 -303
  245. package/src/providers/LoadingProvider/index.tsx +47 -47
  246. package/src/providers/PortalsProvider/index.tsx +54 -54
  247. package/src/providers/PortalsProvider/styles.ts +31 -31
  248. package/src/providers/SettingsProvider/index.tsx +70 -70
  249. package/src/providers/ThemeProvider/defaultTheme.ts +471 -470
  250. package/src/providers/ThemeProvider/helpers.ts +84 -84
  251. package/src/providers/ThemeProvider/index.ts +73 -66
  252. package/src/providers/ThemeProvider/types.ts +134 -134
  253. package/src/providers/ToastProvider/index.tsx +93 -93
  254. package/src/providers/TrackingProvider/hooks.ts +14 -14
  255. package/src/providers/TrackingProvider/index.tsx +71 -71
  256. package/src/providers/UiProviders/index.tsx +76 -76
  257. package/src/providers/UiProviders/styles.ts +10 -10
  258. package/src/providers/hooks.ts +14 -14
  259. package/src/services/HttpService.ts +92 -92
  260. package/src/services/WebSocketService.ts +155 -155
  261. package/src/services/advancedRequests.ts +102 -102
  262. package/src/services/base.ts +23 -23
  263. package/src/services/globalSearch.ts +32 -32
  264. package/src/services/hooks.ts +92 -92
  265. package/src/services/requests/auth.ts +44 -44
  266. package/src/services/requests/generic.ts +62 -62
  267. package/src/services/requests/printing.ts +12 -12
  268. package/src/services/requests/tracking.ts +12 -12
  269. package/src/services/requests/userProfiles.ts +35 -35
  270. package/src/services/requests/users.ts +28 -28
  271. package/src/services/smartQueries.ts +122 -122
  272. package/src/services/sqlRequests.ts +119 -113
  273. package/src/services/types/auth.ts +98 -98
  274. package/src/services/types/base.ts +10 -10
  275. package/src/services/types/generic.ts +82 -82
  276. package/src/services/types/printing.ts +10 -10
  277. package/src/services/types/tracking.ts +29 -29
  278. package/src/services/types/userProfiles.ts +79 -79
  279. package/src/services/types/users.ts +74 -74
  280. package/src/services/updateSqlRequests.ts +32 -32
  281. package/src/styles/animations.scss +30 -30
  282. package/src/styles/index.scss +42 -42
  283. package/src/types.ts +8 -8
  284. package/src/typings.d.ts +2 -2
  285. package/tsconfig.json +18 -18
  286. package/tsconfig.tsbuildinfo +1 -1
@@ -1,24 +1,24 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- export const useElementSize = (element: HTMLElement | null) => {
4
- const [size, setSize] = useState({ width: 0, height: 0 });
5
-
6
- useEffect(() => {
7
- if (!element) {
8
- return;
9
- }
10
-
11
- const observer = new ResizeObserver((entries) => {
12
- const entry = entries[0];
13
- const { width, height } = entry.contentRect;
14
- setSize({ width, height });
15
- });
16
-
17
- observer.observe(element);
18
- return () => {
19
- observer.disconnect();
20
- };
21
- }, [element]);
22
-
23
- return size;
24
- };
1
+ import { useEffect, useState } from 'react';
2
+
3
+ export const useElementSize = (element: HTMLElement | null) => {
4
+ const [size, setSize] = useState({ width: 0, height: 0 });
5
+
6
+ useEffect(() => {
7
+ if (!element) {
8
+ return;
9
+ }
10
+
11
+ const observer = new ResizeObserver((entries) => {
12
+ const entry = entries[0];
13
+ const { width, height } = entry.contentRect;
14
+ setSize({ width, height });
15
+ });
16
+
17
+ observer.observe(element);
18
+ return () => {
19
+ observer.disconnect();
20
+ };
21
+ }, [element]);
22
+
23
+ return size;
24
+ };
@@ -1,9 +1,9 @@
1
- import { useMediaQueryForWidth } from './useMediaQueryForWidth';
2
- import { useWindowSize } from './useWindowSize';
3
-
4
- export const useMediaQuery = () => {
5
- const { width } = useWindowSize();
6
- const realWidth = width ?? 0;
7
-
8
- return useMediaQueryForWidth(realWidth);
9
- };
1
+ import { useMediaQueryForWidth } from './useMediaQueryForWidth';
2
+ import { useWindowSize } from './useWindowSize';
3
+
4
+ export const useMediaQuery = () => {
5
+ const { width } = useWindowSize();
6
+ const realWidth = width ?? 0;
7
+
8
+ return useMediaQueryForWidth(realWidth);
9
+ };
@@ -1,35 +1,35 @@
1
- import {
2
- findBreakpoint,
3
- isGreaterThanOrEqual,
4
- isSmallerThanOrEqual,
5
- } from '../helpers/responsive';
6
-
7
- import { useMemo } from 'react';
8
-
9
- export const useMediaQueryForWidth = (width: number) => {
10
- const breakpoint = findBreakpoint(width);
11
-
12
- return useMemo(
13
- () => ({
14
- breakpoint,
15
-
16
- isXs: breakpoint === 'xs',
17
- isSm: breakpoint === 'sm',
18
- isMd: breakpoint === 'md',
19
- isLg: breakpoint === 'lg',
20
- isXl: breakpoint === 'xl',
21
- isXxl: breakpoint === 'xxl',
22
-
23
- isSmDown: isSmallerThanOrEqual('sm', breakpoint),
24
- isMdDown: isSmallerThanOrEqual('md', breakpoint),
25
- isLgDown: isSmallerThanOrEqual('lg', breakpoint),
26
- isXlDown: isSmallerThanOrEqual('xl', breakpoint),
27
-
28
- isSmUp: isGreaterThanOrEqual('sm', breakpoint),
29
- isMdUp: isGreaterThanOrEqual('md', breakpoint),
30
- isLgUp: isGreaterThanOrEqual('lg', breakpoint),
31
- isXlUp: isGreaterThanOrEqual('xl', breakpoint),
32
- }),
33
- [breakpoint]
34
- );
35
- };
1
+ import {
2
+ findBreakpoint,
3
+ isGreaterThanOrEqual,
4
+ isSmallerThanOrEqual,
5
+ } from '../helpers/responsive';
6
+
7
+ import { useMemo } from 'react';
8
+
9
+ export const useMediaQueryForWidth = (width: number) => {
10
+ const breakpoint = findBreakpoint(width);
11
+
12
+ return useMemo(
13
+ () => ({
14
+ breakpoint,
15
+
16
+ isXs: breakpoint === 'xs',
17
+ isSm: breakpoint === 'sm',
18
+ isMd: breakpoint === 'md',
19
+ isLg: breakpoint === 'lg',
20
+ isXl: breakpoint === 'xl',
21
+ isXxl: breakpoint === 'xxl',
22
+
23
+ isSmDown: isSmallerThanOrEqual('sm', breakpoint),
24
+ isMdDown: isSmallerThanOrEqual('md', breakpoint),
25
+ isLgDown: isSmallerThanOrEqual('lg', breakpoint),
26
+ isXlDown: isSmallerThanOrEqual('xl', breakpoint),
27
+
28
+ isSmUp: isGreaterThanOrEqual('sm', breakpoint),
29
+ isMdUp: isGreaterThanOrEqual('md', breakpoint),
30
+ isLgUp: isGreaterThanOrEqual('lg', breakpoint),
31
+ isXlUp: isGreaterThanOrEqual('xl', breakpoint),
32
+ }),
33
+ [breakpoint]
34
+ );
35
+ };
@@ -0,0 +1,410 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { act, renderHook } from '@testing-library/react';
6
+ import { describe, expect, it } from 'vitest';
7
+ import { isDispatchFunction, useMutableState } from './useMutableState';
8
+
9
+ describe('isDispatchFunction', () => {
10
+ it('should return true for functions', () => {
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const fn = (state: any) => state;
13
+ expect(isDispatchFunction(fn)).toBe(true);
14
+ });
15
+
16
+ it('should return false for objects', () => {
17
+ expect(isDispatchFunction({ key: 'value' })).toBe(false);
18
+ });
19
+
20
+ it('should return false for primitives', () => {
21
+ expect(isDispatchFunction('string')).toBe(false);
22
+ expect(isDispatchFunction(123)).toBe(false);
23
+ expect(isDispatchFunction(null)).toBe(false);
24
+ expect(isDispatchFunction(undefined)).toBe(false);
25
+ });
26
+ });
27
+
28
+ describe('useMutableState', () => {
29
+ describe('initialization', () => {
30
+ it('should initialize with default value', () => {
31
+ const { result } = renderHook(() =>
32
+ useMutableState({ name: 'John', age: 30 })
33
+ );
34
+ const [state] = result.current;
35
+
36
+ expect(state).toEqual({ name: 'John', age: 30 });
37
+ });
38
+
39
+ it('should initialize with empty object when no value is provided', () => {
40
+ const { result } = renderHook(() => useMutableState());
41
+ const [state] = result.current;
42
+
43
+ expect(state).toEqual({});
44
+ });
45
+
46
+ it('should initialize with function result', () => {
47
+ const { result } = renderHook(() =>
48
+ useMutableState(() => ({ count: 0, items: [] }))
49
+ );
50
+ const [state] = result.current;
51
+
52
+ expect(state).toEqual({ count: 0, items: [] });
53
+ });
54
+
55
+ it('should return tuple with three elements', () => {
56
+ const { result } = renderHook(() => useMutableState({ value: 1 }));
57
+
58
+ expect(result.current).toHaveLength(3);
59
+ expect(typeof result.current[0]).toBe('object');
60
+ expect(typeof result.current[1]).toBe('function');
61
+ expect(typeof result.current[2]).toBe('function');
62
+ });
63
+ });
64
+
65
+ describe('setValue (full state update)', () => {
66
+ it('should update entire state with new value', () => {
67
+ const { result } = renderHook(() =>
68
+ useMutableState({ name: 'John', age: 30 })
69
+ );
70
+
71
+ act(() => {
72
+ const [, setValue] = result.current;
73
+ setValue({ name: 'Jane', age: 25 });
74
+ });
75
+
76
+ expect(result.current[0]).toEqual({ name: 'Jane', age: 25 });
77
+ });
78
+
79
+ it('should update state using function', () => {
80
+ const { result } = renderHook(() => useMutableState({ count: 0 }));
81
+
82
+ act(() => {
83
+ const [, setValue] = result.current;
84
+ setValue((prev) => ({ count: prev.count + 1 }));
85
+ });
86
+
87
+ expect(result.current[0]).toEqual({ count: 1 });
88
+ });
89
+
90
+ it('should replace entire state object', () => {
91
+ const { result } = renderHook(() =>
92
+ useMutableState({ name: 'John', age: 30, city: 'Paris' })
93
+ );
94
+
95
+ act(() => {
96
+ const [, setValue] = result.current;
97
+ setValue({ name: 'Jane', age: 22, city: 'London' });
98
+ });
99
+
100
+ expect(result.current[0]).toEqual({
101
+ name: 'Jane',
102
+ age: 22,
103
+ city: 'London',
104
+ });
105
+ });
106
+ });
107
+
108
+ describe('setPartialValue (partial state update)', () => {
109
+ it('should merge partial object with existing state', () => {
110
+ const { result } = renderHook(() =>
111
+ useMutableState({ name: 'John', age: 30, city: 'Paris' })
112
+ );
113
+
114
+ act(() => {
115
+ const [, , setPartialValue] = result.current;
116
+ setPartialValue({ age: 31 });
117
+ });
118
+
119
+ expect(result.current[0]).toEqual({
120
+ name: 'John',
121
+ age: 31,
122
+ city: 'Paris',
123
+ });
124
+ });
125
+
126
+ it('should merge partial object using function', () => {
127
+ const { result } = renderHook(() =>
128
+ useMutableState({ count: 0, total: 100 })
129
+ );
130
+
131
+ act(() => {
132
+ const [, , setPartialValue] = result.current;
133
+ setPartialValue((state) => ({ count: state.count + 5 }));
134
+ });
135
+
136
+ expect(result.current[0]).toEqual({ count: 5, total: 100 });
137
+ });
138
+
139
+ it('should handle deep nested objects', () => {
140
+ const { result } = renderHook(() =>
141
+ useMutableState({
142
+ user: {
143
+ name: 'John',
144
+ address: {
145
+ city: 'Paris',
146
+ country: 'France',
147
+ },
148
+ },
149
+ settings: {
150
+ theme: 'dark',
151
+ },
152
+ })
153
+ );
154
+
155
+ act(() => {
156
+ const [, , setPartialValue] = result.current;
157
+ setPartialValue({
158
+ user: {
159
+ address: {
160
+ city: 'Lyon',
161
+ },
162
+ },
163
+ });
164
+ });
165
+
166
+ expect(result.current[0]).toEqual({
167
+ user: {
168
+ name: 'John',
169
+ address: {
170
+ city: 'Lyon',
171
+ country: 'France',
172
+ },
173
+ },
174
+ settings: {
175
+ theme: 'dark',
176
+ },
177
+ });
178
+ });
179
+
180
+ it('should add new properties to state', () => {
181
+ const { result } = renderHook(() =>
182
+ useMutableState<{ name: string; age?: number }>({ name: 'John' })
183
+ );
184
+
185
+ act(() => {
186
+ const [, , setPartialValue] = result.current;
187
+ setPartialValue({ age: 30 });
188
+ });
189
+
190
+ expect(result.current[0]).toEqual({ name: 'John', age: 30 });
191
+ });
192
+
193
+ it('should handle multiple consecutive updates', () => {
194
+ const { result } = renderHook(() =>
195
+ useMutableState({ count: 0, value: 10 })
196
+ );
197
+
198
+ act(() => {
199
+ const [, , setPartialValue] = result.current;
200
+ setPartialValue({ count: 1 });
201
+ setPartialValue({ value: 20 });
202
+ setPartialValue({ count: 2 });
203
+ });
204
+
205
+ expect(result.current[0]).toEqual({ count: 2, value: 20 });
206
+ });
207
+
208
+ it('should handle empty partial object', () => {
209
+ const { result } = renderHook(() =>
210
+ useMutableState({ name: 'John', age: 30 })
211
+ );
212
+
213
+ act(() => {
214
+ const [, , setPartialValue] = result.current;
215
+ setPartialValue({});
216
+ });
217
+
218
+ expect(result.current[0]).toEqual({ name: 'John', age: 30 });
219
+ });
220
+
221
+ it('should preserve arrays correctly', () => {
222
+ const { result } = renderHook(() =>
223
+ useMutableState({ items: [1, 2, 3], count: 0 })
224
+ );
225
+
226
+ act(() => {
227
+ const [, , setPartialValue] = result.current;
228
+ setPartialValue({ count: 5 });
229
+ });
230
+
231
+ expect(result.current[0]).toEqual({ items: [1, 2, 3], count: 5 });
232
+ });
233
+
234
+ it('should update arrays when provided', () => {
235
+ const { result } = renderHook(() =>
236
+ useMutableState({ items: [1, 2, 3], count: 0 })
237
+ );
238
+
239
+ act(() => {
240
+ const [, , setPartialValue] = result.current;
241
+ setPartialValue({ items: [4, 5, 6] });
242
+ });
243
+
244
+ expect(result.current[0]).toEqual({ items: [4, 5, 6], count: 0 });
245
+ });
246
+ });
247
+
248
+ describe('referential stability', () => {
249
+ it('should maintain stable setPartialValue reference', () => {
250
+ const { result, rerender } = renderHook(() =>
251
+ useMutableState({ count: 0 })
252
+ );
253
+
254
+ const [, , firstSetPartial] = result.current;
255
+
256
+ act(() => {
257
+ const [, setValue] = result.current;
258
+ setValue({ count: 1 });
259
+ });
260
+
261
+ rerender();
262
+
263
+ const [, , secondSetPartial] = result.current;
264
+
265
+ expect(firstSetPartial).toBe(secondSetPartial);
266
+ });
267
+
268
+ it('should trigger new reference when state changes', () => {
269
+ const { result, rerender } = renderHook(() =>
270
+ useMutableState({ count: 0 })
271
+ );
272
+
273
+ const [firstState] = result.current;
274
+
275
+ act(() => {
276
+ const [, , setPartialValue] = result.current;
277
+ setPartialValue({ count: 1 });
278
+ });
279
+
280
+ rerender();
281
+
282
+ const [secondState] = result.current;
283
+
284
+ expect(firstState).not.toBe(secondState);
285
+ });
286
+ });
287
+
288
+ describe('complex types', () => {
289
+ interface ComplexState {
290
+ id: number;
291
+ user: {
292
+ name: string;
293
+ email: string;
294
+ preferences: {
295
+ notifications: boolean;
296
+ theme: 'light' | 'dark';
297
+ };
298
+ };
299
+ items: string[];
300
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
301
+ metadata?: Record<string, any>;
302
+ }
303
+
304
+ it('should handle complex nested types', () => {
305
+ const initialState: ComplexState = {
306
+ id: 1,
307
+ user: {
308
+ name: 'John',
309
+ email: 'john@example.com',
310
+ preferences: {
311
+ notifications: true,
312
+ theme: 'dark',
313
+ },
314
+ },
315
+ items: ['item1', 'item2'],
316
+ };
317
+
318
+ const { result } = renderHook(() => useMutableState(initialState));
319
+
320
+ act(() => {
321
+ const [, , setPartialValue] = result.current;
322
+ setPartialValue({
323
+ user: {
324
+ preferences: {
325
+ theme: 'light',
326
+ },
327
+ },
328
+ metadata: { lastUpdated: Date.now() },
329
+ });
330
+ });
331
+
332
+ const [state] = result.current;
333
+
334
+ expect(state.user.name).toBe('John');
335
+ expect(state.user.email).toBe('john@example.com');
336
+ expect(state.user.preferences.notifications).toBe(true);
337
+ expect(state.user.preferences.theme).toBe('light');
338
+ expect(state.metadata).toBeDefined();
339
+ expect(state.items).toEqual(['item1', 'item2']);
340
+ });
341
+ });
342
+
343
+ describe('edge cases', () => {
344
+ it('should handle null values', () => {
345
+ const { result } = renderHook(() =>
346
+ useMutableState<{ value: string | null }>({ value: 'test' })
347
+ );
348
+
349
+ act(() => {
350
+ const [, , setPartialValue] = result.current;
351
+ setPartialValue({ value: null });
352
+ });
353
+
354
+ expect(result.current[0]).toEqual({ value: null });
355
+ });
356
+
357
+ it('should handle undefined values', () => {
358
+ const { result } = renderHook(() =>
359
+ useMutableState<{ value?: string }>({ value: 'test' })
360
+ );
361
+
362
+ act(() => {
363
+ const [, , setPartialValue] = result.current;
364
+ setPartialValue({ value: undefined });
365
+ });
366
+
367
+ // defaultsDeep doesn't override with undefined, so original value remains
368
+ expect(result.current[0].value).toBe('test');
369
+ });
370
+
371
+ it('should handle state with boolean false', () => {
372
+ const { result } = renderHook(() =>
373
+ useMutableState({ isActive: true, isEnabled: true })
374
+ );
375
+
376
+ act(() => {
377
+ const [, , setPartialValue] = result.current;
378
+ setPartialValue({ isActive: false });
379
+ });
380
+
381
+ expect(result.current[0]).toEqual({ isActive: false, isEnabled: true });
382
+ });
383
+
384
+ it('should handle state with number zero', () => {
385
+ const { result } = renderHook(() =>
386
+ useMutableState({ count: 10, total: 100 })
387
+ );
388
+
389
+ act(() => {
390
+ const [, , setPartialValue] = result.current;
391
+ setPartialValue({ count: 0 });
392
+ });
393
+
394
+ expect(result.current[0]).toEqual({ count: 0, total: 100 });
395
+ });
396
+
397
+ it('should handle state with empty string', () => {
398
+ const { result } = renderHook(() =>
399
+ useMutableState({ name: 'John', description: 'Test' })
400
+ );
401
+
402
+ act(() => {
403
+ const [, , setPartialValue] = result.current;
404
+ setPartialValue({ name: '' });
405
+ });
406
+
407
+ expect(result.current[0]).toEqual({ name: '', description: 'Test' });
408
+ });
409
+ });
410
+ });
@@ -1,25 +1,39 @@
1
- import { useCallback, useMemo, useState } from 'react';
2
-
3
- import { DeepPartial } from '../types';
4
- import { defaultsDeep } from 'lodash';
5
-
6
- export type PartialSetStateAction<T> = (partialValue: DeepPartial<T>) => void;
7
-
8
- export type UseMutableStateReturn<T> = readonly [
9
- T,
10
- React.Dispatch<React.SetStateAction<T>>,
11
- PartialSetStateAction<T>
12
- ];
13
-
14
- export const useMutableState = <T>(initialValue: T | (() => T) = {} as T) => {
15
- const [value, setValue] = useState<T>(initialValue);
16
-
17
- const setPartialValue = useCallback((partialValue: DeepPartial<T>) => {
18
- setValue((value) => defaultsDeep({}, partialValue, value));
19
- }, []);
20
-
21
- return useMemo(
22
- () => [value, setValue, setPartialValue] as const,
23
- [setPartialValue, value]
24
- );
25
- };
1
+ import { Dispatch, useCallback, useMemo, useState } from 'react';
2
+
3
+ import { DeepPartial } from '../types';
4
+ import { defaultsDeep } from 'lodash';
5
+
6
+ export type PartialSetStateAction<T> =
7
+ | DeepPartial<T>
8
+ | ((state: T) => DeepPartial<T>);
9
+
10
+ export type UseMutableStateReturn<T> = readonly [
11
+ T,
12
+ React.Dispatch<React.SetStateAction<T>>,
13
+ Dispatch<PartialSetStateAction<T>>
14
+ ];
15
+
16
+ export const isDispatchFunction = <T>(
17
+ value: PartialSetStateAction<T>
18
+ ): value is (state: T) => DeepPartial<T> => typeof value === 'function';
19
+
20
+ export const useMutableState = <T>(initialValue: T | (() => T) = {} as T) => {
21
+ const [value, setValue] = useState<T>(initialValue);
22
+
23
+ const setPartialValue = useCallback<Dispatch<PartialSetStateAction<T>>>(
24
+ (partialValue) => {
25
+ setValue((value) => {
26
+ const resolvedPartialValue = isDispatchFunction(partialValue)
27
+ ? partialValue(value)
28
+ : partialValue;
29
+ return defaultsDeep({}, resolvedPartialValue, value);
30
+ });
31
+ },
32
+ []
33
+ );
34
+
35
+ return useMemo(
36
+ () => [value, setValue, setPartialValue] as const,
37
+ [setPartialValue, value]
38
+ );
39
+ };
@@ -1,28 +1,28 @@
1
- import { useCallback, useMemo, useState } from 'react';
2
-
3
- import { ConditionDTO } from '../services/sqlRequests';
4
-
5
- export const useShowArchived = (initialValue?: boolean) => {
6
- const [showArchived, setShowArchived] = useState(initialValue ?? false);
7
-
8
- const toggleShowArchived = useCallback((value?: boolean) => {
9
- setShowArchived((prev) => (value === undefined ? !prev : value));
10
- }, []);
11
-
12
- const archivedConditions = useMemo<ConditionDTO[]>(
13
- () =>
14
- showArchived
15
- ? []
16
- : [{ field: 'Archived', operator: 'notEquals', value: 1 }],
17
- [showArchived]
18
- );
19
-
20
- return useMemo(
21
- () => ({
22
- archivedConditions,
23
- showArchived,
24
- toggleShowArchived,
25
- }),
26
- [archivedConditions, showArchived, toggleShowArchived]
27
- );
28
- };
1
+ import { useCallback, useMemo, useState } from 'react';
2
+
3
+ import { ConditionDTO } from '../services/sqlRequests';
4
+
5
+ export const useShowArchived = (initialValue?: boolean) => {
6
+ const [showArchived, setShowArchived] = useState(initialValue ?? false);
7
+
8
+ const toggleShowArchived = useCallback((value?: boolean) => {
9
+ setShowArchived((prev) => (value === undefined ? !prev : value));
10
+ }, []);
11
+
12
+ const archivedConditions = useMemo<ConditionDTO[]>(
13
+ () =>
14
+ showArchived
15
+ ? []
16
+ : [{ field: 'Archived', operator: 'notEquals', value: 1 }],
17
+ [showArchived]
18
+ );
19
+
20
+ return useMemo(
21
+ () => ({
22
+ archivedConditions,
23
+ showArchived,
24
+ toggleShowArchived,
25
+ }),
26
+ [archivedConditions, showArchived, toggleShowArchived]
27
+ );
28
+ };