@rio-cloud/rio-uikit 1.10.0 → 1.11.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 (74) hide show
  1. package/.DS_Store +0 -0
  2. package/components/assetTree/AssetTree.js +1 -1
  3. package/components/assetTree/Tree.d.ts +6 -0
  4. package/components/assetTree/Tree.js +2 -2
  5. package/components/assetTree/TreeNode.d.ts +1 -0
  6. package/components/assetTree/TreeNode.js +3 -2
  7. package/components/dialog/SplitDialog.d.ts +6 -0
  8. package/components/dialog/SplitDialog.js +2 -2
  9. package/components/filepicker/FilePicker.d.ts +1 -1
  10. package/components/formLabel/FormLabel.js +1 -1
  11. package/components/map/components/Map.js +70 -68
  12. package/components/map/components/features/settings/builtinSettings/MapTypeSettings.d.ts +1 -1
  13. package/components/map/utils/rendering.d.ts +1 -1
  14. package/components/map/utils/rendering.js +7 -11
  15. package/hooks/useAverage.d.ts +18 -0
  16. package/hooks/useAverage.js +28 -0
  17. package/hooks/useCount.d.ts +22 -0
  18. package/hooks/useCount.js +31 -0
  19. package/hooks/useMax.d.ts +18 -0
  20. package/hooks/useMax.js +24 -0
  21. package/hooks/useMin.d.ts +18 -0
  22. package/hooks/useMin.js +24 -0
  23. package/hooks/useSum.d.ts +18 -0
  24. package/hooks/useSum.js +23 -0
  25. package/lib/es/components/assetTree/AssetTree.js +1 -1
  26. package/lib/es/components/assetTree/Tree.d.ts +6 -0
  27. package/lib/es/components/assetTree/Tree.js +2 -2
  28. package/lib/es/components/assetTree/TreeNode.d.ts +1 -0
  29. package/lib/es/components/assetTree/TreeNode.js +3 -2
  30. package/lib/es/components/dialog/SplitDialog.d.ts +6 -0
  31. package/lib/es/components/dialog/SplitDialog.js +2 -2
  32. package/lib/es/components/filepicker/FilePicker.d.ts +1 -1
  33. package/lib/es/components/formLabel/FormLabel.js +1 -1
  34. package/lib/es/components/map/components/Map.js +70 -68
  35. package/lib/es/components/map/components/features/settings/builtinSettings/MapTypeSettings.d.ts +1 -1
  36. package/lib/es/components/map/utils/rendering.d.ts +1 -1
  37. package/lib/es/components/map/utils/rendering.js +7 -11
  38. package/lib/es/hooks/useAverage.d.ts +18 -0
  39. package/lib/es/hooks/useAverage.js +30 -0
  40. package/lib/es/hooks/useCount.d.ts +22 -0
  41. package/lib/es/hooks/useCount.js +33 -0
  42. package/lib/es/hooks/useMax.d.ts +18 -0
  43. package/lib/es/hooks/useMax.js +26 -0
  44. package/lib/es/hooks/useMin.d.ts +18 -0
  45. package/lib/es/hooks/useMin.js +26 -0
  46. package/lib/es/hooks/useSum.d.ts +18 -0
  47. package/lib/es/hooks/useSum.js +25 -0
  48. package/lib/es/useAverage.d.ts +2 -0
  49. package/lib/es/useAverage.js +7 -0
  50. package/lib/es/useCount.d.ts +2 -0
  51. package/lib/es/useCount.js +7 -0
  52. package/lib/es/useMax.d.ts +2 -0
  53. package/lib/es/useMax.js +7 -0
  54. package/lib/es/useMin.d.ts +2 -0
  55. package/lib/es/useMin.js +7 -0
  56. package/lib/es/useSum.d.ts +2 -0
  57. package/lib/es/useSum.js +7 -0
  58. package/lib/es/utils/formatUtils.d.ts +16 -0
  59. package/lib/es/utils/formatUtils.js +55 -0
  60. package/lib/es/version.json +1 -1
  61. package/package.json +6 -6
  62. package/useAverage.d.ts +2 -0
  63. package/useAverage.js +2 -0
  64. package/useCount.d.ts +2 -0
  65. package/useCount.js +2 -0
  66. package/useMax.d.ts +2 -0
  67. package/useMax.js +2 -0
  68. package/useMin.d.ts +2 -0
  69. package/useMin.js +2 -0
  70. package/useSum.d.ts +2 -0
  71. package/useSum.js +2 -0
  72. package/utils/formatUtils.d.ts +16 -0
  73. package/utils/formatUtils.js +49 -0
  74. package/version.json +1 -1
package/.DS_Store CHANGED
Binary file
@@ -54,7 +54,7 @@ const AssetTree = memo(forwardRef((props, ref) => {
54
54
  const childrenArray = React.Children.toArray(children);
55
55
  // check for children type of TreeCategory and throw error in case
56
56
  invariant(childrenArray.every(isTreeCategory), 'AssetTree only excepts children of type "TreeCategory"');
57
- const classes = classNames('AssetTree', className, !isOpen && 'closed', bordered && 'panel panel-default', sidebarMode === TreeMode.MODE_FLY ? 'fly' : 'fluid');
57
+ const classes = classNames('AssetTree', className, !isOpen && 'closed', bordered && 'border', sidebarMode === TreeMode.MODE_FLY ? 'fly' : 'fluid');
58
58
  const resizeLimitClasses = classNames('AssetTreeResizeLimit', isResize && 'display-block');
59
59
  const resizeIndicatorPosition = maxWidth || window.innerWidth * 0.5;
60
60
  const resizeLimitStyle = { left: resizeIndicatorPosition };
@@ -27,6 +27,12 @@ export type TreeGroup = {
27
27
  * The prefix `rioglyph-` can be omitted.
28
28
  */
29
29
  icon?: string;
30
+ /**
31
+ * The rioglyph icon name for a expanded group.
32
+ *
33
+ * The prefix `rioglyph-` can be omitted.
34
+ */
35
+ expandedIcon?: string;
30
36
  /**
31
37
  * Additional classes added to the group element.
32
38
  */
@@ -242,7 +242,7 @@ const Tree = React.memo((props) => {
242
242
  width: '100%',
243
243
  height: `${virtualItem.size}px`,
244
244
  transform: `translateY(${virtualItem.start}px)`,
245
- }, children: item.type === 'group' ? (_jsx(TreeNodeContainer, { groupId: item.id, isOpen: item.isExpanded, disableAnimation: disableAnimation, children: _jsx(TreeNode, { node: item.data, hasMultiselect: hasMultiselect, onToggleNode: enhancedHandleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: !isGroupSelected &&
245
+ }, children: item.type === 'group' ? (_jsx(TreeNodeContainer, { groupId: item.id, isOpen: item.isExpanded, disableAnimation: disableAnimation, children: _jsx(TreeNode, { node: item.data, hasMultiselect: hasMultiselect, onToggleNode: enhancedHandleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isOpen: item.isExpanded, isIndeterminate: !isGroupSelected &&
246
246
  item.data.items.some(groupItem => selectedItems.includes(groupItem.id)) }) }, item.id)) : (
247
247
  // Render individual leaf item with proper styling
248
248
  _jsx(TreeNodeContainer, { isOpen: true, disableAnimation: disableAnimation, children: _jsx(TreeLeafList, { leafList: [item.data], hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }) }, item.id)) }, `${item.type}-${item.id}-${virtualItem.index}`));
@@ -263,7 +263,7 @@ const Tree = React.memo((props) => {
263
263
  const numSelectedGroupItems = filter(containsItemById(selectedItems))(groupItems).length;
264
264
  const isGroupSelected = selectedGroups.includes(groupId);
265
265
  const isStateIndeterminate = !isGroupSelected && numSelectedGroupItems > 0;
266
- return (_jsxs(TreeNodeContainer, { groupId: groupId, isOpen: isOpen, disableAnimation: disableAnimation, children: [_jsx(TreeNode, { node: group, hasMultiselect: hasMultiselect, onToggleNode: handleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: isStateIndeterminate }), isOpen && (_jsx(TreeLeafList, { leafList: groupItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }))] }, groupId));
266
+ return (_jsxs(TreeNodeContainer, { groupId: groupId, isOpen: isOpen, disableAnimation: disableAnimation, children: [_jsx(TreeNode, { node: group, hasMultiselect: hasMultiselect, onToggleNode: handleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: isStateIndeterminate, isOpen: isOpen }), isOpen && (_jsx(TreeLeafList, { leafList: groupItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }))] }, groupId));
267
267
  })(groupedItems);
268
268
  return result;
269
269
  };
@@ -4,6 +4,7 @@ export type TreeNodeProps = {
4
4
  node: GroupedItem;
5
5
  hasMultiselect?: boolean;
6
6
  isSelected?: boolean;
7
+ isOpen?: boolean;
7
8
  isIndeterminate?: boolean;
8
9
  onToggleNode: (nodeId: string) => void;
9
10
  onSelect: (node: GroupedItem, isIndeterminate: boolean) => void;
@@ -10,10 +10,11 @@ const withRioglyphPrefix = (name) => {
10
10
  return name.startsWith('rioglyph-') ? name : `rioglyph-${name}`;
11
11
  };
12
12
  const TreeNode = React.memo((props) => {
13
- const { node, hasMultiselect = false, isSelected = false, isIndeterminate = false, onToggleNode, onSelect } = props;
13
+ const { node, hasMultiselect = false, isSelected = false, isOpen = false, isIndeterminate = false, onToggleNode, onSelect, } = props;
14
14
  const treeNodeClassNames = classNames('TreeNode', 'from-group', isSelected && 'checked', node.className && node.className);
15
15
  const hasChildren = !!node.items.length;
16
- const iconName = withRioglyphPrefix(node.icon);
16
+ const expandedIcon = node.expandedIcon || node.icon;
17
+ const iconName = isOpen ? withRioglyphPrefix(expandedIcon) : withRioglyphPrefix(node.icon);
17
18
  return (_jsxs("div", { className: treeNodeClassNames, "data-key": node.id, onClick: () => hasChildren && onToggleNode(node.id), children: [hasMultiselect && (_jsx(Checkbox, { className: 'TreeCheckbox', checked: isSelected, disabled: node.disabled, indeterminate: isIndeterminate, onClick: () => onSelect(node, isIndeterminate) })), _jsxs("span", { className: 'TreeLabel TreeLabelName', children: [iconName && _jsx("span", { className: `rioglyph ${iconName}` }), _jsx("span", { className: 'TreeLabelNameText', children: _jsx("span", { className: 'TreeLabelNameTextHeadline', children: node.name }) }), _jsx("span", { className: 'TreeLabelCount label label-muted label-filled label-condensed', children: node.items.length }), _jsx("span", { className: `TreeLabelExpander rioglyph rioglyph-chevron-down ${hasChildren ? '' : 'text-color-light'}` })] })] }));
18
19
  });
19
20
  export default TreeNode;
@@ -37,6 +37,12 @@ export type SplitDialogProps = Omit<BaseDialogProps, 'useOverflow'> & {
37
37
  * @default true
38
38
  */
39
39
  useOverflow?: boolean;
40
+ /**
41
+ * Allows to disable the divider.
42
+ *
43
+ * @default true
44
+ */
45
+ showDivider?: boolean;
40
46
  };
41
47
  declare const SplitDialog: (props: SplitDialogProps) => import("react/jsx-runtime").JSX.Element;
42
48
  export default SplitDialog;
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import classNames from 'classnames';
3
3
  import Dialog from './Dialog';
4
4
  const SplitDialog = (props) => {
5
- const { leftContent, rightContent, leftContentClassName = '', rightContentClassName = '', className = '', useOverflow = true, ...remainingProps } = props;
5
+ const { leftContent, rightContent, leftContentClassName = '', rightContentClassName = '', className = '', useOverflow = true, showDivider = true, ...remainingProps } = props;
6
6
  const dialogClassName = `split-dialog ${className}`;
7
7
  const dividerClasses = classNames('split-divider', 'bg-lighter');
8
- const body = (_jsxs("div", { className: 'split-wrapper', children: [_jsxs("div", { className: `split-left ${leftContentClassName}`, children: [leftContent, _jsx("div", { className: dividerClasses })] }), _jsx("div", { className: `split-right ${rightContentClassName}`, children: rightContent })] }));
8
+ const body = (_jsxs("div", { className: 'split-wrapper', children: [_jsxs("div", { className: `split-left ${leftContentClassName}`, children: [leftContent, showDivider && _jsx("div", { className: dividerClasses })] }), _jsx("div", { className: `split-right ${rightContentClassName}`, children: rightContent })] }));
9
9
  return _jsx(Dialog, { ...remainingProps, body: body, className: dialogClassName, useOverflow: useOverflow });
10
10
  };
11
11
  export default SplitDialog;
@@ -25,7 +25,7 @@ export type FilePickerProps = {
25
25
  */
26
26
  label?: string | ReactNode;
27
27
  /**
28
- * Maximum file size.
28
+ * Maximum file size in byte. 5 MB = 5,242,880 byte
29
29
  */
30
30
  maxSize?: number;
31
31
  /**
@@ -23,7 +23,7 @@ const FormLabel = (props) => {
23
23
  }
24
24
  }, []);
25
25
  const supportingTextClasses = classNames('text-color-gray', 'text-italic', parentSize === 'sm' && 'text-size-10', parentSize === 'lg' && 'text-size-14', !parentSize && 'text-size-12');
26
- if (isLabel) {
26
+ if (isLabel && remainingProps.htmlFor) {
27
27
  const labelClasses = classNames(!supportingText && 'display-inline-block', supportingText && 'display-inline-flex flex-wrap justify-content-between width-100pct', className);
28
28
  return (
29
29
  // biome-ignore lint/a11y/noLabelWithoutControl: <explanation>
@@ -41,6 +41,15 @@ const Map = (props) => {
41
41
  else {
42
42
  console.debug('initialize here map');
43
43
  }
44
+ if (api?.map) {
45
+ // Cleanup any previously initialized map before doing anything else
46
+ console.debug('disposing previous map');
47
+ removeEventListenerMap(api.map);
48
+ if (api.mapEvents) {
49
+ api.mapEvents.dispose();
50
+ }
51
+ api.map.dispose();
52
+ }
44
53
  const bounds = boundingBox && getMapBounds(boundingBox);
45
54
  // Initialize communication with the platform
46
55
  const platform = getPlatform(credentials);
@@ -53,7 +62,7 @@ const Map = (props) => {
53
62
  // @ts-ignore-next-line: according to the Here docs, the engine type exists
54
63
  // see https://www.here.com/docs/bundle/maps-api-for-javascript-developer-guide/page/topics/harp-migrate.html
55
64
  const defaultLayers = platform.createDefaultLayers({ engineType, lg: language, pois: true });
56
- const defaultLayerMap = getBaseLayer({
65
+ getBaseLayer({
57
66
  baseLayerName: baseLayer,
58
67
  defaultLayers,
59
68
  enableWebGL,
@@ -63,76 +72,69 @@ const Map = (props) => {
63
72
  language,
64
73
  minZoom,
65
74
  maxZoom: safeMaxZoom,
66
- });
67
- // Initialize the map
68
- const hereMap = new H.Map(mapRef.current, defaultLayerMap.baseLayer, {
69
- zoom,
70
- center,
71
- bounds,
72
- engineType,
73
- pixelRatio: devicePixelRatio,
74
- fixedCenter: true,
75
- });
76
- if (defaultLayerMap.overlayLayer) {
77
- // Special case for satellite map where we render street labels and road signs as well as additional pois as vector data
78
- hereMap.addLayer(defaultLayerMap.overlayLayer);
79
- }
80
- setMapInitialized(true);
81
- let hereMapEvents = false;
82
- let hereBehavior;
83
- // Enable the map event system
84
- if (!disableMapEvents) {
85
- hereMapEvents = new H.mapevents.MapEvents(hereMap);
86
- }
87
- if (!(disableMapEvents || disableBehavior)) {
88
- hereBehavior = new H.mapevents.Behavior(hereMapEvents);
89
- // @ts-ignore-next-line
90
- hereBehavior.disable(H.mapevents.Behavior.Feature.FRACTIONAL_ZOOM);
91
- if (disableZoomMomentum) {
92
- // Disable the inertia that occurs on WebGL maps when scrolling/zooming.
93
- // This resulted in a very high scroll sensitivity.
94
- // @ts-ignore-next-line
95
- hereBehavior.disable(H.mapevents.Behavior.Feature.ZOOM_MOMENTUM);
75
+ }).then(defaultLayerMap => {
76
+ // Initialize the map
77
+ const hereMap = new H.Map(mapRef.current, defaultLayerMap.baseLayer, {
78
+ zoom,
79
+ center,
80
+ bounds,
81
+ engineType,
82
+ pixelRatio: devicePixelRatio,
83
+ fixedCenter: true,
84
+ });
85
+ if (defaultLayerMap.overlayLayer) {
86
+ // Special case for satellite map where we render street labels and road signs as well as additional pois as vector data
87
+ // hereMap.setBaseLayer(defaultLayerMap.baseLayer);
88
+ hereMap.addLayer(defaultLayerMap.overlayLayer);
96
89
  }
97
- }
98
- addEventListenerMap(hereMap, eventListenerMap, hereMap);
99
- const hereUi = getHereUi(hereMap, defaultLayers, showScaleBar, language);
100
- // The api will be passed to services when using a render function.
101
- // This allows the service to access the map internals
102
- setApi({
103
- credentials,
104
- defaultLayers,
105
- map: hereMap,
106
- mapEvents: hereMapEvents,
107
- behavior: hereBehavior,
108
- platform,
109
- ui: hereUi,
110
- utils: createUtils(hereMap),
111
- // Put settings back into the map API object so the invoking service
112
- // can check on these settings for instance inside a test
113
- settings: {
114
- enableWebGL,
115
- baseLayer,
116
- activeLayers,
117
- showCluster,
118
- minZoom,
119
- maxZoom: safeMaxZoom,
120
- },
121
- });
122
- // If the base layer changed, re-add all previous objects again,
123
- // otherwise the map would be empty
124
- if (allMapObjects) {
125
- hereMap.addObjects(allMapObjects);
126
- }
127
- return () => {
128
- if (hereMap) {
129
- removeEventListenerMap(hereMap);
130
- if (hereMapEvents) {
131
- hereMapEvents.dispose();
90
+ setMapInitialized(true);
91
+ let hereMapEvents = false;
92
+ let hereBehavior;
93
+ if (!disableMapEvents) {
94
+ // Enable the map event system
95
+ hereMapEvents = new H.mapevents.MapEvents(hereMap);
96
+ }
97
+ if (!(disableMapEvents || disableBehavior)) {
98
+ hereBehavior = new H.mapevents.Behavior(hereMapEvents);
99
+ // @ts-ignore-next-line
100
+ hereBehavior.disable(H.mapevents.Behavior.Feature.FRACTIONAL_ZOOM);
101
+ if (disableZoomMomentum) {
102
+ // Disable the inertia that occurs on WebGL maps when scrolling/zooming.
103
+ // This resulted in a very high scroll sensitivity.
104
+ // @ts-ignore-next-line
105
+ hereBehavior.disable(H.mapevents.Behavior.Feature.ZOOM_MOMENTUM);
132
106
  }
133
- hereMap.dispose();
134
107
  }
135
- };
108
+ addEventListenerMap(hereMap, eventListenerMap, hereMap);
109
+ const hereUi = getHereUi(hereMap, defaultLayers, showScaleBar, language);
110
+ // The api will be passed to services when using a render function.
111
+ // This allows the service to access the map internals
112
+ setApi({
113
+ credentials,
114
+ defaultLayers,
115
+ map: hereMap,
116
+ mapEvents: hereMapEvents,
117
+ behavior: hereBehavior,
118
+ platform,
119
+ ui: hereUi,
120
+ utils: createUtils(hereMap),
121
+ // Put settings back into the map API object so the invoking service
122
+ // can check on these settings for instance inside a test
123
+ settings: {
124
+ enableWebGL,
125
+ baseLayer,
126
+ activeLayers,
127
+ showCluster,
128
+ minZoom,
129
+ maxZoom: safeMaxZoom,
130
+ },
131
+ });
132
+ if (allMapObjects) {
133
+ // If the base layer changed, re-add all previous objects again,
134
+ // otherwise the map would be empty
135
+ hereMap.addObjects(allMapObjects);
136
+ }
137
+ });
136
138
  }, [enableWebGL, enableDevicePixelRatio, language, baseLayer, minZoom, maxZoom]);
137
139
  const isDarkMode = useDarkMode();
138
140
  useEffect(() => {
@@ -3,7 +3,7 @@ import type { MapType } from '../../../../utils/mapTypes';
3
3
  export type MapTypeSettingsProps = {
4
4
  mapType?: string;
5
5
  enableNightMap?: boolean;
6
- onMapTypeChange?: () => MapType;
6
+ onMapTypeChange?: (type: MapType) => void;
7
7
  defaultTypeLabel?: string | JSX.Element;
8
8
  truckTypeLabel?: string | JSX.Element;
9
9
  terrainTypeLabel?: string | JSX.Element;
@@ -20,4 +20,4 @@ export type BaseLayerResponse = {
20
20
  baseLayer: H.map.layer.Layer;
21
21
  overlayLayer?: H.map.layer.Layer;
22
22
  };
23
- export declare const getBaseLayer: ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }: BaseLayer) => BaseLayerResponse;
23
+ export declare const getBaseLayer: ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }: BaseLayer) => Promise<BaseLayerResponse>;
@@ -46,7 +46,7 @@ export const getEngineType = (baseLayerName, enableWebGL) => {
46
46
  return enableWebGL ? ENGINE_TYPE_HARP : ENGINE_TYPE_P2D;
47
47
  }
48
48
  };
49
- export const getBaseLayer = ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }) => {
49
+ export const getBaseLayer = async ({ baseLayerName, defaultLayers, enableWebGL, platform, engineType, language, vehicleRestrictions, minZoom, maxZoom, }) => {
50
50
  const restriction = 'disabled'; // vehicleRestrictions ? 'active_and_inactive' : 'disabled';
51
51
  const features = `pois:all,environmental_zones:all,congestion_zones:all,vehicle_restrictions:${restriction}`;
52
52
  if (enableWebGL && baseLayerName === MAP_TYPE_DEFAULT) {
@@ -61,7 +61,7 @@ export const getBaseLayer = ({ baseLayerName, defaultLayers, enableWebGL, platfo
61
61
  if (enableWebGL) {
62
62
  // This is a workaround for setting the min and max zoom limit for satellite map
63
63
  // since the setMin/setMax cannot be set on the "defaultLayers.hybrid.liteday.raster".
64
- // The HERE support suggests to create a hybrid layer for that and set the zoom limits
64
+ // The HERE support suggested to create a hybrid layer for that and set the zoom limits
65
65
  // on the two layers.
66
66
  const hybridStyleConfig = {
67
67
  base: {
@@ -69,24 +69,20 @@ export const getBaseLayer = ({ baseLayerName, defaultLayers, enableWebGL, platfo
69
69
  scheme: 'hybrid.day',
70
70
  },
71
71
  };
72
- let baseLayer;
73
- let overlayLayer;
74
72
  // This method creates hybrid map layers. A hybrid map consists of raster satellite base layer and vector layers on top.
75
73
  // Layers created by this method can be used only when the Map is instantiated with H.Map.EngineType.HARP engineType.
76
74
  // See https://www.here.com/docs/bundle/maps-api-for-javascript-api-reference/page/H.service.Platform_4.html#createHybridLayers
77
75
  // @ts-ignore-next-line
78
- platform.createHybridLayers(hybridStyleConfig, (layers) => {
76
+ await platform.createHybridLayers(hybridStyleConfig, (layers) => {
79
77
  layers.raster.setMin(minZoom);
80
78
  layers.raster.setMax(maxZoom);
81
79
  layers.vector.setMin(minZoom);
82
80
  layers.vector.setMax(maxZoom);
83
- baseLayer = layers.raster;
84
- overlayLayer = layers.vector;
81
+ return {
82
+ baseLayer: layers.raster,
83
+ overlayLayer: layers.vector,
84
+ };
85
85
  }, console.error);
86
- return {
87
- baseLayer,
88
- overlayLayer,
89
- };
90
86
  }
91
87
  return {
92
88
  baseLayer: getBaseTileLayer(getBaseRasterTileService(platform, 'explore.satellite.day', features, language), engineType, minZoom, maxZoom),
@@ -0,0 +1,18 @@
1
+ export type UseAverageOptions = {
2
+ /**
3
+ * The locale used to parse localized number formats (e.g. "de-DE", "en-GB").
4
+ * @default "en-GB".
5
+ */
6
+ locale?: string;
7
+ };
8
+ /**
9
+ * Calculates the average of numeric values from a list of objects.
10
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
11
+ *
12
+ * @param items - The list of objects to aggregate.
13
+ * @param path - Dot-separated path to the value in each object.
14
+ * @param options - Optional configuration (e.g. locale for number parsing).
15
+ * @returns The average of all valid values as a number. Returns 0 if no values are valid.
16
+ */
17
+ declare const useAverage: (items: unknown[], path: string, options?: UseAverageOptions) => number;
18
+ export default useAverage;
@@ -0,0 +1,28 @@
1
+ import { useMemo } from 'react';
2
+ import { parseNumberFromValue, getValueByPath } from '../utils/formatUtils';
3
+ /**
4
+ * Calculates the average of numeric values from a list of objects.
5
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
6
+ *
7
+ * @param items - The list of objects to aggregate.
8
+ * @param path - Dot-separated path to the value in each object.
9
+ * @param options - Optional configuration (e.g. locale for number parsing).
10
+ * @returns The average of all valid values as a number. Returns 0 if no values are valid.
11
+ */
12
+ const useAverage = (items, path, options = {}) => {
13
+ const { locale = 'en-GB' } = options;
14
+ return useMemo(() => {
15
+ const values = items
16
+ .map(item => {
17
+ const raw = getValueByPath(item, path);
18
+ return parseNumberFromValue(raw, locale);
19
+ })
20
+ .filter(num => !Number.isNaN(num) && num !== 0);
21
+ if (values.length === 0) {
22
+ return 0;
23
+ }
24
+ const sum = values.reduce((total, value) => total + value, 0);
25
+ return sum / values.length;
26
+ }, [items, path, locale]);
27
+ };
28
+ export default useAverage;
@@ -0,0 +1,22 @@
1
+ export type UseCountOptions = {
2
+ /**
3
+ * Count only values that strictly equal this value.
4
+ * If omitted and no `match` is provided, any value that is not null or undefined will be counted.
5
+ */
6
+ equals?: unknown;
7
+ /**
8
+ * A custom matcher function. If provided, it overrides the `equals` option.
9
+ */
10
+ match?: (value: unknown) => boolean;
11
+ };
12
+ /**
13
+ * Counts how many items in a list match a specific condition at a given path.
14
+ * Supports exact value comparison or custom predicate logic.
15
+ *
16
+ * @param items - The list of objects to evaluate.
17
+ * @param path - Dot-separated path to the target property.
18
+ * @param options - Optional config with `equals` or a custom `match` function.
19
+ * @returns Number of items that satisfy the condition.
20
+ */
21
+ declare const useCount: (items: unknown[], path: string, options?: UseCountOptions) => number;
22
+ export default useCount;
@@ -0,0 +1,31 @@
1
+ import { useMemo } from 'react';
2
+ import { getValueByPath } from '../utils/formatUtils';
3
+ /**
4
+ * Counts how many items in a list match a specific condition at a given path.
5
+ * Supports exact value comparison or custom predicate logic.
6
+ *
7
+ * @param items - The list of objects to evaluate.
8
+ * @param path - Dot-separated path to the target property.
9
+ * @param options - Optional config with `equals` or a custom `match` function.
10
+ * @returns Number of items that satisfy the condition.
11
+ */
12
+ const useCount = (items, path, options = {}) => {
13
+ const { equals, match } = options;
14
+ return useMemo(() => {
15
+ return items.reduce((count, item) => {
16
+ const value = getValueByPath(item, path);
17
+ let shouldCount = false;
18
+ if (typeof match === 'function') {
19
+ shouldCount = match(value);
20
+ }
21
+ else if (equals !== undefined) {
22
+ shouldCount = value === equals;
23
+ }
24
+ else {
25
+ shouldCount = value != null; // fallback: count all defined values
26
+ }
27
+ return shouldCount ? count + 1 : count;
28
+ }, 0);
29
+ }, [items, path, equals, match]);
30
+ };
31
+ export default useCount;
@@ -0,0 +1,18 @@
1
+ export type UseMaxOptions = {
2
+ /**
3
+ * The locale used to parse localized number formats (e.g. "de-DE", "en-GB").
4
+ * @default "en-GB".
5
+ */
6
+ locale?: string;
7
+ };
8
+ /**
9
+ * Finds the maximum numeric value from a list of objects.
10
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
11
+ *
12
+ * @param items - The list of objects to evaluate.
13
+ * @param path - Dot-separated path to the value in each object.
14
+ * @param options - Optional configuration (e.g. locale for number parsing).
15
+ * @returns The largest of all valid values, or 0 if none are valid.
16
+ */
17
+ declare const useMax: (items: unknown[], path: string, options?: UseMaxOptions) => number;
18
+ export default useMax;
@@ -0,0 +1,24 @@
1
+ import { useMemo } from 'react';
2
+ import { parseNumberFromValue, getValueByPath } from '../utils/formatUtils';
3
+ /**
4
+ * Finds the maximum numeric value from a list of objects.
5
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
6
+ *
7
+ * @param items - The list of objects to evaluate.
8
+ * @param path - Dot-separated path to the value in each object.
9
+ * @param options - Optional configuration (e.g. locale for number parsing).
10
+ * @returns The largest of all valid values, or 0 if none are valid.
11
+ */
12
+ const useMax = (items, path, options = {}) => {
13
+ const { locale = 'en-GB' } = options;
14
+ return useMemo(() => {
15
+ const values = items
16
+ .map(item => {
17
+ const valueFromPath = getValueByPath(item, path);
18
+ return parseNumberFromValue(valueFromPath, locale);
19
+ })
20
+ .filter(num => !Number.isNaN(num));
21
+ return values.length > 0 ? Math.max(...values) : 0;
22
+ }, [items, path, locale]);
23
+ };
24
+ export default useMax;
@@ -0,0 +1,18 @@
1
+ export type UseMinOptions = {
2
+ /**
3
+ * The locale used to parse localized number formats (e.g. "de-DE", "en-GB").
4
+ * @default "en-GB".
5
+ */
6
+ locale?: string;
7
+ };
8
+ /**
9
+ * Finds the minimum numeric value from a list of objects.
10
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
11
+ *
12
+ * @param items - The list of objects to evaluate.
13
+ * @param path - Dot-separated path to the value in each object.
14
+ * @param options - Optional configuration (e.g. locale for number parsing).
15
+ * @returns The smallest of all valid values, or 0 if none are valid.
16
+ */
17
+ declare const useMin: (items: unknown[], path: string, options?: UseMinOptions) => number;
18
+ export default useMin;
@@ -0,0 +1,24 @@
1
+ import { useMemo } from 'react';
2
+ import { parseNumberFromValue, getValueByPath } from '../utils/formatUtils';
3
+ /**
4
+ * Finds the minimum numeric value from a list of objects.
5
+ * Values are extracted using a dot-separated path and parsed with locale awareness.
6
+ *
7
+ * @param items - The list of objects to evaluate.
8
+ * @param path - Dot-separated path to the value in each object.
9
+ * @param options - Optional configuration (e.g. locale for number parsing).
10
+ * @returns The smallest of all valid values, or 0 if none are valid.
11
+ */
12
+ const useMin = (items, path, options = {}) => {
13
+ const { locale = 'en-GB' } = options;
14
+ return useMemo(() => {
15
+ const values = items
16
+ .map(item => {
17
+ const valueFromPath = getValueByPath(item, path);
18
+ return parseNumberFromValue(valueFromPath, locale);
19
+ })
20
+ .filter(num => !Number.isNaN(num));
21
+ return values.length > 0 ? Math.min(...values) : 0;
22
+ }, [items, path, locale]);
23
+ };
24
+ export default useMin;
@@ -0,0 +1,18 @@
1
+ export type UseSumOptions = {
2
+ /**
3
+ * The locale used to parse localized number formats (e.g. "de-DE", "en-GB").
4
+ * @default "en-GB".
5
+ */
6
+ locale?: string;
7
+ };
8
+ /**
9
+ * Calculates the sum of numeric values from a list of objects, using a defined property path.
10
+ * Supports localized number strings (e.g. "1.234,56 €", "1,000.75").
11
+ *
12
+ * @param items - The list of objects to sum values from.
13
+ * @param path - The dot-separated path to the target value in each object.
14
+ * @param options - Optional configuration such as locale for parsing.
15
+ * @returns The total sum of all valid parsed values as a number.
16
+ */
17
+ declare const useSum: (items: unknown[], path: string, options?: UseSumOptions) => number;
18
+ export default useSum;
@@ -0,0 +1,23 @@
1
+ import { useMemo } from 'react';
2
+ import { parseNumberFromValue, getValueByPath } from '../utils/formatUtils';
3
+ /**
4
+ * Calculates the sum of numeric values from a list of objects, using a defined property path.
5
+ * Supports localized number strings (e.g. "1.234,56 €", "1,000.75").
6
+ *
7
+ * @param items - The list of objects to sum values from.
8
+ * @param path - The dot-separated path to the target value in each object.
9
+ * @param options - Optional configuration such as locale for parsing.
10
+ * @returns The total sum of all valid parsed values as a number.
11
+ */
12
+ const useSum = (items, path, options = {}) => {
13
+ const { locale = 'en-GB' } = options;
14
+ const sum = useMemo(() => {
15
+ return items.reduce((total, item) => {
16
+ const raw = getValueByPath(item, path);
17
+ const value = parseNumberFromValue(raw, locale);
18
+ return total + value;
19
+ }, 0);
20
+ }, [items, path, locale]);
21
+ return sum;
22
+ };
23
+ export default useSum;
@@ -57,7 +57,7 @@ const AssetTree = (0, react_1.memo)((0, react_1.forwardRef)((props, ref) => {
57
57
  const childrenArray = react_1.default.Children.toArray(children);
58
58
  // check for children type of TreeCategory and throw error in case
59
59
  (0, tiny_invariant_1.default)(childrenArray.every(isTreeCategory), 'AssetTree only excepts children of type "TreeCategory"');
60
- const classes = (0, classnames_1.default)('AssetTree', className, !isOpen && 'closed', bordered && 'panel panel-default', sidebarMode === TreeMode.MODE_FLY ? 'fly' : 'fluid');
60
+ const classes = (0, classnames_1.default)('AssetTree', className, !isOpen && 'closed', bordered && 'border', sidebarMode === TreeMode.MODE_FLY ? 'fly' : 'fluid');
61
61
  const resizeLimitClasses = (0, classnames_1.default)('AssetTreeResizeLimit', isResize && 'display-block');
62
62
  const resizeIndicatorPosition = maxWidth || window.innerWidth * 0.5;
63
63
  const resizeLimitStyle = { left: resizeIndicatorPosition };
@@ -27,6 +27,12 @@ export type TreeGroup = {
27
27
  * The prefix `rioglyph-` can be omitted.
28
28
  */
29
29
  icon?: string;
30
+ /**
31
+ * The rioglyph icon name for a expanded group.
32
+ *
33
+ * The prefix `rioglyph-` can be omitted.
34
+ */
35
+ expandedIcon?: string;
30
36
  /**
31
37
  * Additional classes added to the group element.
32
38
  */
@@ -248,7 +248,7 @@ const Tree = react_1.default.memo((props) => {
248
248
  width: '100%',
249
249
  height: `${virtualItem.size}px`,
250
250
  transform: `translateY(${virtualItem.start}px)`,
251
- }, children: item.type === 'group' ? ((0, jsx_runtime_1.jsx)(TreeNodeContainer_1.default, { groupId: item.id, isOpen: item.isExpanded, disableAnimation: disableAnimation, children: (0, jsx_runtime_1.jsx)(TreeNode_1.default, { node: item.data, hasMultiselect: hasMultiselect, onToggleNode: enhancedHandleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: !isGroupSelected &&
251
+ }, children: item.type === 'group' ? ((0, jsx_runtime_1.jsx)(TreeNodeContainer_1.default, { groupId: item.id, isOpen: item.isExpanded, disableAnimation: disableAnimation, children: (0, jsx_runtime_1.jsx)(TreeNode_1.default, { node: item.data, hasMultiselect: hasMultiselect, onToggleNode: enhancedHandleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isOpen: item.isExpanded, isIndeterminate: !isGroupSelected &&
252
252
  item.data.items.some(groupItem => selectedItems.includes(groupItem.id)) }) }, item.id)) : (
253
253
  // Render individual leaf item with proper styling
254
254
  (0, jsx_runtime_1.jsx)(TreeNodeContainer_1.default, { isOpen: true, disableAnimation: disableAnimation, children: (0, jsx_runtime_1.jsx)(TreeLeafList_1.default, { leafList: [item.data], hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }) }, item.id)) }, `${item.type}-${item.id}-${virtualItem.index}`));
@@ -269,7 +269,7 @@ const Tree = react_1.default.memo((props) => {
269
269
  const numSelectedGroupItems = (0, filter_1.default)((0, treeUtils_1.containsItemById)(selectedItems))(groupItems).length;
270
270
  const isGroupSelected = selectedGroups.includes(groupId);
271
271
  const isStateIndeterminate = !isGroupSelected && numSelectedGroupItems > 0;
272
- return ((0, jsx_runtime_1.jsxs)(TreeNodeContainer_1.default, { groupId: groupId, isOpen: isOpen, disableAnimation: disableAnimation, children: [(0, jsx_runtime_1.jsx)(TreeNode_1.default, { node: group, hasMultiselect: hasMultiselect, onToggleNode: handleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: isStateIndeterminate }), isOpen && ((0, jsx_runtime_1.jsx)(TreeLeafList_1.default, { leafList: groupItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }))] }, groupId));
272
+ return ((0, jsx_runtime_1.jsxs)(TreeNodeContainer_1.default, { groupId: groupId, isOpen: isOpen, disableAnimation: disableAnimation, children: [(0, jsx_runtime_1.jsx)(TreeNode_1.default, { node: group, hasMultiselect: hasMultiselect, onToggleNode: handleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: isStateIndeterminate, isOpen: isOpen }), isOpen && ((0, jsx_runtime_1.jsx)(TreeLeafList_1.default, { leafList: groupItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }))] }, groupId));
273
273
  })(groupedItems);
274
274
  return result;
275
275
  };