@rio-cloud/rio-uikit 1.7.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/BarList.d.ts +2 -0
  2. package/BarList.js +2 -0
  3. package/README.md +4 -0
  4. package/SaveableDateInput.d.ts +2 -0
  5. package/SaveableDateInput.js +2 -0
  6. package/SvgImage.d.ts +2 -0
  7. package/SvgImage.js +2 -0
  8. package/TableCol.d.ts +2 -0
  9. package/TableCol.js +2 -0
  10. package/TableHead.d.ts +2 -0
  11. package/TableHead.js +2 -0
  12. package/components/actionBarItem/ActionBarItemIcon.js +1 -1
  13. package/components/actionBarItem/ActionBarOverlay.js +1 -1
  14. package/components/activity/Activity.d.ts +2 -2
  15. package/components/applicationHeader/CollapsedNavItem.js +1 -0
  16. package/components/assetTree/Tree.d.ts +20 -0
  17. package/components/assetTree/Tree.js +75 -38
  18. package/components/assetTree/TreeLeaf.js +1 -1
  19. package/components/assetTree/TreeNodeContainer.d.ts +1 -1
  20. package/components/assetTree/TreeSearch.js +1 -1
  21. package/components/assetTree/TreeSummary.js +1 -1
  22. package/components/assetTree/TypeCounter.d.ts +2 -0
  23. package/components/assetTree/TypeCounter.js +1 -1
  24. package/components/assetTree/useTreeExpansion.d.ts +4 -0
  25. package/components/assetTree/useTreeExpansion.js +25 -0
  26. package/components/assetTree/useTreeHeight.d.ts +1 -0
  27. package/components/assetTree/useTreeHeight.js +60 -0
  28. package/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  29. package/components/assetTree/useTreeScrollPosition.js +19 -0
  30. package/components/assetTree/useTreeVirtualization.d.ts +17 -0
  31. package/components/assetTree/useTreeVirtualization.js +71 -0
  32. package/components/autosuggest/AutoSuggest.js +2 -1
  33. package/components/barList/BarList.d.ts +97 -0
  34. package/components/barList/BarList.js +42 -0
  35. package/components/barList/useSortedBars.d.ts +2 -0
  36. package/components/barList/useSortedBars.js +14 -0
  37. package/components/button/ButtonToolbar.d.ts +1 -1
  38. package/components/button/ButtonToolbar.js +1 -1
  39. package/components/button/ToggleButton.js +0 -1
  40. package/components/charts/PieChart.js +1 -1
  41. package/components/clearableInput/ClearableInput.d.ts +20 -7
  42. package/components/clearableInput/ClearableInput.js +68 -8
  43. package/components/dialog/Dialog.js +1 -1
  44. package/components/dialog/FrameDialog.js +1 -1
  45. package/components/dropdown/ButtonDropdown.d.ts +11 -3
  46. package/components/dropdown/ButtonDropdown.js +79 -64
  47. package/components/dropdown/DropdownToggleButton.d.ts +7 -4
  48. package/components/dropdown/DropdownToggleButton.js +11 -3
  49. package/components/formLabel/FormLabel.d.ts +2 -2
  50. package/components/formLabel/FormLabel.js +1 -1
  51. package/components/listMenu/ListMenu.js +4 -1
  52. package/components/map/components/Map.js +21 -6
  53. package/components/map/components/constants.d.ts +2 -0
  54. package/components/map/components/constants.js +3 -0
  55. package/components/map/components/features/basics/InfoBubble.js +1 -1
  56. package/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
  57. package/components/map/utils/mapTypes.d.ts +5 -0
  58. package/components/map/utils/rendering.d.ts +5 -2
  59. package/components/map/utils/rendering.js +46 -39
  60. package/components/menuItems/MenuItem.js +1 -1
  61. package/components/notification/Notification.js +1 -1
  62. package/components/overlay/OverlayTrigger.js +3 -3
  63. package/components/saveableInput/SaveableDateInput.d.ts +83 -0
  64. package/components/saveableInput/SaveableDateInput.js +122 -0
  65. package/components/selects/BaseSelectDropdown.js +1 -1
  66. package/components/selects/Multiselect.d.ts +8 -0
  67. package/components/selects/Multiselect.js +4 -4
  68. package/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  69. package/components/smoothScrollbars/SmoothScrollbars.js +3 -3
  70. package/components/statsWidget/StatsWidget.d.ts +2 -2
  71. package/components/statsWidget/StatsWidgets.d.ts +2 -2
  72. package/components/svgImage/SvgElement.d.ts +8 -0
  73. package/components/svgImage/SvgElement.js +11 -0
  74. package/components/svgImage/SvgImage.d.ts +30 -0
  75. package/components/svgImage/SvgImage.js +20 -0
  76. package/components/svgImage/svgConverter.d.ts +17 -0
  77. package/components/svgImage/svgConverter.js +78 -0
  78. package/components/svgImage/useSvgLoader.d.ts +9 -0
  79. package/components/svgImage/useSvgLoader.js +43 -0
  80. package/components/switch/Switch.d.ts +4 -0
  81. package/components/switch/Switch.js +5 -6
  82. package/components/table/TableCardsSorting.d.ts +0 -1
  83. package/components/table/TableCol.d.ts +18 -0
  84. package/components/table/TableCol.js +11 -0
  85. package/components/table/TableHead.d.ts +33 -0
  86. package/components/table/TableHead.js +11 -0
  87. package/components/table/TableSettingsDialog.js +1 -1
  88. package/components/tag/Tag.js +1 -1
  89. package/components/timepicker/TimePicker.d.ts +1 -2
  90. package/components/timepicker/TimePicker.js +35 -8
  91. package/components/tooltip/SimpleTooltip.d.ts +1 -1
  92. package/components/virtualList/VirtualList.js +1 -1
  93. package/hooks/useIsFocusWithin.d.ts +33 -0
  94. package/hooks/useIsFocusWithin.js +55 -0
  95. package/hooks/useLocationSuggestions.d.ts +27 -0
  96. package/hooks/useLocationSuggestions.js +94 -0
  97. package/hooks/useOnboarding.d.ts +17 -5
  98. package/hooks/useOnboarding.js +7 -1
  99. package/hooks/usePostMessage.js +0 -1
  100. package/hooks/useSearch.d.ts +63 -0
  101. package/hooks/useSearch.js +73 -0
  102. package/hooks/useSorting.d.ts +6 -0
  103. package/hooks/useSorting.js +7 -4
  104. package/hooks/useTableExport.d.ts +49 -0
  105. package/hooks/useTableExport.js +57 -0
  106. package/hooks/useTableSelection.d.ts +166 -0
  107. package/hooks/useTableSelection.js +201 -0
  108. package/lib/es/BarList.d.ts +2 -0
  109. package/lib/es/BarList.js +7 -0
  110. package/lib/es/SaveableDateInput.d.ts +2 -0
  111. package/lib/es/SaveableDateInput.js +7 -0
  112. package/lib/es/SvgImage.d.ts +2 -0
  113. package/lib/es/SvgImage.js +7 -0
  114. package/lib/es/TableCol.d.ts +2 -0
  115. package/lib/es/TableCol.js +7 -0
  116. package/lib/es/TableHead.d.ts +2 -0
  117. package/lib/es/TableHead.js +7 -0
  118. package/lib/es/components/actionBarItem/ActionBarItemIcon.js +1 -1
  119. package/lib/es/components/actionBarItem/ActionBarOverlay.js +1 -1
  120. package/lib/es/components/activity/Activity.d.ts +2 -2
  121. package/lib/es/components/applicationHeader/CollapsedNavItem.js +1 -0
  122. package/lib/es/components/assetTree/Tree.d.ts +20 -0
  123. package/lib/es/components/assetTree/Tree.js +74 -37
  124. package/lib/es/components/assetTree/TreeLeaf.js +1 -1
  125. package/lib/es/components/assetTree/TreeNodeContainer.d.ts +1 -1
  126. package/lib/es/components/assetTree/TreeSearch.js +1 -1
  127. package/lib/es/components/assetTree/TreeSummary.js +1 -1
  128. package/lib/es/components/assetTree/TypeCounter.d.ts +2 -0
  129. package/lib/es/components/assetTree/TypeCounter.js +1 -1
  130. package/lib/es/components/assetTree/useTreeExpansion.d.ts +4 -0
  131. package/lib/es/components/assetTree/useTreeExpansion.js +29 -0
  132. package/lib/es/components/assetTree/useTreeHeight.d.ts +1 -0
  133. package/lib/es/components/assetTree/useTreeHeight.js +64 -0
  134. package/lib/es/components/assetTree/useTreeScrollPosition.d.ts +3 -0
  135. package/lib/es/components/assetTree/useTreeScrollPosition.js +23 -0
  136. package/lib/es/components/assetTree/useTreeVirtualization.d.ts +17 -0
  137. package/lib/es/components/assetTree/useTreeVirtualization.js +76 -0
  138. package/lib/es/components/autosuggest/AutoSuggest.js +2 -1
  139. package/lib/es/components/barList/BarList.d.ts +97 -0
  140. package/lib/es/components/barList/BarList.js +45 -0
  141. package/lib/es/components/barList/useSortedBars.d.ts +2 -0
  142. package/lib/es/components/barList/useSortedBars.js +17 -0
  143. package/lib/es/components/button/ButtonToolbar.d.ts +1 -1
  144. package/lib/es/components/button/ButtonToolbar.js +1 -1
  145. package/lib/es/components/button/ToggleButton.js +0 -1
  146. package/lib/es/components/charts/PieChart.js +1 -1
  147. package/lib/es/components/clearableInput/ClearableInput.d.ts +20 -7
  148. package/lib/es/components/clearableInput/ClearableInput.js +67 -7
  149. package/lib/es/components/dialog/Dialog.js +1 -1
  150. package/lib/es/components/dialog/FrameDialog.js +1 -1
  151. package/lib/es/components/dropdown/ButtonDropdown.d.ts +11 -3
  152. package/lib/es/components/dropdown/ButtonDropdown.js +79 -64
  153. package/lib/es/components/dropdown/DropdownToggleButton.d.ts +7 -4
  154. package/lib/es/components/dropdown/DropdownToggleButton.js +11 -3
  155. package/lib/es/components/formLabel/FormLabel.d.ts +2 -2
  156. package/lib/es/components/formLabel/FormLabel.js +1 -1
  157. package/lib/es/components/listMenu/ListMenu.js +4 -1
  158. package/lib/es/components/map/components/Map.js +20 -5
  159. package/lib/es/components/map/components/constants.d.ts +2 -0
  160. package/lib/es/components/map/components/constants.js +4 -1
  161. package/lib/es/components/map/components/features/basics/InfoBubble.js +1 -1
  162. package/lib/es/components/map/components/features/layers/overlayLayers/IncidentsLayer.js +1 -1
  163. package/lib/es/components/map/utils/mapTypes.d.ts +5 -0
  164. package/lib/es/components/map/utils/rendering.d.ts +5 -2
  165. package/lib/es/components/map/utils/rendering.js +46 -39
  166. package/lib/es/components/menuItems/MenuItem.js +1 -1
  167. package/lib/es/components/notification/Notification.js +1 -1
  168. package/lib/es/components/overlay/OverlayTrigger.js +3 -3
  169. package/lib/es/components/saveableInput/SaveableDateInput.d.ts +83 -0
  170. package/lib/es/components/saveableInput/SaveableDateInput.js +125 -0
  171. package/lib/es/components/selects/BaseSelectDropdown.js +1 -1
  172. package/lib/es/components/selects/Multiselect.d.ts +8 -0
  173. package/lib/es/components/selects/Multiselect.js +4 -4
  174. package/lib/es/components/smoothScrollbars/SmoothScrollbars.d.ts +1 -0
  175. package/lib/es/components/smoothScrollbars/SmoothScrollbars.js +3 -3
  176. package/lib/es/components/statsWidget/StatsWidget.d.ts +2 -2
  177. package/lib/es/components/statsWidget/StatsWidgets.d.ts +2 -2
  178. package/lib/es/components/svgImage/SvgElement.d.ts +8 -0
  179. package/lib/es/components/svgImage/SvgElement.js +14 -0
  180. package/lib/es/components/svgImage/SvgImage.d.ts +30 -0
  181. package/lib/es/components/svgImage/SvgImage.js +23 -0
  182. package/lib/es/components/svgImage/svgConverter.d.ts +17 -0
  183. package/lib/es/components/svgImage/svgConverter.js +84 -0
  184. package/lib/es/components/svgImage/useSvgLoader.d.ts +9 -0
  185. package/lib/es/components/svgImage/useSvgLoader.js +48 -0
  186. package/lib/es/components/switch/Switch.d.ts +4 -0
  187. package/lib/es/components/switch/Switch.js +5 -6
  188. package/lib/es/components/table/TableCardsSorting.d.ts +0 -1
  189. package/lib/es/components/table/TableCol.d.ts +18 -0
  190. package/lib/es/components/table/TableCol.js +13 -0
  191. package/lib/es/components/table/TableHead.d.ts +33 -0
  192. package/lib/es/components/table/TableHead.js +14 -0
  193. package/lib/es/components/table/TableSettingsDialog.js +1 -1
  194. package/lib/es/components/tag/Tag.js +1 -1
  195. package/lib/es/components/timepicker/TimePicker.d.ts +1 -2
  196. package/lib/es/components/timepicker/TimePicker.js +35 -8
  197. package/lib/es/components/tooltip/SimpleTooltip.d.ts +1 -1
  198. package/lib/es/components/virtualList/VirtualList.js +1 -1
  199. package/lib/es/hooks/useIsFocusWithin.d.ts +33 -0
  200. package/lib/es/hooks/useIsFocusWithin.js +57 -0
  201. package/lib/es/hooks/useLocationSuggestions.d.ts +27 -0
  202. package/lib/es/hooks/useLocationSuggestions.js +97 -0
  203. package/lib/es/hooks/useOnboarding.d.ts +17 -5
  204. package/lib/es/hooks/useOnboarding.js +7 -1
  205. package/lib/es/hooks/usePostMessage.js +0 -1
  206. package/lib/es/hooks/useSearch.d.ts +63 -0
  207. package/lib/es/hooks/useSearch.js +75 -0
  208. package/lib/es/hooks/useSorting.d.ts +6 -0
  209. package/lib/es/hooks/useSorting.js +7 -4
  210. package/lib/es/hooks/useTableExport.d.ts +49 -0
  211. package/lib/es/hooks/useTableExport.js +59 -0
  212. package/lib/es/hooks/useTableSelection.d.ts +166 -0
  213. package/lib/es/hooks/useTableSelection.js +210 -0
  214. package/lib/es/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
  215. package/lib/es/useIsFocusWithin.d.ts +2 -0
  216. package/lib/es/useIsFocusWithin.js +7 -0
  217. package/lib/es/useLocationSuggestions.d.ts +2 -0
  218. package/lib/es/useLocationSuggestions.js +7 -0
  219. package/lib/es/useSearch.d.ts +2 -0
  220. package/lib/es/useSearch.js +7 -0
  221. package/lib/es/useTableExport.d.ts +2 -0
  222. package/lib/es/useTableExport.js +7 -0
  223. package/lib/es/useTableSelection.d.ts +2 -0
  224. package/lib/es/useTableSelection.js +7 -0
  225. package/lib/es/utils/storageUtils.d.ts +2 -2
  226. package/lib/es/utils/storageUtils.js +2 -0
  227. package/lib/es/utils/urlFeatureToggles.d.ts +12 -6
  228. package/lib/es/utils/urlFeatureToggles.js +14 -8
  229. package/lib/es/utils/useDropDirection.js +1 -0
  230. package/lib/es/version.json +1 -1
  231. package/package.json +48 -40
  232. package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
  233. package/useIsFocusWithin.d.ts +2 -0
  234. package/useIsFocusWithin.js +2 -0
  235. package/useLocationSuggestions.d.ts +2 -0
  236. package/useLocationSuggestions.js +2 -0
  237. package/useSearch.d.ts +2 -0
  238. package/useSearch.js +2 -0
  239. package/useTableExport.d.ts +2 -0
  240. package/useTableExport.js +2 -0
  241. package/useTableSelection.d.ts +2 -0
  242. package/useTableSelection.js +2 -0
  243. package/utils/storageUtils.d.ts +2 -2
  244. package/utils/storageUtils.js +2 -0
  245. package/utils/urlFeatureToggles.d.ts +12 -6
  246. package/utils/urlFeatureToggles.js +10 -7
  247. package/utils/useDropDirection.js +1 -0
  248. package/version.json +1 -1
package/BarList.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/barList/BarList';
2
+ export * from './components/barList/BarList';
package/BarList.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/barList/BarList';
2
+ export * from './components/barList/BarList';
package/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  The documentation and how to integrate the UIKIT in your project can be found here: https://uikit.developers.rio.cloud/
6
6
 
7
+ ## Changelog
8
+
9
+ All changes, updates, and improvements for each version are documented in the changelog (https://uikit.developers.rio.cloud/#start/changelog). Refer to it for a detailed overview of new features, bug fixes, and other modifications.
10
+
7
11
  ## Release
8
12
 
9
13
  Starting with version `0.12.8`, all versions of the uikit will be available under https://uikit.developers.rio.cloud/${VERSION}/.
@@ -0,0 +1,2 @@
1
+ export { default } from './components/saveableInput/SaveableDateInput';
2
+ export * from './components/saveableInput/SaveableDateInput';
@@ -0,0 +1,2 @@
1
+ export { default } from './components/saveableInput/SaveableDateInput';
2
+ export * from './components/saveableInput/SaveableDateInput';
package/SvgImage.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/svgImage/SvgImage';
2
+ export * from './components/svgImage/SvgImage';
package/SvgImage.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/svgImage/SvgImage';
2
+ export * from './components/svgImage/SvgImage';
package/TableCol.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/table/TableCol';
2
+ export * from './components/table/TableCol';
package/TableCol.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/table/TableCol';
2
+ export * from './components/table/TableCol';
package/TableHead.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/table/TableHead';
2
+ export * from './components/table/TableHead';
package/TableHead.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default } from './components/table/TableHead';
2
+ export * from './components/table/TableHead';
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import { forwardRef } from 'react';
4
4
  import classNames from 'classnames';
5
5
  const ActionBarItemIcon = forwardRef((props, ref) => {
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import { forwardRef } from 'react';
4
4
  import classNames from 'classnames';
5
5
  import noop from 'lodash/fp/noop';
@@ -7,13 +7,13 @@ declare const STATUS_MAP: {
7
7
  readonly RESTING: "resting";
8
8
  readonly WORKING: "working";
9
9
  };
10
- type ActivityStatus = ObjectValues<typeof STATUS_MAP>;
10
+ export type ActivityStatus = ObjectValues<typeof STATUS_MAP>;
11
11
  declare const SIZE_MAP: {
12
12
  readonly SIZE_SM: "sm";
13
13
  readonly SIZE_LG: "lg";
14
14
  readonly SIZE_XL: "xl";
15
15
  };
16
- type ActivitySize = ObjectValues<typeof SIZE_MAP>;
16
+ export type ActivitySize = ObjectValues<typeof SIZE_MAP>;
17
17
  export type ActivityProps = {
18
18
  /**
19
19
  * Defines the type of activity.
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
2
3
  import { forwardRef } from 'react';
3
4
  import isEmpty from 'lodash/fp/isEmpty';
4
5
  const CollapsedNavItem = forwardRef((props, ref) => {
@@ -150,6 +150,14 @@ export type TreeProps = {
150
150
  * @default false
151
151
  */
152
152
  hideSummary?: boolean;
153
+ /**
154
+ * Callback triggered when the built-in asset type filter changes.
155
+ * This is only available when the default summary is used.
156
+ *
157
+ * @param type
158
+ * @returns
159
+ */
160
+ onTypeFilterChange?: (currentTypes: string[]) => void;
153
161
  /**
154
162
  * Defines whether the entire area below the search field is shown or not. Note: Disabling the
155
163
  * tree head will hide the select all checkbox and the tree options as well as the tree summary.
@@ -192,6 +200,18 @@ export type TreeProps = {
192
200
  * @default false
193
201
  */
194
202
  disableAnimation?: boolean;
203
+ /**
204
+ * The number of items (including groups and children) used for virtualizing the tree.
205
+ *
206
+ * @default 50
207
+ */
208
+ virtualizeThreshold?: number;
209
+ /**
210
+ * The number of items rendered beyond the visible area of a virtualized tree.
211
+ *
212
+ * @default 5
213
+ */
214
+ overscan?: number;
195
215
  /**
196
216
  * Additional classes added to the wrapping element.
197
217
  */
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /* eslint-disable no-use-before-define */
3
- import React, { useEffect, useReducer, useRef, useState } from 'react';
3
+ import React, { useCallback, useEffect, useReducer, useRef } from 'react';
4
4
  import classNames from 'classnames';
5
5
  import isNil from 'lodash/fp/isNil';
6
6
  import isEmpty from 'lodash/fp/isEmpty';
@@ -27,6 +27,11 @@ import TreeRoot from './TreeRoot';
27
27
  import TypeCounter from './TypeCounter';
28
28
  import { containsItemById, debounceFn, filterAssetByType, filterEmptyGroups, filterOutByItemId, getTypeCounts, getFlatItems, getListIds, notEmpty, notEqual, excludeFromList, getMappedItemsToGroups, sortGroupItemsByName, sortGroupsByName, addOrRemoveFromList, } from './treeUtils';
29
29
  import { treeReducer, assetCounted, allCheckedChanged, visibleTypeCountersChanged, searchValueChanged, flatItemsChanged, emptyGroupsChanged, groupedItemsChanged, typeFilterChanged, } from './treeReducer';
30
+ import { useTreeVirtualization } from './useTreeVirtualization';
31
+ import { useTreeExpansion } from './useTreeExpansion';
32
+ import { useTreeHeight } from './useTreeHeight';
33
+ import { useTreeScrollPosition } from './useTreeScrollPosition';
34
+ import SmoothScrollbars from '../../SmoothScrollbars';
30
35
  export { getTypeCounts, getSubTypeCounts } from './treeUtils';
31
36
  const filterProps = omit([
32
37
  'expandedGroups',
@@ -36,8 +41,10 @@ const filterProps = omit([
36
41
  'treeOptions',
37
42
  ]);
38
43
  const customCompare = (prevProps, nextProps) => isEqual(filterProps(prevProps), filterProps(nextProps));
44
+ const VIRTUALIZED_THRESHOLD = 50;
45
+ const DEFAULT_VIRTUALIZED_OVERSCAN = 5;
39
46
  const Tree = React.memo((props) => {
40
- const { groups = [], items = [], selectedGroups = [], selectedItems = [], onSelectionChange = noop, hasMultiselect = true, showRadioButtons = false, hideSearch = false, hideTreeHead, treeHeaderContent, summary, hideSummary = false, search, searchPlaceholder = 'Type here to filter by name', onSearchChange = noop, className, scrollHeight, expandedGroups, onExpandGroupsChange = noop, showEmptyGroups = true, treeOptions = [], treeOptionsTooltip, disableAnimation = false, ...remainingProps } = props;
47
+ const { groups = [], items = [], selectedGroups = [], selectedItems = [], onSelectionChange = noop, hasMultiselect = true, showRadioButtons = false, hideSearch = false, hideTreeHead, treeHeaderContent, summary, hideSummary = false, search, searchPlaceholder = 'Type here to filter by name', onSearchChange = noop, className, scrollHeight, expandedGroups, onExpandGroupsChange = noop, showEmptyGroups = true, treeOptions = [], treeOptionsTooltip, disableAnimation = false, onTypeFilterChange = noop, virtualizeThreshold = VIRTUALIZED_THRESHOLD, overscan = DEFAULT_VIRTUALIZED_OVERSCAN, ...remainingProps } = props;
41
48
  const [state, dispatch] = useReducer(treeReducer, {
42
49
  groupedItems: [],
43
50
  flatItems: [],
@@ -52,7 +59,26 @@ const Tree = React.memo((props) => {
52
59
  const previousItems = useRef();
53
60
  const previousGroups = useRef();
54
61
  const previousSearchValue = useRef('');
55
- const internalExpandedGroups = useRef(expandedGroups);
62
+ const { internalExpandedGroups, handleToggleNode } = useTreeExpansion(props.expandedGroups, props.onExpandGroupsChange);
63
+ const hasGroups = () => groups && notEmpty(groups);
64
+ const hasInternalSearchValue = () => notEmpty(state.searchValue);
65
+ const hasSearchAndGroups = () => hasInternalSearchValue() && hasGroups();
66
+ const hasNoSearchAndGroups = () => !hasInternalSearchValue() && hasGroups();
67
+ const scrollElementRef = useRef(null);
68
+ const { virtualizedItems, virtualizer } = useTreeVirtualization(state.groupedItems, state.flatItems, hasInternalSearchValue(), hasGroups(), internalExpandedGroups, scrollElementRef, overscan);
69
+ const { scrollToTop } = useTreeScrollPosition(virtualizer, scrollElementRef);
70
+ // Enhance the handleToggleNode function
71
+ const enhancedHandleToggleNode = useCallback((nodeId) => {
72
+ // Execute the original toggle logic
73
+ handleToggleNode(nodeId);
74
+ }, [handleToggleNode]);
75
+ // Create a callback for scroll events that works with the virtualizer
76
+ const handleVirtualizedScroll = useCallback((event) => {
77
+ if (virtualizer && event?.target) {
78
+ const scrollElement = event.target;
79
+ virtualizer.scrollToOffset(scrollElement.scrollTop, { align: 'start' });
80
+ }
81
+ }, [virtualizer]);
56
82
  useEffect(() => {
57
83
  // Update Tree when items or groups have changed
58
84
  if (notEqual(previousItems.current, items) || notEqual(previousGroups.current, groups)) {
@@ -79,12 +105,6 @@ const Tree = React.memo((props) => {
79
105
  useEffect(() => makeTree(groups, items), [state.typeFilter]);
80
106
  // Update tree when empty groups are toggled from outside
81
107
  useEffect(() => makeTree(groups, items), [showEmptyGroups]);
82
- // Update expanded groups from outside
83
- const [previousExpandedGroups, setPreviousExpandedGroups] = useState(expandedGroups);
84
- if (!isEqual(expandedGroups, previousExpandedGroups)) {
85
- internalExpandedGroups.current = expandedGroups;
86
- setPreviousExpandedGroups(expandedGroups);
87
- }
88
108
  // Update "select all" state from outside when groups are selected outside programmatically
89
109
  // without using the "select all" checkbox
90
110
  useEffect(() => {
@@ -115,28 +135,6 @@ const Tree = React.memo((props) => {
115
135
  const unselectedItems = updatedItems.filter(filterOutByItemId(updatedSelectedItems));
116
136
  return isEmpty(unselectedItems);
117
137
  };
118
- const handleToggleNode = (nodeId) => {
119
- const nodeContainer = getNodeContainerDomElementById(nodeId);
120
- if (!internalExpandedGroups?.current || !nodeContainer) {
121
- return;
122
- }
123
- const openGroups = internalExpandedGroups.current;
124
- const newExpandedNodes = openGroups.includes(nodeId)
125
- ? openGroups.filter(item => item !== nodeId)
126
- : [...openGroups, nodeId];
127
- // Performance improvement to skip on render cycle and change "open" class directly
128
- if (openGroups.includes(nodeId)) {
129
- nodeContainer.classList.remove('open');
130
- }
131
- else {
132
- nodeContainer.classList.add('open');
133
- }
134
- internalExpandedGroups.current = newExpandedNodes;
135
- onExpandGroupsChange(newExpandedNodes);
136
- };
137
- const getNodeContainerDomElementById = (nodeId) => {
138
- return treeRef?.current?.querySelector(`.TreeNodeContainer[data-id="${nodeId}"]`);
139
- };
140
138
  const selectAllSearchResultItems = (shouldSelect) => selectAllFlatItems(shouldSelect);
141
139
  const handleSelectAll = (shouldSelect, isStateIndeterminate) => {
142
140
  const shouldSelectAll = shouldSelect && !isStateIndeterminate;
@@ -178,10 +176,13 @@ const Tree = React.memo((props) => {
178
176
  const handleSearchChange = (updatedSearchValue) => {
179
177
  onSearchChange(updatedSearchValue);
180
178
  dispatch(searchValueChanged(updatedSearchValue));
179
+ if (virtualizer) {
180
+ // Every time search changes or is cleared, scroll to the top
181
+ setTimeout(() => {
182
+ scrollToTop();
183
+ }, 10);
184
+ }
181
185
  };
182
- const hasGroups = () => groups && notEmpty(groups);
183
- const hasSearchAndGroups = () => hasInternalSearchValue() && hasGroups();
184
- const hasNoSearchAndGroups = () => !hasInternalSearchValue() && hasGroups();
185
186
  const setFlatItemList = (updatedItems, searchValue) => {
186
187
  const flatItems = getFlatItems(updatedItems, searchValue);
187
188
  dispatch(flatItemsChanged(flatItems));
@@ -218,30 +219,64 @@ const Tree = React.memo((props) => {
218
219
  [otherwise, setFlatItems],
219
220
  ])();
220
221
  };
222
+ const containerHeight = useTreeHeight(treeRef, scrollHeight);
223
+ const renderVirtualizedTree = () => {
224
+ const items = virtualizer.getVirtualItems();
225
+ const isGroupedList = hasGroups() && !hasInternalSearchValue();
226
+ return (_jsx(SmoothScrollbars, { ref: scrollElementRef, className: 'tree-virtual-scrollbar', onScroll: handleVirtualizedScroll, autoHeight: false, slideIn: true, style: {
227
+ height: `${containerHeight}px`,
228
+ }, children: _jsx("div", { className: isGroupedList ? 'grouped-list' : 'flat-list', style: {
229
+ height: `${virtualizer.getTotalSize()}px`,
230
+ position: 'relative',
231
+ }, children: items.map(virtualItem => {
232
+ const item = virtualizedItems[virtualItem.index];
233
+ if (!item) {
234
+ return null;
235
+ }
236
+ const isGroupSelected = selectedGroups.includes(item.id) ||
237
+ (item.type === 'leaf' && selectedGroups.includes(item.groupId));
238
+ return (_jsx("div", { "data-index": virtualItem.index, ref: virtualizer.measureElement, className: `virtualized-tree-item ${item.type === 'group' ? 'group-item' : 'leaf-item'} ${isGroupSelected ? 'checked' : ''}`, style: {
239
+ position: 'absolute',
240
+ top: 0,
241
+ left: 0,
242
+ width: '100%',
243
+ height: `${virtualItem.size}px`,
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 &&
246
+ item.data.items.some(groupItem => selectedItems.includes(groupItem.id)) }) }, item.id)) : (
247
+ // Render individual leaf item with proper styling
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}`));
249
+ }) }) }));
250
+ };
221
251
  const renderTree = () => {
222
252
  const { groupedItems } = state;
223
253
  if (isEmpty(groupedItems)) {
224
254
  return _jsx(TreeNothingFound, {});
225
255
  }
256
+ if (virtualizedItems.length > virtualizeThreshold) {
257
+ return renderVirtualizedTree();
258
+ }
226
259
  const result = map((group) => {
227
260
  const groupId = group.id;
228
261
  const groupItems = group.items;
229
- const isOpen = internalExpandedGroups.current?.includes(groupId) ?? false;
262
+ const isOpen = internalExpandedGroups?.includes(groupId) ?? false;
230
263
  const numSelectedGroupItems = filter(containsItemById(selectedItems))(groupItems).length;
231
264
  const isGroupSelected = selectedGroups.includes(groupId);
232
265
  const isStateIndeterminate = !isGroupSelected && numSelectedGroupItems > 0;
233
- return (_jsxs(TreeNodeContainer, { groupId: groupId, isOpen: isOpen, disableAnimation: disableAnimation, children: [_jsx(TreeNode, { node: group, hasMultiselect: hasMultiselect, onToggleNode: handleToggleNode, onSelect: handleGroupSelection, isSelected: isGroupSelected, isIndeterminate: isStateIndeterminate }), _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 && (_jsx(TreeLeafList, { leafList: groupItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }))] }, groupId));
234
267
  })(groupedItems);
235
268
  return result;
236
269
  };
237
270
  const renderFlatList = () => {
238
271
  const { flatItems } = state;
239
272
  const hasLeafs = isEmpty(flatItems);
273
+ if (virtualizedItems.length > virtualizeThreshold) {
274
+ return renderVirtualizedTree();
275
+ }
240
276
  const getLeafs = () => (_jsx(TreeLeafList, { leafList: flatItems, hasMultiselect: hasMultiselect, showRadioButtons: showRadioButtons, selectedItems: selectedItems, selectedGroups: selectedGroups, onSelectionChange: respondSelection }));
241
277
  return (_jsx(TreeNodeContainer, { disableAnimation: disableAnimation, isOpen: true, children: hasLeafs ? _jsx(TreeNothingFound, {}) : getLeafs() }));
242
278
  };
243
279
  const hasExternalGroups = notEmpty(groups);
244
- const hasInternalSearchValue = () => notEmpty(state.searchValue);
245
280
  const hasSelectedAllItems = () => isEqual(size(selectedItems), size(state.flatItems));
246
281
  const hasPartiallySelectedItems = () => notEmpty(selectedItems) && !hasSelectedAllItems();
247
282
  const hasSelectedAllGroups = () => {
@@ -261,7 +296,9 @@ const Tree = React.memo((props) => {
261
296
  [otherwise, () => renderFlatList()],
262
297
  ])();
263
298
  const handleFilterByType = (type) => {
264
- dispatch(typeFilterChanged(addOrRemoveFromList(state.typeFilter, type)));
299
+ const updatedTypeFilter = addOrRemoveFromList(state.typeFilter, type);
300
+ dispatch(typeFilterChanged(updatedTypeFilter));
301
+ onTypeFilterChange(updatedTypeFilter);
265
302
  };
266
303
  const enableActivity = size(state.visibleTypeCounters) !== 1;
267
304
  const isFilterActive = notEmpty(state.typeFilter);
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import React from 'react';
4
4
  import classNames from 'classnames';
5
5
  import isObject from 'lodash/fp/isObject';
@@ -1,4 +1,4 @@
1
- import { type PropsWithChildren } from 'react';
1
+ import type { PropsWithChildren } from 'react';
2
2
  export type TreeNodeContainerProps = {
3
3
  isOpen: boolean;
4
4
  groupId?: string;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import React from 'react';
4
4
  import classNames from 'classnames';
5
5
  import noop from 'lodash/fp/noop';
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import React from 'react';
4
4
  import classNames from 'classnames';
5
5
  import TypeCounter from './TypeCounter';
@@ -33,6 +33,8 @@ export type TypeCounterProps = {
33
33
  hideOnZero?: boolean;
34
34
  /**
35
35
  * Callback function when the counter is clicked. It returns the type value.
36
+ * Make sure the "type" prop is defined to receive the value in the callback.
37
+ *
36
38
  * @param type
37
39
  * @returns
38
40
  */
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // @ts-ignore-next-line importsNotUsedAsValues
2
+ // biome-ignore lint/style/useImportType: required for JSX runtime compatibility with older toolchains
3
3
  import { forwardRef, useRef } from 'react';
4
4
  import classNames from 'classnames';
5
5
  import noop from 'lodash/fp/noop';
@@ -0,0 +1,4 @@
1
+ export declare const useTreeExpansion: (expandedGroups?: string[], onExpandGroupsChange?: (groups: string[]) => void) => {
2
+ internalExpandedGroups: string[] | undefined;
3
+ handleToggleNode: (nodeId: string) => void;
4
+ };
@@ -0,0 +1,25 @@
1
+ import { useState } from 'react';
2
+ import { isEqual } from 'lodash/fp';
3
+ export const useTreeExpansion = (expandedGroups, onExpandGroupsChange) => {
4
+ const [internalExpandedGroups, setInternalExpandedGroups] = useState(expandedGroups);
5
+ const [previousExpandedGroups, setPreviousExpandedGroups] = useState(expandedGroups);
6
+ // Sync with external prop changes and update expanded groups from outside in case
7
+ if (!isEqual(expandedGroups, previousExpandedGroups)) {
8
+ setInternalExpandedGroups(expandedGroups);
9
+ setPreviousExpandedGroups(expandedGroups);
10
+ }
11
+ const handleToggleNode = (nodeId) => {
12
+ if (!internalExpandedGroups) {
13
+ return;
14
+ }
15
+ const newExpandedNodes = internalExpandedGroups.includes(nodeId)
16
+ ? internalExpandedGroups.filter(item => item !== nodeId)
17
+ : [...internalExpandedGroups, nodeId];
18
+ setInternalExpandedGroups(newExpandedNodes);
19
+ onExpandGroupsChange?.(newExpandedNodes);
20
+ };
21
+ return {
22
+ internalExpandedGroups,
23
+ handleToggleNode,
24
+ };
25
+ };
@@ -0,0 +1 @@
1
+ export declare const useTreeHeight: (treeRef: React.RefObject<HTMLDivElement>, scrollHeight?: number) => number;
@@ -0,0 +1,60 @@
1
+ import { useEffect, useState } from 'react';
2
+ const DEFAULT_TREE_ROOT_HEIGHT = 300;
3
+ export const useTreeHeight = (treeRef, scrollHeight) => {
4
+ const [containerHeight, setContainerHeight] = useState(350);
5
+ // Enhanced height calculation with multiple fallback strategies
6
+ useEffect(() => {
7
+ const calculateHeight = () => {
8
+ if (!treeRef.current) {
9
+ return DEFAULT_TREE_ROOT_HEIGHT;
10
+ }
11
+ const parentElement = treeRef.current;
12
+ const treeHeaderElement = parentElement.querySelector('.TreeHeader');
13
+ if (scrollHeight) {
14
+ // Use scrollHeight prop if provided
15
+ return scrollHeight;
16
+ }
17
+ const treeRoot = treeRef.current.querySelector('.TreeRoot');
18
+ return treeRoot?.clientHeight ?? DEFAULT_TREE_ROOT_HEIGHT;
19
+ };
20
+ const updateHeight = () => {
21
+ const newHeight = calculateHeight();
22
+ setContainerHeight(newHeight);
23
+ };
24
+ // Debounce height updates to avoid excessive recalculations
25
+ let timeoutId;
26
+ const debouncedUpdate = () => {
27
+ clearTimeout(timeoutId);
28
+ timeoutId = setTimeout(updateHeight, 16); // ~60fps
29
+ };
30
+ // Initial calculation with small delay to ensure DOM is ready
31
+ const initialTimeout = setTimeout(updateHeight, 50);
32
+ // Set up observers
33
+ const resizeObserver = new ResizeObserver(debouncedUpdate);
34
+ const mutationObserver = new MutationObserver(debouncedUpdate);
35
+ if (treeRef.current) {
36
+ // Watch parent for size changes
37
+ resizeObserver.observe(treeRef.current);
38
+ if (treeRef.current.parentElement) {
39
+ resizeObserver.observe(treeRef.current.parentElement);
40
+ }
41
+ // Watch for DOM changes that might affect layout
42
+ mutationObserver.observe(treeRef.current, {
43
+ childList: true,
44
+ subtree: true,
45
+ attributes: true,
46
+ attributeFilter: ['style', 'class'],
47
+ });
48
+ }
49
+ // Window resize listener
50
+ window.addEventListener('resize', debouncedUpdate);
51
+ return () => {
52
+ clearTimeout(initialTimeout);
53
+ clearTimeout(timeoutId);
54
+ resizeObserver.disconnect();
55
+ mutationObserver.disconnect();
56
+ window.removeEventListener('resize', debouncedUpdate);
57
+ };
58
+ }, [scrollHeight, treeRef]); // Re-run if scrollHeight prop changes or treeRef changes
59
+ return containerHeight;
60
+ };
@@ -0,0 +1,3 @@
1
+ export declare const useTreeScrollPosition: (virtualizer: any, scrollElementRef: React.RefObject<any>) => {
2
+ scrollToTop: () => void;
3
+ };
@@ -0,0 +1,19 @@
1
+ import { useCallback, useRef } from 'react';
2
+ export const useTreeScrollPosition = (virtualizer, scrollElementRef) => {
3
+ const scrollOffsetRef = useRef(0);
4
+ const scrollToTop = useCallback(() => {
5
+ if (scrollElementRef.current) {
6
+ requestAnimationFrame(() => {
7
+ // Reset scroll position to top
8
+ scrollElementRef.current.scrollTop(0);
9
+ // Also reset the stored scroll offset
10
+ scrollOffsetRef.current = 0;
11
+ // Force virtualizer to sync
12
+ if (virtualizer) {
13
+ virtualizer.scrollToOffset(0);
14
+ }
15
+ });
16
+ }
17
+ }, [scrollElementRef, virtualizer]);
18
+ return { scrollToTop };
19
+ };
@@ -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,71 @@
1
+ import { useMemo } from 'react';
2
+ import map from 'lodash/fp/map';
3
+ import { useVirtualizer } from '@tanstack/react-virtual';
4
+ export const useTreeVirtualization = (groupedItems, flatItems, hasSearchValue, hasGroups, internalExpandedGroups, scrollElementRef, overscan) => {
5
+ const virtualizedItems = useMemo(() => {
6
+ // When there's a search value, always show flat items (no groups)
7
+ if (hasSearchValue) {
8
+ return flatItems.map((item) => ({
9
+ type: 'leaf',
10
+ data: item,
11
+ id: item.id,
12
+ }));
13
+ }
14
+ // Virtualize grouped list, when there's no search value and we have groups
15
+ if (hasGroups) {
16
+ const flatList = [];
17
+ map((group) => {
18
+ const isExpanded = internalExpandedGroups?.includes(group.id) ?? false;
19
+ // Add the group header
20
+ flatList.push({
21
+ type: 'group',
22
+ data: group,
23
+ id: group.id,
24
+ isExpanded,
25
+ });
26
+ // Add expanded items
27
+ if (isExpanded) {
28
+ group.items.forEach((item) => {
29
+ flatList.push({
30
+ type: 'leaf',
31
+ data: item,
32
+ id: item.id,
33
+ groupId: group.id,
34
+ });
35
+ });
36
+ }
37
+ })(groupedItems);
38
+ return flatList;
39
+ }
40
+ // Virtualize flat list when no groups are provided initially
41
+ return flatItems.map((item) => ({
42
+ type: 'leaf',
43
+ data: item,
44
+ id: item.id,
45
+ }));
46
+ }, [groupedItems, flatItems, hasSearchValue, hasGroups, internalExpandedGroups]);
47
+ const virtualizer = useVirtualizer({
48
+ count: virtualizedItems.length,
49
+ // getScrollElement: () => scrollElementRef.current,
50
+ getScrollElement: () => {
51
+ // For SmoothScrollbars, we need to get the actual scroll container
52
+ if (scrollElementRef.current) {
53
+ // SmoothScrollbars exposes the scroll container through its view
54
+ const scrollbarsInstance = scrollElementRef.current;
55
+ // Access the internal scroll container
56
+ // This depends on how react-custom-scrollbars-2 exposes its internals
57
+ return scrollbarsInstance?.view;
58
+ }
59
+ return null;
60
+ },
61
+ estimateSize: () => 41, // typical single line height without line-break
62
+ measureElement: element => {
63
+ // This will measure the actual rendered height for more accuracy
64
+ return element?.children[0].clientHeight ?? 41;
65
+ },
66
+ overscan, // Render 10 extra items above and below visible area
67
+ // Add this to enable more aggressive remeasurement
68
+ lanes: 1,
69
+ });
70
+ return { virtualizedItems, virtualizer };
71
+ };
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // biome-ignore lint/style/useImportType: <explanation>
2
3
  import { useEffect, useRef, useState } from 'react';
3
4
  import classNames from 'classnames';
4
5
  import isEmpty from 'lodash/fp/isEmpty';
@@ -21,7 +22,7 @@ export const AutoSuggest = (props) => {
21
22
  onClear: noop,
22
23
  onBlur: noop,
23
24
  onFocus: noop,
24
- placeholder: 'Start typing ...',
25
+ placeholder: 'Start typing',
25
26
  hasError: false,
26
27
  tabIndex: 0,
27
28
  value: undefined,