@rio-cloud/rio-uikit 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.DS_Store +0 -0
  2. package/BarList.d.ts +2 -0
  3. package/BarList.js +2 -0
  4. package/SaveableDateInput.d.ts +2 -0
  5. package/SaveableDateInput.js +2 -0
  6. package/components/activity/Activity.d.ts +2 -2
  7. package/components/assetTree/Tree.d.ts +12 -0
  8. package/components/assetTree/Tree.js +72 -37
  9. package/components/assetTree/TreeNodeContainer.d.ts +1 -1
  10. package/components/assetTree/useTreeExpansion.d.ts +4 -0
  11. package/components/assetTree/useTreeExpansion.js +25 -0
  12. package/components/assetTree/useTreeHeight.d.ts +1 -0
  13. package/components/assetTree/useTreeHeight.js +60 -0
  14. package/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  15. package/components/assetTree/useTreeScrollPosition.js +19 -0
  16. package/components/assetTree/useTreeVirtualization.d.ts +17 -0
  17. package/components/assetTree/useTreeVirtualization.js +71 -0
  18. package/components/barList/BarList.d.ts +97 -0
  19. package/components/barList/BarList.js +42 -0
  20. package/components/barList/useSortedBars.d.ts +2 -0
  21. package/components/barList/useSortedBars.js +14 -0
  22. package/components/charts/PieChart.js +1 -1
  23. package/components/clearableInput/ClearableInput.js +1 -1
  24. package/components/formLabel/FormLabel.d.ts +2 -2
  25. package/components/listMenu/ListMenu.js +3 -1
  26. package/components/map/components/Map.js +20 -5
  27. package/components/map/components/constants.d.ts +2 -0
  28. package/components/map/components/constants.js +3 -0
  29. package/components/map/utils/mapTypes.d.ts +5 -0
  30. package/components/map/utils/rendering.d.ts +5 -2
  31. package/components/map/utils/rendering.js +46 -39
  32. package/components/overlay/OverlayTrigger.js +2 -2
  33. package/components/saveableInput/SaveableDateInput.d.ts +83 -0
  34. package/components/saveableInput/SaveableDateInput.js +122 -0
  35. package/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  36. package/components/smoothScrollbars/SmoothScrollbars.js +2 -2
  37. package/components/statsWidget/StatsWidget.d.ts +2 -2
  38. package/components/statsWidget/StatsWidgets.d.ts +2 -2
  39. package/components/svgImage/SvgImage.d.ts +1 -1
  40. package/components/svgImage/SvgImage.js +1 -1
  41. package/components/table/TableCol.d.ts +1 -1
  42. package/components/table/TableCol.js +2 -2
  43. package/components/table/TableHead.js +2 -2
  44. package/components/tooltip/SimpleTooltip.d.ts +1 -1
  45. package/hooks/useIsFocusWithin.d.ts +33 -0
  46. package/hooks/useIsFocusWithin.js +55 -0
  47. package/hooks/useTableExport.d.ts +49 -0
  48. package/hooks/useTableExport.js +57 -0
  49. package/hooks/useTableSelection.d.ts +15 -0
  50. package/hooks/useTableSelection.js +6 -1
  51. package/lib/es/BarList.d.ts +2 -0
  52. package/lib/es/BarList.js +7 -0
  53. package/lib/es/SaveableDateInput.d.ts +2 -0
  54. package/lib/es/SaveableDateInput.js +7 -0
  55. package/lib/es/components/activity/Activity.d.ts +2 -2
  56. package/lib/es/components/assetTree/Tree.d.ts +12 -0
  57. package/lib/es/components/assetTree/Tree.js +71 -36
  58. package/lib/es/components/assetTree/TreeNodeContainer.d.ts +1 -1
  59. package/lib/es/components/assetTree/useTreeExpansion.d.ts +4 -0
  60. package/lib/es/components/assetTree/useTreeExpansion.js +29 -0
  61. package/lib/es/components/assetTree/useTreeHeight.d.ts +1 -0
  62. package/lib/es/components/assetTree/useTreeHeight.js +64 -0
  63. package/lib/es/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  64. package/lib/es/components/assetTree/useTreeScrollPosition.js +23 -0
  65. package/lib/es/components/assetTree/useTreeVirtualization.d.ts +17 -0
  66. package/lib/es/components/assetTree/useTreeVirtualization.js +76 -0
  67. package/lib/es/components/barList/BarList.d.ts +97 -0
  68. package/lib/es/components/barList/BarList.js +45 -0
  69. package/lib/es/components/barList/useSortedBars.d.ts +2 -0
  70. package/lib/es/components/barList/useSortedBars.js +17 -0
  71. package/lib/es/components/charts/PieChart.js +1 -1
  72. package/lib/es/components/clearableInput/ClearableInput.js +1 -1
  73. package/lib/es/components/formLabel/FormLabel.d.ts +2 -2
  74. package/lib/es/components/listMenu/ListMenu.js +3 -1
  75. package/lib/es/components/map/components/Map.js +19 -4
  76. package/lib/es/components/map/components/constants.d.ts +2 -0
  77. package/lib/es/components/map/components/constants.js +4 -1
  78. package/lib/es/components/map/utils/mapTypes.d.ts +5 -0
  79. package/lib/es/components/map/utils/rendering.d.ts +5 -2
  80. package/lib/es/components/map/utils/rendering.js +46 -39
  81. package/lib/es/components/overlay/OverlayTrigger.js +2 -2
  82. package/lib/es/components/saveableInput/SaveableDateInput.d.ts +83 -0
  83. package/lib/es/components/saveableInput/SaveableDateInput.js +125 -0
  84. package/lib/es/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  85. package/lib/es/components/smoothScrollbars/SmoothScrollbars.js +2 -2
  86. package/lib/es/components/statsWidget/StatsWidget.d.ts +2 -2
  87. package/lib/es/components/statsWidget/StatsWidgets.d.ts +2 -2
  88. package/lib/es/components/svgImage/SvgImage.d.ts +1 -1
  89. package/lib/es/components/svgImage/SvgImage.js +1 -3
  90. package/lib/es/components/table/TableCol.d.ts +1 -1
  91. package/lib/es/components/table/TableCol.js +2 -2
  92. package/lib/es/components/table/TableHead.js +2 -2
  93. package/lib/es/components/tooltip/SimpleTooltip.d.ts +1 -1
  94. package/lib/es/hooks/useIsFocusWithin.d.ts +33 -0
  95. package/lib/es/hooks/useIsFocusWithin.js +57 -0
  96. package/lib/es/hooks/useTableExport.d.ts +49 -0
  97. package/lib/es/hooks/useTableExport.js +59 -0
  98. package/lib/es/hooks/useTableSelection.d.ts +15 -0
  99. package/lib/es/hooks/useTableSelection.js +6 -1
  100. package/lib/es/useIsFocusWithin.d.ts +2 -0
  101. package/lib/es/useIsFocusWithin.js +7 -0
  102. package/lib/es/useTableExport.d.ts +2 -0
  103. package/lib/es/useTableExport.js +7 -0
  104. package/lib/es/version.json +1 -1
  105. package/package.json +8 -7
  106. package/useIsFocusWithin.d.ts +2 -0
  107. package/useIsFocusWithin.js +2 -0
  108. package/useTableExport.d.ts +2 -0
  109. package/useTableExport.js +2 -0
  110. package/version.json +1 -1
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTreeScrollPosition = void 0;
4
+ const react_1 = require("react");
5
+ const useTreeScrollPosition = (virtualizer, scrollElementRef) => {
6
+ const scrollOffsetRef = (0, react_1.useRef)(0);
7
+ const scrollToTop = (0, react_1.useCallback)(() => {
8
+ if (scrollElementRef.current) {
9
+ requestAnimationFrame(() => {
10
+ // Reset scroll position to top
11
+ scrollElementRef.current.scrollTop(0);
12
+ // Also reset the stored scroll offset
13
+ scrollOffsetRef.current = 0;
14
+ // Force virtualizer to sync
15
+ if (virtualizer) {
16
+ virtualizer.scrollToOffset(0);
17
+ }
18
+ });
19
+ }
20
+ }, [scrollElementRef, virtualizer]);
21
+ return { scrollToTop };
22
+ };
23
+ exports.useTreeScrollPosition = useTreeScrollPosition;
@@ -0,0 +1,17 @@
1
+ import type { TreeItem, GroupedItem } from './Tree';
2
+ type VirtualizedItem = {
3
+ type: 'group';
4
+ data: GroupedItem;
5
+ id: string;
6
+ isExpanded: boolean;
7
+ } | {
8
+ type: 'leaf';
9
+ data: TreeItem;
10
+ id: string;
11
+ groupId: string;
12
+ };
13
+ export declare const useTreeVirtualization: (groupedItems: GroupedItem[], flatItems: TreeItem[], hasSearchValue: boolean, hasGroups: boolean, internalExpandedGroups: string[] | undefined, scrollElementRef: React.RefObject<HTMLDivElement>, overscan: number) => {
14
+ virtualizedItems: VirtualizedItem[];
15
+ virtualizer: import("@tanstack/virtual-core").Virtualizer<any, Element>;
16
+ };
17
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTreeVirtualization = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = require("react");
6
+ const map_1 = tslib_1.__importDefault(require("lodash/fp/map"));
7
+ const react_virtual_1 = require("@tanstack/react-virtual");
8
+ const useTreeVirtualization = (groupedItems, flatItems, hasSearchValue, hasGroups, internalExpandedGroups, scrollElementRef, overscan) => {
9
+ const virtualizedItems = (0, react_1.useMemo)(() => {
10
+ // When there's a search value, always show flat items (no groups)
11
+ if (hasSearchValue) {
12
+ return flatItems.map((item) => ({
13
+ type: 'leaf',
14
+ data: item,
15
+ id: item.id,
16
+ }));
17
+ }
18
+ // Virtualize grouped list, when there's no search value and we have groups
19
+ if (hasGroups) {
20
+ const flatList = [];
21
+ (0, map_1.default)((group) => {
22
+ const isExpanded = internalExpandedGroups?.includes(group.id) ?? false;
23
+ // Add the group header
24
+ flatList.push({
25
+ type: 'group',
26
+ data: group,
27
+ id: group.id,
28
+ isExpanded,
29
+ });
30
+ // Add expanded items
31
+ if (isExpanded) {
32
+ group.items.forEach((item) => {
33
+ flatList.push({
34
+ type: 'leaf',
35
+ data: item,
36
+ id: item.id,
37
+ groupId: group.id,
38
+ });
39
+ });
40
+ }
41
+ })(groupedItems);
42
+ return flatList;
43
+ }
44
+ // Virtualize flat list when no groups are provided initially
45
+ return flatItems.map((item) => ({
46
+ type: 'leaf',
47
+ data: item,
48
+ id: item.id,
49
+ }));
50
+ }, [groupedItems, flatItems, hasSearchValue, hasGroups, internalExpandedGroups]);
51
+ const virtualizer = (0, react_virtual_1.useVirtualizer)({
52
+ count: virtualizedItems.length,
53
+ // getScrollElement: () => scrollElementRef.current,
54
+ getScrollElement: () => {
55
+ // For SmoothScrollbars, we need to get the actual scroll container
56
+ if (scrollElementRef.current) {
57
+ // SmoothScrollbars exposes the scroll container through its view
58
+ const scrollbarsInstance = scrollElementRef.current;
59
+ // Access the internal scroll container
60
+ // This depends on how react-custom-scrollbars-2 exposes its internals
61
+ return scrollbarsInstance?.view;
62
+ }
63
+ return null;
64
+ },
65
+ estimateSize: () => 41, // typical single line height without line-break
66
+ measureElement: element => {
67
+ // This will measure the actual rendered height for more accuracy
68
+ return element?.children[0].clientHeight ?? 41;
69
+ },
70
+ overscan, // Render 10 extra items above and below visible area
71
+ // Add this to enable more aggressive remeasurement
72
+ lanes: 1,
73
+ });
74
+ return { virtualizedItems, virtualizer };
75
+ };
76
+ exports.useTreeVirtualization = useTreeVirtualization;
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+ import { type SortDirectionType } from '../../utils/SortUtils';
3
+ export type BarListRow<T> = T & {
4
+ key?: string;
5
+ href?: string;
6
+ value: number;
7
+ name: string;
8
+ color?: string;
9
+ barColor?: string;
10
+ background?: string;
11
+ };
12
+ /**
13
+ * Props for the BarList component.
14
+ *
15
+ * @template T - The type of the custom data associated with each bar row.
16
+ */
17
+ type BarListProps<T = unknown> = React.HTMLAttributes<HTMLDivElement> & {
18
+ /**
19
+ * Array of bar row data to be rendered.
20
+ */
21
+ data: BarListRow<T>[];
22
+ /**
23
+ * Optional function to format the numeric value displayed on the right side of each bar.
24
+ * Can return a string or a React element.
25
+ *
26
+ * @example
27
+ * valueFormatter={(value) => `${value}%`}
28
+ */
29
+ valueFormatter?: (value: number) => string | React.ReactElement;
30
+ /**
31
+ * A reference value used to calculate relative widths.
32
+ * If not provided, the maximum value in `data` will be used.
33
+ *
34
+ * @default max(data.value)
35
+ */
36
+ referenceValue?: number;
37
+ /**
38
+ * Whether to animate the bar width transitions using Framer Motion.
39
+ *
40
+ * @default false
41
+ */
42
+ showAnimation?: boolean;
43
+ /**
44
+ * Callback fired when a bar is clicked.
45
+ *
46
+ * @param payload - The full data object of the clicked bar.
47
+ */
48
+ onSelectRow?: (payload: BarListRow<T>) => void;
49
+ /**
50
+ * The sort order for the bars. Options are 'asc', 'desc', or 'none'.
51
+ *
52
+ * @default 'none'
53
+ */
54
+ sortOrder?: SortDirectionType | 'none';
55
+ /**
56
+ * Height of each bar row in pixels.
57
+ *
58
+ * @default 32
59
+ */
60
+ rowHeight?: number;
61
+ /**
62
+ * Opacity applied to non-hovered bars (between 0 and 1).
63
+ *
64
+ * @default 0.5
65
+ */
66
+ opacity?: number;
67
+ /**
68
+ * CSS color string used for the active/progress portion of each bar.
69
+ *
70
+ * @default 'bg-highlight-light'
71
+ */
72
+ barColor?: string;
73
+ /**
74
+ * CSS color string used for the text labels.
75
+ *
76
+ * @default 'text-color-darker'
77
+ */
78
+ labelColor?: string;
79
+ /**
80
+ * CSS color string used for the bar background.
81
+ *
82
+ * @default 'bg-transparent'
83
+ */
84
+ background?: string;
85
+ /**
86
+ * Additional className added to the wrapper element.
87
+ */
88
+ className?: string;
89
+ };
90
+ declare const BarListInner: {
91
+ <T>(props: BarListProps<T>, forwardedRef: React.ForwardedRef<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
92
+ displayName: string;
93
+ };
94
+ declare const BarList: <T>(props: BarListProps<T> & {
95
+ ref?: React.ForwardedRef<HTMLDivElement>;
96
+ }) => ReturnType<typeof BarListInner>;
97
+ export default BarList;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = tslib_1.__importStar(require("react"));
6
+ const classnames_1 = tslib_1.__importDefault(require("classnames"));
7
+ const framer_motion_1 = require("framer-motion");
8
+ const SortUtils_1 = require("../../utils/SortUtils");
9
+ const useSortedBars_1 = require("./useSortedBars");
10
+ // Animation variants
11
+ const containerVariants = {
12
+ animate: {
13
+ transition: {
14
+ staggerChildren: 0.1,
15
+ },
16
+ },
17
+ };
18
+ const barVariants = {
19
+ initial: { width: 0 },
20
+ animate: (width) => ({
21
+ width: `${width}%`,
22
+ transition: { duration: 0.8, ease: 'easeOut' },
23
+ }),
24
+ };
25
+ const DEFAULT_ROW_HEIGHT = 25;
26
+ const DEFAULT_OPACITY = 0.5;
27
+ const BarListInner = (props, forwardedRef) => {
28
+ const { data = [], valueFormatter = value => value.toString(), showAnimation = false, onSelectRow, referenceValue, sortOrder = SortUtils_1.SortDirection.DESCENDING, barColor = 'bg-highlight-light', labelColor = 'text-color-darker', background = 'bg-transparent', rowHeight = DEFAULT_ROW_HEIGHT, opacity = DEFAULT_OPACITY, className = '', ...remainingProps } = props;
29
+ const sortedData = (0, useSortedBars_1.useSortedBars)(data, sortOrder, item => item.value);
30
+ const [hoveredIndex, setHoveredIndex] = react_1.default.useState(null);
31
+ const widths = (0, react_1.useMemo)(() => {
32
+ const base = referenceValue ?? Math.max(...sortedData.map(item => item.value), 0);
33
+ return sortedData.map(item => (base === 0 || item.value === 0 ? 0 : Math.max((item.value / base) * 100, 2)));
34
+ }, [sortedData, referenceValue]);
35
+ return ((0, jsx_runtime_1.jsxs)("div", { ...remainingProps, ref: forwardedRef, className: (0, classnames_1.default)('display-flex justify-content-between gap-15', className), children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { variants: showAnimation ? containerVariants : undefined, initial: 'initial', animate: 'animate', className: 'width-100pct space-y-5', children: sortedData.map((item, index) => {
36
+ const width = widths[index];
37
+ const itemLabelColor = item.color ?? labelColor;
38
+ const itemBarColor = item.barColor ?? barColor;
39
+ const itemBackground = item.background ?? background;
40
+ return ((0, jsx_runtime_1.jsxs)("div", { onMouseEnter: () => setHoveredIndex(index), onMouseLeave: () => setHoveredIndex(null), onClick: () => onSelectRow?.(item), className: (0, classnames_1.default)('position-relative width-100pct rounded-small', 'transition-all transition-ease-in-out transition-duration-01', itemBackground, onSelectRow && 'cursor-pointer', hoveredIndex === index && 'bg-lightest'), children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { custom: width, variants: showAnimation ? barVariants : undefined, className: (0, classnames_1.default)('display-flex align-items-center rounded-small', 'transition-all transition-ease-in-out transition-duration-01', itemBarColor), style: { height: `${rowHeight}px`, opacity: hoveredIndex === index ? 1 : opacity }, role: 'presentation' }), (0, jsx_runtime_1.jsx)("div", { className: 'position-absolute left-0 top-50pct translate-y-50pct display-flex width-100pct padding-left-10', children: item.href ? ((0, jsx_runtime_1.jsx)("a", { href: item.href, className: itemLabelColor, target: '_blank', rel: 'noreferrer', onClick: event => event.stopPropagation(), children: item.name })) : ((0, jsx_runtime_1.jsx)("div", { className: itemLabelColor, children: item.name })) })] }, item.key ?? item.name));
41
+ }) }), (0, jsx_runtime_1.jsx)("div", { className: 'space-y-5', children: sortedData.map(item => ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('display-flex align-items-center justify-content-end'), style: { height: `${rowHeight}px` }, children: (0, jsx_runtime_1.jsx)("div", { className: 'text-color-darkest', children: valueFormatter(item.value) }) }, item.key ?? item.name))) })] }));
42
+ };
43
+ BarListInner.displayName = 'BarList';
44
+ const BarList = react_1.default.forwardRef(BarListInner);
45
+ exports.default = BarList;
@@ -0,0 +1,2 @@
1
+ import { type SortDirectionType } from '../../utils/SortUtils';
2
+ export declare function useSortedBars<T>(data: T[], sortOrder: SortDirectionType | 'none', getValue: (item: T) => number): T[];
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSortedBars = useSortedBars;
4
+ const react_1 = require("react");
5
+ const SortUtils_1 = require("../../utils/SortUtils");
6
+ function useSortedBars(data, sortOrder, getValue) {
7
+ return (0, react_1.useMemo)(() => {
8
+ if (sortOrder === 'none') {
9
+ return data;
10
+ }
11
+ return [...data].sort((a, b) => {
12
+ const aVal = getValue(a);
13
+ const bVal = getValue(b);
14
+ return sortOrder === SortUtils_1.SortDirection.ASCENDING ? aVal - bVal : bVal - aVal;
15
+ });
16
+ }, [data, sortOrder, getValue]);
17
+ }
@@ -17,7 +17,7 @@ const renderCustomInnerLabel = (dataUnit) => ({ cx, cy, midAngle, innerRadius, o
17
17
  };
18
18
  const PieChart = (props) => {
19
19
  const { width, height, innerRadius, outerRadius, data = [], dataKey = 'value', dataUnit = '', nameKey = 'name', color, filled = false, labels = true, innerLabels = false, paddingAngle = 3, legend = (0, jsx_runtime_1.jsx)(recharts_1.Legend, {}), tooltip = true, pieOptions, containerOptions, ...remainingProps } = props;
20
- // biome-ignore lint/suspicious/noExplicitAny:
20
+ // biome-ignore lint/suspicious/noExplicitAny: unknown type
21
21
  const renderLabels = (entry) => `${(0, isFunction_1.default)(dataKey) ? dataKey(entry) : entry[dataKey]} ${dataUnit}`;
22
22
  const pieLabel = labels && (innerLabels ? renderCustomInnerLabel(dataUnit) : renderLabels);
23
23
  const tooltipProps = (0, isObject_1.default)(tooltip) ? tooltip.props : {};
@@ -140,7 +140,7 @@ const ClearableInput = (0, react_1.forwardRef)((props, ref) => {
140
140
  maxLength: hasMask ? undefined : maxLength,
141
141
  tabIndex,
142
142
  };
143
- const input = hasMask ? ((0, jsx_runtime_1.jsx)(react_imask_1.IMaskInput, { ...inputProps, ref: mergedInternalMaskRef, mask: mask, placeholderChar: maskPlaceholder, onAccept: handleAccept, lazy: !shouldShowMask(), overwrite: true })) : ((0, jsx_runtime_1.jsx)("input", { ...inputProps, ref: inputRef || ref }));
143
+ const input = hasMask ? ((0, jsx_runtime_1.jsx)(react_imask_1.IMaskInput, { ...inputProps, inputRef: mergedInternalMaskRef, mask: mask, placeholderChar: maskPlaceholder, onAccept: handleAccept, lazy: !shouldShowMask(), overwrite: true })) : ((0, jsx_runtime_1.jsx)("input", { ...inputProps, ref: inputRef || ref }));
144
144
  return ((0, jsx_runtime_1.jsxs)("div", { className: classes, children: [children && (0, isFunction_1.default)(children) ? children(inputProps) : input, (0, jsx_runtime_1.jsx)("span", { className: clearButtonClassNames, onClick: clearInputValue, children: (0, jsx_runtime_1.jsx)("span", { className: 'clearButtonIcon rioglyph rioglyph-remove-sign' }) })] }));
145
145
  });
146
146
  exports.default = ClearableInput;
@@ -1,9 +1,9 @@
1
- import { type PropsWithChildren, type ComponentProps } from 'react';
1
+ import React, { type PropsWithChildren, type ComponentProps } from 'react';
2
2
  export type FormLabelProps = ComponentProps<'label'> & {
3
3
  /**
4
4
  * Additional supporting text displayed next to the label.
5
5
  */
6
- supportingText?: string;
6
+ supportingText?: string | React.ReactElement;
7
7
  /**
8
8
  * Additional classes set to the outer element.
9
9
  */
@@ -77,7 +77,9 @@ const ListMenu = (props) => {
77
77
  }
78
78
  };
79
79
  const formClassNames = (0, classnames_1.default)('form-group', 'margin-bottom-5', 'padding-left-15', 'padding-right-15', 'padding-bottom-15', 'position-sticky', 'top-0', 'z-index-1');
80
- const listMenu = ((0, jsx_runtime_1.jsxs)("div", { ...remainingProps, className: `ListMenu ${className} ${filterValue ? 'filtered' : ''}`, ref: listRef, children: [enableFilter && ((0, jsx_runtime_1.jsx)("div", { className: formClassNames, children: (0, jsx_runtime_1.jsxs)("div", { className: 'input-group width-100pct', children: [(0, jsx_runtime_1.jsx)("span", { className: 'input-group-addon', children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-search', "aria-hidden": 'true' }) }), (0, jsx_runtime_1.jsx)(ClearableInput_1.default, { value: filterValue, inputRef: inputRef, placeholder: filterPlaceholder, onChange: handleFilterChange, onClear: handleClear }), trailingInputAddon && trailingInputAddon] }) })), !hasMenuItems(filteredMenuItems) && ((0, jsx_runtime_1.jsx)("div", { className: 'padding-top-25 text-center text-color-gray', children: notFoundMessage })), filteredMenuItems.map(menuGroup => ((0, jsx_runtime_1.jsx)(ListMenuGroup_1.default, { className: groupClassName, menuGroup: menuGroup }, crypto.randomUUID())))] }));
80
+ const listMenu = ((0, jsx_runtime_1.jsxs)("div", { ...remainingProps, className: `ListMenu ${className} ${filterValue ? 'filtered' : ''}`, ref: listRef, children: [enableFilter && ((0, jsx_runtime_1.jsx)("div", { className: formClassNames, children: (0, jsx_runtime_1.jsxs)("div", { className: 'input-group width-100pct', children: [(0, jsx_runtime_1.jsx)("span", { className: 'input-group-addon', children: (0, jsx_runtime_1.jsx)("span", { className: 'rioglyph rioglyph-search', "aria-hidden": 'true' }) }), (0, jsx_runtime_1.jsx)(ClearableInput_1.default, { value: filterValue, inputRef: inputRef, placeholder: filterPlaceholder, onChange: handleFilterChange, onClear: handleClear }), trailingInputAddon && trailingInputAddon] }) })), !hasMenuItems(filteredMenuItems) && ((0, jsx_runtime_1.jsx)("div", { className: 'padding-top-25 text-center text-color-gray', children: notFoundMessage })), filteredMenuItems.map((menuGroup, index) => (
81
+ // biome-ignore lint/suspicious/noArrayIndexKey: using a random key would re-render the list every time the parent updates
82
+ (0, jsx_runtime_1.jsx)(ListMenuGroup_1.default, { className: groupClassName, menuGroup: menuGroup }, index)))] }));
81
83
  if (responsive && isMobileMode) {
82
84
  return ((0, jsx_runtime_1.jsx)(ExpanderPanel_1.default, { title: mobileHeader, bsStyle: 'default', open: isExpanderOpen, onToggle: () => setIsExpanderOpen(!isExpanderOpen), unmountOnExit: false, className: 'shadow-default', children: (0, jsx_runtime_1.jsx)("div", { onClick: handleExpanderBodyClick, children: listMenu }) }));
83
85
  }
@@ -19,7 +19,13 @@ const MapElements_1 = tslib_1.__importDefault(require("./MapElements"));
19
19
  const rendering_1 = require("../utils/rendering");
20
20
  // biome-ignore lint/suspicious/noShadowRestrictedNames: <explanation>
21
21
  const Map = (props) => {
22
- const { children, credentials, width, height, language: lang = 'en', center, zoom, zoomAnimation = false, boundingBox, hideClusterSettings = false, hideMapLayerSettings = false, disableMapEvents, disableBehavior = false, eventListenerMap, mapType = constants_1.MAP_TYPE_DEFAULT, mapLayer = [], showCluster: externalShowCluster = true, showScaleBar = false, onMapLayerChange = () => { }, onMapTypeChange = () => { }, onShowClusterChange = () => { }, onZoomIn = () => { }, onZoomOut = () => { }, onIncidentsChange = () => { }, mapSettingsTooltip, mapSettings, enableWebGL = true, enableDevicePixelRatio = true, } = props;
22
+ const { children, credentials, width, height, language: lang = 'en', center, zoom, zoomAnimation = false, boundingBox, hideClusterSettings = false, hideMapLayerSettings = false, disableMapEvents, disableBehavior = false, disableZoomMomentum = true, eventListenerMap, mapType = constants_1.MAP_TYPE_DEFAULT, mapLayer = [], showCluster: externalShowCluster = true, showScaleBar = false, onMapLayerChange = () => { }, onMapTypeChange = () => { }, onShowClusterChange = () => { }, onZoomIn = () => { }, onZoomOut = () => { }, onIncidentsChange = () => { }, mapSettingsTooltip, mapSettings, enableWebGL = true, enableDevicePixelRatio = true, minZoom = constants_1.DEFAULT_MIN_ZOOM, maxZoom = constants_1.DEFAULT_MAX_ZOOM, } = props;
23
+ let safeMaxZoom = maxZoom;
24
+ if (minZoom > maxZoom) {
25
+ // Avoid crashing the map for invalid zoom limits
26
+ safeMaxZoom = constants_1.DEFAULT_MAX_ZOOM;
27
+ console.error('Invalid condition for zoom limits: min <= max)');
28
+ }
23
29
  const mapRef = (0, react_1.useRef)(null);
24
30
  const [isMapInitialized, setMapInitialized] = (0, react_1.useState)(false);
25
31
  const [api, setApi] = (0, react_1.useState)();
@@ -58,6 +64,8 @@ const Map = (props) => {
58
64
  engineType,
59
65
  vehicleRestrictions: activeLayers.includes(constants_1.MAP_LAYER_ROAD_RESTRICTIONS),
60
66
  language,
67
+ minZoom,
68
+ maxZoom: safeMaxZoom,
61
69
  });
62
70
  // Initialize the map
63
71
  const hereMap = new H.Map(mapRef.current, defaultLayerMap.baseLayer, {
@@ -68,8 +76,8 @@ const Map = (props) => {
68
76
  pixelRatio: devicePixelRatio,
69
77
  fixedCenter: true,
70
78
  });
71
- // Render street labels and road signs as well as additional pois as vector data
72
79
  if (defaultLayerMap.overlayLayer) {
80
+ // Special case for satellite map where we render street labels and road signs as well as additional pois as vector data
73
81
  hereMap.addLayer(defaultLayerMap.overlayLayer);
74
82
  }
75
83
  setMapInitialized(true);
@@ -79,11 +87,16 @@ const Map = (props) => {
79
87
  if (!disableMapEvents) {
80
88
  hereMapEvents = new H.mapevents.MapEvents(hereMap);
81
89
  }
82
- // Enable map interaction (pan, zoom, pinch-to-zoom)
83
90
  if (!(disableMapEvents || disableBehavior)) {
84
91
  hereBehavior = new H.mapevents.Behavior(hereMapEvents);
85
92
  // @ts-ignore-next-line
86
93
  hereBehavior.disable(H.mapevents.Behavior.Feature.FRACTIONAL_ZOOM);
94
+ if (disableZoomMomentum) {
95
+ // Disable the inertia that occurs on WebGL maps when scrolling/zooming.
96
+ // This resulted in a very high scroll sensitivity.
97
+ // @ts-ignore-next-line
98
+ hereBehavior.disable(H.mapevents.Behavior.Feature.ZOOM_MOMENTUM);
99
+ }
87
100
  }
88
101
  (0, eventHandling_1.addEventListenerMap)(hereMap, eventListenerMap, hereMap);
89
102
  const hereUi = (0, mapUi_1.getHereUi)(hereMap, defaultLayers, showScaleBar, language);
@@ -105,6 +118,8 @@ const Map = (props) => {
105
118
  baseLayer,
106
119
  activeLayers,
107
120
  showCluster,
121
+ minZoom,
122
+ maxZoom: safeMaxZoom,
108
123
  },
109
124
  });
110
125
  // If the base layer changed, re-add all previous objects again,
@@ -121,7 +136,7 @@ const Map = (props) => {
121
136
  hereMap.dispose();
122
137
  }
123
138
  };
124
- }, [enableWebGL, enableDevicePixelRatio, language, baseLayer]);
139
+ }, [enableWebGL, enableDevicePixelRatio, language, baseLayer, minZoom, maxZoom]);
125
140
  const isDarkMode = (0, useDarkMode_1.default)();
126
141
  (0, react_1.useEffect)(() => {
127
142
  // Toggle night map only if current map type is default
@@ -15,3 +15,5 @@ export declare const ENGINE_TYPE_HARP: any;
15
15
  export declare const ENGINE_TYPE_P2D = H.Map.EngineType.P2D;
16
16
  export declare const DEFAULT_TILE_SIZE = 512;
17
17
  export declare const DEFAULT_RASTER_LAYER_FORMAT = "png";
18
+ export declare const DEFAULT_MIN_ZOOM = 3;
19
+ export declare const DEFAULT_MAX_ZOOM = 20;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_RASTER_LAYER_FORMAT = exports.DEFAULT_TILE_SIZE = exports.ENGINE_TYPE_P2D = exports.ENGINE_TYPE_HARP = exports.NO_CREDENTIALS_ERROR_MESSAGE = exports.TILE_TYPE = exports.TILE_SIZE = exports.FORMAT = exports.MAP_LAYER_ROAD_RESTRICTIONS = exports.MAP_LAYER_TRAFFIC = exports.MAP_LAYER_INCIDENTS = exports.MAP_TYPE_NIGHT = exports.MAP_TYPE_TERRAIN = exports.MAP_TYPE_SATELLITE = exports.MAP_TYPE_FLEET_STYLE = exports.MAP_TYPE_DEFAULT = void 0;
3
+ exports.DEFAULT_MAX_ZOOM = exports.DEFAULT_MIN_ZOOM = exports.DEFAULT_RASTER_LAYER_FORMAT = exports.DEFAULT_TILE_SIZE = exports.ENGINE_TYPE_P2D = exports.ENGINE_TYPE_HARP = exports.NO_CREDENTIALS_ERROR_MESSAGE = exports.TILE_TYPE = exports.TILE_SIZE = exports.FORMAT = exports.MAP_LAYER_ROAD_RESTRICTIONS = exports.MAP_LAYER_TRAFFIC = exports.MAP_LAYER_INCIDENTS = exports.MAP_TYPE_NIGHT = exports.MAP_TYPE_TERRAIN = exports.MAP_TYPE_SATELLITE = exports.MAP_TYPE_FLEET_STYLE = exports.MAP_TYPE_DEFAULT = void 0;
4
4
  exports.MAP_TYPE_DEFAULT = 'DEFAULT';
5
5
  exports.MAP_TYPE_FLEET_STYLE = 'FLEET_STYLE';
6
6
  exports.MAP_TYPE_SATELLITE = 'SATELLITE';
@@ -15,7 +15,10 @@ exports.TILE_SIZE = 256;
15
15
  exports.TILE_TYPE = 'maptile';
16
16
  exports.NO_CREDENTIALS_ERROR_MESSAGE = 'Cannot instantiate the Map. Missing credentials property.';
17
17
  // @ts-ignore-next-line
18
+ // biome-ignore lint/complexity/useLiteralKeys: <explanation>
18
19
  exports.ENGINE_TYPE_HARP = H.Map.EngineType['HARP'];
19
20
  exports.ENGINE_TYPE_P2D = H.Map.EngineType.P2D;
20
21
  exports.DEFAULT_TILE_SIZE = 512;
21
22
  exports.DEFAULT_RASTER_LAYER_FORMAT = 'png'; // 'jpeg';
23
+ exports.DEFAULT_MIN_ZOOM = 3;
24
+ exports.DEFAULT_MAX_ZOOM = 20;
@@ -57,6 +57,7 @@ export type MapProps = {
57
57
  boundingBox?: BoundingBox;
58
58
  disableMapEvents?: boolean;
59
59
  disableBehavior?: boolean;
60
+ disableZoomMomentum?: boolean;
60
61
  eventListenerMap?: EventListenerMap;
61
62
  hideMapSettings?: boolean;
62
63
  hideClusterSettings?: boolean;
@@ -76,6 +77,8 @@ export type MapProps = {
76
77
  zoomAnimation?: boolean;
77
78
  enableWebGL?: boolean;
78
79
  enableDevicePixelRatio?: boolean;
80
+ minZoom?: number;
81
+ maxZoom?: number;
79
82
  children?: React.ReactNode | ((api: MapApi, incidents?: MapIncidents) => React.ReactNode);
80
83
  };
81
84
  export type MapApi = {
@@ -93,6 +96,8 @@ export type MapApi = {
93
96
  baseLayer?: MapType;
94
97
  activeLayers?: MapLayer[];
95
98
  showCluster?: boolean;
99
+ minZoom?: number;
100
+ maxZoom?: number;
96
101
  };
97
102
  };
98
103
  export type MapIncidents = {
@@ -2,7 +2,7 @@ import type { MapCredentials, MapType } from './mapTypes';
2
2
  export declare const getPPI: () => 100 | 200;
3
3
  export declare const isVectorBased: (enableWebGL: boolean, baseLayer: MapType) => boolean;
4
4
  export declare const getPlatform: (credentials: MapCredentials) => H.service.Platform;
5
- export declare const getBaseTileLayer: <T>(rasterTileService: T, engineType: H.Map.EngineType) => H.map.layer.TileLayer;
5
+ export declare const getBaseTileLayer: <T>(rasterTileService: T, engineType: H.Map.EngineType, minZoom: number, maxZoom: number) => H.map.layer.TileLayer;
6
6
  export declare const getBaseRasterTileService: (platform: H.service.Platform, style: string, features: string, lang: string) => any;
7
7
  export declare const getEngineType: (baseLayerName: string, enableWebGL: boolean) => any;
8
8
  export type BaseLayer = {
@@ -13,8 +13,11 @@ export type BaseLayer = {
13
13
  engineType: H.Map.EngineType;
14
14
  language: string;
15
15
  vehicleRestrictions: boolean;
16
+ minZoom: number;
17
+ maxZoom: number;
16
18
  };
17
- export declare const getBaseLayer: ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, }: BaseLayer) => {
19
+ export type BaseLayerResponse = {
18
20
  baseLayer: H.map.layer.Layer;
19
21
  overlayLayer?: H.map.layer.Layer;
20
22
  };
23
+ export declare const getBaseLayer: ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }: BaseLayer) => BaseLayerResponse;
@@ -15,16 +15,20 @@ const getPlatform = (credentials) =>
15
15
  // Initiate and authenticate your connection to the HERE platform:
16
16
  new H.service.Platform({
17
17
  apikey: credentials.apikey ?? '',
18
- useHTTPS: location.protocol === 'https:' ? true : false,
18
+ useHTTPS: location.protocol === 'https:',
19
19
  });
20
20
  exports.getPlatform = getPlatform;
21
- const getBaseTileLayer = (rasterTileService, engineType) => {
21
+ const getBaseTileLayer = (rasterTileService, engineType, minZoom, maxZoom) => {
22
22
  // @ts-ignore-next-line "H.service.rasterTile" is newer that the types
23
23
  const rasterTileProvider = new H.service.rasterTile.Provider(rasterTileService, {
24
24
  engineType,
25
25
  tileSize: 512,
26
26
  });
27
- return new H.map.layer.TileLayer(rasterTileProvider);
27
+ const rasterTileLayer = new H.map.layer.TileLayer(rasterTileProvider);
28
+ // force the tile layer minimum zoom (furthest away possible) and maximum zoom (nearest) to the desired level
29
+ rasterTileLayer.setMin(minZoom);
30
+ rasterTileLayer.setMax(maxZoom);
31
+ return rasterTileLayer;
28
32
  };
29
33
  exports.getBaseTileLayer = getBaseTileLayer;
30
34
  const getBaseRasterTileService = (platform, style, features, lang) => {
@@ -51,79 +55,82 @@ const getEngineType = (baseLayerName, enableWebGL) => {
51
55
  }
52
56
  };
53
57
  exports.getEngineType = getEngineType;
54
- const getBaseLayer = ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, }) => {
58
+ const getBaseLayer = ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }) => {
55
59
  const restriction = 'disabled'; // vehicleRestrictions ? 'active_and_inactive' : 'disabled';
56
60
  const features = `pois:all,environmental_zones:all,congestion_zones:all,vehicle_restrictions:${restriction}`;
57
61
  if (enableWebGL && baseLayerName === constants_1.MAP_TYPE_DEFAULT) {
58
- // const rasterTileService = platform?.getRasterTileService({
59
- // format: 'png', // 'png', // or jpg, png8
60
- // queryParams: {
61
- // lang: 'en',
62
- // ppi: window.devicePixelRatio >= 1.7 ? 400 : 100,
63
- // // style: 'explore.day',
64
- // features: 'environmental_zones:all',
65
- // },
66
- // });
67
- // const rasterTileProvider = new H.service.rasterTile.Provider(rasterTileService, {
68
- // engineType: enableWebGL ? H.Map.EngineType['HARP'] : H.Map.EngineType['P2D'],
69
- // tileSize: 512,
70
- // });
71
- // const rasterTileLayer = new H.map.layer.TileLayer(rasterTileProvider);
72
- // const envLayer = rasterTileLayer;
73
- // // create a service that calls the custom endpoint
74
- // const service = platform.getOMVService({ path: 'v2/vectortiles/core/mc' });
75
- // // create a provider and a layer that use the custom service and a custom style
76
- // const provider = new H.service.omv.Provider(
77
- // service,
78
- // new H.map.Style('https://js.api.here.com/v3/3.1/styles/omv/oslo/japan/normal.day.yaml')
79
- // );
80
- // const layer = new H.map.layer.TileLayer(provider, { max: 22 });
62
+ defaultLayers?.vector.normal.map.setMin(minZoom);
63
+ defaultLayers?.vector.normal.map.setMax(maxZoom);
81
64
  return {
82
65
  baseLayer: defaultLayers?.vector.normal.map,
83
- // baseLayer: layer,
84
- // overlayLayer: envLayer,
85
66
  };
86
67
  }
87
68
  switch (baseLayerName) {
88
69
  case constants_1.MAP_TYPE_SATELLITE: {
89
70
  if (enableWebGL) {
71
+ // This is a workaround for setting the min and max zoom limit for satellite map
72
+ // since the setMin/setMax cannot be set on the "defaultLayers.hybrid.liteday.raster".
73
+ // The HERE support suggests to create a hybrid layer for that and set the zoom limits
74
+ // on the two layers.
75
+ const hybridStyleConfig = {
76
+ base: {
77
+ style: 'oslo',
78
+ scheme: 'hybrid.day',
79
+ },
80
+ };
81
+ let baseLayer;
82
+ let overlayLayer;
83
+ // This method creates hybrid map layers. A hybrid map consists of raster satellite base layer and vector layers on top.
84
+ // Layers created by this method can be used only when the Map is instantiated with H.Map.EngineType.HARP engineType.
85
+ // See https://www.here.com/docs/bundle/maps-api-for-javascript-api-reference/page/H.service.Platform_4.html#createHybridLayers
86
+ // @ts-ignore-next-line
87
+ platform.createHybridLayers(hybridStyleConfig, (layers) => {
88
+ layers.raster.setMin(minZoom);
89
+ layers.raster.setMax(maxZoom);
90
+ layers.vector.setMin(minZoom);
91
+ layers.vector.setMax(maxZoom);
92
+ baseLayer = layers.raster;
93
+ overlayLayer = layers.vector;
94
+ }, console.error);
90
95
  return {
91
- // @ts-ignore-next-line "hybrid.liteday.raster" is newer that the types
92
- baseLayer: defaultLayers.hybrid.liteday.raster,
93
- // @ts-ignore-next-line "hybrid.day.vector" is newer that the types
94
- overlayLayer: defaultLayers.hybrid.day.vector,
96
+ baseLayer,
97
+ overlayLayer,
95
98
  };
96
99
  }
97
100
  return {
98
- baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.satellite.day', features, language), engineType),
101
+ baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.satellite.day', features, language), engineType, minZoom, maxZoom),
99
102
  };
100
103
  }
101
104
  case constants_1.MAP_TYPE_TERRAIN: {
102
105
  return {
103
- baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'topo.day', features, language), engineType),
106
+ baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'topo.day', features, language), engineType, minZoom, maxZoom),
104
107
  };
105
108
  }
106
109
  case constants_1.MAP_TYPE_FLEET_STYLE: {
107
110
  return {
108
- baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'logistics.day', features, language), constants_1.ENGINE_TYPE_P2D),
111
+ baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'logistics.day', features, language), constants_1.ENGINE_TYPE_P2D, minZoom, maxZoom),
109
112
  };
110
113
  }
111
114
  case constants_1.MAP_TYPE_NIGHT: {
112
115
  if (enableWebGL) {
116
+ // @ts-ignore-next-line "setMin" is working on "vector.normal.mapnight"
117
+ defaultLayers?.vector.normal.mapnight.setMin(minZoom);
118
+ // @ts-ignore-next-line "setMax" is working on "vector.normal.mapnight"
119
+ defaultLayers?.vector.normal.mapnight.setMax(maxZoom);
113
120
  return {
114
- // @ts-ignore-next-line "vector.normal.mapnight" is newer that the types
121
+ // @ts-ignore-next-line "vector.normal.mapnight" is newer than the types
115
122
  baseLayer: defaultLayers.vector.normal.mapnight,
116
123
  };
117
124
  }
118
125
  return {
119
- baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.night', features, language), engineType),
126
+ baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.night', features, language), engineType, minZoom, maxZoom),
120
127
  };
121
128
  }
122
129
  default: {
123
130
  // As a replacement for "defaultLayers?.raster.normal.map" which uses the old and deprecated
124
131
  // H.service.MapTileService, we use the Raster Tile Service v3 instead
125
132
  return {
126
- baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.day', features, language), engineType),
133
+ baseLayer: (0, exports.getBaseTileLayer)((0, exports.getBaseRasterTileService)(platform, 'explore.day', features, language), engineType, minZoom, maxZoom),
127
134
  };
128
135
  }
129
136
  }
@@ -35,7 +35,7 @@ const OverlayTrigger = (props) => {
35
35
  const handleShow = () => {
36
36
  timeout.clear();
37
37
  hoverStateRef.current = 'show';
38
- if (typeof delay === 'number' || !delay?.show) {
38
+ if (delay === 0 || (typeof delay !== 'number' && !delay?.show)) {
39
39
  setShow(true);
40
40
  return;
41
41
  }
@@ -56,7 +56,7 @@ const OverlayTrigger = (props) => {
56
56
  if (hoverStateRef.current === 'hide') {
57
57
  setShow(false);
58
58
  }
59
- }, typeof delay === 'number' ? delay : delay?.hide);
59
+ }, delay?.hide);
60
60
  };
61
61
  const handleFocus = (0, react_1.useCallback)((...args) => {
62
62
  handleShow();