@nvidia-elements/core 2.23.5 → 2.23.6

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 (209) hide show
  1. package/CHANGELOG.md +6 -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/bundles/index.js +7 -7
  10. package/dist/button/button2.js +1 -1
  11. package/dist/button-group/button-group2.js +1 -1
  12. package/dist/card/card2.js +4 -4
  13. package/dist/chat-message/chat-message2.js +1 -1
  14. package/dist/checkbox/checkbox-group2.js +1 -1
  15. package/dist/checkbox/checkbox2.js +1 -1
  16. package/dist/color/color2.js +1 -1
  17. package/dist/combobox/combobox2.js +1 -1
  18. package/dist/copy-button/copy-button2.js +1 -1
  19. package/dist/custom-elements.json +1000 -229
  20. package/dist/date/date2.js +1 -1
  21. package/dist/datetime/datetime2.js +1 -1
  22. package/dist/dialog/dialog-footer2.js +1 -1
  23. package/dist/dialog/dialog-header2.js +1 -1
  24. package/dist/dialog/dialog2.js +1 -1
  25. package/dist/divider/divider2.js +1 -1
  26. package/dist/dot/dot2.js +1 -1
  27. package/dist/drag-handle/drag-handle2.js +1 -1
  28. package/dist/drawer/drawer-content2.js +1 -1
  29. package/dist/drawer/drawer-footer2.js +1 -1
  30. package/dist/drawer/drawer-header2.js +1 -1
  31. package/dist/drawer/drawer2.js +1 -1
  32. package/dist/dropdown/dropdown-footer2.js +1 -1
  33. package/dist/dropdown/dropdown-header2.js +1 -1
  34. package/dist/dropdown/dropdown2.js +1 -1
  35. package/dist/dropdown-group/dropdown-group.js +1 -1
  36. package/dist/dropzone/dropzone2.js +1 -1
  37. package/dist/file/file2.js +1 -1
  38. package/dist/format-bytes/format-bytes2.js +1 -1
  39. package/dist/format-datetime/format-datetime2.js +1 -1
  40. package/dist/format-number/format-number2.js +1 -1
  41. package/dist/format-relative-time/format-relative-time2.js +1 -1
  42. package/dist/format-truncate/format-truncate2.js +1 -1
  43. package/dist/forms/control/control2.js +1 -1
  44. package/dist/forms/control-group/control-group2.js +1 -1
  45. package/dist/forms/control-message/control-message2.js +1 -1
  46. package/dist/gauge/gauge2.js +1 -1
  47. package/dist/ghost/ghost2.js +1 -1
  48. package/dist/grid/cell/cell2.js +1 -1
  49. package/dist/grid/column/column2.js +1 -1
  50. package/dist/grid/footer/footer2.js +1 -1
  51. package/dist/grid/grid2.js +1 -1
  52. package/dist/grid/header/header2.js +1 -1
  53. package/dist/grid/placeholder/placeholder2.js +1 -1
  54. package/dist/grid/row/row2.js +1 -1
  55. package/dist/icon/icon2.js +1 -1
  56. package/dist/icon-button/icon-button2.js +1 -1
  57. package/dist/iframe/iframe2.js +1 -1
  58. package/dist/index.js +1 -1
  59. package/dist/input/input-group2.js +1 -1
  60. package/dist/input/input2.js +1 -1
  61. package/dist/joystick/joystick2.js +1 -1
  62. package/dist/logo/logo2.js +1 -1
  63. package/dist/menu/menu-group2.js +1 -1
  64. package/dist/menu/menu-item2.js +1 -1
  65. package/dist/menu/menu2.js +1 -1
  66. package/dist/month/month2.js +1 -1
  67. package/dist/notification/notification-group2.js +1 -1
  68. package/dist/notification/notification2.js +1 -1
  69. package/dist/page/page-panel/page-panel-content2.js +1 -1
  70. package/dist/page/page-panel/page-panel-footer2.js +1 -1
  71. package/dist/page/page-panel/page-panel-header2.js +1 -1
  72. package/dist/page/page-panel/page-panel2.js +1 -1
  73. package/dist/page/page2.js +1 -1
  74. package/dist/page-header/page-header2.js +1 -1
  75. package/dist/page-loader/page-loader2.js +1 -1
  76. package/dist/pagination/pagination2.js +1 -1
  77. package/dist/panel/panel2.js +4 -4
  78. package/dist/password/password2.js +1 -1
  79. package/dist/preferences-input/preferences-input2.js +1 -1
  80. package/dist/progress-bar/progress-bar2.js +1 -1
  81. package/dist/progress-dot/progress-dot2.js +1 -1
  82. package/dist/progress-ring/progress-ring2.js +1 -1
  83. package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
  84. package/dist/pulse/pulse2.js +1 -1
  85. package/dist/radio/radio-group2.js +1 -1
  86. package/dist/radio/radio2.js +1 -1
  87. package/dist/range/range2.js +1 -1
  88. package/dist/resize-handle/resize-handle2.js +1 -1
  89. package/dist/search/search2.js +1 -1
  90. package/dist/select/select2.js +1 -1
  91. package/dist/skeleton/skeleton2.js +1 -1
  92. package/dist/sort-button/sort-button2.js +1 -1
  93. package/dist/sparkline/sparkline2.js +1 -1
  94. package/dist/star-rating/star-rating2.js +1 -1
  95. package/dist/steps/steps2.js +2 -2
  96. package/dist/switch/switch-group2.js +1 -1
  97. package/dist/switch/switch2.js +1 -1
  98. package/dist/tabs/tabs-group2.js +1 -1
  99. package/dist/tabs/tabs-item-group2.js +1 -1
  100. package/dist/tabs/tabs2.js +2 -2
  101. package/dist/tag/tag2.js +1 -1
  102. package/dist/textarea/textarea2.js +1 -1
  103. package/dist/time/time2.js +1 -1
  104. package/dist/toast/toast2.js +1 -1
  105. package/dist/toggletip/toggletip-footer2.js +1 -1
  106. package/dist/toggletip/toggletip-header2.js +1 -1
  107. package/dist/toggletip/toggletip2.js +1 -1
  108. package/dist/toolbar/toolbar2.js +1 -1
  109. package/dist/tooltip/tooltip2.js +1 -1
  110. package/dist/tree/tree-node2.js +1 -1
  111. package/dist/tree/tree2.js +1 -1
  112. package/dist/week/week2.js +1 -1
  113. package/dist/workspace/controllers/workspace-composition.controller.d.ts +4 -1
  114. package/dist/workspace/controllers/workspace-composition.controller.js +69 -39
  115. package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -1
  116. package/dist/workspace/controllers/workspace-rearrange.controller.js +27 -27
  117. package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -1
  118. package/dist/workspace/controllers/workspace-restoration.controller.js +2 -2
  119. package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -1
  120. package/dist/workspace/panel/panel2.js +2 -2
  121. package/dist/workspace/panel/panel2.js.map +1 -1
  122. package/dist/workspace/panel-content/panel-content2.js +1 -1
  123. package/dist/workspace/panel-footer/panel-footer2.js +1 -1
  124. package/dist/workspace/panel-header/panel-header2.js +1 -1
  125. package/dist/workspace/utils/comparison.utils.d.ts +3 -0
  126. package/dist/workspace/utils/comparison.utils.js +13 -0
  127. package/dist/workspace/utils/comparison.utils.js.map +1 -0
  128. package/dist/workspace/utils/evaluation.utils.d.ts +65 -6
  129. package/dist/workspace/utils/evaluation.utils.js +334 -99
  130. package/dist/workspace/utils/evaluation.utils.js.map +1 -1
  131. package/dist/workspace/utils/geometry/allocation.utils.js +15 -13
  132. package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -1
  133. package/dist/workspace/utils/geometry/sizing.utils.d.ts +2 -0
  134. package/dist/workspace/utils/geometry/sizing.utils.js +37 -17
  135. package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -1
  136. package/dist/workspace/utils/interaction/boundary.utils.d.ts +2 -2
  137. package/dist/workspace/utils/interaction/boundary.utils.js +2 -2
  138. package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -1
  139. package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +3 -3
  140. package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -1
  141. package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +11 -9
  142. package/dist/workspace/utils/interaction/insertion-offers.utils.js +37 -43
  143. package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -1
  144. package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +6 -1
  145. package/dist/workspace/utils/interaction/placement-decision.utils.js +94 -87
  146. package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -1
  147. package/dist/workspace/utils/model/layout.utils.d.ts +2 -1
  148. package/dist/workspace/utils/model/layout.utils.js +12 -10
  149. package/dist/workspace/utils/model/layout.utils.js.map +1 -1
  150. package/dist/workspace/utils/model/membership.utils.d.ts +4 -0
  151. package/dist/workspace/utils/model/membership.utils.js +13 -4
  152. package/dist/workspace/utils/model/membership.utils.js.map +1 -1
  153. package/dist/workspace/utils/model/operations.utils.d.ts +1 -0
  154. package/dist/workspace/utils/model/operations.utils.js +51 -46
  155. package/dist/workspace/utils/model/operations.utils.js.map +1 -1
  156. package/dist/workspace/utils/model/projection.utils.d.ts +4 -2
  157. package/dist/workspace/utils/model/projection.utils.js +49 -40
  158. package/dist/workspace/utils/model/projection.utils.js.map +1 -1
  159. package/dist/workspace/utils/model/value.utils.d.ts +4 -3
  160. package/dist/workspace/utils/model/value.utils.js +15 -50
  161. package/dist/workspace/utils/model/value.utils.js.map +1 -1
  162. package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +2 -0
  163. package/dist/workspace/utils/placement/acquisition-sizing.utils.js +30 -22
  164. package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -1
  165. package/dist/workspace/utils/placement/group-insertion.utils.d.ts +19 -13
  166. package/dist/workspace/utils/placement/group-insertion.utils.js +50 -47
  167. package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -1
  168. package/dist/workspace/utils/placement/planner.utils.d.ts +13 -2
  169. package/dist/workspace/utils/placement/planner.utils.js +79 -73
  170. package/dist/workspace/utils/placement/planner.utils.js.map +1 -1
  171. package/dist/workspace/utils/placement/preparation.utils.d.ts +5 -2
  172. package/dist/workspace/utils/placement/preparation.utils.js +45 -41
  173. package/dist/workspace/utils/placement/preparation.utils.js.map +1 -1
  174. package/dist/workspace/utils/placement/region.utils.js +32 -32
  175. package/dist/workspace/utils/placement/region.utils.js.map +1 -1
  176. package/dist/workspace/utils/placement/scope.utils.d.ts +34 -0
  177. package/dist/workspace/utils/placement/scope.utils.js +155 -0
  178. package/dist/workspace/utils/placement/scope.utils.js.map +1 -0
  179. package/dist/workspace/utils/placement/session.utils.d.ts +11 -0
  180. package/dist/workspace/utils/placement/session.utils.js +78 -0
  181. package/dist/workspace/utils/placement/session.utils.js.map +1 -0
  182. package/dist/workspace/utils/placement/split-sizing.utils.d.ts +2 -2
  183. package/dist/workspace/utils/placement/split-sizing.utils.js +19 -19
  184. package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -1
  185. package/dist/workspace/utils/presentation/composition.utils.d.ts +1 -1
  186. package/dist/workspace/utils/presentation/composition.utils.js +4 -2
  187. package/dist/workspace/utils/presentation/composition.utils.js.map +1 -1
  188. package/dist/workspace/utils/presentation/groups.utils.d.ts +3 -3
  189. package/dist/workspace/utils/presentation/groups.utils.js +40 -30
  190. package/dist/workspace/utils/presentation/groups.utils.js.map +1 -1
  191. package/dist/workspace/utils/presentation/measurements.utils.d.ts +1 -0
  192. package/dist/workspace/utils/presentation/measurements.utils.js +6 -14
  193. package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -1
  194. package/dist/workspace/utils/presentation/offers.utils.d.ts +1 -1
  195. package/dist/workspace/utils/presentation/offers.utils.js +3 -3
  196. package/dist/workspace/utils/presentation/offers.utils.js.map +1 -1
  197. package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
  198. package/dist/workspace/utils/presentation/preview.utils.js +14 -3
  199. package/dist/workspace/utils/presentation/preview.utils.js.map +1 -1
  200. package/dist/workspace/workspace.examples.js.map +1 -1
  201. package/dist/workspace/workspace.examples.json +4 -4
  202. package/dist/workspace/workspace.js +1 -1
  203. package/dist/workspace/workspace.js.map +1 -1
  204. package/dist/workspace/workspace2.js +206 -212
  205. package/dist/workspace/workspace2.js.map +1 -1
  206. package/package.json +1 -1
  207. package/dist/workspace/utils/placement/context.utils.d.ts +0 -36
  208. package/dist/workspace/utils/placement/context.utils.js +0 -135
  209. package/dist/workspace/utils/placement/context.utils.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"value.utils.js","names":["layoutKeys","groupKeys","splitKeys","parseWorkspaceValue","value","data","ids","record","item","node","id","splitShape","child","normalizeLayout","serializeWorkspaceValue","layout","sameSerializedWorkspaceLayout","left","right","hasOrderedKeys","sameValues","sameNode","weight","sum","keys","sameGroup","sameSplit","sameChildren","index","key","expected"],"sources":["../../../../src/workspace/utils/model/value.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { normalizeLayout } from './layout.utils.js';\n\nimport type { WorkspaceGroup, WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';\n\nconst layoutKeys = ['version', 'root', 'closed'];\nconst groupKeys = ['type', 'panels', 'active'];\nconst splitKeys = ['type', 'axis', 'children', 'weights'];\n\nexport function parseWorkspaceValue(value: string): WorkspaceLayout | undefined {\n if (!value) return undefined;\n\n const data: unknown = JSON.parse(value);\n const ids = new Set<string>();\n const record = (item: unknown): item is Record<string, unknown> => typeof item === 'object' && item !== null;\n const node = (item: unknown): item is WorkspaceNode => {\n if (!record(item)) return false;\n if (item.type === 'group') {\n if (\n !Array.isArray(item.panels) ||\n !item.panels.length ||\n typeof item.active !== 'string' ||\n !item.panels.includes(item.active)\n ) {\n return false;\n }\n return item.panels.every(id => {\n if (typeof id !== 'string' || !id || ids.has(id)) return false;\n ids.add(id);\n return true;\n });\n }\n if (!splitShape(item)) return false;\n return item.children.every(child => node(child));\n };\n if (\n !record(data) ||\n data.version !== 1 ||\n !(data.root === null || node(data.root)) ||\n !Array.isArray(data.closed) ||\n !data.closed.every(id => typeof id === 'string' && ids.has(id)) ||\n new Set(data.closed).size !== data.closed.length\n ) {\n throw new TypeError('Invalid workspace arrangement');\n }\n return { version: 1, root: data.root === null ? null : normalizeLayout(data.root), closed: [...data.closed] };\n}\n\nexport function serializeWorkspaceValue(layout: WorkspaceLayout | undefined): string {\n return layout ? JSON.stringify(layout) : '';\n}\n\n/** Compares serialized layout representations, including property order and supplied group fields. */\nexport function sameSerializedWorkspaceLayout(\n left: WorkspaceLayout | undefined,\n right: WorkspaceLayout | undefined\n): boolean {\n if (left === right) {\n return true;\n }\n if (!left || !right) {\n return false;\n }\n if (!hasOrderedKeys(left, layoutKeys) || !hasOrderedKeys(right, layoutKeys)) {\n return serializeWorkspaceValue(left) === serializeWorkspaceValue(right);\n }\n return left.version === right.version && sameValues(left.closed, right.closed) && sameNode(left.root, right.root);\n}\n\nfunction splitShape(item: Record<string, unknown>): item is Record<string, unknown> & WorkspaceSplit {\n if (item.type !== 'split' || !['horizontal', 'vertical'].includes(String(item.axis))) return false;\n if (!Array.isArray(item.children) || item.children.length < 2) return false;\n if (!Array.isArray(item.weights) || item.weights.length !== item.children.length) return false;\n if (!item.weights.every(weight => typeof weight === 'number' && Number.isFinite(weight) && weight > 0)) return false;\n return Number.isFinite(item.weights.reduce((sum: number, weight: number) => sum + weight, 0));\n}\n\nfunction sameNode(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean {\n if (left === right) {\n return true;\n }\n if (!left || !right || left.type !== right.type) {\n return false;\n }\n const keys = left.type === 'group' ? groupKeys : splitKeys;\n if (!hasOrderedKeys(left, keys) || !hasOrderedKeys(right, keys)) {\n return JSON.stringify(left) === JSON.stringify(right);\n }\n return left.type === 'group' ? sameGroup(left, right) : sameSplit(left, right);\n}\n\nfunction sameGroup(left: WorkspaceGroup, right: WorkspaceNode) {\n return right.type === 'group' && left.active === right.active && sameValues(left.panels, right.panels);\n}\n\nfunction sameSplit(left: WorkspaceSplit, right: WorkspaceNode) {\n return (\n right.type === 'split' &&\n left.axis === right.axis &&\n sameValues(left.weights, right.weights) &&\n sameChildren(left.children, right.children)\n );\n}\n\nfunction sameChildren(left: WorkspaceNode[], right: WorkspaceNode[]) {\n if (left === right) {\n return true;\n }\n if (left.length !== right.length) {\n return false;\n }\n for (let index = 0; index < left.length; index++) {\n if (!sameNode(left[index]!, right[index]!)) {\n return false;\n }\n }\n return true;\n}\n\nfunction sameValues<T>(left: T[], right: T[]) {\n if (left === right) {\n return true;\n }\n if (left.length !== right.length) {\n return false;\n }\n for (let index = 0; index < left.length; index++) {\n if (left[index] !== right[index]) {\n return false;\n }\n }\n return true;\n}\n\nfunction hasOrderedKeys(value: object, expected: string[]) {\n if ('toJSON' in value) {\n return false;\n }\n let index = 0;\n for (const key in value) {\n if (!Object.hasOwn(value, key)) {\n continue;\n }\n if (key !== expected[index++]) {\n return false;\n }\n }\n return index === expected.length;\n}\n"],"mappings":";;AAOA,IAAMA,IAAa;CAAC;CAAW;CAAQ;AAAQ,GACzCC,IAAY;CAAC;CAAQ;CAAU;AAAQ,GACvCC,IAAY;CAAC;CAAQ;CAAQ;CAAY;AAAS;AAExD,SAAgBC,EAAoB,GAA4C;CAC9E,IAAI,CAACC,GAAO;CAEZ,IAAMC,IAAgB,KAAK,MAAMD,CAAK,GAChCE,oBAAM,IAAI,IAAY,GACtBC,KAAU,MAAmD,OAAOC,KAAS,cAAYA,GACzFC,KAAQ,MACPF,EAAOC,CAAI,IACZA,EAAK,SAAS,UAEd,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,UACb,OAAOA,EAAK,UAAW,YACvB,CAACA,EAAK,OAAO,SAASA,EAAK,MAAM,IAE1B,KAEFA,EAAK,OAAO,OAAM,MACnB,OAAOE,KAAO,YAAY,CAACA,KAAMJ,EAAI,IAAII,CAAE,IAAU,MACzDJ,EAAI,IAAII,CAAE,GACH,GACR,IAEEC,EAAWH,CAAI,IACbA,EAAK,SAAS,OAAM,MAASC,EAAKG,CAAK,CAAC,IADjB,KAhBJ;CAmB5B,IACE,CAACL,EAAOF,CAAI,KACZA,EAAK,YAAY,KACjB,EAAEA,EAAK,SAAS,QAAQI,EAAKJ,EAAK,IAAI,MACtC,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,OAAM,MAAM,OAAOK,KAAO,YAAYJ,EAAI,IAAII,CAAE,CAAC,KAC9D,IAAI,IAAIL,EAAK,MAAM,CAAC,CAAC,SAASA,EAAK,OAAO,QAE1C,MAAU,UAAU,+BAA+B;CAErD,OAAO;EAAE,SAAS;EAAG,MAAMA,EAAK,SAAS,OAAO,OAAOQ,EAAgBR,EAAK,IAAI;EAAG,QAAQ,CAAC,GAAGA,EAAK,MAAM;CAAE;AAC9G;AAEA,SAAgBS,EAAwB,GAA6C;CACnF,OAAOC,IAAS,KAAK,UAAUA,CAAM,IAAI;AAC3C;AAGA,SAAgBC,EACd,GACA,GACS;CAUT,OATIC,MAASC,IACJ,KAEL,CAACD,KAAQ,CAACC,IACL,KAEL,CAACC,EAAeF,GAAMjB,CAAU,KAAK,CAACmB,EAAeD,GAAOlB,CAAU,IACjEc,EAAwBG,CAAI,MAAMH,EAAwBI,CAAK,IAEjED,EAAK,YAAYC,EAAM,WAAWE,EAAWH,EAAK,QAAQC,EAAM,MAAM,KAAKG,EAASJ,EAAK,MAAMC,EAAM,IAAI;AAClH;AAEA,SAASP,EAAW,GAAiF;CAKnG,OAJIH,EAAK,SAAS,WAAW,CAAC,CAAC,cAAc,UAAU,CAAC,CAAC,SAAS,OAAOA,EAAK,IAAI,CAAC,KAC/E,CAAC,MAAM,QAAQA,EAAK,QAAQ,KAAKA,EAAK,SAAS,SAAS,KACxD,CAAC,MAAM,QAAQA,EAAK,OAAO,KAAKA,EAAK,QAAQ,WAAWA,EAAK,SAAS,UACtE,CAACA,EAAK,QAAQ,OAAM,MAAU,OAAOc,KAAW,YAAY,OAAO,SAASA,CAAM,KAAKA,IAAS,CAAC,IAAU,KACxG,OAAO,SAASd,EAAK,QAAQ,QAAQ,GAAa,MAAmBe,IAAMD,GAAQ,CAAC,CAAC;AAC9F;AAEA,SAASD,EAAS,GAA4B,GAAsC;CAClF,IAAIJ,MAASC,GACX,OAAO;CAET,IAAI,CAACD,KAAQ,CAACC,KAASD,EAAK,SAASC,EAAM,MACzC,OAAO;CAET,IAAMM,IAAOP,EAAK,SAAS,UAAUhB,IAAYC;CAIjD,OAHI,CAACiB,EAAeF,GAAMO,CAAI,KAAK,CAACL,EAAeD,GAAOM,CAAI,IACrD,KAAK,UAAUP,CAAI,MAAM,KAAK,UAAUC,CAAK,IAE/CD,EAAK,SAAS,UAAUQ,EAAUR,GAAMC,CAAK,IAAIQ,EAAUT,GAAMC,CAAK;AAC/E;AAEA,SAASO,EAAU,GAAsB,GAAsB;CAC7D,OAAOP,EAAM,SAAS,WAAWD,EAAK,WAAWC,EAAM,UAAUE,EAAWH,EAAK,QAAQC,EAAM,MAAM;AACvG;AAEA,SAASQ,EAAU,GAAsB,GAAsB;CAC7D,OACER,EAAM,SAAS,WACfD,EAAK,SAASC,EAAM,QACpBE,EAAWH,EAAK,SAASC,EAAM,OAAO,KACtCS,EAAaV,EAAK,UAAUC,EAAM,QAAQ;AAE9C;AAEA,SAASS,EAAa,GAAuB,GAAwB;CACnE,IAAIV,MAASC,GACX,OAAO;CAET,IAAID,EAAK,WAAWC,EAAM,QACxB,OAAO;CAET,KAAK,IAAIU,IAAQ,GAAGA,IAAQX,EAAK,QAAQ,KACvC,IAAI,CAACI,EAASJ,EAAKW,IAASV,EAAMU,EAAO,GACvC,OAAO;CAGX,OAAO;AACT;AAEA,SAASR,EAAc,GAAW,GAAY;CAC5C,IAAIH,MAASC,GACX,OAAO;CAET,IAAID,EAAK,WAAWC,EAAM,QACxB,OAAO;CAET,KAAK,IAAIU,IAAQ,GAAGA,IAAQX,EAAK,QAAQ,KACvC,IAAIA,EAAKW,OAAWV,EAAMU,IACxB,OAAO;CAGX,OAAO;AACT;AAEA,SAAST,EAAe,GAAe,GAAoB;CACzD,IAAI,YAAYf,GACd,OAAO;CAET,IAAIwB,IAAQ;CACZ,KAAK,IAAMC,KAAOzB,GAChB,IAAK,OAAO,OAAOA,GAAOyB,CAAG,KAGzBA,MAAQC,EAAS,MACnB,OAAO;CAGX,OAAOF,MAAUE,EAAS;AAC5B"}
1
+ {"version":3,"file":"value.utils.js","names":["parseWorkspaceValue","value","data","ids","record","item","node","id","splitShape","child","normalizeLayout","serializeWorkspaceValue","layout","weight","sum","sameWorkspaceLayout","left","right","sameArrayItems","sameWorkspaceNode","index"],"sources":["../../../../src/workspace/utils/model/value.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { normalizeLayout } from './layout.utils.js';\nimport { sameArrayItems } from '../comparison.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';\n\nexport function parseWorkspaceValue(value: string): WorkspaceLayout | undefined {\n if (!value) return undefined;\n\n const data: unknown = JSON.parse(value);\n const ids = new Set<string>();\n const record = (item: unknown): item is Record<string, unknown> => typeof item === 'object' && item !== null;\n const node = (item: unknown): item is WorkspaceNode => {\n if (!record(item)) return false;\n if (item.type === 'group') {\n if (\n !Array.isArray(item.panels) ||\n !item.panels.length ||\n typeof item.active !== 'string' ||\n !item.panels.includes(item.active)\n ) {\n return false;\n }\n return item.panels.every(id => {\n if (typeof id !== 'string' || !id || ids.has(id)) return false;\n ids.add(id);\n return true;\n });\n }\n if (!splitShape(item)) return false;\n return item.children.every(child => node(child));\n };\n if (\n !record(data) ||\n data.version !== 1 ||\n !(data.root === null || node(data.root)) ||\n !Array.isArray(data.closed) ||\n !data.closed.every(id => typeof id === 'string' && ids.has(id)) ||\n new Set(data.closed).size !== data.closed.length\n ) {\n throw new TypeError('Invalid workspace arrangement');\n }\n return { version: 1, root: data.root === null ? null : normalizeLayout(data.root), closed: [...data.closed] };\n}\n\nexport function serializeWorkspaceValue(layout: WorkspaceLayout | undefined): string {\n return layout ? JSON.stringify(layout) : '';\n}\n\nfunction splitShape(item: Record<string, unknown>): item is Record<string, unknown> & WorkspaceSplit {\n if (item.type !== 'split' || !['horizontal', 'vertical'].includes(String(item.axis))) return false;\n if (!Array.isArray(item.children) || item.children.length < 2) return false;\n if (!Array.isArray(item.weights) || item.weights.length !== item.children.length) return false;\n if (!item.weights.every(weight => typeof weight === 'number' && Number.isFinite(weight) && weight > 0)) return false;\n return Number.isFinite(item.weights.reduce((sum: number, weight: number) => sum + weight, 0));\n}\n\n/** Compares known arrangement fields; object property insertion order is irrelevant. */\nexport function sameWorkspaceLayout(left: WorkspaceLayout | undefined, right: WorkspaceLayout | undefined): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n return (\n left.version === right.version &&\n sameArrayItems(left.closed, right.closed) &&\n sameWorkspaceNode(left.root, right.root)\n );\n}\n\n// eslint-disable-next-line complexity -- Compare the owned node fields directly without comparison callbacks.\nexport function sameWorkspaceNode(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n if (left.type === 'group') {\n return right.type === 'group' && left.active === right.active && sameArrayItems(left.panels, right.panels);\n }\n if (\n right.type !== 'split' ||\n left.axis !== right.axis ||\n !sameArrayItems(left.weights, right.weights) ||\n left.children.length !== right.children.length\n )\n return false;\n for (let index = 0; index < left.children.length; index++) {\n if (!sameWorkspaceNode(left.children[index]!, right.children[index]!)) return false;\n }\n return true;\n}\n"],"mappings":";;;AAQA,SAAgBA,EAAoB,GAA4C;CAC9E,IAAI,CAACC,GAAO;CAEZ,IAAMC,IAAgB,KAAK,MAAMD,CAAK,GAChCE,oBAAM,IAAI,IAAY,GACtBC,KAAU,MAAmD,OAAOC,KAAS,cAAYA,GACzFC,KAAQ,MACPF,EAAOC,CAAI,IACZA,EAAK,SAAS,UAEd,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,UACb,OAAOA,EAAK,UAAW,YACvB,CAACA,EAAK,OAAO,SAASA,EAAK,MAAM,IAE1B,KAEFA,EAAK,OAAO,OAAM,MACnB,OAAOE,KAAO,YAAY,CAACA,KAAMJ,EAAI,IAAII,CAAE,IAAU,MACzDJ,EAAI,IAAII,CAAE,GACH,GACR,IAEEC,EAAWH,CAAI,IACbA,EAAK,SAAS,OAAM,MAASC,EAAKG,CAAK,CAAC,IADjB,KAhBJ;CAmB5B,IACE,CAACL,EAAOF,CAAI,KACZA,EAAK,YAAY,KACjB,EAAEA,EAAK,SAAS,QAAQI,EAAKJ,EAAK,IAAI,MACtC,CAAC,MAAM,QAAQA,EAAK,MAAM,KAC1B,CAACA,EAAK,OAAO,OAAM,MAAM,OAAOK,KAAO,YAAYJ,EAAI,IAAII,CAAE,CAAC,KAC9D,IAAI,IAAIL,EAAK,MAAM,CAAC,CAAC,SAASA,EAAK,OAAO,QAE1C,MAAU,UAAU,+BAA+B;CAErD,OAAO;EAAE,SAAS;EAAG,MAAMA,EAAK,SAAS,OAAO,OAAOQ,EAAgBR,EAAK,IAAI;EAAG,QAAQ,CAAC,GAAGA,EAAK,MAAM;CAAE;AAC9G;AAEA,SAAgBS,EAAwB,GAA6C;CACnF,OAAOC,IAAS,KAAK,UAAUA,CAAM,IAAI;AAC3C;AAEA,SAASJ,EAAW,GAAiF;CAKnG,OAJIH,EAAK,SAAS,WAAW,CAAC,CAAC,cAAc,UAAU,CAAC,CAAC,SAAS,OAAOA,EAAK,IAAI,CAAC,KAC/E,CAAC,MAAM,QAAQA,EAAK,QAAQ,KAAKA,EAAK,SAAS,SAAS,KACxD,CAAC,MAAM,QAAQA,EAAK,OAAO,KAAKA,EAAK,QAAQ,WAAWA,EAAK,SAAS,UACtE,CAACA,EAAK,QAAQ,OAAM,MAAU,OAAOQ,KAAW,YAAY,OAAO,SAASA,CAAM,KAAKA,IAAS,CAAC,IAAU,KACxG,OAAO,SAASR,EAAK,QAAQ,QAAQ,GAAa,MAAmBS,IAAMD,GAAQ,CAAC,CAAC;AAC9F;AAGA,SAAgBE,EAAoB,GAAmC,GAA6C;CAGlH,OAFIC,MAASC,IAAc,KACvB,CAACD,KAAQ,CAACC,IAAc,KAE1BD,EAAK,YAAYC,EAAM,WACvBC,EAAeF,EAAK,QAAQC,EAAM,MAAM,KACxCE,EAAkBH,EAAK,MAAMC,EAAM,IAAI;AAE3C;AAGA,SAAgBE,EAAkB,GAA4B,GAAsC;CAClG,IAAIH,MAASC,GAAO,OAAO;CAC3B,IAAI,CAACD,KAAQ,CAACC,GAAO,OAAO;CAC5B,IAAID,EAAK,SAAS,SAChB,OAAOC,EAAM,SAAS,WAAWD,EAAK,WAAWC,EAAM,UAAUC,EAAeF,EAAK,QAAQC,EAAM,MAAM;CAE3G,IACEA,EAAM,SAAS,WACfD,EAAK,SAASC,EAAM,QACpB,CAACC,EAAeF,EAAK,SAASC,EAAM,OAAO,KAC3CD,EAAK,SAAS,WAAWC,EAAM,SAAS,QAExC,OAAO;CACT,KAAK,IAAIG,IAAQ,GAAGA,IAAQJ,EAAK,SAAS,QAAQ,KAChD,IAAI,CAACG,EAAkBH,EAAK,SAASI,IAASH,EAAM,SAASG,EAAO,GAAG,OAAO;CAEhF,OAAO;AACT"}
@@ -4,7 +4,9 @@ import type { WorkspaceRequirements } from '../geometry/sizing.utils.js';
4
4
  import type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';
5
5
  import type { WorkspaceLayout } from '../model/layout.utils.js';
6
6
  import type { WorkspacePlacementPlan } from './planner.utils.js';
7
+ import type { WorkspacePlacementSession } from './session.utils.js';
7
8
  interface AcquisitionInput {
9
+ placementSession?: WorkspacePlacementSession;
8
10
  plan: WorkspacePlacementPlan;
9
11
  previous: WorkspaceLayout;
10
12
  source: string[];
@@ -1,9 +1,10 @@
1
1
  import { getPanelIds as e } from "../model/layout.utils.js";
2
2
  import { projectLayout as t } from "../model/operations.utils.js";
3
3
  import { matchesPlacementIntent as n } from "../interaction/drag-preview.utils.js";
4
- import { getAllocatedContextRect as r, getContextKey as i } from "./context.utils.js";
5
- import { rebaseProjectedSplit as a } from "../model/projection.utils.js";
6
- import { describePlacementSlot as o } from "./group-insertion.utils.js";
4
+ import { samePanelMembership as r } from "../model/membership.utils.js";
5
+ import { rebaseProjectedSplit as i } from "../model/projection.utils.js";
6
+ import { getAllocatedScopeRect as a } from "./scope.utils.js";
7
+ import { getGroupInsertion as o } from "./group-insertion.utils.js";
7
8
  import { getMinimumWorkspaceDimensions as s } from "../geometry/sizing.utils.js";
8
9
  import { fitSizes as c } from "../geometry/partition.utils.js";
9
10
  import { allocateWorkspace as l } from "../geometry/allocation.utils.js";
@@ -24,7 +25,7 @@ function u(e) {
24
25
  } : void 0;
25
26
  }
26
27
  function d(e, t) {
27
- return !!e?.previous && !!e.next && !!t && (e.axis !== t.axis || i(e.members) !== i(t.members));
28
+ return !!e?.previous && !!e.next && !!t && (e.axis !== t.axis || !r(e.members, t.members));
28
29
  }
29
30
  function f(e, t) {
30
31
  return !!t && e.covers(t, "x") && e.covers(t, "y");
@@ -36,20 +37,27 @@ function p(e, n) {
36
37
  } : {
37
38
  start: e.acquisition.point[t],
38
39
  end: e.acquisition.point[t]
39
- };
40
+ }, o;
40
41
  return {
41
42
  input: e,
42
43
  axis: r,
43
44
  extent: i,
44
45
  range: a,
45
46
  covers: (e, t) => m(e, t, a(t)),
46
- allocate: (n) => l({
47
- root: t(n, e.available).root,
48
- rect: e.rect,
49
- minimum: (t) => s(t, e.requirements),
50
- policy: "stop",
51
- gap: e.requirements.gap
52
- })
47
+ allocate: (n) => {
48
+ if (o?.layout === n) return o.allocation;
49
+ let r = l({
50
+ root: t(n, e.available).root,
51
+ rect: e.rect,
52
+ minimum: (t) => s(t, e.requirements),
53
+ policy: "stop",
54
+ gap: e.requirements.gap
55
+ });
56
+ return o = {
57
+ layout: n,
58
+ allocation: r
59
+ }, r;
60
+ }
53
61
  };
54
62
  }
55
63
  function m(e, t, n) {
@@ -72,30 +80,30 @@ function h(e, t) {
72
80
  }
73
81
  return r;
74
82
  }
75
- function g({ fit: t, layout: n, parent: i, index: o }) {
76
- if (i.node.type !== "split") return;
77
- let l = i.node.axis === "horizontal" ? "width" : "height", u = i.node.children.map((e) => s(e, t.input.requirements)[l]), d = i.rect[l] - t.input.requirements.gap * (u.length - 1), f = i.node.children.map((n, i) => i === o ? 0 : r({
83
+ function g({ fit: t, layout: n, parent: r, index: o }) {
84
+ if (r.node.type !== "split") return;
85
+ let l = r.node.axis === "horizontal" ? "width" : "height", u = r.node.children.map((e) => s(e, t.input.requirements)[l]), d = r.rect[l] - t.input.requirements.gap * (u.length - 1), f = r.node.children.map((n, r) => r === o ? 0 : a({
78
86
  members: e(n),
79
87
  allocation: t.input.current,
80
88
  source: t.input.source
81
89
  })?.[l]);
82
90
  if (f.some((e) => e === void 0) || y(u) > d) return;
83
91
  let p = f.map((e) => e);
84
- return p[o] = Math.max(u[o], d - y(p)), a(n, i.node, c(p, u, d), t.input.available) ?? n;
92
+ return p[o] = Math.max(u[o], d - y(p)), i(n, r.node, c(p, u, d), t.input.available) ?? n;
85
93
  }
86
94
  function _(e, t, n) {
87
- let r = e.allocate(t), i = r.regions.find((e) => e.key === n.split(".").slice(0, -1).join("."));
88
- if (i.node.type !== "split") return;
95
+ let r = e.allocate(t), a = r.regions.find((e) => e.key === n.split(".").slice(0, -1).join("."));
96
+ if (a.node.type !== "split") return;
89
97
  let o = r.groups.find((e) => e.key === n), s = Number(n.split(".").at(-1)), c = v({
90
98
  fit: e,
91
99
  owner: {
92
- ...i,
93
- node: i.node
100
+ ...a,
101
+ node: a.node
94
102
  },
95
103
  incoming: o.rect,
96
104
  index: s
97
105
  });
98
- if (c) return a(t, i.node, c, e.input.available) ?? t;
106
+ if (c) return i(t, a.node, c, e.input.available) ?? t;
99
107
  }
100
108
  function v(e) {
101
109
  let { fit: t, owner: n, incoming: r, index: i } = e, { axis: a, extent: o } = t, l = n.node.children.map((e) => s(e, t.input.requirements)[o]), u = l.slice(0, i), d = l.slice(i + 1), f = Math.max(n.rect[a] + y(u) + t.input.requirements.gap * i, t.range(a).end - r[o]), p = Math.min(n.rect[a] + n.rect[o] - y(d) - t.input.requirements.gap * d.length - r[o], t.range(a).start);
@@ -142,7 +150,7 @@ function x(e, t) {
142
150
  return ["order", "insert"].includes(e.intent.kind) && ["insert", "reorder"].includes(t.kind);
143
151
  }
144
152
  function S(e, t) {
145
- return e?.phase === "detached" && !e.blocked && e.allocation === "reserved" && i(e.source) === i(t);
153
+ return e?.phase === "detached" && !e.blocked && e.allocation === "reserved" && r(e.source, t);
146
154
  }
147
155
  function C(e, t) {
148
156
  return e?.phase === "detached" && e.blocked && n(e.intent, t);
@@ -1 +1 @@
1
- {"version":3,"file":"acquisition-sizing.utils.js","names":["fitAcquiredPlacement","next","describePlacementSlot","input","crossScopeInterior","fit","acquisitionFit","moving","group","id","coversAcquisition","ancestors","fitReceivingPath","layout","fitIncoming","achieved","prior","getContextKey","rect","axis","direction","extent","range","dimension","coversRange","allocateWorkspace","projectLayout","getMinimumWorkspaceDimensions","node","end","path","depth","key","regions","parent","region","receiving","fitAncestor","size","minima","child","budget","extents","slot","index","getAllocatedContextRect","getPanelIds","value","sum","preferred","rebaseProjectedSplit","fitSizes","allocation","owner","incoming","sizes","incomingSizes","before","after","start","position","values","total","resolveSelectedPlacementPlan","blockedSelection","selectedReservation","spatialReservation","current","point","preview","plan","source","matchesPlacementIntent","intent"],"sources":["../../../../src/workspace/utils/placement/acquisition-sizing.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 { allocateWorkspace } from '../geometry/allocation.utils.js';\nimport { fitSizes } from '../geometry/partition.utils.js';\nimport { getMinimumWorkspaceDimensions } from '../geometry/sizing.utils.js';\nimport { matchesPlacementIntent } from '../interaction/drag-preview.utils.js';\nimport { getPanelIds } from '../model/layout.utils.js';\nimport { projectLayout } from '../model/operations.utils.js';\nimport { rebaseProjectedSplit } from '../model/projection.utils.js';\nimport { getAllocatedContextRect, getContextKey } from './context.utils.js';\nimport { describePlacementSlot } from './group-insertion.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceRequirements } from '../geometry/sizing.utils.js';\nimport type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';\nimport type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { WorkspacePlacementPlan } from './planner.utils.js';\n\ninterface AcquisitionInput {\n plan: WorkspacePlacementPlan;\n previous: WorkspaceLayout;\n source: string[];\n available: string[];\n current: WorkspacePlacedRegion[];\n rect: Rect;\n acquisition: { rect: Rect; point: Point };\n requirements: WorkspaceRequirements;\n}\n\ninterface Fit {\n input: AcquisitionInput;\n axis: 'x' | 'y';\n extent: 'width' | 'height';\n range: (axis: 'x' | 'y') => { start: number; end: number };\n covers: (rect: Rect, axis: 'x' | 'y') => boolean;\n allocate: (layout: WorkspaceLayout) => ReturnType<typeof allocateWorkspace>;\n}\n\n/** Fits a cross-scope interior reservation to its acquired allocation without retaining a hidden target. */\nexport function fitAcquiredPlacement(input: AcquisitionInput): WorkspacePlacementPlan | undefined {\n const next = describePlacementSlot(input);\n const prior = describePlacementSlot({ ...input, plan: { layout: input.previous } });\n if (!crossScopeInterior(next, prior)) return input.plan;\n const fit = acquisitionFit(input, next.axis);\n const moving = fit\n .allocate(input.plan.layout)\n .groups.find(group => group.group.panels.every(id => input.source.includes(id)));\n if (!moving) return undefined;\n if (coversAcquisition(fit, moving.rect)) return input.plan;\n const ancestors = fitReceivingPath(fit, moving.key);\n const layout = ancestors && fitIncoming(fit, ancestors, moving.key);\n const achieved = layout && fit.allocate(layout).groups.find(group => group.key === moving.key);\n return layout && coversAcquisition(fit, achieved?.rect) ? { ...input.plan, layout } : undefined;\n}\n\nfunction crossScopeInterior(\n next: ReturnType<typeof describePlacementSlot>,\n prior: ReturnType<typeof describePlacementSlot>\n): next is NonNullable<typeof next> {\n return (\n !!next?.previous &&\n !!next.next &&\n !!prior &&\n (next.axis !== prior.axis || getContextKey(next.members) !== getContextKey(prior.members))\n );\n}\n\nfunction coversAcquisition(fit: Fit, rect?: Rect) {\n return !!rect && fit.covers(rect, 'x') && fit.covers(rect, 'y');\n}\n\nfunction acquisitionFit(input: AcquisitionInput, direction: WorkspaceSplit['axis']): Fit {\n const axis = direction === 'horizontal' ? 'x' : 'y';\n const extent = axis === 'x' ? 'width' : 'height';\n const range = (dimension: 'x' | 'y') =>\n dimension === axis\n ? { start: input.acquisition.rect[axis], end: input.acquisition.rect[axis] + input.acquisition.rect[extent] }\n : { start: input.acquisition.point[dimension], end: input.acquisition.point[dimension] };\n return {\n input,\n axis,\n extent,\n range,\n covers: (rect, dimension) => coversRange(rect, dimension, range(dimension)),\n allocate: layout =>\n allocateWorkspace({\n root: projectLayout(layout, input.available).root,\n rect: input.rect,\n minimum: node => getMinimumWorkspaceDimensions(node, input.requirements),\n policy: 'stop',\n gap: input.requirements.gap\n })\n };\n}\n\nfunction coversRange(rect: Rect, axis: 'x' | 'y', range: { start: number; end: number }) {\n const end = rect[axis] + rect[axis === 'x' ? 'width' : 'height'];\n return range.start === range.end\n ? rect[axis] <= range.start && range.start < end\n : rect[axis] <= range.start + 1e-7 && end >= range.end - 1e-7;\n}\n\nfunction fitReceivingPath(fit: Fit, moving: string) {\n const path = moving.split('.');\n let layout: WorkspaceLayout | undefined = fit.input.plan.layout;\n for (let depth = 1; depth < path.length - 1; depth++) {\n if (!layout) return undefined;\n const key = path.slice(0, depth).join('.');\n const regions = fit.allocate(layout).regions;\n const parent = regions.find(region => region.key === key)!;\n const receiving = regions.find(region => region.key === `${key}.${path[depth]}`)!;\n if (parent.node.type !== 'split') return undefined;\n const axis = parent.node.axis === 'horizontal' ? 'x' : 'y';\n if (!fit.covers(receiving.rect, axis)) {\n layout = fitAncestor({ fit, layout, parent, index: Number(path[depth]) });\n }\n }\n return layout;\n}\n\nfunction fitAncestor({\n fit,\n layout,\n parent,\n index\n}: {\n fit: Fit;\n layout: WorkspaceLayout;\n parent: WorkspacePlacedRegion;\n index: number;\n}) {\n if (parent.node.type !== 'split') return undefined;\n const size = parent.node.axis === 'horizontal' ? 'width' : 'height';\n const minima = parent.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[size]);\n const budget = parent.rect[size] - fit.input.requirements.gap * (minima.length - 1);\n const extents = parent.node.children.map((child, slot) =>\n slot === index\n ? 0\n : getAllocatedContextRect({\n members: getPanelIds(child),\n allocation: fit.input.current,\n source: fit.input.source\n })?.[size]\n );\n if (extents.some(value => value === undefined) || sum(minima) > budget) return undefined;\n const preferred = extents.map(value => value!);\n preferred[index] = Math.max(minima[index]!, budget - sum(preferred));\n return rebaseProjectedSplit(layout, parent.node, fitSizes(preferred, minima, budget), fit.input.available) ?? layout;\n}\n\nfunction fitIncoming(fit: Fit, layout: WorkspaceLayout, key: string) {\n const allocation = fit.allocate(layout);\n const owner = allocation.regions.find(region => region.key === key.split('.').slice(0, -1).join('.'))!;\n if (owner.node.type !== 'split') return undefined;\n const incoming = allocation.groups.find(group => group.key === key)!;\n const index = Number(key.split('.').at(-1));\n const sizes = incomingSizes({ fit, owner: { ...owner, node: owner.node }, incoming: incoming.rect, index });\n if (!sizes) return undefined;\n\n const rebased = rebaseProjectedSplit(layout, owner.node, sizes, fit.input.available);\n return rebased ?? layout;\n}\n\nfunction incomingSizes(input: {\n fit: Fit;\n owner: WorkspacePlacedRegion & { node: WorkspaceSplit };\n incoming: Rect;\n index: number;\n}) {\n const { fit, owner, incoming, index } = input;\n const { axis, extent } = fit;\n const minima = owner.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[extent]);\n const before = minima.slice(0, index);\n const after = minima.slice(index + 1);\n const start = Math.max(\n owner.rect[axis] + sum(before) + fit.input.requirements.gap * index,\n fit.range(axis).end - incoming[extent]\n );\n const end = Math.min(\n owner.rect[axis] + owner.rect[extent] - sum(after) - fit.input.requirements.gap * after.length - incoming[extent],\n fit.range(axis).start\n );\n if (start > end) return undefined;\n const position = Math.max(start, Math.min(incoming[axis], end));\n return [\n ...fitSizes(\n owner.node.weights.slice(0, index),\n before,\n position - owner.rect[axis] - fit.input.requirements.gap * index\n ),\n incoming[extent],\n ...fitSizes(\n owner.node.weights.slice(index + 1),\n after,\n owner.rect[axis] + owner.rect[extent] - position - incoming[extent] - fit.input.requirements.gap * after.length\n )\n ];\n}\n\nconst sum = (values: number[]) => values.reduce((total, value) => total + value, 0);\n\n/** Reuses the actual selected reservation before considering a different spatial offer. */\nexport function resolveSelectedPlacementPlan(\n input: Omit<AcquisitionInput, 'previous' | 'acquisition'> & {\n previous?: WorkspaceDragPreview;\n acquisition?: { rect: Rect; point: Point };\n clientOrigin: Rect;\n intent: WorkspaceDropIntent;\n }\n): WorkspacePlacementPlan | undefined {\n const prior = input.previous;\n if (blockedSelection(prior, input.intent) && !input.acquisition) return undefined;\n if (!selectedReservation(prior, input.source) || !spatialReservation(prior, input.plan)) return input.plan;\n const current = describePlacementSlot({ ...input, plan: prior });\n const next = describePlacementSlot(input);\n if (current && current.key === next?.key) return { ...input.plan, layout: prior.layout };\n if (!input.acquisition) return input.plan;\n const { rect, point } = input.acquisition;\n return fitAcquiredPlacement({\n ...input,\n previous: prior.layout,\n acquisition: {\n rect: { ...rect, x: rect.x - input.clientOrigin.x, y: rect.y - input.clientOrigin.y },\n point: { x: point.x - input.clientOrigin.x, y: point.y - input.clientOrigin.y }\n }\n });\n}\n\nfunction spatialReservation(preview: WorkspaceDragPreview, plan: WorkspacePlacementPlan) {\n return ['order', 'insert'].includes(preview.intent.kind) && ['insert', 'reorder'].includes(plan.kind);\n}\n\nfunction selectedReservation(\n preview: WorkspaceDragPreview | undefined,\n source: string[]\n): preview is Extract<WorkspaceDragPreview, { phase: 'detached' }> & { allocation: 'reserved' } {\n return (\n preview?.phase === 'detached' &&\n !preview.blocked &&\n preview.allocation === 'reserved' &&\n getContextKey(preview.source) === getContextKey(source)\n );\n}\n\nfunction blockedSelection(preview: WorkspaceDragPreview | undefined, intent: WorkspaceDropIntent) {\n return preview?.phase === 'detached' && preview.blocked && matchesPlacementIntent(preview.intent, intent);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"acquisition-sizing.utils.js","names":["fitAcquiredPlacement","next","getGroupInsertion","input","crossScopeInterior","fit","acquisitionFit","moving","group","id","coversAcquisition","ancestors","fitReceivingPath","layout","fitIncoming","achieved","prior","samePanelMembership","rect","axis","direction","extent","range","dimension","lastAllocation","coversRange","allocation","allocateWorkspace","projectLayout","getMinimumWorkspaceDimensions","node","end","path","depth","key","regions","parent","region","receiving","fitAncestor","size","minima","child","budget","extents","childIndex","index","getAllocatedScopeRect","getPanelIds","value","sum","preferred","rebaseProjectedSplit","fitSizes","owner","incoming","sizes","incomingSizes","before","after","start","position","values","total","resolveSelectedPlacementPlan","blockedSelection","selectedReservation","spatialReservation","current","point","preview","plan","source","matchesPlacementIntent","intent"],"sources":["../../../../src/workspace/utils/placement/acquisition-sizing.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 { allocateWorkspace } from '../geometry/allocation.utils.js';\nimport { fitSizes } from '../geometry/partition.utils.js';\nimport { getMinimumWorkspaceDimensions } from '../geometry/sizing.utils.js';\nimport { matchesPlacementIntent } from '../interaction/drag-preview.utils.js';\nimport { getPanelIds } from '../model/layout.utils.js';\nimport { samePanelMembership } from '../model/membership.utils.js';\nimport { projectLayout } from '../model/operations.utils.js';\nimport { rebaseProjectedSplit } from '../model/projection.utils.js';\nimport { getGroupInsertion } from './group-insertion.utils.js';\nimport { getAllocatedScopeRect } from './scope.utils.js';\n\nimport type { WorkspacePlacedRegion } from '../geometry/allocation.utils.js';\nimport type { WorkspaceRequirements } from '../geometry/sizing.utils.js';\nimport type { WorkspaceDragPreview, WorkspaceDropIntent } from '../interaction/drag-preview.utils.js';\nimport type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';\nimport type { GroupInsertion } from './group-insertion.utils.js';\nimport type { WorkspacePlacementPlan } from './planner.utils.js';\nimport type { WorkspacePlacementSession } from './session.utils.js';\n\ninterface AcquisitionInput {\n placementSession?: WorkspacePlacementSession;\n plan: WorkspacePlacementPlan;\n previous: WorkspaceLayout;\n source: string[];\n available: string[];\n current: WorkspacePlacedRegion[];\n rect: Rect;\n acquisition: { rect: Rect; point: Point };\n requirements: WorkspaceRequirements;\n}\n\ninterface Fit {\n input: AcquisitionInput;\n axis: 'x' | 'y';\n extent: 'width' | 'height';\n range: (axis: 'x' | 'y') => { start: number; end: number };\n covers: (rect: Rect, axis: 'x' | 'y') => boolean;\n allocate: (layout: WorkspaceLayout) => ReturnType<typeof allocateWorkspace>;\n}\n\n/** Fits a cross-scope interior reservation to its acquired allocation without retaining a hidden target. */\nexport function fitAcquiredPlacement(input: AcquisitionInput): WorkspacePlacementPlan | undefined {\n const next = getGroupInsertion(input);\n const prior = getGroupInsertion({ ...input, plan: { layout: input.previous } });\n if (!crossScopeInterior(next, prior)) return input.plan;\n const fit = acquisitionFit(input, next.axis);\n const moving = fit\n .allocate(input.plan.layout)\n .groups.find(group => group.group.panels.every(id => input.source.includes(id)));\n if (!moving) return undefined;\n if (coversAcquisition(fit, moving.rect)) return input.plan;\n const ancestors = fitReceivingPath(fit, moving.key);\n const layout = ancestors && fitIncoming(fit, ancestors, moving.key);\n const achieved = layout && fit.allocate(layout).groups.find(group => group.key === moving.key);\n return layout && coversAcquisition(fit, achieved?.rect) ? { ...input.plan, layout } : undefined;\n}\n\nfunction crossScopeInterior(\n next: GroupInsertion | undefined,\n prior: GroupInsertion | undefined\n): next is NonNullable<typeof next> {\n return (\n !!next?.previous &&\n !!next.next &&\n !!prior &&\n (next.axis !== prior.axis || !samePanelMembership(next.members, prior.members))\n );\n}\n\nfunction coversAcquisition(fit: Fit, rect?: Rect) {\n return !!rect && fit.covers(rect, 'x') && fit.covers(rect, 'y');\n}\n\nfunction acquisitionFit(input: AcquisitionInput, direction: WorkspaceSplit['axis']): Fit {\n const axis = direction === 'horizontal' ? 'x' : 'y';\n const extent = axis === 'x' ? 'width' : 'height';\n const range = (dimension: 'x' | 'y') =>\n dimension === axis\n ? { start: input.acquisition.rect[axis], end: input.acquisition.rect[axis] + input.acquisition.rect[extent] }\n : { start: input.acquisition.point[dimension], end: input.acquisition.point[dimension] };\n let lastAllocation: { layout: WorkspaceLayout; allocation: ReturnType<typeof allocateWorkspace> } | undefined;\n return {\n input,\n axis,\n extent,\n range,\n covers: (rect, dimension) => coversRange(rect, dimension, range(dimension)),\n allocate: layout => {\n if (lastAllocation?.layout === layout) return lastAllocation.allocation;\n const allocation = allocateWorkspace({\n root: projectLayout(layout, input.available).root,\n rect: input.rect,\n minimum: node => getMinimumWorkspaceDimensions(node, input.requirements),\n policy: 'stop',\n gap: input.requirements.gap\n });\n lastAllocation = { layout, allocation };\n return allocation;\n }\n };\n}\n\nfunction coversRange(rect: Rect, axis: 'x' | 'y', range: { start: number; end: number }) {\n const end = rect[axis] + rect[axis === 'x' ? 'width' : 'height'];\n return range.start === range.end\n ? rect[axis] <= range.start && range.start < end\n : rect[axis] <= range.start + 1e-7 && end >= range.end - 1e-7;\n}\n\nfunction fitReceivingPath(fit: Fit, moving: string) {\n const path = moving.split('.');\n let layout: WorkspaceLayout | undefined = fit.input.plan.layout;\n for (let depth = 1; depth < path.length - 1; depth++) {\n if (!layout) return undefined;\n const key = path.slice(0, depth).join('.');\n const regions = fit.allocate(layout).regions;\n const parent = regions.find(region => region.key === key)!;\n const receiving = regions.find(region => region.key === `${key}.${path[depth]}`)!;\n if (parent.node.type !== 'split') return undefined;\n const axis = parent.node.axis === 'horizontal' ? 'x' : 'y';\n if (!fit.covers(receiving.rect, axis)) {\n layout = fitAncestor({ fit, layout, parent, index: Number(path[depth]) });\n }\n }\n return layout;\n}\n\nfunction fitAncestor({\n fit,\n layout,\n parent,\n index\n}: {\n fit: Fit;\n layout: WorkspaceLayout;\n parent: WorkspacePlacedRegion;\n index: number;\n}) {\n if (parent.node.type !== 'split') return undefined;\n const size = parent.node.axis === 'horizontal' ? 'width' : 'height';\n const minima = parent.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[size]);\n const budget = parent.rect[size] - fit.input.requirements.gap * (minima.length - 1);\n const extents = parent.node.children.map((child, childIndex) =>\n childIndex === index\n ? 0\n : getAllocatedScopeRect({\n members: getPanelIds(child),\n allocation: fit.input.current,\n source: fit.input.source\n })?.[size]\n );\n if (extents.some(value => value === undefined) || sum(minima) > budget) return undefined;\n const preferred = extents.map(value => value!);\n preferred[index] = Math.max(minima[index]!, budget - sum(preferred));\n return rebaseProjectedSplit(layout, parent.node, fitSizes(preferred, minima, budget), fit.input.available) ?? layout;\n}\n\nfunction fitIncoming(fit: Fit, layout: WorkspaceLayout, key: string) {\n const allocation = fit.allocate(layout);\n const owner = allocation.regions.find(region => region.key === key.split('.').slice(0, -1).join('.'))!;\n if (owner.node.type !== 'split') return undefined;\n const incoming = allocation.groups.find(group => group.key === key)!;\n const index = Number(key.split('.').at(-1));\n const sizes = incomingSizes({ fit, owner: { ...owner, node: owner.node }, incoming: incoming.rect, index });\n if (!sizes) return undefined;\n\n const rebased = rebaseProjectedSplit(layout, owner.node, sizes, fit.input.available);\n return rebased ?? layout;\n}\n\nfunction incomingSizes(input: {\n fit: Fit;\n owner: WorkspacePlacedRegion & { node: WorkspaceSplit };\n incoming: Rect;\n index: number;\n}) {\n const { fit, owner, incoming, index } = input;\n const { axis, extent } = fit;\n const minima = owner.node.children.map(child => getMinimumWorkspaceDimensions(child, fit.input.requirements)[extent]);\n const before = minima.slice(0, index);\n const after = minima.slice(index + 1);\n const start = Math.max(\n owner.rect[axis] + sum(before) + fit.input.requirements.gap * index,\n fit.range(axis).end - incoming[extent]\n );\n const end = Math.min(\n owner.rect[axis] + owner.rect[extent] - sum(after) - fit.input.requirements.gap * after.length - incoming[extent],\n fit.range(axis).start\n );\n if (start > end) return undefined;\n const position = Math.max(start, Math.min(incoming[axis], end));\n return [\n ...fitSizes(\n owner.node.weights.slice(0, index),\n before,\n position - owner.rect[axis] - fit.input.requirements.gap * index\n ),\n incoming[extent],\n ...fitSizes(\n owner.node.weights.slice(index + 1),\n after,\n owner.rect[axis] + owner.rect[extent] - position - incoming[extent] - fit.input.requirements.gap * after.length\n )\n ];\n}\n\nconst sum = (values: number[]) => values.reduce((total, value) => total + value, 0);\n\n/** Reuses the actual selected reservation before considering a different spatial offer. */\nexport function resolveSelectedPlacementPlan(\n input: Omit<AcquisitionInput, 'previous' | 'acquisition'> & {\n previous?: WorkspaceDragPreview;\n acquisition?: { rect: Rect; point: Point };\n clientOrigin: Rect;\n intent: WorkspaceDropIntent;\n }\n): WorkspacePlacementPlan | undefined {\n const prior = input.previous;\n if (blockedSelection(prior, input.intent) && !input.acquisition) return undefined;\n if (!selectedReservation(prior, input.source) || !spatialReservation(prior, input.plan)) return input.plan;\n const current = getGroupInsertion({ ...input, plan: prior });\n const next = getGroupInsertion(input);\n if (current && current.key === next?.key) return { ...input.plan, layout: prior.layout };\n if (!input.acquisition) return input.plan;\n const { rect, point } = input.acquisition;\n return fitAcquiredPlacement({\n ...input,\n previous: prior.layout,\n acquisition: {\n rect: { ...rect, x: rect.x - input.clientOrigin.x, y: rect.y - input.clientOrigin.y },\n point: { x: point.x - input.clientOrigin.x, y: point.y - input.clientOrigin.y }\n }\n });\n}\n\nfunction spatialReservation(preview: WorkspaceDragPreview, plan: WorkspacePlacementPlan) {\n return ['order', 'insert'].includes(preview.intent.kind) && ['insert', 'reorder'].includes(plan.kind);\n}\n\nfunction selectedReservation(\n preview: WorkspaceDragPreview | undefined,\n source: string[]\n): preview is Extract<WorkspaceDragPreview, { phase: 'detached' }> & { allocation: 'reserved' } {\n return (\n preview?.phase === 'detached' &&\n !preview.blocked &&\n preview.allocation === 'reserved' &&\n samePanelMembership(preview.source, source)\n );\n}\n\nfunction blockedSelection(preview: WorkspaceDragPreview | undefined, intent: WorkspaceDropIntent) {\n return preview?.phase === 'detached' && preview.blocked && matchesPlacementIntent(preview.intent, intent);\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
- import type { WorkspaceLayout } from '../model/layout.utils.js';
1
+ import type { WorkspaceLayout, WorkspaceSplit } from '../model/layout.utils.js';
2
2
  import type { WorkspaceDestination } from '../model/operations.utils.js';
3
3
  import type { WorkspaceLayoutProjector } from '../model/projection.utils.js';
4
- import type { WorkspacePlacementPlan } from './planner.utils.js';
4
+ import type { WorkspacePlacementPlan, WorkspacePlacementPlanner } from './planner.utils.js';
5
+ import type { WorkspacePlacementSession } from './session.utils.js';
5
6
  interface InsertionInput {
6
7
  layout: WorkspaceLayout;
7
8
  source: string[];
@@ -9,18 +10,23 @@ interface InsertionInput {
9
10
  available: string[];
10
11
  projectLayout?: WorkspaceLayoutProjector;
11
12
  }
12
- export declare function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined;
13
- export declare function describePlacementSlot(input: {
14
- plan: Pick<WorkspacePlacementPlan, 'layout'>;
15
- source: string[];
16
- available: string[];
17
- projectLayout?: WorkspaceLayoutProjector;
18
- }): {
19
- axis: "horizontal" | "vertical";
13
+ export interface GroupInsertionInputs {
14
+ readonly plan: Pick<WorkspacePlacementPlan, 'layout'>;
15
+ readonly source: string[];
16
+ readonly available: string[];
17
+ readonly projectLayout?: WorkspaceLayoutProjector;
18
+ readonly placementSession?: WorkspacePlacementSession;
19
+ readonly planPlacement?: WorkspacePlacementPlanner;
20
+ }
21
+ export interface GroupInsertion {
22
+ axis: WorkspaceSplit['axis'];
20
23
  index: number;
21
24
  members: string[];
22
- previous: string[] | undefined;
23
- next: string[] | undefined;
25
+ previous?: string[];
26
+ next?: string[];
24
27
  key: string;
25
- } | undefined;
28
+ }
29
+ export declare function getGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined;
30
+ export declare function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined;
31
+ export declare function computeGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined;
26
32
  export {};
@@ -1,48 +1,51 @@
1
1
  import { getPanelIds as e, getSplitSide as t } from "../model/layout.utils.js";
2
2
  import { createDetachedLayout as n, projectLayout as r } from "../model/operations.utils.js";
3
- import { findDeepestProjectionCarrier as i, getProjectionSignature as a, rebaseProjectedSplit as o } from "../model/projection.utils.js";
3
+ import { findDeepestProjectionCarrier as i, rebaseProjectedSplit as a, sameProjectionShape as o } from "../model/projection.utils.js";
4
4
  import { findWorkspaceRegion as s, placeRegion as c } from "./region.utils.js";
5
5
  // src/workspace/utils/placement/group-insertion.utils.ts
6
6
  function l(e) {
7
- let t = m(e);
7
+ return e.placementSession && !e.planPlacement ? e.placementSession.getInsertion(e) : S(e);
8
+ }
9
+ function u(e) {
10
+ let t = h(e);
8
11
  if (!t) return;
9
- let n = u(e, t);
10
- return n ? d({
12
+ let n = d(e, t);
13
+ return n ? f({
11
14
  input: e,
12
15
  context: t,
13
16
  topology: n
14
17
  }) : void 0;
15
18
  }
16
- function u(o, s) {
17
- let { peers: l, slot: u, visible: d, root: f, axis: p } = s, m = l[Math.min(u, l.length - 1)], h = o.projectLayout ?? r, g = i(f, a(m.node), (e) => {
19
+ function d(a, o) {
20
+ let { peers: s, insertionIndex: l, visible: u, root: d, axis: f } = o, p = s[Math.min(l, s.length - 1)], m = a.projectLayout ?? r, h = i(d, p.node, (e) => {
18
21
  let t = n({
19
22
  version: 1,
20
23
  root: e,
21
24
  closed: []
22
- }, o.source);
23
- return h(t, d).root;
24
- }), _ = g && y(f, g);
25
- if (!_ || !g) return;
26
- let v = u < l.length, b = {
27
- target: e(g)[0],
28
- region: _,
29
- position: t(p, v ? "before" : "after")
25
+ }, a.source);
26
+ return m(t, u).root;
27
+ }), g = h && b(d, h);
28
+ if (!g || !h) return;
29
+ let _ = l < s.length, v = {
30
+ target: e(h)[0],
31
+ region: g,
32
+ position: t(f, _ ? "before" : "after")
30
33
  };
31
34
  return c({
32
- ...o,
33
- destination: b
35
+ ...a,
36
+ destination: v
34
37
  });
35
38
  }
36
- function d({ input: t, context: n, topology: i }) {
37
- let { owner: a, peers: o, visible: s, axis: c } = n, l = (t.projectLayout ?? r)(i.layout, s).root, u = t.source.filter((e) => s.includes(e)), d = _(l, u);
39
+ function f({ input: t, context: n, topology: i }) {
40
+ let { owner: a, peers: o, visible: s, axis: c } = n, l = (t.projectLayout ?? r)(i.layout, s).root, u = t.source.filter((e) => s.includes(e)), d = v(l, u);
38
41
  if (!d || d.axis !== c || d.children.length !== o.length + 1) return;
39
- let f = g({
42
+ let f = _({
40
43
  branch: d,
41
44
  peers: o,
42
45
  moving: u
43
46
  });
44
47
  if (!f) return;
45
- let p = b({
48
+ let p = x({
46
49
  layout: i.layout,
47
50
  branch: d,
48
51
  weights: f,
@@ -51,18 +54,18 @@ function d({ input: t, context: n, topology: i }) {
51
54
  if (p) return {
52
55
  kind: "insert",
53
56
  layout: p,
54
- context: {
57
+ scope: {
55
58
  kind: "rail",
56
59
  members: [.../* @__PURE__ */ new Set([...e(a), ...u])]
57
60
  }
58
61
  };
59
62
  }
60
- function f(e) {
63
+ function p(e) {
61
64
  let { destination: t, layout: n } = e;
62
65
  if (!t.region || t.position === "tab") return;
63
66
  let i = e.available.filter((e) => !n.closed.includes(e)), a = (e.projectLayout ?? r)(n, i).root, o = s(a, t.region);
64
67
  if (!a || !o) return;
65
- let c = t.position === "left" || t.position === "right" ? "horizontal" : "vertical", l = p({
68
+ let c = t.position === "left" || t.position === "right" ? "horizontal" : "vertical", l = m({
66
69
  root: a,
67
70
  target: o,
68
71
  key: t.region,
@@ -76,13 +79,13 @@ function f(e) {
76
79
  owner: l
77
80
  };
78
81
  }
79
- function p(e) {
82
+ function m(e) {
80
83
  if (e.target.type === "split" && e.target.axis === e.axis) return e.target;
81
84
  let t = s(e.root, e.key.split(".").slice(0, -1).join("."));
82
85
  return t?.type === "split" && t.axis === e.axis ? t : e.target.type === "split" ? e.target : void 0;
83
86
  }
84
- function m(t) {
85
- let r = f(t);
87
+ function h(t) {
88
+ let r = p(t);
86
89
  if (!r) return;
87
90
  let { owner: i, target: a, axis: o } = r, s = n({
88
91
  version: 1,
@@ -90,16 +93,16 @@ function m(t) {
90
93
  closed: []
91
94
  }, t.source).root;
92
95
  if (!s) return;
93
- let c = h(s, o), l = new Set(e(a).filter((e) => !t.source.includes(e))), u = c.flatMap((t, n) => e(t.node).every((e) => l.has(e)) ? [n] : []);
96
+ let c = g(s, o), l = new Set(e(a).filter((e) => !t.source.includes(e))), u = c.flatMap((t, n) => e(t.node).every((e) => l.has(e)) ? [n] : []);
94
97
  if (!u.length) return;
95
98
  let d = t.destination.position === "left" || t.destination.position === "top";
96
99
  return {
97
100
  ...r,
98
101
  peers: c,
99
- slot: d ? u[0] : u.at(-1) + 1
102
+ insertionIndex: d ? u[0] : u.at(-1) + 1
100
103
  };
101
104
  }
102
- function h(e, t) {
105
+ function g(e, t) {
103
106
  return e.type !== "split" || e.axis !== t ? [{
104
107
  node: e,
105
108
  weight: 1
@@ -108,43 +111,43 @@ function h(e, t) {
108
111
  weight: e.weights[n]
109
112
  }));
110
113
  }
111
- function g(e) {
114
+ function _(e) {
112
115
  let t = e.peers.reduce((e, t) => e + t.weight, 0) / e.peers.length, n = e.branch.children.map((n) => {
113
- if (v(n, e.moving)) return t;
114
- let r = e.peers.findIndex((e) => a(e.node) === a(n));
116
+ if (y(n, e.moving)) return t;
117
+ let r = e.peers.findIndex((e) => o(e.node, n));
115
118
  if (!(r < 0)) return e.peers[r].weight;
116
119
  });
117
120
  return n.every((e) => e !== void 0) ? n : void 0;
118
121
  }
119
- function _(e, t) {
122
+ function v(e, t) {
120
123
  if (e?.type === "split") {
121
- if (e.children.some((e) => e.type === "group" && e.panels.length > 0 && v(e, t))) return e;
124
+ if (e.children.some((e) => e.type === "group" && e.panels.length > 0 && y(e, t))) return e;
122
125
  for (let n of e.children) {
123
- let e = _(n, t);
126
+ let e = v(n, t);
124
127
  if (e) return e;
125
128
  }
126
129
  }
127
130
  }
128
- function v(e, t) {
131
+ function y(e, t) {
129
132
  return e.type === "group" && e.panels.every((e) => t.includes(e));
130
133
  }
131
- function y(e, t, n = "root") {
134
+ function b(e, t, n = "root") {
132
135
  if (e === t) return n;
133
136
  if (e.type === "split") for (let [r, i] of e.children.entries()) {
134
- let e = y(i, t, `${n}.${r}`);
137
+ let e = b(i, t, `${n}.${r}`);
135
138
  if (e) return e;
136
139
  }
137
140
  }
138
- function b(e) {
139
- let t = o(e.layout, e.branch, e.weights, e.available);
141
+ function x(e) {
142
+ let t = a(e.layout, e.branch, e.weights, e.available);
140
143
  if (t) return t;
141
144
  let n = e.weights.reduce((e, t) => e + t, 0);
142
145
  return e.branch.weights.every((t, r) => Math.abs(t - e.weights[r] / n) < 1e-10) ? e.layout : void 0;
143
146
  }
144
- function x(t) {
145
- let n = t.available.filter((e) => !t.plan.layout.closed.includes(e)), i = t.source.filter((e) => n.includes(e)), a = _((t.projectLayout ?? r)(t.plan.layout, n).root, i);
147
+ function S(t) {
148
+ let n = t.available.filter((e) => !t.plan.layout.closed.includes(e)), i = t.source.filter((e) => n.includes(e)), a = v((t.projectLayout ?? r)(t.plan.layout, n).root, i);
146
149
  if (!a) return;
147
- let o = a.children.findIndex((e) => v(e, i));
150
+ let o = a.children.findIndex((e) => y(e, i));
148
151
  if (!(o < 0)) return {
149
152
  axis: a.axis,
150
153
  index: o,
@@ -154,18 +157,18 @@ function x(t) {
154
157
  key: JSON.stringify([
155
158
  a.axis,
156
159
  o,
157
- S(t.plan.layout.root),
160
+ C(t.plan.layout.root),
158
161
  t.plan.layout.closed
159
162
  ])
160
163
  };
161
164
  }
162
- function S(e) {
165
+ function C(e) {
163
166
  return e ? e.type === "group" ? [
164
167
  "group",
165
168
  e.panels,
166
169
  e.active
167
- ] : [e.axis, e.children.map(S)] : null;
170
+ ] : [e.axis, e.children.map(C)] : null;
168
171
  }
169
- export { x as describePlacementSlot, l as planGroupInsertion };
172
+ export { S as computeGroupInsertion, l as getGroupInsertion, u as planGroupInsertion };
170
173
 
171
174
  //# sourceMappingURL=group-insertion.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"group-insertion.utils.js","names":["planGroupInsertion","context","insertionContext","input","topology","insertionTopology","sizeInsertion","donor","peers","slot","projectLayoutForCandidate","projectLayout","carrier","findDeepestProjectionCarrier","root","getProjectionSignature","residualLayout","createDetachedLayout","node","visible","key","nodeKey","before","destination","getPanelIds","getSplitSide","axis","placeRegion","projectedRoot","moving","id","branch","movingOwner","weights","insertedWeights","layout","insertionWeights","owner","insertionBasis","target","findWorkspaceRegion","insertionOwner","parent","basis","residual","insertionPeers","selected","matches","peer","index","incoming","sum","isMovingGroup","child","weight","found","rebased","rebaseProjectedSplit","total","describePlacementSlot","placementShape"],"sources":["../../../../src/workspace/utils/placement/group-insertion.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, getSplitSide } from '../model/layout.utils.js';\nimport { createDetachedLayout, projectLayout } from '../model/operations.utils.js';\nimport {\n findDeepestProjectionCarrier,\n getProjectionSignature,\n rebaseProjectedSplit\n} from '../model/projection.utils.js';\nimport { findWorkspaceRegion, placeRegion } from './region.utils.js';\n\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 { WorkspacePlacementPlan } from './planner.utils.js';\n\ninterface InsertionInput {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}\n\nexport function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined {\n const context = insertionContext(input);\n if (!context) return undefined;\n const topology = insertionTopology(input, context);\n return topology ? sizeInsertion({ input, context, topology }) : undefined;\n}\n\nfunction insertionTopology(input: InsertionInput, context: NonNullable<ReturnType<typeof insertionContext>>) {\n const { peers, slot, visible, root, axis } = context;\n const donorIndex = Math.min(slot, peers.length - 1);\n const donor = peers[donorIndex]!;\n const projectLayoutForCandidate = input.projectLayout ?? projectLayout;\n const carrier = findDeepestProjectionCarrier(root, getProjectionSignature(donor.node), node => {\n const residualLayout = createDetachedLayout({ version: 1, root: node, closed: [] }, input.source);\n return projectLayoutForCandidate(residualLayout, visible).root;\n });\n const key = carrier && nodeKey(root, carrier);\n if (!key || !carrier) return undefined;\n const before = slot < peers.length;\n const destination: WorkspaceDestination = {\n target: getPanelIds(carrier)[0]!,\n region: key,\n position: getSplitSide(axis, before ? 'before' : 'after')\n };\n const topology = placeRegion({ ...input, destination });\n return topology;\n}\n\nfunction sizeInsertion({\n input,\n context,\n topology\n}: {\n input: InsertionInput;\n context: NonNullable<ReturnType<typeof insertionContext>>;\n topology: WorkspacePlacementPlan;\n}): WorkspacePlacementPlan | undefined {\n const { owner, peers, visible, axis } = context;\n const projectedRoot = (input.projectLayout ?? projectLayout)(topology.layout, visible).root;\n const moving = input.source.filter(id => visible.includes(id));\n const branch = movingOwner(projectedRoot, moving);\n if (!branch || branch.axis !== axis || branch.children.length !== peers.length + 1) return undefined;\n const weights = insertedWeights({\n branch,\n peers,\n moving\n });\n if (!weights) return undefined;\n const layout = insertionWeights({ layout: topology.layout, branch, weights, available: input.available });\n if (!layout) return undefined;\n return {\n kind: 'insert',\n layout,\n context: { kind: 'rail', members: [...new Set([...getPanelIds(owner), ...moving])] }\n };\n}\n\nfunction insertionBasis(input: InsertionInput) {\n const { destination, layout } = input;\n if (!destination.region || destination.position === 'tab') return undefined;\n const visible = input.available.filter(id => !layout.closed.includes(id));\n const root = (input.projectLayout ?? projectLayout)(layout, visible).root;\n const target = findWorkspaceRegion(root, destination.region);\n if (!root || !target) return undefined;\n const axis: WorkspaceSplit['axis'] =\n destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical';\n const owner = insertionOwner({ root, target, key: destination.region, axis });\n if (!owner) return undefined;\n return {\n visible,\n root,\n target,\n axis,\n owner\n };\n}\n\nfunction insertionOwner(input: {\n root: WorkspaceNode;\n target: WorkspaceNode;\n key: string;\n axis: WorkspaceSplit['axis'];\n}) {\n if (input.target.type === 'split' && input.target.axis === input.axis) return input.target;\n const parent = findWorkspaceRegion(input.root, input.key.split('.').slice(0, -1).join('.'));\n if (parent?.type === 'split' && parent.axis === input.axis) return parent;\n return input.target.type === 'split' ? input.target : undefined;\n}\n\nfunction insertionContext(input: InsertionInput) {\n const basis = insertionBasis(input);\n if (!basis) return undefined;\n const { owner, target, axis } = basis;\n const residual = createDetachedLayout({ version: 1, root: owner, closed: [] }, input.source).root;\n if (!residual) return undefined;\n const peers = insertionPeers(residual, axis);\n const selected = new Set(getPanelIds(target).filter(id => !input.source.includes(id)));\n const matches = peers.flatMap((peer, index) => (getPanelIds(peer.node).every(id => selected.has(id)) ? [index] : []));\n if (!matches.length) return undefined;\n const before = input.destination.position === 'left' || input.destination.position === 'top';\n return { ...basis, peers, slot: before ? matches[0]! : matches.at(-1)! + 1 };\n}\n\nfunction insertionPeers(residual: WorkspaceNode, axis: WorkspaceSplit['axis']) {\n if (residual.type !== 'split' || residual.axis !== axis) return [{ node: residual, weight: 1 }];\n return residual.children.map((node, index) => ({ node, weight: residual.weights[index]! }));\n}\n\nfunction insertedWeights(input: {\n branch: WorkspaceSplit;\n peers: { node: WorkspaceNode; weight: number }[];\n moving: string[];\n}) {\n const incoming = input.peers.reduce((sum, peer) => sum + peer.weight, 0) / input.peers.length;\n const weights = input.branch.children.map(child => {\n if (isMovingGroup(child, input.moving)) return incoming;\n const index = input.peers.findIndex(peer => getProjectionSignature(peer.node) === getProjectionSignature(child));\n if (index < 0) return undefined;\n const weight = input.peers[index]!.weight;\n return weight;\n });\n return weights.every((weight): weight is number => weight !== undefined) ? weights : undefined;\n}\n\nfunction movingOwner(node: WorkspaceNode | null, moving: string[]): WorkspaceSplit | undefined {\n if (node?.type !== 'split') return undefined;\n if (node.children.some(child => child.type === 'group' && child.panels.length > 0 && isMovingGroup(child, moving)))\n return node;\n for (const child of node.children) {\n const found = movingOwner(child, moving);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction isMovingGroup(node: WorkspaceNode, moving: string[]) {\n return node.type === 'group' && node.panels.every(id => moving.includes(id));\n}\n\nfunction nodeKey(node: WorkspaceNode, target: WorkspaceNode, key = 'root'): string | undefined {\n if (node === target) return key;\n if (node.type !== 'split') return undefined;\n for (const [index, child] of node.children.entries()) {\n const found = nodeKey(child, target, `${key}.${index}`);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction insertionWeights(input: {\n layout: WorkspaceLayout;\n branch: WorkspaceSplit;\n weights: number[];\n available: string[];\n}) {\n const rebased = rebaseProjectedSplit(input.layout, input.branch, input.weights, input.available);\n if (rebased) return rebased;\n const total = input.weights.reduce((sum, weight) => sum + weight, 0);\n return input.branch.weights.every((weight, index) => Math.abs(weight - input.weights[index]! / total) < 1e-10)\n ? input.layout\n : undefined;\n}\n\nexport function describePlacementSlot(input: {\n plan: Pick<WorkspacePlacementPlan, 'layout'>;\n source: string[];\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}) {\n const visible = input.available.filter(id => !input.plan.layout.closed.includes(id));\n const moving = input.source.filter(id => visible.includes(id));\n const owner = movingOwner((input.projectLayout ?? projectLayout)(input.plan.layout, visible).root, moving);\n if (!owner) return undefined;\n const index = owner.children.findIndex(child => isMovingGroup(child, moving));\n if (index < 0) return undefined;\n return {\n axis: owner.axis,\n index,\n members: getPanelIds(owner).filter(id => !moving.includes(id)),\n previous: owner.children[index - 1] ? getPanelIds(owner.children[index - 1]!) : undefined,\n next: owner.children[index + 1] ? getPanelIds(owner.children[index + 1]!) : undefined,\n key: JSON.stringify([owner.axis, index, placementShape(input.plan.layout.root), input.plan.layout.closed])\n };\n}\n\nfunction placementShape(node: WorkspaceNode | null): unknown {\n if (!node) return null;\n return node.type === 'group' ? ['group', node.panels, node.active] : [node.axis, node.children.map(placementShape)];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"group-insertion.utils.js","names":["getGroupInsertion","input","computeGroupInsertion","planGroupInsertion","context","insertionContext","topology","insertionTopology","sizeInsertion","donor","peers","insertionIndex","projectLayoutForCandidate","projectLayout","carrier","findDeepestProjectionCarrier","root","residualLayout","createDetachedLayout","node","visible","key","nodeKey","before","destination","getPanelIds","getSplitSide","axis","placeRegion","projectedRoot","moving","id","branch","movingOwner","weights","insertedWeights","layout","insertionWeights","owner","insertionBasis","target","findWorkspaceRegion","insertionOwner","parent","basis","residual","insertionPeers","selected","matches","peer","index","incoming","sum","isMovingGroup","child","sameProjectionShape","weight","found","rebased","rebaseProjectedSplit","total","placementShape"],"sources":["../../../../src/workspace/utils/placement/group-insertion.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, getSplitSide } from '../model/layout.utils.js';\nimport { createDetachedLayout, projectLayout } from '../model/operations.utils.js';\nimport { findDeepestProjectionCarrier, rebaseProjectedSplit, sameProjectionShape } from '../model/projection.utils.js';\nimport { findWorkspaceRegion, placeRegion } from './region.utils.js';\n\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 { WorkspacePlacementPlan, WorkspacePlacementPlanner } from './planner.utils.js';\nimport type { WorkspacePlacementSession } from './session.utils.js';\n\ninterface InsertionInput {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n available: string[];\n projectLayout?: WorkspaceLayoutProjector;\n}\n\nexport interface GroupInsertionInputs {\n readonly plan: Pick<WorkspacePlacementPlan, 'layout'>;\n readonly source: string[];\n readonly available: string[];\n readonly projectLayout?: WorkspaceLayoutProjector;\n readonly placementSession?: WorkspacePlacementSession;\n readonly planPlacement?: WorkspacePlacementPlanner;\n}\n\nexport interface GroupInsertion {\n axis: WorkspaceSplit['axis'];\n index: number;\n members: string[];\n previous?: string[];\n next?: string[];\n key: string;\n}\n\nexport function getGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined {\n return input.placementSession && !input.planPlacement\n ? input.placementSession.getInsertion(input)\n : computeGroupInsertion(input);\n}\n\nexport function planGroupInsertion(input: InsertionInput): WorkspacePlacementPlan | undefined {\n const context = insertionContext(input);\n if (!context) return undefined;\n const topology = insertionTopology(input, context);\n return topology ? sizeInsertion({ input, context, topology }) : undefined;\n}\n\nfunction insertionTopology(input: InsertionInput, context: NonNullable<ReturnType<typeof insertionContext>>) {\n const { peers, insertionIndex, visible, root, axis } = context;\n const donorIndex = Math.min(insertionIndex, peers.length - 1);\n const donor = peers[donorIndex]!;\n const projectLayoutForCandidate = input.projectLayout ?? projectLayout;\n const carrier = findDeepestProjectionCarrier(root, donor.node, node => {\n const residualLayout = createDetachedLayout({ version: 1, root: node, closed: [] }, input.source);\n return projectLayoutForCandidate(residualLayout, visible).root;\n });\n const key = carrier && nodeKey(root, carrier);\n if (!key || !carrier) return undefined;\n const before = insertionIndex < peers.length;\n const destination: WorkspaceDestination = {\n target: getPanelIds(carrier)[0]!,\n region: key,\n position: getSplitSide(axis, before ? 'before' : 'after')\n };\n const topology = placeRegion({ ...input, destination });\n return topology;\n}\n\nfunction sizeInsertion({\n input,\n context,\n topology\n}: {\n input: InsertionInput;\n context: NonNullable<ReturnType<typeof insertionContext>>;\n topology: WorkspacePlacementPlan;\n}): WorkspacePlacementPlan | undefined {\n const { owner, peers, visible, axis } = context;\n const projectedRoot = (input.projectLayout ?? projectLayout)(topology.layout, visible).root;\n const moving = input.source.filter(id => visible.includes(id));\n const branch = movingOwner(projectedRoot, moving);\n if (!branch || branch.axis !== axis || branch.children.length !== peers.length + 1) return undefined;\n const weights = insertedWeights({\n branch,\n peers,\n moving\n });\n if (!weights) return undefined;\n const layout = insertionWeights({ layout: topology.layout, branch, weights, available: input.available });\n if (!layout) return undefined;\n return {\n kind: 'insert',\n layout,\n scope: { kind: 'rail', members: [...new Set([...getPanelIds(owner), ...moving])] }\n };\n}\n\nfunction insertionBasis(input: InsertionInput) {\n const { destination, layout } = input;\n if (!destination.region || destination.position === 'tab') return undefined;\n const visible = input.available.filter(id => !layout.closed.includes(id));\n const root = (input.projectLayout ?? projectLayout)(layout, visible).root;\n const target = findWorkspaceRegion(root, destination.region);\n if (!root || !target) return undefined;\n const axis: WorkspaceSplit['axis'] =\n destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical';\n const owner = insertionOwner({ root, target, key: destination.region, axis });\n if (!owner) return undefined;\n return {\n visible,\n root,\n target,\n axis,\n owner\n };\n}\n\nfunction insertionOwner(input: {\n root: WorkspaceNode;\n target: WorkspaceNode;\n key: string;\n axis: WorkspaceSplit['axis'];\n}) {\n if (input.target.type === 'split' && input.target.axis === input.axis) return input.target;\n const parent = findWorkspaceRegion(input.root, input.key.split('.').slice(0, -1).join('.'));\n if (parent?.type === 'split' && parent.axis === input.axis) return parent;\n return input.target.type === 'split' ? input.target : undefined;\n}\n\nfunction insertionContext(input: InsertionInput) {\n const basis = insertionBasis(input);\n if (!basis) return undefined;\n const { owner, target, axis } = basis;\n const residual = createDetachedLayout({ version: 1, root: owner, closed: [] }, input.source).root;\n if (!residual) return undefined;\n const peers = insertionPeers(residual, axis);\n const selected = new Set(getPanelIds(target).filter(id => !input.source.includes(id)));\n const matches = peers.flatMap((peer, index) => (getPanelIds(peer.node).every(id => selected.has(id)) ? [index] : []));\n if (!matches.length) return undefined;\n const before = input.destination.position === 'left' || input.destination.position === 'top';\n return { ...basis, peers, insertionIndex: before ? matches[0]! : matches.at(-1)! + 1 };\n}\n\nfunction insertionPeers(residual: WorkspaceNode, axis: WorkspaceSplit['axis']) {\n if (residual.type !== 'split' || residual.axis !== axis) return [{ node: residual, weight: 1 }];\n return residual.children.map((node, index) => ({ node, weight: residual.weights[index]! }));\n}\n\nfunction insertedWeights(input: {\n branch: WorkspaceSplit;\n peers: { node: WorkspaceNode; weight: number }[];\n moving: string[];\n}) {\n const incoming = input.peers.reduce((sum, peer) => sum + peer.weight, 0) / input.peers.length;\n const weights = input.branch.children.map(child => {\n if (isMovingGroup(child, input.moving)) return incoming;\n const index = input.peers.findIndex(peer => sameProjectionShape(peer.node, child));\n if (index < 0) return undefined;\n const weight = input.peers[index]!.weight;\n return weight;\n });\n return weights.every((weight): weight is number => weight !== undefined) ? weights : undefined;\n}\n\nfunction movingOwner(node: WorkspaceNode | null, moving: string[]): WorkspaceSplit | undefined {\n if (node?.type !== 'split') return undefined;\n if (node.children.some(child => child.type === 'group' && child.panels.length > 0 && isMovingGroup(child, moving)))\n return node;\n for (const child of node.children) {\n const found = movingOwner(child, moving);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction isMovingGroup(node: WorkspaceNode, moving: string[]) {\n return node.type === 'group' && node.panels.every(id => moving.includes(id));\n}\n\nfunction nodeKey(node: WorkspaceNode, target: WorkspaceNode, key = 'root'): string | undefined {\n if (node === target) return key;\n if (node.type !== 'split') return undefined;\n for (const [index, child] of node.children.entries()) {\n const found = nodeKey(child, target, `${key}.${index}`);\n if (found) return found;\n }\n return undefined;\n}\n\nfunction insertionWeights(input: {\n layout: WorkspaceLayout;\n branch: WorkspaceSplit;\n weights: number[];\n available: string[];\n}) {\n const rebased = rebaseProjectedSplit(input.layout, input.branch, input.weights, input.available);\n if (rebased) return rebased;\n const total = input.weights.reduce((sum, weight) => sum + weight, 0);\n return input.branch.weights.every((weight, index) => Math.abs(weight - input.weights[index]! / total) < 1e-10)\n ? input.layout\n : undefined;\n}\n\nexport function computeGroupInsertion(input: GroupInsertionInputs): GroupInsertion | undefined {\n const visible = input.available.filter(id => !input.plan.layout.closed.includes(id));\n const moving = input.source.filter(id => visible.includes(id));\n const owner = movingOwner((input.projectLayout ?? projectLayout)(input.plan.layout, visible).root, moving);\n if (!owner) return undefined;\n const index = owner.children.findIndex(child => isMovingGroup(child, moving));\n if (index < 0) return undefined;\n return {\n axis: owner.axis,\n index,\n members: getPanelIds(owner).filter(id => !moving.includes(id)),\n previous: owner.children[index - 1] ? getPanelIds(owner.children[index - 1]!) : undefined,\n next: owner.children[index + 1] ? getPanelIds(owner.children[index + 1]!) : undefined,\n key: JSON.stringify([owner.axis, index, placementShape(input.plan.layout.root), input.plan.layout.closed])\n };\n}\n\nfunction placementShape(node: WorkspaceNode | null): unknown {\n if (!node) return null;\n return node.type === 'group' ? ['group', node.panels, node.active] : [node.axis, node.children.map(placementShape)];\n}\n"],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  import type { WorkspaceLayout } from '../model/layout.utils.js';
2
2
  import type { WorkspaceDestination } from '../model/operations.utils.js';
3
3
  import type { WorkspaceLayoutProjector } from '../model/projection.utils.js';
4
- import type { WorkspacePlacementContext } from './context.utils.js';
4
+ import type { WorkspacePlacementScope } from './scope.utils.js';
5
+ import type { WorkspacePlacementSession } from './session.utils.js';
5
6
  export interface WorkspacePlacementPlan {
6
7
  kind: 'reorder' | 'split' | 'tab' | 'insert';
7
- context?: WorkspacePlacementContext;
8
+ scope?: WorkspacePlacementScope;
8
9
  layout: WorkspaceLayout;
9
10
  }
10
11
  interface PlacementInput {
@@ -18,5 +19,15 @@ interface PlacementInput {
18
19
  export type WorkspacePlacementPlanner = (input: PlacementInput) => WorkspacePlacementPlan | undefined;
19
20
  /** Requires an immutable current layout; projection callbacks are never retained. */
20
21
  export declare function createWorkspacePlacementPlanner(): WorkspacePlacementPlanner;
22
+ interface WorkspacePlanningContext {
23
+ currentLayout: WorkspaceLayout;
24
+ source: string[];
25
+ available: string[];
26
+ projectLayout?: WorkspaceLayoutProjector;
27
+ planPlacement?: WorkspacePlacementPlanner;
28
+ placementSession?: WorkspacePlacementSession;
29
+ }
30
+ /** Supplied planners keep their ordinary path; component gestures use their explicit session. */
31
+ export declare function resolvePlacementPlan(context: WorkspacePlanningContext, destination: WorkspaceDestination, operation: PlacementInput['operation']): WorkspacePlacementPlan | undefined;
21
32
  export declare function planWorkspacePlacement(input: PlacementInput): WorkspacePlacementPlan | undefined;
22
33
  export {};