@rio-cloud/rio-uikit 2.1.0 → 2.2.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 (445) hide show
  1. package/CircularProgress.d.ts +2 -0
  2. package/CircularProgress.js +5 -0
  3. package/CircularProgress.js.map +1 -0
  4. package/RadioCardGroup.d.ts +2 -0
  5. package/RadioCardGroup.js +7 -0
  6. package/RadioCardGroup.js.map +1 -0
  7. package/SearchHighlightText.d.ts +2 -0
  8. package/SearchHighlightText.js +5 -0
  9. package/SearchHighlightText.js.map +1 -0
  10. package/TextTruncateMiddle.d.ts +2 -0
  11. package/TextTruncateMiddle.js +5 -0
  12. package/TextTruncateMiddle.js.map +1 -0
  13. package/Tracker.d.ts +2 -0
  14. package/Tracker.js +5 -0
  15. package/Tracker.js.map +1 -0
  16. package/classNames.d.ts +2 -0
  17. package/classNames.js +5 -0
  18. package/classNames.js.map +1 -0
  19. package/components/accentBar/AccentBar.js +1 -1
  20. package/components/accentBar/AccentBar.js.map +1 -1
  21. package/components/actionBarItem/ActionBarItem.js +7 -7
  22. package/components/actionBarItem/ActionBarItem.js.map +1 -1
  23. package/components/actionBarItem/ActionBarItemIcon.js +1 -1
  24. package/components/actionBarItem/ActionBarItemIcon.js.map +1 -1
  25. package/components/actionBarItem/ActionBarItemList.js +1 -1
  26. package/components/actionBarItem/ActionBarItemList.js.map +1 -1
  27. package/components/actionBarItem/ActionBarItemListItem.js +1 -1
  28. package/components/actionBarItem/ActionBarItemListItem.js.map +1 -1
  29. package/components/actionBarItem/ActionBarItemListSeparator.js +1 -1
  30. package/components/actionBarItem/ActionBarItemListSeparator.js.map +1 -1
  31. package/components/actionBarItem/ActionBarItemPopoverContent.js +3 -3
  32. package/components/actionBarItem/ActionBarItemPopoverContent.js.map +1 -1
  33. package/components/actionBarItem/ActionBarOverlay.js +1 -1
  34. package/components/actionBarItem/ActionBarOverlay.js.map +1 -1
  35. package/components/activity/Activity.js +1 -1
  36. package/components/activity/Activity.js.map +1 -1
  37. package/components/animatedTextReveal/AnimatedTextReveal.js +1 -1
  38. package/components/animatedTextReveal/AnimatedTextReveal.js.map +1 -1
  39. package/components/applicationHeader/AppMenu.js +2 -2
  40. package/components/applicationHeader/AppMenu.js.map +1 -1
  41. package/components/applicationHeader/AppMenuDropdown.js +13 -11
  42. package/components/applicationHeader/AppMenuDropdown.js.map +1 -1
  43. package/components/applicationHeader/ApplicationHeader.js +1 -1
  44. package/components/applicationHeader/ApplicationHeader.js.map +1 -1
  45. package/components/applicationHeader/MobileHeaderModal.js +8 -8
  46. package/components/applicationHeader/MobileHeaderModal.js.map +1 -1
  47. package/components/applicationHeader/MobileSubmoduleNavigation.js +1 -1
  48. package/components/applicationHeader/MobileSubmoduleNavigation.js.map +1 -1
  49. package/components/applicationHeader/NavItems.js +4 -4
  50. package/components/applicationHeader/NavItems.js.map +1 -1
  51. package/components/applicationLayout/ApplicationLayout.js +10 -10
  52. package/components/applicationLayout/ApplicationLayout.js.map +1 -1
  53. package/components/applicationLayout/ApplicationLayoutBody.js +2 -2
  54. package/components/applicationLayout/ApplicationLayoutBody.js.map +1 -1
  55. package/components/applicationLayout/ApplicationLayoutBodyBanner.js +1 -1
  56. package/components/applicationLayout/ApplicationLayoutBodyBanner.js.map +1 -1
  57. package/components/applicationLayout/ApplicationLayoutBodyBottomBar.js +1 -1
  58. package/components/applicationLayout/ApplicationLayoutBodyBottomBar.js.map +1 -1
  59. package/components/applicationLayout/ApplicationLayoutBodyNavigation.js +1 -1
  60. package/components/applicationLayout/ApplicationLayoutBodyNavigation.js.map +1 -1
  61. package/components/applicationLayout/ApplicationLayoutHeader.js +1 -1
  62. package/components/applicationLayout/ApplicationLayoutHeader.js.map +1 -1
  63. package/components/applicationLayout/ApplicationLayoutSidebar.js +1 -1
  64. package/components/applicationLayout/ApplicationLayoutSidebar.js.map +1 -1
  65. package/components/applicationLayout/SubNavigation.js +1 -1
  66. package/components/applicationLayout/SubNavigation.js.map +1 -1
  67. package/components/assetTree/AssetTree.js +1 -1
  68. package/components/assetTree/AssetTree.js.map +1 -1
  69. package/components/assetTree/Tree.js +1 -1
  70. package/components/assetTree/Tree.js.map +1 -1
  71. package/components/assetTree/TreeIcon.js +3 -3
  72. package/components/assetTree/TreeIcon.js.map +1 -1
  73. package/components/assetTree/TreeLeaf.js +4 -4
  74. package/components/assetTree/TreeLeaf.js.map +1 -1
  75. package/components/assetTree/TreeNode.js +1 -1
  76. package/components/assetTree/TreeNode.js.map +1 -1
  77. package/components/assetTree/TreeNodeContainer.js +1 -1
  78. package/components/assetTree/TreeNodeContainer.js.map +1 -1
  79. package/components/assetTree/TreeOption.js +3 -3
  80. package/components/assetTree/TreeOption.js.map +1 -1
  81. package/components/assetTree/TreeOptions.js +4 -4
  82. package/components/assetTree/TreeOptions.js.map +1 -1
  83. package/components/assetTree/TreeRoot.js +3 -3
  84. package/components/assetTree/TreeRoot.js.map +1 -1
  85. package/components/assetTree/TreeSearch.js +3 -3
  86. package/components/assetTree/TreeSearch.js.map +1 -1
  87. package/components/assetTree/TreeSidebar.js +1 -1
  88. package/components/assetTree/TreeSidebar.js.map +1 -1
  89. package/components/assetTree/TreeSidebarCategories.js +4 -4
  90. package/components/assetTree/TreeSidebarCategories.js.map +1 -1
  91. package/components/assetTree/TreeSummary.js +1 -1
  92. package/components/assetTree/TreeSummary.js.map +1 -1
  93. package/components/assetTree/TypeCounter.js +1 -1
  94. package/components/assetTree/TypeCounter.js.map +1 -1
  95. package/components/autosuggest/AutoSuggest.js +1 -1
  96. package/components/autosuggest/AutoSuggest.js.map +1 -1
  97. package/components/avatar/Avatar.js +1 -1
  98. package/components/avatar/Avatar.js.map +1 -1
  99. package/components/banner/Banner.js +1 -1
  100. package/components/banner/Banner.js.map +1 -1
  101. package/components/banner/BannerContent.js +1 -1
  102. package/components/banner/BannerContent.js.map +1 -1
  103. package/components/barList/BarList.js +1 -1
  104. package/components/barList/BarList.js.map +1 -1
  105. package/components/bottomSheet/BottomSheet.js +1 -1
  106. package/components/bottomSheet/BottomSheet.js.map +1 -1
  107. package/components/button/Button.d.ts +53 -7
  108. package/components/button/Button.js +87 -64
  109. package/components/button/Button.js.map +1 -1
  110. package/components/button/ButtonToolbar.js +1 -1
  111. package/components/button/ButtonToolbar.js.map +1 -1
  112. package/components/button/ToggleButton.d.ts +4 -1
  113. package/components/button/ToggleButton.js.map +1 -1
  114. package/components/calendarStripe/CalendarStripe.js +16 -16
  115. package/components/calendarStripe/CalendarStripe.js.map +1 -1
  116. package/components/card/Card.js +1 -1
  117. package/components/card/Card.js.map +1 -1
  118. package/components/charts/RadialBarChart.js +106 -103
  119. package/components/charts/RadialBarChart.js.map +1 -1
  120. package/components/checkbox/Checkbox.js +6 -6
  121. package/components/checkbox/Checkbox.js.map +1 -1
  122. package/components/circularProgress/CircularProgress.d.ts +139 -0
  123. package/components/circularProgress/CircularProgress.js +197 -0
  124. package/components/circularProgress/CircularProgress.js.map +1 -0
  125. package/components/clearableInput/ClearableInput.js +9 -9
  126. package/components/clearableInput/ClearableInput.js.map +1 -1
  127. package/components/dataTabs/DataTabHeader.js +1 -1
  128. package/components/dataTabs/DataTabHeader.js.map +1 -1
  129. package/components/dataTabs/DataTabs.js +4 -4
  130. package/components/dataTabs/DataTabs.js.map +1 -1
  131. package/components/datepicker/DatePicker.js +6 -6
  132. package/components/datepicker/DatePicker.js.map +1 -1
  133. package/components/datepicker/DateRangePicker.js +1 -1
  134. package/components/datepicker/DateRangePicker.js.map +1 -1
  135. package/components/datepicker/DayPicker.js +1 -1
  136. package/components/datepicker/DayPicker.js.map +1 -1
  137. package/components/dialog/Dialog.js +55 -55
  138. package/components/dialog/Dialog.js.map +1 -1
  139. package/components/dialog/DialogBody.js +1 -1
  140. package/components/dialog/DialogBody.js.map +1 -1
  141. package/components/dialog/DialogFooter.js +1 -1
  142. package/components/dialog/DialogFooter.js.map +1 -1
  143. package/components/dialog/DialogHeader.js +1 -1
  144. package/components/dialog/DialogHeader.js.map +1 -1
  145. package/components/dialog/MediaDialog.js +1 -1
  146. package/components/dialog/MediaDialog.js.map +1 -1
  147. package/components/dialog/SplitDialog.js +1 -1
  148. package/components/dialog/SplitDialog.js.map +1 -1
  149. package/components/divider/Divider.js +1 -1
  150. package/components/divider/Divider.js.map +1 -1
  151. package/components/dropdown/ButtonDropdown.js +1 -1
  152. package/components/dropdown/ButtonDropdown.js.map +1 -1
  153. package/components/dropdown/DropdownSubmenu.js +3 -3
  154. package/components/dropdown/DropdownSubmenu.js.map +1 -1
  155. package/components/dropdown/DropdownToggleButton.d.ts +1 -1
  156. package/components/dropdown/DropdownToggleButton.js +4 -3
  157. package/components/dropdown/DropdownToggleButton.js.map +1 -1
  158. package/components/dropdown/SplitCaretButton.js +6 -6
  159. package/components/dropdown/SplitCaretButton.js.map +1 -1
  160. package/components/editableContent/EditableContent.js +1 -1
  161. package/components/editableContent/EditableContent.js.map +1 -1
  162. package/components/ellipsis/TextTruncateMiddle.d.ts +23 -0
  163. package/components/ellipsis/TextTruncateMiddle.js +21 -0
  164. package/components/ellipsis/TextTruncateMiddle.js.map +1 -0
  165. package/components/expander/ExpanderList.js +5 -5
  166. package/components/expander/ExpanderList.js.map +1 -1
  167. package/components/expander/ExpanderPanel.js +1 -1
  168. package/components/expander/ExpanderPanel.js.map +1 -1
  169. package/components/feedback/FeedbackRating.js +1 -1
  170. package/components/feedback/FeedbackRating.js.map +1 -1
  171. package/components/feedback/FeedbackReactions.js +1 -1
  172. package/components/feedback/FeedbackReactions.js.map +1 -1
  173. package/components/formLabel/FormLabel.js +6 -9
  174. package/components/formLabel/FormLabel.js.map +1 -1
  175. package/components/formLabel/LabeledElement.js +1 -1
  176. package/components/formLabel/LabeledElement.js.map +1 -1
  177. package/components/listMenu/ListMenu.js +2 -5
  178. package/components/listMenu/ListMenu.js.map +1 -1
  179. package/components/listMenu/ListMenuGroup.js +2 -2
  180. package/components/listMenu/ListMenuGroup.js.map +1 -1
  181. package/components/loadMore/LoadMoreButton.js +1 -1
  182. package/components/loadMore/LoadMoreButton.js.map +1 -1
  183. package/components/loadMore/LoadMoreProgress.js +1 -1
  184. package/components/loadMore/LoadMoreProgress.js.map +1 -1
  185. package/components/map/components/features/MapSettings.js +4 -4
  186. package/components/map/components/features/MapSettings.js.map +1 -1
  187. package/components/map/components/features/settings/MapSettingsItem.js +1 -1
  188. package/components/map/components/features/settings/MapSettingsItem.js.map +1 -1
  189. package/components/map/components/features/settings/MapSettingsPanel.js +6 -20
  190. package/components/map/components/features/settings/MapSettingsPanel.js.map +1 -1
  191. package/components/map/components/features/settings/MapSettingsTile.js +87 -61
  192. package/components/map/components/features/settings/MapSettingsTile.js.map +1 -1
  193. package/components/map/components/features/settings/ZoomButtons.js +1 -1
  194. package/components/map/components/features/settings/ZoomButtons.js.map +1 -1
  195. package/components/map/components/features/settings/builtinSettings/MapTypeSettings.d.ts +38 -1
  196. package/components/map/components/features/settings/builtinSettings/MapTypeSettings.js +128 -92
  197. package/components/map/components/features/settings/builtinSettings/MapTypeSettings.js.map +1 -1
  198. package/components/map/utils/eventHandling.js +9 -9
  199. package/components/map/utils/eventHandling.js.map +1 -1
  200. package/components/map/utils/mapUtils.d.ts +6 -6
  201. package/components/map/utils/mapUtils.js +14 -19
  202. package/components/map/utils/mapUtils.js.map +1 -1
  203. package/components/mapMarker/ClusterMapMarker.js +1 -1
  204. package/components/mapMarker/ClusterMapMarker.js.map +1 -1
  205. package/components/mapMarker/SingleMapMarker.js +1 -1
  206. package/components/mapMarker/SingleMapMarker.js.map +1 -1
  207. package/components/menuItems/MenuItem.js +1 -1
  208. package/components/menuItems/MenuItem.js.map +1 -1
  209. package/components/menuItems/MenuItemList.js +1 -1
  210. package/components/menuItems/MenuItemList.js.map +1 -1
  211. package/components/navigation/AppNavigationBar.js +4 -4
  212. package/components/navigation/AppNavigationBar.js.map +1 -1
  213. package/components/noData/NoData.js +1 -1
  214. package/components/noData/NoData.js.map +1 -1
  215. package/components/numberControl/NumberControl.js +4 -4
  216. package/components/numberControl/NumberControl.js.map +1 -1
  217. package/components/numberInput/NumberInput.js +1 -1
  218. package/components/numberInput/NumberInput.js.map +1 -1
  219. package/components/onboarding/OnboardingTip.js +4 -4
  220. package/components/onboarding/OnboardingTip.js.map +1 -1
  221. package/components/page/Page.js +1 -1
  222. package/components/page/Page.js.map +1 -1
  223. package/components/pager/Pager.js +1 -1
  224. package/components/pager/Pager.js.map +1 -1
  225. package/components/radiobutton/RadioButton.d.ts +1 -1
  226. package/components/radiobutton/RadioButton.js +5 -5
  227. package/components/radiobutton/RadioButton.js.map +1 -1
  228. package/components/radiobutton/RadioCardGroup.d.ts +86 -0
  229. package/components/radiobutton/RadioCardGroup.js +110 -0
  230. package/components/radiobutton/RadioCardGroup.js.map +1 -0
  231. package/components/resizer/Resizer.js +1 -1
  232. package/components/resizer/Resizer.js.map +1 -1
  233. package/components/responsiveColumnStripe/ResponsiveColumnStripe.js +1 -1
  234. package/components/responsiveColumnStripe/ResponsiveColumnStripe.js.map +1 -1
  235. package/components/rioglyph/Rioglyph.js +1 -1
  236. package/components/rioglyph/Rioglyph.js.map +1 -1
  237. package/components/rioglyph/RioglyphIconType.d.ts +1 -1
  238. package/components/rules/RuleConnector.js +1 -1
  239. package/components/rules/RuleConnector.js.map +1 -1
  240. package/components/rules/RuleContainer.js +27 -27
  241. package/components/rules/RuleContainer.js.map +1 -1
  242. package/components/saveableInput/SaveableDateInput.js +1 -1
  243. package/components/saveableInput/SaveableDateInput.js.map +1 -1
  244. package/components/saveableInput/SaveableInput.js +49 -49
  245. package/components/saveableInput/SaveableInput.js.map +1 -1
  246. package/components/searchHighlight/SearchHighlightText.d.ts +28 -0
  247. package/components/searchHighlight/SearchHighlightText.js +15 -0
  248. package/components/searchHighlight/SearchHighlightText.js.map +1 -0
  249. package/components/selects/BaseSelectDropdown.js +1 -1
  250. package/components/selects/BaseSelectDropdown.js.map +1 -1
  251. package/components/selects/ClearButton.js +4 -4
  252. package/components/selects/ClearButton.js.map +1 -1
  253. package/components/selects/Multiselect.js +6 -6
  254. package/components/selects/Multiselect.js.map +1 -1
  255. package/components/selects/MultiselectToggleFilter.js +4 -4
  256. package/components/selects/MultiselectToggleFilter.js.map +1 -1
  257. package/components/selects/MultiselectToggleSelection.js +1 -1
  258. package/components/selects/MultiselectToggleSelection.js.map +1 -1
  259. package/components/selects/Select.js +6 -6
  260. package/components/selects/Select.js.map +1 -1
  261. package/components/selects/SelectFilter.js +1 -1
  262. package/components/selects/SelectFilter.js.map +1 -1
  263. package/components/selects/WithFeedbackAndAddon.js +1 -1
  264. package/components/selects/WithFeedbackAndAddon.js.map +1 -1
  265. package/components/sidebars/Sidebar.js +54 -54
  266. package/components/sidebars/Sidebar.js.map +1 -1
  267. package/components/sidebars/SidebarBackdrop.js +4 -4
  268. package/components/sidebars/SidebarBackdrop.js.map +1 -1
  269. package/components/sidebars/SidebarFooter.js +1 -1
  270. package/components/sidebars/SidebarFooter.js.map +1 -1
  271. package/components/sidebars/SidebarFullscreenToggle.js +4 -4
  272. package/components/sidebars/SidebarFullscreenToggle.js.map +1 -1
  273. package/components/slider/RangeSlider.js +1 -1
  274. package/components/slider/RangeSlider.js.map +1 -1
  275. package/components/slider/Slider.js +1 -1
  276. package/components/slider/Slider.js.map +1 -1
  277. package/components/smoothScrollbars/SmoothScrollbars.js +1 -1
  278. package/components/smoothScrollbars/SmoothScrollbars.js.map +1 -1
  279. package/components/spinner/Spinner.js +5 -4
  280. package/components/spinner/Spinner.js.map +1 -1
  281. package/components/states/CustomState.d.ts +69 -1
  282. package/components/states/CustomState.js +1 -1
  283. package/components/states/CustomState.js.map +1 -1
  284. package/components/states/EmptyState.d.ts +1 -1
  285. package/components/states/EmptyState.js.map +1 -1
  286. package/components/states/ErrorState.d.ts +1 -1
  287. package/components/states/ErrorState.js.map +1 -1
  288. package/components/states/ForbiddenState.d.ts +1 -1
  289. package/components/states/ForbiddenState.js.map +1 -1
  290. package/components/states/MaintenanceState.d.ts +1 -1
  291. package/components/states/MaintenanceState.js.map +1 -1
  292. package/components/states/NotBookedState.d.ts +1 -1
  293. package/components/states/NotBookedState.js.map +1 -1
  294. package/components/states/NotFoundState.d.ts +1 -1
  295. package/components/states/NotFoundState.js.map +1 -1
  296. package/components/states/StateButton.js +1 -1
  297. package/components/states/StateButton.js.map +1 -1
  298. package/components/statsWidget/StatsWidget.js +1 -1
  299. package/components/statsWidget/StatsWidget.js.map +1 -1
  300. package/components/statsWidget/StatsWidgetBody.js +1 -1
  301. package/components/statsWidget/StatsWidgetBody.js.map +1 -1
  302. package/components/statsWidget/StatsWidgetFooter.js +1 -1
  303. package/components/statsWidget/StatsWidgetFooter.js.map +1 -1
  304. package/components/statsWidget/StatsWidgetHeader.js +1 -1
  305. package/components/statsWidget/StatsWidgetHeader.js.map +1 -1
  306. package/components/statsWidget/StatsWidgetNumber.js +2 -2
  307. package/components/statsWidget/StatsWidgetNumber.js.map +1 -1
  308. package/components/statsWidget/StatsWidgetSpacer.js +1 -1
  309. package/components/statsWidget/StatsWidgetSpacer.js.map +1 -1
  310. package/components/statsWidget/StatsWidgets.js +1 -1
  311. package/components/statsWidget/StatsWidgets.js.map +1 -1
  312. package/components/statusBar/StatusBar.d.ts +126 -2
  313. package/components/statusBar/StatusBar.js +24 -17
  314. package/components/statusBar/StatusBar.js.map +1 -1
  315. package/components/statusBar/StatusBarIcon.d.ts +1 -1
  316. package/components/statusBar/StatusBarIcon.js +4 -4
  317. package/components/statusBar/StatusBarIcon.js.map +1 -1
  318. package/components/statusBar/StatusBarLabel.d.ts +1 -1
  319. package/components/statusBar/StatusBarLabel.js +5 -7
  320. package/components/statusBar/StatusBarLabel.js.map +1 -1
  321. package/components/statusBar/StatusBarProgressBar.d.ts +1 -1
  322. package/components/statusBar/StatusBarProgressBar.js +1 -1
  323. package/components/statusBar/StatusBarProgressBar.js.map +1 -1
  324. package/components/steppedProgressBar/SteppedProgressBar.js +1 -1
  325. package/components/steppedProgressBar/SteppedProgressBar.js.map +1 -1
  326. package/components/switch/Switch.d.ts +16 -1
  327. package/components/switch/Switch.js +77 -35
  328. package/components/switch/Switch.js.map +1 -1
  329. package/components/table/TableCardsSorting.js +4 -4
  330. package/components/table/TableCardsSorting.js.map +1 -1
  331. package/components/table/TableHead.js +1 -1
  332. package/components/table/TableHead.js.map +1 -1
  333. package/components/table/TableSearch.js +1 -1
  334. package/components/table/TableSearch.js.map +1 -1
  335. package/components/table/TableSettingsColumnButtons.d.ts +1 -1
  336. package/components/table/TableSettingsColumnButtons.js +1 -1
  337. package/components/table/TableSettingsColumnButtons.js.map +1 -1
  338. package/components/table/TableSettingsColumnDetails.d.ts +1 -1
  339. package/components/table/TableSettingsColumnDetails.js +1 -1
  340. package/components/table/TableSettingsColumnDetails.js.map +1 -1
  341. package/components/table/TableSettingsDialog.d.ts +51 -1
  342. package/components/table/TableSettingsDialog.js +164 -148
  343. package/components/table/TableSettingsDialog.js.map +1 -1
  344. package/components/table/TableSettingsDialogFooter.js +1 -1
  345. package/components/table/TableSettingsDialogFooter.js.map +1 -1
  346. package/components/table/TableSettingsListContainer.d.ts +1 -1
  347. package/components/table/TableSettingsListContainer.js.map +1 -1
  348. package/components/table/TableSettingsListItem.d.ts +1 -1
  349. package/components/table/TableSettingsListItem.js +8 -8
  350. package/components/table/TableSettingsListItem.js.map +1 -1
  351. package/components/table/TableToolbar.js +1 -1
  352. package/components/table/TableToolbar.js.map +1 -1
  353. package/components/table/TableViewToggles.js +1 -1
  354. package/components/table/TableViewToggles.js.map +1 -1
  355. package/components/tag/Tag.js +1 -1
  356. package/components/tag/Tag.js.map +1 -1
  357. package/components/tag/TagList.js +1 -1
  358. package/components/tag/TagList.js.map +1 -1
  359. package/components/tagManager/CustomSuggestionItem.js +1 -1
  360. package/components/tagManager/CustomSuggestionItem.js.map +1 -1
  361. package/components/tagManager/TagManager.d.ts +14 -2
  362. package/components/tagManager/TagManager.js +6 -6
  363. package/components/tagManager/TagManager.js.map +1 -1
  364. package/components/tagManager/TagManagerItemList.d.ts +1 -1
  365. package/components/tagManager/TagManagerItemList.js +1 -1
  366. package/components/tagManager/TagManagerItemList.js.map +1 -1
  367. package/components/teaser/Teaser.js +1 -1
  368. package/components/teaser/Teaser.js.map +1 -1
  369. package/components/teaser/TeaserContainer.js +1 -1
  370. package/components/teaser/TeaserContainer.js.map +1 -1
  371. package/components/timepicker/TimePicker.d.ts +20 -0
  372. package/components/timepicker/TimePicker.js +153 -99
  373. package/components/timepicker/TimePicker.js.map +1 -1
  374. package/components/tooltip/Tooltip.js +1 -1
  375. package/components/tooltip/Tooltip.js.map +1 -1
  376. package/components/tracker/Tracker.d.ts +85 -0
  377. package/components/tracker/Tracker.js +54 -0
  378. package/components/tracker/Tracker.js.map +1 -0
  379. package/components/tracker/TrackerBlock.d.ts +11 -0
  380. package/components/tracker/TrackerBlock.js +34 -0
  381. package/components/tracker/TrackerBlock.js.map +1 -0
  382. package/components/video/ResponsiveVideo.js +1 -1
  383. package/components/video/ResponsiveVideo.js.map +1 -1
  384. package/hooks/useCookies.d.ts +79 -0
  385. package/hooks/useCookies.js +33 -0
  386. package/hooks/useCookies.js.map +1 -0
  387. package/hooks/useInterval.js +5 -5
  388. package/hooks/useInterval.js.map +1 -1
  389. package/hooks/useIsFocusWithin.js +3 -3
  390. package/hooks/useIsFocusWithin.js.map +1 -1
  391. package/hooks/useLatest.d.ts +16 -0
  392. package/hooks/useLatest.js +11 -0
  393. package/hooks/useLatest.js.map +1 -0
  394. package/hooks/usePostMessage.d.ts +2 -1
  395. package/hooks/usePostMessage.js.map +1 -1
  396. package/hooks/useRioCookieConsent.d.ts +49 -0
  397. package/hooks/useRioCookieConsent.js +44 -0
  398. package/hooks/useRioCookieConsent.js.map +1 -0
  399. package/hooks/useSearch.d.ts +1 -1
  400. package/hooks/useSearch.js +28 -17
  401. package/hooks/useSearch.js.map +1 -1
  402. package/hooks/useSearchHighlight.d.ts +60 -0
  403. package/hooks/useSearchHighlight.js +54 -0
  404. package/hooks/useSearchHighlight.js.map +1 -0
  405. package/hooks/useTimeout.js +11 -11
  406. package/hooks/useTimeout.js.map +1 -1
  407. package/hooks/useUrlState.d.ts +62 -0
  408. package/hooks/useUrlState.js +137 -0
  409. package/hooks/useUrlState.js.map +1 -0
  410. package/mergeClassNameOverrides.d.ts +1 -0
  411. package/mergeClassNameOverrides.js +5 -0
  412. package/mergeClassNameOverrides.js.map +1 -0
  413. package/package.json +17 -18
  414. package/routeUtils.js +11 -5
  415. package/routeUtils.js.map +1 -1
  416. package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
  417. package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js.map +1 -1
  418. package/useCookies.d.ts +2 -0
  419. package/useCookies.js +5 -0
  420. package/useCookies.js.map +1 -0
  421. package/useRioCookieConsent.d.ts +2 -0
  422. package/useRioCookieConsent.js +5 -0
  423. package/useRioCookieConsent.js.map +1 -0
  424. package/useSearchHighlight.d.ts +2 -0
  425. package/useSearchHighlight.js +6 -0
  426. package/useSearchHighlight.js.map +1 -0
  427. package/useUrlState.d.ts +2 -0
  428. package/useUrlState.js +5 -0
  429. package/useUrlState.js.map +1 -0
  430. package/utils/classNames.d.ts +3 -0
  431. package/utils/classNames.js +5 -0
  432. package/utils/classNames.js.map +1 -0
  433. package/utils/mergeClassNameOverrides.d.ts +1 -0
  434. package/utils/mergeClassNameOverrides.js +55 -0
  435. package/utils/mergeClassNameOverrides.js.map +1 -0
  436. package/utils/routeUtils.d.ts +122 -13
  437. package/utils/routeUtils.js +89 -31
  438. package/utils/routeUtils.js.map +1 -1
  439. package/version.d.ts +1 -1
  440. package/version.js +1 -1
  441. package/version.js.map +1 -1
  442. package/components/states/BaseStateProps.d.ts +0 -70
  443. package/components/statusBar/StatusBarProps.d.ts +0 -127
  444. package/components/table/TableSettingsDialog.types.d.ts +0 -39
  445. package/components/tagManager/TagManagerTag.d.ts +0 -14
@@ -0,0 +1,44 @@
1
+ import { useCallback as c } from "react";
2
+ import n from "./useCookies.js";
3
+ const a = (e) => {
4
+ if (!e)
5
+ return {
6
+ cookieName: "cookie_settings",
7
+ isSet: !1,
8
+ uxCookiesAccepted: !1,
9
+ marketingCookiesAccepted: !1,
10
+ status: "missing"
11
+ };
12
+ try {
13
+ const t = JSON.parse(e), s = t["switch-49"] === 1, o = t["switch-2"] === 1;
14
+ let i = "custom";
15
+ return s && !o ? i = "ux-cookies-accepted" : !s && o && (i = "marketing-cookies-accepted"), {
16
+ cookieName: "cookie_settings",
17
+ isSet: !0,
18
+ rawValue: e,
19
+ parsedValue: {
20
+ "switch-2": Number(t["switch-2"]),
21
+ "switch-49": Number(t["switch-49"])
22
+ },
23
+ uxCookiesAccepted: s,
24
+ marketingCookiesAccepted: o,
25
+ status: i
26
+ };
27
+ } catch {
28
+ return {
29
+ cookieName: "cookie_settings",
30
+ isSet: !0,
31
+ rawValue: e,
32
+ uxCookiesAccepted: !1,
33
+ marketingCookiesAccepted: !1,
34
+ status: "invalid"
35
+ };
36
+ }
37
+ }, u = () => {
38
+ const { getCookie: e } = n();
39
+ return { getRioCookieConsentInfo: c(() => a(e("cookie_settings")), [e]) };
40
+ };
41
+ export {
42
+ u as default
43
+ };
44
+ //# sourceMappingURL=useRioCookieConsent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRioCookieConsent.js","sources":["../../src/hooks/useRioCookieConsent.ts"],"sourcesContent":["import { useCallback } from 'react';\n\nimport useCookies from './useCookies';\n\nexport type RioCookieConsentStatus =\n | 'missing'\n | 'invalid'\n | 'ux-cookies-accepted'\n | 'marketing-cookies-accepted'\n | 'custom';\n\nexport type RioCookieConsentInfo = {\n /**\n * Name of the RIO consent cookie.\n */\n cookieName: 'cookie_settings';\n\n /**\n * Indicates whether the consent cookie exists.\n */\n isSet: boolean;\n\n /**\n * Raw cookie value as read from `document.cookie`.\n */\n rawValue?: string;\n\n /**\n * Parsed and normalized cookie switches when JSON parsing succeeds.\n */\n parsedValue?: Record<string, number>;\n\n /**\n * True when UX cookies are accepted (`switch-49 === 1`).\n */\n uxCookiesAccepted: boolean;\n\n /**\n * True when marketing cookies are accepted (`switch-2 === 1`).\n */\n marketingCookiesAccepted: boolean;\n\n /**\n * Computed consent status derived from parsed cookie values.\n */\n status: RioCookieConsentStatus;\n};\n\nexport type UseRioCookieConsentResult = {\n /**\n * Reads and parses the RIO cookie consent settings.\n */\n getRioCookieConsentInfo: () => RioCookieConsentInfo;\n};\n\nconst evaluateRioCookieSettings = (cookieValue?: string): RioCookieConsentInfo => {\n if (!cookieValue) {\n return {\n cookieName: 'cookie_settings',\n isSet: false,\n uxCookiesAccepted: false,\n marketingCookiesAccepted: false,\n status: 'missing',\n };\n }\n\n try {\n const parsed = JSON.parse(cookieValue) as Record<string, unknown>;\n const uxCookiesAccepted = parsed['switch-49'] === 1;\n const marketingCookiesAccepted = parsed['switch-2'] === 1;\n\n let status: RioCookieConsentStatus = 'custom';\n if (uxCookiesAccepted && !marketingCookiesAccepted) {\n status = 'ux-cookies-accepted';\n } else if (!uxCookiesAccepted && marketingCookiesAccepted) {\n status = 'marketing-cookies-accepted';\n }\n\n return {\n cookieName: 'cookie_settings',\n isSet: true,\n rawValue: cookieValue,\n parsedValue: {\n 'switch-2': Number(parsed['switch-2']),\n 'switch-49': Number(parsed['switch-49']),\n },\n uxCookiesAccepted,\n marketingCookiesAccepted,\n status,\n };\n } catch {\n return {\n cookieName: 'cookie_settings',\n isSet: true,\n rawValue: cookieValue,\n uxCookiesAccepted: false,\n marketingCookiesAccepted: false,\n status: 'invalid',\n };\n }\n};\n\n/**\n * Returns helpers for reading RIO's cookie consent state from `cookie_settings`.\n *\n * @returns {UseRioCookieConsentResult} Cookie consent helper functions.\n *\n * @example\n * const { getRioCookieConsentInfo } = useRioCookieConsent();\n * const consent = getRioCookieConsentInfo();\n * const uxAccepted = consent.uxCookiesAccepted;\n */\nconst useRioCookieConsent = (): UseRioCookieConsentResult => {\n const { getCookie } = useCookies();\n\n const getRioCookieConsentInfo = useCallback(() => {\n return evaluateRioCookieSettings(getCookie('cookie_settings'));\n }, [getCookie]);\n\n return { getRioCookieConsentInfo };\n};\n\nexport default useRioCookieConsent;\n"],"names":["evaluateRioCookieSettings","cookieValue","parsed","uxCookiesAccepted","marketingCookiesAccepted","status","useRioCookieConsent","getCookie","useCookies","useCallback"],"mappings":";;AAuDA,MAAMA,IAA4B,CAACC,MAA+C;AAC9E,MAAI,CAACA;AACD,WAAO;AAAA,MACH,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,MAC1B,QAAQ;AAAA,IAAA;AAIhB,MAAI;AACA,UAAMC,IAAS,KAAK,MAAMD,CAAW,GAC/BE,IAAoBD,EAAO,WAAW,MAAM,GAC5CE,IAA2BF,EAAO,UAAU,MAAM;AAExD,QAAIG,IAAiC;AACrC,WAAIF,KAAqB,CAACC,IACtBC,IAAS,wBACF,CAACF,KAAqBC,MAC7BC,IAAS,+BAGN;AAAA,MACH,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAUJ;AAAA,MACV,aAAa;AAAA,QACT,YAAY,OAAOC,EAAO,UAAU,CAAC;AAAA,QACrC,aAAa,OAAOA,EAAO,WAAW,CAAC;AAAA,MAAA;AAAA,MAE3C,mBAAAC;AAAA,MACA,0BAAAC;AAAA,MACA,QAAAC;AAAA,IAAA;AAAA,EAER,QAAQ;AACJ,WAAO;AAAA,MACH,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAUJ;AAAA,MACV,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,MAC1B,QAAQ;AAAA,IAAA;AAAA,EAEhB;AACJ,GAYMK,IAAsB,MAAiC;AACzD,QAAM,EAAE,WAAAC,EAAA,IAAcC,EAAA;AAMtB,SAAO,EAAE,yBAJuBC,EAAY,MACjCT,EAA0BO,EAAU,iBAAiB,CAAC,GAC9D,CAACA,CAAS,CAAC,EAEL;AACb;"}
@@ -57,7 +57,7 @@ type UseSearchOptions<T> = {
57
57
  */
58
58
  declare const useSearch: <T extends object>(list: T[], options?: UseSearchOptions<T>) => {
59
59
  searchValue: string;
60
- setSearchValue: import('react').Dispatch<import('react').SetStateAction<string>> | import('es-toolkit/function').DebouncedFunction<(q: string) => void>;
60
+ setSearchValue: (query: string) => void;
61
61
  filteredList: T[];
62
62
  };
63
63
  export default useSearch;
@@ -1,31 +1,42 @@
1
- import { useState as d, useCallback as b, useMemo as m } from "react";
2
- import { debounce as S } from "es-toolkit/function";
3
- const g = (r, e) => e.split(".").reduce((t, u) => t ? t[u] : void 0, r), h = (r) => Object.keys(r).filter((e) => {
1
+ import { useState as i, useMemo as b, useCallback as V, useEffect as h } from "react";
2
+ import { debounce as v } from "es-toolkit/function";
3
+ const y = (r, e) => e.split(".").reduce((t, s) => t ? t[s] : void 0, r), C = (r) => Object.keys(r).filter((e) => {
4
4
  const t = r[e];
5
5
  return typeof t == "string" || typeof t == "number";
6
- }), M = (r, e = {}) => {
7
- const [t, u] = d(""), o = b(
8
- e.debounceMs ? S((n) => u(n), e.debounceMs) : u,
9
- [e.debounceMs]
10
- ), f = m(() => {
6
+ }), w = (r, e = {}) => {
7
+ const [t, s] = i(""), [l, a] = i(""), f = b(() => e.debounceMs ? v((c) => a(c), e.debounceMs) : null, [e.debounceMs]), m = V(
8
+ (u) => {
9
+ if (s(u), !f) {
10
+ a(u);
11
+ return;
12
+ }
13
+ f(u);
14
+ },
15
+ [f]
16
+ );
17
+ h(() => {
18
+ e.debounceMs || a(t);
19
+ }, [e.debounceMs, t]);
20
+ const S = b(() => {
21
+ const u = e.debounceMs ? l : t;
11
22
  if (!t)
12
23
  return r;
13
24
  if (r.length === 0)
14
25
  return [];
15
- const n = e.caseSensitive ?? !1, a = n ? t : t.toLowerCase();
26
+ const c = e.caseSensitive ?? !1, d = c ? u : u.toLowerCase();
16
27
  if (e.customFilter)
17
- return r.filter((c) => e.customFilter?.(c, t));
18
- const l = e.fields ?? h(r[0]);
28
+ return r.filter((o) => e.customFilter?.(o, u));
29
+ const g = e.fields ?? C(r[0]);
19
30
  return r.filter(
20
- (c) => l.some((i) => {
21
- const s = g(c, i.toString());
22
- return typeof s == "string" ? (n ? s : s.toLowerCase()).includes(a) : typeof s == "number" ? s.toString().includes(a) : !1;
31
+ (o) => g.some((M) => {
32
+ const n = y(o, M.toString());
33
+ return typeof n == "string" ? (c ? n : n.toLowerCase()).includes(d) : typeof n == "number" ? n.toString().includes(d) : !1;
23
34
  })
24
35
  );
25
- }, [r, e, t]);
26
- return { searchValue: t, setSearchValue: o, filteredList: f };
36
+ }, [l, r, e, t]);
37
+ return { searchValue: t, setSearchValue: m, filteredList: S };
27
38
  };
28
39
  export {
29
- M as default
40
+ w as default
30
41
  };
31
42
  //# sourceMappingURL=useSearch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSearch.js","sources":["../../src/hooks/useSearch.ts"],"sourcesContent":["import { useMemo, useState, useCallback } from 'react';\nimport { debounce } from 'es-toolkit/function';\n\n/**\n * Options for configuring the `useSearch` hook.\n */\ntype UseSearchOptions<T> = {\n /**\n * List of object fields to search within. Dot notation (e.g. `'address.city'`) is supported for nested properties.\n * If omitted, all top-level string and number fields will be used.\n */\n fields?: (keyof T | string)[]; // `string` to allow dot notation\n\n /**\n * Optional custom filtering function.\n * If provided, this takes precedence over field-based filtering.\n *\n * @param item - The current item in the list.\n * @param query - The current search query string.\n * @returns `true` if the item should be included in the filtered list.\n */\n customFilter?: (item: T, query: string) => boolean;\n\n /**\n * Number of milliseconds to debounce the search input.\n * If omitted, debounce is disabled.\n */\n debounceMs?: number;\n\n /**\n * Whether to perform a case-sensitive match.\n * Default is `false` (case-insensitive).\n *\n * @default false\n */\n caseSensitive?: boolean;\n};\n\n/**\n * Gets the value of a nested field from an object using dot notation.\n *\n * @param obj - The object to traverse.\n * @param path - The dot-notated path string.\n * @returns The value at the specified path, or undefined.\n */\nconst getNestedValue = (obj: any, path: string): unknown =>\n path.split('.').reduce((val, key) => (val ? val[key] : undefined), obj);\n\nconst inferSearchableFields = <T extends object>(item: T): string[] =>\n Object.keys(item).filter(key => {\n const value = (item as any)[key];\n return typeof value === 'string' || typeof value === 'number';\n });\n\n/**\n * A hook to filter a list of objects by a search value.\n * Supports field-based filtering, custom filtering logic, debounce, and case sensitivity.\n *\n * @template T - The type of items in the list (must be an object).\n *\n * @param list - The array of objects to search through.\n * @param options - Configuration options for the search behavior.\n * @param options.fields - Fields to search through. If omitted, all top-level string/number fields are used.\n * @param options.customFilter - Optional custom filter function overriding field-based filtering.\n * @param options.debounceMs - Debounce time in milliseconds.\n * @param options.caseSensitive - Whether the search should be case-sensitive.\n *\n * @returns An object containing:\n * - `searchValue`: The current search input string.\n * - `setSearchValue`: A setter function to update the search query.\n * - `filteredList`: The list of items matching the current search query.\n *\n * @example\n * ```ts\n * const { searchValue, setSearchValue, filteredList } = useSearch(users, {\n * fields: ['name', 'email'],\n * debounceMs: 300,\n * });\n * ```\n */\nconst useSearch = <T extends object>(list: T[], options: UseSearchOptions<T> = {}) => {\n const [searchValue, _setSearchValue] = useState('');\n\n // Debounced setter\n const setSearchValue = useCallback(\n options.debounceMs ? debounce((q: string) => _setSearchValue(q), options.debounceMs) : _setSearchValue,\n [options.debounceMs]\n );\n\n const filteredList = useMemo(() => {\n if (!searchValue) {\n return list;\n }\n if (list.length === 0) {\n return [];\n }\n\n const isCaseSensitive = options.caseSensitive ?? false;\n const query = isCaseSensitive ? searchValue : searchValue.toLowerCase();\n\n // Custom filter takes precedence\n if (options.customFilter) {\n return list.filter(item => options.customFilter?.(item, searchValue));\n }\n\n const fields = options.fields ?? inferSearchableFields(list[0]);\n\n return list.filter(item =>\n fields.some(field => {\n const value = getNestedValue(item, field.toString());\n\n if (typeof value === 'string') {\n const target = isCaseSensitive ? value : value.toLowerCase();\n return target.includes(query);\n }\n\n if (typeof value === 'number') {\n return value.toString().includes(query);\n }\n\n return false;\n })\n );\n }, [list, options, searchValue]);\n\n return { searchValue, setSearchValue, filteredList };\n};\n\nexport default useSearch;\n"],"names":["getNestedValue","obj","path","val","key","inferSearchableFields","item","value","useSearch","list","options","searchValue","_setSearchValue","useState","setSearchValue","useCallback","debounce","q","filteredList","useMemo","isCaseSensitive","query","fields","field"],"mappings":";;AA6CA,MAAMA,IAAiB,CAACC,GAAUC,MAC9BA,EAAK,MAAM,GAAG,EAAE,OAAO,CAACC,GAAKC,MAASD,IAAMA,EAAIC,CAAG,IAAI,QAAYH,CAAG,GAEpEI,IAAwB,CAAmBC,MAC7C,OAAO,KAAKA,CAAI,EAAE,OAAO,CAAAF,MAAO;AAC5B,QAAMG,IAASD,EAAaF,CAAG;AAC/B,SAAO,OAAOG,KAAU,YAAY,OAAOA,KAAU;AACzD,CAAC,GA4BCC,IAAY,CAAmBC,GAAWC,IAA+B,OAAO;AAClF,QAAM,CAACC,GAAaC,CAAe,IAAIC,EAAS,EAAE,GAG5CC,IAAiBC;AAAA,IACnBL,EAAQ,aAAaM,EAAS,CAACC,MAAcL,EAAgBK,CAAC,GAAGP,EAAQ,UAAU,IAAIE;AAAA,IACvF,CAACF,EAAQ,UAAU;AAAA,EAAA,GAGjBQ,IAAeC,EAAQ,MAAM;AAC/B,QAAI,CAACR;AACD,aAAOF;AAEX,QAAIA,EAAK,WAAW;AAChB,aAAO,CAAA;AAGX,UAAMW,IAAkBV,EAAQ,iBAAiB,IAC3CW,IAAQD,IAAkBT,IAAcA,EAAY,YAAA;AAG1D,QAAID,EAAQ;AACR,aAAOD,EAAK,OAAO,CAAAH,MAAQI,EAAQ,eAAeJ,GAAMK,CAAW,CAAC;AAGxE,UAAMW,IAASZ,EAAQ,UAAUL,EAAsBI,EAAK,CAAC,CAAC;AAE9D,WAAOA,EAAK;AAAA,MAAO,CAAAH,MACfgB,EAAO,KAAK,CAAAC,MAAS;AACjB,cAAMhB,IAAQP,EAAeM,GAAMiB,EAAM,UAAU;AAEnD,eAAI,OAAOhB,KAAU,YACFa,IAAkBb,IAAQA,EAAM,YAAA,GACjC,SAASc,CAAK,IAG5B,OAAOd,KAAU,WACVA,EAAM,WAAW,SAASc,CAAK,IAGnC;AAAA,MACX,CAAC;AAAA,IAAA;AAAA,EAET,GAAG,CAACZ,GAAMC,GAASC,CAAW,CAAC;AAE/B,SAAO,EAAE,aAAAA,GAAa,gBAAAG,GAAgB,cAAAI,EAAA;AAC1C;"}
1
+ {"version":3,"file":"useSearch.js","sources":["../../src/hooks/useSearch.ts"],"sourcesContent":["import { useMemo, useState, useCallback, useEffect } from 'react';\nimport { debounce } from 'es-toolkit/function';\n\n/**\n * Options for configuring the `useSearch` hook.\n */\ntype UseSearchOptions<T> = {\n /**\n * List of object fields to search within. Dot notation (e.g. `'address.city'`) is supported for nested properties.\n * If omitted, all top-level string and number fields will be used.\n */\n fields?: (keyof T | string)[]; // `string` to allow dot notation\n\n /**\n * Optional custom filtering function.\n * If provided, this takes precedence over field-based filtering.\n *\n * @param item - The current item in the list.\n * @param query - The current search query string.\n * @returns `true` if the item should be included in the filtered list.\n */\n customFilter?: (item: T, query: string) => boolean;\n\n /**\n * Number of milliseconds to debounce the search input.\n * If omitted, debounce is disabled.\n */\n debounceMs?: number;\n\n /**\n * Whether to perform a case-sensitive match.\n * Default is `false` (case-insensitive).\n *\n * @default false\n */\n caseSensitive?: boolean;\n};\n\n/**\n * Gets the value of a nested field from an object using dot notation.\n *\n * @param obj - The object to traverse.\n * @param path - The dot-notated path string.\n * @returns The value at the specified path, or undefined.\n */\nconst getNestedValue = (obj: any, path: string): unknown =>\n path.split('.').reduce((val, key) => (val ? val[key] : undefined), obj);\n\nconst inferSearchableFields = <T extends object>(item: T): string[] =>\n Object.keys(item).filter(key => {\n const value = (item as any)[key];\n return typeof value === 'string' || typeof value === 'number';\n });\n\n/**\n * A hook to filter a list of objects by a search value.\n * Supports field-based filtering, custom filtering logic, debounce, and case sensitivity.\n *\n * @template T - The type of items in the list (must be an object).\n *\n * @param list - The array of objects to search through.\n * @param options - Configuration options for the search behavior.\n * @param options.fields - Fields to search through. If omitted, all top-level string/number fields are used.\n * @param options.customFilter - Optional custom filter function overriding field-based filtering.\n * @param options.debounceMs - Debounce time in milliseconds.\n * @param options.caseSensitive - Whether the search should be case-sensitive.\n *\n * @returns An object containing:\n * - `searchValue`: The current search input string.\n * - `setSearchValue`: A setter function to update the search query.\n * - `filteredList`: The list of items matching the current search query.\n *\n * @example\n * ```ts\n * const { searchValue, setSearchValue, filteredList } = useSearch(users, {\n * fields: ['name', 'email'],\n * debounceMs: 300,\n * });\n * ```\n */\nconst useSearch = <T extends object>(list: T[], options: UseSearchOptions<T> = {}) => {\n // what the input renders (must update immediately)\n const [searchValue, _setSearchValue] = useState('');\n\n // what filtering uses (debounced if configured)\n const [debouncedValue, setDebouncedValue] = useState('');\n\n // stable debounced updater\n const debouncedUpdate = useMemo(() => {\n if (!options.debounceMs) {\n return null;\n }\n\n const fn = debounce((query: string) => setDebouncedValue(query), options.debounceMs);\n return fn;\n }, [options.debounceMs]);\n\n // setter exposed to consumers\n const setSearchValue = useCallback(\n (query: string) => {\n _setSearchValue(query);\n\n if (!debouncedUpdate) {\n setDebouncedValue(query);\n return;\n }\n\n debouncedUpdate(query);\n },\n [debouncedUpdate]\n );\n\n // keep debouncedValue in sync for the \"no debounce\" case and initial render\n useEffect(() => {\n if (!options.debounceMs) {\n setDebouncedValue(searchValue);\n }\n }, [options.debounceMs, searchValue]);\n\n const filteredList = useMemo(() => {\n const activeQueryValue = options.debounceMs ? debouncedValue : searchValue;\n\n if (!searchValue) {\n return list;\n }\n if (list.length === 0) {\n return [];\n }\n\n const isCaseSensitive = options.caseSensitive ?? false;\n const query = isCaseSensitive ? activeQueryValue : activeQueryValue.toLowerCase();\n\n // Custom filter takes precedence\n if (options.customFilter) {\n return list.filter(item => options.customFilter?.(item, activeQueryValue));\n }\n\n const fields = options.fields ?? inferSearchableFields(list[0]);\n\n return list.filter(item =>\n fields.some(field => {\n const value = getNestedValue(item, field.toString());\n\n if (typeof value === 'string') {\n const target = isCaseSensitive ? value : value.toLowerCase();\n return target.includes(query);\n }\n\n if (typeof value === 'number') {\n return value.toString().includes(query);\n }\n\n return false;\n })\n );\n }, [debouncedValue, list, options, searchValue]);\n\n return { searchValue, setSearchValue, filteredList };\n};\n\nexport default useSearch;\n"],"names":["getNestedValue","obj","path","val","key","inferSearchableFields","item","value","useSearch","list","options","searchValue","_setSearchValue","useState","debouncedValue","setDebouncedValue","debouncedUpdate","useMemo","debounce","query","setSearchValue","useCallback","useEffect","filteredList","activeQueryValue","isCaseSensitive","fields","field"],"mappings":";;AA6CA,MAAMA,IAAiB,CAACC,GAAUC,MAC9BA,EAAK,MAAM,GAAG,EAAE,OAAO,CAACC,GAAKC,MAASD,IAAMA,EAAIC,CAAG,IAAI,QAAYH,CAAG,GAEpEI,IAAwB,CAAmBC,MAC7C,OAAO,KAAKA,CAAI,EAAE,OAAO,CAAAF,MAAO;AAC5B,QAAMG,IAASD,EAAaF,CAAG;AAC/B,SAAO,OAAOG,KAAU,YAAY,OAAOA,KAAU;AACzD,CAAC,GA4BCC,IAAY,CAAmBC,GAAWC,IAA+B,OAAO;AAElF,QAAM,CAACC,GAAaC,CAAe,IAAIC,EAAS,EAAE,GAG5C,CAACC,GAAgBC,CAAiB,IAAIF,EAAS,EAAE,GAGjDG,IAAkBC,EAAQ,MACvBP,EAAQ,aAIFQ,EAAS,CAACC,MAAkBJ,EAAkBI,CAAK,GAAGT,EAAQ,UAAU,IAHxE,MAKZ,CAACA,EAAQ,UAAU,CAAC,GAGjBU,IAAiBC;AAAA,IACnB,CAACF,MAAkB;AAGf,UAFAP,EAAgBO,CAAK,GAEjB,CAACH,GAAiB;AAClB,QAAAD,EAAkBI,CAAK;AACvB;AAAA,MACJ;AAEA,MAAAH,EAAgBG,CAAK;AAAA,IACzB;AAAA,IACA,CAACH,CAAe;AAAA,EAAA;AAIpB,EAAAM,EAAU,MAAM;AACZ,IAAKZ,EAAQ,cACTK,EAAkBJ,CAAW;AAAA,EAErC,GAAG,CAACD,EAAQ,YAAYC,CAAW,CAAC;AAEpC,QAAMY,IAAeN,EAAQ,MAAM;AAC/B,UAAMO,IAAmBd,EAAQ,aAAaI,IAAiBH;AAE/D,QAAI,CAACA;AACD,aAAOF;AAEX,QAAIA,EAAK,WAAW;AAChB,aAAO,CAAA;AAGX,UAAMgB,IAAkBf,EAAQ,iBAAiB,IAC3CS,IAAQM,IAAkBD,IAAmBA,EAAiB,YAAA;AAGpE,QAAId,EAAQ;AACR,aAAOD,EAAK,OAAO,CAAAH,MAAQI,EAAQ,eAAeJ,GAAMkB,CAAgB,CAAC;AAG7E,UAAME,IAAShB,EAAQ,UAAUL,EAAsBI,EAAK,CAAC,CAAC;AAE9D,WAAOA,EAAK;AAAA,MAAO,CAAAH,MACfoB,EAAO,KAAK,CAAAC,MAAS;AACjB,cAAMpB,IAAQP,EAAeM,GAAMqB,EAAM,UAAU;AAEnD,eAAI,OAAOpB,KAAU,YACFkB,IAAkBlB,IAAQA,EAAM,YAAA,GACjC,SAASY,CAAK,IAG5B,OAAOZ,KAAU,WACVA,EAAM,WAAW,SAASY,CAAK,IAGnC;AAAA,MACX,CAAC;AAAA,IAAA;AAAA,EAET,GAAG,CAACL,GAAgBL,GAAMC,GAASC,CAAW,CAAC;AAE/C,SAAO,EAAE,aAAAA,GAAa,gBAAAS,GAAgB,cAAAG,EAAA;AAC1C;"}
@@ -0,0 +1,60 @@
1
+ export declare const SEARCH_HIGHLIGHT_CLASS = "search-result-highlight";
2
+ export type UseSearchHighlightParams = {
3
+ /**
4
+ * Ref to the element whose text content should be searched.
5
+ */
6
+ ref: React.RefObject<HTMLElement>;
7
+ /**
8
+ * Search query used for highlighting.
9
+ */
10
+ query: string;
11
+ /**
12
+ * Name of the CSS highlight.
13
+ *
14
+ * @default 'search-result-highlight'
15
+ */
16
+ highlightClassName?: string;
17
+ /**
18
+ * Optional selector to limit the search scope
19
+ * (e.g. '.ListMenuGroup' or '.OptionLabel').
20
+ */
21
+ scopeSelector?: string;
22
+ /**
23
+ * Whether to perform a case-sensitive match.
24
+ *
25
+ * @default false
26
+ */
27
+ caseSensitive?: boolean;
28
+ /**
29
+ * Optional dependencies that should trigger re-collecting and applying ranges.
30
+ * Useful when the DOM changes after the query changes (e.g. debounced filtering).
31
+ */
32
+ deps?: unknown[];
33
+ };
34
+ /**
35
+ * React hook for visually highlighting search query matches
36
+ * using the native CSS Highlight API.
37
+ *
38
+ * The hook scans the text content of the referenced element
39
+ * and applies a named CSS highlight to all matching substrings.
40
+ *
41
+ * Key characteristics:
42
+ * - Progressive enhancement: safely no-ops in unsupported browsers
43
+ * - Does not modify or re-render DOM markup
44
+ * - Designed for search UIs (Autocomplete, ListMenu, Dropdown, etc.)
45
+ *
46
+ * Usage notes:
47
+ * - The hook must always be called unconditionally
48
+ * - Use `useSearchHighlight.supported()` only for render-time
49
+ * fallback decisions (e.g. `<mark>` rendering)
50
+ *
51
+ * @param ref Ref to the element whose text should be searched
52
+ * @param query Search query to highlight
53
+ * @param highlightName Optional CSS highlight name
54
+ * @param scopeSelector Optional selector to limit the search scope
55
+ */
56
+ declare const useSearchHighlight: {
57
+ (params: UseSearchHighlightParams): void;
58
+ supported(): boolean;
59
+ };
60
+ export default useSearchHighlight;
@@ -0,0 +1,54 @@
1
+ import { useMemo as d, useEffect as x } from "react";
2
+ const m = "search-result-highlight", u = () => typeof window < "u" && "CSS" in window && "highlights" in CSS && typeof Highlight < "u", w = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), H = (s, c, h) => {
3
+ const t = [];
4
+ if (!c)
5
+ return t;
6
+ const n = new RegExp(w(c), h ? "g" : "gi"), a = document.createTreeWalker(s, NodeFilter.SHOW_TEXT);
7
+ let e = a.nextNode();
8
+ for (; e; ) {
9
+ const o = e.textContent ?? "";
10
+ n.lastIndex = 0;
11
+ let r = n.exec(o);
12
+ for (; r; ) {
13
+ const i = document.createRange();
14
+ i.setStart(e, r.index), i.setEnd(e, r.index + r[0].length), t.push(i), r = n.exec(o);
15
+ }
16
+ e = a.nextNode();
17
+ }
18
+ return t;
19
+ }, C = (s) => {
20
+ const {
21
+ ref: c,
22
+ query: h,
23
+ highlightClassName: t = m,
24
+ scopeSelector: n,
25
+ caseSensitive: a = !1,
26
+ deps: e
27
+ } = s, o = d(() => h.trim(), [h]), r = d(() => e ?? [], [e]);
28
+ x(() => {
29
+ if (!u())
30
+ return;
31
+ const i = c.current;
32
+ if (!i)
33
+ return;
34
+ const g = CSS.highlights.get(t) ?? new Highlight();
35
+ CSS.highlights.set(t, g);
36
+ const p = () => {
37
+ if (g.clear(), !o)
38
+ return;
39
+ const l = n ? i.querySelector(n) : i;
40
+ if (l)
41
+ for (const f of H(l, o, a))
42
+ g.add(f);
43
+ }, S = window.requestAnimationFrame(p);
44
+ return () => {
45
+ window.cancelAnimationFrame(S), g.clear();
46
+ };
47
+ }, [a, t, o, c, n, r]);
48
+ };
49
+ C.supported = () => u();
50
+ export {
51
+ m as SEARCH_HIGHLIGHT_CLASS,
52
+ C as default
53
+ };
54
+ //# sourceMappingURL=useSearchHighlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSearchHighlight.js","sources":["../../src/hooks/useSearchHighlight.ts"],"sourcesContent":["import { useEffect, useMemo } from 'react';\n\nexport const SEARCH_HIGHLIGHT_CLASS = 'search-result-highlight';\n\nexport type UseSearchHighlightParams = {\n /**\n * Ref to the element whose text content should be searched.\n */\n ref: React.RefObject<HTMLElement>;\n\n /**\n * Search query used for highlighting.\n */\n query: string;\n\n /**\n * Name of the CSS highlight.\n *\n * @default 'search-result-highlight'\n */\n highlightClassName?: string;\n\n /**\n * Optional selector to limit the search scope\n * (e.g. '.ListMenuGroup' or '.OptionLabel').\n */\n scopeSelector?: string;\n\n /**\n * Whether to perform a case-sensitive match.\n *\n * @default false\n */\n caseSensitive?: boolean;\n\n /**\n * Optional dependencies that should trigger re-collecting and applying ranges.\n * Useful when the DOM changes after the query changes (e.g. debounced filtering).\n */\n deps?: unknown[];\n};\n\n// Guard for browser support of the CSS Highlight API.\nconst isSearchHighlightSupported = () =>\n typeof window !== 'undefined' && 'CSS' in window && 'highlights' in CSS && typeof Highlight !== 'undefined';\n\nconst escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Collects DOM Ranges for all matches of a search query\n * within the text content of a given root element.\n *\n * Purpose:\n * This utility is used by `useSearchHighlight` to translate a plain-text\n * search query into DOM `Range` objects that can be consumed by the\n * native CSS Highlight API (`Highlight` / `CSS.highlights`).\n *\n * Why this exists:\n * - The Highlight API does not accept strings or selectors, only `Range`s.\n * - React nodes may contain arbitrary nested markup; injecting `<mark>`\n * elements would break component structure and semantics.\n * - Walking the DOM text nodes allows highlighting without mutating\n * the rendered output.\n *\n * What it does:\n * - Traverses all text nodes inside `root` using a `TreeWalker`\n * - Finds all matches of `query`\n * - Creates a `Range` for each match, precisely spanning the matched text\n * - Returns all collected ranges in document order\n *\n * What it does NOT do:\n * - It does not modify the DOM\n * - It does not register or apply highlights\n * - It does not perform filtering or visibility logic\n *\n * Performance notes:\n * - Intended for reasonably sized, already-filtered DOM trees\n * (e.g. visible menu items, dropdown options)\n * - Consumers should avoid running this on large, unbounded documents\n *\n * @param root The root element whose text content should be searched\n * @param query The normalized (trimmed) search query\n * @param caseSensitive Whether matches should be case-sensitive\n * @returns An array of DOM Ranges matching the query\n */\nconst collectRanges = (root: HTMLElement, query: string, caseSensitive: boolean): Range[] => {\n const ranges: Range[] = [];\n\n if (!query) {\n return ranges;\n }\n\n const regex = new RegExp(escapeRegExp(query), caseSensitive ? 'g' : 'gi');\n\n // Walk text nodes only to avoid splitting markup.\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n\n let node: Node | null = walker.nextNode();\n\n while (node) {\n const text = node.textContent ?? '';\n regex.lastIndex = 0;\n\n let match: RegExpExecArray | null = regex.exec(text);\n\n while (match) {\n const range = document.createRange();\n range.setStart(node, match.index);\n range.setEnd(node, match.index + match[0].length);\n ranges.push(range);\n\n match = regex.exec(text);\n }\n\n node = walker.nextNode();\n }\n\n return ranges;\n};\n\n/**\n * React hook for visually highlighting search query matches\n * using the native CSS Highlight API.\n *\n * The hook scans the text content of the referenced element\n * and applies a named CSS highlight to all matching substrings.\n *\n * Key characteristics:\n * - Progressive enhancement: safely no-ops in unsupported browsers\n * - Does not modify or re-render DOM markup\n * - Designed for search UIs (Autocomplete, ListMenu, Dropdown, etc.)\n *\n * Usage notes:\n * - The hook must always be called unconditionally\n * - Use `useSearchHighlight.supported()` only for render-time\n * fallback decisions (e.g. `<mark>` rendering)\n *\n * @param ref Ref to the element whose text should be searched\n * @param query Search query to highlight\n * @param highlightName Optional CSS highlight name\n * @param scopeSelector Optional selector to limit the search scope\n */\nconst useSearchHighlight = (params: UseSearchHighlightParams) => {\n const {\n ref,\n query,\n highlightClassName = SEARCH_HIGHLIGHT_CLASS,\n scopeSelector,\n caseSensitive = false,\n deps,\n } = params;\n\n const normalizedQuery = useMemo(() => query.trim(), [query]);\n\n const extraDeps = useMemo(() => deps ?? [], [deps]);\n\n useEffect(() => {\n if (!isSearchHighlightSupported()) {\n return;\n }\n\n const container = ref.current;\n if (!container) {\n return;\n }\n\n // Reuse the named highlight so multiple renders update the same layer.\n const highlight = CSS.highlights.get(highlightClassName) ?? new Highlight();\n CSS.highlights.set(highlightClassName, highlight);\n\n const applyHighlight = () => {\n // Always clear before re-adding to avoid stale ranges.\n highlight.clear();\n\n if (!normalizedQuery) {\n return;\n }\n\n const scopeRoot = scopeSelector\n ? (container.querySelector(scopeSelector) as HTMLElement | null)\n : container;\n\n if (!scopeRoot) {\n return;\n }\n\n for (const range of collectRanges(scopeRoot, normalizedQuery, caseSensitive)) {\n highlight.add(range);\n }\n };\n\n // Defer until after layout so text nodes are in place.\n const raf = window.requestAnimationFrame(applyHighlight);\n\n return () => {\n window.cancelAnimationFrame(raf);\n // Ensure highlights are removed when query or component unmounts.\n highlight.clear();\n };\n }, [caseSensitive, highlightClassName, normalizedQuery, ref, scopeSelector, extraDeps]);\n};\n\n/**\n * Indicates whether the current environment supports\n * the native CSS Highlight API.\n *\n * Can be used to decide whether to render a `<mark>` fallback.\n */\nuseSearchHighlight.supported = () => isSearchHighlightSupported();\n\nexport default useSearchHighlight;\n"],"names":["SEARCH_HIGHLIGHT_CLASS","isSearchHighlightSupported","escapeRegExp","value","collectRanges","root","query","caseSensitive","ranges","regex","walker","node","text","match","range","useSearchHighlight","params","ref","highlightClassName","scopeSelector","deps","normalizedQuery","useMemo","extraDeps","useEffect","container","highlight","applyHighlight","scopeRoot","raf"],"mappings":";AAEO,MAAMA,IAAyB,2BAyChCC,IAA6B,MAC/B,OAAO,SAAW,OAAe,SAAS,UAAU,gBAAgB,OAAO,OAAO,YAAc,KAE9FC,IAAe,CAACC,MAAkBA,EAAM,QAAQ,uBAAuB,MAAM,GAuC7EC,IAAgB,CAACC,GAAmBC,GAAeC,MAAoC;AACzF,QAAMC,IAAkB,CAAA;AAExB,MAAI,CAACF;AACD,WAAOE;AAGX,QAAMC,IAAQ,IAAI,OAAOP,EAAaI,CAAK,GAAGC,IAAgB,MAAM,IAAI,GAGlEG,IAAS,SAAS,iBAAiBL,GAAM,WAAW,SAAS;AAEnE,MAAIM,IAAoBD,EAAO,SAAA;AAE/B,SAAOC,KAAM;AACT,UAAMC,IAAOD,EAAK,eAAe;AACjC,IAAAF,EAAM,YAAY;AAElB,QAAII,IAAgCJ,EAAM,KAAKG,CAAI;AAEnD,WAAOC,KAAO;AACV,YAAMC,IAAQ,SAAS,YAAA;AACvB,MAAAA,EAAM,SAASH,GAAME,EAAM,KAAK,GAChCC,EAAM,OAAOH,GAAME,EAAM,QAAQA,EAAM,CAAC,EAAE,MAAM,GAChDL,EAAO,KAAKM,CAAK,GAEjBD,IAAQJ,EAAM,KAAKG,CAAI;AAAA,IAC3B;AAEA,IAAAD,IAAOD,EAAO,SAAA;AAAA,EAClB;AAEA,SAAOF;AACX,GAwBMO,IAAqB,CAACC,MAAqC;AAC7D,QAAM;AAAA,IACF,KAAAC;AAAA,IACA,OAAAX;AAAA,IACA,oBAAAY,IAAqBlB;AAAA,IACrB,eAAAmB;AAAA,IACA,eAAAZ,IAAgB;AAAA,IAChB,MAAAa;AAAA,EAAA,IACAJ,GAEEK,IAAkBC,EAAQ,MAAMhB,EAAM,QAAQ,CAACA,CAAK,CAAC,GAErDiB,IAAYD,EAAQ,MAAMF,KAAQ,CAAA,GAAI,CAACA,CAAI,CAAC;AAElD,EAAAI,EAAU,MAAM;AACZ,QAAI,CAACvB;AACD;AAGJ,UAAMwB,IAAYR,EAAI;AACtB,QAAI,CAACQ;AACD;AAIJ,UAAMC,IAAY,IAAI,WAAW,IAAIR,CAAkB,KAAK,IAAI,UAAA;AAChE,QAAI,WAAW,IAAIA,GAAoBQ,CAAS;AAEhD,UAAMC,IAAiB,MAAM;AAIzB,UAFAD,EAAU,MAAA,GAEN,CAACL;AACD;AAGJ,YAAMO,IAAYT,IACXM,EAAU,cAAcN,CAAa,IACtCM;AAEN,UAAKG;AAIL,mBAAWd,KAASV,EAAcwB,GAAWP,GAAiBd,CAAa;AACvE,UAAAmB,EAAU,IAAIZ,CAAK;AAAA,IAE3B,GAGMe,IAAM,OAAO,sBAAsBF,CAAc;AAEvD,WAAO,MAAM;AACT,aAAO,qBAAqBE,CAAG,GAE/BH,EAAU,MAAA;AAAA,IACd;AAAA,EACJ,GAAG,CAACnB,GAAeW,GAAoBG,GAAiBJ,GAAKE,GAAeI,CAAS,CAAC;AAC1F;AAQAR,EAAmB,YAAY,MAAMd,EAAA;"}
@@ -4,30 +4,30 @@ const f = (s, t) => {
4
4
  return l(() => {
5
5
  c.current = s;
6
6
  }, [s]), l(() => {
7
- const r = () => c.current();
7
+ const n = () => c.current();
8
8
  if (typeof t == "number")
9
- return e.current = window.setTimeout(r, t), () => {
10
- e.current !== null && window.clearTimeout(e.current);
9
+ return e.current = setTimeout(n, t), () => {
10
+ e.current !== null && clearTimeout(e.current);
11
11
  };
12
12
  }, [t]), e;
13
13
  }, _ = () => {
14
14
  const t = (u, i, o) => {
15
- const n = o - Date.now();
16
- u.current = n <= 2147483647 ? setTimeout(i, n) : setTimeout(() => t(u, i, o), 2147483647);
17
- }, e = m(null), { set: c, clear: r } = T(() => {
15
+ const r = o - Date.now();
16
+ u.current = r <= 2147483647 ? setTimeout(i, r) : setTimeout(() => t(u, i, o), 2147483647);
17
+ }, e = m(null), { set: c, clear: n } = T(() => {
18
18
  const u = () => clearTimeout(e.current);
19
19
  return {
20
- set: (o, n = 0) => {
21
- u(), n <= 2147483647 ? e.current = setTimeout(o, n) : t(e, o, Date.now() + n);
20
+ set: (o, r = 0) => {
21
+ u(), r <= 2147483647 ? e.current = setTimeout(o, r) : t(e, o, Date.now() + r);
22
22
  },
23
23
  clear: u
24
24
  };
25
25
  }, []);
26
26
  return l(() => () => {
27
- r();
28
- }, [r]), {
27
+ n();
28
+ }, [n]), {
29
29
  set: c,
30
- clear: r,
30
+ clear: n,
31
31
  handleRef: e
32
32
  };
33
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useTimeout.js","sources":["../../src/hooks/useTimeout.ts"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useMemo, useRef } from 'react';\n\n// See www.joshwcomeau.com/snippets/react-hooks/use-timeout/\n\n/**\n * A custom hook for handling timeout events.\n *\n * @param callback The callback function to execute after the timeout.\n * @param delay The duration of the timeout in milliseconds. Pass `null` to cancel the timeout.\n *\n * @returns A mutable ref object to manage the timeout ID.\n */\nconst useTimeout = (callback: () => void, delay: number | null): React.MutableRefObject<number | null> => {\n const timeoutRef = useRef<number | null>(null);\n const savedCallback = useRef<() => void>(callback);\n\n // Update the saved callback when the callback prop changes\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the timeout when the delay changes\n useEffect(() => {\n const tick = () => savedCallback.current();\n\n // If delay is a number, set up the timeout\n if (typeof delay === 'number') {\n timeoutRef.current = window.setTimeout(tick, delay);\n\n // Cleanup function to clear the timeout when delay changes or component unmounts\n return () => {\n if (timeoutRef.current !== null) {\n window.clearTimeout(timeoutRef.current);\n }\n };\n }\n }, [delay]);\n\n return timeoutRef;\n};\n\nexport const useChainedTimeout = () => {\n const MAX_DELAY_MS = 2 ** 31 - 1;\n\n const setChainedTimeout = (ref: React.MutableRefObject<any>, fn: () => void, timeoutAtMs: number) => {\n const delayMs = timeoutAtMs - Date.now();\n\n ref.current =\n delayMs <= MAX_DELAY_MS\n ? setTimeout(fn, delayMs)\n : setTimeout(() => setChainedTimeout(ref, fn, timeoutAtMs), MAX_DELAY_MS);\n };\n\n const handleRef = useRef<any>(null);\n\n const { set, clear } = useMemo(() => {\n const clear = () => clearTimeout(handleRef.current);\n\n const set = (fn: () => void, delayMs = 0): void => {\n clear();\n\n if (delayMs <= MAX_DELAY_MS) {\n // For simplicity, if the timeout is short, just set a normal timeout.\n handleRef.current = setTimeout(fn, delayMs);\n } else {\n setChainedTimeout(handleRef, fn, Date.now() + delayMs);\n }\n };\n\n return {\n set,\n clear,\n };\n }, []);\n\n useEffect(() => {\n return () => {\n clear();\n };\n }, [clear]);\n\n return {\n set,\n clear,\n handleRef,\n };\n};\n\nexport default useTimeout;\n"],"names":["useTimeout","callback","delay","timeoutRef","useRef","savedCallback","useEffect","tick","useChainedTimeout","setChainedTimeout","ref","fn","timeoutAtMs","delayMs","handleRef","set","clear","useMemo"],"mappings":";AAaA,MAAMA,IAAa,CAACC,GAAsBC,MAAgE;AACtG,QAAMC,IAAaC,EAAsB,IAAI,GACvCC,IAAgBD,EAAmBH,CAAQ;AAGjD,SAAAK,EAAU,MAAM;AACZ,IAAAD,EAAc,UAAUJ;AAAA,EAC5B,GAAG,CAACA,CAAQ,CAAC,GAGbK,EAAU,MAAM;AACZ,UAAMC,IAAO,MAAMF,EAAc,QAAA;AAGjC,QAAI,OAAOH,KAAU;AACjB,aAAAC,EAAW,UAAU,OAAO,WAAWI,GAAML,CAAK,GAG3C,MAAM;AACT,QAAIC,EAAW,YAAY,QACvB,OAAO,aAAaA,EAAW,OAAO;AAAA,MAE9C;AAAA,EAER,GAAG,CAACD,CAAK,CAAC,GAEHC;AACX,GAEaK,IAAoB,MAAM;AAGnC,QAAMC,IAAoB,CAACC,GAAkCC,GAAgBC,MAAwB;AACjG,UAAMC,IAAUD,IAAc,KAAK,IAAA;AAEnC,IAAAF,EAAI,UACAG,KAAW,aACL,WAAWF,GAAIE,CAAO,IACtB,WAAW,MAAMJ,EAAkBC,GAAKC,GAAIC,CAAW,GAAG,UAAY;AAAA,EACpF,GAEME,IAAYV,EAAY,IAAI,GAE5B,EAAE,KAAAW,GAAK,OAAAC,EAAA,IAAUC,EAAQ,MAAM;AACjC,UAAMD,IAAQ,MAAM,aAAaF,EAAU,OAAO;AAalD,WAAO;AAAA,MACH,KAZQ,CAACH,GAAgBE,IAAU,MAAY;AAC/CG,QAAAA,EAAAA,GAEIH,KAAW,aAEXC,EAAU,UAAU,WAAWH,GAAIE,CAAO,IAE1CJ,EAAkBK,GAAWH,GAAI,KAAK,IAAA,IAAQE,CAAO;AAAA,MAE7D;AAAA,MAII,OAAAG;AAAAA,IAAA;AAAA,EAER,GAAG,CAAA,CAAE;AAEL,SAAAV,EAAU,MACC,MAAM;AACT,IAAAU,EAAA;AAAA,EACJ,GACD,CAACA,CAAK,CAAC,GAEH;AAAA,IACH,KAAAD;AAAA,IACA,OAAAC;AAAA,IACA,WAAAF;AAAA,EAAA;AAER;"}
1
+ {"version":3,"file":"useTimeout.js","sources":["../../src/hooks/useTimeout.ts"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useMemo, useRef } from 'react';\n\n// See www.joshwcomeau.com/snippets/react-hooks/use-timeout/\n\n/**\n * A custom hook for handling timeout events.\n *\n * @param callback The callback function to execute after the timeout.\n * @param delay The duration of the timeout in milliseconds. Pass `null` to cancel the timeout.\n *\n * @returns A mutable ref object to manage the timeout ID.\n */\nconst useTimeout = (callback: () => void, delay: number | null): React.MutableRefObject<number | null> => {\n const timeoutRef = useRef<number | null>(null);\n const savedCallback = useRef<() => void>(callback);\n\n // Update the saved callback when the callback prop changes\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the timeout when the delay changes\n useEffect(() => {\n const tick = () => savedCallback.current();\n\n // If delay is a number, set up the timeout\n if (typeof delay === 'number') {\n timeoutRef.current = setTimeout(tick, delay) as unknown as number;\n\n // Cleanup function to clear the timeout when delay changes or component unmounts\n return () => {\n if (timeoutRef.current !== null) {\n clearTimeout(timeoutRef.current);\n }\n };\n }\n }, [delay]);\n\n return timeoutRef;\n};\n\nexport const useChainedTimeout = () => {\n const MAX_DELAY_MS = 2 ** 31 - 1;\n\n const setChainedTimeout = (ref: React.MutableRefObject<any>, fn: () => void, timeoutAtMs: number) => {\n const delayMs = timeoutAtMs - Date.now();\n\n ref.current =\n delayMs <= MAX_DELAY_MS\n ? setTimeout(fn, delayMs)\n : setTimeout(() => setChainedTimeout(ref, fn, timeoutAtMs), MAX_DELAY_MS);\n };\n\n const handleRef = useRef<any>(null);\n\n const { set, clear } = useMemo(() => {\n const clear = () => clearTimeout(handleRef.current);\n\n const set = (fn: () => void, delayMs = 0): void => {\n clear();\n\n if (delayMs <= MAX_DELAY_MS) {\n // For simplicity, if the timeout is short, just set a normal timeout.\n handleRef.current = setTimeout(fn, delayMs);\n } else {\n setChainedTimeout(handleRef, fn, Date.now() + delayMs);\n }\n };\n\n return {\n set,\n clear,\n };\n }, []);\n\n useEffect(() => {\n return () => {\n clear();\n };\n }, [clear]);\n\n return {\n set,\n clear,\n handleRef,\n };\n};\n\nexport default useTimeout;\n"],"names":["useTimeout","callback","delay","timeoutRef","useRef","savedCallback","useEffect","tick","useChainedTimeout","setChainedTimeout","ref","fn","timeoutAtMs","delayMs","handleRef","set","clear","useMemo"],"mappings":";AAaA,MAAMA,IAAa,CAACC,GAAsBC,MAAgE;AACtG,QAAMC,IAAaC,EAAsB,IAAI,GACvCC,IAAgBD,EAAmBH,CAAQ;AAGjD,SAAAK,EAAU,MAAM;AACZ,IAAAD,EAAc,UAAUJ;AAAA,EAC5B,GAAG,CAACA,CAAQ,CAAC,GAGbK,EAAU,MAAM;AACZ,UAAMC,IAAO,MAAMF,EAAc,QAAA;AAGjC,QAAI,OAAOH,KAAU;AACjB,aAAAC,EAAW,UAAU,WAAWI,GAAML,CAAK,GAGpC,MAAM;AACT,QAAIC,EAAW,YAAY,QACvB,aAAaA,EAAW,OAAO;AAAA,MAEvC;AAAA,EAER,GAAG,CAACD,CAAK,CAAC,GAEHC;AACX,GAEaK,IAAoB,MAAM;AAGnC,QAAMC,IAAoB,CAACC,GAAkCC,GAAgBC,MAAwB;AACjG,UAAMC,IAAUD,IAAc,KAAK,IAAA;AAEnC,IAAAF,EAAI,UACAG,KAAW,aACL,WAAWF,GAAIE,CAAO,IACtB,WAAW,MAAMJ,EAAkBC,GAAKC,GAAIC,CAAW,GAAG,UAAY;AAAA,EACpF,GAEME,IAAYV,EAAY,IAAI,GAE5B,EAAE,KAAAW,GAAK,OAAAC,EAAA,IAAUC,EAAQ,MAAM;AACjC,UAAMD,IAAQ,MAAM,aAAaF,EAAU,OAAO;AAalD,WAAO;AAAA,MACH,KAZQ,CAACH,GAAgBE,IAAU,MAAY;AAC/CG,QAAAA,EAAAA,GAEIH,KAAW,aAEXC,EAAU,UAAU,WAAWH,GAAIE,CAAO,IAE1CJ,EAAkBK,GAAWH,GAAI,KAAK,IAAA,IAAQE,CAAO;AAAA,MAE7D;AAAA,MAII,OAAAG;AAAAA,IAAA;AAAA,EAER,GAAG,CAAA,CAAE;AAEL,SAAAV,EAAU,MACC,MAAM;AACT,IAAAU,EAAA;AAAA,EACJ,GACD,CAACA,CAAK,CAAC,GAEH;AAAA,IACH,KAAAD;AAAA,IACA,OAAAC;AAAA,IACA,WAAAF;AAAA,EAAA;AAER;"}
@@ -0,0 +1,62 @@
1
+ import { UrlConfigItem } from '../utils/routeUtils';
2
+ type QueryString = string;
3
+ /**
4
+ * Configuration contract for `useUrlState`.
5
+ *
6
+ * Use this hook when your application uses **store/redux as source of truth**
7
+ * and you want a centralized URL synchronizer:
8
+ * - URL -> store: parse incoming search params and dispatch updates
9
+ * - store -> URL: serialize current store values and navigate with push/replace
10
+ *
11
+ * Recommended setup:
12
+ * - Mount one top-level synchronizer component near the router
13
+ * - Pass only URL-managed store values via `storeValues`
14
+ * - Keep URL writing centralized through this hook
15
+ *
16
+ * Not intended for "URL-only state" screens where you directly read/write
17
+ * params via router APIs (for example `useSearchParams`) without store sync.
18
+ */
19
+ type UseUrlStateProps<TState> = {
20
+ /**
21
+ * URL sync configuration.
22
+ * Each entry maps one query param key to a store selector and update action.
23
+ */
24
+ config: readonly UrlConfigItem<TState, any>[];
25
+ /**
26
+ * Current URL search string (for example `location.search`).
27
+ * Expected shape: `'?q=test&sort=-name'` or `''`.
28
+ */
29
+ searchString: QueryString;
30
+ /**
31
+ * Current store values used by the configured selectors. This could be values from a redux store.
32
+ * Keys should match the `config` keys, values are compared against URL/defaults.
33
+ */
34
+ storeValues: Record<string, unknown>;
35
+ /**
36
+ * Optional localStorage key for sticky URL state restore on initial load
37
+ * when managed URL params are missing.
38
+ */
39
+ localStorageKey?: string;
40
+ /**
41
+ * Router navigation type (typically from React Router `useNavigationType`).
42
+ * `POP` indicates browser back/forward navigation.
43
+ */
44
+ navigationType?: 'POP' | 'PUSH' | 'REPLACE' | string;
45
+ /**
46
+ * Store update callback invoked when URL -> store sync detects a change.
47
+ * Usually wraps `dispatch(...)`.
48
+ */
49
+ onUpdateStore: (action: any) => void;
50
+ /**
51
+ * Navigation callback used for store -> URL sync writes.
52
+ * `historyMode` controls whether to `push` or `replace` the history entry.
53
+ */
54
+ onNavigate: (search: string, historyMode: 'push' | 'replace') => void;
55
+ };
56
+ /**
57
+ * ----------------------------------------------------------------------------
58
+ * MAIN EXPORT
59
+ * ----------------------------------------------------------------------------
60
+ */
61
+ declare const useUrlState: <TState>(props: UseUrlStateProps<TState>) => void;
62
+ export default useUrlState;
@@ -0,0 +1,137 @@
1
+ import { useRef as R, useEffect as D } from "react";
2
+ import { isNil as z, isEqual as v } from "es-toolkit";
3
+ import { deserializeValue as T, toQueryString as M, serializeValue as A } from "../utils/routeUtils.js";
4
+ import E from "./useAfterMount.js";
5
+ import U from "./useLatest.js";
6
+ const C = (r) => {
7
+ const e = r.replace(/^\?/, "");
8
+ return new URLSearchParams(e).toString();
9
+ }, L = (r, e) => r.customDeserialize ? r.customDeserialize(e) : T(e, r.type ?? "string"), N = (r, e) => r ?? e, I = (r) => {
10
+ const { valueToApply: e, currentStoreValue: t, urlRawValue: a, defaultValue: d } = r;
11
+ if (typeof e > "u" || v(e, t))
12
+ return !1;
13
+ const l = z(a), n = v(t, d);
14
+ return !(l && n);
15
+ }, O = (r, e, t) => t ? null : r.customSerialize ? r.customSerialize(e) : A(e, r.type ?? "string"), x = (r) => {
16
+ const { nextParams: e, key: t, serializedValue: a } = r;
17
+ return z(a) ? e.has(t) ? (e.delete(t), !0) : !1 : (e.set(t, a), !0);
18
+ }, K = (r, e) => {
19
+ if (z(e))
20
+ return !0;
21
+ const t = L(r, e), a = N(t, r.defaultValue);
22
+ return v(a, r.defaultValue);
23
+ }, F = ({
24
+ config: r,
25
+ searchString: e,
26
+ storeValues: t,
27
+ navigationType: a,
28
+ onUpdateStore: d,
29
+ lastWrittenNormalizedSearchRef: l,
30
+ isRestoringRef: n,
31
+ hasCheckedStorageRef: g
32
+ }) => {
33
+ const h = U(r), p = U(t), y = U(d);
34
+ D(() => {
35
+ if (!g.current)
36
+ return;
37
+ const s = C(e);
38
+ if (l.current === s && (l.current = null), n.current)
39
+ return;
40
+ const P = new URLSearchParams(e);
41
+ h.current.forEach((c) => {
42
+ const u = P.get(c.key), i = L(c, u), f = N(i, c.defaultValue), S = p.current[c.key];
43
+ if (I({
44
+ valueToApply: f,
45
+ currentStoreValue: S,
46
+ urlRawValue: u,
47
+ defaultValue: c.defaultValue
48
+ })) {
49
+ if (z(u) && a !== "POP")
50
+ return;
51
+ y.current(c.action(f));
52
+ }
53
+ });
54
+ }, [e, l, n, g]);
55
+ }, q = (r) => {
56
+ const {
57
+ config: e,
58
+ searchString: t,
59
+ storeValues: a,
60
+ onNavigate: d,
61
+ lastWrittenNormalizedSearchRef: l,
62
+ localStorageKey: n,
63
+ navigationType: g
64
+ } = r, h = U(d), p = R(C(t));
65
+ E(() => {
66
+ const y = C(t), s = p.current !== y;
67
+ if (p.current = y, g === "POP" && s)
68
+ return;
69
+ const c = new URLSearchParams(t), u = new URLSearchParams(t);
70
+ let i = !1, f = !1, S = !0;
71
+ if (e.forEach((o) => {
72
+ const V = a[o.key], m = c.get(o.key), k = v(V, o.defaultValue);
73
+ k || (S = !1);
74
+ const w = O(o, V, k);
75
+ w !== m && (i = x({ nextParams: u, key: o.key, serializedValue: w }) || i, ((o.history ?? "push") === "push" || !k && K(o, m)) && (f = !0));
76
+ }), i) {
77
+ const o = M(u, e), V = u.toString();
78
+ l.current = V, n && (S && o === "" ? localStorage.removeItem(n) : localStorage.setItem(n, o));
79
+ const m = f ? "push" : "replace";
80
+ h.current(o, m);
81
+ }
82
+ }, [a, t, e, n, g]);
83
+ }, Q = (r) => {
84
+ const {
85
+ config: e,
86
+ searchString: t,
87
+ localStorageKey: a,
88
+ onUpdateStore: d,
89
+ onNavigate: l,
90
+ isRestoringRef: n,
91
+ lastWrittenNormalizedSearchRef: g,
92
+ hasCheckedStorageRef: h
93
+ } = r;
94
+ D(() => {
95
+ if (!a) {
96
+ h.current = !0;
97
+ return;
98
+ }
99
+ const p = new URLSearchParams(t);
100
+ if (!e.some((s) => p.has(s.key))) {
101
+ const s = localStorage.getItem(a);
102
+ if (s) {
103
+ n.current = !0;
104
+ const P = new URLSearchParams(s);
105
+ e.forEach((i) => {
106
+ const f = P.get(i.key), S = L(i, f);
107
+ S !== null && typeof S < "u" && d(i.action(S));
108
+ });
109
+ const c = s.replace(/^\?/, ""), u = t.replace(/^\?/, "");
110
+ c !== u && (g.current = new URLSearchParams(s).toString(), l(s, "replace")), setTimeout(() => {
111
+ n.current = !1;
112
+ }, 0);
113
+ }
114
+ }
115
+ h.current = !0;
116
+ }, [a]);
117
+ }, J = (r) => {
118
+ const e = R(null), t = R(!1), a = R(!r.localStorageKey);
119
+ Q({
120
+ ...r,
121
+ lastWrittenNormalizedSearchRef: e,
122
+ isRestoringRef: t,
123
+ hasCheckedStorageRef: a
124
+ }), F({
125
+ ...r,
126
+ lastWrittenNormalizedSearchRef: e,
127
+ isRestoringRef: t,
128
+ hasCheckedStorageRef: a
129
+ }), q({
130
+ ...r,
131
+ lastWrittenNormalizedSearchRef: e
132
+ });
133
+ };
134
+ export {
135
+ J as default
136
+ };
137
+ //# sourceMappingURL=useUrlState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUrlState.js","sources":["../../src/hooks/useUrlState.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { isEqual, isNil } from 'es-toolkit';\n\nimport { deserializeValue, serializeValue, toQueryString, type UrlConfigItem } from '../utils/routeUtils';\nimport useAfterMount from './useAfterMount';\nimport useLatest from './useLatest';\n\ntype QueryString = string;\n\n/**\n * Configuration contract for `useUrlState`.\n *\n * Use this hook when your application uses **store/redux as source of truth**\n * and you want a centralized URL synchronizer:\n * - URL -> store: parse incoming search params and dispatch updates\n * - store -> URL: serialize current store values and navigate with push/replace\n *\n * Recommended setup:\n * - Mount one top-level synchronizer component near the router\n * - Pass only URL-managed store values via `storeValues`\n * - Keep URL writing centralized through this hook\n *\n * Not intended for \"URL-only state\" screens where you directly read/write\n * params via router APIs (for example `useSearchParams`) without store sync.\n */\ntype UseUrlStateProps<TState> = {\n /**\n * URL sync configuration.\n * Each entry maps one query param key to a store selector and update action.\n */\n config: readonly UrlConfigItem<TState, any>[];\n\n /**\n * Current URL search string (for example `location.search`).\n * Expected shape: `'?q=test&sort=-name'` or `''`.\n */\n searchString: QueryString;\n\n /**\n * Current store values used by the configured selectors. This could be values from a redux store.\n * Keys should match the `config` keys, values are compared against URL/defaults.\n */\n storeValues: Record<string, unknown>;\n\n /**\n * Optional localStorage key for sticky URL state restore on initial load\n * when managed URL params are missing.\n */\n localStorageKey?: string;\n\n /**\n * Router navigation type (typically from React Router `useNavigationType`).\n * `POP` indicates browser back/forward navigation.\n */\n navigationType?: 'POP' | 'PUSH' | 'REPLACE' | string;\n\n /**\n * Store update callback invoked when URL -> store sync detects a change.\n * Usually wraps `dispatch(...)`.\n */\n onUpdateStore: (action: any) => void;\n\n /**\n * Navigation callback used for store -> URL sync writes.\n * `historyMode` controls whether to `push` or `replace` the history entry.\n */\n onNavigate: (search: string, historyMode: 'push' | 'replace') => void;\n};\n\n// Helper for URL for Comparison:\n// Browsers/Routers might decode parts of the string automatically.\n// We force everything to a standard encoded format for reliable diffing.\nconst normalizeSearch = (search: string) => {\n const clean = search.replace(/^\\?/, '');\n return new URLSearchParams(clean).toString();\n};\n\nconst parseConfigValue = (item: UrlConfigItem<any, any>, urlRawValue: string | null) =>\n item.customDeserialize ? item.customDeserialize(urlRawValue) : deserializeValue(urlRawValue, item.type ?? 'string');\n\nconst getValueToApply = (parsedValue: unknown, defaultValue: unknown) => parsedValue ?? defaultValue;\n\nconst shouldDispatchParsedValue = (params: {\n valueToApply: unknown;\n currentStoreValue: unknown;\n urlRawValue: string | null;\n defaultValue: unknown;\n}) => {\n const { valueToApply, currentStoreValue, urlRawValue, defaultValue } = params;\n\n if (typeof valueToApply === 'undefined' || isEqual(valueToApply, currentStoreValue)) {\n return false;\n }\n\n const isUrlMissing = isNil(urlRawValue);\n const isStoreDefault = isEqual(currentStoreValue, defaultValue);\n return !(isUrlMissing && isStoreDefault);\n};\n\nconst serializeConfigValue = (\n item: UrlConfigItem<any, any>,\n storeValue: unknown,\n isDefault: boolean\n): string | null => {\n if (isDefault) {\n return null;\n }\n if (item.customSerialize) {\n return item.customSerialize(storeValue as never);\n }\n return serializeValue(storeValue as never, item.type ?? 'string');\n};\n\nconst applySearchParamUpdate = (params: {\n nextParams: URLSearchParams;\n key: string;\n serializedValue: string | null;\n}) => {\n const { nextParams, key, serializedValue } = params;\n\n if (isNil(serializedValue)) {\n if (!nextParams.has(key)) {\n return false;\n }\n nextParams.delete(key);\n return true;\n }\n\n nextParams.set(key, serializedValue);\n return true;\n};\n\nconst isUrlValueDefault = (item: UrlConfigItem<any, any>, urlRawValue: string | null) => {\n if (isNil(urlRawValue)) {\n return true;\n }\n const parsedValue = parseConfigValue(item, urlRawValue);\n const valueFromUrl = getValueToApply(parsedValue, item.defaultValue);\n return isEqual(valueFromUrl, item.defaultValue);\n};\n\n/**\n * ----------------------------------------------------------------------------\n * 1. URL -> Redux\n * ----------------------------------------------------------------------------\n * Responsibilities:\n * - Listen to searchString changes.\n * - Check against the \"Loop Lock\" (ignore if we just wrote this URL).\n * - Parse and Dispatch actions.\n */\ntype UseSyncUrlToStoreProps = {\n config: readonly UrlConfigItem<any, any>[];\n searchString: string;\n storeValues: Record<string, unknown>;\n navigationType?: string;\n onUpdateStore: (a: any) => void;\n lastWrittenNormalizedSearchRef: React.MutableRefObject<string | null>;\n isRestoringRef: React.MutableRefObject<boolean>;\n hasCheckedStorageRef: React.MutableRefObject<boolean>;\n};\n\nconst useSyncUrlToStore = ({\n config,\n searchString,\n storeValues,\n navigationType,\n onUpdateStore,\n lastWrittenNormalizedSearchRef,\n isRestoringRef,\n hasCheckedStorageRef,\n}: UseSyncUrlToStoreProps) => {\n // Keep latest values stable for URL-driven effect without adding them to deps.\n const latestConfigRef = useLatest(config);\n const latestStoreValuesRef = useLatest(storeValues);\n const latestOnUpdateStoreRef = useLatest(onUpdateStore);\n\n useEffect(() => {\n // SAFETY: Wait for Storage Check (Sticky State)\n if (!hasCheckedStorageRef.current) {\n return;\n }\n\n // 1. Check Loop Lock (Did we just write this URL?)\n const currentStandard = normalizeSearch(searchString);\n if (lastWrittenNormalizedSearchRef.current === currentStandard) {\n // Match found. Release marker and continue parsing.\n // This avoids skipping browser POP navigation when search equals\n // a previously written URL.\n lastWrittenNormalizedSearchRef.current = null;\n }\n\n // 2. Check Restoration Block\n if (isRestoringRef.current) {\n return;\n }\n\n // 3. Parse & Diff\n const currentParams = new URLSearchParams(searchString);\n\n latestConfigRef.current.forEach(item => {\n const urlRawValue = currentParams.get(item.key);\n const parsedValue = parseConfigValue(item, urlRawValue);\n const valueToApply = getValueToApply(parsedValue, item.defaultValue);\n const currentStoreValue = latestStoreValuesRef.current[item.key];\n\n if (\n shouldDispatchParsedValue({\n valueToApply,\n currentStoreValue,\n urlRawValue,\n defaultValue: item.defaultValue,\n })\n ) {\n // Missing URL params should not reset store on regular in-app navigations.\n // We only apply \"missing => default\" during POP (back/forward) transitions.\n if (isNil(urlRawValue) && navigationType !== 'POP') {\n return;\n }\n latestOnUpdateStoreRef.current(item.action(valueToApply));\n }\n });\n\n // CRITICAL: This dependency array MUST NOT include 'onUpdateStore' or 'storeValues'.\n // It should ONLY run when the URL string physically changes.\n }, [searchString, lastWrittenNormalizedSearchRef, isRestoringRef, hasCheckedStorageRef]);\n};\n\n/**\n * ----------------------------------------------------------------------------\n * 2. Redux -> URL\n * ----------------------------------------------------------------------------\n * Responsibilities:\n * - Listen to Redux changes.\n * - Calculate Ideal URL.\n * - Diff against Current URL.\n * - Handle Navigation Type ('POP' prevention).\n * - Set \"Loop Lock\" and Navigate.\n */\ntype UseSyncStoreToUrlProps = {\n config: readonly UrlConfigItem<any, any>[];\n searchString: string;\n storeValues: Record<string, unknown>;\n onNavigate: (s: string, m: 'push' | 'replace') => void;\n lastWrittenNormalizedSearchRef: React.MutableRefObject<string | null>;\n localStorageKey?: string;\n navigationType?: string;\n};\n\nconst useSyncStoreToUrl = (props: UseSyncStoreToUrlProps) => {\n const {\n config,\n searchString,\n storeValues,\n onNavigate,\n lastWrittenNormalizedSearchRef,\n localStorageKey,\n navigationType,\n } = props;\n\n // Keep navigate callback stable inside effect.\n const latestOnNavigateRef = useLatest(onNavigate);\n const previousSearchRef = useRef<string | null>(normalizeSearch(searchString));\n\n // Skip initial render (Reader handles hydration)\n useAfterMount(() => {\n const currentStandardSearch = normalizeSearch(searchString);\n const hasSearchChanged = previousSearchRef.current !== currentStandardSearch;\n previousSearchRef.current = currentStandardSearch;\n\n // POP navigation should be URL -> store only for the transition step.\n // If we write here, we can overwrite the forward stack.\n // This prevents the writer from immediately rewriting URL during back/forward\n // transitions (which can overwrite forward history).\n const isPopNavigationSync = navigationType === 'POP' && hasSearchChanged;\n if (isPopNavigationSync) {\n return;\n }\n\n const currentParams = new URLSearchParams(searchString);\n const nextParams = new URLSearchParams(searchString);\n\n let hasChanges = false;\n let hasPushChange = false;\n let isAllDefaults = true;\n\n config.forEach(item => {\n const storeVal = storeValues[item.key];\n const currentUrlVal = currentParams.get(item.key);\n const isDefault = isEqual(storeVal, item.defaultValue);\n\n if (!isDefault) isAllDefaults = false;\n\n const serializedVal = serializeConfigValue(item, storeVal, isDefault);\n\n if (serializedVal !== currentUrlVal) {\n hasChanges =\n applySearchParamUpdate({ nextParams, key: item.key, serializedValue: serializedVal }) || hasChanges;\n\n // Determine history mode preference for changed fields.\n // Global rule:\n // - 'push' items always push when changed.\n // - 'replace' items push once on default -> non-default, then replace thereafter.\n const historyMode = item.history ?? 'push';\n if (historyMode === 'push') {\n hasPushChange = true;\n } else if (!isDefault && isUrlValueDefault(item, currentUrlVal)) {\n hasPushChange = true;\n }\n }\n });\n\n if (hasChanges) {\n // 1. Generate URLs\n const prettyString = toQueryString(nextParams, config);\n const strictString = nextParams.toString();\n\n // 2. Set loop lock (Crucial: Use strict string for comparison)\n lastWrittenNormalizedSearchRef.current = strictString;\n\n // 3. Persist to Storage (if key provided)\n if (localStorageKey) {\n if (isAllDefaults && prettyString === '') {\n localStorage.removeItem(localStorageKey);\n } else {\n localStorage.setItem(localStorageKey, prettyString);\n }\n }\n\n // 4. Calculate Mode\n const mode = hasPushChange ? 'push' : 'replace';\n\n latestOnNavigateRef.current(prettyString, mode);\n }\n }, [storeValues, searchString, config, localStorageKey, navigationType]);\n // ^ onNavigate excluded from deps (used via ref) to be safe,\n // though storeValues changing is the main trigger.\n};\n\n/**\n * ----------------------------------------------------------------------------\n * 3. RESTORER HOOK (LocalStorage -> Redux)\n * ----------------------------------------------------------------------------\n * Responsibilities:\n * - Run once on mount.\n * - If URL is empty & Storage exists -> Force Redux update & URL Replace.\n */\n\ntype UseInitialRestoreFromStorageProps = {\n config: readonly UrlConfigItem<any, any>[];\n searchString: string;\n localStorageKey?: string;\n onUpdateStore: (a: any) => void;\n onNavigate: (s: string, m: 'push' | 'replace') => void;\n isRestoringRef: React.MutableRefObject<boolean>;\n lastWrittenNormalizedSearchRef: React.MutableRefObject<string | null>;\n hasCheckedStorageRef: React.MutableRefObject<boolean>;\n};\n\nconst useInitialRestoreFromStorage = (props: UseInitialRestoreFromStorageProps) => {\n const {\n config,\n searchString,\n localStorageKey,\n onUpdateStore,\n onNavigate,\n isRestoringRef,\n lastWrittenNormalizedSearchRef,\n hasCheckedStorageRef,\n } = props;\n\n useEffect(() => {\n if (!localStorageKey) {\n hasCheckedStorageRef.current = true;\n return;\n }\n\n const currentParams = new URLSearchParams(searchString);\n const hasManagedParams = config.some(item => currentParams.has(item.key));\n\n // Only restore if URL is \"empty\" regarding our config\n if (!hasManagedParams) {\n const savedString = localStorage.getItem(localStorageKey);\n\n if (savedString) {\n // Block the Reader from interfering\n isRestoringRef.current = true;\n\n // 1. Hydrate Redux (conceptually similar to Reader logic but forced)\n const savedParams = new URLSearchParams(savedString);\n config.forEach(item => {\n const val = savedParams.get(item.key);\n const deserialized = parseConfigValue(item, val);\n\n if (deserialized !== null && typeof deserialized !== 'undefined') {\n onUpdateStore(item.action(deserialized));\n }\n });\n\n // 2. Hydrate URL (Visual)\n const cleanSaved = savedString.replace(/^\\?/, '');\n const cleanCurrent = searchString.replace(/^\\?/, '');\n\n if (cleanSaved !== cleanCurrent) {\n // Set Lock so Reader doesn't freak out\n lastWrittenNormalizedSearchRef.current = new URLSearchParams(savedString).toString();\n onNavigate(savedString, 'replace');\n }\n\n // Unlock after tick\n setTimeout(() => {\n isRestoringRef.current = false;\n }, 0);\n }\n }\n\n hasCheckedStorageRef.current = true;\n }, [localStorageKey]); // Run once\n};\n\n/**\n * ----------------------------------------------------------------------------\n * MAIN EXPORT\n * ----------------------------------------------------------------------------\n */\nconst useUrlState = <TState>(props: UseUrlStateProps<TState>) => {\n // Shared communication channel between hooks\n\n // Stores the last URL search string written by this hook (normalized encoding).\n const lastWrittenNormalizedSearchRef = useRef<string | null>(null);\n\n // Shared flag for Restoration phase\n const isRestoringRef = useRef(false);\n const hasCheckedStorageRef = useRef(!props.localStorageKey);\n\n // 1. Sticky State (Restorer)\n useInitialRestoreFromStorage({\n ...props,\n lastWrittenNormalizedSearchRef,\n isRestoringRef,\n hasCheckedStorageRef,\n });\n\n // 2. Read from URL (URL -> Redux)\n useSyncUrlToStore({\n ...props,\n lastWrittenNormalizedSearchRef,\n isRestoringRef,\n hasCheckedStorageRef,\n });\n\n // 3. Write to URL (Redux -> URL)\n useSyncStoreToUrl({\n ...props,\n lastWrittenNormalizedSearchRef,\n });\n};\n\nexport default useUrlState;\n"],"names":["normalizeSearch","search","clean","parseConfigValue","item","urlRawValue","deserializeValue","getValueToApply","parsedValue","defaultValue","shouldDispatchParsedValue","params","valueToApply","currentStoreValue","isEqual","isUrlMissing","isNil","isStoreDefault","serializeConfigValue","storeValue","isDefault","serializeValue","applySearchParamUpdate","nextParams","key","serializedValue","isUrlValueDefault","valueFromUrl","useSyncUrlToStore","config","searchString","storeValues","navigationType","onUpdateStore","lastWrittenNormalizedSearchRef","isRestoringRef","hasCheckedStorageRef","latestConfigRef","useLatest","latestStoreValuesRef","latestOnUpdateStoreRef","useEffect","currentStandard","currentParams","useSyncStoreToUrl","props","onNavigate","localStorageKey","latestOnNavigateRef","previousSearchRef","useRef","useAfterMount","currentStandardSearch","hasSearchChanged","hasChanges","hasPushChange","isAllDefaults","storeVal","currentUrlVal","serializedVal","prettyString","toQueryString","strictString","mode","useInitialRestoreFromStorage","savedString","savedParams","val","deserialized","cleanSaved","cleanCurrent","useUrlState"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from './utils/mergeClassNameOverrides';
@@ -0,0 +1,5 @@
1
+ import { mergeClassNameOverrides as m } from "./utils/mergeClassNameOverrides.js";
2
+ export {
3
+ m as mergeClassNameOverrides
4
+ };
5
+ //# sourceMappingURL=mergeClassNameOverrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeClassNameOverrides.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}