@cube-dev/ui-kit 0.0.0-canary-ad23b00 → 0.0.0-canary-c76c00e

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 (416) hide show
  1. package/dist/_internal/hooks/use-chained-callback.js +1 -1
  2. package/dist/_internal/hooks/use-debounced-value.js +1 -1
  3. package/dist/_internal/hooks/use-deprecation-warning.js +1 -1
  4. package/dist/_internal/hooks/use-event.js +1 -1
  5. package/dist/_internal/hooks/use-is-first-render.js +1 -1
  6. package/dist/_internal/hooks/use-sync-ref.js +1 -1
  7. package/dist/_internal/hooks/use-timer/timer.js +1 -1
  8. package/dist/_internal/hooks/use-timer/use-timer.js +1 -1
  9. package/dist/_internal/hooks/use-warn.js +1 -1
  10. package/dist/components/Block.js +1 -1
  11. package/dist/components/CollectionItem.js +1 -1
  12. package/dist/components/GlobalStyles.js +1 -1
  13. package/dist/components/GridProvider.js +1 -1
  14. package/dist/components/HiddenInput.js +1 -1
  15. package/dist/components/Root.js +1 -1
  16. package/dist/components/actions/Action/Action.js +1 -1
  17. package/dist/components/actions/Banner/Banner.js +1 -1
  18. package/dist/components/actions/Button/Button.js +1 -1
  19. package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
  20. package/dist/components/actions/ButtonSplit/ButtonSplit.js +1 -1
  21. package/dist/components/actions/ButtonSplit/context.js +1 -1
  22. package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
  23. package/dist/components/actions/CommandMenu/styled.js +1 -1
  24. package/dist/components/actions/ItemAction/ItemAction.js +1 -1
  25. package/dist/components/actions/ItemActionContext.js +1 -1
  26. package/dist/components/actions/ItemButton/ItemButton.js +1 -1
  27. package/dist/components/actions/Link/Link.js +1 -1
  28. package/dist/components/actions/Menu/Menu.js +1 -1
  29. package/dist/components/actions/Menu/MenuItem.js +1 -1
  30. package/dist/components/actions/Menu/MenuSection.js +1 -1
  31. package/dist/components/actions/Menu/MenuTrigger.js +1 -1
  32. package/dist/components/actions/Menu/SubMenuTrigger.js +1 -1
  33. package/dist/components/actions/Menu/SubmenuTriggerContext.js +1 -1
  34. package/dist/components/actions/Menu/context.js +1 -1
  35. package/dist/components/actions/Menu/styled.js +1 -1
  36. package/dist/components/actions/index.js +1 -1
  37. package/dist/components/actions/use-action.js +1 -1
  38. package/dist/components/actions/use-anchored-menu.js +1 -1
  39. package/dist/components/actions/use-context-menu.js +1 -1
  40. package/dist/components/content/ActiveZone/ActiveZone.js +1 -1
  41. package/dist/components/content/Alert/Alert.js +1 -1
  42. package/dist/components/content/Alert/use-alert.js +1 -1
  43. package/dist/components/content/Avatar/Avatar.js +1 -1
  44. package/dist/components/content/Badge/Badge.js +1 -1
  45. package/dist/components/content/Card/Card.js +1 -1
  46. package/dist/components/content/Content.js +1 -1
  47. package/dist/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
  48. package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
  49. package/dist/components/content/Disclosure/Disclosure.js +1 -1
  50. package/dist/components/content/Divider.js +1 -1
  51. package/dist/components/content/Footer.js +1 -1
  52. package/dist/components/content/Header.js +1 -1
  53. package/dist/components/content/HotKeys/HotKeys.js +1 -1
  54. package/dist/components/content/Item/Item.js +1 -1
  55. package/dist/components/content/ItemBadge/ItemBadge.js +1 -1
  56. package/dist/components/content/ItemCard/ItemCard.js +1 -1
  57. package/dist/components/content/Layout/GridLayout.js +1 -1
  58. package/dist/components/content/Layout/Layout.js +1 -1
  59. package/dist/components/content/Layout/LayoutBlock.js +1 -1
  60. package/dist/components/content/Layout/LayoutCenter.js +1 -1
  61. package/dist/components/content/Layout/LayoutContainer.js +1 -1
  62. package/dist/components/content/Layout/LayoutContent.js +1 -1
  63. package/dist/components/content/Layout/LayoutContext.js +1 -1
  64. package/dist/components/content/Layout/LayoutFlex.js +1 -1
  65. package/dist/components/content/Layout/LayoutFooter.js +1 -1
  66. package/dist/components/content/Layout/LayoutGrid.js +1 -1
  67. package/dist/components/content/Layout/LayoutHeader.js +1 -1
  68. package/dist/components/content/Layout/LayoutPane.js +1 -1
  69. package/dist/components/content/Layout/LayoutPanel.js +1 -1
  70. package/dist/components/content/Layout/LayoutPanelHeader.js +1 -1
  71. package/dist/components/content/Layout/LayoutToolbar.js +1 -1
  72. package/dist/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
  73. package/dist/components/content/Layout/index.js +1 -1
  74. package/dist/components/content/Layout/utils.js +1 -1
  75. package/dist/components/content/Paragraph.js +1 -1
  76. package/dist/components/content/Placeholder/Placeholder.js +1 -1
  77. package/dist/components/content/PrismCode/PrismCode.js +1 -1
  78. package/dist/components/content/PrismCode/prismSetup.js +1 -1
  79. package/dist/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
  80. package/dist/components/content/Result/Result.js +1 -1
  81. package/dist/components/content/Skeleton/Skeleton.js +1 -1
  82. package/dist/components/content/Tag/Tag.js +1 -1
  83. package/dist/components/content/Text.js +1 -1
  84. package/dist/components/content/TextItem/TextItem.js +1 -1
  85. package/dist/components/content/Title.js +1 -1
  86. package/dist/components/content/Tree/Tree.js +43 -35
  87. package/dist/components/content/Tree/Tree.js.map +1 -1
  88. package/dist/components/content/Tree/TreeNode.js +1 -1
  89. package/dist/components/content/Tree/styled.js +1 -1
  90. package/dist/components/content/Tree/tree-index.js +26 -0
  91. package/dist/components/content/Tree/tree-index.js.map +1 -0
  92. package/dist/components/content/Tree/use-checkbox-tree.js +44 -97
  93. package/dist/components/content/Tree/use-checkbox-tree.js.map +1 -1
  94. package/dist/components/content/Tree/use-load-data.js +3 -3
  95. package/dist/components/content/Tree/use-load-data.js.map +1 -1
  96. package/dist/components/content/highlightText.js +1 -1
  97. package/dist/components/content/use-auto-tooltip.js +1 -1
  98. package/dist/components/fields/Checkbox/Checkbox.js +1 -1
  99. package/dist/components/fields/Checkbox/CheckboxGroup.js +1 -1
  100. package/dist/components/fields/Checkbox/context.js +1 -1
  101. package/dist/components/fields/ComboBox/ComboBox.js +1 -1
  102. package/dist/components/fields/DatePicker/DateInput.js +1 -1
  103. package/dist/components/fields/DatePicker/DateInputBase.js +1 -1
  104. package/dist/components/fields/DatePicker/DatePicker.js +1 -1
  105. package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
  106. package/dist/components/fields/DatePicker/DatePickerElement.js +1 -1
  107. package/dist/components/fields/DatePicker/DatePickerInput.js +1 -1
  108. package/dist/components/fields/DatePicker/DatePickerSegment.js +1 -1
  109. package/dist/components/fields/DatePicker/DateRangePicker.js +1 -1
  110. package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
  111. package/dist/components/fields/DatePicker/TimeInput.js +1 -1
  112. package/dist/components/fields/DatePicker/intl.js +1 -1
  113. package/dist/components/fields/DatePicker/parseDate.js +1 -1
  114. package/dist/components/fields/DatePicker/props.js +1 -1
  115. package/dist/components/fields/DatePicker/utils.js +1 -1
  116. package/dist/components/fields/FileInput/FileInput.js +1 -1
  117. package/dist/components/fields/FilterListBox/FilterListBox.js +1 -1
  118. package/dist/components/fields/FilterPicker/FilterPicker.js +1 -1
  119. package/dist/components/fields/Input/Input.js +1 -1
  120. package/dist/components/fields/ListBox/ListBox.js +1 -1
  121. package/dist/components/fields/NumberInput/NumberInput.js +1 -1
  122. package/dist/components/fields/NumberInput/StepButton.js +1 -1
  123. package/dist/components/fields/PasswordInput/PasswordInput.js +1 -1
  124. package/dist/components/fields/Picker/Picker.js +1 -1
  125. package/dist/components/fields/RadioGroup/Radio.js +1 -1
  126. package/dist/components/fields/RadioGroup/RadioGroup.js +1 -1
  127. package/dist/components/fields/RadioGroup/context.js +1 -1
  128. package/dist/components/fields/SearchInput/SearchInput.js +1 -1
  129. package/dist/components/fields/Select/Select.js +1 -1
  130. package/dist/components/fields/Slider/Gradation.js +1 -1
  131. package/dist/components/fields/Slider/HueSlider.js +1 -1
  132. package/dist/components/fields/Slider/RangeSlider.js +1 -1
  133. package/dist/components/fields/Slider/Slider.js +1 -1
  134. package/dist/components/fields/Slider/SliderBase.js +1 -1
  135. package/dist/components/fields/Slider/SliderThumb.js +1 -1
  136. package/dist/components/fields/Slider/SliderTrack.js +1 -1
  137. package/dist/components/fields/Slider/elements.js +1 -1
  138. package/dist/components/fields/Slider/index.js +1 -1
  139. package/dist/components/fields/Switch/Switch.js +1 -1
  140. package/dist/components/fields/TextArea/TextArea.js +1 -1
  141. package/dist/components/fields/TextInput/TextInput.js +1 -1
  142. package/dist/components/fields/TextInput/TextInputBase.js +1 -1
  143. package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
  144. package/dist/components/form/FieldWrapper/FieldWrapper.js +1 -1
  145. package/dist/components/form/FieldWrapper/extract-field-wrapper-props.js +1 -1
  146. package/dist/components/form/Form/Field.js +1 -1
  147. package/dist/components/form/Form/Form.js +1 -1
  148. package/dist/components/form/Form/ResetButton/ResetButton.js +1 -1
  149. package/dist/components/form/Form/SubmitButton/SubmitButton.js +1 -1
  150. package/dist/components/form/Form/SubmitError.js +1 -1
  151. package/dist/components/form/Form/index.js +1 -1
  152. package/dist/components/form/Form/use-field/use-field-props.js +1 -1
  153. package/dist/components/form/Form/use-field/use-field.js +1 -1
  154. package/dist/components/form/Form/use-form.js +1 -1
  155. package/dist/components/form/Form/validation.js +1 -1
  156. package/dist/components/form/Label.js +1 -1
  157. package/dist/components/form/wrapper.js +1 -1
  158. package/dist/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
  159. package/dist/components/helpers/IconSwitch/IconSwitch.js +1 -1
  160. package/dist/components/layout/Flex.js +1 -1
  161. package/dist/components/layout/Flow.js +1 -1
  162. package/dist/components/layout/Grid.js +1 -1
  163. package/dist/components/layout/Panel.js +1 -1
  164. package/dist/components/layout/Prefix.js +1 -1
  165. package/dist/components/layout/ResizablePanel.js +1 -1
  166. package/dist/components/layout/Space.js +1 -1
  167. package/dist/components/layout/Suffix.js +1 -1
  168. package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
  169. package/dist/components/navigation/Tabs/EditableTitle.js +1 -1
  170. package/dist/components/navigation/Tabs/TabButton.js +1 -1
  171. package/dist/components/navigation/Tabs/TabDropIndicator.js +1 -1
  172. package/dist/components/navigation/Tabs/TabPanel.js +1 -1
  173. package/dist/components/navigation/Tabs/TabPicker.js +1 -1
  174. package/dist/components/navigation/Tabs/Tabs.js +1 -1
  175. package/dist/components/navigation/Tabs/TabsAction.js +1 -1
  176. package/dist/components/navigation/Tabs/TabsContext.js +1 -1
  177. package/dist/components/navigation/Tabs/styled.js +1 -1
  178. package/dist/components/navigation/Tabs/types.js +1 -1
  179. package/dist/components/navigation/Tabs/use-tab-editing.js +1 -1
  180. package/dist/components/navigation/Tabs/use-tab-indicator.js +1 -1
  181. package/dist/components/organisms/FileTabs/FileTabs.js +1 -1
  182. package/dist/components/organisms/StatsCard/StatsCard.js +1 -1
  183. package/dist/components/other/Calendar/Calendar.js +1 -1
  184. package/dist/components/other/Calendar/CalendarCell.js +1 -1
  185. package/dist/components/other/Calendar/CalendarGrid.js +1 -1
  186. package/dist/components/other/Calendar/RangeCalendar.js +1 -1
  187. package/dist/components/other/CloudLogo/CloudLogo.js +1 -1
  188. package/dist/components/overlays/AlertDialog/AlertDialog.js +1 -1
  189. package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
  190. package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
  191. package/dist/components/overlays/Dialog/Dialog.js +1 -1
  192. package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
  193. package/dist/components/overlays/Dialog/DialogForm.js +1 -1
  194. package/dist/components/overlays/Dialog/DialogTrigger.js +1 -1
  195. package/dist/components/overlays/Dialog/context.js +1 -1
  196. package/dist/components/overlays/Dialog/use-dialog-container.js +1 -1
  197. package/dist/components/overlays/Modal/Modal.js +1 -1
  198. package/dist/components/overlays/Modal/OpenTransition.js +1 -1
  199. package/dist/components/overlays/Modal/Overlay.js +1 -1
  200. package/dist/components/overlays/Modal/Popover.js +1 -1
  201. package/dist/components/overlays/Modal/Tray.js +1 -1
  202. package/dist/components/overlays/Modal/Underlay.js +1 -1
  203. package/dist/components/overlays/Notifications/Notification.js +1 -1
  204. package/dist/components/overlays/Notifications/NotificationAction.js +1 -1
  205. package/dist/components/overlays/Notifications/NotificationCard.js +1 -1
  206. package/dist/components/overlays/Notifications/NotificationContext.js +1 -1
  207. package/dist/components/overlays/Notifications/NotificationItem.js +1 -1
  208. package/dist/components/overlays/Notifications/OverlayContainer.js +1 -1
  209. package/dist/components/overlays/Notifications/OverlayProvider.js +1 -1
  210. package/dist/components/overlays/Notifications/PersistentNotificationsList.js +1 -1
  211. package/dist/components/overlays/Notifications/dismissed-storage.js +1 -1
  212. package/dist/components/overlays/Notifications/format-relative-time.js +1 -1
  213. package/dist/components/overlays/Notifications/index.js +1 -1
  214. package/dist/components/overlays/Notifications/use-notification-state.js +1 -1
  215. package/dist/components/overlays/Notifications/use-notifications.js +1 -1
  216. package/dist/components/overlays/Notifications/use-overlay-timers.js +1 -1
  217. package/dist/components/overlays/Notifications/use-persistent-notifications.js +1 -1
  218. package/dist/components/overlays/Notifications/use-persistent-state.js +1 -1
  219. package/dist/components/overlays/Notifications/use-toast-state.js +1 -1
  220. package/dist/components/overlays/Toast/ToastItem.js +1 -1
  221. package/dist/components/overlays/Toast/index.js +1 -1
  222. package/dist/components/overlays/Toast/useProgressToast.js +1 -1
  223. package/dist/components/overlays/Toast/useToast.js +1 -1
  224. package/dist/components/overlays/Tooltip/Tooltip.js +1 -1
  225. package/dist/components/overlays/Tooltip/TooltipProvider.js +1 -1
  226. package/dist/components/overlays/Tooltip/TooltipTrigger.js +1 -1
  227. package/dist/components/overlays/Tooltip/context.js +1 -1
  228. package/dist/components/portal/Portal.js +1 -1
  229. package/dist/components/portal/PortalProvider.js +1 -1
  230. package/dist/components/portal/usePortal.js +1 -1
  231. package/dist/components/shared/InvalidIcon.js +1 -1
  232. package/dist/components/shared/ValidIcon.js +1 -1
  233. package/dist/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
  234. package/dist/components/status/Spin/Cube.js +1 -1
  235. package/dist/components/status/Spin/InternalSpinner.js +1 -1
  236. package/dist/components/status/Spin/Spin.js +1 -1
  237. package/dist/components/status/Spin/SpinsContainer.js +1 -1
  238. package/dist/data/item-themes.js +1 -1
  239. package/dist/data/themes.js +1 -1
  240. package/dist/icons/AdjustmentsHorizontalIcon.js +1 -1
  241. package/dist/icons/AdjustmentsIcon.js +1 -1
  242. package/dist/icons/AiIcon.js +1 -1
  243. package/dist/icons/AreaChartIcon.js +1 -1
  244. package/dist/icons/BackwardIcon.js +1 -1
  245. package/dist/icons/BarChartIcon.js +1 -1
  246. package/dist/icons/BellFilledIcon.js +1 -1
  247. package/dist/icons/BellIcon.js +1 -1
  248. package/dist/icons/BooleanIcon.js +1 -1
  249. package/dist/icons/CalendarEditIcon.js +1 -1
  250. package/dist/icons/CalendarIcon.js +1 -1
  251. package/dist/icons/CaretDownIcon.js +1 -1
  252. package/dist/icons/CaretUpIcon.js +1 -1
  253. package/dist/icons/ChartAreaStackedIcon.js +1 -1
  254. package/dist/icons/ChartAreaStackedPercentageIcon.js +1 -1
  255. package/dist/icons/ChartBarGroupedHorizontalIcon.js +1 -1
  256. package/dist/icons/ChartBarGroupedIcon.js +1 -1
  257. package/dist/icons/ChartBarHorizontalIcon.js +1 -1
  258. package/dist/icons/ChartBarLineIcon.js +1 -1
  259. package/dist/icons/ChartBarStackedHorizontalIcon.js +1 -1
  260. package/dist/icons/ChartBarStackedIcon.js +1 -1
  261. package/dist/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
  262. package/dist/icons/ChartBarStackedPercentageIcon.js +1 -1
  263. package/dist/icons/ChartBoxPlot2Icon.js +1 -1
  264. package/dist/icons/ChartBoxPlotIcon.js +1 -1
  265. package/dist/icons/ChartBubbleIcon.js +1 -1
  266. package/dist/icons/ChartDonut2Icon.js +1 -1
  267. package/dist/icons/ChartFunnelIcon.js +1 -1
  268. package/dist/icons/ChartHeatmapIcon.js +1 -1
  269. package/dist/icons/ChartKPIIcon.js +1 -1
  270. package/dist/icons/ChartPie2Icon.js +1 -1
  271. package/dist/icons/ChartScatterIcon.js +1 -1
  272. package/dist/icons/CheckCircleFilledIcon.js +1 -1
  273. package/dist/icons/CheckCircleIcon.js +1 -1
  274. package/dist/icons/CheckIcon.js +1 -1
  275. package/dist/icons/CircleFilledIcon.js +1 -1
  276. package/dist/icons/ClearIcon.js +1 -1
  277. package/dist/icons/CloseCircleFilledIcon.js +1 -1
  278. package/dist/icons/CloseCircleIcon.js +1 -1
  279. package/dist/icons/CloseIcon.js +1 -1
  280. package/dist/icons/CodeIcon.js +1 -1
  281. package/dist/icons/ColumnTotalIcon.js +1 -1
  282. package/dist/icons/CopyIcon.js +1 -1
  283. package/dist/icons/CountIcon.js +1 -1
  284. package/dist/icons/CubeIcon.js +1 -1
  285. package/dist/icons/CubePauseIcon.js +1 -1
  286. package/dist/icons/CubePlayIcon.js +1 -1
  287. package/dist/icons/CurrencyDollarIcon.js +1 -1
  288. package/dist/icons/DangerIcon.js +1 -1
  289. package/dist/icons/DashboardIcon.js +1 -1
  290. package/dist/icons/DatabaseIcon.js +1 -1
  291. package/dist/icons/DecimalDecreaseIcon.js +1 -1
  292. package/dist/icons/DecimalIncreaseIcon.js +1 -1
  293. package/dist/icons/DirectionIcon.js +1 -1
  294. package/dist/icons/DonutIcon.js +1 -1
  295. package/dist/icons/DownIcon.js +1 -1
  296. package/dist/icons/EditIcon.js +1 -1
  297. package/dist/icons/ExclamationCircleFilledIcon.js +1 -1
  298. package/dist/icons/ExclamationCircleIcon.js +1 -1
  299. package/dist/icons/ExclamationIcon.js +1 -1
  300. package/dist/icons/EyeIcon.js +1 -1
  301. package/dist/icons/EyeInvisibleIcon.js +1 -1
  302. package/dist/icons/FilterIcon.js +1 -1
  303. package/dist/icons/FolderFilledIcon.js +1 -1
  304. package/dist/icons/FolderIcon.js +1 -1
  305. package/dist/icons/FolderOpenFilledIcon.js +1 -1
  306. package/dist/icons/FolderOpenIcon.js +1 -1
  307. package/dist/icons/ForwardIcon.js +1 -1
  308. package/dist/icons/HierarchyIcon.js +1 -1
  309. package/dist/icons/HierarchyOpenIcon.js +1 -1
  310. package/dist/icons/Icon.js +1 -1
  311. package/dist/icons/InfoCircleIcon.js +1 -1
  312. package/dist/icons/InfoIcon.js +1 -1
  313. package/dist/icons/KeyIcon.js +1 -1
  314. package/dist/icons/LeftIcon.js +1 -1
  315. package/dist/icons/LineChartIcon.js +1 -1
  316. package/dist/icons/LoadingIcon.js +1 -1
  317. package/dist/icons/LockFilledIcon.js +1 -1
  318. package/dist/icons/LockIcon.js +1 -1
  319. package/dist/icons/MoreIcon.js +1 -1
  320. package/dist/icons/NotAllowedIcon.js +1 -1
  321. package/dist/icons/Number123Icon.js +1 -1
  322. package/dist/icons/NumberIcon.js +1 -1
  323. package/dist/icons/PauseCircleFilledIcon.js +1 -1
  324. package/dist/icons/PauseCircleIcon.js +1 -1
  325. package/dist/icons/PauseIcon.js +1 -1
  326. package/dist/icons/PercentageIcon.js +1 -1
  327. package/dist/icons/PieChartIcon.js +1 -1
  328. package/dist/icons/PlayCircleIcon.js +1 -1
  329. package/dist/icons/PlayIcon.js +1 -1
  330. package/dist/icons/PlusIcon.js +1 -1
  331. package/dist/icons/ProgressBarIcon.js +1 -1
  332. package/dist/icons/ReloadIcon.js +1 -1
  333. package/dist/icons/ReportIcon.js +1 -1
  334. package/dist/icons/ReturnIcon.js +1 -1
  335. package/dist/icons/RightIcon.js +1 -1
  336. package/dist/icons/RowTotalsIcon.js +1 -1
  337. package/dist/icons/SchemeIcon.js +1 -1
  338. package/dist/icons/SearchIcon.js +1 -1
  339. package/dist/icons/SemanticQueryIcon.js +1 -1
  340. package/dist/icons/SettingsIcon.js +1 -1
  341. package/dist/icons/ShieldFilledIcon.js +1 -1
  342. package/dist/icons/ShieldIcon.js +1 -1
  343. package/dist/icons/SlashIcon.js +1 -1
  344. package/dist/icons/SparklesIcon.js +1 -1
  345. package/dist/icons/SqlIcon.js +1 -1
  346. package/dist/icons/StatsIcon.js +1 -1
  347. package/dist/icons/StopIcon.js +1 -1
  348. package/dist/icons/StringIcon.js +1 -1
  349. package/dist/icons/SubtotalsIcon.js +1 -1
  350. package/dist/icons/SwitchIcon.js +1 -1
  351. package/dist/icons/TableIcon.js +1 -1
  352. package/dist/icons/ThumbsDownIcon.js +1 -1
  353. package/dist/icons/ThumbsUpIcon.js +1 -1
  354. package/dist/icons/ThunderboltCrossedIcon.js +1 -1
  355. package/dist/icons/ThunderboltFilledIcon.js +1 -1
  356. package/dist/icons/ThunderboltIcon.js +1 -1
  357. package/dist/icons/TimeIcon.js +1 -1
  358. package/dist/icons/TrashIcon.js +1 -1
  359. package/dist/icons/UnlockIcon.js +1 -1
  360. package/dist/icons/UpIcon.js +1 -1
  361. package/dist/icons/UserGroupIcon.js +1 -1
  362. package/dist/icons/UserIcon.js +1 -1
  363. package/dist/icons/UserLockIcon.js +1 -1
  364. package/dist/icons/ViewIcon.js +1 -1
  365. package/dist/icons/WarningFilledIcon.js +1 -1
  366. package/dist/icons/WarningIcon.js +1 -1
  367. package/dist/icons/wrap-icon.js +1 -1
  368. package/dist/index.js +1 -1
  369. package/dist/provider.js +1 -1
  370. package/dist/providers/TrackingProvider.js +1 -1
  371. package/dist/providers/navigationAdapter.default.js +1 -1
  372. package/dist/tokens/base.js +1 -1
  373. package/dist/tokens/colors.js +1 -1
  374. package/dist/tokens/index.js +1 -1
  375. package/dist/tokens/layout.js +1 -1
  376. package/dist/tokens/shadows.js +1 -1
  377. package/dist/tokens/sizes.js +1 -1
  378. package/dist/tokens/spacing.js +1 -1
  379. package/dist/tokens/typography.js +1 -1
  380. package/dist/utils/ResizeSensor.js +1 -1
  381. package/dist/utils/is-dev-env.js +1 -1
  382. package/dist/utils/modules.js +1 -1
  383. package/dist/utils/promise.js +1 -1
  384. package/dist/utils/raf.js +1 -1
  385. package/dist/utils/random.js +1 -1
  386. package/dist/utils/range.js +1 -1
  387. package/dist/utils/react/RenderCache.js +1 -1
  388. package/dist/utils/react/Slots.js +1 -1
  389. package/dist/utils/react/chain.js +1 -1
  390. package/dist/utils/react/forwardRefWithGenerics.js +1 -1
  391. package/dist/utils/react/index.js +1 -1
  392. package/dist/utils/react/interactions.js +1 -1
  393. package/dist/utils/react/isTextOnly.js +1 -1
  394. package/dist/utils/react/mapProps.js +1 -1
  395. package/dist/utils/react/mergeProps.js +1 -1
  396. package/dist/utils/react/nullableValue.js +1 -1
  397. package/dist/utils/react/resolveIcon.js +1 -1
  398. package/dist/utils/react/sharedStore.js +1 -1
  399. package/dist/utils/react/useCombinedRefs.js +1 -1
  400. package/dist/utils/react/useControlledFocusVisible.js +1 -1
  401. package/dist/utils/react/useEventBus.js +1 -1
  402. package/dist/utils/react/useId.js +1 -1
  403. package/dist/utils/react/useIsDarwin.js +1 -1
  404. package/dist/utils/react/useKeySymbols.js +1 -1
  405. package/dist/utils/react/useLayoutEffect.js +1 -1
  406. package/dist/utils/react/useLocalStorage.js +1 -1
  407. package/dist/utils/react/useMergeStyles.js +1 -1
  408. package/dist/utils/react/useQaProps.js +1 -1
  409. package/dist/utils/react/useViewportSize.js +1 -1
  410. package/dist/utils/react/wrapNodeIfPlain.js +1 -1
  411. package/dist/utils/selection.js +1 -1
  412. package/dist/utils/styles.js +1 -1
  413. package/dist/utils/tree.js +1 -1
  414. package/dist/utils/warnings.js +1 -1
  415. package/dist/version.js +2 -2
  416. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { extractStyles } from "../../../utils/styles.js";
3
3
  import { mergeProps } from "../../../utils/react/mergeProps.js";
4
4
  import { wrapNodeIfPlain } from "../../../utils/react/wrapNodeIfPlain.js";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { Space } from "../../layout/Space.js";
3
3
  import { Grid } from "../../layout/Grid.js";
4
4
  import { Flow } from "../../layout/Flow.js";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { _Item } from "../Item/Item.js";
3
3
  import { CloseIcon } from "../../../icons/CloseIcon.js";
4
4
  import { tasty } from "@tenphi/tasty";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { extractStyles } from "../../utils/styles.js";
3
3
  import { useSlotProps } from "../../utils/react/Slots.js";
4
4
  import { BASE_STYLES, COLOR_STYLES, TEXT_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { extractStyles } from "../../../utils/styles.js";
3
3
  import { TEXT_PROP_MAP, _Text } from "../Text.js";
4
4
  import { highlightText } from "../highlightText.js";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { extractStyles } from "../../utils/styles.js";
3
3
  import { useSlotProps } from "../../utils/react/Slots.js";
4
4
  import { TEXT_PROP_MAP } from "./Text.js";
@@ -1,8 +1,10 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { extractStyles } from "../../../utils/styles.js";
3
3
  import { mergeProps as mergeProps$1 } from "../../../utils/react/mergeProps.js";
4
+ import { mergeRefs } from "../../../utils/react/useCombinedRefs.js";
4
5
  import { useEvent } from "../../../_internal/hooks/use-event.js";
5
6
  import { TreeElement } from "./styled.js";
7
+ import { buildTreeIndex } from "./tree-index.js";
6
8
  import { TreeNode } from "./TreeNode.js";
7
9
  import { useCheckboxTree } from "./use-checkbox-tree.js";
8
10
  import { useLoadData } from "./use-load-data.js";
@@ -34,18 +36,6 @@ function renderItem(node) {
34
36
  children: node.title
35
37
  }, node.key);
36
38
  }
37
- /** Walk the treeData and build a flat `key -> node` index. */
38
- function buildNodesByKey(treeData) {
39
- const map = /* @__PURE__ */ new Map();
40
- const visit = (nodes) => {
41
- for (const node of nodes) {
42
- map.set(node.key, node);
43
- if (node.children) visit(node.children);
44
- }
45
- };
46
- visit(treeData);
47
- return map;
48
- }
49
39
  /** Walk the treeData and collect all keys whose `isDisabled === true`. */
50
40
  function collectDisabledKeys(treeData, treeIsDisabled) {
51
41
  const keys = [];
@@ -59,20 +49,6 @@ function collectDisabledKeys(treeData, treeIsDisabled) {
59
49
  return keys;
60
50
  }
61
51
  /**
62
- * Map `key -> parentKey` (used for `autoExpandParent`).
63
- */
64
- function buildParentOf(treeData) {
65
- const parentOf = /* @__PURE__ */ new Map();
66
- const visit = (nodes, parent) => {
67
- for (const node of nodes) {
68
- parentOf.set(node.key, parent);
69
- if (node.children) visit(node.children, node.key);
70
- }
71
- };
72
- visit(treeData, null);
73
- return parentOf;
74
- }
75
- /**
76
52
  * Expand the supplied keys with all of their ancestors. Used when
77
53
  * `autoExpandParent` is `true` so that the consumer can pass deep keys
78
54
  * (e.g. search matches) without having to manually walk parents.
@@ -106,8 +82,14 @@ function TreeBase(props, ref) {
106
82
  const { treeData, isCheckable = false, isSelectable, selectionMode: selectionModeProp, blockNode = false, isDisabled = false, defaultExpandedKeys, expandedKeys, autoExpandParent = false, defaultCheckedKeys, checkedKeys, defaultSelectedKeys, selectedKeys, height, loadData, onExpand, onCheck, onSelect, rowStyles, qa, ...otherProps } = props;
107
83
  const baseStyles = extractStyles(otherProps, OUTER_STYLES);
108
84
  const treeRef = useRef(null);
109
- const nodesByKey = useMemo(() => buildNodesByKey(treeData), [treeData]);
110
- const parentOf = useMemo(() => buildParentOf(treeData), [treeData]);
85
+ /**
86
+ * Single tree walk that produces `byKey`, `parentOf`, and `childrenOf`.
87
+ * Shared with `useCheckboxTree` so a `treeData` change triggers exactly
88
+ * one walk (instead of three) for these three maps.
89
+ */
90
+ const treeIndex = useMemo(() => buildTreeIndex(treeData), [treeData]);
91
+ const nodesByKey = treeIndex.byKey;
92
+ const parentOf = treeIndex.parentOf;
111
93
  const disabledKeys = useMemo(() => collectDisabledKeys(treeData, isDisabled), [treeData, isDisabled]);
112
94
  const selectionMode = resolveSelectionMode(selectionModeProp, isSelectable);
113
95
  /**
@@ -120,8 +102,20 @@ function TreeBase(props, ref) {
120
102
  expandedKeys,
121
103
  parentOf
122
104
  ]);
105
+ /**
106
+ * Mirror the same logic for the uncontrolled `defaultExpandedKeys`.
107
+ * `useTreeState` only reads it on mount, but we still need to expand
108
+ * ancestors so consumers passing a deep key (e.g. a search match) get
109
+ * the same behaviour as in the controlled mode.
110
+ */
111
+ const effectiveDefaultExpandedKeys = useMemo(() => autoExpandParent ? expandWithParents(defaultExpandedKeys, parentOf) : defaultExpandedKeys, [
112
+ autoExpandParent,
113
+ defaultExpandedKeys,
114
+ parentOf
115
+ ]);
123
116
  const checkbox = useCheckboxTree({
124
117
  treeData,
118
+ index: treeIndex,
125
119
  isCheckable,
126
120
  defaultCheckedKeys,
127
121
  checkedKeys,
@@ -129,7 +123,8 @@ function TreeBase(props, ref) {
129
123
  });
130
124
  const loadDataController = useLoadData({
131
125
  nodesByKey,
132
- loadData
126
+ loadData,
127
+ initialExpandedKeys: effectiveExpandedKeys ?? effectiveDefaultExpandedKeys
133
128
  });
134
129
  /**
135
130
  * Tracks the previously-expanded set so we can diff against the next set
@@ -138,8 +133,14 @@ function TreeBase(props, ref) {
138
133
  * ref is the only source for the previous state — `effectiveExpandedKeys`
139
134
  * is `undefined` and would otherwise produce an empty `previous` set,
140
135
  * mis-identifying every toggle.
136
+ *
137
+ * Must mirror what `useTreeState` was initialized with (the *effective*
138
+ * sets, which include `autoExpandParent` ancestors). Using the raw
139
+ * `defaultExpandedKeys` here would make the first toggle in uncontrolled
140
+ * mode diff against an undersized previous set, reporting auto-expanded
141
+ * ancestors as newly expanded.
141
142
  */
142
- const previousExpandedRef = useRef(new Set(expandedKeys ?? defaultExpandedKeys ?? []));
143
+ const previousExpandedRef = useRef(new Set(effectiveExpandedKeys ?? effectiveDefaultExpandedKeys ?? []));
143
144
  /**
144
145
  * Translate Stately's `Set<Key>` callbacks into the public AntD-flavoured
145
146
  * `Key[]` shape and dispatch the per-key load.
@@ -215,7 +216,7 @@ function TreeBase(props, ref) {
215
216
  defaultSelectedKeys,
216
217
  onSelectionChange: onSelect && selectionMode !== "none" ? handleSelectionChange : void 0,
217
218
  expandedKeys: effectiveExpandedKeys,
218
- defaultExpandedKeys,
219
+ defaultExpandedKeys: effectiveDefaultExpandedKeys,
219
220
  onExpandedChange: handleExpandedChange,
220
221
  disabledKeys,
221
222
  disabledBehavior: "all",
@@ -229,7 +230,7 @@ function TreeBase(props, ref) {
229
230
  onSelect,
230
231
  handleSelectionChange,
231
232
  effectiveExpandedKeys,
232
- defaultExpandedKeys,
233
+ effectiveDefaultExpandedKeys,
233
234
  handleExpandedChange,
234
235
  disabledKeys,
235
236
  treeData,
@@ -275,9 +276,16 @@ function TreeBase(props, ref) {
275
276
  }, [state.collection, state.expandedKeys]);
276
277
  const heightStyle = useMemo(() => height != null ? { ["--tree-height"]: `${height}px` } : void 0, [height]);
277
278
  const mods = useMemo(() => ({ "has-height": height != null }), [height]);
279
+ /**
280
+ * Merge the consumer's forwarded ref with our internal `treeRef`. Both
281
+ * must point at the same DOM node: `useTree` reads `treeRef.current` for
282
+ * keyboard navigation/focus management, and consumers expect the
283
+ * forwarded `ref` to receive the element too.
284
+ */
285
+ const mergedRef = useMemo(() => mergeRefs(ref, treeRef), [ref]);
278
286
  return /* @__PURE__ */ jsx(TreeElement, {
279
- ...mergeProps$1(gridProps, { ref: ref ?? treeRef }),
280
- ref: ref ?? treeRef,
287
+ ...mergeProps$1(gridProps, { ref: mergedRef }),
288
+ ref: mergedRef,
281
289
  qa: qa ?? "Tree",
282
290
  mods,
283
291
  styles: baseStyles,
@@ -1 +1 @@
1
- {"version":3,"file":"Tree.js","names":["mergeProps"],"sources":["../../../../src/components/content/Tree/Tree.tsx"],"sourcesContent":["import { OUTER_STYLES } from '@tenphi/tasty';\nimport { forwardRef, useMemo, useRef } from 'react';\nimport { useTree } from 'react-aria';\nimport { Item, useTreeState } from 'react-stately';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { mergeProps } from '../../../utils/react';\nimport { extractStyles } from '../../../utils/styles';\n\nimport { TreeElement } from './styled';\nimport { TreeNode } from './TreeNode';\nimport { useCheckboxTree } from './use-checkbox-tree';\nimport { useLoadData } from './use-load-data';\n\nimport type { Key, Node, Selection } from '@react-types/shared';\nimport type { CSSProperties, ForwardedRef, ReactElement } from 'react';\nimport type {\n CubeTreeNodeData,\n CubeTreeProps,\n TreeOnExpandInfo,\n TreeOnSelectInfo,\n TreeSelectionMode,\n} from './types';\n\n/**\n * Render an `<Item>` for React Stately's collection builder.\n *\n * The visible row content is rendered by `TreeNode` via a\n * `nodesByKey` lookup, so the `<Item>`'s body is only used by\n * Stately to build the collection (`textValue` for keyboard nav,\n * `childItems` for nested traversal).\n *\n * For nested traversal to work, the `children` of the `<Tree>` must\n * be passed as a *function* together with the top-level `items`\n * array — see the `<Tree>` `useCollection` call below. Stately\n * propagates that renderer into `childItems` so nested arrays of\n * raw `CubeTreeNodeData` are turned back into `<Item>` elements.\n */\nfunction renderItem(node: CubeTreeNodeData): ReactElement {\n const textValue =\n typeof node.title === 'string' ? node.title : String(node.key);\n return (\n <Item\n key={node.key}\n textValue={textValue}\n childItems={node.children as CubeTreeNodeData[] | undefined}\n >\n {node.title as any}\n </Item>\n );\n}\n\n/** Walk the treeData and build a flat `key -> node` index. */\nfunction buildNodesByKey(\n treeData: CubeTreeNodeData[],\n): Map<string, CubeTreeNodeData> {\n const map = new Map<string, CubeTreeNodeData>();\n const visit = (nodes: CubeTreeNodeData[]) => {\n for (const node of nodes) {\n map.set(node.key, node);\n if (node.children) visit(node.children);\n }\n };\n visit(treeData);\n return map;\n}\n\n/** Walk the treeData and collect all keys whose `isDisabled === true`. */\nfunction collectDisabledKeys(\n treeData: CubeTreeNodeData[],\n treeIsDisabled: boolean,\n): string[] {\n const keys: string[] = [];\n const visit = (nodes: CubeTreeNodeData[]) => {\n for (const node of nodes) {\n if (treeIsDisabled || node.isDisabled) keys.push(node.key);\n if (node.children) visit(node.children);\n }\n };\n visit(treeData);\n return keys;\n}\n\n/**\n * Map `key -> parentKey` (used for `autoExpandParent`).\n */\nfunction buildParentOf(\n treeData: CubeTreeNodeData[],\n): Map<string, string | null> {\n const parentOf = new Map<string, string | null>();\n const visit = (nodes: CubeTreeNodeData[], parent: string | null) => {\n for (const node of nodes) {\n parentOf.set(node.key, parent);\n if (node.children) visit(node.children, node.key);\n }\n };\n visit(treeData, null);\n return parentOf;\n}\n\n/**\n * Expand the supplied keys with all of their ancestors. Used when\n * `autoExpandParent` is `true` so that the consumer can pass deep keys\n * (e.g. search matches) without having to manually walk parents.\n */\nfunction expandWithParents(\n keys: string[] | undefined,\n parentOf: Map<string, string | null>,\n): string[] | undefined {\n if (!keys || keys.length === 0) return keys;\n const set = new Set<string>(keys);\n for (const key of keys) {\n let parent = parentOf.get(key);\n while (parent) {\n set.add(parent);\n parent = parentOf.get(parent);\n }\n }\n return Array.from(set);\n}\n\n/**\n * Coerce the public `selectionMode` / `isSelectable` pair into a single\n * `selectionMode` value for `useTreeState`.\n *\n * - `selectionMode` wins when both are passed.\n * - `isSelectable === false` is sugar for `selectionMode='none'`.\n * - `selectionMode` defaults to `'single'` (matches AntD's default).\n */\nfunction resolveSelectionMode(\n selectionMode: TreeSelectionMode | undefined,\n isSelectable: boolean | undefined,\n): TreeSelectionMode {\n if (selectionMode != null) return selectionMode;\n if (isSelectable === false) return 'none';\n return 'single';\n}\n\nfunction TreeBase(props: CubeTreeProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n treeData,\n isCheckable = false,\n isSelectable,\n selectionMode: selectionModeProp,\n blockNode = false,\n isDisabled = false,\n defaultExpandedKeys,\n expandedKeys,\n autoExpandParent = false,\n defaultCheckedKeys,\n checkedKeys,\n defaultSelectedKeys,\n selectedKeys,\n height,\n loadData,\n onExpand,\n onCheck,\n onSelect,\n rowStyles,\n qa,\n ...otherProps\n } = props;\n\n const baseStyles = extractStyles(otherProps, OUTER_STYLES);\n\n const treeRef = useRef<HTMLDivElement>(null);\n\n const nodesByKey = useMemo(() => buildNodesByKey(treeData), [treeData]);\n const parentOf = useMemo(() => buildParentOf(treeData), [treeData]);\n\n const disabledKeys = useMemo(\n () => collectDisabledKeys(treeData, isDisabled),\n [treeData, isDisabled],\n );\n\n const selectionMode = resolveSelectionMode(selectionModeProp, isSelectable);\n\n /**\n * Apply `autoExpandParent` to the controlled `expandedKeys`. This is\n * a one-shot thing — once the consumer responds to `onExpand` and\n * sets `autoExpandParent` to `false`, we stop force-expanding parents.\n */\n const effectiveExpandedKeys = useMemo(\n () =>\n autoExpandParent\n ? expandWithParents(expandedKeys, parentOf)\n : expandedKeys,\n [autoExpandParent, expandedKeys, parentOf],\n );\n\n const checkbox = useCheckboxTree({\n treeData,\n isCheckable,\n defaultCheckedKeys,\n checkedKeys,\n onCheck,\n });\n\n const loadDataController = useLoadData({ nodesByKey, loadData });\n\n /**\n * Tracks the previously-expanded set so we can diff against the next set\n * inside `handleExpandedChange`. In controlled mode the parent owns the\n * truth (read from `effectiveExpandedKeys`); in uncontrolled mode this\n * ref is the only source for the previous state — `effectiveExpandedKeys`\n * is `undefined` and would otherwise produce an empty `previous` set,\n * mis-identifying every toggle.\n */\n const previousExpandedRef = useRef<Set<Key>>(\n new Set<Key>(expandedKeys ?? defaultExpandedKeys ?? []),\n );\n\n /**\n * Translate Stately's `Set<Key>` callbacks into the public AntD-flavoured\n * `Key[]` shape and dispatch the per-key load.\n */\n const handleExpandedChange = useEvent((nextSet: Set<Key>) => {\n loadDataController.onExpandedChanged(nextSet);\n\n const previous =\n expandedKeys !== undefined\n ? new Set<Key>(effectiveExpandedKeys ?? [])\n : previousExpandedRef.current;\n previousExpandedRef.current = new Set<Key>(nextSet);\n\n if (!onExpand) return;\n const nextArr: Key[] = Array.from(nextSet);\n\n /**\n * Find the single key that toggled relative to the previous set.\n * Useful for `info.node` and `info.expanded` — matches AntD.\n */\n let toggledKey: Key | null = null;\n let toggledExpanded = false;\n for (const k of nextArr) {\n if (!previous.has(k)) {\n toggledKey = k;\n toggledExpanded = true;\n break;\n }\n }\n if (toggledKey == null) {\n for (const k of previous) {\n if (!nextSet.has(k)) {\n toggledKey = k;\n toggledExpanded = false;\n break;\n }\n }\n }\n\n const node =\n toggledKey != null ? nodesByKey.get(String(toggledKey)) : undefined;\n const info: TreeOnExpandInfo = {\n expanded: toggledExpanded,\n node: node ?? ({} as CubeTreeNodeData),\n };\n onExpand(nextArr, info);\n });\n\n const handleSelectionChange = useEvent((selection: Selection) => {\n if (!onSelect) return;\n const arr: Key[] =\n selection === 'all'\n ? Array.from(nodesByKey.keys())\n : Array.from(selection);\n /**\n * Stately's `onSelectionChange` hands us the *next* selection only —\n * we don't get a \"toggled key\" diff for free. For `single` mode we\n * can infer it cheaply (it's the only entry); for `multiple` we\n * report the most recent addition. Falls back to the first key.\n */\n let toggledKey: Key | null = null;\n let toggledSelected = false;\n if (selectionMode === 'single') {\n toggledKey = arr[0] ?? null;\n toggledSelected = arr.length > 0;\n } else if (selection !== 'all') {\n toggledKey = arr.length > 0 ? arr[arr.length - 1] : null;\n toggledSelected = arr.length > 0;\n } else {\n toggledKey = arr[0] ?? null;\n toggledSelected = true;\n }\n\n const node =\n toggledKey != null ? nodesByKey.get(String(toggledKey)) : undefined;\n const selectedNodes = arr\n .map((k) => nodesByKey.get(String(k)))\n .filter((n): n is CubeTreeNodeData => !!n);\n\n const info: TreeOnSelectInfo = {\n selected: toggledSelected,\n node: node ?? ({} as CubeTreeNodeData),\n selectedNodes,\n };\n\n onSelect(arr, info);\n });\n\n /**\n * Stately propagates the `children` function through `childItems`,\n * so a single render function recursively turns the entire\n * `treeData` array into `<Item>` elements.\n */\n const renderCollectionItem = useEvent((item: CubeTreeNodeData) =>\n renderItem(item),\n );\n\n const ariaProps = useMemo(\n () => ({\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange:\n onSelect && selectionMode !== 'none'\n ? handleSelectionChange\n : undefined,\n expandedKeys: effectiveExpandedKeys,\n defaultExpandedKeys,\n onExpandedChange: handleExpandedChange,\n disabledKeys,\n disabledBehavior: 'all' as const,\n items: treeData,\n children: renderCollectionItem as any,\n 'aria-label': 'Tree',\n }),\n [\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelect,\n handleSelectionChange,\n effectiveExpandedKeys,\n defaultExpandedKeys,\n handleExpandedChange,\n disabledKeys,\n treeData,\n renderCollectionItem,\n ],\n );\n\n const baseState = useTreeState<CubeTreeNodeData>(ariaProps);\n\n /**\n * The legacy `TreeCollection` returned by `useTreeState` doesn't\n * implement `getChildren`, but `@react-aria/tree`'s `useTree`\n * (via `useGridListItem`) calls it unguarded for any nested row\n * (`node.level > 0`). Patch it once so `useTree` works on top of\n * the legacy state without forking.\n */\n const state = useMemo(() => {\n const collection = baseState.collection;\n if (typeof (collection as any).getChildren === 'function') {\n return baseState;\n }\n const getChildren = (key: Key): Iterable<Node<CubeTreeNodeData>> => {\n const result: Node<CubeTreeNodeData>[] = [];\n const node = collection.getItem(key);\n if (!node) return result;\n for (const child of node.childNodes) {\n result.push(child);\n }\n return result;\n };\n const patched = Object.assign(\n Object.create(Object.getPrototypeOf(collection)),\n collection,\n { getChildren },\n );\n return { ...baseState, collection: patched };\n }, [baseState]);\n\n const { gridProps } = useTree(ariaProps, state, treeRef);\n\n /**\n * Iterate the collection in DOM order. The TreeCollection only walks\n * into expanded subtrees, so `getKeys()` already gives us *only*\n * visible rows — no manual filtering required.\n */\n const visibleNodes: Node<CubeTreeNodeData>[] = useMemo(() => {\n const out: Node<CubeTreeNodeData>[] = [];\n for (const key of state.collection.getKeys()) {\n const node = state.collection.getItem(key);\n if (node && node.type === 'item') out.push(node);\n }\n return out;\n }, [state.collection, state.expandedKeys]);\n\n const heightStyle = useMemo<CSSProperties | undefined>(\n () =>\n height != null\n ? ({\n ['--tree-height' as keyof CSSProperties]: `${height}px`,\n } as CSSProperties)\n : undefined,\n [height],\n );\n\n const mods = useMemo(\n () => ({\n 'has-height': height != null,\n }),\n [height],\n );\n\n const elementProps = mergeProps(gridProps, {\n ref: ref ?? treeRef,\n });\n\n return (\n <TreeElement\n {...elementProps}\n ref={ref ?? treeRef}\n qa={qa ?? 'Tree'}\n mods={mods}\n styles={baseStyles}\n style={heightStyle}\n >\n {visibleNodes.map((node) => {\n const data = nodesByKey.get(String(node.key));\n if (!data) return null;\n const isExpanded = state.expandedKeys.has(node.key);\n return (\n <TreeNode\n key={node.key}\n node={node}\n data={data}\n state={state}\n isCheckable={isCheckable}\n isExpanded={isExpanded}\n isChecked={checkbox.checkedSet.has(String(node.key))}\n isIndeterminate={checkbox.halfCheckedSet.has(String(node.key))}\n isLoading={loadDataController.loadingKeys.has(String(node.key))}\n isBlockNode={blockNode}\n rowStyles={rowStyles}\n onToggleChecked={checkbox.toggle}\n />\n );\n })}\n </TreeElement>\n );\n}\n\nconst _Tree = forwardRef(TreeBase);\n\n/**\n * Hierarchical data display with optional checkboxes, single/multi\n * selection, async lazy loading, and keyboard navigation.\n *\n * Built on `useTree` / `useTreeState` (React Aria + React Stately) and\n * styled with Tasty.\n *\n * @example\n * ```tsx\n * <Tree\n * treeData={data}\n * isCheckable\n * selectionMode=\"none\"\n * defaultExpandedKeys={['root']}\n * onCheck={(keys) => console.log(keys)}\n * />\n * ```\n */\nexport const Tree = _Tree;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tree.js","names":["mergeProps"],"sources":["../../../../src/components/content/Tree/Tree.tsx"],"sourcesContent":["import { OUTER_STYLES } from '@tenphi/tasty';\nimport { forwardRef, useMemo, useRef } from 'react';\nimport { useTree } from 'react-aria';\nimport { Item, useTreeState } from 'react-stately';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { mergeProps, mergeRefs } from '../../../utils/react';\nimport { extractStyles } from '../../../utils/styles';\n\nimport { TreeElement } from './styled';\nimport { buildTreeIndex } from './tree-index';\nimport { TreeNode } from './TreeNode';\nimport { useCheckboxTree } from './use-checkbox-tree';\nimport { useLoadData } from './use-load-data';\n\nimport type { Key, Node, Selection } from '@react-types/shared';\nimport type { CSSProperties, ForwardedRef, ReactElement } from 'react';\nimport type {\n CubeTreeNodeData,\n CubeTreeProps,\n TreeOnExpandInfo,\n TreeOnSelectInfo,\n TreeSelectionMode,\n} from './types';\n\n/**\n * Render an `<Item>` for React Stately's collection builder.\n *\n * The visible row content is rendered by `TreeNode` via a\n * `nodesByKey` lookup, so the `<Item>`'s body is only used by\n * Stately to build the collection (`textValue` for keyboard nav,\n * `childItems` for nested traversal).\n *\n * For nested traversal to work, the `children` of the `<Tree>` must\n * be passed as a *function* together with the top-level `items`\n * array — see the `<Tree>` `useCollection` call below. Stately\n * propagates that renderer into `childItems` so nested arrays of\n * raw `CubeTreeNodeData` are turned back into `<Item>` elements.\n */\nfunction renderItem(node: CubeTreeNodeData): ReactElement {\n const textValue =\n typeof node.title === 'string' ? node.title : String(node.key);\n return (\n <Item\n key={node.key}\n textValue={textValue}\n childItems={node.children as CubeTreeNodeData[] | undefined}\n >\n {node.title as any}\n </Item>\n );\n}\n\n/** Walk the treeData and collect all keys whose `isDisabled === true`. */\nfunction collectDisabledKeys(\n treeData: CubeTreeNodeData[],\n treeIsDisabled: boolean,\n): string[] {\n const keys: string[] = [];\n const visit = (nodes: CubeTreeNodeData[]) => {\n for (const node of nodes) {\n if (treeIsDisabled || node.isDisabled) keys.push(node.key);\n if (node.children) visit(node.children);\n }\n };\n visit(treeData);\n return keys;\n}\n\n/**\n * Expand the supplied keys with all of their ancestors. Used when\n * `autoExpandParent` is `true` so that the consumer can pass deep keys\n * (e.g. search matches) without having to manually walk parents.\n */\nfunction expandWithParents(\n keys: string[] | undefined,\n parentOf: Map<string, string | null>,\n): string[] | undefined {\n if (!keys || keys.length === 0) return keys;\n const set = new Set<string>(keys);\n for (const key of keys) {\n let parent = parentOf.get(key);\n while (parent) {\n set.add(parent);\n parent = parentOf.get(parent);\n }\n }\n return Array.from(set);\n}\n\n/**\n * Coerce the public `selectionMode` / `isSelectable` pair into a single\n * `selectionMode` value for `useTreeState`.\n *\n * - `selectionMode` wins when both are passed.\n * - `isSelectable === false` is sugar for `selectionMode='none'`.\n * - `selectionMode` defaults to `'single'` (matches AntD's default).\n */\nfunction resolveSelectionMode(\n selectionMode: TreeSelectionMode | undefined,\n isSelectable: boolean | undefined,\n): TreeSelectionMode {\n if (selectionMode != null) return selectionMode;\n if (isSelectable === false) return 'none';\n return 'single';\n}\n\nfunction TreeBase(props: CubeTreeProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n treeData,\n isCheckable = false,\n isSelectable,\n selectionMode: selectionModeProp,\n blockNode = false,\n isDisabled = false,\n defaultExpandedKeys,\n expandedKeys,\n autoExpandParent = false,\n defaultCheckedKeys,\n checkedKeys,\n defaultSelectedKeys,\n selectedKeys,\n height,\n loadData,\n onExpand,\n onCheck,\n onSelect,\n rowStyles,\n qa,\n ...otherProps\n } = props;\n\n const baseStyles = extractStyles(otherProps, OUTER_STYLES);\n\n const treeRef = useRef<HTMLDivElement>(null);\n\n /**\n * Single tree walk that produces `byKey`, `parentOf`, and `childrenOf`.\n * Shared with `useCheckboxTree` so a `treeData` change triggers exactly\n * one walk (instead of three) for these three maps.\n */\n const treeIndex = useMemo(() => buildTreeIndex(treeData), [treeData]);\n const nodesByKey = treeIndex.byKey;\n const parentOf = treeIndex.parentOf;\n\n const disabledKeys = useMemo(\n () => collectDisabledKeys(treeData, isDisabled),\n [treeData, isDisabled],\n );\n\n const selectionMode = resolveSelectionMode(selectionModeProp, isSelectable);\n\n /**\n * Apply `autoExpandParent` to the controlled `expandedKeys`. This is\n * a one-shot thing — once the consumer responds to `onExpand` and\n * sets `autoExpandParent` to `false`, we stop force-expanding parents.\n */\n const effectiveExpandedKeys = useMemo(\n () =>\n autoExpandParent\n ? expandWithParents(expandedKeys, parentOf)\n : expandedKeys,\n [autoExpandParent, expandedKeys, parentOf],\n );\n\n /**\n * Mirror the same logic for the uncontrolled `defaultExpandedKeys`.\n * `useTreeState` only reads it on mount, but we still need to expand\n * ancestors so consumers passing a deep key (e.g. a search match) get\n * the same behaviour as in the controlled mode.\n */\n const effectiveDefaultExpandedKeys = useMemo(\n () =>\n autoExpandParent\n ? expandWithParents(defaultExpandedKeys, parentOf)\n : defaultExpandedKeys,\n [autoExpandParent, defaultExpandedKeys, parentOf],\n );\n\n const checkbox = useCheckboxTree({\n treeData,\n index: treeIndex,\n isCheckable,\n defaultCheckedKeys,\n checkedKeys,\n onCheck,\n });\n\n const loadDataController = useLoadData({\n nodesByKey,\n loadData,\n initialExpandedKeys: effectiveExpandedKeys ?? effectiveDefaultExpandedKeys,\n });\n\n /**\n * Tracks the previously-expanded set so we can diff against the next set\n * inside `handleExpandedChange`. In controlled mode the parent owns the\n * truth (read from `effectiveExpandedKeys`); in uncontrolled mode this\n * ref is the only source for the previous state — `effectiveExpandedKeys`\n * is `undefined` and would otherwise produce an empty `previous` set,\n * mis-identifying every toggle.\n *\n * Must mirror what `useTreeState` was initialized with (the *effective*\n * sets, which include `autoExpandParent` ancestors). Using the raw\n * `defaultExpandedKeys` here would make the first toggle in uncontrolled\n * mode diff against an undersized previous set, reporting auto-expanded\n * ancestors as newly expanded.\n */\n const previousExpandedRef = useRef<Set<Key>>(\n new Set<Key>(effectiveExpandedKeys ?? effectiveDefaultExpandedKeys ?? []),\n );\n\n /**\n * Translate Stately's `Set<Key>` callbacks into the public AntD-flavoured\n * `Key[]` shape and dispatch the per-key load.\n */\n const handleExpandedChange = useEvent((nextSet: Set<Key>) => {\n loadDataController.onExpandedChanged(nextSet);\n\n const previous =\n expandedKeys !== undefined\n ? new Set<Key>(effectiveExpandedKeys ?? [])\n : previousExpandedRef.current;\n previousExpandedRef.current = new Set<Key>(nextSet);\n\n if (!onExpand) return;\n const nextArr: Key[] = Array.from(nextSet);\n\n /**\n * Find the single key that toggled relative to the previous set.\n * Useful for `info.node` and `info.expanded` — matches AntD.\n */\n let toggledKey: Key | null = null;\n let toggledExpanded = false;\n for (const k of nextArr) {\n if (!previous.has(k)) {\n toggledKey = k;\n toggledExpanded = true;\n break;\n }\n }\n if (toggledKey == null) {\n for (const k of previous) {\n if (!nextSet.has(k)) {\n toggledKey = k;\n toggledExpanded = false;\n break;\n }\n }\n }\n\n const node =\n toggledKey != null ? nodesByKey.get(String(toggledKey)) : undefined;\n const info: TreeOnExpandInfo = {\n expanded: toggledExpanded,\n node: node ?? ({} as CubeTreeNodeData),\n };\n onExpand(nextArr, info);\n });\n\n const handleSelectionChange = useEvent((selection: Selection) => {\n if (!onSelect) return;\n const arr: Key[] =\n selection === 'all'\n ? Array.from(nodesByKey.keys())\n : Array.from(selection);\n /**\n * Stately's `onSelectionChange` hands us the *next* selection only —\n * we don't get a \"toggled key\" diff for free. For `single` mode we\n * can infer it cheaply (it's the only entry); for `multiple` we\n * report the most recent addition. Falls back to the first key.\n */\n let toggledKey: Key | null = null;\n let toggledSelected = false;\n if (selectionMode === 'single') {\n toggledKey = arr[0] ?? null;\n toggledSelected = arr.length > 0;\n } else if (selection !== 'all') {\n toggledKey = arr.length > 0 ? arr[arr.length - 1] : null;\n toggledSelected = arr.length > 0;\n } else {\n toggledKey = arr[0] ?? null;\n toggledSelected = true;\n }\n\n const node =\n toggledKey != null ? nodesByKey.get(String(toggledKey)) : undefined;\n const selectedNodes = arr\n .map((k) => nodesByKey.get(String(k)))\n .filter((n): n is CubeTreeNodeData => !!n);\n\n const info: TreeOnSelectInfo = {\n selected: toggledSelected,\n node: node ?? ({} as CubeTreeNodeData),\n selectedNodes,\n };\n\n onSelect(arr, info);\n });\n\n /**\n * Stately propagates the `children` function through `childItems`,\n * so a single render function recursively turns the entire\n * `treeData` array into `<Item>` elements.\n */\n const renderCollectionItem = useEvent((item: CubeTreeNodeData) =>\n renderItem(item),\n );\n\n const ariaProps = useMemo(\n () => ({\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange:\n onSelect && selectionMode !== 'none'\n ? handleSelectionChange\n : undefined,\n expandedKeys: effectiveExpandedKeys,\n defaultExpandedKeys: effectiveDefaultExpandedKeys,\n onExpandedChange: handleExpandedChange,\n disabledKeys,\n disabledBehavior: 'all' as const,\n items: treeData,\n children: renderCollectionItem as any,\n 'aria-label': 'Tree',\n }),\n [\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelect,\n handleSelectionChange,\n effectiveExpandedKeys,\n effectiveDefaultExpandedKeys,\n handleExpandedChange,\n disabledKeys,\n treeData,\n renderCollectionItem,\n ],\n );\n\n const baseState = useTreeState<CubeTreeNodeData>(ariaProps);\n\n /**\n * The legacy `TreeCollection` returned by `useTreeState` doesn't\n * implement `getChildren`, but `@react-aria/tree`'s `useTree`\n * (via `useGridListItem`) calls it unguarded for any nested row\n * (`node.level > 0`). Patch it once so `useTree` works on top of\n * the legacy state without forking.\n */\n const state = useMemo(() => {\n const collection = baseState.collection;\n if (typeof (collection as any).getChildren === 'function') {\n return baseState;\n }\n const getChildren = (key: Key): Iterable<Node<CubeTreeNodeData>> => {\n const result: Node<CubeTreeNodeData>[] = [];\n const node = collection.getItem(key);\n if (!node) return result;\n for (const child of node.childNodes) {\n result.push(child);\n }\n return result;\n };\n const patched = Object.assign(\n Object.create(Object.getPrototypeOf(collection)),\n collection,\n { getChildren },\n );\n return { ...baseState, collection: patched };\n }, [baseState]);\n\n const { gridProps } = useTree(ariaProps, state, treeRef);\n\n /**\n * Iterate the collection in DOM order. The TreeCollection only walks\n * into expanded subtrees, so `getKeys()` already gives us *only*\n * visible rows — no manual filtering required.\n */\n const visibleNodes: Node<CubeTreeNodeData>[] = useMemo(() => {\n const out: Node<CubeTreeNodeData>[] = [];\n for (const key of state.collection.getKeys()) {\n const node = state.collection.getItem(key);\n if (node && node.type === 'item') out.push(node);\n }\n return out;\n }, [state.collection, state.expandedKeys]);\n\n const heightStyle = useMemo<CSSProperties | undefined>(\n () =>\n height != null\n ? ({\n ['--tree-height' as keyof CSSProperties]: `${height}px`,\n } as CSSProperties)\n : undefined,\n [height],\n );\n\n const mods = useMemo(\n () => ({\n 'has-height': height != null,\n }),\n [height],\n );\n\n /**\n * Merge the consumer's forwarded ref with our internal `treeRef`. Both\n * must point at the same DOM node: `useTree` reads `treeRef.current` for\n * keyboard navigation/focus management, and consumers expect the\n * forwarded `ref` to receive the element too.\n */\n const mergedRef = useMemo(() => mergeRefs(ref, treeRef), [ref]);\n\n const elementProps = mergeProps(gridProps, {\n ref: mergedRef,\n });\n\n return (\n <TreeElement\n {...elementProps}\n ref={mergedRef}\n qa={qa ?? 'Tree'}\n mods={mods}\n styles={baseStyles}\n style={heightStyle}\n >\n {visibleNodes.map((node) => {\n const data = nodesByKey.get(String(node.key));\n if (!data) return null;\n const isExpanded = state.expandedKeys.has(node.key);\n return (\n <TreeNode\n key={node.key}\n node={node}\n data={data}\n state={state}\n isCheckable={isCheckable}\n isExpanded={isExpanded}\n isChecked={checkbox.checkedSet.has(String(node.key))}\n isIndeterminate={checkbox.halfCheckedSet.has(String(node.key))}\n isLoading={loadDataController.loadingKeys.has(String(node.key))}\n isBlockNode={blockNode}\n rowStyles={rowStyles}\n onToggleChecked={checkbox.toggle}\n />\n );\n })}\n </TreeElement>\n );\n}\n\nconst _Tree = forwardRef(TreeBase);\n\n/**\n * Hierarchical data display with optional checkboxes, single/multi\n * selection, async lazy loading, and keyboard navigation.\n *\n * Built on `useTree` / `useTreeState` (React Aria + React Stately) and\n * styled with Tasty.\n *\n * @example\n * ```tsx\n * <Tree\n * treeData={data}\n * isCheckable\n * selectionMode=\"none\"\n * defaultExpandedKeys={['root']}\n * onCheck={(keys) => console.log(keys)}\n * />\n * ```\n */\nexport const Tree = _Tree;\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { mergeProps as mergeProps$1 } from "../../../utils/react/mergeProps.js";
3
3
  import { useEvent } from "../../../_internal/hooks/use-event.js";
4
4
  import { LoadingIcon } from "../../../icons/LoadingIcon.js";
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { _Item } from "../Item/Item.js";
3
3
  import { Action } from "../../actions/Action/Action.js";
4
4
  import { tasty } from "@tenphi/tasty";
@@ -0,0 +1,26 @@
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
+ //#region src/components/content/Tree/tree-index.ts
3
+ function buildTreeIndex(treeData) {
4
+ const byKey = /* @__PURE__ */ new Map();
5
+ const parentOf = /* @__PURE__ */ new Map();
6
+ const childrenOf = /* @__PURE__ */ new Map();
7
+ const visit = (nodes, parent) => {
8
+ for (const node of nodes) {
9
+ byKey.set(node.key, node);
10
+ parentOf.set(node.key, parent);
11
+ const childKeys = (node.children ?? []).map((c) => c.key);
12
+ childrenOf.set(node.key, childKeys);
13
+ if (node.children) visit(node.children, node.key);
14
+ }
15
+ };
16
+ visit(treeData, null);
17
+ return {
18
+ byKey,
19
+ parentOf,
20
+ childrenOf
21
+ };
22
+ }
23
+
24
+ //#endregion
25
+ export { buildTreeIndex };
26
+ //# sourceMappingURL=tree-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-index.js","names":[],"sources":["../../../../src/components/content/Tree/tree-index.ts"],"sourcesContent":["import type { CubeTreeNodeData } from './types';\n\n/**\n * Map of `key -> { node, parentKey, childKeys }` for fast cascading lookups.\n *\n * Built from the public `treeData` rather than from React Stately's\n * collection, because we need the consumer's original (controlled)\n * shape to derive parent/child relationships and to call back with the\n * actual `node` objects.\n *\n * Shared between `Tree.tsx` (for `nodesByKey` / `parentOf`) and\n * `useCheckboxTree` (cascading checked state) so a single tree walk\n * powers all three maps.\n */\nexport interface TreeIndex {\n byKey: Map<string, CubeTreeNodeData>;\n parentOf: Map<string, string | null>;\n childrenOf: Map<string, string[]>;\n}\n\nexport function buildTreeIndex(treeData: CubeTreeNodeData[]): TreeIndex {\n const byKey = new Map<string, CubeTreeNodeData>();\n const parentOf = new Map<string, string | null>();\n const childrenOf = new Map<string, string[]>();\n\n const visit = (nodes: CubeTreeNodeData[], parent: string | null) => {\n for (const node of nodes) {\n byKey.set(node.key, node);\n parentOf.set(node.key, parent);\n const childKeys = (node.children ?? []).map((c) => c.key);\n childrenOf.set(node.key, childKeys);\n if (node.children) {\n visit(node.children, node.key);\n }\n }\n };\n\n visit(treeData, null);\n\n return { byKey, parentOf, childrenOf };\n}\n"],"mappings":";;AAoBA,SAAgB,eAAe,UAAyC;CACtE,MAAM,wBAAQ,IAAI,KAA+B;CACjD,MAAM,2BAAW,IAAI,KAA4B;CACjD,MAAM,6BAAa,IAAI,KAAuB;CAE9C,MAAM,SAAS,OAA2B,WAA0B;AAClE,OAAK,MAAM,QAAQ,OAAO;AACxB,SAAM,IAAI,KAAK,KAAK,KAAK;AACzB,YAAS,IAAI,KAAK,KAAK,OAAO;GAC9B,MAAM,aAAa,KAAK,YAAY,EAAE,EAAE,KAAK,MAAM,EAAE,IAAI;AACzD,cAAW,IAAI,KAAK,KAAK,UAAU;AACnC,OAAI,KAAK,SACP,OAAM,KAAK,UAAU,KAAK,IAAI;;;AAKpC,OAAM,UAAU,KAAK;AAErB,QAAO;EAAE;EAAO;EAAU;EAAY"}
@@ -1,28 +1,8 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { useEvent } from "../../../_internal/hooks/use-event.js";
3
3
  import { useMemo, useState } from "react";
4
4
 
5
5
  //#region src/components/content/Tree/use-checkbox-tree.ts
6
- function buildIndex(treeData) {
7
- const byKey = /* @__PURE__ */ new Map();
8
- const parentOf = /* @__PURE__ */ new Map();
9
- const childrenOf = /* @__PURE__ */ new Map();
10
- const visit = (nodes, parent) => {
11
- for (const node of nodes) {
12
- byKey.set(node.key, node);
13
- parentOf.set(node.key, parent);
14
- const childKeys = (node.children ?? []).map((c) => c.key);
15
- childrenOf.set(node.key, childKeys);
16
- if (node.children) visit(node.children, node.key);
17
- }
18
- };
19
- visit(treeData, null);
20
- return {
21
- byKey,
22
- parentOf,
23
- childrenOf
24
- };
25
- }
26
6
  /**
27
7
  * Returns whether a node should be checkable (i.e. clicking the
28
8
  * checkbox should affect it).
@@ -39,6 +19,46 @@ function isNodeEligible(node) {
39
19
  if (node.isCheckable === false) return false;
40
20
  return true;
41
21
  }
22
+ /**
23
+ * Recursively walk a subtree bottom-up, deriving which nodes are fully
24
+ * checked vs half-checked. Mutates `checked` and `half` in place.
25
+ */
26
+ function deriveCheckedState(node, index, checked, half) {
27
+ const childKeys = index.childrenOf.get(node.key) ?? [];
28
+ if (childKeys.length === 0) {
29
+ const eligible = isNodeEligible(node);
30
+ const isChecked = checked.has(node.key);
31
+ return {
32
+ allChecked: !eligible || isChecked,
33
+ anyChecked: isChecked,
34
+ anyEligible: eligible
35
+ };
36
+ }
37
+ let allChecked = true;
38
+ let anyChecked = false;
39
+ let anyEligible = false;
40
+ for (const childKey of childKeys) {
41
+ const child = index.byKey.get(childKey);
42
+ if (!child) continue;
43
+ const r = deriveCheckedState(child, index, checked, half);
44
+ if (r.anyEligible) anyEligible = true;
45
+ if (!r.allChecked) allChecked = false;
46
+ if (r.anyChecked) anyChecked = true;
47
+ }
48
+ const eligible = isNodeEligible(node);
49
+ if (anyEligible && allChecked) {
50
+ checked.add(node.key);
51
+ half.delete(node.key);
52
+ } else if (anyChecked) {
53
+ checked.delete(node.key);
54
+ half.add(node.key);
55
+ } else checked.delete(node.key);
56
+ return {
57
+ allChecked: !eligible ? allChecked : checked.has(node.key) && allChecked,
58
+ anyChecked: anyChecked || checked.has(node.key),
59
+ anyEligible: anyEligible || eligible
60
+ };
61
+ }
42
62
  function normalizeControlledChecked(controlled) {
43
63
  if (controlled == null) return null;
44
64
  if (Array.isArray(controlled)) return {
@@ -62,8 +82,7 @@ function normalizeControlledChecked(controlled) {
62
82
  * and recomputes ancestors *up* in a single pass.
63
83
  */
64
84
  function useCheckboxTree(opts) {
65
- const { treeData, isCheckable, defaultCheckedKeys, checkedKeys, onCheck } = opts;
66
- const index = useMemo(() => buildIndex(treeData), [treeData]);
85
+ const { treeData, index, isCheckable, defaultCheckedKeys, checkedKeys, onCheck } = opts;
67
86
  const controlled = normalizeControlledChecked(checkedKeys);
68
87
  const isControlled = controlled != null;
69
88
  const wantsObjectShape = checkedKeys != null && !Array.isArray(checkedKeys);
@@ -100,43 +119,7 @@ function useCheckboxTree(opts) {
100
119
  };
101
120
  const checked = new Set(sourceChecked);
102
121
  const half = /* @__PURE__ */ new Set();
103
- const visit = (node) => {
104
- const childKeys = index.childrenOf.get(node.key) ?? [];
105
- if (childKeys.length === 0) {
106
- const eligible = isNodeEligible(node);
107
- const isChecked = checked.has(node.key);
108
- return {
109
- allChecked: !eligible || isChecked,
110
- anyChecked: isChecked,
111
- anyEligible: eligible
112
- };
113
- }
114
- let allChecked = true;
115
- let anyChecked = false;
116
- let anyEligible = false;
117
- for (const childKey of childKeys) {
118
- const child = index.byKey.get(childKey);
119
- if (!child) continue;
120
- const r = visit(child);
121
- if (r.anyEligible) anyEligible = true;
122
- if (!r.allChecked) allChecked = false;
123
- if (r.anyChecked) anyChecked = true;
124
- }
125
- const eligible = isNodeEligible(node);
126
- if (anyEligible && allChecked) {
127
- checked.add(node.key);
128
- half.delete(node.key);
129
- } else if (anyChecked || half.has(node.key)) {
130
- checked.delete(node.key);
131
- half.add(node.key);
132
- } else checked.delete(node.key);
133
- return {
134
- allChecked: !eligible ? allChecked : checked.has(node.key) && allChecked,
135
- anyChecked: anyChecked || checked.has(node.key),
136
- anyEligible: anyEligible || eligible
137
- };
138
- };
139
- for (const root of treeData) visit(root);
122
+ for (const root of treeData) deriveCheckedState(root, index, checked, half);
140
123
  return {
141
124
  checkedSet: checked,
142
125
  halfCheckedSet: half
@@ -199,43 +182,7 @@ function useCheckboxTree(opts) {
199
182
  if (onCheck) {
200
183
  const finalChecked = new Set(next);
201
184
  const finalHalf = /* @__PURE__ */ new Set();
202
- const recompute = (n) => {
203
- const childKeys = index.childrenOf.get(n.key) ?? [];
204
- if (childKeys.length === 0) {
205
- const eligible = isNodeEligible(n);
206
- const isChecked = finalChecked.has(n.key);
207
- return {
208
- allChecked: !eligible || isChecked,
209
- anyChecked: isChecked,
210
- anyEligible: eligible
211
- };
212
- }
213
- let allChecked = true;
214
- let anyChecked = false;
215
- let anyEligible = false;
216
- for (const ck of childKeys) {
217
- const child = index.byKey.get(ck);
218
- if (!child) continue;
219
- const r = recompute(child);
220
- if (r.anyEligible) anyEligible = true;
221
- if (!r.allChecked) allChecked = false;
222
- if (r.anyChecked) anyChecked = true;
223
- }
224
- const eligible = isNodeEligible(n);
225
- if (anyEligible && allChecked) {
226
- finalChecked.add(n.key);
227
- finalHalf.delete(n.key);
228
- } else if (anyChecked) {
229
- finalChecked.delete(n.key);
230
- finalHalf.add(n.key);
231
- } else finalChecked.delete(n.key);
232
- return {
233
- allChecked: !eligible ? allChecked : finalChecked.has(n.key) && allChecked,
234
- anyChecked: anyChecked || finalChecked.has(n.key),
235
- anyEligible: anyEligible || eligible
236
- };
237
- };
238
- for (const root of treeData) recompute(root);
185
+ for (const root of treeData) deriveCheckedState(root, index, finalChecked, finalHalf);
239
186
  const checkedArr = Array.from(finalChecked);
240
187
  const halfArr = Array.from(finalHalf);
241
188
  const info = {
@@ -1 +1 @@
1
- {"version":3,"file":"use-checkbox-tree.js","names":[],"sources":["../../../../src/components/content/Tree/use-checkbox-tree.ts"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useEvent } from '../../../_internal/hooks';\n\nimport type { Key } from '@react-types/shared';\nimport type { CubeTreeNodeData, TreeOnCheckInfo } from './types';\n\nexport interface UseCheckboxTreeOptions {\n treeData: CubeTreeNodeData[];\n isCheckable: boolean;\n defaultCheckedKeys?: string[];\n /** Either an array (AntD's default) or `{ checked, halfChecked }`. */\n checkedKeys?: string[] | { checked: string[]; halfChecked?: string[] };\n onCheck?: (\n checked: Key[] | { checked: Key[]; halfChecked: Key[] },\n info: TreeOnCheckInfo,\n ) => void;\n}\n\nexport interface CheckboxTree {\n /** Set of keys that are fully checked. */\n checkedSet: Set<string>;\n /** Set of keys that are in the indeterminate (half-checked) state. */\n halfCheckedSet: Set<string>;\n /** Toggle a key, propagating to descendants and updating ancestors. */\n toggle: (key: string) => void;\n}\n\n/**\n * Map of `key -> { node, parentKey, childKeys }` for fast cascading lookups.\n *\n * Built from the public `treeData` rather than from React Stately's\n * collection, because we need the consumer's original (controlled)\n * shape to derive parent/child relationships and to call back with the\n * actual `node` objects in `onCheck`'s `info`.\n */\ninterface NodeIndex {\n byKey: Map<string, CubeTreeNodeData>;\n parentOf: Map<string, string | null>;\n childrenOf: Map<string, string[]>;\n}\n\nfunction buildIndex(treeData: CubeTreeNodeData[]): NodeIndex {\n const byKey = new Map<string, CubeTreeNodeData>();\n const parentOf = new Map<string, string | null>();\n const childrenOf = new Map<string, string[]>();\n\n const visit = (nodes: CubeTreeNodeData[], parent: string | null) => {\n for (const node of nodes) {\n byKey.set(node.key, node);\n parentOf.set(node.key, parent);\n const childKeys = (node.children ?? []).map((c) => c.key);\n childrenOf.set(node.key, childKeys);\n if (node.children) {\n visit(node.children, node.key);\n }\n }\n };\n\n visit(treeData, null);\n\n return { byKey, parentOf, childrenOf };\n}\n\n/**\n * Returns whether a node should be checkable (i.e. clicking the\n * checkbox should affect it).\n *\n * Skips:\n * - explicitly disabled nodes (`isDisabled === true`)\n * - explicitly disabled checkboxes (`isCheckboxDisabled === true`)\n * - nodes that opted out via `isCheckable === false`\n */\nfunction isNodeEligible(node: CubeTreeNodeData | undefined): boolean {\n if (!node) return false;\n if (node.isDisabled) return false;\n if (node.isCheckboxDisabled) return false;\n if (node.isCheckable === false) return false;\n return true;\n}\n\nfunction normalizeControlledChecked(\n controlled: UseCheckboxTreeOptions['checkedKeys'],\n): { checked: Set<string>; halfChecked: Set<string> } | null {\n if (controlled == null) return null;\n if (Array.isArray(controlled)) {\n return {\n checked: new Set(controlled),\n halfChecked: new Set(),\n };\n }\n return {\n checked: new Set(controlled.checked ?? []),\n halfChecked: new Set(controlled.halfChecked ?? []),\n };\n}\n\n/**\n * Local hook implementing AntD-style cascading checkbox state.\n *\n * - `checked` and `halfChecked` are always derived together from a single\n * `checked` set (the source of truth) so callers don't need to track\n * indeterminate keys themselves.\n * - When the consumer passes `checkedKeys` as `{ checked, halfChecked }`,\n * we keep the wire shape on the way out — same as AntD.\n * - Toggling a node propagates *down* (skipping ineligible descendants)\n * and recomputes ancestors *up* in a single pass.\n */\nexport function useCheckboxTree(opts: UseCheckboxTreeOptions): CheckboxTree {\n const { treeData, isCheckable, defaultCheckedKeys, checkedKeys, onCheck } =\n opts;\n\n const index = useMemo(() => buildIndex(treeData), [treeData]);\n\n const controlled = normalizeControlledChecked(checkedKeys);\n const isControlled = controlled != null;\n const wantsObjectShape = checkedKeys != null && !Array.isArray(checkedKeys);\n\n const [uncontrolledChecked, setUncontrolledChecked] = useState<Set<string>>(\n () => new Set(defaultCheckedKeys ?? []),\n );\n\n const sourceChecked = isControlled\n ? controlled!.checked\n : uncontrolledChecked;\n\n /**\n * Derive `{ checked, halfChecked }` from the source-of-truth `checked` set\n * by walking the tree bottom-up:\n *\n * - A parent is considered fully checked iff every eligible descendant\n * leaf is checked.\n * - A parent is half-checked iff at least one eligible descendant is\n * checked or half-checked, but not all.\n *\n * Ineligible nodes (disabled / opt-out) are ignored when computing the\n * parent's state — they neither force a parent into the unchecked nor\n * half state.\n */\n const { checkedSet, halfCheckedSet } = useMemo(() => {\n if (!isCheckable) {\n return {\n checkedSet: new Set<string>(),\n halfCheckedSet: new Set<string>(),\n };\n }\n\n /**\n * If the consumer passed the object shape (`{ checked, halfChecked }`),\n * they own the half-checked set and we use it as-is. With the array\n * shape we still need to derive `halfChecked` ourselves — the consumer\n * only provides `checked`, so parents should still light up\n * indeterminate when only some descendants are checked.\n */\n if (isControlled && wantsObjectShape) {\n return {\n checkedSet: new Set(sourceChecked),\n halfCheckedSet: new Set(controlled!.halfChecked),\n };\n }\n\n const checked = new Set(sourceChecked);\n const half = new Set<string>();\n\n const visit = (\n node: CubeTreeNodeData,\n ): { allChecked: boolean; anyChecked: boolean; anyEligible: boolean } => {\n const childKeys = index.childrenOf.get(node.key) ?? [];\n\n if (childKeys.length === 0) {\n const eligible = isNodeEligible(node);\n const isChecked = checked.has(node.key);\n return {\n allChecked: !eligible || isChecked,\n anyChecked: isChecked,\n anyEligible: eligible,\n };\n }\n\n let allChecked = true;\n let anyChecked = false;\n let anyEligible = false;\n\n for (const childKey of childKeys) {\n const child = index.byKey.get(childKey);\n if (!child) continue;\n const r = visit(child);\n if (r.anyEligible) anyEligible = true;\n if (!r.allChecked) allChecked = false;\n if (r.anyChecked) anyChecked = true;\n }\n\n const eligible = isNodeEligible(node);\n\n if (anyEligible && allChecked) {\n checked.add(node.key);\n half.delete(node.key);\n } else if (anyChecked || half.has(node.key)) {\n checked.delete(node.key);\n half.add(node.key);\n } else {\n checked.delete(node.key);\n }\n\n return {\n allChecked: !eligible\n ? allChecked\n : checked.has(node.key) && allChecked,\n anyChecked: anyChecked || checked.has(node.key),\n anyEligible: anyEligible || eligible,\n };\n };\n\n for (const root of treeData) {\n visit(root);\n }\n\n return { checkedSet: checked, halfCheckedSet: half };\n }, [\n isCheckable,\n isControlled,\n wantsObjectShape,\n sourceChecked,\n controlled,\n treeData,\n index,\n ]);\n\n const toggle = useEvent((key: string) => {\n const node = index.byKey.get(key);\n if (!node || !isNodeEligible(node)) return;\n\n const isCurrentlyChecked = checkedSet.has(key);\n const willCheck = !isCurrentlyChecked;\n\n const next = new Set(sourceChecked);\n\n const apply = (n: CubeTreeNodeData, value: boolean) => {\n if (!isNodeEligible(n)) return;\n if (value) next.add(n.key);\n else next.delete(n.key);\n const childKeys = index.childrenOf.get(n.key) ?? [];\n for (const ck of childKeys) {\n const child = index.byKey.get(ck);\n if (child) apply(child, value);\n }\n };\n\n apply(node, willCheck);\n\n /**\n * After the cascade, recompute ancestors so the public `checked` set\n * doesn't carry parent keys that should be half-checked instead.\n * Ancestors of `key` get visited bottom-up here.\n */\n let parentKey = index.parentOf.get(key);\n while (parentKey) {\n const parent = index.byKey.get(parentKey);\n if (!parent) break;\n const childKeys = index.childrenOf.get(parentKey) ?? [];\n let allEligibleChecked = true;\n let anyEligible = false;\n for (const ck of childKeys) {\n const child = index.byKey.get(ck);\n if (!child) continue;\n if (!isNodeEligible(child)) continue;\n anyEligible = true;\n if (!next.has(ck)) {\n allEligibleChecked = false;\n break;\n }\n }\n if (anyEligible && allEligibleChecked && isNodeEligible(parent)) {\n next.add(parentKey);\n } else {\n next.delete(parentKey);\n }\n parentKey = index.parentOf.get(parentKey);\n }\n\n if (!isControlled) {\n setUncontrolledChecked(next);\n }\n\n if (onCheck) {\n const finalChecked = new Set(next);\n const finalHalf = new Set<string>();\n\n const recompute = (\n n: CubeTreeNodeData,\n ): {\n allChecked: boolean;\n anyChecked: boolean;\n anyEligible: boolean;\n } => {\n const childKeys = index.childrenOf.get(n.key) ?? [];\n if (childKeys.length === 0) {\n const eligible = isNodeEligible(n);\n const isChecked = finalChecked.has(n.key);\n return {\n allChecked: !eligible || isChecked,\n anyChecked: isChecked,\n anyEligible: eligible,\n };\n }\n let allChecked = true;\n let anyChecked = false;\n let anyEligible = false;\n for (const ck of childKeys) {\n const child = index.byKey.get(ck);\n if (!child) continue;\n const r = recompute(child);\n if (r.anyEligible) anyEligible = true;\n if (!r.allChecked) allChecked = false;\n if (r.anyChecked) anyChecked = true;\n }\n const eligible = isNodeEligible(n);\n if (anyEligible && allChecked) {\n finalChecked.add(n.key);\n finalHalf.delete(n.key);\n } else if (anyChecked) {\n finalChecked.delete(n.key);\n finalHalf.add(n.key);\n } else {\n finalChecked.delete(n.key);\n }\n return {\n allChecked: !eligible\n ? allChecked\n : finalChecked.has(n.key) && allChecked,\n anyChecked: anyChecked || finalChecked.has(n.key),\n anyEligible: anyEligible || eligible,\n };\n };\n\n for (const root of treeData) recompute(root);\n\n const checkedArr = Array.from(finalChecked);\n const halfArr = Array.from(finalHalf);\n const checkedNodes: CubeTreeNodeData[] = checkedArr\n .map((k) => index.byKey.get(k))\n .filter((n): n is CubeTreeNodeData => !!n);\n\n const info: TreeOnCheckInfo = {\n checked: willCheck,\n node,\n checkedNodes,\n halfCheckedKeys: halfArr,\n };\n\n if (wantsObjectShape) {\n onCheck({ checked: checkedArr, halfChecked: halfArr }, info);\n } else {\n onCheck(checkedArr, info);\n }\n }\n });\n\n return { checkedSet, halfCheckedSet, toggle };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-checkbox-tree.js","names":[],"sources":["../../../../src/components/content/Tree/use-checkbox-tree.ts"],"sourcesContent":["import { useMemo, useState } from 'react';\n\nimport { useEvent } from '../../../_internal/hooks';\n\nimport type { Key } from '@react-types/shared';\nimport type { TreeIndex } from './tree-index';\nimport type { CubeTreeNodeData, TreeOnCheckInfo } from './types';\n\nexport interface UseCheckboxTreeOptions {\n treeData: CubeTreeNodeData[];\n /**\n * Pre-built tree index, shared with `Tree.tsx` so that `treeData`\n * is walked exactly once per change rather than once per consumer.\n */\n index: TreeIndex;\n isCheckable: boolean;\n defaultCheckedKeys?: string[];\n /** Either an array (AntD's default) or `{ checked, halfChecked }`. */\n checkedKeys?: string[] | { checked: string[]; halfChecked?: string[] };\n onCheck?: (\n checked: Key[] | { checked: Key[]; halfChecked: Key[] },\n info: TreeOnCheckInfo,\n ) => void;\n}\n\nexport interface CheckboxTree {\n /** Set of keys that are fully checked. */\n checkedSet: Set<string>;\n /** Set of keys that are in the indeterminate (half-checked) state. */\n halfCheckedSet: Set<string>;\n /** Toggle a key, propagating to descendants and updating ancestors. */\n toggle: (key: string) => void;\n}\n\n/**\n * Returns whether a node should be checkable (i.e. clicking the\n * checkbox should affect it).\n *\n * Skips:\n * - explicitly disabled nodes (`isDisabled === true`)\n * - explicitly disabled checkboxes (`isCheckboxDisabled === true`)\n * - nodes that opted out via `isCheckable === false`\n */\nfunction isNodeEligible(node: CubeTreeNodeData | undefined): boolean {\n if (!node) return false;\n if (node.isDisabled) return false;\n if (node.isCheckboxDisabled) return false;\n if (node.isCheckable === false) return false;\n return true;\n}\n\n/**\n * Recursively walk a subtree bottom-up, deriving which nodes are fully\n * checked vs half-checked. Mutates `checked` and `half` in place.\n */\nfunction deriveCheckedState(\n node: CubeTreeNodeData,\n index: TreeIndex,\n checked: Set<string>,\n half: Set<string>,\n): { allChecked: boolean; anyChecked: boolean; anyEligible: boolean } {\n const childKeys = index.childrenOf.get(node.key) ?? [];\n\n if (childKeys.length === 0) {\n const eligible = isNodeEligible(node);\n const isChecked = checked.has(node.key);\n return {\n allChecked: !eligible || isChecked,\n anyChecked: isChecked,\n anyEligible: eligible,\n };\n }\n\n let allChecked = true;\n let anyChecked = false;\n let anyEligible = false;\n\n for (const childKey of childKeys) {\n const child = index.byKey.get(childKey);\n if (!child) continue;\n const r = deriveCheckedState(child, index, checked, half);\n if (r.anyEligible) anyEligible = true;\n if (!r.allChecked) allChecked = false;\n if (r.anyChecked) anyChecked = true;\n }\n\n const eligible = isNodeEligible(node);\n\n if (anyEligible && allChecked) {\n checked.add(node.key);\n half.delete(node.key);\n } else if (anyChecked) {\n checked.delete(node.key);\n half.add(node.key);\n } else {\n checked.delete(node.key);\n }\n\n return {\n allChecked: !eligible ? allChecked : checked.has(node.key) && allChecked,\n anyChecked: anyChecked || checked.has(node.key),\n anyEligible: anyEligible || eligible,\n };\n}\n\nfunction normalizeControlledChecked(\n controlled: UseCheckboxTreeOptions['checkedKeys'],\n): { checked: Set<string>; halfChecked: Set<string> } | null {\n if (controlled == null) return null;\n if (Array.isArray(controlled)) {\n return {\n checked: new Set(controlled),\n halfChecked: new Set(),\n };\n }\n return {\n checked: new Set(controlled.checked ?? []),\n halfChecked: new Set(controlled.halfChecked ?? []),\n };\n}\n\n/**\n * Local hook implementing AntD-style cascading checkbox state.\n *\n * - `checked` and `halfChecked` are always derived together from a single\n * `checked` set (the source of truth) so callers don't need to track\n * indeterminate keys themselves.\n * - When the consumer passes `checkedKeys` as `{ checked, halfChecked }`,\n * we keep the wire shape on the way out — same as AntD.\n * - Toggling a node propagates *down* (skipping ineligible descendants)\n * and recomputes ancestors *up* in a single pass.\n */\nexport function useCheckboxTree(opts: UseCheckboxTreeOptions): CheckboxTree {\n const {\n treeData,\n index,\n isCheckable,\n defaultCheckedKeys,\n checkedKeys,\n onCheck,\n } = opts;\n\n const controlled = normalizeControlledChecked(checkedKeys);\n const isControlled = controlled != null;\n const wantsObjectShape = checkedKeys != null && !Array.isArray(checkedKeys);\n\n const [uncontrolledChecked, setUncontrolledChecked] = useState<Set<string>>(\n () => new Set(defaultCheckedKeys ?? []),\n );\n\n const sourceChecked = isControlled\n ? controlled!.checked\n : uncontrolledChecked;\n\n /**\n * Derive `{ checked, halfChecked }` from the source-of-truth `checked` set\n * by walking the tree bottom-up:\n *\n * - A parent is considered fully checked iff every eligible descendant\n * leaf is checked.\n * - A parent is half-checked iff at least one eligible descendant is\n * checked or half-checked, but not all.\n *\n * Ineligible nodes (disabled / opt-out) are ignored when computing the\n * parent's state — they neither force a parent into the unchecked nor\n * half state.\n */\n const { checkedSet, halfCheckedSet } = useMemo(() => {\n if (!isCheckable) {\n return {\n checkedSet: new Set<string>(),\n halfCheckedSet: new Set<string>(),\n };\n }\n\n /**\n * If the consumer passed the object shape (`{ checked, halfChecked }`),\n * they own the half-checked set and we use it as-is. With the array\n * shape we still need to derive `halfChecked` ourselves — the consumer\n * only provides `checked`, so parents should still light up\n * indeterminate when only some descendants are checked.\n */\n if (isControlled && wantsObjectShape) {\n return {\n checkedSet: new Set(sourceChecked),\n halfCheckedSet: new Set(controlled!.halfChecked),\n };\n }\n\n const checked = new Set(sourceChecked);\n const half = new Set<string>();\n\n for (const root of treeData) {\n deriveCheckedState(root, index, checked, half);\n }\n\n return { checkedSet: checked, halfCheckedSet: half };\n }, [\n isCheckable,\n isControlled,\n wantsObjectShape,\n sourceChecked,\n controlled,\n treeData,\n index,\n ]);\n\n const toggle = useEvent((key: string) => {\n const node = index.byKey.get(key);\n if (!node || !isNodeEligible(node)) return;\n\n const isCurrentlyChecked = checkedSet.has(key);\n const willCheck = !isCurrentlyChecked;\n\n const next = new Set(sourceChecked);\n\n const apply = (n: CubeTreeNodeData, value: boolean) => {\n if (!isNodeEligible(n)) return;\n if (value) next.add(n.key);\n else next.delete(n.key);\n const childKeys = index.childrenOf.get(n.key) ?? [];\n for (const ck of childKeys) {\n const child = index.byKey.get(ck);\n if (child) apply(child, value);\n }\n };\n\n apply(node, willCheck);\n\n /**\n * After the cascade, recompute ancestors so the public `checked` set\n * doesn't carry parent keys that should be half-checked instead.\n * Ancestors of `key` get visited bottom-up here.\n */\n let parentKey = index.parentOf.get(key);\n while (parentKey) {\n const parent = index.byKey.get(parentKey);\n if (!parent) break;\n const childKeys = index.childrenOf.get(parentKey) ?? [];\n let allEligibleChecked = true;\n let anyEligible = false;\n for (const ck of childKeys) {\n const child = index.byKey.get(ck);\n if (!child) continue;\n if (!isNodeEligible(child)) continue;\n anyEligible = true;\n if (!next.has(ck)) {\n allEligibleChecked = false;\n break;\n }\n }\n if (anyEligible && allEligibleChecked && isNodeEligible(parent)) {\n next.add(parentKey);\n } else {\n next.delete(parentKey);\n }\n parentKey = index.parentOf.get(parentKey);\n }\n\n if (!isControlled) {\n setUncontrolledChecked(next);\n }\n\n if (onCheck) {\n const finalChecked = new Set(next);\n const finalHalf = new Set<string>();\n\n for (const root of treeData) {\n deriveCheckedState(root, index, finalChecked, finalHalf);\n }\n\n const checkedArr = Array.from(finalChecked);\n const halfArr = Array.from(finalHalf);\n const checkedNodes: CubeTreeNodeData[] = checkedArr\n .map((k) => index.byKey.get(k))\n .filter((n): n is CubeTreeNodeData => !!n);\n\n const info: TreeOnCheckInfo = {\n checked: willCheck,\n node,\n checkedNodes,\n halfCheckedKeys: halfArr,\n };\n\n if (wantsObjectShape) {\n onCheck({ checked: checkedArr, halfChecked: halfArr }, info);\n } else {\n onCheck(checkedArr, info);\n }\n }\n });\n\n return { checkedSet, halfCheckedSet, toggle };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { useCallback, useRef, useState } from "react";
3
3
 
4
4
  //#region src/components/content/Tree/use-load-data.ts
@@ -18,9 +18,9 @@ import { useCallback, useRef, useState } from "react";
18
18
  * `treeData` themselves (matching AntD's pattern).
19
19
  */
20
20
  function useLoadData(opts) {
21
- const { nodesByKey, loadData } = opts;
21
+ const { nodesByKey, loadData, initialExpandedKeys } = opts;
22
22
  const [loadingKeys, setLoadingKeys] = useState(() => /* @__PURE__ */ new Set());
23
- const previousExpandedRef = useRef(/* @__PURE__ */ new Set());
23
+ const previousExpandedRef = useRef(new Set(initialExpandedKeys));
24
24
  const inFlightRef = useRef(/* @__PURE__ */ new Set());
25
25
  return {
26
26
  loadingKeys,
@@ -1 +1 @@
1
- {"version":3,"file":"use-load-data.js","names":[],"sources":["../../../../src/components/content/Tree/use-load-data.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\n\nimport type { Key } from '@react-types/shared';\nimport type { CubeTreeNodeData, TreeLoadDataNode } from './types';\n\nexport interface UseLoadDataOptions {\n /**\n * Map of `key -> node` built from the consumer's `treeData`. Used to\n * find the node being expanded when `loadData` fires.\n */\n nodesByKey: Map<string, CubeTreeNodeData>;\n loadData?: (node: TreeLoadDataNode) => Promise<void>;\n}\n\nexport interface LoadDataController {\n /** Set of keys that are currently waiting on `loadData`. */\n loadingKeys: Set<string>;\n /**\n * Called by `Tree.tsx` whenever the underlying React Stately state's\n * `expandedKeys` change. We diff against the previous set, and for\n * each newly-expanded key we trigger `loadData` if appropriate.\n */\n onExpandedChanged: (expandedKeys: Iterable<Key>) => void;\n}\n\n/**\n * Tracks which rows are currently fetching their children via `loadData`\n * and exposes a setter for the Tree to call after every expand change.\n *\n * `loadData` is fired exactly once per key per \"first expand\" event:\n *\n * - Skipped if there is no `loadData` callback.\n * - Skipped for leaf nodes (`isLeaf === true`).\n * - Skipped if the node already has `children` (already loaded).\n * - Skipped if a previous fetch for the same key is still in flight.\n *\n * The promise's resolution is awaited only to clear the `loading` mod;\n * the consumer is expected to commit the new children to the controlled\n * `treeData` themselves (matching AntD's pattern).\n */\nexport function useLoadData(opts: UseLoadDataOptions): LoadDataController {\n const { nodesByKey, loadData } = opts;\n const [loadingKeys, setLoadingKeys] = useState<Set<string>>(() => new Set());\n const previousExpandedRef = useRef<Set<string>>(new Set());\n const inFlightRef = useRef<Set<string>>(new Set());\n\n const onExpandedChanged = useCallback(\n (expandedKeys: Iterable<Key>) => {\n const next = new Set<string>();\n for (const k of expandedKeys) next.add(String(k));\n\n const prev = previousExpandedRef.current;\n const newlyExpanded: string[] = [];\n for (const k of next) {\n if (!prev.has(k)) newlyExpanded.push(k);\n }\n previousExpandedRef.current = next;\n\n if (!loadData || newlyExpanded.length === 0) return;\n\n let added = false;\n const toLoad: string[] = [];\n for (const key of newlyExpanded) {\n const node = nodesByKey.get(key);\n if (!node) continue;\n if (node.isLeaf) continue;\n if (node.children && node.children.length > 0) continue;\n if (inFlightRef.current.has(key)) continue;\n inFlightRef.current.add(key);\n toLoad.push(key);\n added = true;\n }\n\n if (!added) return;\n\n setLoadingKeys((current) => {\n const updated = new Set(current);\n for (const k of toLoad) updated.add(k);\n return updated;\n });\n\n for (const key of toLoad) {\n Promise.resolve(loadData({ key }))\n .catch(() => {\n // Allow consumers to re-trigger after a rejected load by\n // letting the next expand event re-enter this branch.\n })\n .finally(() => {\n inFlightRef.current.delete(key);\n setLoadingKeys((current) => {\n if (!current.has(key)) return current;\n const updated = new Set(current);\n updated.delete(key);\n return updated;\n });\n });\n }\n },\n [loadData, nodesByKey],\n );\n\n return { loadingKeys, onExpandedChanged };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,YAAY,MAA8C;CACxE,MAAM,EAAE,YAAY,aAAa;CACjC,MAAM,CAAC,aAAa,kBAAkB,+BAA4B,IAAI,KAAK,CAAC;CAC5E,MAAM,sBAAsB,uBAAoB,IAAI,KAAK,CAAC;CAC1D,MAAM,cAAc,uBAAoB,IAAI,KAAK,CAAC;AAyDlD,QAAO;EAAE;EAAa,mBAvDI,aACvB,iBAAgC;GAC/B,MAAM,uBAAO,IAAI,KAAa;AAC9B,QAAK,MAAM,KAAK,aAAc,MAAK,IAAI,OAAO,EAAE,CAAC;GAEjD,MAAM,OAAO,oBAAoB;GACjC,MAAM,gBAA0B,EAAE;AAClC,QAAK,MAAM,KAAK,KACd,KAAI,CAAC,KAAK,IAAI,EAAE,CAAE,eAAc,KAAK,EAAE;AAEzC,uBAAoB,UAAU;AAE9B,OAAI,CAAC,YAAY,cAAc,WAAW,EAAG;GAE7C,IAAI,QAAQ;GACZ,MAAM,SAAmB,EAAE;AAC3B,QAAK,MAAM,OAAO,eAAe;IAC/B,MAAM,OAAO,WAAW,IAAI,IAAI;AAChC,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,OAAQ;AACjB,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,EAAG;AAC/C,QAAI,YAAY,QAAQ,IAAI,IAAI,CAAE;AAClC,gBAAY,QAAQ,IAAI,IAAI;AAC5B,WAAO,KAAK,IAAI;AAChB,YAAQ;;AAGV,OAAI,CAAC,MAAO;AAEZ,mBAAgB,YAAY;IAC1B,MAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,SAAK,MAAM,KAAK,OAAQ,SAAQ,IAAI,EAAE;AACtC,WAAO;KACP;AAEF,QAAK,MAAM,OAAO,OAChB,SAAQ,QAAQ,SAAS,EAAE,KAAK,CAAC,CAAC,CAC/B,YAAY,GAGX,CACD,cAAc;AACb,gBAAY,QAAQ,OAAO,IAAI;AAC/B,oBAAgB,YAAY;AAC1B,SAAI,CAAC,QAAQ,IAAI,IAAI,CAAE,QAAO;KAC9B,MAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,aAAQ,OAAO,IAAI;AACnB,YAAO;MACP;KACF;KAGR,CAAC,UAAU,WAAW,CACvB;EAEwC"}
1
+ {"version":3,"file":"use-load-data.js","names":[],"sources":["../../../../src/components/content/Tree/use-load-data.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\n\nimport type { Key } from '@react-types/shared';\nimport type { CubeTreeNodeData, TreeLoadDataNode } from './types';\n\nexport interface UseLoadDataOptions {\n /**\n * Map of `key -> node` built from the consumer's `treeData`. Used to\n * find the node being expanded when `loadData` fires.\n */\n nodesByKey: Map<string, CubeTreeNodeData>;\n loadData?: (node: TreeLoadDataNode) => Promise<void>;\n /**\n * Keys that are expanded at mount time (controlled or default).\n * Seeds `previousExpandedRef` so the first `onExpandedChanged` call\n * doesn't misidentify them as user-triggered expansions.\n */\n initialExpandedKeys?: Iterable<string>;\n}\n\nexport interface LoadDataController {\n /** Set of keys that are currently waiting on `loadData`. */\n loadingKeys: Set<string>;\n /**\n * Called by `Tree.tsx` whenever the underlying React Stately state's\n * `expandedKeys` change. We diff against the previous set, and for\n * each newly-expanded key we trigger `loadData` if appropriate.\n */\n onExpandedChanged: (expandedKeys: Iterable<Key>) => void;\n}\n\n/**\n * Tracks which rows are currently fetching their children via `loadData`\n * and exposes a setter for the Tree to call after every expand change.\n *\n * `loadData` is fired exactly once per key per \"first expand\" event:\n *\n * - Skipped if there is no `loadData` callback.\n * - Skipped for leaf nodes (`isLeaf === true`).\n * - Skipped if the node already has `children` (already loaded).\n * - Skipped if a previous fetch for the same key is still in flight.\n *\n * The promise's resolution is awaited only to clear the `loading` mod;\n * the consumer is expected to commit the new children to the controlled\n * `treeData` themselves (matching AntD's pattern).\n */\nexport function useLoadData(opts: UseLoadDataOptions): LoadDataController {\n const { nodesByKey, loadData, initialExpandedKeys } = opts;\n const [loadingKeys, setLoadingKeys] = useState<Set<string>>(() => new Set());\n const previousExpandedRef = useRef<Set<string>>(new Set(initialExpandedKeys));\n const inFlightRef = useRef<Set<string>>(new Set());\n\n const onExpandedChanged = useCallback(\n (expandedKeys: Iterable<Key>) => {\n const next = new Set<string>();\n for (const k of expandedKeys) next.add(String(k));\n\n const prev = previousExpandedRef.current;\n const newlyExpanded: string[] = [];\n for (const k of next) {\n if (!prev.has(k)) newlyExpanded.push(k);\n }\n previousExpandedRef.current = next;\n\n if (!loadData || newlyExpanded.length === 0) return;\n\n let added = false;\n const toLoad: string[] = [];\n for (const key of newlyExpanded) {\n const node = nodesByKey.get(key);\n if (!node) continue;\n if (node.isLeaf) continue;\n if (node.children && node.children.length > 0) continue;\n if (inFlightRef.current.has(key)) continue;\n inFlightRef.current.add(key);\n toLoad.push(key);\n added = true;\n }\n\n if (!added) return;\n\n setLoadingKeys((current) => {\n const updated = new Set(current);\n for (const k of toLoad) updated.add(k);\n return updated;\n });\n\n for (const key of toLoad) {\n Promise.resolve(loadData({ key }))\n .catch(() => {\n // Allow consumers to re-trigger after a rejected load by\n // letting the next expand event re-enter this branch.\n })\n .finally(() => {\n inFlightRef.current.delete(key);\n setLoadingKeys((current) => {\n if (!current.has(key)) return current;\n const updated = new Set(current);\n updated.delete(key);\n return updated;\n });\n });\n }\n },\n [loadData, nodesByKey],\n );\n\n return { loadingKeys, onExpandedChanged };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,YAAY,MAA8C;CACxE,MAAM,EAAE,YAAY,UAAU,wBAAwB;CACtD,MAAM,CAAC,aAAa,kBAAkB,+BAA4B,IAAI,KAAK,CAAC;CAC5E,MAAM,sBAAsB,OAAoB,IAAI,IAAI,oBAAoB,CAAC;CAC7E,MAAM,cAAc,uBAAoB,IAAI,KAAK,CAAC;AAyDlD,QAAO;EAAE;EAAa,mBAvDI,aACvB,iBAAgC;GAC/B,MAAM,uBAAO,IAAI,KAAa;AAC9B,QAAK,MAAM,KAAK,aAAc,MAAK,IAAI,OAAO,EAAE,CAAC;GAEjD,MAAM,OAAO,oBAAoB;GACjC,MAAM,gBAA0B,EAAE;AAClC,QAAK,MAAM,KAAK,KACd,KAAI,CAAC,KAAK,IAAI,EAAE,CAAE,eAAc,KAAK,EAAE;AAEzC,uBAAoB,UAAU;AAE9B,OAAI,CAAC,YAAY,cAAc,WAAW,EAAG;GAE7C,IAAI,QAAQ;GACZ,MAAM,SAAmB,EAAE;AAC3B,QAAK,MAAM,OAAO,eAAe;IAC/B,MAAM,OAAO,WAAW,IAAI,IAAI;AAChC,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,OAAQ;AACjB,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,EAAG;AAC/C,QAAI,YAAY,QAAQ,IAAI,IAAI,CAAE;AAClC,gBAAY,QAAQ,IAAI,IAAI;AAC5B,WAAO,KAAK,IAAI;AAChB,YAAQ;;AAGV,OAAI,CAAC,MAAO;AAEZ,mBAAgB,YAAY;IAC1B,MAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,SAAK,MAAM,KAAK,OAAQ,SAAQ,IAAI,EAAE;AACtC,WAAO;KACP;AAEF,QAAK,MAAM,OAAO,OAChB,SAAQ,QAAQ,SAAS,EAAE,KAAK,CAAC,CAAC,CAC/B,YAAY,GAGX,CACD,cAAc;AACb,gBAAY,QAAQ,OAAO,IAAI;AAC/B,oBAAgB,YAAY;AAC1B,SAAI,CAAC,QAAQ,IAAI,IAAI,CAAE,QAAO;KAC9B,MAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,aAAQ,OAAO,IAAI;AACnB,YAAO;MACP;KACF;KAGR,CAAC,UAAU,WAAW,CACvB;EAEwC"}
@@ -1,4 +1,4 @@
1
- /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ad23b00 | Cube Dev Team */
1
+ /** @license MIT | @cube-dev/ui-kit v0.0.0-canary-c76c00e | Cube Dev Team */
2
2
  import { _Text } from "./Text.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4