@accelint/design-toolkit 9.9.2 → 9.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (436) hide show
  1. package/catalog-info.yaml +2 -2
  2. package/dist/components/accordion/group.d.ts +2 -2
  3. package/dist/components/accordion/header.d.ts +2 -2
  4. package/dist/components/accordion/index.d.ts +2 -2
  5. package/dist/components/accordion/styles.module.css +19 -3
  6. package/dist/components/accordion/trigger.d.ts +2 -2
  7. package/dist/components/action-bar/index.d.ts +2 -2
  8. package/dist/components/audio/index.d.ts +2 -2
  9. package/dist/components/avatar/context.d.ts +4 -4
  10. package/dist/components/avatar/index.d.ts +2 -2
  11. package/dist/components/badge/context.d.ts +4 -4
  12. package/dist/components/badge/index.d.ts +2 -2
  13. package/dist/components/breadcrumbs/index.d.ts +2 -2
  14. package/dist/components/breadcrumbs/item.d.ts +2 -2
  15. package/dist/components/button/context.d.ts +8 -8
  16. package/dist/components/button/index.d.ts +2 -2
  17. package/dist/components/button/link.d.ts +2 -2
  18. package/dist/components/button/styles.module.css +16 -0
  19. package/dist/components/button/toggle.d.ts +2 -2
  20. package/dist/components/carousel/context.d.ts +40 -0
  21. package/dist/components/carousel/context.js +55 -0
  22. package/dist/components/carousel/context.js.map +1 -0
  23. package/dist/components/carousel/gallery.d.ts +38 -0
  24. package/dist/components/carousel/gallery.js +84 -0
  25. package/dist/components/carousel/gallery.js.map +1 -0
  26. package/dist/components/carousel/index.d.ts +56 -0
  27. package/dist/components/carousel/index.js +66 -0
  28. package/dist/components/carousel/index.js.map +1 -0
  29. package/dist/components/carousel/navigation.d.ts +51 -0
  30. package/dist/components/carousel/navigation.js +82 -0
  31. package/dist/components/carousel/navigation.js.map +1 -0
  32. package/dist/components/carousel/position.d.ts +33 -0
  33. package/dist/components/carousel/position.js +48 -0
  34. package/dist/components/carousel/position.js.map +1 -0
  35. package/dist/components/carousel/select.d.ts +38 -0
  36. package/dist/components/carousel/select.js +69 -0
  37. package/dist/components/carousel/select.js.map +1 -0
  38. package/dist/components/carousel/style.module.css +62 -0
  39. package/dist/components/carousel/types.d.ts +87 -0
  40. package/dist/components/carousel/types.js +12 -0
  41. package/dist/components/carousel/viewer.d.ts +40 -0
  42. package/dist/components/carousel/viewer.js +75 -0
  43. package/dist/components/carousel/viewer.js.map +1 -0
  44. package/dist/components/checkbox/context.d.ts +3 -3
  45. package/dist/components/checkbox/group.d.ts +2 -2
  46. package/dist/components/checkbox/group.js +1 -1
  47. package/dist/components/checkbox/index.d.ts +2 -2
  48. package/dist/components/chip/context.d.ts +4 -4
  49. package/dist/components/chip/deletable.d.ts +2 -2
  50. package/dist/components/chip/index.d.ts +2 -2
  51. package/dist/components/chip/list.d.ts +4 -4
  52. package/dist/components/chip/selectable.d.ts +2 -2
  53. package/dist/components/classification-badge/context.d.ts +4 -4
  54. package/dist/components/classification-badge/index.d.ts +2 -2
  55. package/dist/components/classification-banner/context.d.ts +4 -4
  56. package/dist/components/classification-banner/index.d.ts +2 -2
  57. package/dist/components/clock/index.d.ts +2 -2
  58. package/dist/components/color-picker/index.d.ts +2 -2
  59. package/dist/components/combobox-field/context.d.ts +4 -4
  60. package/dist/components/combobox-field/index.d.ts +2 -2
  61. package/dist/components/combobox-field/index.js +1 -1
  62. package/dist/components/combobox-field/styles.module.css +12 -0
  63. package/dist/components/coordinate-field/context.d.ts +6 -6
  64. package/dist/components/coordinate-field/index.d.ts +2 -2
  65. package/dist/components/coordinate-field/segment.d.ts +2 -2
  66. package/dist/components/date-field/index.d.ts +2 -2
  67. package/dist/components/deferred-collection/index.d.ts +2 -2
  68. package/dist/components/details-list/context.d.ts +4 -4
  69. package/dist/components/details-list/index.d.ts +2 -2
  70. package/dist/components/details-list/label.d.ts +2 -2
  71. package/dist/components/details-list/value.d.ts +2 -2
  72. package/dist/components/dialog/content.d.ts +2 -2
  73. package/dist/components/dialog/context.d.ts +2 -2
  74. package/dist/components/dialog/footer.d.ts +2 -2
  75. package/dist/components/dialog/index.d.ts +2 -2
  76. package/dist/components/dialog/styles.module.css +23 -0
  77. package/dist/components/dialog/title.d.ts +2 -2
  78. package/dist/components/divider/context.d.ts +4 -4
  79. package/dist/components/divider/index.d.ts +2 -2
  80. package/dist/components/drawer/back.d.ts +2 -2
  81. package/dist/components/drawer/close.d.ts +2 -2
  82. package/dist/components/drawer/content.d.ts +2 -2
  83. package/dist/components/drawer/context.d.ts +2 -2
  84. package/dist/components/drawer/footer.d.ts +2 -2
  85. package/dist/components/drawer/header-title.d.ts +2 -2
  86. package/dist/components/drawer/header.d.ts +2 -2
  87. package/dist/components/drawer/index.d.ts +2 -2
  88. package/dist/components/drawer/layout-main.d.ts +2 -2
  89. package/dist/components/drawer/layout.d.ts +2 -2
  90. package/dist/components/drawer/menu-item.d.ts +2 -2
  91. package/dist/components/drawer/menu.d.ts +2 -2
  92. package/dist/components/drawer/panel.d.ts +2 -2
  93. package/dist/components/drawer/styles.module.css +54 -2
  94. package/dist/components/drawer/trigger.d.ts +2 -2
  95. package/dist/components/drawer/view.d.ts +2 -2
  96. package/dist/components/flashcard/index.d.ts +9 -9
  97. package/dist/components/floating-card/context.d.ts +37 -5
  98. package/dist/components/floating-card/context.js +18 -3
  99. package/dist/components/floating-card/context.js.map +1 -1
  100. package/dist/components/floating-card/index.d.ts +51 -1
  101. package/dist/components/floating-card/index.js +41 -11
  102. package/dist/components/floating-card/index.js.map +1 -1
  103. package/dist/components/floating-card/provider.d.ts +94 -17
  104. package/dist/components/floating-card/provider.js +116 -20
  105. package/dist/components/floating-card/provider.js.map +1 -1
  106. package/dist/components/floating-card/styles.module.css +5 -0
  107. package/dist/components/gantt/components/base-elements/point.d.ts +28 -0
  108. package/dist/components/gantt/components/base-elements/point.js +44 -0
  109. package/dist/components/gantt/components/base-elements/point.js.map +1 -0
  110. package/dist/components/gantt/components/base-elements/range.d.ts +30 -0
  111. package/dist/components/gantt/components/base-elements/range.js +51 -0
  112. package/dist/components/gantt/components/base-elements/range.js.map +1 -0
  113. package/dist/components/gantt/components/base-elements/use-point-element-layout/index.d.ts +12 -0
  114. package/dist/components/gantt/components/base-elements/use-point-element-layout/index.js +42 -0
  115. package/dist/components/gantt/components/base-elements/use-point-element-layout/index.js.map +1 -0
  116. package/dist/components/gantt/components/base-elements/use-range-element-layout/index.d.ts +23 -0
  117. package/dist/components/gantt/components/base-elements/use-range-element-layout/index.js +50 -0
  118. package/dist/components/gantt/components/base-elements/use-range-element-layout/index.js.map +1 -0
  119. package/dist/components/gantt/components/containers/external/gantt-content-container/index.d.ts +23 -0
  120. package/dist/components/gantt/components/containers/external/gantt-content-container/index.js +40 -0
  121. package/dist/components/gantt/components/containers/external/gantt-content-container/index.js.map +1 -0
  122. package/dist/components/gantt/components/containers/external/gantt-panel-container/index.d.ts +23 -0
  123. package/dist/components/gantt/components/containers/external/gantt-panel-container/index.js +33 -0
  124. package/dist/components/gantt/components/containers/external/gantt-panel-container/index.js.map +1 -0
  125. package/dist/components/gantt/components/containers/external/styles.module.css +32 -0
  126. package/dist/components/gantt/components/containers/internal/index.d.ts +22 -0
  127. package/dist/components/gantt/components/containers/internal/index.js +35 -0
  128. package/dist/components/gantt/components/containers/internal/index.js.map +1 -0
  129. package/dist/components/gantt/components/containers/internal/layout-container/index.d.ts +22 -0
  130. package/dist/components/gantt/components/containers/internal/layout-container/index.js +27 -0
  131. package/dist/components/gantt/components/containers/internal/layout-container/index.js.map +1 -0
  132. package/dist/components/gantt/components/containers/internal/styles.module.css +35 -0
  133. package/dist/components/gantt/components/containers/internal/virtualized-content-height-container/index.d.ts +22 -0
  134. package/dist/components/gantt/components/containers/internal/virtualized-content-height-container/index.js +38 -0
  135. package/dist/components/gantt/components/containers/internal/virtualized-content-height-container/index.js.map +1 -0
  136. package/dist/components/gantt/components/content-row/block.d.ts +27 -0
  137. package/dist/components/gantt/components/content-row/block.js +39 -0
  138. package/dist/components/gantt/components/content-row/block.js.map +1 -0
  139. package/dist/components/gantt/components/content-row/bracket.d.ts +23 -0
  140. package/dist/components/gantt/components/content-row/bracket.js +48 -0
  141. package/dist/components/gantt/components/content-row/bracket.js.map +1 -0
  142. package/dist/components/gantt/components/content-row/icon-marker.d.ts +27 -0
  143. package/dist/components/gantt/components/content-row/icon-marker.js +41 -0
  144. package/dist/components/gantt/components/content-row/icon-marker.js.map +1 -0
  145. package/dist/components/gantt/components/content-row/index.d.ts +24 -0
  146. package/dist/components/gantt/components/content-row/index.js +32 -0
  147. package/dist/components/gantt/components/content-row/index.js.map +1 -0
  148. package/dist/components/gantt/components/content-row/marker.d.ts +21 -0
  149. package/dist/components/gantt/components/content-row/marker.js +35 -0
  150. package/dist/components/gantt/components/content-row/marker.js.map +1 -0
  151. package/dist/components/gantt/components/content-row/spacer.d.ts +23 -0
  152. package/dist/components/gantt/components/content-row/spacer.js +35 -0
  153. package/dist/components/gantt/components/content-row/spacer.js.map +1 -0
  154. package/dist/components/gantt/components/content-row/styles.module.css +198 -0
  155. package/dist/components/gantt/components/content-row/use-elapsed-percentage/index.d.ts +19 -0
  156. package/dist/components/gantt/components/content-row/use-elapsed-percentage/index.js +27 -0
  157. package/dist/components/gantt/components/content-row/use-elapsed-percentage/index.js.map +1 -0
  158. package/dist/components/gantt/components/content-row/use-is-elapsed/index.d.ts +10 -0
  159. package/dist/components/gantt/components/content-row/use-is-elapsed/index.js +24 -0
  160. package/dist/components/gantt/components/content-row/use-is-elapsed/index.js.map +1 -0
  161. package/dist/components/gantt/components/current-time/index.d.ts +28 -0
  162. package/dist/components/gantt/components/current-time/index.js +63 -0
  163. package/dist/components/gantt/components/current-time/index.js.map +1 -0
  164. package/dist/components/gantt/components/current-time/styles.module.css +42 -0
  165. package/dist/components/gantt/components/current-time/use-current-time-layout/index.d.ts +31 -0
  166. package/dist/components/gantt/components/current-time/use-current-time-layout/index.js +58 -0
  167. package/dist/components/gantt/components/current-time/use-current-time-layout/index.js.map +1 -0
  168. package/dist/components/gantt/components/header/index.d.ts +25 -0
  169. package/dist/components/gantt/components/header/index.js +41 -0
  170. package/dist/components/gantt/components/header/index.js.map +1 -0
  171. package/dist/components/gantt/components/header/styles.module.css +23 -0
  172. package/dist/components/gantt/components/panel-row/index.d.ts +24 -0
  173. package/dist/components/gantt/components/panel-row/index.js +33 -0
  174. package/dist/components/gantt/components/panel-row/index.js.map +1 -0
  175. package/dist/components/gantt/components/panel-row/styles.module.css +24 -0
  176. package/dist/components/gantt/components/rows-virtualizer/index.d.ts +25 -0
  177. package/dist/components/gantt/components/rows-virtualizer/index.js +67 -0
  178. package/dist/components/gantt/components/rows-virtualizer/index.js.map +1 -0
  179. package/dist/components/gantt/components/rows-virtualizer/styles.module.css +30 -0
  180. package/dist/components/gantt/components/rows-virtualizer/use-rendered-rows/index.d.ts +29 -0
  181. package/dist/components/gantt/components/rows-virtualizer/use-rendered-rows/index.js +57 -0
  182. package/dist/components/gantt/components/rows-virtualizer/use-rendered-rows/index.js.map +1 -0
  183. package/dist/components/gantt/components/rows-virtualizer/use-scroll-sync/index.d.ts +10 -0
  184. package/dist/components/gantt/components/rows-virtualizer/use-scroll-sync/index.js +58 -0
  185. package/dist/components/gantt/components/rows-virtualizer/use-scroll-sync/index.js.map +1 -0
  186. package/dist/components/gantt/components/styles.module.css +46 -0
  187. package/dist/components/gantt/components/timeline/index.d.ts +19 -0
  188. package/dist/components/gantt/components/timeline/index.js +45 -0
  189. package/dist/components/gantt/components/timeline/index.js.map +1 -0
  190. package/dist/components/gantt/components/timeline/use-timeline-transform/index.d.ts +29 -0
  191. package/dist/components/gantt/components/timeline/use-timeline-transform/index.js +33 -0
  192. package/dist/components/gantt/components/timeline/use-timeline-transform/index.js.map +1 -0
  193. package/dist/components/gantt/components/timeline-chunk/index.d.ts +25 -0
  194. package/dist/components/gantt/components/timeline-chunk/index.js +43 -0
  195. package/dist/components/gantt/components/timeline-chunk/index.js.map +1 -0
  196. package/dist/components/gantt/constants.d.ts +31 -0
  197. package/dist/components/gantt/constants.js +57 -0
  198. package/dist/components/gantt/constants.js.map +1 -0
  199. package/dist/components/gantt/context/index.d.ts +60 -0
  200. package/dist/components/gantt/context/index.js +78 -0
  201. package/dist/components/gantt/context/index.js.map +1 -0
  202. package/dist/components/gantt/context/store/index.d.ts +45 -0
  203. package/dist/components/gantt/context/store/index.js +42 -0
  204. package/dist/components/gantt/context/store/index.js.map +1 -0
  205. package/dist/components/gantt/context/temporal-data/index.d.ts +48 -0
  206. package/dist/components/gantt/context/temporal-data/index.js +80 -0
  207. package/dist/components/gantt/context/temporal-data/index.js.map +1 -0
  208. package/dist/components/gantt/gantt.d.ts +50 -0
  209. package/dist/components/gantt/gantt.js +51 -0
  210. package/dist/components/gantt/gantt.js.map +1 -0
  211. package/dist/components/gantt/hooks/use-horizontal-scroll-update/index.d.ts +22 -0
  212. package/dist/components/gantt/hooks/use-horizontal-scroll-update/index.js +36 -0
  213. package/dist/components/gantt/hooks/use-horizontal-scroll-update/index.js.map +1 -0
  214. package/dist/components/gantt/hooks/use-layout-subscription/index.d.ts +26 -0
  215. package/dist/components/gantt/hooks/use-layout-subscription/index.js +45 -0
  216. package/dist/components/gantt/hooks/use-layout-subscription/index.js.map +1 -0
  217. package/dist/components/gantt/hooks/use-resize-intersection-effect/index.d.ts +26 -0
  218. package/dist/components/gantt/hooks/use-resize-intersection-effect/index.js +50 -0
  219. package/dist/components/gantt/hooks/use-resize-intersection-effect/index.js.map +1 -0
  220. package/dist/components/gantt/hooks/use-root-element-height/index.d.ts +5 -0
  221. package/dist/components/gantt/hooks/use-root-element-height/index.js +24 -0
  222. package/dist/components/gantt/hooks/use-root-element-height/index.js.map +1 -0
  223. package/dist/components/gantt/hooks/use-scrollbar-height/index.d.ts +5 -0
  224. package/dist/components/gantt/hooks/use-scrollbar-height/index.js +40 -0
  225. package/dist/components/gantt/hooks/use-scrollbar-height/index.js.map +1 -0
  226. package/dist/components/gantt/hooks/use-total-data-region-thresholds/index.d.ts +19 -0
  227. package/dist/components/gantt/hooks/use-total-data-region-thresholds/index.js +87 -0
  228. package/dist/components/gantt/hooks/use-total-data-region-thresholds/index.js.map +1 -0
  229. package/dist/components/gantt/hooks/use-vertical-scroll-update/index.d.ts +22 -0
  230. package/dist/components/gantt/hooks/use-vertical-scroll-update/index.js +38 -0
  231. package/dist/components/gantt/hooks/use-vertical-scroll-update/index.js.map +1 -0
  232. package/dist/components/gantt/public-types.d.ts +31 -0
  233. package/dist/components/gantt/public-types.js +12 -0
  234. package/dist/components/gantt/store.d.ts +51 -0
  235. package/dist/components/gantt/store.js +46 -0
  236. package/dist/components/gantt/store.js.map +1 -0
  237. package/dist/components/gantt/styles.module.css +30 -0
  238. package/dist/components/gantt/types.d.ts +67 -0
  239. package/dist/components/gantt/types.js +12 -0
  240. package/dist/components/gantt/utils/conversions.d.ts +23 -0
  241. package/dist/components/gantt/utils/conversions.js +34 -0
  242. package/dist/components/gantt/utils/conversions.js.map +1 -0
  243. package/dist/components/gantt/utils/dates.d.ts +11 -0
  244. package/dist/components/gantt/utils/dates.js +41 -0
  245. package/dist/components/gantt/utils/dates.js.map +1 -0
  246. package/dist/components/gantt/utils/formatting.d.ts +5 -0
  247. package/dist/components/gantt/utils/formatting.js +54 -0
  248. package/dist/components/gantt/utils/formatting.js.map +1 -0
  249. package/dist/components/gantt/utils/generation.d.ts +19 -0
  250. package/dist/components/gantt/utils/generation.js +37 -0
  251. package/dist/components/gantt/utils/generation.js.map +1 -0
  252. package/dist/components/gantt/utils/helpers.d.ts +26 -0
  253. package/dist/components/gantt/utils/helpers.js +55 -0
  254. package/dist/components/gantt/utils/helpers.js.map +1 -0
  255. package/dist/components/gantt/utils/layout.d.ts +32 -0
  256. package/dist/components/gantt/utils/layout.js +55 -0
  257. package/dist/components/gantt/utils/layout.js.map +1 -0
  258. package/dist/components/gantt/utils/thresholds.d.ts +52 -0
  259. package/dist/components/gantt/utils/thresholds.js +116 -0
  260. package/dist/components/gantt/utils/thresholds.js.map +1 -0
  261. package/dist/components/hero/context.d.ts +2 -2
  262. package/dist/components/hero/index.d.ts +2 -2
  263. package/dist/components/hero/subtitle.d.ts +2 -2
  264. package/dist/components/hero/title.d.ts +2 -2
  265. package/dist/components/hotkey/context.d.ts +4 -4
  266. package/dist/components/hotkey/index.d.ts +2 -2
  267. package/dist/components/hotkey/set.d.ts +2 -2
  268. package/dist/components/icon/context.d.ts +4 -4
  269. package/dist/components/icon/index.d.ts +2 -2
  270. package/dist/components/input/context.d.ts +2 -2
  271. package/dist/components/input/index.d.ts +2 -2
  272. package/dist/components/kanban/card-body.d.ts +2 -2
  273. package/dist/components/kanban/card-header-actions.d.ts +2 -2
  274. package/dist/components/kanban/card-header-title.d.ts +2 -2
  275. package/dist/components/kanban/card-header.d.ts +2 -2
  276. package/dist/components/kanban/card.d.ts +2 -2
  277. package/dist/components/kanban/column-actions.d.ts +2 -2
  278. package/dist/components/kanban/column-container.d.ts +2 -2
  279. package/dist/components/kanban/column-content.d.ts +2 -2
  280. package/dist/components/kanban/column-header-actions.d.ts +2 -2
  281. package/dist/components/kanban/column-header-drag-handle.d.ts +2 -2
  282. package/dist/components/kanban/column-header-title.d.ts +2 -2
  283. package/dist/components/kanban/column-header.d.ts +2 -2
  284. package/dist/components/kanban/column.d.ts +2 -2
  285. package/dist/components/kanban/context.d.ts +2 -2
  286. package/dist/components/kanban/header-actions.d.ts +2 -2
  287. package/dist/components/kanban/header-search.d.ts +2 -2
  288. package/dist/components/kanban/header-title.d.ts +2 -2
  289. package/dist/components/kanban/header.d.ts +2 -2
  290. package/dist/components/kanban/kanban.d.ts +4 -4
  291. package/dist/components/label/context.d.ts +4 -4
  292. package/dist/components/label/index.d.ts +2 -2
  293. package/dist/components/lines/index.d.ts +2 -2
  294. package/dist/components/link/context.d.ts +2 -2
  295. package/dist/components/link/index.d.ts +2 -2
  296. package/dist/components/list/context.d.ts +2 -2
  297. package/dist/components/list/index.d.ts +2 -2
  298. package/dist/components/list/item-content.d.ts +2 -2
  299. package/dist/components/list/item-description.d.ts +2 -2
  300. package/dist/components/list/item-title.d.ts +2 -2
  301. package/dist/components/list/item.d.ts +2 -2
  302. package/dist/components/media-controls/context.d.ts +4 -4
  303. package/dist/components/media-controls/fullscreen-button.d.ts +2 -2
  304. package/dist/components/media-controls/index.d.ts +2 -2
  305. package/dist/components/media-controls/mute-button.d.ts +2 -2
  306. package/dist/components/media-controls/play-button.d.ts +2 -2
  307. package/dist/components/media-controls/playback-rate.d.ts +2 -2
  308. package/dist/components/media-controls/seek-button.d.ts +2 -2
  309. package/dist/components/media-controls/time-display.d.ts +2 -2
  310. package/dist/components/media-controls/time-range.d.ts +2 -2
  311. package/dist/components/media-controls/volume-slider.d.ts +2 -2
  312. package/dist/components/menu/context.d.ts +2 -2
  313. package/dist/components/menu/index.d.ts +2 -2
  314. package/dist/components/menu/item-description.d.ts +2 -2
  315. package/dist/components/menu/item-label.d.ts +2 -2
  316. package/dist/components/menu/item.d.ts +2 -2
  317. package/dist/components/menu/section.d.ts +2 -2
  318. package/dist/components/menu/separator.d.ts +2 -2
  319. package/dist/components/menu/styles.module.css +12 -0
  320. package/dist/components/menu/submenu.d.ts +2 -2
  321. package/dist/components/notice/index.d.ts +2 -2
  322. package/dist/components/notice/index.js +1 -0
  323. package/dist/components/notice/index.js.map +1 -1
  324. package/dist/components/notice/list.d.ts +2 -2
  325. package/dist/components/notice/list.js +10 -1
  326. package/dist/components/notice/list.js.map +1 -1
  327. package/dist/components/notice/notice-icon.d.ts +2 -2
  328. package/dist/components/notice/styles.module.css +27 -0
  329. package/dist/components/options/context.d.ts +2 -2
  330. package/dist/components/options/index.d.ts +2 -2
  331. package/dist/components/options/item-content.d.ts +2 -2
  332. package/dist/components/options/item-description.d.ts +2 -2
  333. package/dist/components/options/item-label.d.ts +2 -2
  334. package/dist/components/options/item.d.ts +2 -2
  335. package/dist/components/options/section.d.ts +2 -2
  336. package/dist/components/pagination/context.d.ts +2 -2
  337. package/dist/components/pagination/index.d.ts +2 -2
  338. package/dist/components/pagination/next.d.ts +2 -2
  339. package/dist/components/pagination/pages.d.ts +2 -2
  340. package/dist/components/pagination/prev.d.ts +2 -2
  341. package/dist/components/popover/content.d.ts +2 -2
  342. package/dist/components/popover/footer.d.ts +2 -2
  343. package/dist/components/popover/index.d.ts +2 -2
  344. package/dist/components/popover/styles.module.css +34 -0
  345. package/dist/components/popover/title.d.ts +2 -2
  346. package/dist/components/popover/trigger.d.ts +2 -2
  347. package/dist/components/query-builder/action-element.d.ts +2 -2
  348. package/dist/components/query-builder/actions.d.ts +4 -4
  349. package/dist/components/query-builder/combinator-selector.d.ts +2 -2
  350. package/dist/components/query-builder/index.d.ts +2 -2
  351. package/dist/components/query-builder/rule-group.d.ts +4 -4
  352. package/dist/components/query-builder/rule.d.ts +2 -2
  353. package/dist/components/query-builder/value-editor.d.ts +2 -2
  354. package/dist/components/query-builder/value-selector.d.ts +2 -2
  355. package/dist/components/query-builder/value-selector.js +1 -1
  356. package/dist/components/radio/context.d.ts +3 -3
  357. package/dist/components/radio/group.d.ts +2 -2
  358. package/dist/components/radio/index.d.ts +2 -2
  359. package/dist/components/search-field/context.d.ts +4 -4
  360. package/dist/components/search-field/index.d.ts +2 -2
  361. package/dist/components/select-field/context.d.ts +4 -4
  362. package/dist/components/select-field/index.d.ts +2 -2
  363. package/dist/components/sidenav/avatar.d.ts +2 -2
  364. package/dist/components/sidenav/content.d.ts +2 -2
  365. package/dist/components/sidenav/context.d.ts +2 -2
  366. package/dist/components/sidenav/footer.d.ts +2 -2
  367. package/dist/components/sidenav/header.d.ts +2 -2
  368. package/dist/components/sidenav/index.d.ts +2 -2
  369. package/dist/components/sidenav/item.d.ts +2 -2
  370. package/dist/components/sidenav/link.d.ts +2 -2
  371. package/dist/components/sidenav/menu-item.d.ts +2 -2
  372. package/dist/components/sidenav/menu.d.ts +2 -2
  373. package/dist/components/sidenav/styles.module.css +10 -2
  374. package/dist/components/sidenav/trigger.d.ts +2 -2
  375. package/dist/components/skeleton/index.d.ts +2 -2
  376. package/dist/components/slider/index.d.ts +2 -2
  377. package/dist/components/status-indicator/index.d.ts +2 -2
  378. package/dist/components/switch/context.d.ts +4 -4
  379. package/dist/components/switch/index.d.ts +2 -2
  380. package/dist/components/switch/styles.module.css +8 -0
  381. package/dist/components/table/body.d.ts +2 -2
  382. package/dist/components/table/cell.d.ts +2 -2
  383. package/dist/components/table/context.d.ts +2 -2
  384. package/dist/components/table/header-cell.d.ts +2 -2
  385. package/dist/components/table/header.d.ts +2 -2
  386. package/dist/components/table/index.d.ts +2 -2
  387. package/dist/components/table/index.js +2 -2
  388. package/dist/components/table/index.js.map +1 -1
  389. package/dist/components/table/row.d.ts +2 -2
  390. package/dist/components/tabs/context.d.ts +6 -6
  391. package/dist/components/tabs/index.d.ts +2 -2
  392. package/dist/components/tabs/list.d.ts +2 -2
  393. package/dist/components/tabs/panel.d.ts +2 -2
  394. package/dist/components/tabs/tab.d.ts +2 -2
  395. package/dist/components/text-area-field/context.d.ts +4 -4
  396. package/dist/components/text-area-field/index.d.ts +2 -2
  397. package/dist/components/text-field/context.d.ts +4 -4
  398. package/dist/components/text-field/index.d.ts +2 -2
  399. package/dist/components/time-field/index.d.ts +2 -2
  400. package/dist/components/tooltip/context.d.ts +2 -2
  401. package/dist/components/tooltip/index.d.ts +2 -2
  402. package/dist/components/tooltip/styles.module.css +35 -0
  403. package/dist/components/tooltip/trigger.d.ts +2 -2
  404. package/dist/components/tree/context.d.ts +3 -3
  405. package/dist/components/tree/index.d.ts +2 -2
  406. package/dist/components/tree/index.js +20 -10
  407. package/dist/components/tree/index.js.map +1 -1
  408. package/dist/components/tree/item-actions.d.ts +2 -2
  409. package/dist/components/tree/item-content.d.ts +2 -2
  410. package/dist/components/tree/item-content.js +3 -2
  411. package/dist/components/tree/item-content.js.map +1 -1
  412. package/dist/components/tree/item-description.d.ts +2 -2
  413. package/dist/components/tree/item-label.d.ts +2 -2
  414. package/dist/components/tree/item-prefix-icon.d.ts +2 -2
  415. package/dist/components/tree/item.d.ts +2 -2
  416. package/dist/components/tree/lines.d.ts +2 -2
  417. package/dist/components/tree/types.d.ts +1 -0
  418. package/dist/components/video/index.d.ts +2 -2
  419. package/dist/components/view-stack/index.d.ts +2 -2
  420. package/dist/components/view-stack/trigger.d.ts +2 -2
  421. package/dist/components/view-stack/view.d.ts +2 -2
  422. package/dist/hooks/use-tree/actions/cache.d.ts +20 -3
  423. package/dist/hooks/use-tree/actions/cache.js +110 -2
  424. package/dist/hooks/use-tree/actions/cache.js.map +1 -1
  425. package/dist/hooks/use-tree/actions/index.d.ts +2 -1
  426. package/dist/hooks/use-tree/actions/index.js +70 -11
  427. package/dist/hooks/use-tree/actions/index.js.map +1 -1
  428. package/dist/hooks/use-tree/state/index.d.ts +20 -1
  429. package/dist/hooks/use-tree/state/index.js +22 -2
  430. package/dist/hooks/use-tree/state/index.js.map +1 -1
  431. package/dist/hooks/use-tree/types.d.ts +14 -0
  432. package/dist/index.d.ts +24 -5
  433. package/dist/index.js +27 -10
  434. package/dist/providers/portal.d.ts +2 -2
  435. package/dist/providers/theme-provider.d.ts +2 -2
  436. package/package.json +64 -6
@@ -71,12 +71,13 @@ declare class Cache<T> {
71
71
  toTree(deriveVisible?: boolean): TreeNode<T>[];
72
72
  /**
73
73
  * CACHE FUNCTIONS
74
- * These manage cache operations. No cache operations should ever be done
75
- * outside this file.
74
+ * These are the public functions to manage cache operations. No cache operations should ever be done
75
+ * outside this file since it risks corruption of the data.
76
76
  **/
77
77
  getNode(key: Key): TreeNode<T>;
78
78
  getAllKeys(): MapIterator<Key>;
79
79
  getAllNodes(): MapIterator<CacheTreeNode<T>>;
80
+ getParentForPosition(target: Key | null, position: 'before' | 'after'): Key | null;
80
81
  setNode(key: Key, node: TreeNode<T>): void;
81
82
  setAllNodes({
82
83
  parentKey,
@@ -88,7 +89,23 @@ declare class Cache<T> {
88
89
  insertNode(parentKey: Key | null, node: TreeNode<T>, idx: number): void;
89
90
  moveNodes(target: Key | null, nodes: Set<Key>, position: 'before' | 'after'): void;
90
91
  moveNode(parentKey: Key | null, key: Key, idx: number): void;
92
+ /**
93
+ * Cascade selection down through descendants
94
+ */
95
+ cascadeSelection(key: Key, selected: boolean): void;
96
+ /**
97
+ * Bubble up selection state through ancestors
98
+ */
99
+ bubbleUpSelection(key: Key): void;
100
+ /**
101
+ * Compute selection state for a node based on its children
102
+ */
103
+ private computeSelectionState;
104
+ /**
105
+ * Sync cascade state for parents after a move operation
106
+ */
107
+ syncParentsAfterMove(oldParents: Set<Key>, newParent: Key | null): void;
91
108
  }
92
109
  //#endregion
93
- export { Cache };
110
+ export { Cache, CacheTreeNode };
94
111
  //# sourceMappingURL=cache.d.ts.map
@@ -41,6 +41,7 @@ var Cache = class {
41
41
  isSelected: false,
42
42
  isVisible: false,
43
43
  isVisibleComputed: false,
44
+ isIndeterminate: false,
44
45
  ...rest,
45
46
  parentKey,
46
47
  ...children ? { children: children.map((child) => child.key) } : {}
@@ -56,6 +57,7 @@ var Cache = class {
56
57
  return cache;
57
58
  }
58
59
  get(key) {
60
+ if (key == null) throw new Error(`Key is ${key} (null/undefined) - this is invalid`);
59
61
  const node = this.cache.lookup.get(key);
60
62
  if (node === void 0) throw new Error(`Key of ${key} does not exist in tree`);
61
63
  return node;
@@ -183,8 +185,8 @@ var Cache = class {
183
185
  }
184
186
  /**
185
187
  * CACHE FUNCTIONS
186
- * These manage cache operations. No cache operations should ever be done
187
- * outside this file.
188
+ * These are the public functions to manage cache operations. No cache operations should ever be done
189
+ * outside this file since it risks corruption of the data.
188
190
  **/
189
191
  getNode(key) {
190
192
  const node = this.get(key);
@@ -199,6 +201,10 @@ var Cache = class {
199
201
  getAllNodes() {
200
202
  return this.cache.lookup.values();
201
203
  }
204
+ getParentForPosition(target, position) {
205
+ const { parentKey } = this.parentOrSibling(target, position);
206
+ return parentKey;
207
+ }
202
208
  setNode(key, node) {
203
209
  this.set(key, {
204
210
  ...node,
@@ -231,6 +237,7 @@ var Cache = class {
231
237
  isSelected: false,
232
238
  isVisible: false,
233
239
  isVisibleComputed: false,
240
+ isIndeterminate: false,
234
241
  ...rest,
235
242
  parentKey,
236
243
  ...children ? { children: children.map((child) => child.key) } : {}
@@ -248,6 +255,107 @@ var Cache = class {
248
255
  node.parentKey ? this.removeFromParent(node.parentKey, key) : this.removeFromRoot(key);
249
256
  parentKey ? this.addToParent(parentKey, key, idx) : this.addToRoot(key, idx);
250
257
  }
258
+ /**
259
+ * Cascade selection down through descendants
260
+ */
261
+ cascadeSelection(key, selected) {
262
+ try {
263
+ const node = this.get(key);
264
+ if (!node.isDisabled) this.set(key, {
265
+ ...node,
266
+ isSelected: selected,
267
+ isIndeterminate: false
268
+ });
269
+ if (node.children) {
270
+ for (const childKey of node.children) if (childKey != null) this.cascadeSelection(childKey, selected);
271
+ }
272
+ } catch {
273
+ return;
274
+ }
275
+ }
276
+ /**
277
+ * Bubble up selection state through ancestors
278
+ */
279
+ bubbleUpSelection(key) {
280
+ try {
281
+ let current = this.get(key);
282
+ while (current.parentKey) {
283
+ const parent = this.get(current.parentKey);
284
+ const newState = this.computeSelectionState(parent);
285
+ if (parent.isSelected === newState.isSelected && parent.isIndeterminate === newState.isIndeterminate) break;
286
+ this.set(parent.key, {
287
+ ...parent,
288
+ isSelected: newState.isSelected,
289
+ isIndeterminate: newState.isIndeterminate
290
+ });
291
+ current = parent;
292
+ }
293
+ } catch {
294
+ return;
295
+ }
296
+ }
297
+ /**
298
+ * Compute selection state for a node based on its children
299
+ */
300
+ computeSelectionState(node) {
301
+ if (!node.children || node.children.length === 0) return {
302
+ isSelected: node.isSelected ?? false,
303
+ isIndeterminate: false
304
+ };
305
+ const selectableChildren = node.children.filter((k) => {
306
+ try {
307
+ return !this.get(k).isDisabled;
308
+ } catch {
309
+ return false;
310
+ }
311
+ }).map((k) => this.get(k));
312
+ if (selectableChildren.length === 0) return {
313
+ isSelected: node.isSelected ?? false,
314
+ isIndeterminate: false
315
+ };
316
+ const selectedCount = selectableChildren.filter((c) => c.isSelected).length;
317
+ if (selectableChildren.filter((c) => c.isIndeterminate).length > 0) return {
318
+ isSelected: false,
319
+ isIndeterminate: true
320
+ };
321
+ if (selectedCount === selectableChildren.length) return {
322
+ isSelected: true,
323
+ isIndeterminate: false
324
+ };
325
+ if (selectedCount === 0) return {
326
+ isSelected: false,
327
+ isIndeterminate: false
328
+ };
329
+ return {
330
+ isSelected: false,
331
+ isIndeterminate: true
332
+ };
333
+ }
334
+ /**
335
+ * Sync cascade state for parents after a move operation
336
+ */
337
+ syncParentsAfterMove(oldParents, newParent) {
338
+ for (const parentKey of oldParents) try {
339
+ const parent = this.get(parentKey);
340
+ const newState = this.computeSelectionState(parent);
341
+ this.set(parentKey, {
342
+ ...parent,
343
+ isSelected: newState.isSelected,
344
+ isIndeterminate: newState.isIndeterminate
345
+ });
346
+ if (parent.parentKey) this.bubbleUpSelection(parentKey);
347
+ } catch {}
348
+ if (newParent) try {
349
+ const parent = this.get(newParent);
350
+ const newState = this.computeSelectionState(parent);
351
+ this.set(newParent, {
352
+ ...parent,
353
+ isSelected: newState.isSelected,
354
+ isIndeterminate: newState.isIndeterminate
355
+ });
356
+ if (parent.parentKey) this.bubbleUpSelection(newParent);
357
+ } catch {}
358
+ }
251
359
  };
252
360
 
253
361
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","names":["index: number","parentKey: Key | null","key"],"sources":["../../../../src/hooks/use-tree/actions/cache.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Key } from '@react-types/shared';\nimport type { TreeNode } from '../types';\n\ntype CacheTreeNode<T> = Omit<TreeNode<T>, 'children'> & {\n children?: Key[];\n};\n\n/**\n * This is a cache created only for performance reasons and is considered\n * to be only a temporary mirror of the data. The data is *always* correct\n * cache should be updated according to the data, only. If the data and\n * the cache do not match, the cache is invalidated and rebuilt.\n *\n * This will initialize once on load with data, then\n * updated with each tree operation.\n */\nexport class Cache<T> {\n protected cache: { lookup: Map<Key, CacheTreeNode<T>>; roots: Key[] } = {\n lookup: new Map(),\n roots: [],\n };\n\n constructor(nodes: TreeNode<T>[] = []) {\n this.rebuild(nodes);\n }\n\n /**\n * Recursively creates the cache object from tree data\n */\n rebuild(\n nodes: TreeNode<T>[],\n lookup: Map<Key, CacheTreeNode<T>> = new Map(),\n parentKey: Key | null = null,\n ) {\n nodes.forEach((node) => {\n const { children, ...rest } = node;\n\n lookup.set(node.key, {\n isDisabled: false,\n isExpanded: false,\n isSelected: false,\n isVisible: false,\n isVisibleComputed: false,\n ...rest,\n parentKey,\n ...(children ? { children: children.map((child) => child.key) } : {}),\n });\n\n if (node.children) {\n this.rebuild(node.children, lookup, node.key);\n }\n });\n\n const cache = { lookup, roots: nodes.map((node) => node.key) };\n\n if (!parentKey) {\n this.cache = cache;\n }\n\n this.deriveVisibility();\n return cache;\n }\n\n protected get(key: Key) {\n const node = this.cache.lookup.get(key);\n\n if (node === undefined) {\n throw new Error(`Key of ${key} does not exist in tree`);\n }\n\n return node;\n }\n\n protected set(key: Key, node: CacheTreeNode<T>) {\n this.cache.lookup.set(key, node);\n }\n\n protected delete(key: Key) {\n this.cache.lookup.delete(key);\n }\n\n protected addToParent(parentKey: Key, childKey: Key, idx: number) {\n const parent = this.get(parentKey);\n const child = this.get(childKey);\n const index = Math.max(0, idx);\n\n this.set(childKey, {\n ...child,\n parentKey,\n });\n\n const children = (parent.children ?? []).slice(0);\n\n children.splice(index, 0, childKey);\n\n this.set(parentKey, {\n ...parent,\n children,\n });\n }\n\n protected addToRoot(key: Key, idx: number) {\n const node = this.get(key);\n const index = Math.max(0, idx);\n\n this.set(key, {\n ...node,\n parentKey: null,\n });\n\n this.cache.roots.splice(index, 0, key);\n }\n\n protected removeFromParent(parentKey: Key, childKey: Key) {\n const parent = this.get(parentKey);\n const child = this.get(childKey);\n\n this.set(childKey, {\n ...child,\n parentKey: null,\n });\n\n this.cache.lookup.set(parentKey, {\n ...parent,\n children: parent.children?.filter((key) => key !== childKey),\n });\n }\n\n protected removeFromRoot(key: Key) {\n const node = this.get(key);\n const idx = this.cache.roots.indexOf(key);\n\n if (idx >= 0) {\n this.set(key, {\n ...node,\n parentKey: null,\n });\n\n this.cache.roots.splice(idx, 1);\n }\n }\n\n protected parentOrSibling(target: Key | null, position: 'before' | 'after') {\n let index: number;\n let parentKey: Key | null = null;\n\n if (target === null) {\n index = position === 'before' ? 0 : this.cache.roots.length;\n } else {\n const targetNode = this.get(target);\n\n if (targetNode.parentKey) {\n const parent = this.get(targetNode.parentKey);\n\n parentKey = parent.key;\n index = parent.children?.indexOf(target) ?? 0;\n } else {\n index = this.cache.roots.indexOf(target);\n }\n }\n\n return { parentKey, index };\n }\n\n protected traverse(key: Key) {\n const node = this.get(key);\n\n this.cache.lookup.set(key, {\n ...node,\n isVisibleComputed: this.calculateVisibility(key),\n });\n\n node.children?.map((child) => this.traverse(child));\n }\n\n protected calculateVisibility(key: Key) {\n let current = this.get(key);\n const ancestry = [current];\n\n while (current.parentKey) {\n const parent = this.get(current.parentKey);\n if (parent) {\n ancestry.push(parent);\n }\n current = parent;\n }\n\n return ancestry.every((n) => n.isVisible);\n }\n\n protected deriveVisibility() {\n return this.cache.roots.map((key) => this.traverse(key));\n }\n /**\n * Recursively builds a TreeNode from a key\n *\n * @param key\n */\n protected buildNode(key: Key): TreeNode<T> {\n const node = this.get(key);\n\n const children = (node.children ?? []).reduce(\n (acc: TreeNode<T>[], child) => {\n const childNode = this.cache.lookup.get(child);\n\n if (childNode && childNode.parentKey === key) {\n acc.push(this.buildNode(child));\n }\n\n return acc;\n },\n [],\n );\n\n return {\n ...node,\n children,\n };\n }\n\n /**\n * Builds a tree structure from cache\n *\n * TODO: optimization - rebuild only from change to root\n * Rebuild only from the changed node up the tree to avoid\n * rebuilding the entire tree\n *\n * @param deriveVisible boolean - if true, will recompute visibility for nodes based on ancestry\n */\n toTree(deriveVisible?: boolean): TreeNode<T>[] {\n if (deriveVisible) {\n this.deriveVisibility();\n }\n return this.cache.roots.map((key) => this.buildNode(key));\n }\n\n /**\n * CACHE FUNCTIONS\n * These manage cache operations. No cache operations should ever be done\n * outside this file.\n **/\n getNode(key: Key): TreeNode<T> {\n const node = this.get(key);\n\n return {\n ...node,\n children: node.children?.map((key) => this.buildNode(key)),\n };\n }\n\n getAllKeys() {\n return this.cache.lookup.keys();\n }\n\n getAllNodes() {\n return this.cache.lookup.values();\n }\n\n setNode(key: Key, node: TreeNode<T>) {\n this.set(key, {\n ...node,\n children: (node.children ?? []).map((child) => child.key),\n });\n }\n\n setAllNodes({ parentKey, children, ...rest }: Partial<TreeNode<T>>) {\n for (const node of this.cache.lookup.values()) {\n this.set(node.key, {\n ...node,\n ...rest,\n });\n }\n }\n\n deleteNode(key: Key) {\n const node = this.cache.lookup.get(key);\n\n if (!node) {\n return;\n }\n\n // remove children\n node.children?.map((key) => this.deleteNode(key));\n\n // remove node from previous parent or root\n node.parentKey\n ? this.removeFromParent(node.parentKey, key)\n : this.removeFromRoot(key);\n\n // remove the actual node\n this.delete(key);\n }\n\n addNodes(\n target: Key | null,\n nodes: TreeNode<T>[],\n position: 'before' | 'after',\n ) {\n const { parentKey, index } = this.parentOrSibling(target, position);\n const idx = index + (position === 'before' ? 0 : 1);\n\n nodes.map((node, i) => this.insertNode(parentKey, node, idx + i));\n }\n\n insertNode(parentKey: Key | null, node: TreeNode<T>, idx: number) {\n const { children, ...rest } = node;\n\n this.set(node.key, {\n isDisabled: false,\n isExpanded: false,\n isSelected: false,\n isVisible: false,\n isVisibleComputed: false,\n ...rest,\n parentKey,\n ...(children ? { children: children.map((child) => child.key) } : {}),\n });\n\n node.children?.map((child, i) => this.insertNode(node.key, child, i));\n\n parentKey === null\n ? this.addToRoot(node.key, idx)\n : this.addToParent(parentKey, node.key, idx);\n }\n\n moveNodes(target: Key | null, nodes: Set<Key>, position: 'before' | 'after') {\n const { parentKey, index } = this.parentOrSibling(target, position);\n const idx = index + (position === 'before' ? 0 : 1);\n\n Array.from(nodes).map((key, i) => this.moveNode(parentKey, key, idx + i));\n }\n\n moveNode(parentKey: Key | null, key: Key, idx: number) {\n const node = this.get(key);\n\n // remove from previous parent\n node.parentKey\n ? this.removeFromParent(node.parentKey, key)\n : this.removeFromRoot(key);\n\n // add as child to new parent or root at position\n parentKey\n ? this.addToParent(parentKey, key, idx)\n : this.addToRoot(key, idx);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","names":["index: number","parentKey: Key | null","key"],"sources":["../../../../src/hooks/use-tree/actions/cache.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Key } from '@react-types/shared';\nimport type { TreeNode } from '../types';\n\nexport type CacheTreeNode<T> = Omit<TreeNode<T>, 'children'> & {\n children?: Key[];\n};\n\n/**\n * This is a cache created only for performance reasons and is considered\n * to be only a temporary mirror of the data. The data is *always* correct\n * cache should be updated according to the data, only. If the data and\n * the cache do not match, the cache is invalidated and rebuilt.\n *\n * This will initialize once on load with data, then\n * updated with each tree operation.\n */\nexport class Cache<T> {\n protected cache: { lookup: Map<Key, CacheTreeNode<T>>; roots: Key[] } = {\n lookup: new Map(),\n roots: [],\n };\n\n constructor(nodes: TreeNode<T>[] = []) {\n this.rebuild(nodes);\n }\n\n /**\n * Recursively creates the cache object from tree data\n */\n rebuild(\n nodes: TreeNode<T>[],\n lookup: Map<Key, CacheTreeNode<T>> = new Map(),\n parentKey: Key | null = null,\n ) {\n nodes.forEach((node) => {\n const { children, ...rest } = node;\n\n lookup.set(node.key, {\n isDisabled: false,\n isExpanded: false,\n isSelected: false,\n isVisible: false,\n isVisibleComputed: false,\n isIndeterminate: false,\n ...rest,\n parentKey,\n ...(children ? { children: children.map((child) => child.key) } : {}),\n });\n\n if (node.children) {\n this.rebuild(node.children, lookup, node.key);\n }\n });\n\n const cache = { lookup, roots: nodes.map((node) => node.key) };\n\n if (!parentKey) {\n this.cache = cache;\n }\n\n this.deriveVisibility();\n return cache;\n }\n\n protected get(key: Key) {\n if (key == null) {\n throw new Error(`Key is ${key} (null/undefined) - this is invalid`);\n }\n\n const node = this.cache.lookup.get(key);\n\n if (node === undefined) {\n throw new Error(`Key of ${key} does not exist in tree`);\n }\n\n return node;\n }\n\n protected set(key: Key, node: CacheTreeNode<T>) {\n this.cache.lookup.set(key, node);\n }\n\n protected delete(key: Key) {\n this.cache.lookup.delete(key);\n }\n\n protected addToParent(parentKey: Key, childKey: Key, idx: number) {\n const parent = this.get(parentKey);\n const child = this.get(childKey);\n const index = Math.max(0, idx);\n\n this.set(childKey, {\n ...child,\n parentKey,\n });\n\n const children = (parent.children ?? []).slice(0);\n\n children.splice(index, 0, childKey);\n\n this.set(parentKey, {\n ...parent,\n children,\n });\n }\n\n protected addToRoot(key: Key, idx: number) {\n const node = this.get(key);\n const index = Math.max(0, idx);\n\n this.set(key, {\n ...node,\n parentKey: null,\n });\n\n this.cache.roots.splice(index, 0, key);\n }\n\n protected removeFromParent(parentKey: Key, childKey: Key) {\n const parent = this.get(parentKey);\n const child = this.get(childKey);\n\n this.set(childKey, {\n ...child,\n parentKey: null,\n });\n\n this.cache.lookup.set(parentKey, {\n ...parent,\n children: parent.children?.filter((key) => key !== childKey),\n });\n }\n\n protected removeFromRoot(key: Key) {\n const node = this.get(key);\n const idx = this.cache.roots.indexOf(key);\n\n if (idx >= 0) {\n this.set(key, {\n ...node,\n parentKey: null,\n });\n\n this.cache.roots.splice(idx, 1);\n }\n }\n\n protected parentOrSibling(target: Key | null, position: 'before' | 'after') {\n let index: number;\n let parentKey: Key | null = null;\n\n if (target === null) {\n index = position === 'before' ? 0 : this.cache.roots.length;\n } else {\n const targetNode = this.get(target);\n\n if (targetNode.parentKey) {\n const parent = this.get(targetNode.parentKey);\n\n parentKey = parent.key;\n index = parent.children?.indexOf(target) ?? 0;\n } else {\n index = this.cache.roots.indexOf(target);\n }\n }\n\n return { parentKey, index };\n }\n\n protected traverse(key: Key) {\n const node = this.get(key);\n\n this.cache.lookup.set(key, {\n ...node,\n isVisibleComputed: this.calculateVisibility(key),\n });\n\n node.children?.map((child) => this.traverse(child));\n }\n\n protected calculateVisibility(key: Key) {\n let current = this.get(key);\n const ancestry = [current];\n\n while (current.parentKey) {\n const parent = this.get(current.parentKey);\n if (parent) {\n ancestry.push(parent);\n }\n current = parent;\n }\n\n return ancestry.every((n) => n.isVisible);\n }\n\n protected deriveVisibility() {\n return this.cache.roots.map((key) => this.traverse(key));\n }\n /**\n * Recursively builds a TreeNode from a key\n *\n * @param key\n */\n protected buildNode(key: Key): TreeNode<T> {\n const node = this.get(key);\n\n const children = (node.children ?? []).reduce(\n (acc: TreeNode<T>[], child) => {\n const childNode = this.cache.lookup.get(child);\n\n if (childNode && childNode.parentKey === key) {\n acc.push(this.buildNode(child));\n }\n\n return acc;\n },\n [],\n );\n\n return {\n ...node,\n children,\n };\n }\n\n /**\n * Builds a tree structure from cache\n *\n * TODO: optimization - rebuild only from change to root\n * Rebuild only from the changed node up the tree to avoid\n * rebuilding the entire tree\n *\n * @param deriveVisible boolean - if true, will recompute visibility for nodes based on ancestry\n */\n toTree(deriveVisible?: boolean): TreeNode<T>[] {\n if (deriveVisible) {\n this.deriveVisibility();\n }\n return this.cache.roots.map((key) => this.buildNode(key));\n }\n\n /**\n * CACHE FUNCTIONS\n * These are the public functions to manage cache operations. No cache operations should ever be done\n * outside this file since it risks corruption of the data.\n **/\n getNode(key: Key): TreeNode<T> {\n const node = this.get(key);\n\n return {\n ...node,\n children: node.children?.map((key) => this.buildNode(key)),\n };\n }\n\n getAllKeys() {\n return this.cache.lookup.keys();\n }\n\n getAllNodes() {\n return this.cache.lookup.values();\n }\n\n getParentForPosition(\n target: Key | null,\n position: 'before' | 'after',\n ): Key | null {\n const { parentKey } = this.parentOrSibling(target, position);\n return parentKey;\n }\n\n setNode(key: Key, node: TreeNode<T>) {\n this.set(key, {\n ...node,\n children: (node.children ?? []).map((child) => child.key),\n });\n }\n\n setAllNodes({ parentKey, children, ...rest }: Partial<TreeNode<T>>) {\n for (const node of this.cache.lookup.values()) {\n this.set(node.key, {\n ...node,\n ...rest,\n });\n }\n }\n\n deleteNode(key: Key) {\n const node = this.cache.lookup.get(key);\n\n if (!node) {\n return;\n }\n\n // remove children\n node.children?.map((key) => this.deleteNode(key));\n\n // remove node from previous parent or root\n node.parentKey\n ? this.removeFromParent(node.parentKey, key)\n : this.removeFromRoot(key);\n\n // remove the actual node\n this.delete(key);\n }\n\n addNodes(\n target: Key | null,\n nodes: TreeNode<T>[],\n position: 'before' | 'after',\n ) {\n const { parentKey, index } = this.parentOrSibling(target, position);\n const idx = index + (position === 'before' ? 0 : 1);\n\n nodes.map((node, i) => this.insertNode(parentKey, node, idx + i));\n }\n\n insertNode(parentKey: Key | null, node: TreeNode<T>, idx: number) {\n const { children, ...rest } = node;\n\n this.set(node.key, {\n isDisabled: false,\n isExpanded: false,\n isSelected: false,\n isVisible: false,\n isVisibleComputed: false,\n isIndeterminate: false,\n ...rest,\n parentKey,\n ...(children\n ? {\n children: children.map((child) => child.key),\n }\n : {}),\n });\n\n node.children?.map((child, i) => this.insertNode(node.key, child, i));\n\n parentKey === null\n ? this.addToRoot(node.key, idx)\n : this.addToParent(parentKey, node.key, idx);\n }\n\n moveNodes(target: Key | null, nodes: Set<Key>, position: 'before' | 'after') {\n const { parentKey, index } = this.parentOrSibling(target, position);\n const idx = index + (position === 'before' ? 0 : 1);\n\n Array.from(nodes).map((key, i) => this.moveNode(parentKey, key, idx + i));\n }\n\n moveNode(parentKey: Key | null, key: Key, idx: number) {\n const node = this.get(key);\n\n // remove from previous parent\n node.parentKey\n ? this.removeFromParent(node.parentKey, key)\n : this.removeFromRoot(key);\n\n // add as child to new parent or root at position\n parentKey\n ? this.addToParent(parentKey, key, idx)\n : this.addToRoot(key, idx);\n }\n\n /**\n * Cascade selection down through descendants\n */\n cascadeSelection(key: Key, selected: boolean): void {\n try {\n const node = this.get(key);\n\n // Update this node (skip if disabled)\n if (!node.isDisabled) {\n this.set(key, {\n ...node,\n isSelected: selected,\n isIndeterminate: false,\n });\n }\n\n // Recurse to children\n if (node.children) {\n for (const childKey of node.children) {\n if (childKey != null) {\n this.cascadeSelection(childKey, selected);\n }\n }\n }\n } catch {\n // Key doesn't exist, skip\n return;\n }\n }\n\n /**\n * Bubble up selection state through ancestors\n */\n bubbleUpSelection(key: Key): void {\n try {\n let current = this.get(key);\n\n while (current.parentKey) {\n const parent = this.get(current.parentKey);\n const newState = this.computeSelectionState(parent);\n\n // Early termination: if parent state unchanged, ancestors won't change\n if (\n parent.isSelected === newState.isSelected &&\n parent.isIndeterminate === newState.isIndeterminate\n ) {\n break;\n }\n\n this.set(parent.key, {\n ...parent,\n isSelected: newState.isSelected,\n isIndeterminate: newState.isIndeterminate,\n });\n\n current = parent;\n }\n } catch {\n // Key doesn't exist, skip\n return;\n }\n }\n\n /**\n * Compute selection state for a node based on its children\n */\n private computeSelectionState(node: CacheTreeNode<T>): {\n isSelected: boolean;\n isIndeterminate: boolean;\n } {\n // Leaf nodes: use their own state\n if (!node.children || node.children.length === 0) {\n return {\n isSelected: node.isSelected ?? false,\n isIndeterminate: false,\n };\n }\n\n // Get selectable children (exclude disabled)\n const selectableChildren = node.children\n .filter((k) => {\n try {\n const child = this.get(k);\n return !child.isDisabled;\n } catch {\n return false;\n }\n })\n .map((k) => this.get(k));\n\n // If all children disabled, treat as leaf\n if (selectableChildren.length === 0) {\n return {\n isSelected: node.isSelected ?? false,\n isIndeterminate: false,\n };\n }\n\n // Check if all/none/some selected\n const selectedCount = selectableChildren.filter((c) => c.isSelected).length;\n const indeterminateCount = selectableChildren.filter(\n (c) => c.isIndeterminate,\n ).length;\n\n // If any child is indeterminate, parent is indeterminate\n if (indeterminateCount > 0) {\n return {\n isSelected: false,\n isIndeterminate: true,\n };\n }\n\n // All children selected\n if (selectedCount === selectableChildren.length) {\n return {\n isSelected: true,\n isIndeterminate: false,\n };\n }\n\n // No children selected\n if (selectedCount === 0) {\n return {\n isSelected: false,\n isIndeterminate: false,\n };\n }\n\n // Some children selected (indeterminate)\n return {\n isSelected: false,\n isIndeterminate: true,\n };\n }\n\n /**\n * Sync cascade state for parents after a move operation\n */\n syncParentsAfterMove(oldParents: Set<Key>, newParent: Key | null): void {\n // Update old parents (lost children)\n for (const parentKey of oldParents) {\n try {\n const parent = this.get(parentKey);\n const newState = this.computeSelectionState(parent);\n\n this.set(parentKey, {\n ...parent,\n isSelected: newState.isSelected,\n isIndeterminate: newState.isIndeterminate,\n });\n\n // Bubble up to ancestors\n if (parent.parentKey) {\n this.bubbleUpSelection(parentKey);\n }\n } catch {\n // Parent doesn't exist, skip\n }\n }\n\n // Update new parent (gained children)\n if (newParent) {\n try {\n const parent = this.get(newParent);\n const newState = this.computeSelectionState(parent);\n\n this.set(newParent, {\n ...parent,\n isSelected: newState.isSelected,\n isIndeterminate: newState.isIndeterminate,\n });\n\n // Bubble up to ancestors\n if (parent.parentKey) {\n this.bubbleUpSelection(newParent);\n }\n } catch {\n // Parent doesn't exist, skip\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -48,7 +48,8 @@ import "client-only";
48
48
  * ```
49
49
  */
50
50
  declare function useTreeActions<T>({
51
- nodes
51
+ nodes,
52
+ selectionCascade
52
53
  }: UseTreeActionsOptions<T>): TreeActions<T>;
53
54
  //#endregion
54
55
  export { useTreeActions };
@@ -51,11 +51,41 @@ import { useUpdateEffect } from "@react-aria/utils";
51
51
  * ]);
52
52
  * ```
53
53
  */
54
- function useTreeActions({ nodes }) {
54
+ function useTreeActions({ nodes, selectionCascade = false }) {
55
55
  const cache = useRef(new Cache(nodes)).current;
56
56
  useUpdateEffect(() => {
57
57
  cache.rebuild(nodes);
58
58
  }, [nodes]);
59
+ /** HELPERS **/
60
+ /**
61
+ * Collects parent keys for a set of nodes before a move operation
62
+ */
63
+ function getParents(keys) {
64
+ const prevParents = /* @__PURE__ */ new Set();
65
+ for (const key of keys) {
66
+ const node = cache.getNode(key);
67
+ if (node.parentKey) prevParents.add(node.parentKey);
68
+ }
69
+ return prevParents;
70
+ }
71
+ /** CASCADE SELECTION **/
72
+ /**
73
+ * Selection change with cascade logic
74
+ */
75
+ function onSelectionChangeCascade(keys) {
76
+ const previouslySelected = /* @__PURE__ */ new Set();
77
+ for (const k of cache.getAllKeys()) try {
78
+ if (cache.getNode(k).isSelected) previouslySelected.add(k);
79
+ } catch {}
80
+ const validKeys = [...keys].filter((k) => k != null);
81
+ const added = validKeys.filter((k) => !previouslySelected.has(k));
82
+ const removed = [...previouslySelected].filter((k) => !validKeys.includes(k));
83
+ for (const key of added) cache.cascadeSelection(key, true);
84
+ for (const key of removed) cache.cascadeSelection(key, false);
85
+ const affectedKeys = new Set([...added, ...removed]);
86
+ for (const key of affectedKeys) cache.bubbleUpSelection(key);
87
+ return cache.toTree();
88
+ }
59
89
  /** GET NODE **/
60
90
  function getNode(key) {
61
91
  return cache.getNode(key);
@@ -75,15 +105,35 @@ function useTreeActions({ nodes }) {
75
105
  }
76
106
  /** MOVE NODES **/
77
107
  function moveAfter(target, keys) {
108
+ if (!selectionCascade) {
109
+ cache.moveNodes(target, keys, "after");
110
+ return cache.toTree();
111
+ }
112
+ const prevParents = getParents(keys);
113
+ const newParent = cache.getParentForPosition(target, "after");
78
114
  cache.moveNodes(target, keys, "after");
115
+ cache.syncParentsAfterMove(prevParents, newParent);
79
116
  return cache.toTree();
80
117
  }
81
118
  function moveBefore(target, keys) {
119
+ if (!selectionCascade) {
120
+ cache.moveNodes(target, keys, "before");
121
+ return cache.toTree();
122
+ }
123
+ const prevParents = getParents(keys);
124
+ const newParent = cache.getParentForPosition(target, "before");
82
125
  cache.moveNodes(target, keys, "before");
126
+ cache.syncParentsAfterMove(prevParents, newParent);
83
127
  return cache.toTree();
84
128
  }
85
129
  function moveInto(target, keys) {
130
+ if (!selectionCascade) {
131
+ for (const key of keys) cache.moveNode(target, key, 0);
132
+ return cache.toTree();
133
+ }
134
+ const prevParents = getParents(keys);
86
135
  for (const key of keys) cache.moveNode(target, key, 0);
136
+ cache.syncParentsAfterMove(prevParents, target);
87
137
  return cache.toTree();
88
138
  }
89
139
  /** UPDATE NODES **/
@@ -99,22 +149,31 @@ function useTreeActions({ nodes }) {
99
149
  }
100
150
  /** SELECTION **/
101
151
  function onSelectionChange(keys) {
102
- unselectAll();
103
- for (const key of keys) {
104
- const node = cache.getNode(key);
105
- cache.setNode(node.key, {
106
- ...node,
107
- isSelected: true
108
- });
152
+ if (!selectionCascade) {
153
+ unselectAll();
154
+ for (const key of keys) {
155
+ const node = cache.getNode(key);
156
+ cache.setNode(node.key, {
157
+ ...node,
158
+ isSelected: true
159
+ });
160
+ }
161
+ return cache.toTree();
109
162
  }
110
- return cache.toTree();
163
+ return onSelectionChangeCascade(keys);
111
164
  }
112
165
  function selectAll() {
113
- cache.setAllNodes({ isSelected: true });
166
+ cache.setAllNodes({
167
+ isSelected: true,
168
+ isIndeterminate: false
169
+ });
114
170
  return cache.toTree();
115
171
  }
116
172
  function unselectAll() {
117
- cache.setAllNodes({ isSelected: false });
173
+ cache.setAllNodes({
174
+ isSelected: false,
175
+ isIndeterminate: false
176
+ });
118
177
  return cache.toTree();
119
178
  }
120
179
  /** EXPANSION **/
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["nodes"],"sources":["../../../../src/hooks/use-tree/actions/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\n\nimport 'client-only';\nimport { useUpdateEffect } from '@react-aria/utils';\nimport { useRef } from 'react';\nimport { Cache } from './cache';\nimport type { Key } from '@react-types/shared';\nimport type {\n TreeActions,\n TreeData,\n TreeNode,\n TreeNodeBase,\n UseTreeActionsOptions,\n} from '../types';\n\n/**\n * Stateless hook that transforms tree data according to actions\n * it takes in nodes and returns a new version of the tree.\n *\n * Note: each operation returns the whole tree. Future iterations\n * might want to return only the changed portion of the tree.\n *\n * @param options - {@link UseTreeActionsOptions}\n * @param options.nodes - Current tree nodes to operate on.\n * @returns {@link TreeActions} Object containing all tree manipulation functions.\n *\n * @example\n * ```tsx\n * const treeActions = useTreeActions({\n * nodes: [\n * {\n * key: 'root',\n * label: 'Root',\n * children: [\n * { key: 'child1', label: 'Child 1' },\n * { key: 'child2', label: 'Child 2' }\n * ]\n * }\n * ]\n * });\n *\n * // Use tree actions\n * const updatedTree = treeActions.insertAfter('child1', [\n * { key: 'newChild', label: 'New Child' }\n * ]);\n * ```\n */\nexport function useTreeActions<T>({\n nodes,\n}: UseTreeActionsOptions<T>): TreeActions<T> {\n const cache = useRef(new Cache<T>(nodes)).current;\n\n useUpdateEffect(() => {\n cache.rebuild(nodes);\n }, [nodes]);\n\n /** GET NODE **/\n function getNode(key: Key) {\n return cache.getNode(key);\n }\n\n /** INSERT NODES **/\n function insertAfter(\n target: Key | null,\n nodes: TreeNode<T>[],\n ): TreeNode<T>[] {\n cache.addNodes(target, nodes, 'after');\n\n return cache.toTree(true);\n }\n\n function insertBefore(\n target: Key | null,\n nodes: TreeNode<T>[],\n ): TreeNode<T>[] {\n cache.addNodes(target, nodes, 'before');\n\n return cache.toTree(true);\n }\n\n function insertInto(target: Key | null, nodes: TreeNode<T>[]): TreeNode<T>[] {\n for (const node of nodes) {\n cache.insertNode(target, node, 0);\n }\n\n return cache.toTree(true);\n }\n\n /** MOVE NODES **/\n function moveAfter(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n cache.moveNodes(target, keys, 'after');\n\n return cache.toTree();\n }\n\n function moveBefore(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n cache.moveNodes(target, keys, 'before');\n\n return cache.toTree();\n }\n\n function moveInto(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n for (const key of keys) {\n cache.moveNode(target, key, 0);\n }\n\n return cache.toTree();\n }\n\n /** UPDATE NODES **/\n function updateNode(\n key: Key,\n callback: (node: TreeNodeBase<T>) => TreeNodeBase<T>,\n ): TreeNode<T>[] {\n const node = cache.getNode(key);\n\n cache.setNode(key, callback(node));\n\n return cache.toTree(true);\n }\n\n /** REMOVE NODES **/\n function remove(keys: Set<Key>): TreeNode<T>[] {\n for (const key of keys.values()) {\n cache.deleteNode(key);\n }\n\n return cache.toTree(true);\n }\n\n /** SELECTION **/\n function onSelectionChange(keys: Set<Key>): TreeNode<T>[] {\n unselectAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n\n cache.setNode(node.key, {\n ...node,\n isSelected: true,\n });\n }\n\n return cache.toTree();\n }\n\n function selectAll(): TreeNode<T>[] {\n cache.setAllNodes({ isSelected: true });\n\n return cache.toTree();\n }\n\n function unselectAll(): TreeNode<T>[] {\n cache.setAllNodes({ isSelected: false });\n\n return cache.toTree();\n }\n\n /** EXPANSION **/\n function onExpandedChange(keys: Set<Key>): TreeNode<T>[] {\n collapseAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n\n cache.setNode(node.key, {\n ...node,\n isExpanded: true,\n });\n }\n\n return cache.toTree();\n }\n\n function expandAll(): TreeNode<T>[] {\n cache.setAllNodes({ isExpanded: true });\n\n return cache.toTree();\n }\n\n function collapseAll(): TreeNode<T>[] {\n cache.setAllNodes({ isExpanded: false });\n\n return cache.toTree();\n }\n\n /** VISIBILITY **/\n function onVisibilityChange(keys: Set<Key>): TreeData<T> {\n hideAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n cache.setNode(node.key, {\n ...node,\n isVisible: true,\n });\n }\n return cache.toTree(true);\n }\n\n function revealAll(): TreeNode<T>[] {\n cache.setAllNodes({ isVisible: true });\n\n return cache.toTree(true);\n }\n\n function hideAll(): TreeNode<T>[] {\n cache.setAllNodes({ isVisible: false });\n\n return cache.toTree(true);\n }\n\n return {\n getNode,\n insertAfter,\n insertBefore,\n insertInto,\n moveAfter,\n moveBefore,\n moveInto,\n remove,\n updateNode,\n\n // Expansion\n collapseAll,\n expandAll,\n onExpandedChange,\n\n // Selection\n selectAll,\n unselectAll,\n onSelectionChange,\n\n // Visibility\n hideAll,\n revealAll,\n onVisibilityChange,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAgB,eAAkB,EAChC,SAC2C;CAC3C,MAAM,QAAQ,OAAO,IAAI,MAAS,MAAM,CAAC,CAAC;AAE1C,uBAAsB;AACpB,QAAM,QAAQ,MAAM;IACnB,CAAC,MAAM,CAAC;;CAGX,SAAS,QAAQ,KAAU;AACzB,SAAO,MAAM,QAAQ,IAAI;;;CAI3B,SAAS,YACP,QACA,SACe;AACf,QAAM,SAAS,QAAQA,SAAO,QAAQ;AAEtC,SAAO,MAAM,OAAO,KAAK;;CAG3B,SAAS,aACP,QACA,SACe;AACf,QAAM,SAAS,QAAQA,SAAO,SAAS;AAEvC,SAAO,MAAM,OAAO,KAAK;;CAG3B,SAAS,WAAW,QAAoB,SAAqC;AAC3E,OAAK,MAAM,QAAQA,QACjB,OAAM,WAAW,QAAQ,MAAM,EAAE;AAGnC,SAAO,MAAM,OAAO,KAAK;;;CAI3B,SAAS,UAAU,QAAoB,MAA+B;AACpE,QAAM,UAAU,QAAQ,MAAM,QAAQ;AAEtC,SAAO,MAAM,QAAQ;;CAGvB,SAAS,WAAW,QAAoB,MAA+B;AACrE,QAAM,UAAU,QAAQ,MAAM,SAAS;AAEvC,SAAO,MAAM,QAAQ;;CAGvB,SAAS,SAAS,QAAoB,MAA+B;AACnE,OAAK,MAAM,OAAO,KAChB,OAAM,SAAS,QAAQ,KAAK,EAAE;AAGhC,SAAO,MAAM,QAAQ;;;CAIvB,SAAS,WACP,KACA,UACe;EACf,MAAM,OAAO,MAAM,QAAQ,IAAI;AAE/B,QAAM,QAAQ,KAAK,SAAS,KAAK,CAAC;AAElC,SAAO,MAAM,OAAO,KAAK;;;CAI3B,SAAS,OAAO,MAA+B;AAC7C,OAAK,MAAM,OAAO,KAAK,QAAQ,CAC7B,OAAM,WAAW,IAAI;AAGvB,SAAO,MAAM,OAAO,KAAK;;;CAI3B,SAAS,kBAAkB,MAA+B;AACxD,eAAa;AAEb,OAAK,MAAM,OAAO,MAAM;GACtB,MAAM,OAAO,MAAM,QAAQ,IAAI;AAE/B,SAAM,QAAQ,KAAK,KAAK;IACtB,GAAG;IACH,YAAY;IACb,CAAC;;AAGJ,SAAO,MAAM,QAAQ;;CAGvB,SAAS,YAA2B;AAClC,QAAM,YAAY,EAAE,YAAY,MAAM,CAAC;AAEvC,SAAO,MAAM,QAAQ;;CAGvB,SAAS,cAA6B;AACpC,QAAM,YAAY,EAAE,YAAY,OAAO,CAAC;AAExC,SAAO,MAAM,QAAQ;;;CAIvB,SAAS,iBAAiB,MAA+B;AACvD,eAAa;AAEb,OAAK,MAAM,OAAO,MAAM;GACtB,MAAM,OAAO,MAAM,QAAQ,IAAI;AAE/B,SAAM,QAAQ,KAAK,KAAK;IACtB,GAAG;IACH,YAAY;IACb,CAAC;;AAGJ,SAAO,MAAM,QAAQ;;CAGvB,SAAS,YAA2B;AAClC,QAAM,YAAY,EAAE,YAAY,MAAM,CAAC;AAEvC,SAAO,MAAM,QAAQ;;CAGvB,SAAS,cAA6B;AACpC,QAAM,YAAY,EAAE,YAAY,OAAO,CAAC;AAExC,SAAO,MAAM,QAAQ;;;CAIvB,SAAS,mBAAmB,MAA6B;AACvD,WAAS;AAET,OAAK,MAAM,OAAO,MAAM;GACtB,MAAM,OAAO,MAAM,QAAQ,IAAI;AAC/B,SAAM,QAAQ,KAAK,KAAK;IACtB,GAAG;IACH,WAAW;IACZ,CAAC;;AAEJ,SAAO,MAAM,OAAO,KAAK;;CAG3B,SAAS,YAA2B;AAClC,QAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAEtC,SAAO,MAAM,OAAO,KAAK;;CAG3B,SAAS,UAAyB;AAChC,QAAM,YAAY,EAAE,WAAW,OAAO,CAAC;AAEvC,SAAO,MAAM,OAAO,KAAK;;AAG3B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EAGA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"index.js","names":["nodes"],"sources":["../../../../src/hooks/use-tree/actions/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\n\nimport 'client-only';\nimport { useUpdateEffect } from '@react-aria/utils';\nimport { useRef } from 'react';\nimport { Cache } from './cache';\nimport type { Key } from '@react-types/shared';\nimport type {\n TreeActions,\n TreeData,\n TreeNode,\n TreeNodeBase,\n UseTreeActionsOptions,\n} from '../types';\n\n/**\n * Stateless hook that transforms tree data according to actions\n * it takes in nodes and returns a new version of the tree.\n *\n * Note: each operation returns the whole tree. Future iterations\n * might want to return only the changed portion of the tree.\n *\n * @param options - {@link UseTreeActionsOptions}\n * @param options.nodes - Current tree nodes to operate on.\n * @returns {@link TreeActions} Object containing all tree manipulation functions.\n *\n * @example\n * ```tsx\n * const treeActions = useTreeActions({\n * nodes: [\n * {\n * key: 'root',\n * label: 'Root',\n * children: [\n * { key: 'child1', label: 'Child 1' },\n * { key: 'child2', label: 'Child 2' }\n * ]\n * }\n * ]\n * });\n *\n * // Use tree actions\n * const updatedTree = treeActions.insertAfter('child1', [\n * { key: 'newChild', label: 'New Child' }\n * ]);\n * ```\n */\nexport function useTreeActions<T>({\n nodes,\n selectionCascade = false,\n}: UseTreeActionsOptions<T>): TreeActions<T> {\n const cache = useRef(new Cache<T>(nodes)).current;\n\n useUpdateEffect(() => {\n cache.rebuild(nodes);\n }, [nodes]);\n\n /** HELPERS **/\n\n /**\n * Collects parent keys for a set of nodes before a move operation\n */\n function getParents(keys: Set<Key>): Set<Key> {\n const prevParents = new Set<Key>();\n for (const key of keys) {\n const node = cache.getNode(key);\n if (node.parentKey) {\n prevParents.add(node.parentKey);\n }\n }\n return prevParents;\n }\n\n /** CASCADE SELECTION **/\n\n /**\n * Selection change with cascade logic\n */\n function onSelectionChangeCascade(keys: Set<Key>): TreeNode<T>[] {\n // Detect changes\n const previouslySelected = new Set<Key>();\n for (const k of cache.getAllKeys()) {\n try {\n const node = cache.getNode(k);\n if (node.isSelected) {\n previouslySelected.add(k);\n }\n } catch {\n // Skip invalid keys\n }\n }\n\n const validKeys = [...keys].filter((k) => k != null);\n const added = validKeys.filter((k) => !previouslySelected.has(k));\n const removed = [...previouslySelected].filter(\n (k) => !validKeys.includes(k),\n );\n\n // Cascade down\n for (const key of added) {\n cache.cascadeSelection(key, true);\n }\n\n for (const key of removed) {\n cache.cascadeSelection(key, false);\n }\n\n // Bubble up\n const affectedKeys = new Set([...added, ...removed]);\n for (const key of affectedKeys) {\n cache.bubbleUpSelection(key);\n }\n\n return cache.toTree();\n }\n\n /** GET NODE **/\n function getNode(key: Key) {\n return cache.getNode(key);\n }\n\n /** INSERT NODES **/\n function insertAfter(\n target: Key | null,\n nodes: TreeNode<T>[],\n ): TreeNode<T>[] {\n cache.addNodes(target, nodes, 'after');\n\n return cache.toTree(true);\n }\n\n function insertBefore(\n target: Key | null,\n nodes: TreeNode<T>[],\n ): TreeNode<T>[] {\n cache.addNodes(target, nodes, 'before');\n\n return cache.toTree(true);\n }\n\n function insertInto(target: Key | null, nodes: TreeNode<T>[]): TreeNode<T>[] {\n for (const node of nodes) {\n cache.insertNode(target, node, 0);\n }\n\n return cache.toTree(true);\n }\n\n /** MOVE NODES **/\n function moveAfter(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n if (!selectionCascade) {\n cache.moveNodes(target, keys, 'after');\n return cache.toTree();\n }\n\n // Collect old parents before move\n const prevParents = getParents(keys);\n\n // Get new parent before move\n const newParent = cache.getParentForPosition(target, 'after');\n\n // Perform move\n cache.moveNodes(target, keys, 'after');\n\n // Sync cascade state\n cache.syncParentsAfterMove(prevParents, newParent);\n\n return cache.toTree();\n }\n\n function moveBefore(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n if (!selectionCascade) {\n cache.moveNodes(target, keys, 'before');\n return cache.toTree();\n }\n\n // Collect old parents before move\n const prevParents = getParents(keys);\n\n // Get new parent before move\n const newParent = cache.getParentForPosition(target, 'before');\n\n // Perform move\n cache.moveNodes(target, keys, 'before');\n\n // Sync cascade state\n cache.syncParentsAfterMove(prevParents, newParent);\n\n return cache.toTree();\n }\n\n function moveInto(target: Key | null, keys: Set<Key>): TreeNode<T>[] {\n if (!selectionCascade) {\n for (const key of keys) {\n cache.moveNode(target, key, 0);\n }\n return cache.toTree();\n }\n\n // Collect old parents before move\n const prevParents = getParents(keys);\n\n // Perform move\n for (const key of keys) {\n cache.moveNode(target, key, 0);\n }\n\n // Sync cascade state (target IS the new parent for moveInto)\n cache.syncParentsAfterMove(prevParents, target);\n\n return cache.toTree();\n }\n\n /** UPDATE NODES **/\n function updateNode(\n key: Key,\n callback: (node: TreeNodeBase<T>) => TreeNodeBase<T>,\n ): TreeNode<T>[] {\n const node = cache.getNode(key);\n\n cache.setNode(key, callback(node));\n\n return cache.toTree(true);\n }\n\n /** REMOVE NODES **/\n function remove(keys: Set<Key>): TreeNode<T>[] {\n for (const key of keys.values()) {\n cache.deleteNode(key);\n }\n\n return cache.toTree(true);\n }\n\n /** SELECTION **/\n function onSelectionChange(keys: Set<Key>): TreeNode<T>[] {\n if (!selectionCascade) {\n // Current behavior (no cascade)\n unselectAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n\n cache.setNode(node.key, {\n ...node,\n isSelected: true,\n });\n }\n\n return cache.toTree();\n }\n\n // Cascade behavior\n return onSelectionChangeCascade(keys);\n }\n\n function selectAll(): TreeNode<T>[] {\n cache.setAllNodes({ isSelected: true, isIndeterminate: false });\n\n return cache.toTree();\n }\n\n function unselectAll(): TreeNode<T>[] {\n cache.setAllNodes({ isSelected: false, isIndeterminate: false });\n\n return cache.toTree();\n }\n\n /** EXPANSION **/\n function onExpandedChange(keys: Set<Key>): TreeNode<T>[] {\n collapseAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n\n cache.setNode(node.key, {\n ...node,\n isExpanded: true,\n });\n }\n\n return cache.toTree();\n }\n\n function expandAll(): TreeNode<T>[] {\n cache.setAllNodes({ isExpanded: true });\n\n return cache.toTree();\n }\n\n function collapseAll(): TreeNode<T>[] {\n cache.setAllNodes({ isExpanded: false });\n\n return cache.toTree();\n }\n\n /** VISIBILITY **/\n function onVisibilityChange(keys: Set<Key>): TreeData<T> {\n hideAll();\n\n for (const key of keys) {\n const node = cache.getNode(key);\n cache.setNode(node.key, {\n ...node,\n isVisible: true,\n });\n }\n return cache.toTree(true);\n }\n\n function revealAll(): TreeNode<T>[] {\n cache.setAllNodes({ isVisible: true });\n\n return cache.toTree(true);\n }\n\n function hideAll(): TreeNode<T>[] {\n cache.setAllNodes({ isVisible: false });\n\n return cache.toTree(true);\n }\n\n return {\n getNode,\n insertAfter,\n insertBefore,\n insertInto,\n moveAfter,\n moveBefore,\n moveInto,\n remove,\n updateNode,\n\n // Expansion\n collapseAll,\n expandAll,\n onExpandedChange,\n\n // Selection\n selectAll,\n unselectAll,\n onSelectionChange,\n\n // Visibility\n hideAll,\n revealAll,\n onVisibilityChange,\n };\n}\n"],"mappings":"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"}
@@ -14,15 +14,34 @@ import { UseTreeState, UseTreeStateOptions } from "../types.js";
14
14
  import "client-only";
15
15
 
16
16
  //#region src/hooks/use-tree/state/index.d.ts
17
+
17
18
  /**
18
19
  * Stateful tree manager with drag-and-drop, selection, expansion, and visibility controls
19
20
  *
20
21
  * @param options - {@link UseTreeStateOptions}
21
22
  * @param options.items - Initial tree node items.
23
+ * @param options.selectionCascade - Enable cascade selection mode. When true, selecting a parent
24
+ * automatically selects all descendants, and parent checkboxes show indeterminate state when
25
+ * partially selected. Default: false.
22
26
  * @returns {@link UseTreeState} Tree state, actions, and drag-and-drop configuration.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * // Basic tree without cascade
31
+ * const { nodes, actions } = useTreeState({
32
+ * items: myTree,
33
+ * });
34
+ *
35
+ * // Tree with cascade selection (file system-like behavior)
36
+ * const { nodes, actions } = useTreeState({
37
+ * items: fileSystemTree,
38
+ * selectionCascade: true,
39
+ * });
40
+ * ```
23
41
  */
24
42
  declare function useTreeState<T>({
25
- items
43
+ items,
44
+ selectionCascade
26
45
  }: UseTreeStateOptions<T>): UseTreeState<T>;
27
46
  //#endregion
28
47
  export { useTreeState };
@@ -24,11 +24,31 @@ import { useState } from "react";
24
24
  *
25
25
  * @param options - {@link UseTreeStateOptions}
26
26
  * @param options.items - Initial tree node items.
27
+ * @param options.selectionCascade - Enable cascade selection mode. When true, selecting a parent
28
+ * automatically selects all descendants, and parent checkboxes show indeterminate state when
29
+ * partially selected. Default: false.
27
30
  * @returns {@link UseTreeState} Tree state, actions, and drag-and-drop configuration.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * // Basic tree without cascade
35
+ * const { nodes, actions } = useTreeState({
36
+ * items: myTree,
37
+ * });
38
+ *
39
+ * // Tree with cascade selection (file system-like behavior)
40
+ * const { nodes, actions } = useTreeState({
41
+ * items: fileSystemTree,
42
+ * selectionCascade: true,
43
+ * });
44
+ * ```
28
45
  */
29
- function useTreeState({ items }) {
46
+ function useTreeState({ items, selectionCascade = false }) {
30
47
  const [nodes, setNodes] = useState(items);
31
- const actions = useTreeActions({ nodes });
48
+ const actions = useTreeActions({
49
+ nodes,
50
+ selectionCascade
51
+ });
32
52
  const dragAndDropConfig = {
33
53
  getItems: (keys) => [...keys].map((key) => {
34
54
  const node = actions.getNode(key);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["dragAndDropConfig: DragAndDropConfig","items"],"sources":["../../../../src/hooks/use-tree/state/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\n\nimport 'client-only';\nimport { useState } from 'react';\nimport { useTreeActions } from '../actions';\nimport { processDroppedItems } from './utils';\nimport type {\n DragItem,\n DroppableCollectionInsertDropEvent,\n DroppableCollectionRootDropEvent,\n Key,\n Selection,\n} from '@react-types/shared';\nimport type {\n DragAndDropConfig,\n UseTreeState,\n UseTreeStateOptions,\n} from '../types';\n\n/**\n * Stateful tree manager with drag-and-drop, selection, expansion, and visibility controls\n *\n * @param options - {@link UseTreeStateOptions}\n * @param options.items - Initial tree node items.\n * @returns {@link UseTreeState} Tree state, actions, and drag-and-drop configuration.\n */\nexport function useTreeState<T>({\n items,\n}: UseTreeStateOptions<T>): UseTreeState<T> {\n const [nodes, setNodes] = useState(items);\n const actions = useTreeActions<T>({ nodes });\n\n const dragAndDropConfig: DragAndDropConfig = {\n getItems: (keys: Set<Key>): DragItem[] =>\n [...keys].map((key) => {\n const node = actions.getNode(key);\n\n return {\n key: `${key}`,\n 'text/plain': JSON.stringify(node),\n };\n }),\n onInsert: ({ items, target }: DroppableCollectionInsertDropEvent) => {\n (async () => {\n const processedItems = await processDroppedItems(\n items,\n dragAndDropConfig.acceptedDragTypes ?? [],\n );\n\n setNodes(\n actions.remove(new Set(processedItems.map((item) => item.id))),\n );\n\n if (target.dropPosition === 'before') {\n setNodes(actions.insertBefore(target.key, processedItems));\n } else if (target.dropPosition === 'after') {\n setNodes(actions.insertAfter(target.key, processedItems));\n }\n })();\n },\n onRootDrop: ({ items }: DroppableCollectionRootDropEvent) => {\n (async () => {\n const processedItems = await processDroppedItems(\n items,\n dragAndDropConfig.acceptedDragTypes ?? [],\n );\n\n setNodes(\n actions.remove(new Set(processedItems.map((item) => item.key))),\n );\n setNodes(actions.insertAfter(null, processedItems));\n })();\n },\n onMove: (e) => {\n if (e.target.dropPosition === 'before') {\n setNodes(actions.moveBefore(e.target.key, e.keys));\n } else if (e.target.dropPosition === 'after') {\n setNodes(actions.moveAfter(e.target.key, e.keys));\n } else if (e.target.dropPosition === 'on') {\n const targetNode = actions.getNode(e.target.key);\n if (targetNode) {\n setNodes(actions.moveInto(e.target.key, e.keys));\n }\n }\n },\n };\n\n function collapseAll() {\n setNodes(actions.collapseAll());\n }\n\n function expandAll() {\n setNodes(actions.expandAll());\n }\n\n function onExpandedChange(keys: Set<Key>) {\n setNodes(actions.onExpandedChange(keys));\n }\n\n function selectAll() {\n setNodes(actions.selectAll());\n }\n\n function unselectAll() {\n setNodes(actions.unselectAll());\n }\n\n function onSelectionChange(keys: Selection) {\n if (keys === 'all') {\n return selectAll();\n }\n\n setNodes(actions.onSelectionChange(keys));\n }\n\n function hideAll() {\n setNodes(actions.hideAll());\n }\n\n function revealAll() {\n setNodes(actions.revealAll());\n }\n\n function onVisibilityChange(keys: Set<Key>) {\n setNodes(actions.onVisibilityChange(keys));\n }\n\n return {\n nodes,\n actions: {\n // Expansion\n collapseAll,\n expandAll,\n onExpandedChange,\n\n // Selection\n selectAll,\n unselectAll,\n onSelectionChange,\n\n // Visibility\n hideAll,\n revealAll,\n onVisibilityChange,\n },\n dragAndDropConfig,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,SAAgB,aAAgB,EAC9B,SAC0C;CAC1C,MAAM,CAAC,OAAO,YAAY,SAAS,MAAM;CACzC,MAAM,UAAU,eAAkB,EAAE,OAAO,CAAC;CAE5C,MAAMA,oBAAuC;EAC3C,WAAW,SACT,CAAC,GAAG,KAAK,CAAC,KAAK,QAAQ;GACrB,MAAM,OAAO,QAAQ,QAAQ,IAAI;AAEjC,UAAO;IACL,KAAK,GAAG;IACR,cAAc,KAAK,UAAU,KAAK;IACnC;IACD;EACJ,WAAW,EAAE,gBAAO,aAAiD;AACnE,IAAC,YAAY;IACX,MAAM,iBAAiB,MAAM,oBAC3BC,SACA,kBAAkB,qBAAqB,EAAE,CAC1C;AAED,aACE,QAAQ,OAAO,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,GAAG,CAAC,CAAC,CAC/D;AAED,QAAI,OAAO,iBAAiB,SAC1B,UAAS,QAAQ,aAAa,OAAO,KAAK,eAAe,CAAC;aACjD,OAAO,iBAAiB,QACjC,UAAS,QAAQ,YAAY,OAAO,KAAK,eAAe,CAAC;OAEzD;;EAEN,aAAa,EAAE,qBAA8C;AAC3D,IAAC,YAAY;IACX,MAAM,iBAAiB,MAAM,oBAC3BA,SACA,kBAAkB,qBAAqB,EAAE,CAC1C;AAED,aACE,QAAQ,OAAO,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,CAChE;AACD,aAAS,QAAQ,YAAY,MAAM,eAAe,CAAC;OACjD;;EAEN,SAAS,MAAM;AACb,OAAI,EAAE,OAAO,iBAAiB,SAC5B,UAAS,QAAQ,WAAW,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;YACzC,EAAE,OAAO,iBAAiB,QACnC,UAAS,QAAQ,UAAU,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;YACxC,EAAE,OAAO,iBAAiB,MAEnC;QADmB,QAAQ,QAAQ,EAAE,OAAO,IAAI,CAE9C,UAAS,QAAQ,SAAS,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;;;EAIvD;CAED,SAAS,cAAc;AACrB,WAAS,QAAQ,aAAa,CAAC;;CAGjC,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,iBAAiB,MAAgB;AACxC,WAAS,QAAQ,iBAAiB,KAAK,CAAC;;CAG1C,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,cAAc;AACrB,WAAS,QAAQ,aAAa,CAAC;;CAGjC,SAAS,kBAAkB,MAAiB;AAC1C,MAAI,SAAS,MACX,QAAO,WAAW;AAGpB,WAAS,QAAQ,kBAAkB,KAAK,CAAC;;CAG3C,SAAS,UAAU;AACjB,WAAS,QAAQ,SAAS,CAAC;;CAG7B,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,mBAAmB,MAAgB;AAC1C,WAAS,QAAQ,mBAAmB,KAAK,CAAC;;AAG5C,QAAO;EACL;EACA,SAAS;GAEP;GACA;GACA;GAGA;GACA;GACA;GAGA;GACA;GACA;GACD;EACD;EACD"}
1
+ {"version":3,"file":"index.js","names":["dragAndDropConfig: DragAndDropConfig","items"],"sources":["../../../../src/hooks/use-tree/state/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\n\nimport 'client-only';\nimport { useState } from 'react';\nimport { useTreeActions } from '../actions';\nimport { processDroppedItems } from './utils';\nimport type {\n DragItem,\n DroppableCollectionInsertDropEvent,\n DroppableCollectionRootDropEvent,\n Key,\n Selection,\n} from '@react-types/shared';\nimport type {\n DragAndDropConfig,\n UseTreeState,\n UseTreeStateOptions,\n} from '../types';\n\n/**\n * Stateful tree manager with drag-and-drop, selection, expansion, and visibility controls\n *\n * @param options - {@link UseTreeStateOptions}\n * @param options.items - Initial tree node items.\n * @param options.selectionCascade - Enable cascade selection mode. When true, selecting a parent\n * automatically selects all descendants, and parent checkboxes show indeterminate state when\n * partially selected. Default: false.\n * @returns {@link UseTreeState} Tree state, actions, and drag-and-drop configuration.\n *\n * @example\n * ```tsx\n * // Basic tree without cascade\n * const { nodes, actions } = useTreeState({\n * items: myTree,\n * });\n *\n * // Tree with cascade selection (file system-like behavior)\n * const { nodes, actions } = useTreeState({\n * items: fileSystemTree,\n * selectionCascade: true,\n * });\n * ```\n */\nexport function useTreeState<T>({\n items,\n selectionCascade = false,\n}: UseTreeStateOptions<T>): UseTreeState<T> {\n const [nodes, setNodes] = useState(items);\n const actions = useTreeActions<T>({ nodes, selectionCascade });\n\n const dragAndDropConfig: DragAndDropConfig = {\n getItems: (keys: Set<Key>): DragItem[] =>\n [...keys].map((key) => {\n const node = actions.getNode(key);\n\n return {\n key: `${key}`,\n 'text/plain': JSON.stringify(node),\n };\n }),\n onInsert: ({ items, target }: DroppableCollectionInsertDropEvent) => {\n (async () => {\n const processedItems = await processDroppedItems(\n items,\n dragAndDropConfig.acceptedDragTypes ?? [],\n );\n\n setNodes(\n actions.remove(new Set(processedItems.map((item) => item.id))),\n );\n\n if (target.dropPosition === 'before') {\n setNodes(actions.insertBefore(target.key, processedItems));\n } else if (target.dropPosition === 'after') {\n setNodes(actions.insertAfter(target.key, processedItems));\n }\n })();\n },\n onRootDrop: ({ items }: DroppableCollectionRootDropEvent) => {\n (async () => {\n const processedItems = await processDroppedItems(\n items,\n dragAndDropConfig.acceptedDragTypes ?? [],\n );\n\n setNodes(\n actions.remove(new Set(processedItems.map((item) => item.key))),\n );\n setNodes(actions.insertAfter(null, processedItems));\n })();\n },\n onMove: (e) => {\n if (e.target.dropPosition === 'before') {\n setNodes(actions.moveBefore(e.target.key, e.keys));\n } else if (e.target.dropPosition === 'after') {\n setNodes(actions.moveAfter(e.target.key, e.keys));\n } else if (e.target.dropPosition === 'on') {\n const targetNode = actions.getNode(e.target.key);\n if (targetNode) {\n setNodes(actions.moveInto(e.target.key, e.keys));\n }\n }\n },\n };\n\n function collapseAll() {\n setNodes(actions.collapseAll());\n }\n\n function expandAll() {\n setNodes(actions.expandAll());\n }\n\n function onExpandedChange(keys: Set<Key>) {\n setNodes(actions.onExpandedChange(keys));\n }\n\n function selectAll() {\n setNodes(actions.selectAll());\n }\n\n function unselectAll() {\n setNodes(actions.unselectAll());\n }\n\n function onSelectionChange(keys: Selection) {\n if (keys === 'all') {\n return selectAll();\n }\n\n setNodes(actions.onSelectionChange(keys));\n }\n\n function hideAll() {\n setNodes(actions.hideAll());\n }\n\n function revealAll() {\n setNodes(actions.revealAll());\n }\n\n function onVisibilityChange(keys: Set<Key>) {\n setNodes(actions.onVisibilityChange(keys));\n }\n\n return {\n nodes,\n actions: {\n // Expansion\n collapseAll,\n expandAll,\n onExpandedChange,\n\n // Selection\n selectAll,\n unselectAll,\n onSelectionChange,\n\n // Visibility\n hideAll,\n revealAll,\n onVisibilityChange,\n },\n dragAndDropConfig,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,SAAgB,aAAgB,EAC9B,OACA,mBAAmB,SACuB;CAC1C,MAAM,CAAC,OAAO,YAAY,SAAS,MAAM;CACzC,MAAM,UAAU,eAAkB;EAAE;EAAO;EAAkB,CAAC;CAE9D,MAAMA,oBAAuC;EAC3C,WAAW,SACT,CAAC,GAAG,KAAK,CAAC,KAAK,QAAQ;GACrB,MAAM,OAAO,QAAQ,QAAQ,IAAI;AAEjC,UAAO;IACL,KAAK,GAAG;IACR,cAAc,KAAK,UAAU,KAAK;IACnC;IACD;EACJ,WAAW,EAAE,gBAAO,aAAiD;AACnE,IAAC,YAAY;IACX,MAAM,iBAAiB,MAAM,oBAC3BC,SACA,kBAAkB,qBAAqB,EAAE,CAC1C;AAED,aACE,QAAQ,OAAO,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,GAAG,CAAC,CAAC,CAC/D;AAED,QAAI,OAAO,iBAAiB,SAC1B,UAAS,QAAQ,aAAa,OAAO,KAAK,eAAe,CAAC;aACjD,OAAO,iBAAiB,QACjC,UAAS,QAAQ,YAAY,OAAO,KAAK,eAAe,CAAC;OAEzD;;EAEN,aAAa,EAAE,qBAA8C;AAC3D,IAAC,YAAY;IACX,MAAM,iBAAiB,MAAM,oBAC3BA,SACA,kBAAkB,qBAAqB,EAAE,CAC1C;AAED,aACE,QAAQ,OAAO,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,CAChE;AACD,aAAS,QAAQ,YAAY,MAAM,eAAe,CAAC;OACjD;;EAEN,SAAS,MAAM;AACb,OAAI,EAAE,OAAO,iBAAiB,SAC5B,UAAS,QAAQ,WAAW,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;YACzC,EAAE,OAAO,iBAAiB,QACnC,UAAS,QAAQ,UAAU,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;YACxC,EAAE,OAAO,iBAAiB,MAEnC;QADmB,QAAQ,QAAQ,EAAE,OAAO,IAAI,CAE9C,UAAS,QAAQ,SAAS,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC;;;EAIvD;CAED,SAAS,cAAc;AACrB,WAAS,QAAQ,aAAa,CAAC;;CAGjC,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,iBAAiB,MAAgB;AACxC,WAAS,QAAQ,iBAAiB,KAAK,CAAC;;CAG1C,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,cAAc;AACrB,WAAS,QAAQ,aAAa,CAAC;;CAGjC,SAAS,kBAAkB,MAAiB;AAC1C,MAAI,SAAS,MACX,QAAO,WAAW;AAGpB,WAAS,QAAQ,kBAAkB,KAAK,CAAC;;CAG3C,SAAS,UAAU;AACjB,WAAS,QAAQ,SAAS,CAAC;;CAG7B,SAAS,YAAY;AACnB,WAAS,QAAQ,WAAW,CAAC;;CAG/B,SAAS,mBAAmB,MAAgB;AAC1C,WAAS,QAAQ,mBAAmB,KAAK,CAAC;;AAG5C,QAAO;EACL;EACA,SAAS;GAEP;GACA;GACA;GAGA;GACA;GACA;GAGA;GACA;GACA;GACD;EACD;EACD"}
@@ -54,6 +54,13 @@ type DragAndDropConfig = {
54
54
  type UseTreeStateOptions<T> = {
55
55
  /** Initial root items in the tree. If omitted, will return an empty tree. */
56
56
  items: TreeNode<T>[];
57
+ /**
58
+ * Enable semantic cascade selection mode. When true, selecting a parent
59
+ * automatically selects all descendants, and parent state reflects children
60
+ * (selected/indeterminate/unselected). Only works with dynamic collections.
61
+ * @default false
62
+ */
63
+ selectionCascade?: boolean;
57
64
  };
58
65
  /** Return value from the useTreeState hook */
59
66
  type UseTreeState<T> = {
@@ -108,6 +115,8 @@ type TreeNodeBase<T> = {
108
115
  isVisible?: boolean;
109
116
  /** Computed actual visibility based on ancestors and self visibility **/
110
117
  isVisibleComputed?: boolean;
118
+ /** Computed indeterminate state for cascade selection (some but not all descendants selected) **/
119
+ isIndeterminate?: boolean;
111
120
  };
112
121
  type TreeNode<T> = TreeNodeBase<T> & {
113
122
  /** The key of the parent node. */
@@ -119,6 +128,11 @@ type TreeNode<T> = TreeNodeBase<T> & {
119
128
  type UseTreeActionsOptions<T> = {
120
129
  /** Current tree nodes to operate on */
121
130
  nodes: TreeNode<T>[];
131
+ /**
132
+ * Enable semantic cascade selection mode.
133
+ * @default false
134
+ */
135
+ selectionCascade?: boolean;
122
136
  };
123
137
  /**
124
138
  * Stateless collection of transform actions to simplify tree operations