@nvidia-elements/core 2.22.5 → 2.23.1

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 (304) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/accordion/accordion2.js +4 -4
  3. package/dist/alert/alert-group2.js +1 -1
  4. package/dist/alert/alert2.js +1 -1
  5. package/dist/avatar/avatar-group2.js +1 -1
  6. package/dist/avatar/avatar2.js +1 -1
  7. package/dist/badge/badge2.js +1 -1
  8. package/dist/breadcrumb/breadcrumb2.js +1 -1
  9. package/dist/bundle.d.ts +4 -0
  10. package/dist/bundles/index.d.ts +357 -1
  11. package/dist/bundles/index.js +14 -14
  12. package/dist/button/button2.js +1 -1
  13. package/dist/button-group/button-group2.js +1 -1
  14. package/dist/card/card2.js +4 -4
  15. package/dist/chat-message/chat-message2.js +1 -1
  16. package/dist/checkbox/checkbox-group2.js +1 -1
  17. package/dist/checkbox/checkbox2.js +1 -1
  18. package/dist/color/color2.js +6 -6
  19. package/dist/combobox/combobox2.js +1 -1
  20. package/dist/copy-button/copy-button2.js +1 -1
  21. package/dist/custom-elements-jsx.d.ts +189 -0
  22. package/dist/custom-elements-vue.d.ts +189 -0
  23. package/dist/custom-elements.json +6561 -339
  24. package/dist/data.html.json +133 -0
  25. package/dist/date/date2.js +6 -6
  26. package/dist/datetime/datetime2.js +6 -6
  27. package/dist/dialog/dialog-footer2.js +1 -1
  28. package/dist/dialog/dialog-header2.js +1 -1
  29. package/dist/dialog/dialog2.js +1 -1
  30. package/dist/divider/divider2.js +1 -1
  31. package/dist/dot/dot2.js +1 -1
  32. package/dist/drag-handle/drag-handle2.js +1 -1
  33. package/dist/drawer/drawer-content2.js +1 -1
  34. package/dist/drawer/drawer-footer2.js +1 -1
  35. package/dist/drawer/drawer-header2.js +1 -1
  36. package/dist/drawer/drawer2.js +1 -1
  37. package/dist/dropdown/dropdown-footer2.js +1 -1
  38. package/dist/dropdown/dropdown-header2.js +1 -1
  39. package/dist/dropdown/dropdown2.js +1 -1
  40. package/dist/dropdown-group/dropdown-group.js +1 -1
  41. package/dist/dropzone/dropzone2.js +1 -1
  42. package/dist/file/file2.js +1 -1
  43. package/dist/format-bytes/format-bytes2.js +1 -1
  44. package/dist/format-datetime/format-datetime2.js +1 -1
  45. package/dist/format-number/format-number2.js +1 -1
  46. package/dist/format-relative-time/format-relative-time2.js +1 -1
  47. package/dist/format-truncate/format-truncate2.js +1 -1
  48. package/dist/forms/control/control2.js +1 -1
  49. package/dist/forms/control-group/control-group2.js +1 -1
  50. package/dist/forms/control-message/control-message2.js +1 -1
  51. package/dist/forms/utils/layout.d.ts +0 -1
  52. package/dist/forms/utils/layout.js.map +1 -1
  53. package/dist/forms/utils/states.d.ts +0 -1
  54. package/dist/forms/utils/states.js.map +1 -1
  55. package/dist/gauge/gauge2.js +1 -1
  56. package/dist/ghost/define.d.ts +6 -0
  57. package/dist/ghost/define.js +6 -0
  58. package/dist/ghost/define.js.map +1 -0
  59. package/dist/ghost/ghost.d.ts +27 -0
  60. package/dist/ghost/ghost.examples.js +5 -0
  61. package/dist/ghost/ghost.examples.js.map +1 -0
  62. package/dist/ghost/ghost.examples.json +37 -0
  63. package/dist/ghost/ghost.js +5 -0
  64. package/dist/ghost/ghost.js.map +1 -0
  65. package/dist/ghost/ghost2.js +28 -0
  66. package/dist/ghost/ghost2.js.map +1 -0
  67. package/dist/ghost/index.d.ts +1 -0
  68. package/dist/ghost/index.js +1 -0
  69. package/dist/grid/cell/cell2.js +1 -1
  70. package/dist/grid/column/column2.js +1 -1
  71. package/dist/grid/footer/footer2.js +1 -1
  72. package/dist/grid/grid2.js +1 -1
  73. package/dist/grid/header/header2.js +1 -1
  74. package/dist/grid/placeholder/placeholder2.js +1 -1
  75. package/dist/grid/row/row2.js +1 -1
  76. package/dist/icon/icon2.js +2 -2
  77. package/dist/icon-button/icon-button2.js +1 -1
  78. package/dist/iframe/iframe2.js +1 -1
  79. package/dist/index.d.ts +4 -0
  80. package/dist/index.js +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/input/input-group2.js +1 -1
  83. package/dist/input/input2.js +1 -1
  84. package/dist/internal/controllers/keynav-spatial.controller.d.ts +0 -1
  85. package/dist/internal/controllers/keynav-spatial.controller.js.map +1 -1
  86. package/dist/internal/controllers/type-native-popover.utils.d.ts +0 -1
  87. package/dist/internal/controllers/type-native-popover.utils.js.map +1 -1
  88. package/dist/internal/index.d.ts +0 -1
  89. package/dist/internal/index.js +116 -128
  90. package/dist/internal/index.js.map +1 -1
  91. package/dist/internal/types/index.d.ts +37 -3
  92. package/dist/internal/types/index.js.map +1 -1
  93. package/dist/internal/utils/audit-logs.d.ts +0 -1
  94. package/dist/internal/utils/audit-logs.js.map +1 -1
  95. package/dist/internal/utils/dom.d.ts +0 -5
  96. package/dist/internal/utils/dom.js +30 -46
  97. package/dist/internal/utils/dom.js.map +1 -1
  98. package/dist/internal/utils/events.d.ts +0 -1
  99. package/dist/internal/utils/events.js +4 -7
  100. package/dist/internal/utils/events.js.map +1 -1
  101. package/dist/internal/utils/keynav.d.ts +0 -1
  102. package/dist/internal/utils/keynav.js +2 -5
  103. package/dist/internal/utils/keynav.js.map +1 -1
  104. package/dist/internal/utils/objects.d.ts +0 -2
  105. package/dist/internal/utils/objects.js +2 -8
  106. package/dist/internal/utils/objects.js.map +1 -1
  107. package/dist/joystick/joystick2.js +5 -5
  108. package/dist/logo/logo2.js +1 -1
  109. package/dist/menu/menu-group2.js +1 -1
  110. package/dist/menu/menu-item2.js +1 -1
  111. package/dist/menu/menu2.js +1 -1
  112. package/dist/month/month2.js +6 -6
  113. package/dist/notification/notification-group2.js +1 -1
  114. package/dist/notification/notification2.js +1 -1
  115. package/dist/page/page-panel/page-panel-content2.js +1 -1
  116. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  117. package/dist/page/page-panel/page-panel-header2.js +1 -1
  118. package/dist/page/page-panel/page-panel2.js +1 -1
  119. package/dist/page/page2.js +1 -1
  120. package/dist/page-header/page-header2.js +1 -1
  121. package/dist/page-loader/page-loader2.js +1 -1
  122. package/dist/pagination/pagination2.js +1 -1
  123. package/dist/panel/panel2.js +4 -4
  124. package/dist/password/password2.js +6 -6
  125. package/dist/preferences-input/preferences-input2.js +5 -5
  126. package/dist/progress-bar/progress-bar2.js +1 -1
  127. package/dist/progress-dot/progress-dot2.js +1 -1
  128. package/dist/progress-ring/progress-ring2.js +1 -1
  129. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  130. package/dist/pulse/pulse2.js +1 -1
  131. package/dist/radio/radio-group2.js +1 -1
  132. package/dist/radio/radio2.js +1 -1
  133. package/dist/range/range2.js +1 -1
  134. package/dist/resize-handle/resize-handle2.js +5 -5
  135. package/dist/search/search2.js +6 -6
  136. package/dist/select/select2.js +1 -1
  137. package/dist/skeleton/skeleton2.js +1 -1
  138. package/dist/sort-button/sort-button2.js +1 -1
  139. package/dist/sparkline/sparkline2.js +1 -1
  140. package/dist/star-rating/star-rating2.js +1 -1
  141. package/dist/steps/steps2.js +6 -6
  142. package/dist/switch/switch-group2.js +1 -1
  143. package/dist/switch/switch2.js +1 -1
  144. package/dist/tabs/tabs-group2.js +1 -1
  145. package/dist/tabs/tabs-item-group2.js +1 -1
  146. package/dist/tabs/tabs2.js +2 -2
  147. package/dist/tag/tag2.js +5 -5
  148. package/dist/textarea/textarea2.js +1 -1
  149. package/dist/time/time2.js +6 -6
  150. package/dist/toast/toast2.js +1 -1
  151. package/dist/toggletip/toggletip-footer2.js +1 -1
  152. package/dist/toggletip/toggletip-header2.js +1 -1
  153. package/dist/toggletip/toggletip2.js +1 -1
  154. package/dist/toolbar/toolbar2.js +1 -1
  155. package/dist/tooltip/tooltip2.js +1 -1
  156. package/dist/tree/tree-node2.js +1 -1
  157. package/dist/tree/tree2.js +1 -1
  158. package/dist/week/week2.js +6 -6
  159. package/dist/workspace/controllers/workspace-command.controller.d.ts +34 -0
  160. package/dist/workspace/controllers/workspace-command.controller.js +87 -0
  161. package/dist/workspace/controllers/workspace-command.controller.js.map +1 -0
  162. package/dist/workspace/controllers/workspace-composition.controller.d.ts +54 -0
  163. package/dist/workspace/controllers/workspace-composition.controller.js +169 -0
  164. package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -0
  165. package/dist/workspace/controllers/workspace-fullscreen.controller.d.ts +25 -0
  166. package/dist/workspace/controllers/workspace-fullscreen.controller.js +84 -0
  167. package/dist/workspace/controllers/workspace-fullscreen.controller.js.map +1 -0
  168. package/dist/workspace/controllers/workspace-measurement.controller.d.ts +19 -0
  169. package/dist/workspace/controllers/workspace-measurement.controller.js +188 -0
  170. package/dist/workspace/controllers/workspace-measurement.controller.js.map +1 -0
  171. package/dist/workspace/controllers/workspace-rearrange.controller.d.ts +40 -0
  172. package/dist/workspace/controllers/workspace-rearrange.controller.js +385 -0
  173. package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -0
  174. package/dist/workspace/controllers/workspace-resize.controller.d.ts +43 -0
  175. package/dist/workspace/controllers/workspace-resize.controller.js +168 -0
  176. package/dist/workspace/controllers/workspace-resize.controller.js.map +1 -0
  177. package/dist/workspace/controllers/workspace-restoration.controller.d.ts +24 -0
  178. package/dist/workspace/controllers/workspace-restoration.controller.js +193 -0
  179. package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -0
  180. package/dist/workspace/define.d.ts +10 -0
  181. package/dist/workspace/define.js +9 -0
  182. package/dist/workspace/define.js.map +1 -0
  183. package/dist/workspace/index.d.ts +11 -0
  184. package/dist/workspace/index.js +6 -0
  185. package/dist/workspace/panel/panel.d.ts +48 -0
  186. package/dist/workspace/panel/panel.js +5 -0
  187. package/dist/workspace/panel/panel.js.map +1 -0
  188. package/dist/workspace/panel/panel2.js +53 -0
  189. package/dist/workspace/panel/panel2.js.map +1 -0
  190. package/dist/workspace/panel-content/panel-content.d.ts +20 -0
  191. package/dist/workspace/panel-content/panel-content.js +5 -0
  192. package/dist/workspace/panel-content/panel-content.js.map +1 -0
  193. package/dist/workspace/panel-content/panel-content2.js +22 -0
  194. package/dist/workspace/panel-content/panel-content2.js.map +1 -0
  195. package/dist/workspace/panel-footer/panel-footer.d.ts +24 -0
  196. package/dist/workspace/panel-footer/panel-footer.js +5 -0
  197. package/dist/workspace/panel-footer/panel-footer.js.map +1 -0
  198. package/dist/workspace/panel-footer/panel-footer2.js +28 -0
  199. package/dist/workspace/panel-footer/panel-footer2.js.map +1 -0
  200. package/dist/workspace/panel-header/panel-header.d.ts +61 -0
  201. package/dist/workspace/panel-header/panel-header.js +5 -0
  202. package/dist/workspace/panel-header/panel-header.js.map +1 -0
  203. package/dist/workspace/panel-header/panel-header2.js +102 -0
  204. package/dist/workspace/panel-header/panel-header2.js.map +1 -0
  205. package/dist/workspace/utils/evaluation.utils.d.ts +83 -0
  206. package/dist/workspace/utils/evaluation.utils.js +294 -0
  207. package/dist/workspace/utils/evaluation.utils.js.map +1 -0
  208. package/dist/workspace/utils/geometry/allocation.utils.d.ts +40 -0
  209. package/dist/workspace/utils/geometry/allocation.utils.js +73 -0
  210. package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -0
  211. package/dist/workspace/utils/geometry/partition.utils.d.ts +10 -0
  212. package/dist/workspace/utils/geometry/partition.utils.js +40 -0
  213. package/dist/workspace/utils/geometry/partition.utils.js.map +1 -0
  214. package/dist/workspace/utils/geometry/sizing.utils.d.ts +35 -0
  215. package/dist/workspace/utils/geometry/sizing.utils.js +42 -0
  216. package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -0
  217. package/dist/workspace/utils/interaction/boundary.utils.d.ts +40 -0
  218. package/dist/workspace/utils/interaction/boundary.utils.js +91 -0
  219. package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -0
  220. package/dist/workspace/utils/interaction/command.utils.d.ts +74 -0
  221. package/dist/workspace/utils/interaction/command.utils.js +189 -0
  222. package/dist/workspace/utils/interaction/command.utils.js.map +1 -0
  223. package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +79 -0
  224. package/dist/workspace/utils/interaction/drag-preview.utils.js +16 -0
  225. package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -0
  226. package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +58 -0
  227. package/dist/workspace/utils/interaction/insertion-offers.utils.js +259 -0
  228. package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -0
  229. package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +55 -0
  230. package/dist/workspace/utils/interaction/placement-decision.utils.js +242 -0
  231. package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -0
  232. package/dist/workspace/utils/interaction/resize-input.utils.d.ts +1 -0
  233. package/dist/workspace/utils/interaction/resize-input.utils.js +17 -0
  234. package/dist/workspace/utils/interaction/resize-input.utils.js.map +1 -0
  235. package/dist/workspace/utils/model/layout.utils.d.ts +22 -0
  236. package/dist/workspace/utils/model/layout.utils.js +41 -0
  237. package/dist/workspace/utils/model/layout.utils.js.map +1 -0
  238. package/dist/workspace/utils/model/membership.utils.d.ts +14 -0
  239. package/dist/workspace/utils/model/membership.utils.js +17 -0
  240. package/dist/workspace/utils/model/membership.utils.js.map +1 -0
  241. package/dist/workspace/utils/model/operations.utils.d.ts +31 -0
  242. package/dist/workspace/utils/model/operations.utils.js +178 -0
  243. package/dist/workspace/utils/model/operations.utils.js.map +1 -0
  244. package/dist/workspace/utils/model/projection.utils.d.ts +7 -0
  245. package/dist/workspace/utils/model/projection.utils.js +87 -0
  246. package/dist/workspace/utils/model/projection.utils.js.map +1 -0
  247. package/dist/workspace/utils/model/value.utils.d.ts +5 -0
  248. package/dist/workspace/utils/model/value.utils.js +68 -0
  249. package/dist/workspace/utils/model/value.utils.js.map +1 -0
  250. package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +32 -0
  251. package/dist/workspace/utils/placement/acquisition-sizing.utils.js +152 -0
  252. package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -0
  253. package/dist/workspace/utils/placement/context.utils.d.ts +36 -0
  254. package/dist/workspace/utils/placement/context.utils.js +135 -0
  255. package/dist/workspace/utils/placement/context.utils.js.map +1 -0
  256. package/dist/workspace/utils/placement/group-insertion.utils.d.ts +26 -0
  257. package/dist/workspace/utils/placement/group-insertion.utils.js +171 -0
  258. package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -0
  259. package/dist/workspace/utils/placement/origin.utils.d.ts +13 -0
  260. package/dist/workspace/utils/placement/origin.utils.js +49 -0
  261. package/dist/workspace/utils/placement/origin.utils.js.map +1 -0
  262. package/dist/workspace/utils/placement/planner.utils.d.ts +22 -0
  263. package/dist/workspace/utils/placement/planner.utils.js +184 -0
  264. package/dist/workspace/utils/placement/planner.utils.js.map +1 -0
  265. package/dist/workspace/utils/placement/preparation.utils.d.ts +28 -0
  266. package/dist/workspace/utils/placement/preparation.utils.js +140 -0
  267. package/dist/workspace/utils/placement/preparation.utils.js.map +1 -0
  268. package/dist/workspace/utils/placement/region.utils.d.ts +15 -0
  269. package/dist/workspace/utils/placement/region.utils.js +111 -0
  270. package/dist/workspace/utils/placement/region.utils.js.map +1 -0
  271. package/dist/workspace/utils/placement/split-sizing.utils.d.ts +18 -0
  272. package/dist/workspace/utils/placement/split-sizing.utils.js +108 -0
  273. package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -0
  274. package/dist/workspace/utils/presentation/composition.utils.d.ts +17 -0
  275. package/dist/workspace/utils/presentation/composition.utils.js +95 -0
  276. package/dist/workspace/utils/presentation/composition.utils.js.map +1 -0
  277. package/dist/workspace/utils/presentation/groups.utils.d.ts +91 -0
  278. package/dist/workspace/utils/presentation/groups.utils.js +169 -0
  279. package/dist/workspace/utils/presentation/groups.utils.js.map +1 -0
  280. package/dist/workspace/utils/presentation/header-configuration.utils.d.ts +11 -0
  281. package/dist/workspace/utils/presentation/header-configuration.utils.js +7 -0
  282. package/dist/workspace/utils/presentation/header-configuration.utils.js.map +1 -0
  283. package/dist/workspace/utils/presentation/measurements.utils.d.ts +21 -0
  284. package/dist/workspace/utils/presentation/measurements.utils.js +28 -0
  285. package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -0
  286. package/dist/workspace/utils/presentation/offers.utils.d.ts +43 -0
  287. package/dist/workspace/utils/presentation/offers.utils.js +137 -0
  288. package/dist/workspace/utils/presentation/offers.utils.js.map +1 -0
  289. package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
  290. package/dist/workspace/utils/presentation/preview.utils.js +36 -0
  291. package/dist/workspace/utils/presentation/preview.utils.js.map +1 -0
  292. package/dist/workspace/workspace.d.ts +103 -0
  293. package/dist/workspace/workspace.examples.js +5 -0
  294. package/dist/workspace/workspace.examples.js.map +1 -0
  295. package/dist/workspace/workspace.examples.json +133 -0
  296. package/dist/workspace/workspace.js +5 -0
  297. package/dist/workspace/workspace.js.map +1 -0
  298. package/dist/workspace/workspace.types.d.ts +3 -0
  299. package/dist/workspace/workspace2.js +518 -0
  300. package/dist/workspace/workspace2.js.map +1 -0
  301. package/package.json +27 -3
  302. package/dist/internal/utils/supports.d.ts +0 -3
  303. package/dist/internal/utils/supports.js +0 -13
  304. package/dist/internal/utils/supports.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insertion-offers.utils.js","names":["placementOwnsChrome","childSlot","offer","directions","findSourcePeerRegionKey","node","child","source","id","key","index","owner","createInsertionOffers","offers","seen","input","candidates","splitGroups","groupInsertions","group","a","b","members","getPanelIds","rect","getAllocatedContextRect","explorationRect","context","planWorkspacePlacement","explorationContext","insertionDestinations","receivingContext","destination","createInsertionOffer","target","direction","plan","planPlacement","slot","describePlacementSlot","domain","insertionEndcap","rectArea","edgeArea","interior","interiorInsertion","candidate","destinations","seam","getCurrentInsertionSeam","getPlacementOfferIntent","getOrderHintRect","horizontal","start","extent","normal","orderAnchor","end","previousEnd","partitionPlacementOffers","sorted","tangentExtent","placed","occupied","lane","sameEdge","other","vertical","isVerticalEdge","shift","position","tangent","previous","geometry","next","axisDimensions","gap","normalExtent","from","to","tangentSize","axis"],"sources":["../../../../src/workspace/utils/interaction/insertion-offers.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Rect } from '@nvidia-elements/core/internal';\n\nimport { getPanelIds } from '../model/layout.utils.js';\nimport { getAllocatedContextRect } from '../placement/context.utils.js';\nimport { describePlacementSlot } from '../placement/group-insertion.utils.js';\nimport { planWorkspacePlacement } from '../placement/planner.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceDropIntent } from './drag-preview.utils.js';\nimport type { WorkspaceLayout, WorkspaceNode } from '../model/layout.utils.js';\nimport type { WorkspaceDestination } from '../model/operations.utils.js';\nimport type { WorkspaceLayoutProjector } from '../model/projection.utils.js';\nimport type { WorkspaceContextRectResolver } from '../placement/context.utils.js';\nimport type { WorkspacePlacementPlan, WorkspacePlacementPlanner } from '../placement/planner.utils.js';\n\nexport interface WorkspaceInsertionOffer {\n kind: 'order' | 'insert';\n owner: string;\n boundary?: 'start' | 'end';\n scope: NonNullable<ReturnType<typeof describePlacementSlot>>;\n plan: WorkspacePlacementPlan;\n rect: Rect;\n hitRect?: Rect;\n scopeRect: Rect;\n destination: WorkspaceDestination;\n}\n\n/** Gives only an explicit peer lane or structural receiving endcap priority over chrome. */\nexport function placementOwnsChrome(offer: WorkspaceInsertionOffer) {\n const childSlot = offer.destination.region?.slice(0, offer.destination.region.lastIndexOf('.')) === offer.owner;\n return offer.kind === 'order' || !!offer.boundary || (childSlot && !!offer.scope.previous && !!offer.scope.next);\n}\n\nconst directions = ['left', 'right', 'top', 'bottom'] as const;\n\nexport function findSourcePeerRegionKey(\n node: WorkspaceNode | null,\n source: string[],\n key = 'root'\n): string | undefined {\n if (node?.type !== 'split') return undefined;\n if (node.children.some(child => child.type === 'group' && child.panels.every(id => source.includes(id)))) return key;\n for (const [index, child] of node.children.entries()) {\n const owner = findSourcePeerRegionKey(child, source, `${key}.${index}`);\n if (owner) return owner;\n }\n return undefined;\n}\n\n/** Aliases of the same planned insertion share one descriptor. */\nexport function createInsertionOffers(input: {\n currentLayout: WorkspaceLayout;\n root: WorkspaceNode | null;\n source: string[];\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n planPlacement?: WorkspacePlacementPlanner;\n contextRect?: WorkspaceContextRectResolver;\n regions: WorkspacePlacedRegion[];\n explorationRegions?: WorkspacePlacedRegion[];\n existing: WorkspaceInsertionOffer[];\n gap: number;\n}) {\n const offers: WorkspaceInsertionOffer[] = [];\n const seen = new Set<string>();\n for (const offer of input.existing) {\n seen.add(offer.scope.key);\n offers.push(offer);\n }\n const candidates = splitGroups(input.root)\n .flatMap(group => groupInsertions(input, group))\n .sort((a, b) => Number(a.interior) - Number(b.interior));\n for (const { offer } of candidates) {\n if (seen.has(offer.scope.key)) continue;\n seen.add(offer.scope.key);\n offers.push(offer);\n }\n return offers;\n}\n\nfunction groupInsertions(\n input: Parameters<typeof createInsertionOffers>[0],\n group: { node: WorkspaceNode; key: string }\n): { offer: WorkspaceInsertionOffer; interior: boolean }[] {\n const members = getPanelIds(group.node).filter(id => !input.source.includes(id));\n const rect = (input.contextRect ?? getAllocatedContextRect)({\n members,\n allocation: input.regions,\n source: input.source\n });\n if (!rect) return [];\n const explorationRect = (input.contextRect ?? getAllocatedContextRect)({\n members,\n allocation: input.explorationRegions ?? input.regions,\n source: input.source\n });\n const context = { input, group, rect, planPlacement: input.planPlacement ?? planWorkspacePlacement };\n const explorationContext = explorationRect ? { ...context, rect: explorationRect } : undefined;\n return insertionDestinations(group).flatMap(destination => {\n // Receiving edges cannot depend on their own reservation; peer seams follow allocated neighbors.\n const receivingContext = destination.interior ? context : explorationContext;\n return receivingContext ? createInsertionOffer(receivingContext, destination) : [];\n });\n}\n\nfunction createInsertionOffer(\n {\n input,\n group,\n rect,\n planPlacement\n }: {\n input: Parameters<typeof createInsertionOffers>[0];\n group: { node: WorkspaceNode; key: string };\n rect: Rect;\n planPlacement: WorkspacePlacementPlanner;\n },\n { target, key, direction, interior }: ReturnType<typeof insertionDestinations>[number]\n): { offer: WorkspaceInsertionOffer; interior: boolean }[] {\n const destination: WorkspaceDestination = {\n target: getPanelIds(target).find(id => !input.source.includes(id)) ?? '',\n region: key,\n position: direction\n };\n const plan = planPlacement({\n layout: input.currentLayout,\n source: input.source,\n destination,\n available: input.available,\n projectLayout: input.projectLayout,\n operation: 'insert'\n });\n if (!plan) return [];\n const slot = describePlacementSlot({\n plan,\n source: input.source,\n available: input.available,\n projectLayout: input.projectLayout\n });\n if (!slot) return [];\n const domain = insertionEndcap(input, slot) ?? rect;\n const rectArea = edgeArea(domain, direction);\n if (!rectArea) return [];\n const offer: WorkspaceInsertionOffer = {\n scope: slot,\n owner: group.key,\n boundary: !slot.previous ? 'start' : !slot.next ? 'end' : undefined,\n plan,\n scopeRect: domain,\n rect: rectArea,\n destination,\n kind: plan.kind === 'reorder' ? 'order' : 'insert'\n };\n return (interior ? interiorInsertion(offer, input) : [offer]).map(candidate => ({ offer: candidate, interior }));\n}\n\nfunction insertionDestinations(group: { node: WorkspaceNode; key: string }) {\n const destinations = directions.map(direction => ({\n target: group.node,\n key: group.key,\n direction,\n interior: false\n }));\n if (group.node.type === 'split') {\n const direction = group.node.axis === 'horizontal' ? 'left' : 'top';\n group.node.children.slice(1).forEach((target, index) =>\n destinations.push({\n target,\n key: `${group.key}.${index + 1}`,\n direction,\n interior: true\n })\n );\n }\n return destinations;\n}\n\nfunction interiorInsertion(\n offer: WorkspaceInsertionOffer,\n input: Parameters<typeof createInsertionOffers>[0]\n): WorkspaceInsertionOffer[] {\n const seam = getCurrentInsertionSeam(offer, input);\n return seam ? [{ ...offer, rect: seam }] : [];\n}\n\nfunction insertionEndcap(\n input: Parameters<typeof createInsertionOffers>[0],\n slot: NonNullable<ReturnType<typeof describePlacementSlot>>\n) {\n if (!!slot.previous === !!slot.next) return undefined;\n return (input.contextRect ?? getAllocatedContextRect)({\n members: slot.members,\n allocation: input.explorationRegions ?? input.regions,\n source: input.source\n });\n}\n\nfunction splitGroups(node: WorkspaceNode | null, key = 'root'): { key: string; node: WorkspaceNode }[] {\n return node?.type === 'split'\n ? [{ key, node }, ...node.children.flatMap((child, index) => splitGroups(child, `${key}.${index}`))]\n : [];\n}\n\nfunction edgeArea(rect: Rect, direction: (typeof directions)[number]): Rect | undefined {\n if (direction === 'left' || direction === 'right')\n return 12 <= rect.width\n ? {\n x: direction === 'left' ? rect.x : rect.x + rect.width - 12,\n y: rect.y,\n width: 12,\n height: rect.height\n }\n : undefined;\n return 12 <= rect.height\n ? {\n x: rect.x,\n y: direction === 'top' ? rect.y : rect.y + rect.height - 12,\n width: rect.width,\n height: 12\n }\n : undefined;\n}\n\n/** Shares the painted descriptor's exact operation with input resolution. */\nexport function getPlacementOfferIntent(offer: WorkspaceInsertionOffer): WorkspaceDropIntent {\n if (offer.destination.position === 'tab') return { kind: 'invalid' };\n const destination = { ...offer.destination, position: offer.destination.position };\n return offer.kind === 'insert' ? { kind: 'insert', destination } : { kind: 'order', destination };\n}\n\n/** Locates ordering availability in the computed exploration geometry, not a prospective landing. */\nexport function getOrderHintRect(input: {\n owner: Rect;\n recipient: Rect;\n previous?: Rect;\n axis: 'horizontal' | 'vertical';\n after: boolean;\n sourceSlot?: Rect;\n boundary?: 'start' | 'end';\n}): Rect | undefined {\n const horizontal = input.axis === 'horizontal';\n const start = horizontal ? 'x' : 'y';\n const extent = horizontal ? 'width' : 'height';\n if (input.owner[extent] < 12) return undefined;\n const normal = orderAnchor(input, { start, extent });\n return horizontal\n ? { x: normal, y: input.owner.y, width: 12, height: input.owner.height }\n : { x: input.owner.x, y: normal, width: input.owner.width, height: 12 };\n}\n\nfunction orderAnchor(\n input: Parameters<typeof getOrderHintRect>[0],\n { start, extent }: { start: 'x' | 'y'; extent: 'width' | 'height' }\n) {\n if (input.boundary === 'start') return input.owner[start];\n const end = input.owner[start] + input.owner[extent] - 12;\n if (input.boundary === 'end') return end;\n const slot = input.sourceSlot;\n if (input.after)\n return slot && slot[start] >= input.recipient[start] + input.recipient[extent]\n ? (input.recipient[start] + input.recipient[extent] + slot[start]) / 2 - 6\n : end;\n if (!input.previous) return input.owner[start];\n const previousEnd = input.previous[start] + input.previous[extent];\n const nextStart =\n slot && slot[start] >= previousEnd && slot[start] < input.recipient[start] ? slot[start] : input.recipient[start];\n return (previousEnd + nextStart) / 2 - 6;\n}\n\n/** Orders overlapping scope offers into lanes from outermost to innermost. */\nexport function partitionPlacementOffers(offers: WorkspaceInsertionOffer[]): WorkspaceInsertionOffer[] {\n const sorted = [...offers].sort((a, b) => tangentExtent(b) - tangentExtent(a));\n const placed: WorkspaceInsertionOffer[] = [];\n const occupied: WorkspaceInsertionOffer[] = [];\n for (const offer of sorted) {\n const lane = occupied.filter(other => sameEdge(offer, other)).length;\n occupied.push(offer);\n const vertical = isVerticalEdge(offer.destination.position);\n const shift =\n (offer.destination.position === 'right' || offer.destination.position === 'bottom' ? -1 : 1) * lane * 12;\n const rect = { ...offer.rect, x: offer.rect.x + (vertical ? shift : 0), y: offer.rect.y + (vertical ? 0 : shift) };\n if (\n rect.x < offer.scopeRect.x ||\n rect.y < offer.scopeRect.y ||\n rect.x + rect.width > offer.scopeRect.x + offer.scopeRect.width ||\n rect.y + rect.height > offer.scopeRect.y + offer.scopeRect.height\n ) {\n continue;\n }\n placed.push({ ...offer, rect });\n }\n return placed;\n}\n\nfunction isVerticalEdge(position: WorkspaceDestination['position']) {\n return position === 'left' || position === 'right';\n}\n\nfunction tangentExtent(offer: WorkspaceInsertionOffer) {\n return offer.destination.position === 'left' || offer.destination.position === 'right'\n ? offer.rect.height\n : offer.rect.width;\n}\n\nfunction sameEdge(a: WorkspaceInsertionOffer, b: WorkspaceInsertionOffer) {\n if (a.destination.position !== b.destination.position) return false;\n const vertical = isVerticalEdge(a.destination.position);\n const normal = vertical ? 'x' : 'y';\n const tangent = vertical ? 'y' : 'x';\n const extent = vertical ? 'height' : 'width';\n return (\n Math.abs(a.rect[normal] - b.rect[normal]) < 1 &&\n Math.max(a.rect[tangent], b.rect[tangent]) <\n Math.min(a.rect[tangent] + a.rect[extent], b.rect[tangent] + b.rect[extent])\n );\n}\n\n/** Uses current peer geometry for interior insertion cues, before allocating the candidate. */\nexport function getCurrentInsertionSeam(\n offer: WorkspaceInsertionOffer,\n geometry: {\n regions: WorkspacePlacedRegion[];\n source: string[];\n gap: number;\n contextRect?: WorkspaceContextRectResolver;\n }\n): Rect | undefined {\n if (offer.kind !== 'insert' || !offer.scope.previous || !offer.scope.next) return undefined;\n const previous = (geometry.contextRect ?? getAllocatedContextRect)({\n members: offer.scope.previous,\n allocation: geometry.regions,\n source: geometry.source\n });\n const next = (geometry.contextRect ?? getAllocatedContextRect)({\n members: offer.scope.next,\n allocation: geometry.regions,\n source: geometry.source\n });\n if (!previous || !next) return undefined;\n const { normal, normalExtent, tangent, tangentSize } = axisDimensions(offer.scope.axis);\n const gap = next[normal] - previous[normal] - previous[normalExtent];\n if (Math.abs(gap - geometry.gap) > 1) return undefined;\n const from = Math.max(previous[tangent], next[tangent]);\n const to = Math.min(previous[tangent] + previous[tangentSize], next[tangent] + next[tangentSize]);\n if (to <= from) return undefined;\n const owner = { ...offer.scopeRect, [tangent]: from, [tangentSize]: to - from };\n return getOrderHintRect({ owner, recipient: next, previous, axis: offer.scope.axis, after: false });\n}\n\nfunction axisDimensions(axis: 'horizontal' | 'vertical') {\n return axis === 'horizontal'\n ? ({ normal: 'x', normalExtent: 'width', tangent: 'y', tangentSize: 'height' } as const)\n : ({ normal: 'y', normalExtent: 'height', tangent: 'x', tangentSize: 'width' } as const);\n}\n"],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { Point, Rect } from '@nvidia-elements/core/internal';
2
+ import type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';
3
+ import type { WorkspaceDragPreview, WorkspaceDropIntent, WorkspacePlacementAcquisition } from './drag-preview.utils.js';
4
+ import type { WorkspaceInsertionOffer } from './insertion-offers.utils.js';
5
+ import type { WorkspaceLayout, WorkspaceNode } from '../model/layout.utils.js';
6
+ import type { WorkspaceLayoutProjector } from '../model/projection.utils.js';
7
+ import type { WorkspacePlacementPlanner } from '../placement/planner.utils.js';
8
+ import type { WorkspacePlacementCatalog } from '../evaluation.utils.js';
9
+ interface WorkspacePlacementQuery {
10
+ gap: number;
11
+ source: string[];
12
+ point: Point;
13
+ regions: WorkspacePlacedRegion[];
14
+ orderingRegions?: WorkspacePlacedRegion[];
15
+ sourceSlot?: Rect;
16
+ headers?: Rect[];
17
+ preview?: WorkspaceDragPreview;
18
+ local?: WorkspaceDropIntent;
19
+ header: boolean;
20
+ bounds: Rect;
21
+ }
22
+ type DecisionInput = WorkspacePlacementQuery & {
23
+ currentLayout: WorkspaceLayout;
24
+ available: string[];
25
+ projectLayout?: WorkspaceLayoutProjector;
26
+ planPlacement?: WorkspacePlacementPlanner;
27
+ };
28
+ export interface WorkspacePlacementDecision {
29
+ intent: WorkspaceDropIntent | undefined;
30
+ acquisition?: WorkspacePlacementAcquisition;
31
+ }
32
+ interface PointerPlacementInput {
33
+ placement: WorkspacePlacementCatalog;
34
+ canonicalRoot: WorkspaceNode | null;
35
+ currentLayout: WorkspaceLayout;
36
+ source: string[];
37
+ point: Point;
38
+ heldIntent: WorkspaceDropIntent;
39
+ groupable: boolean;
40
+ gap: number;
41
+ available: string[];
42
+ projectLayout?: WorkspaceLayoutProjector;
43
+ planPlacement?: WorkspacePlacementPlanner;
44
+ }
45
+ export declare function decidePointerPlacement(input: PointerPlacementInput): WorkspacePlacementDecision;
46
+ /** Chooses input and availability together from the two operation-specific computed projections. */
47
+ export declare function decidePlacement(input: DecisionInput): {
48
+ acquisition: {
49
+ plan: import("../placement/planner.utils.js").WorkspacePlacementPlan;
50
+ rect: Rect;
51
+ } | undefined;
52
+ intent: WorkspaceDropIntent | undefined;
53
+ hint: WorkspaceInsertionOffer | undefined;
54
+ };
55
+ export {};
@@ -0,0 +1,242 @@
1
+ import { getPanelIds as e, getSplitSide as t } from "../model/layout.utils.js";
2
+ import { findGroup as n, projectLayout as r } from "../model/operations.utils.js";
3
+ import { clipCue as i, matchesPlacementIntent as a } from "./drag-preview.utils.js";
4
+ import { createContextRectResolver as o } from "../placement/context.utils.js";
5
+ import { findWorkspaceRegion as s } from "../placement/region.utils.js";
6
+ import { describePlacementSlot as c } from "../placement/group-insertion.utils.js";
7
+ import { planWorkspacePlacement as l } from "../placement/planner.utils.js";
8
+ import { createInsertionOffers as u, findSourcePeerRegionKey as d, getOrderHintRect as f, getPlacementOfferIntent as p, placementOwnsChrome as m } from "./insertion-offers.utils.js";
9
+ import { getBoundaryPlacementOffers as h } from "./boundary.utils.js";
10
+ import { getTabInsertionIndex as g, preservesGroupMembership as _ } from "../model/membership.utils.js";
11
+ // src/workspace/utils/interaction/placement-decision.utils.ts
12
+ var v = (e, t) => t.x >= e.x && t.x < e.x + e.width && t.y >= e.y && t.y < e.y + e.height;
13
+ function y(e) {
14
+ let { placement: t, point: n } = e, r = !!t.headerTarget, i = x(e, t.headerTarget ?? (v(t.bounds, n) ? t.targets.find((e) => v(e.rect, n)) : void 0), r);
15
+ return b({
16
+ ...t,
17
+ source: e.source,
18
+ point: n,
19
+ local: i,
20
+ header: r,
21
+ currentLayout: e.currentLayout,
22
+ gap: e.gap,
23
+ available: e.available,
24
+ projectLayout: e.projectLayout,
25
+ planPlacement: e.planPlacement
26
+ });
27
+ }
28
+ function b(e) {
29
+ let t = E({
30
+ ...e,
31
+ contextRect: o()
32
+ }), n = O(t.offers, e), r = C(e), i = t.offers.filter((t) => w(t, r, e.bounds)), a = i.filter((e) => e.scope.key !== n).map((t) => ({
33
+ offer: t,
34
+ distance: k(t, e.point)
35
+ })).sort((e, t) => e.distance - t.distance)[0], s = v(e.bounds, e.point) ? t.offers.find((t) => v(t.hitRect ?? t.rect, e.point) && (!e.header || m(t))) : void 0, c = t.hit ?? s;
36
+ return {
37
+ acquisition: c ? {
38
+ plan: c.plan,
39
+ rect: c.hitRect ?? c.rect
40
+ } : void 0,
41
+ intent: D(e, c),
42
+ hint: T({
43
+ hit: c && i.includes(c) ? c : void 0,
44
+ selectedKey: n,
45
+ boundary: t.hit,
46
+ nearest: a
47
+ })
48
+ };
49
+ }
50
+ function x(e, t, n) {
51
+ let { reservationHit: r } = e.placement, i = !n && r, a = n && r === "tab" && e.heldIntent.kind === "tab";
52
+ if (i || a) return e.heldIntent;
53
+ if (!t) return;
54
+ let o = t.panels[0];
55
+ return o ? n ? S(e, t, o) : {
56
+ kind: "split",
57
+ destination: {
58
+ target: o,
59
+ position: I(e.point, {
60
+ rect: t.rect,
61
+ headerHeight: t.headerHeight
62
+ })
63
+ }
64
+ } : { kind: "invalid" };
65
+ }
66
+ function S(e, t, r) {
67
+ let i = t.tabs.find((t) => e.point.x < t.rect.x + t.rect.width / 2), a = n(e.canonicalRoot, r)?.panels ?? [], o = {
68
+ kind: "tab",
69
+ destination: {
70
+ target: r,
71
+ position: "tab",
72
+ index: g(a, i?.id)
73
+ }
74
+ };
75
+ return e.groupable || _({
76
+ root: e.canonicalRoot,
77
+ source: e.source,
78
+ intent: o
79
+ }) ? o : void 0;
80
+ }
81
+ function C(e) {
82
+ let t = e.preview;
83
+ if (e.sourceSlot && t?.phase === "detached" && !t.blocked && t.allocation === "reserved" && t.cue.kind === "group") return i(e.sourceSlot, e.bounds);
84
+ }
85
+ function w(e, t, n) {
86
+ if (!t) return !0;
87
+ let r = i(e.rect, n), a = e.destination.position === "left" || e.destination.position === "right", o = a ? "x" : "y", s = a ? "width" : "height", c = a ? "y" : "x", l = a ? "height" : "width";
88
+ return r[o] > t[o] && r[o] + r[s] < t[o] + t[s] ? !(r[c] >= t[c] && r[c] + r[l] <= t[c] + t[l]) : !0;
89
+ }
90
+ function T({ hit: e, selectedKey: t, boundary: n, nearest: r }) {
91
+ if (e && e.scope.key !== t) return e;
92
+ if (!n && r && r.distance <= 24) return r.offer;
93
+ }
94
+ function E(e) {
95
+ let t = (e.projectLayout ?? r)(e.currentLayout, e.available).root, n = e.orderingRegions ?? e.regions, i = u({
96
+ ...e,
97
+ root: t,
98
+ regions: n,
99
+ explorationRegions: e.regions,
100
+ existing: j({
101
+ ...e,
102
+ root: t
103
+ })
104
+ });
105
+ return h({
106
+ offers: i,
107
+ bounds: e.bounds,
108
+ point: e.point,
109
+ current: e.preview?.intent,
110
+ headers: e.headers ?? [],
111
+ geometry: {
112
+ regions: n,
113
+ source: e.source,
114
+ gap: e.gap,
115
+ contextRect: e.contextRect
116
+ }
117
+ });
118
+ }
119
+ function D(e, t) {
120
+ if (t) return p(t);
121
+ if (v(e.bounds, e.point)) return e.sourceSlot && v(e.sourceSlot, e.point) ? e.preview?.intent ?? e.local : e.local;
122
+ }
123
+ function O(e, t) {
124
+ let n = t.preview;
125
+ if (n && n.phase === "detached") return "layout" in n ? c({
126
+ plan: n,
127
+ source: t.source,
128
+ available: t.available,
129
+ projectLayout: t.projectLayout
130
+ })?.key : e.find((e) => a(p(e), n.intent))?.scope.key;
131
+ }
132
+ function k(e, t) {
133
+ let n = e.hitRect ?? e.rect, r = e.destination.position === "left" || e.destination.position === "right", i = r ? t.y : t.x, a = r ? n.y : n.x, o = r ? n.height : n.width;
134
+ if (!(i >= a && i < a + o)) return Infinity;
135
+ let s = r ? t.x - n.x : t.y - n.y, c = r ? n.width : n.height;
136
+ return Math.abs(s - c / 2);
137
+ }
138
+ function A(t) {
139
+ let { root: r, source: i } = t, a = d(r, i) ?? "root", o = s(r, a), c = n(t.currentLayout.root, i[0]);
140
+ if (o?.type !== "split" || !P(c, i)) return;
141
+ let l = (n) => n.find((e) => e.key === a)?.rect ?? t.contextRect({
142
+ members: e(o).filter((e) => !i.includes(e)),
143
+ allocation: n,
144
+ source: i
145
+ }), u = l(t.regions), f = l(t.orderingRegions ?? t.regions);
146
+ if (!u || !f) return;
147
+ let p = o.children.findIndex((e) => e.type === "group" && e.panels.some((e) => i.includes(e)));
148
+ if (!(p < 0)) return {
149
+ key: a,
150
+ owner: o,
151
+ rect: u,
152
+ adjacencyRect: f,
153
+ peers: o.children.flatMap((e, t) => t === p ? [] : [{
154
+ node: e,
155
+ index: t
156
+ }])
157
+ };
158
+ }
159
+ function j(e) {
160
+ let t = A(e);
161
+ if (!t) return [];
162
+ let n = t.peers.map((e) => ({
163
+ ...e,
164
+ after: !1
165
+ })), r = t.peers.at(-1);
166
+ return r && n.push({
167
+ ...r,
168
+ after: !0
169
+ }), n.flatMap((n, r) => M({
170
+ input: e,
171
+ owner: t,
172
+ entry: n,
173
+ slot: r
174
+ }));
175
+ }
176
+ function M({ input: n, owner: r, entry: i, slot: a }) {
177
+ let o = F({
178
+ input: n,
179
+ owner: r,
180
+ entry: i,
181
+ slot: a
182
+ });
183
+ if (!o) return [];
184
+ let { region: s, before: u } = o, d = {
185
+ target: e(i.node)[0],
186
+ region: s.key,
187
+ position: t(r.owner.axis, i.after ? "after" : "before")
188
+ }, p = (n.planPlacement ?? l)({
189
+ layout: n.currentLayout,
190
+ source: n.source,
191
+ destination: d,
192
+ available: n.available,
193
+ projectLayout: n.projectLayout,
194
+ operation: "order"
195
+ });
196
+ if (p?.kind !== "reorder") return [];
197
+ let m = c({
198
+ plan: p,
199
+ source: n.source,
200
+ available: n.available,
201
+ projectLayout: n.projectLayout
202
+ }), h = N(i, a), g = h ? r.rect : r.adjacencyRect, _ = f({
203
+ owner: g,
204
+ recipient: s.rect,
205
+ previous: u?.rect,
206
+ axis: r.owner.axis,
207
+ after: i.after,
208
+ sourceSlot: n.sourceSlot,
209
+ boundary: h
210
+ });
211
+ return !_ || !m ? [] : [{
212
+ destination: d,
213
+ owner: r.key,
214
+ boundary: h,
215
+ rect: _,
216
+ scopeRect: g,
217
+ scope: m,
218
+ plan: p,
219
+ kind: "order"
220
+ }];
221
+ }
222
+ function N(e, t) {
223
+ if (e.after) return "end";
224
+ if (t === 0) return "start";
225
+ }
226
+ function P(e, t) {
227
+ return !!e && e.panels.length === t.length && e.panels.every((e) => t.includes(e));
228
+ }
229
+ function F({ input: e, owner: t, entry: n, slot: r }) {
230
+ let i = e.orderingRegions ?? e.regions, a = i.find((e) => e.key === `${t.key}.${n.index}`), o = t.peers[r - 1], s = o && i.find((e) => e.key === `${t.key}.${o.index}`);
231
+ return !a || r > 0 && !n.after && !s ? void 0 : {
232
+ region: a,
233
+ before: s
234
+ };
235
+ }
236
+ function I(e, t) {
237
+ let { rect: n, headerHeight: r } = t, i = n.x + n.width / 2, a = Math.max(1, n.height - r), o = n.y + r + a / 2, s = (e.x - i) / Math.max(1, n.width / 2), c = (e.y - o) / Math.max(1, a / 2);
238
+ return Math.abs(s) > Math.abs(c) ? s < 0 ? "left" : "right" : c < 0 ? "top" : "bottom";
239
+ }
240
+ export { b as decidePlacement, y as decidePointerPlacement };
241
+
242
+ //# sourceMappingURL=placement-decision.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement-decision.utils.js","names":["inside","point","rect","decidePointerPlacement","input","header","placement","local","localPlacementIntent","item","decidePlacement","boundary","placementOffers","createContextRectResolver","selectedKey","selectedScopeKey","sourceSlot","reservedSourceSlot","hints","eligiblePlacementHint","offer","nearest","distance","a","b","candidate","placementOwnsChrome","hit","acquiredIntent","placementHint","overReservedBody","reservationHit","overReservedTab","target","anchor","headerPlacementIntent","contentDirection","tab","preferred","findGroup","intent","getTabInsertionIndex","preservesGroupMembership","preview","clipCue","bounds","vertical","normal","normalSize","tangent","tangentSize","root","projectLayout","regions","offers","createInsertionOffers","orderOffers","getBoundaryPlacementOffers","getPlacementOfferIntent","describePlacementSlot","matchesPlacementIntent","start","extent","normalOffset","normalExtent","orderOwner","key","findSourcePeerRegionKey","source","owner","findWorkspaceRegion","group","wholeSource","ownerRect","region","getPanelIds","id","adjacencyRect","from","node","index","entries","peer","last","orderOffer","neighbors","orderNeighbors","destination","entry","getSplitSide","plan","planWorkspacePlacement","descriptor","orderBoundary","slot","area","getOrderHintRect","before","previous","centerX","contentHeight","headerHeight","centerY","dx","dy"],"sources":["../../../../src/workspace/utils/interaction/placement-decision.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Point, Rect } from '@nvidia-elements/core/internal';\n\nimport { getBoundaryPlacementOffers } from './boundary.utils.js';\nimport { clipCue, matchesPlacementIntent } from './drag-preview.utils.js';\nimport {\n createInsertionOffers,\n findSourcePeerRegionKey,\n getOrderHintRect,\n getPlacementOfferIntent,\n placementOwnsChrome\n} from './insertion-offers.utils.js';\nimport { getPanelIds, getSplitSide } from '../model/layout.utils.js';\nimport { getTabInsertionIndex, preservesGroupMembership } from '../model/membership.utils.js';\nimport { findGroup, projectLayout } from '../model/operations.utils.js';\nimport { createContextRectResolver } from '../placement/context.utils.js';\nimport { describePlacementSlot } from '../placement/group-insertion.utils.js';\nimport { planWorkspacePlacement } from '../placement/planner.utils.js';\nimport { findWorkspaceRegion } from '../placement/region.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceDragPreview, WorkspaceDropIntent, WorkspacePlacementAcquisition } from './drag-preview.utils.js';\nimport type { WorkspaceInsertionOffer } from './insertion-offers.utils.js';\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { WorkspaceDestination } from '../model/operations.utils.js';\nimport type { WorkspaceLayoutProjector } from '../model/projection.utils.js';\nimport type { WorkspaceContextRectResolver } from '../placement/context.utils.js';\nimport type { WorkspacePlacementPlanner } from '../placement/planner.utils.js';\nimport type { WorkspaceTarget } from '../presentation/groups.utils.js';\nimport type { WorkspacePlacementCatalog } from '../evaluation.utils.js';\n\ninterface WorkspacePlacementQuery {\n gap: number;\n source: string[];\n point: Point;\n regions: WorkspacePlacedRegion[];\n orderingRegions?: WorkspacePlacedRegion[];\n sourceSlot?: Rect;\n headers?: Rect[];\n preview?: WorkspaceDragPreview;\n local?: WorkspaceDropIntent;\n header: boolean;\n bounds: Rect;\n}\n\ntype DecisionInput = WorkspacePlacementQuery & {\n currentLayout: WorkspaceLayout;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n planPlacement?: WorkspacePlacementPlanner;\n};\n\ntype OfferInput = DecisionInput & { contextRect: WorkspaceContextRectResolver };\n\nexport interface WorkspacePlacementDecision {\n intent: WorkspaceDropIntent | undefined;\n acquisition?: WorkspacePlacementAcquisition;\n}\n\ninterface PointerPlacementInput {\n placement: WorkspacePlacementCatalog;\n canonicalRoot: WorkspaceNode | null;\n currentLayout: WorkspaceLayout;\n source: string[];\n point: Point;\n heldIntent: WorkspaceDropIntent;\n groupable: boolean;\n gap: number;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n planPlacement?: WorkspacePlacementPlanner;\n}\n\nconst inside = (rect: Rect, point: Point) =>\n point.x >= rect.x && point.x < rect.x + rect.width && point.y >= rect.y && point.y < rect.y + rect.height;\n\nexport function decidePointerPlacement(input: PointerPlacementInput): WorkspacePlacementDecision {\n const { placement, point } = input;\n const header = !!placement.headerTarget;\n const target =\n placement.headerTarget ??\n (inside(placement.bounds, point) ? placement.targets.find(item => inside(item.rect, point)) : undefined);\n const local = localPlacementIntent(input, target, header);\n return decidePlacement({\n ...placement,\n source: input.source,\n point,\n local,\n header,\n currentLayout: input.currentLayout,\n gap: input.gap,\n available: input.available,\n projectLayout: input.projectLayout,\n planPlacement: input.planPlacement\n });\n}\n\n/** Chooses input and availability together from the two operation-specific computed projections. */\nexport function decidePlacement(input: DecisionInput) {\n const boundary = placementOffers({ ...input, contextRect: createContextRectResolver() });\n const selectedKey = selectedScopeKey(boundary.offers, input);\n const sourceSlot = reservedSourceSlot(input);\n const hints = boundary.offers.filter(offer => eligiblePlacementHint(offer, sourceSlot, input.bounds));\n const nearest = hints\n .filter(offer => offer.scope.key !== selectedKey)\n .map(offer => ({ offer, distance: distance(offer, input.point) }))\n .sort((a, b) => a.distance - b.distance)[0];\n const candidate = inside(input.bounds, input.point)\n ? boundary.offers.find(\n offer => inside(offer.hitRect ?? offer.rect, input.point) && (!input.header || placementOwnsChrome(offer))\n )\n : undefined;\n const hit = boundary.hit ?? candidate;\n return {\n acquisition: hit ? { plan: hit.plan, rect: hit.hitRect ?? hit.rect } : undefined,\n intent: acquiredIntent(input, hit),\n hint: placementHint({\n hit: hit && hints.includes(hit) ? hit : undefined,\n selectedKey,\n boundary: boundary.hit,\n nearest\n })\n };\n}\n\nfunction localPlacementIntent(input: PointerPlacementInput, target: WorkspaceTarget | undefined, header: boolean) {\n const { reservationHit } = input.placement;\n const overReservedBody = !header && reservationHit;\n const overReservedTab = header && reservationHit === 'tab' && input.heldIntent.kind === 'tab';\n if (overReservedBody || overReservedTab) {\n return input.heldIntent;\n }\n if (!target) return undefined;\n const anchor = target.panels[0];\n if (!anchor) return { kind: 'invalid' } as const;\n if (header) {\n return headerPlacementIntent(input, target, anchor);\n }\n return {\n kind: 'split',\n destination: {\n target: anchor,\n position: contentDirection(input.point, { rect: target.rect, headerHeight: target.headerHeight })\n }\n } as const;\n}\n\nfunction headerPlacementIntent(input: PointerPlacementInput, target: WorkspaceTarget, anchor: string) {\n const tab = target.tabs.find(item => input.point.x < item.rect.x + item.rect.width / 2);\n const preferred = findGroup(input.canonicalRoot, anchor)?.panels ?? [];\n const index = getTabInsertionIndex(preferred, tab?.id);\n const intent = { kind: 'tab', destination: { target: anchor, position: 'tab', index } } as const;\n const allowed =\n input.groupable || preservesGroupMembership({ root: input.canonicalRoot, source: input.source, intent });\n return allowed ? intent : undefined;\n}\n\nfunction reservedSourceSlot(input: WorkspacePlacementQuery) {\n const preview = input.preview;\n if (\n !input.sourceSlot ||\n preview?.phase !== 'detached' ||\n preview.blocked ||\n preview.allocation !== 'reserved' ||\n preview.cue.kind !== 'group'\n ) {\n return undefined;\n }\n return clipCue(input.sourceSlot, input.bounds);\n}\n\nfunction eligiblePlacementHint(offer: WorkspaceInsertionOffer, sourceSlot: Rect | undefined, bounds: Rect) {\n if (!sourceSlot) return true;\n const rect = clipCue(offer.rect, bounds);\n const vertical = offer.destination.position === 'left' || offer.destination.position === 'right';\n const normal = vertical ? 'x' : 'y';\n const normalSize = vertical ? 'width' : 'height';\n const tangent = vertical ? 'y' : 'x';\n const tangentSize = vertical ? 'height' : 'width';\n const normalInsideSource =\n rect[normal] > sourceSlot[normal] && rect[normal] + rect[normalSize] < sourceSlot[normal] + sourceSlot[normalSize];\n if (!normalInsideSource) return true;\n\n const tangentCoveredBySource =\n rect[tangent] >= sourceSlot[tangent] &&\n rect[tangent] + rect[tangentSize] <= sourceSlot[tangent] + sourceSlot[tangentSize];\n return !tangentCoveredBySource;\n}\n\nfunction placementHint({\n hit,\n selectedKey,\n boundary,\n nearest\n}: {\n hit?: WorkspaceInsertionOffer;\n selectedKey?: string;\n boundary?: WorkspaceInsertionOffer;\n nearest?: { offer: WorkspaceInsertionOffer; distance: number };\n}) {\n if (hit && hit.scope.key !== selectedKey) return hit;\n if (!boundary && nearest && nearest.distance <= 24) return nearest.offer;\n return undefined;\n}\n\nfunction placementOffers(input: OfferInput) {\n const root = (input.projectLayout ?? projectLayout)(input.currentLayout, input.available).root;\n const regions = input.orderingRegions ?? input.regions;\n const offers = createInsertionOffers({\n ...input,\n root,\n regions,\n explorationRegions: input.regions,\n existing: orderOffers({ ...input, root })\n });\n return getBoundaryPlacementOffers({\n offers,\n bounds: input.bounds,\n point: input.point,\n current: input.preview?.intent,\n headers: input.headers ?? [],\n geometry: { regions, source: input.source, gap: input.gap, contextRect: input.contextRect }\n });\n}\n\nfunction acquiredIntent(input: WorkspacePlacementQuery, hit: WorkspaceInsertionOffer | undefined) {\n if (hit) return getPlacementOfferIntent(hit);\n if (!inside(input.bounds, input.point)) return undefined;\n if (input.sourceSlot && inside(input.sourceSlot, input.point)) return input.preview?.intent ?? input.local;\n return input.local;\n}\n\nfunction selectedScopeKey(offers: WorkspaceInsertionOffer[], input: DecisionInput) {\n const preview = input.preview;\n if (!preview || preview.phase !== 'detached') return undefined;\n if ('layout' in preview)\n return describePlacementSlot({\n plan: preview,\n source: input.source,\n available: input.available,\n projectLayout: input.projectLayout\n })?.key;\n return offers.find(offer => matchesPlacementIntent(getPlacementOfferIntent(offer), preview.intent))?.scope.key;\n}\n\nfunction distance(offer: WorkspaceInsertionOffer, point: Point) {\n const rect = offer.hitRect ?? offer.rect;\n const vertical = offer.destination.position === 'left' || offer.destination.position === 'right';\n const tangent = vertical ? point.y : point.x;\n const start = vertical ? rect.y : rect.x;\n const extent = vertical ? rect.height : rect.width;\n const withinTangent = tangent >= start && tangent < start + extent;\n if (!withinTangent) return Infinity;\n\n const normalOffset = vertical ? point.x - rect.x : point.y - rect.y;\n const normalExtent = vertical ? rect.width : rect.height;\n return Math.abs(normalOffset - normalExtent / 2);\n}\n\ninterface OrderOwner {\n key: string;\n owner: WorkspaceSplit;\n rect: Rect;\n adjacencyRect: Rect;\n peers: { node: WorkspaceNode; index: number }[];\n}\n\nfunction orderOwner(input: OfferInput & { root: WorkspaceNode | null }): OrderOwner | undefined {\n const { root, source } = input;\n const key = findSourcePeerRegionKey(root, source) ?? 'root';\n const owner = findWorkspaceRegion(root, key);\n const group = findGroup(input.currentLayout.root, source[0]);\n if (owner?.type !== 'split' || !wholeSource(group, source)) return undefined;\n const ownerRect = (regions: WorkspacePlacedRegion[]) =>\n regions.find(region => region.key === key)?.rect ??\n input.contextRect({ members: getPanelIds(owner).filter(id => !source.includes(id)), allocation: regions, source });\n const rect = ownerRect(input.regions);\n const adjacencyRect = ownerRect(input.orderingRegions ?? input.regions);\n if (!rect || !adjacencyRect) return undefined;\n const from = owner.children.findIndex(node => node.type === 'group' && node.panels.some(id => source.includes(id)));\n if (from < 0) return undefined;\n return {\n key,\n owner,\n rect,\n adjacencyRect,\n peers: owner.children.flatMap((node, index) => (index === from ? [] : [{ node, index }]))\n };\n}\n\nfunction orderOffers(input: OfferInput & { root: WorkspaceNode | null }): WorkspaceInsertionOffer[] {\n const owner = orderOwner(input);\n if (!owner) return [];\n const entries = owner.peers.map(peer => ({ ...peer, after: false }));\n const last = owner.peers.at(-1);\n if (last) {\n entries.push({ ...last, after: true });\n }\n return entries.flatMap((entry, slot) => orderOffer({ input, owner, entry, slot }));\n}\n\ninterface OrderOfferInput {\n input: OfferInput;\n owner: OrderOwner;\n entry: { node: WorkspaceNode; index: number; after: boolean };\n slot: number;\n}\n\nfunction orderOffer({ input, owner, entry, slot }: OrderOfferInput): WorkspaceInsertionOffer[] {\n const neighbors = orderNeighbors({ input, owner, entry, slot });\n if (!neighbors) return [];\n const { region, before } = neighbors;\n const destination = {\n target: getPanelIds(entry.node)[0]!,\n region: region.key,\n position: getSplitSide(owner.owner.axis, entry.after ? 'after' : 'before')\n };\n const plan = (input.planPlacement ?? planWorkspacePlacement)({\n layout: input.currentLayout,\n source: input.source,\n destination,\n available: input.available,\n projectLayout: input.projectLayout,\n operation: 'order'\n });\n if (plan?.kind !== 'reorder') return [];\n const descriptor = describePlacementSlot({\n plan,\n source: input.source,\n available: input.available,\n projectLayout: input.projectLayout\n });\n const boundary = orderBoundary(entry, slot);\n const ownerRect = boundary ? owner.rect : owner.adjacencyRect;\n const area = getOrderHintRect({\n owner: ownerRect,\n recipient: region.rect,\n previous: before?.rect,\n axis: owner.owner.axis,\n after: entry.after,\n sourceSlot: input.sourceSlot,\n boundary\n });\n if (!area || !descriptor) return [];\n return [\n {\n destination,\n owner: owner.key,\n boundary,\n rect: area,\n scopeRect: ownerRect,\n scope: descriptor,\n plan,\n kind: 'order'\n }\n ];\n}\n\nfunction orderBoundary(entry: OrderOfferInput['entry'], slot: number): WorkspaceInsertionOffer['boundary'] {\n if (entry.after) return 'end';\n if (slot === 0) return 'start';\n return undefined;\n}\n\nfunction wholeSource(group: ReturnType<typeof findGroup>, source: string[]) {\n return !!group && group.panels.length === source.length && group.panels.every(id => source.includes(id));\n}\n\nfunction orderNeighbors({ input, owner, entry, slot }: Parameters<typeof orderOffer>[0]) {\n const regions = input.orderingRegions ?? input.regions;\n const region = regions.find(candidate => candidate.key === `${owner.key}.${entry.index}`);\n const previous = owner.peers[slot - 1];\n const before = previous && regions.find(candidate => candidate.key === `${owner.key}.${previous.index}`);\n return !region || (slot > 0 && !entry.after && !before) ? undefined : { region, before };\n}\n\nfunction contentDirection(\n point: Point,\n input: { rect: Rect; headerHeight: number }\n): Exclude<WorkspaceDestination['position'], 'tab'> {\n const { rect, headerHeight } = input;\n const centerX = rect.x + rect.width / 2;\n const contentHeight = Math.max(1, rect.height - headerHeight);\n const centerY = rect.y + headerHeight + contentHeight / 2;\n const dx = (point.x - centerX) / Math.max(1, rect.width / 2);\n const dy = (point.y - centerY) / Math.max(1, contentHeight / 2);\n if (Math.abs(dx) > Math.abs(dy)) return dx < 0 ? 'left' : 'right';\n return dy < 0 ? 'top' : 'bottom';\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function isResizeKey(key: string): boolean;
@@ -0,0 +1,17 @@
1
+ // src/workspace/utils/interaction/resize-input.utils.ts
2
+ var e = [
3
+ "ArrowLeft",
4
+ "ArrowRight",
5
+ "ArrowUp",
6
+ "ArrowDown",
7
+ "Home",
8
+ "End",
9
+ "PageUp",
10
+ "PageDown"
11
+ ];
12
+ function t(t) {
13
+ return e.includes(t);
14
+ }
15
+ export { t as isResizeKey };
16
+
17
+ //# sourceMappingURL=resize-input.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize-input.utils.js","names":["resizeKeys","isResizeKey","key"],"sources":["../../../../src/workspace/utils/interaction/resize-input.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nconst resizeKeys: readonly string[] = [\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown'\n];\n\nexport function isResizeKey(key: string): boolean {\n return resizeKeys.includes(key);\n}\n"],"mappings":";AAGA,IAAMA,IAAgC;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgBC,EAAY,GAAsB;CAChD,OAAOD,EAAW,SAASE,CAAG;AAChC"}
@@ -0,0 +1,22 @@
1
+ export type WorkspaceNode = WorkspaceGroup | WorkspaceSplit;
2
+ export interface WorkspaceGroup {
3
+ type: 'group';
4
+ panels: string[];
5
+ active: string;
6
+ }
7
+ export interface WorkspaceSplit {
8
+ type: 'split';
9
+ axis: 'horizontal' | 'vertical';
10
+ weights: number[];
11
+ children: WorkspaceNode[];
12
+ }
13
+ export interface WorkspaceLayout {
14
+ version: 1;
15
+ root: WorkspaceNode | null;
16
+ closed: string[];
17
+ }
18
+ export declare function getPanelIds(node: WorkspaceNode | null): string[];
19
+ export declare function getSplitSide(axis: WorkspaceSplit['axis'], position: 'before' | 'after'): 'left' | 'right' | 'top' | 'bottom';
20
+ /** Converts consecutive splits on the same axis into siblings. */
21
+ export declare function normalizeLayout(node: WorkspaceNode): WorkspaceNode;
22
+ export declare function normalizeOwnedLayout(node: WorkspaceNode): WorkspaceNode;
@@ -0,0 +1,41 @@
1
+ // src/workspace/utils/model/layout.utils.ts
2
+ function e(t) {
3
+ return t ? t.type === "group" ? t.panels : t.children.flatMap(e) : [];
4
+ }
5
+ function t(e, t) {
6
+ return e === "horizontal" ? t === "before" ? "left" : "right" : t === "before" ? "top" : "bottom";
7
+ }
8
+ function n(e) {
9
+ return i(e, "copy");
10
+ }
11
+ function r(e) {
12
+ return i(e, "owned");
13
+ }
14
+ function i(e, t) {
15
+ if (e.type === "group") return t === "copy" ? {
16
+ ...e,
17
+ panels: [...e.panels]
18
+ } : e;
19
+ let n = e.weights.reduce((e, t) => e + t, 0), r = [], a = t === "copy" ? [] : void 0;
20
+ e.children.forEach((o, s) => {
21
+ let c = i(o, t), l = e.weights[s] / n;
22
+ if (!(l > 0)) throw TypeError("Split proportions exceed the supported range");
23
+ if (c.type === "split" && c.axis === e.axis) {
24
+ let t = a ??= e.weights.slice(0, s), n = c.weights.reduce((e, t) => e + t, 0);
25
+ c.children.forEach((e, i) => {
26
+ r.push(e), t.push(l * c.weights[i] / n);
27
+ });
28
+ } else !a && l !== e.weights[s] && (a = e.weights.slice(0, s)), r.push(c), a?.push(l);
29
+ });
30
+ let o = a ?? e.weights;
31
+ if (!o.every((e) => Number.isFinite(e) && e > 0)) throw TypeError("Split proportions exceed the supported range");
32
+ return {
33
+ type: "split",
34
+ axis: e.axis,
35
+ children: r,
36
+ weights: o
37
+ };
38
+ }
39
+ export { e as getPanelIds, t as getSplitSide, n as normalizeLayout, r as normalizeOwnedLayout };
40
+
41
+ //# sourceMappingURL=layout.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.utils.js","names":["getPanelIds","node","getSplitSide","axis","position","normalizeLayout","normalizeNode","normalizeOwnedLayout","ownership","total","a","b","children","weights","normalized","child","share","index","shares","sum","nested","normalizedWeights","weight"],"sources":["../../../../src/workspace/utils/model/layout.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nexport type WorkspaceNode = WorkspaceGroup | WorkspaceSplit;\n\nexport interface WorkspaceGroup {\n type: 'group';\n panels: string[];\n active: string;\n}\n\nexport interface WorkspaceSplit {\n type: 'split';\n axis: 'horizontal' | 'vertical';\n weights: number[];\n children: WorkspaceNode[];\n}\n\nexport interface WorkspaceLayout {\n version: 1;\n root: WorkspaceNode | null;\n closed: string[];\n}\n\nexport function getPanelIds(node: WorkspaceNode | null): string[] {\n if (!node) return [];\n return node.type === 'group' ? node.panels : node.children.flatMap(getPanelIds);\n}\n\nexport function getSplitSide(\n axis: WorkspaceSplit['axis'],\n position: 'before' | 'after'\n): 'left' | 'right' | 'top' | 'bottom' {\n if (axis === 'horizontal') return position === 'before' ? 'left' : 'right';\n return position === 'before' ? 'top' : 'bottom';\n}\n\n/** Converts consecutive splits on the same axis into siblings. */\nexport function normalizeLayout(node: WorkspaceNode): WorkspaceNode {\n return normalizeNode(node, 'copy');\n}\n\nexport function normalizeOwnedLayout(node: WorkspaceNode): WorkspaceNode {\n return normalizeNode(node, 'owned');\n}\n\nfunction normalizeNode(node: WorkspaceNode, ownership: 'copy' | 'owned'): WorkspaceNode {\n if (node.type === 'group') return ownership === 'copy' ? { ...node, panels: [...node.panels] } : node;\n const total = node.weights.reduce((a, b) => a + b, 0);\n const children: WorkspaceNode[] = [];\n let weights: number[] | undefined = ownership === 'copy' ? [] : undefined;\n node.children.forEach((child, index) => {\n const normalized = normalizeNode(child, ownership);\n const share = node.weights[index]! / total;\n if (!(share > 0)) throw new TypeError('Split proportions exceed the supported range');\n if (normalized.type === 'split' && normalized.axis === node.axis) {\n const shares = (weights ??= node.weights.slice(0, index));\n const sum = normalized.weights.reduce((a, b) => a + b, 0);\n normalized.children.forEach((nested, i) => {\n children.push(nested);\n shares.push((share * normalized.weights[i]!) / sum);\n });\n } else {\n if (!weights && share !== node.weights[index]) {\n weights = node.weights.slice(0, index);\n }\n children.push(normalized);\n weights?.push(share);\n }\n });\n const normalizedWeights = weights ?? node.weights;\n if (!normalizedWeights.every(weight => Number.isFinite(weight) && weight > 0))\n throw new TypeError('Split proportions exceed the supported range');\n return { type: 'split', axis: node.axis, children, weights: normalizedWeights };\n}\n"],"mappings":";AAwBA,SAAgBA,EAAY,GAAsC;CAEhE,OADKC,IACEA,EAAK,SAAS,UAAUA,EAAK,SAASA,EAAK,SAAS,QAAQD,CAAW,IAD5D,CAAC;AAErB;AAEA,SAAgBE,EACd,GACA,GACqC;CAErC,OADIC,MAAS,eAAqBC,MAAa,WAAW,SAAS,UAC5DA,MAAa,WAAW,QAAQ;AACzC;AAGA,SAAgBC,EAAgB,GAAoC;CAClE,OAAOC,EAAcL,GAAM,MAAM;AACnC;AAEA,SAAgBM,EAAqB,GAAoC;CACvE,OAAOD,EAAcL,GAAM,OAAO;AACpC;AAEA,SAASK,EAAc,GAAqB,GAA4C;CACtF,IAAIL,EAAK,SAAS,SAAS,OAAOO,MAAc,SAAS;EAAE,GAAGP;EAAM,QAAQ,CAAC,GAAGA,EAAK,MAAM;CAAE,IAAIA;CACjG,IAAMQ,IAAQR,EAAK,QAAQ,QAAQ,GAAG,MAAMS,IAAIC,GAAG,CAAC,GAC9CC,IAA4B,CAAC,GAC/BC,IAAgCL,MAAc,SAAS,CAAC,IAAI,KAAA;CAChE,EAAK,SAAS,SAAS,GAAO,MAAU;EACtC,IAAMM,IAAaR,EAAcS,GAAOP,CAAS,GAC3CQ,IAAQf,EAAK,QAAQgB,KAAUR;EACrC,IAAI,EAAEO,IAAQ,IAAI,MAAU,UAAU,8CAA8C;EACpF,IAAIF,EAAW,SAAS,WAAWA,EAAW,SAASb,EAAK,MAAM;GAChE,IAAMiB,IAAU,MAAYjB,EAAK,QAAQ,MAAM,GAAGgB,CAAK,GACjDE,IAAML,EAAW,QAAQ,QAAQ,GAAG,MAAMJ,IAAIC,GAAG,CAAC;GACxD,EAAW,SAAS,SAAS,GAAQ,MAAM;IAEzC,AADAC,EAAS,KAAKQ,CAAM,GACpBF,EAAO,KAAMF,IAAQF,EAAW,QAAQ,KAAOK,CAAG;GACpD,CAAC;EACH,OAKE,AAJI,CAACN,KAAWG,MAAUf,EAAK,QAAQgB,OACrC,IAAUhB,EAAK,QAAQ,MAAM,GAAGgB,CAAK,IAEvCL,EAAS,KAAKE,CAAU,GACxBD,GAAS,KAAKG,CAAK;CAEvB,CAAC;CACD,IAAMK,IAAoBR,KAAWZ,EAAK;CAC1C,IAAI,CAACoB,EAAkB,OAAM,MAAU,OAAO,SAASC,CAAM,KAAKA,IAAS,CAAC,GAC1E,MAAU,UAAU,8CAA8C;CACpE,OAAO;EAAE,MAAM;EAAS,MAAMrB,EAAK;EAAM;EAAU,SAASoB;CAAkB;AAChF"}
@@ -0,0 +1,14 @@
1
+ import type { WorkspacePlacementIntent } from '../interaction/command.utils.js';
2
+ import type { WorkspaceLayout, WorkspaceNode } from './layout.utils.js';
3
+ export declare function preservesGroupMembership(input: {
4
+ root: WorkspaceNode | null;
5
+ source: string[];
6
+ intent: WorkspacePlacementIntent;
7
+ }): boolean;
8
+ export declare function getWorkspacePanelSource(input: {
9
+ layout?: WorkspaceLayout;
10
+ anchor: string;
11
+ available: string[];
12
+ }): string[];
13
+ /** Maps a visible insertion neighbor to its original order, retaining dormant members. */
14
+ export declare function getTabInsertionIndex(preferred: string[], before: string | undefined): number;
@@ -0,0 +1,17 @@
1
+ import { findGroup as e } from "./operations.utils.js";
2
+ // src/workspace/utils/model/membership.utils.ts
3
+ function t(t) {
4
+ let n = e(t.root, t.source[0]);
5
+ return !n || !t.source.length ? !1 : t.intent.kind === "tab" ? e(t.root, t.intent.destination.target) === n : n.panels.every((e) => t.source.includes(e));
6
+ }
7
+ function n(t) {
8
+ let n = e(t.layout?.root ?? null, t.anchor);
9
+ return n && n.panels.filter((e) => !t.layout?.closed.includes(e) && t.available.includes(e)).length === 1 ? [...n.panels] : [t.anchor];
10
+ }
11
+ function r(e, t) {
12
+ let n = t === void 0 ? e.length : e.indexOf(t);
13
+ return n < 0 ? e.length : n;
14
+ }
15
+ export { r as getTabInsertionIndex, n as getWorkspacePanelSource, t as preservesGroupMembership };
16
+
17
+ //# sourceMappingURL=membership.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"membership.utils.js","names":["preservesGroupMembership","origin","findGroup","input","id","getWorkspacePanelSource","group","getTabInsertionIndex","index","before","preferred"],"sources":["../../../../src/workspace/utils/model/membership.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { findGroup } from './operations.utils.js';\n\nimport type { WorkspacePlacementIntent } from '../interaction/command.utils.js';\nimport type { WorkspaceLayout, WorkspaceNode } from './layout.utils.js';\n\nexport function preservesGroupMembership(input: {\n root: WorkspaceNode | null;\n source: string[];\n intent: WorkspacePlacementIntent;\n}): boolean {\n const origin = findGroup(input.root, input.source[0]);\n if (!origin || !input.source.length) return false;\n if (input.intent.kind === 'tab') return findGroup(input.root, input.intent.destination.target) === origin;\n return origin.panels.every(id => input.source.includes(id));\n}\n\nexport function getWorkspacePanelSource(input: {\n layout?: WorkspaceLayout;\n anchor: string;\n available: string[];\n}): string[] {\n const group = findGroup(input.layout?.root ?? null, input.anchor);\n return group &&\n group.panels.filter(id => !input.layout?.closed.includes(id) && input.available.includes(id)).length === 1\n ? [...group.panels]\n : [input.anchor];\n}\n\n/** Maps a visible insertion neighbor to its original order, retaining dormant members. */\nexport function getTabInsertionIndex(preferred: string[], before: string | undefined): number {\n const index = before === undefined ? preferred.length : preferred.indexOf(before);\n return index < 0 ? preferred.length : index;\n}\n"],"mappings":";;AAQA,SAAgBA,EAAyB,GAI7B;CACV,IAAMC,IAASC,EAAUC,EAAM,MAAMA,EAAM,OAAO,EAAE;CAGpD,OAFI,CAACF,KAAU,CAACE,EAAM,OAAO,SAAe,KACxCA,EAAM,OAAO,SAAS,QAAcD,EAAUC,EAAM,MAAMA,EAAM,OAAO,YAAY,MAAM,MAAMF,IAC5FA,EAAO,OAAO,OAAM,MAAME,EAAM,OAAO,SAASC,CAAE,CAAC;AAC5D;AAEA,SAAgBC,EAAwB,GAI3B;CACX,IAAMC,IAAQJ,EAAUC,EAAM,QAAQ,QAAQ,MAAMA,EAAM,MAAM;CAChE,OAAOG,KACLA,EAAM,OAAO,QAAO,MAAM,CAACH,EAAM,QAAQ,OAAO,SAASC,CAAE,KAAKD,EAAM,UAAU,SAASC,CAAE,CAAC,CAAC,CAAC,WAAW,IACvG,CAAC,GAAGE,EAAM,MAAM,IAChB,CAACH,EAAM,MAAM;AACnB;AAGA,SAAgBI,EAAqB,GAAqB,GAAoC;CAC5F,IAAMC,IAAQC,MAAW,KAAA,IAAYC,EAAU,SAASA,EAAU,QAAQD,CAAM;CAChF,OAAOD,IAAQ,IAAIE,EAAU,SAASF;AACxC"}
@@ -0,0 +1,31 @@
1
+ import type { WorkspaceGroup, WorkspaceLayout, WorkspaceNode } from './layout.utils.js';
2
+ export interface WorkspaceDestination {
3
+ target: string;
4
+ /** Region path in the visible projection of the current layout. */
5
+ region?: string;
6
+ position: 'tab' | 'left' | 'right' | 'top' | 'bottom';
7
+ index?: number;
8
+ }
9
+ export declare function findGroup(node: WorkspaceNode | null, id?: string): WorkspaceGroup | undefined;
10
+ export declare function isValidInsertionIndex(index: number | undefined): boolean;
11
+ /** Removes carried panels from the arrangement and closed list without changing the saved layout. */
12
+ export declare function createDetachedLayout(layout: WorkspaceLayout, source: string[]): WorkspaceLayout;
13
+ export declare function placePanels(input: {
14
+ layout: WorkspaceLayout;
15
+ source: string[];
16
+ destination: WorkspaceDestination;
17
+ splitWeights?: [number, number];
18
+ }): WorkspaceLayout | undefined;
19
+ /** Retains panel placement and active preference when closing. */
20
+ export declare function closePanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined;
21
+ export declare function openPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined;
22
+ /** Retains saved panel positions when supplied panels change. */
23
+ export declare function reconcilePanels(layout: WorkspaceLayout, available: string[]): WorkspaceLayout;
24
+ /** Creates the visible arrangement while retaining the saved snapshot. */
25
+ export declare function projectLayout(layout: WorkspaceLayout, available: string[]): WorkspaceLayout;
26
+ export declare function selectPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined;
27
+ export declare function getFullscreenWorkspaceLayout(layout: WorkspaceLayout, anchor: string | undefined): {
28
+ version: 1;
29
+ closed: string[];
30
+ root: WorkspaceGroup;
31
+ } | undefined;