@rio-cloud/rio-uikit 1.7.1 → 1.9.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 (248) hide show
  1. package/BarList.d.ts +2 -0
  2. package/BarList.js +2 -0
  3. package/README.md +4 -0
  4. package/SaveableDateInput.d.ts +2 -0
  5. package/SaveableDateInput.js +2 -0
  6. package/SvgImage.d.ts +2 -0
  7. package/SvgImage.js +2 -0
  8. package/TableCol.d.ts +2 -0
  9. package/TableCol.js +2 -0
  10. package/TableHead.d.ts +2 -0
  11. package/TableHead.js +2 -0
  12. package/components/actionBarItem/ActionBarItemIcon.js +1 -1
  13. package/components/actionBarItem/ActionBarOverlay.js +1 -1
  14. package/components/activity/Activity.d.ts +2 -2
  15. package/components/applicationHeader/CollapsedNavItem.js +1 -0
  16. package/components/assetTree/Tree.d.ts +20 -0
  17. package/components/assetTree/Tree.js +75 -38
  18. package/components/assetTree/TreeLeaf.js +1 -1
  19. package/components/assetTree/TreeNodeContainer.d.ts +1 -1
  20. package/components/assetTree/TreeSearch.js +1 -1
  21. package/components/assetTree/TreeSummary.js +1 -1
  22. package/components/assetTree/TypeCounter.d.ts +2 -0
  23. package/components/assetTree/TypeCounter.js +1 -1
  24. package/components/assetTree/useTreeExpansion.d.ts +4 -0
  25. package/components/assetTree/useTreeExpansion.js +25 -0
  26. package/components/assetTree/useTreeHeight.d.ts +1 -0
  27. package/components/assetTree/useTreeHeight.js +60 -0
  28. package/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  29. package/components/assetTree/useTreeScrollPosition.js +19 -0
  30. package/components/assetTree/useTreeVirtualization.d.ts +17 -0
  31. package/components/assetTree/useTreeVirtualization.js +71 -0
  32. package/components/autosuggest/AutoSuggest.js +2 -1
  33. package/components/barList/BarList.d.ts +97 -0
  34. package/components/barList/BarList.js +42 -0
  35. package/components/barList/useSortedBars.d.ts +2 -0
  36. package/components/barList/useSortedBars.js +14 -0
  37. package/components/button/ButtonToolbar.d.ts +1 -1
  38. package/components/button/ButtonToolbar.js +1 -1
  39. package/components/button/ToggleButton.js +0 -1
  40. package/components/charts/PieChart.js +1 -1
  41. package/components/clearableInput/ClearableInput.d.ts +20 -7
  42. package/components/clearableInput/ClearableInput.js +68 -8
  43. package/components/dialog/Dialog.js +1 -1
  44. package/components/dialog/FrameDialog.js +1 -1
  45. package/components/dropdown/ButtonDropdown.d.ts +11 -3
  46. package/components/dropdown/ButtonDropdown.js +79 -64
  47. package/components/dropdown/DropdownToggleButton.d.ts +7 -4
  48. package/components/dropdown/DropdownToggleButton.js +11 -3
  49. package/components/formLabel/FormLabel.d.ts +2 -2
  50. package/components/formLabel/FormLabel.js +1 -1
  51. package/components/listMenu/ListMenu.js +4 -1
  52. package/components/map/components/Map.js +21 -6
  53. package/components/map/components/constants.d.ts +2 -0
  54. package/components/map/components/constants.js +3 -0
  55. package/components/map/components/features/basics/InfoBubble.js +1 -1
  56. package/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
  57. package/components/map/utils/mapTypes.d.ts +5 -0
  58. package/components/map/utils/rendering.d.ts +5 -2
  59. package/components/map/utils/rendering.js +46 -39
  60. package/components/menuItems/MenuItem.js +1 -1
  61. package/components/notification/Notification.js +1 -1
  62. package/components/overlay/OverlayTrigger.js +3 -3
  63. package/components/saveableInput/SaveableDateInput.d.ts +83 -0
  64. package/components/saveableInput/SaveableDateInput.js +122 -0
  65. package/components/selects/BaseSelectDropdown.js +1 -1
  66. package/components/selects/Multiselect.d.ts +8 -0
  67. package/components/selects/Multiselect.js +4 -4
  68. package/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  69. package/components/smoothScrollbars/SmoothScrollbars.js +3 -3
  70. package/components/statsWidget/StatsWidget.d.ts +2 -2
  71. package/components/statsWidget/StatsWidgets.d.ts +2 -2
  72. package/components/svgImage/SvgElement.d.ts +8 -0
  73. package/components/svgImage/SvgElement.js +11 -0
  74. package/components/svgImage/SvgImage.d.ts +30 -0
  75. package/components/svgImage/SvgImage.js +20 -0
  76. package/components/svgImage/svgConverter.d.ts +17 -0
  77. package/components/svgImage/svgConverter.js +78 -0
  78. package/components/svgImage/useSvgLoader.d.ts +9 -0
  79. package/components/svgImage/useSvgLoader.js +43 -0
  80. package/components/switch/Switch.d.ts +4 -0
  81. package/components/switch/Switch.js +5 -6
  82. package/components/table/TableCardsSorting.d.ts +0 -1
  83. package/components/table/TableCol.d.ts +18 -0
  84. package/components/table/TableCol.js +11 -0
  85. package/components/table/TableHead.d.ts +33 -0
  86. package/components/table/TableHead.js +11 -0
  87. package/components/table/TableSettingsDialog.js +1 -1
  88. package/components/tag/Tag.js +1 -1
  89. package/components/timepicker/TimePicker.d.ts +1 -2
  90. package/components/timepicker/TimePicker.js +35 -8
  91. package/components/tooltip/SimpleTooltip.d.ts +1 -1
  92. package/components/virtualList/VirtualList.js +1 -1
  93. package/hooks/useIsFocusWithin.d.ts +33 -0
  94. package/hooks/useIsFocusWithin.js +55 -0
  95. package/hooks/useLocationSuggestions.d.ts +27 -0
  96. package/hooks/useLocationSuggestions.js +94 -0
  97. package/hooks/useOnboarding.d.ts +17 -5
  98. package/hooks/useOnboarding.js +7 -1
  99. package/hooks/usePostMessage.js +0 -1
  100. package/hooks/useSearch.d.ts +63 -0
  101. package/hooks/useSearch.js +73 -0
  102. package/hooks/useSorting.d.ts +6 -0
  103. package/hooks/useSorting.js +7 -4
  104. package/hooks/useTableExport.d.ts +49 -0
  105. package/hooks/useTableExport.js +57 -0
  106. package/hooks/useTableSelection.d.ts +166 -0
  107. package/hooks/useTableSelection.js +201 -0
  108. package/lib/es/BarList.d.ts +2 -0
  109. package/lib/es/BarList.js +7 -0
  110. package/lib/es/SaveableDateInput.d.ts +2 -0
  111. package/lib/es/SaveableDateInput.js +7 -0
  112. package/lib/es/SvgImage.d.ts +2 -0
  113. package/lib/es/SvgImage.js +7 -0
  114. package/lib/es/TableCol.d.ts +2 -0
  115. package/lib/es/TableCol.js +7 -0
  116. package/lib/es/TableHead.d.ts +2 -0
  117. package/lib/es/TableHead.js +7 -0
  118. package/lib/es/components/actionBarItem/ActionBarItemIcon.js +1 -1
  119. package/lib/es/components/actionBarItem/ActionBarOverlay.js +1 -1
  120. package/lib/es/components/activity/Activity.d.ts +2 -2
  121. package/lib/es/components/applicationHeader/CollapsedNavItem.js +1 -0
  122. package/lib/es/components/assetTree/Tree.d.ts +20 -0
  123. package/lib/es/components/assetTree/Tree.js +74 -37
  124. package/lib/es/components/assetTree/TreeLeaf.js +1 -1
  125. package/lib/es/components/assetTree/TreeNodeContainer.d.ts +1 -1
  126. package/lib/es/components/assetTree/TreeSearch.js +1 -1
  127. package/lib/es/components/assetTree/TreeSummary.js +1 -1
  128. package/lib/es/components/assetTree/TypeCounter.d.ts +2 -0
  129. package/lib/es/components/assetTree/TypeCounter.js +1 -1
  130. package/lib/es/components/assetTree/useTreeExpansion.d.ts +4 -0
  131. package/lib/es/components/assetTree/useTreeExpansion.js +29 -0
  132. package/lib/es/components/assetTree/useTreeHeight.d.ts +1 -0
  133. package/lib/es/components/assetTree/useTreeHeight.js +64 -0
  134. package/lib/es/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  135. package/lib/es/components/assetTree/useTreeScrollPosition.js +23 -0
  136. package/lib/es/components/assetTree/useTreeVirtualization.d.ts +17 -0
  137. package/lib/es/components/assetTree/useTreeVirtualization.js +76 -0
  138. package/lib/es/components/autosuggest/AutoSuggest.js +2 -1
  139. package/lib/es/components/barList/BarList.d.ts +97 -0
  140. package/lib/es/components/barList/BarList.js +45 -0
  141. package/lib/es/components/barList/useSortedBars.d.ts +2 -0
  142. package/lib/es/components/barList/useSortedBars.js +17 -0
  143. package/lib/es/components/button/ButtonToolbar.d.ts +1 -1
  144. package/lib/es/components/button/ButtonToolbar.js +1 -1
  145. package/lib/es/components/button/ToggleButton.js +0 -1
  146. package/lib/es/components/charts/PieChart.js +1 -1
  147. package/lib/es/components/clearableInput/ClearableInput.d.ts +20 -7
  148. package/lib/es/components/clearableInput/ClearableInput.js +67 -7
  149. package/lib/es/components/dialog/Dialog.js +1 -1
  150. package/lib/es/components/dialog/FrameDialog.js +1 -1
  151. package/lib/es/components/dropdown/ButtonDropdown.d.ts +11 -3
  152. package/lib/es/components/dropdown/ButtonDropdown.js +79 -64
  153. package/lib/es/components/dropdown/DropdownToggleButton.d.ts +7 -4
  154. package/lib/es/components/dropdown/DropdownToggleButton.js +11 -3
  155. package/lib/es/components/formLabel/FormLabel.d.ts +2 -2
  156. package/lib/es/components/formLabel/FormLabel.js +1 -1
  157. package/lib/es/components/listMenu/ListMenu.js +4 -1
  158. package/lib/es/components/map/components/Map.js +20 -5
  159. package/lib/es/components/map/components/constants.d.ts +2 -0
  160. package/lib/es/components/map/components/constants.js +4 -1
  161. package/lib/es/components/map/components/features/basics/InfoBubble.js +1 -1
  162. package/lib/es/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
  163. package/lib/es/components/map/utils/mapTypes.d.ts +5 -0
  164. package/lib/es/components/map/utils/rendering.d.ts +5 -2
  165. package/lib/es/components/map/utils/rendering.js +46 -39
  166. package/lib/es/components/menuItems/MenuItem.js +1 -1
  167. package/lib/es/components/notification/Notification.js +1 -1
  168. package/lib/es/components/overlay/OverlayTrigger.js +3 -3
  169. package/lib/es/components/saveableInput/SaveableDateInput.d.ts +83 -0
  170. package/lib/es/components/saveableInput/SaveableDateInput.js +125 -0
  171. package/lib/es/components/selects/BaseSelectDropdown.js +1 -1
  172. package/lib/es/components/selects/Multiselect.d.ts +8 -0
  173. package/lib/es/components/selects/Multiselect.js +4 -4
  174. package/lib/es/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  175. package/lib/es/components/smoothScrollbars/SmoothScrollbars.js +3 -3
  176. package/lib/es/components/statsWidget/StatsWidget.d.ts +2 -2
  177. package/lib/es/components/statsWidget/StatsWidgets.d.ts +2 -2
  178. package/lib/es/components/svgImage/SvgElement.d.ts +8 -0
  179. package/lib/es/components/svgImage/SvgElement.js +14 -0
  180. package/lib/es/components/svgImage/SvgImage.d.ts +30 -0
  181. package/lib/es/components/svgImage/SvgImage.js +23 -0
  182. package/lib/es/components/svgImage/svgConverter.d.ts +17 -0
  183. package/lib/es/components/svgImage/svgConverter.js +84 -0
  184. package/lib/es/components/svgImage/useSvgLoader.d.ts +9 -0
  185. package/lib/es/components/svgImage/useSvgLoader.js +48 -0
  186. package/lib/es/components/switch/Switch.d.ts +4 -0
  187. package/lib/es/components/switch/Switch.js +5 -6
  188. package/lib/es/components/table/TableCardsSorting.d.ts +0 -1
  189. package/lib/es/components/table/TableCol.d.ts +18 -0
  190. package/lib/es/components/table/TableCol.js +13 -0
  191. package/lib/es/components/table/TableHead.d.ts +33 -0
  192. package/lib/es/components/table/TableHead.js +14 -0
  193. package/lib/es/components/table/TableSettingsDialog.js +1 -1
  194. package/lib/es/components/tag/Tag.js +1 -1
  195. package/lib/es/components/timepicker/TimePicker.d.ts +1 -2
  196. package/lib/es/components/timepicker/TimePicker.js +35 -8
  197. package/lib/es/components/tooltip/SimpleTooltip.d.ts +1 -1
  198. package/lib/es/components/virtualList/VirtualList.js +1 -1
  199. package/lib/es/hooks/useIsFocusWithin.d.ts +33 -0
  200. package/lib/es/hooks/useIsFocusWithin.js +57 -0
  201. package/lib/es/hooks/useLocationSuggestions.d.ts +27 -0
  202. package/lib/es/hooks/useLocationSuggestions.js +97 -0
  203. package/lib/es/hooks/useOnboarding.d.ts +17 -5
  204. package/lib/es/hooks/useOnboarding.js +7 -1
  205. package/lib/es/hooks/usePostMessage.js +0 -1
  206. package/lib/es/hooks/useSearch.d.ts +63 -0
  207. package/lib/es/hooks/useSearch.js +75 -0
  208. package/lib/es/hooks/useSorting.d.ts +6 -0
  209. package/lib/es/hooks/useSorting.js +7 -4
  210. package/lib/es/hooks/useTableExport.d.ts +49 -0
  211. package/lib/es/hooks/useTableExport.js +59 -0
  212. package/lib/es/hooks/useTableSelection.d.ts +166 -0
  213. package/lib/es/hooks/useTableSelection.js +210 -0
  214. package/lib/es/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
  215. package/lib/es/useIsFocusWithin.d.ts +2 -0
  216. package/lib/es/useIsFocusWithin.js +7 -0
  217. package/lib/es/useLocationSuggestions.d.ts +2 -0
  218. package/lib/es/useLocationSuggestions.js +7 -0
  219. package/lib/es/useSearch.d.ts +2 -0
  220. package/lib/es/useSearch.js +7 -0
  221. package/lib/es/useTableExport.d.ts +2 -0
  222. package/lib/es/useTableExport.js +7 -0
  223. package/lib/es/useTableSelection.d.ts +2 -0
  224. package/lib/es/useTableSelection.js +7 -0
  225. package/lib/es/utils/storageUtils.d.ts +2 -2
  226. package/lib/es/utils/storageUtils.js +2 -0
  227. package/lib/es/utils/urlFeatureToggles.d.ts +12 -6
  228. package/lib/es/utils/urlFeatureToggles.js +14 -8
  229. package/lib/es/utils/useDropDirection.js +1 -0
  230. package/lib/es/version.json +1 -1
  231. package/package.json +48 -40
  232. package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
  233. package/useIsFocusWithin.d.ts +2 -0
  234. package/useIsFocusWithin.js +2 -0
  235. package/useLocationSuggestions.d.ts +2 -0
  236. package/useLocationSuggestions.js +2 -0
  237. package/useSearch.d.ts +2 -0
  238. package/useSearch.js +2 -0
  239. package/useTableExport.d.ts +2 -0
  240. package/useTableExport.js +2 -0
  241. package/useTableSelection.d.ts +2 -0
  242. package/useTableSelection.js +2 -0
  243. package/utils/storageUtils.d.ts +2 -2
  244. package/utils/storageUtils.js +2 -0
  245. package/utils/urlFeatureToggles.d.ts +12 -6
  246. package/utils/urlFeatureToggles.js +10 -7
  247. package/utils/useDropDirection.js +1 -0
  248. package/version.json +1 -1
@@ -0,0 +1,55 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ /**
3
+ * React hook that tracks whether focus is currently within a given element or its children.
4
+ * Provides a boolean state and a ref to attach to the tracked element.
5
+ *
6
+ * @param options Hook configuration including external ref, callbacks, and optional delay.
7
+ * @returns An object containing the ref and whether focus is currently within the element.
8
+ */
9
+ const useIsFocusWithin = ({ ref: externalRef, onFocusWithin = () => { }, onBlurWithin = () => { }, delay = 0, } = {}) => {
10
+ const internalRef = useRef(null);
11
+ const targetRef = externalRef ?? internalRef;
12
+ const [isFocusedWithin, setIsFocusedWithin] = useState(false);
13
+ const timeoutId = useRef(null);
14
+ const clearTimeoutIfAny = () => {
15
+ if (timeoutId.current !== null) {
16
+ window.clearTimeout(timeoutId.current);
17
+ timeoutId.current = null;
18
+ }
19
+ };
20
+ useEffect(() => {
21
+ const node = targetRef.current;
22
+ if (!node) {
23
+ return;
24
+ }
25
+ const handleFocusIn = () => {
26
+ clearTimeoutIfAny();
27
+ if (!isFocusedWithin) {
28
+ setIsFocusedWithin(true);
29
+ onFocusWithin();
30
+ }
31
+ };
32
+ const handleFocusOut = (e) => {
33
+ clearTimeoutIfAny();
34
+ timeoutId.current = window.setTimeout(() => {
35
+ if (!node.contains(e.relatedTarget)) {
36
+ setIsFocusedWithin(false);
37
+ onBlurWithin();
38
+ }
39
+ timeoutId.current = null;
40
+ }, delay);
41
+ };
42
+ node.addEventListener('focusin', handleFocusIn);
43
+ node.addEventListener('focusout', handleFocusOut);
44
+ return () => {
45
+ node.removeEventListener('focusin', handleFocusIn);
46
+ node.removeEventListener('focusout', handleFocusOut);
47
+ clearTimeoutIfAny();
48
+ };
49
+ }, [targetRef, delay, onFocusWithin, onBlurWithin, isFocusedWithin]);
50
+ return {
51
+ ref: targetRef,
52
+ isFocusedWithin,
53
+ };
54
+ };
55
+ export default useIsFocusWithin;
@@ -0,0 +1,27 @@
1
+ export type LocationSuggestion = {
2
+ id: string;
3
+ label: string;
4
+ };
5
+ export type LocationFetchOptions = Record<string, unknown> & {
6
+ apiKey?: string;
7
+ fetchUrl?: string;
8
+ limit?: number;
9
+ };
10
+ /**
11
+ * Custom React hook for fetching location suggestions using HERE Maps Autocomplete API.
12
+ *
13
+ * @param query - The user input string to search for location suggestions.
14
+ * @param options - Optional configuration:
15
+ * - apiKey: Your HERE Maps API key (default is 'YOUR_API_KEY').
16
+ * - fetchUrl: Optional override for the autocomplete endpoint URL.
17
+ * @returns An object containing:
18
+ * - suggestions: Array of location suggestions with `id` and `label`.
19
+ * - loading: Boolean indicating whether the fetch is in progress.
20
+ * - error: Any error that occurred during fetching.
21
+ */
22
+ declare const useLocationSuggestions: (query: string, options?: LocationFetchOptions) => {
23
+ suggestions: LocationSuggestion[];
24
+ loading: boolean;
25
+ error: Error | null;
26
+ };
27
+ export default useLocationSuggestions;
@@ -0,0 +1,94 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import debounce from 'lodash/fp/debounce';
3
+ const DEFAULT_URL = 'https://autocomplete.search.hereapi.com/v1/autocomplete';
4
+ const fetchLocationSuggestions = async (query, signal, options = {}) => {
5
+ const { apiKey, fetchUrl = DEFAULT_URL, limit = 5, ...restOptions } = options;
6
+ if (!query || !apiKey) {
7
+ return [];
8
+ }
9
+ const params = new URLSearchParams({
10
+ q: query,
11
+ apiKey,
12
+ limit: String(limit),
13
+ // Add any additional options dynamically
14
+ ...restOptions,
15
+ });
16
+ const response = await fetch(`${fetchUrl}?${params.toString()}`, { signal });
17
+ if (!response.ok) {
18
+ // Throw an error for bad responses (4xx, 5xx)
19
+ // This allows the hook's catch block to handle API errors
20
+ throw new Error(`API request failed with status ${response.status}`);
21
+ }
22
+ const data = await response.json();
23
+ // Ensure data.items exists and is an array before mapping
24
+ return Array.isArray(data?.items)
25
+ ? data.items.map((item) => ({
26
+ id: item.id,
27
+ label: item.title,
28
+ }))
29
+ : [];
30
+ };
31
+ const FETCH_DEBOUNCE_IN_MS = 300;
32
+ /**
33
+ * Custom React hook for fetching location suggestions using HERE Maps Autocomplete API.
34
+ *
35
+ * @param query - The user input string to search for location suggestions.
36
+ * @param options - Optional configuration:
37
+ * - apiKey: Your HERE Maps API key (default is 'YOUR_API_KEY').
38
+ * - fetchUrl: Optional override for the autocomplete endpoint URL.
39
+ * @returns An object containing:
40
+ * - suggestions: Array of location suggestions with `id` and `label`.
41
+ * - loading: Boolean indicating whether the fetch is in progress.
42
+ * - error: Any error that occurred during fetching.
43
+ */
44
+ const useLocationSuggestions = (query, options = {}) => {
45
+ const [suggestions, setSuggestions] = useState([]);
46
+ const [loading, setLoading] = useState(false);
47
+ const [error, setError] = useState(null);
48
+ const abortRef = useRef(null);
49
+ // React re-renders the component every time state or props change. If we define the debounce() call
50
+ // directly inside the component without useRef, we'll create a new debounced function on every render,
51
+ // which defeats the purpose of debouncing.
52
+ // By wrapping it in useRef, we ensure the debounced function is created only once and persists between renders
53
+ const debouncedFetch = useRef(debounce(FETCH_DEBOUNCE_IN_MS, async (currentQuery, currentOptions) => {
54
+ // Abort any ongoing request from previous calls
55
+ abortRef.current?.abort();
56
+ const controller = new AbortController();
57
+ abortRef.current = controller;
58
+ // Reset error before a new fetch attempt
59
+ setError(null);
60
+ try {
61
+ const results = await fetchLocationSuggestions(currentQuery, controller.signal, currentOptions);
62
+ setSuggestions(results);
63
+ }
64
+ catch (fetchError) {
65
+ if (fetchError.name !== 'AbortError') {
66
+ setError(fetchError);
67
+ }
68
+ setSuggestions([]);
69
+ }
70
+ finally {
71
+ setLoading(false);
72
+ }
73
+ })).current;
74
+ // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
75
+ useEffect(() => {
76
+ if (!query || !options.apiKey) {
77
+ setSuggestions([]);
78
+ setLoading(false);
79
+ // Abort if there was an ongoing request
80
+ abortRef.current?.abort();
81
+ return;
82
+ }
83
+ setLoading(true);
84
+ debouncedFetch(query, options);
85
+ }, [query, debouncedFetch, options.apiKey, options.fetchUrl]); // `debouncedFetch` is stable due to useRef
86
+ // Cleanup on unmount
87
+ useEffect(() => {
88
+ return () => {
89
+ abortRef.current?.abort();
90
+ };
91
+ }, []);
92
+ return { suggestions, loading, error };
93
+ };
94
+ export default useLocationSuggestions;
@@ -1,8 +1,8 @@
1
- import { type PopoverDOM as DriverPopoverDOM, type State as DriverState, type AllowedButtons } from 'driver.js';
1
+ import { type PopoverDOM as DriverPopoverDOM, type State as DriverState, type AllowedButtons, type DriveStep } from 'driver.js';
2
2
  import 'driver.js/dist/driver.css';
3
3
  export type PopoverDOM = DriverPopoverDOM;
4
4
  export type OnboardingState = DriverState;
5
- export type OnboardingStep = {
5
+ export type OnboardingStep = DriveStep & {
6
6
  element?: string | Element;
7
7
  onHighlightStarted?: (element: Element | undefined, step: OnboardingStep, opts: any) => void;
8
8
  onHighlighted?: (element: Element | undefined, step: OnboardingStep, opts: any) => void;
@@ -14,6 +14,7 @@ export type OnboardingStep = {
14
14
  align?: 'start' | 'center' | 'end';
15
15
  showButtons?: ('next' | 'previous' | 'close')[];
16
16
  disableButtons?: ('next' | 'previous' | 'close')[];
17
+ disableActiveInteraction?: boolean;
17
18
  popoverClass?: string;
18
19
  doneBtnText?: string;
19
20
  nextBtnText?: string;
@@ -78,6 +79,13 @@ type OnboardingOptions = {
78
79
  * Array of buttons to disable. This is useful when you want to show some of the buttons, but disable some of them.
79
80
  */
80
81
  disableButtons?: AllowedButtons[];
82
+ /**
83
+ * Whether to disable interaction with the highlighted element.
84
+ * Can be configured at the step level as well.
85
+ *
86
+ * @default false
87
+ */
88
+ disableActiveInteraction?: boolean;
81
89
  /**
82
90
  * Option to disable the backdrop. Note, the backdrop element is still there but with 100% opacity
83
91
  * and the close on the backdrop is disabled.
@@ -97,18 +105,22 @@ type OnboardingOptions = {
97
105
  * @returns
98
106
  */
99
107
  onPopoverRender?: (popover: PopoverDOM, state: OnboardingState) => void;
108
+ /**
109
+ * Callback triggered when the onboarding tour is destroyed
110
+ */
111
+ onDestroyed?: () => void;
100
112
  };
101
113
  export declare const useOnboardingTour: (params: OnboardingOptions) => {
102
114
  run: () => void;
103
115
  destroy: () => void;
104
- onboardingState: () => DriverState;
116
+ onboardingState: () => any;
105
117
  refresh: () => void;
106
118
  isActive: () => boolean;
107
119
  moveNext: () => void;
108
120
  movePrevious: () => void;
109
121
  moveTo: (stepNumber: number) => void;
110
- hasNextStep: () => false | import("driver.js").DriveStep;
111
- hasPreviousStep: () => false | import("driver.js").DriveStep;
122
+ hasNextStep: () => boolean;
123
+ hasPreviousStep: () => boolean;
112
124
  isFirstStep: () => boolean;
113
125
  isLastStep: () => boolean;
114
126
  getActiveIndex: () => number | undefined;
@@ -1,10 +1,14 @@
1
1
  import { driver, } from 'driver.js';
2
2
  import 'driver.js/dist/driver.css';
3
3
  export const useOnboardingTour = (params) => {
4
- const { steps, prevBtnText = 'Previous', nextBtnText = 'Next', doneBtnText = 'Done', showProgress = true, allowClose = false, stagePadding = 10, stageRadius = 5, allowKeyboardControl = true, showButtons, disableButtons, popoverClass, noBackdrop = false, onPopoverRender = () => { }, } = params;
4
+ console.log({ params });
5
+ const { steps, prevBtnText = 'Previous', nextBtnText = 'Next', doneBtnText = 'Done', showProgress = true, allowClose = false, stagePadding = 10, stageRadius = 5, allowKeyboardControl = true, showButtons, disableButtons, popoverClass, noBackdrop = false, onPopoverRender = () => { }, onDestroyed = () => { }, ...driverProps } = params;
5
6
  const handlePopoverRender = (popover, options) => {
6
7
  onPopoverRender(popover, options.state);
7
8
  };
9
+ const handleDestroyed = () => {
10
+ onDestroyed();
11
+ };
8
12
  const isSingleStep = !steps || steps.length === 1;
9
13
  // This configuration is applied to all steps.
10
14
  // Driver.js allows also for individual customization for single steps too.
@@ -25,6 +29,8 @@ export const useOnboardingTour = (params) => {
25
29
  allowKeyboardControl,
26
30
  popoverClass,
27
31
  onPopoverRender: handlePopoverRender,
32
+ onDestroyed: handleDestroyed,
33
+ ...driverProps,
28
34
  });
29
35
  return {
30
36
  // Use for onboarding tours. Pass in all steps as "steps" parameter for initial configuration.
@@ -33,7 +33,6 @@ const usePostMessage = (messagePrefix, onReceiveMessage) => {
33
33
  if (!actionType) {
34
34
  return;
35
35
  }
36
- console.log(event);
37
36
  if (actionType.startsWith(messagePrefix)) {
38
37
  callback(event.data);
39
38
  }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Options for configuring the `useSearch` hook.
3
+ */
4
+ type UseSearchOptions<T> = {
5
+ /**
6
+ * List of object fields to search within. Dot notation (e.g. `'address.city'`) is supported for nested properties.
7
+ * If omitted, all top-level string and number fields will be used.
8
+ */
9
+ fields?: (keyof T | string)[];
10
+ /**
11
+ * Optional custom filtering function.
12
+ * If provided, this takes precedence over field-based filtering.
13
+ *
14
+ * @param item - The current item in the list.
15
+ * @param query - The current search query string.
16
+ * @returns `true` if the item should be included in the filtered list.
17
+ */
18
+ customFilter?: (item: T, query: string) => boolean;
19
+ /**
20
+ * Number of milliseconds to debounce the search input.
21
+ * If omitted, debounce is disabled.
22
+ */
23
+ debounceMs?: number;
24
+ /**
25
+ * Whether to perform a case-sensitive match.
26
+ * Default is `false` (case-insensitive).
27
+ *
28
+ * @default false
29
+ */
30
+ caseSensitive?: boolean;
31
+ };
32
+ /**
33
+ * A hook to filter a list of objects by a search value.
34
+ * Supports field-based filtering, custom filtering logic, debounce, and case sensitivity.
35
+ *
36
+ * @template T - The type of items in the list (must be an object).
37
+ *
38
+ * @param list - The array of objects to search through.
39
+ * @param options - Configuration options for the search behavior.
40
+ * @param options.fields - Fields to search through. If omitted, all top-level string/number fields are used.
41
+ * @param options.customFilter - Optional custom filter function overriding field-based filtering.
42
+ * @param options.debounceMs - Debounce time in milliseconds.
43
+ * @param options.caseSensitive - Whether the search should be case-sensitive.
44
+ *
45
+ * @returns An object containing:
46
+ * - `searchValue`: The current search input string.
47
+ * - `setSearchValue`: A setter function to update the search query.
48
+ * - `filteredList`: The list of items matching the current search query.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const { searchValue, setSearchValue, filteredList } = useSearch(users, {
53
+ * fields: ['name', 'email'],
54
+ * debounceMs: 300,
55
+ * });
56
+ * ```
57
+ */
58
+ declare const useSearch: <T extends object>(list: T[], options?: UseSearchOptions<T>) => {
59
+ searchValue: string;
60
+ setSearchValue: import("react").Dispatch<import("react").SetStateAction<string>> | import("lodash").DebouncedFunc<(q: string) => void>;
61
+ filteredList: T[];
62
+ };
63
+ export default useSearch;
@@ -0,0 +1,73 @@
1
+ import { useMemo, useState, useCallback } from 'react';
2
+ import { debounce } from 'lodash/fp';
3
+ /**
4
+ * Gets the value of a nested field from an object using dot notation.
5
+ *
6
+ * @param obj - The object to traverse.
7
+ * @param path - The dot-notated path string.
8
+ * @returns The value at the specified path, or undefined.
9
+ */
10
+ const getNestedValue = (obj, path) => path.split('.').reduce((val, key) => (val ? val[key] : undefined), obj);
11
+ const inferSearchableFields = (item) => Object.keys(item).filter(key => {
12
+ const value = item[key];
13
+ return typeof value === 'string' || typeof value === 'number';
14
+ });
15
+ /**
16
+ * A hook to filter a list of objects by a search value.
17
+ * Supports field-based filtering, custom filtering logic, debounce, and case sensitivity.
18
+ *
19
+ * @template T - The type of items in the list (must be an object).
20
+ *
21
+ * @param list - The array of objects to search through.
22
+ * @param options - Configuration options for the search behavior.
23
+ * @param options.fields - Fields to search through. If omitted, all top-level string/number fields are used.
24
+ * @param options.customFilter - Optional custom filter function overriding field-based filtering.
25
+ * @param options.debounceMs - Debounce time in milliseconds.
26
+ * @param options.caseSensitive - Whether the search should be case-sensitive.
27
+ *
28
+ * @returns An object containing:
29
+ * - `searchValue`: The current search input string.
30
+ * - `setSearchValue`: A setter function to update the search query.
31
+ * - `filteredList`: The list of items matching the current search query.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const { searchValue, setSearchValue, filteredList } = useSearch(users, {
36
+ * fields: ['name', 'email'],
37
+ * debounceMs: 300,
38
+ * });
39
+ * ```
40
+ */
41
+ const useSearch = (list, options = {}) => {
42
+ const [searchValue, _setSearchValue] = useState('');
43
+ // Debounced setter
44
+ const setSearchValue = useCallback(options.debounceMs ? debounce(options.debounceMs, (q) => _setSearchValue(q)) : _setSearchValue, [options.debounceMs]);
45
+ const filteredList = useMemo(() => {
46
+ if (!searchValue) {
47
+ return list;
48
+ }
49
+ if (list.length === 0) {
50
+ return [];
51
+ }
52
+ const isCaseSensitive = options.caseSensitive ?? false;
53
+ const query = isCaseSensitive ? searchValue : searchValue.toLowerCase();
54
+ // Custom filter takes precedence
55
+ if (options.customFilter) {
56
+ return list.filter(item => options.customFilter?.(item, searchValue));
57
+ }
58
+ const fields = options.fields ?? inferSearchableFields(list[0]);
59
+ return list.filter(item => fields.some(field => {
60
+ const value = getNestedValue(item, field.toString());
61
+ if (typeof value === 'string') {
62
+ const target = isCaseSensitive ? value : value.toLowerCase();
63
+ return target.includes(query);
64
+ }
65
+ if (typeof value === 'number') {
66
+ return value.toString().includes(query);
67
+ }
68
+ return false;
69
+ }));
70
+ }, [list, options, searchValue]);
71
+ return { searchValue, setSearchValue, filteredList };
72
+ };
73
+ export default useSearch;
@@ -19,6 +19,12 @@ type UseSortingResult<T> = {
19
19
  * @returns
20
20
  */
21
21
  setSortKey: (newKey: SortKey<T>) => void;
22
+ /**
23
+ * Function to change the sorting order afterwards
24
+ * @param newKey the new sorting key(s)
25
+ * @returns
26
+ */
27
+ setSortDirection: (newSortDirection: SortDirectionType) => void;
22
28
  /**
23
29
  * Function to toggle the sorting between ascending and descending order
24
30
  * @returns
@@ -10,10 +10,12 @@ const useSorting = (items, initialKey, initialDirection = SortDirection.ASCENDIN
10
10
  : arr.sort((a, b) => {
11
11
  const aVal = a[key];
12
12
  const bVal = b[key];
13
- if (aVal < bVal)
13
+ if (aVal < bVal) {
14
14
  return sortDirection === SortDirection.ASCENDING ? -1 : 1;
15
- if (aVal > bVal)
15
+ }
16
+ if (aVal > bVal) {
16
17
  return sortDirection === SortDirection.ASCENDING ? 1 : -1;
18
+ }
17
19
  return 0;
18
20
  });
19
21
  };
@@ -23,8 +25,9 @@ const useSorting = (items, initialKey, initialDirection = SortDirection.ASCENDIN
23
25
  // Group items with the same primary key value
24
26
  const groups = primarySorted.reduce((acc, item) => {
25
27
  const key = String(item[primaryKey]);
26
- if (!acc[key])
28
+ if (!acc[key]) {
27
29
  acc[key] = [];
30
+ }
28
31
  acc[key].push(item);
29
32
  return acc;
30
33
  }, {});
@@ -36,6 +39,6 @@ const useSorting = (items, initialKey, initialDirection = SortDirection.ASCENDIN
36
39
  const toggleDirection = () => {
37
40
  setSortDirection(prev => prev === SortDirection.ASCENDING ? SortDirection.DESCENDING : SortDirection.ASCENDING);
38
41
  };
39
- return { sortedItems, sortKey, sortDirection, setSortKey, toggleDirection };
42
+ return { sortedItems, sortKey, sortDirection, setSortKey, setSortDirection, toggleDirection };
40
43
  };
41
44
  export default useSorting;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Options for exporting tabular data to CSV.
3
+ */
4
+ export type ExportOptions<T extends object> = {
5
+ /**
6
+ * Array of data objects to export. Each object represents one row in the table.
7
+ */
8
+ data: T[];
9
+ /**
10
+ * Optional name for the exported file.
11
+ * @default "export.csv"
12
+ */
13
+ fileName?: string;
14
+ /**
15
+ * Optional list of object keys to export as columns.
16
+ * If omitted, all keys from the first row will be used.
17
+ */
18
+ columns?: (keyof T)[];
19
+ /**
20
+ * Optional map of column keys to custom header labels.
21
+ * @example { firstName: 'First Name' }
22
+ */
23
+ headers?: Partial<Record<keyof T, string>>;
24
+ /**
25
+ * Optional delimiter to use between values in the CSV.
26
+ * You can use `";"` or `"\t"` for other formats.
27
+ * @default ","
28
+ */
29
+ delimiter?: string;
30
+ /**
31
+ * Whether to include UTF-8 BOM (useful for Excel).
32
+ * @default true
33
+ */
34
+ withBom?: boolean;
35
+ };
36
+ /**
37
+ * React hook for exporting tabular data to a downloadable CSV file.
38
+ *
39
+ * @template T Type of each data row object.
40
+ * @returns An object with a `exportToCSV` function to trigger the export.
41
+ *
42
+ * @example
43
+ * const { exportToCSV } = useTableExport<User>();
44
+ * exportToCSV({ data: users, fileName: 'users.csv', delimiter: ';' });
45
+ */
46
+ declare const useTableExport: <T extends object>() => {
47
+ exportToCSV: ({ data, fileName, columns, headers, delimiter, withBom }: ExportOptions<T>) => void;
48
+ };
49
+ export default useTableExport;
@@ -0,0 +1,57 @@
1
+ import { useCallback } from 'react';
2
+ /**
3
+ * Converts a dataset into CSV format as a string.
4
+ *
5
+ * @template T Type of each row object.
6
+ * @param data The data array to convert.
7
+ * @param columns Optional keys to include as columns.
8
+ * @param headers Optional key-to-label mapping for header row.
9
+ * @param delimiter Delimiter to separate columns. Defaults to `","`.
10
+ * @returns A string representing the CSV data.
11
+ */
12
+ const convertToCSV = (data, columns, headers, delimiter = ',') => {
13
+ if (!data.length) {
14
+ return '';
15
+ }
16
+ const escapeFn = (val) => {
17
+ if (val === null || val === undefined) {
18
+ return '';
19
+ }
20
+ const str = String(val);
21
+ const needsQuotes = str.includes(delimiter) || str.includes('"') || str.includes('\n');
22
+ const escaped = str.replace(/"/g, '""');
23
+ return needsQuotes ? `"${escaped}"` : escaped;
24
+ };
25
+ const headerRow = columns.map(key => escapeFn(headers?.[key] ?? String(key))).join(delimiter);
26
+ const dataRows = data.map(row => columns.map(key => escapeFn(row[key])).join(delimiter));
27
+ return [headerRow, ...dataRows].join('\n');
28
+ };
29
+ /**
30
+ * React hook for exporting tabular data to a downloadable CSV file.
31
+ *
32
+ * @template T Type of each data row object.
33
+ * @returns An object with a `exportToCSV` function to trigger the export.
34
+ *
35
+ * @example
36
+ * const { exportToCSV } = useTableExport<User>();
37
+ * exportToCSV({ data: users, fileName: 'users.csv', delimiter: ';' });
38
+ */
39
+ const useTableExport = () => {
40
+ const exportToCSV = useCallback(({ data, fileName = 'export.csv', columns, headers, delimiter = ',', withBom = true }) => {
41
+ if (!data.length) {
42
+ return;
43
+ }
44
+ const cols = columns ?? Object.keys(data[0]);
45
+ const csv = convertToCSV(data, cols, headers, delimiter);
46
+ const bom = withBom ? '\uFEFF' : '';
47
+ const blob = new Blob([bom + csv], { type: 'text/csv;charset=utf-8;' });
48
+ const link = document.createElement('a');
49
+ link.href = URL.createObjectURL(blob);
50
+ link.setAttribute('download', fileName);
51
+ document.body.appendChild(link);
52
+ link.click();
53
+ document.body.removeChild(link);
54
+ }, []);
55
+ return { exportToCSV };
56
+ };
57
+ export default useTableExport;