@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.
- package/BarList.d.ts +2 -0
- package/BarList.js +2 -0
- package/README.md +4 -0
- package/SaveableDateInput.d.ts +2 -0
- package/SaveableDateInput.js +2 -0
- package/SvgImage.d.ts +2 -0
- package/SvgImage.js +2 -0
- package/TableCol.d.ts +2 -0
- package/TableCol.js +2 -0
- package/TableHead.d.ts +2 -0
- package/TableHead.js +2 -0
- package/components/actionBarItem/ActionBarItemIcon.js +1 -1
- package/components/actionBarItem/ActionBarOverlay.js +1 -1
- package/components/activity/Activity.d.ts +2 -2
- package/components/applicationHeader/CollapsedNavItem.js +1 -0
- package/components/assetTree/Tree.d.ts +20 -0
- package/components/assetTree/Tree.js +75 -38
- package/components/assetTree/TreeLeaf.js +1 -1
- package/components/assetTree/TreeNodeContainer.d.ts +1 -1
- package/components/assetTree/TreeSearch.js +1 -1
- package/components/assetTree/TreeSummary.js +1 -1
- package/components/assetTree/TypeCounter.d.ts +2 -0
- package/components/assetTree/TypeCounter.js +1 -1
- package/components/assetTree/useTreeExpansion.d.ts +4 -0
- package/components/assetTree/useTreeExpansion.js +25 -0
- package/components/assetTree/useTreeHeight.d.ts +1 -0
- package/components/assetTree/useTreeHeight.js +60 -0
- package/components/assetTree/useTreeScrollPosition.d.ts +3 -0
- package/components/assetTree/useTreeScrollPosition.js +19 -0
- package/components/assetTree/useTreeVirtualization.d.ts +17 -0
- package/components/assetTree/useTreeVirtualization.js +71 -0
- package/components/autosuggest/AutoSuggest.js +2 -1
- package/components/barList/BarList.d.ts +97 -0
- package/components/barList/BarList.js +42 -0
- package/components/barList/useSortedBars.d.ts +2 -0
- package/components/barList/useSortedBars.js +14 -0
- package/components/button/ButtonToolbar.d.ts +1 -1
- package/components/button/ButtonToolbar.js +1 -1
- package/components/button/ToggleButton.js +0 -1
- package/components/charts/PieChart.js +1 -1
- package/components/clearableInput/ClearableInput.d.ts +20 -7
- package/components/clearableInput/ClearableInput.js +68 -8
- package/components/dialog/Dialog.js +1 -1
- package/components/dialog/FrameDialog.js +1 -1
- package/components/dropdown/ButtonDropdown.d.ts +11 -3
- package/components/dropdown/ButtonDropdown.js +79 -64
- package/components/dropdown/DropdownToggleButton.d.ts +7 -4
- package/components/dropdown/DropdownToggleButton.js +11 -3
- package/components/formLabel/FormLabel.d.ts +2 -2
- package/components/formLabel/FormLabel.js +1 -1
- package/components/listMenu/ListMenu.js +4 -1
- package/components/map/components/Map.js +21 -6
- package/components/map/components/constants.d.ts +2 -0
- package/components/map/components/constants.js +3 -0
- package/components/map/components/features/basics/InfoBubble.js +1 -1
- package/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
- package/components/map/utils/mapTypes.d.ts +5 -0
- package/components/map/utils/rendering.d.ts +5 -2
- package/components/map/utils/rendering.js +46 -39
- package/components/menuItems/MenuItem.js +1 -1
- package/components/notification/Notification.js +1 -1
- package/components/overlay/OverlayTrigger.js +3 -3
- package/components/saveableInput/SaveableDateInput.d.ts +83 -0
- package/components/saveableInput/SaveableDateInput.js +122 -0
- package/components/selects/BaseSelectDropdown.js +1 -1
- package/components/selects/Multiselect.d.ts +8 -0
- package/components/selects/Multiselect.js +4 -4
- package/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
- package/components/smoothScrollbars/SmoothScrollbars.js +3 -3
- package/components/statsWidget/StatsWidget.d.ts +2 -2
- package/components/statsWidget/StatsWidgets.d.ts +2 -2
- package/components/svgImage/SvgElement.d.ts +8 -0
- package/components/svgImage/SvgElement.js +11 -0
- package/components/svgImage/SvgImage.d.ts +30 -0
- package/components/svgImage/SvgImage.js +20 -0
- package/components/svgImage/svgConverter.d.ts +17 -0
- package/components/svgImage/svgConverter.js +78 -0
- package/components/svgImage/useSvgLoader.d.ts +9 -0
- package/components/svgImage/useSvgLoader.js +43 -0
- package/components/switch/Switch.d.ts +4 -0
- package/components/switch/Switch.js +5 -6
- package/components/table/TableCardsSorting.d.ts +0 -1
- package/components/table/TableCol.d.ts +18 -0
- package/components/table/TableCol.js +11 -0
- package/components/table/TableHead.d.ts +33 -0
- package/components/table/TableHead.js +11 -0
- package/components/table/TableSettingsDialog.js +1 -1
- package/components/tag/Tag.js +1 -1
- package/components/timepicker/TimePicker.d.ts +1 -2
- package/components/timepicker/TimePicker.js +35 -8
- package/components/tooltip/SimpleTooltip.d.ts +1 -1
- package/components/virtualList/VirtualList.js +1 -1
- package/hooks/useIsFocusWithin.d.ts +33 -0
- package/hooks/useIsFocusWithin.js +55 -0
- package/hooks/useLocationSuggestions.d.ts +27 -0
- package/hooks/useLocationSuggestions.js +94 -0
- package/hooks/useOnboarding.d.ts +17 -5
- package/hooks/useOnboarding.js +7 -1
- package/hooks/usePostMessage.js +0 -1
- package/hooks/useSearch.d.ts +63 -0
- package/hooks/useSearch.js +73 -0
- package/hooks/useSorting.d.ts +6 -0
- package/hooks/useSorting.js +7 -4
- package/hooks/useTableExport.d.ts +49 -0
- package/hooks/useTableExport.js +57 -0
- package/hooks/useTableSelection.d.ts +166 -0
- package/hooks/useTableSelection.js +201 -0
- package/lib/es/BarList.d.ts +2 -0
- package/lib/es/BarList.js +7 -0
- package/lib/es/SaveableDateInput.d.ts +2 -0
- package/lib/es/SaveableDateInput.js +7 -0
- package/lib/es/SvgImage.d.ts +2 -0
- package/lib/es/SvgImage.js +7 -0
- package/lib/es/TableCol.d.ts +2 -0
- package/lib/es/TableCol.js +7 -0
- package/lib/es/TableHead.d.ts +2 -0
- package/lib/es/TableHead.js +7 -0
- package/lib/es/components/actionBarItem/ActionBarItemIcon.js +1 -1
- package/lib/es/components/actionBarItem/ActionBarOverlay.js +1 -1
- package/lib/es/components/activity/Activity.d.ts +2 -2
- package/lib/es/components/applicationHeader/CollapsedNavItem.js +1 -0
- package/lib/es/components/assetTree/Tree.d.ts +20 -0
- package/lib/es/components/assetTree/Tree.js +74 -37
- package/lib/es/components/assetTree/TreeLeaf.js +1 -1
- package/lib/es/components/assetTree/TreeNodeContainer.d.ts +1 -1
- package/lib/es/components/assetTree/TreeSearch.js +1 -1
- package/lib/es/components/assetTree/TreeSummary.js +1 -1
- package/lib/es/components/assetTree/TypeCounter.d.ts +2 -0
- package/lib/es/components/assetTree/TypeCounter.js +1 -1
- package/lib/es/components/assetTree/useTreeExpansion.d.ts +4 -0
- package/lib/es/components/assetTree/useTreeExpansion.js +29 -0
- package/lib/es/components/assetTree/useTreeHeight.d.ts +1 -0
- package/lib/es/components/assetTree/useTreeHeight.js +64 -0
- package/lib/es/components/assetTree/useTreeScrollPosition.d.ts +3 -0
- package/lib/es/components/assetTree/useTreeScrollPosition.js +23 -0
- package/lib/es/components/assetTree/useTreeVirtualization.d.ts +17 -0
- package/lib/es/components/assetTree/useTreeVirtualization.js +76 -0
- package/lib/es/components/autosuggest/AutoSuggest.js +2 -1
- package/lib/es/components/barList/BarList.d.ts +97 -0
- package/lib/es/components/barList/BarList.js +45 -0
- package/lib/es/components/barList/useSortedBars.d.ts +2 -0
- package/lib/es/components/barList/useSortedBars.js +17 -0
- package/lib/es/components/button/ButtonToolbar.d.ts +1 -1
- package/lib/es/components/button/ButtonToolbar.js +1 -1
- package/lib/es/components/button/ToggleButton.js +0 -1
- package/lib/es/components/charts/PieChart.js +1 -1
- package/lib/es/components/clearableInput/ClearableInput.d.ts +20 -7
- package/lib/es/components/clearableInput/ClearableInput.js +67 -7
- package/lib/es/components/dialog/Dialog.js +1 -1
- package/lib/es/components/dialog/FrameDialog.js +1 -1
- package/lib/es/components/dropdown/ButtonDropdown.d.ts +11 -3
- package/lib/es/components/dropdown/ButtonDropdown.js +79 -64
- package/lib/es/components/dropdown/DropdownToggleButton.d.ts +7 -4
- package/lib/es/components/dropdown/DropdownToggleButton.js +11 -3
- package/lib/es/components/formLabel/FormLabel.d.ts +2 -2
- package/lib/es/components/formLabel/FormLabel.js +1 -1
- package/lib/es/components/listMenu/ListMenu.js +4 -1
- package/lib/es/components/map/components/Map.js +20 -5
- package/lib/es/components/map/components/constants.d.ts +2 -0
- package/lib/es/components/map/components/constants.js +4 -1
- package/lib/es/components/map/components/features/basics/InfoBubble.js +1 -1
- package/lib/es/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
- package/lib/es/components/map/utils/mapTypes.d.ts +5 -0
- package/lib/es/components/map/utils/rendering.d.ts +5 -2
- package/lib/es/components/map/utils/rendering.js +46 -39
- package/lib/es/components/menuItems/MenuItem.js +1 -1
- package/lib/es/components/notification/Notification.js +1 -1
- package/lib/es/components/overlay/OverlayTrigger.js +3 -3
- package/lib/es/components/saveableInput/SaveableDateInput.d.ts +83 -0
- package/lib/es/components/saveableInput/SaveableDateInput.js +125 -0
- package/lib/es/components/selects/BaseSelectDropdown.js +1 -1
- package/lib/es/components/selects/Multiselect.d.ts +8 -0
- package/lib/es/components/selects/Multiselect.js +4 -4
- package/lib/es/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
- package/lib/es/components/smoothScrollbars/SmoothScrollbars.js +3 -3
- package/lib/es/components/statsWidget/StatsWidget.d.ts +2 -2
- package/lib/es/components/statsWidget/StatsWidgets.d.ts +2 -2
- package/lib/es/components/svgImage/SvgElement.d.ts +8 -0
- package/lib/es/components/svgImage/SvgElement.js +14 -0
- package/lib/es/components/svgImage/SvgImage.d.ts +30 -0
- package/lib/es/components/svgImage/SvgImage.js +23 -0
- package/lib/es/components/svgImage/svgConverter.d.ts +17 -0
- package/lib/es/components/svgImage/svgConverter.js +84 -0
- package/lib/es/components/svgImage/useSvgLoader.d.ts +9 -0
- package/lib/es/components/svgImage/useSvgLoader.js +48 -0
- package/lib/es/components/switch/Switch.d.ts +4 -0
- package/lib/es/components/switch/Switch.js +5 -6
- package/lib/es/components/table/TableCardsSorting.d.ts +0 -1
- package/lib/es/components/table/TableCol.d.ts +18 -0
- package/lib/es/components/table/TableCol.js +13 -0
- package/lib/es/components/table/TableHead.d.ts +33 -0
- package/lib/es/components/table/TableHead.js +14 -0
- package/lib/es/components/table/TableSettingsDialog.js +1 -1
- package/lib/es/components/tag/Tag.js +1 -1
- package/lib/es/components/timepicker/TimePicker.d.ts +1 -2
- package/lib/es/components/timepicker/TimePicker.js +35 -8
- package/lib/es/components/tooltip/SimpleTooltip.d.ts +1 -1
- package/lib/es/components/virtualList/VirtualList.js +1 -1
- package/lib/es/hooks/useIsFocusWithin.d.ts +33 -0
- package/lib/es/hooks/useIsFocusWithin.js +57 -0
- package/lib/es/hooks/useLocationSuggestions.d.ts +27 -0
- package/lib/es/hooks/useLocationSuggestions.js +97 -0
- package/lib/es/hooks/useOnboarding.d.ts +17 -5
- package/lib/es/hooks/useOnboarding.js +7 -1
- package/lib/es/hooks/usePostMessage.js +0 -1
- package/lib/es/hooks/useSearch.d.ts +63 -0
- package/lib/es/hooks/useSearch.js +75 -0
- package/lib/es/hooks/useSorting.d.ts +6 -0
- package/lib/es/hooks/useSorting.js +7 -4
- package/lib/es/hooks/useTableExport.d.ts +49 -0
- package/lib/es/hooks/useTableExport.js +59 -0
- package/lib/es/hooks/useTableSelection.d.ts +166 -0
- package/lib/es/hooks/useTableSelection.js +210 -0
- package/lib/es/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
- package/lib/es/useIsFocusWithin.d.ts +2 -0
- package/lib/es/useIsFocusWithin.js +7 -0
- package/lib/es/useLocationSuggestions.d.ts +2 -0
- package/lib/es/useLocationSuggestions.js +7 -0
- package/lib/es/useSearch.d.ts +2 -0
- package/lib/es/useSearch.js +7 -0
- package/lib/es/useTableExport.d.ts +2 -0
- package/lib/es/useTableExport.js +7 -0
- package/lib/es/useTableSelection.d.ts +2 -0
- package/lib/es/useTableSelection.js +7 -0
- package/lib/es/utils/storageUtils.d.ts +2 -2
- package/lib/es/utils/storageUtils.js +2 -0
- package/lib/es/utils/urlFeatureToggles.d.ts +12 -6
- package/lib/es/utils/urlFeatureToggles.js +14 -8
- package/lib/es/utils/useDropDirection.js +1 -0
- package/lib/es/version.json +1 -1
- package/package.json +48 -40
- package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
- package/useIsFocusWithin.d.ts +2 -0
- package/useIsFocusWithin.js +2 -0
- package/useLocationSuggestions.d.ts +2 -0
- package/useLocationSuggestions.js +2 -0
- package/useSearch.d.ts +2 -0
- package/useSearch.js +2 -0
- package/useTableExport.d.ts +2 -0
- package/useTableExport.js +2 -0
- package/useTableSelection.d.ts +2 -0
- package/useTableSelection.js +2 -0
- package/utils/storageUtils.d.ts +2 -2
- package/utils/storageUtils.js +2 -0
- package/utils/urlFeatureToggles.d.ts +12 -6
- package/utils/urlFeatureToggles.js +10 -7
- package/utils/useDropDirection.js +1 -0
- 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;
|
package/hooks/useOnboarding.d.ts
CHANGED
|
@@ -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: () =>
|
|
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: () =>
|
|
111
|
-
hasPreviousStep: () =>
|
|
122
|
+
hasNextStep: () => boolean;
|
|
123
|
+
hasPreviousStep: () => boolean;
|
|
112
124
|
isFirstStep: () => boolean;
|
|
113
125
|
isLastStep: () => boolean;
|
|
114
126
|
getActiveIndex: () => number | undefined;
|
package/hooks/useOnboarding.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
package/hooks/usePostMessage.js
CHANGED
|
@@ -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;
|
package/hooks/useSorting.d.ts
CHANGED
|
@@ -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
|
package/hooks/useSorting.js
CHANGED
|
@@ -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
|
-
|
|
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;
|