@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,17 +1,17 @@
1
1
  import { getPanelIds as e, getSplitSide as t } from "../model/layout.utils.js";
2
2
  import { findGroup as n, projectLayout as r } from "../model/operations.utils.js";
3
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";
4
+ import { getTabInsertionIndex as o, preservesGroupMembership as s } from "../model/membership.utils.js";
5
+ import { createScopeRectResolver as c } from "../placement/scope.utils.js";
6
+ import { findWorkspaceRegion as l } from "../placement/region.utils.js";
7
+ import { getGroupInsertion as u } from "../placement/group-insertion.utils.js";
8
+ import { resolvePlacementPlan as d } from "../placement/planner.utils.js";
9
+ import { createInsertionOffers as f, findSourcePeerRegionKey as p, getOrderHintRect as m, getPlacementOfferIntent as h, placementOwnsChrome as g } from "./insertion-offers.utils.js";
10
+ import { getBoundaryPlacementOffers as _ } from "./boundary.utils.js";
11
11
  // src/workspace/utils/interaction/placement-decision.utils.ts
12
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
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);
14
+ let { placement: t, point: n } = e, r = !!t.headerTarget, i = S(e, t.headerTarget ?? (v(t.bounds, n) ? t.targets.find((e) => v(e.rect, n)) : void 0), r);
15
15
  return b({
16
16
  ...t,
17
17
  source: e.source,
@@ -22,25 +22,23 @@ function y(e) {
22
22
  gap: e.gap,
23
23
  available: e.available,
24
24
  projectLayout: e.projectLayout,
25
- planPlacement: e.planPlacement
25
+ planPlacement: e.planPlacement,
26
+ placementSession: e.placementSession
26
27
  });
27
28
  }
28
29
  function b(e) {
29
- let t = E({
30
+ let t = D({
30
31
  ...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;
32
+ resolveScopeRect: e.resolveScopeRect ?? c()
33
+ }), n = k(t.offers, e), r = w(e), i = t.offers.filter((t) => T(t, r, e.bounds)), a = x(i, n, e.point), o = v(e.bounds, e.point) ? t.offers.find((t) => v(t.hitRect ?? t.rect, e.point) && (!e.header || g(t))) : void 0, s = t.hit ?? o;
36
34
  return {
37
- acquisition: c ? {
38
- plan: c.plan,
39
- rect: c.hitRect ?? c.rect
35
+ acquisition: s ? {
36
+ plan: s.plan,
37
+ rect: s.hitRect ?? s.rect
40
38
  } : void 0,
41
- intent: D(e, c),
42
- hint: T({
43
- hit: c && i.includes(c) ? c : void 0,
39
+ intent: O(e, s),
40
+ hint: E({
41
+ hit: s && i.includes(s) ? s : void 0,
44
42
  selectedKey: n,
45
43
  boundary: t.hit,
46
44
  nearest: a
@@ -48,61 +46,73 @@ function b(e) {
48
46
  };
49
47
  }
50
48
  function x(e, t, n) {
49
+ let r, i = Infinity;
50
+ for (let a of e) {
51
+ if (a.insertion.key === t) continue;
52
+ let e = A(a, n);
53
+ (!r || e < i) && (r = a, i = e);
54
+ }
55
+ return r && {
56
+ offer: r,
57
+ distance: i
58
+ };
59
+ }
60
+ function S(e, t, n) {
51
61
  let { reservationHit: r } = e.placement, i = !n && r, a = n && r === "tab" && e.heldIntent.kind === "tab";
52
62
  if (i || a) return e.heldIntent;
53
63
  if (!t) return;
54
64
  let o = t.panels[0];
55
- return o ? n ? S(e, t, o) : {
65
+ return o ? n ? C(e, t, o) : {
56
66
  kind: "split",
57
67
  destination: {
58
68
  target: o,
59
- position: I(e.point, {
69
+ position: L(e.point, {
60
70
  rect: t.rect,
61
71
  headerHeight: t.headerHeight
62
72
  })
63
73
  }
64
74
  } : { kind: "invalid" };
65
75
  }
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 = {
76
+ function C(e, t, r) {
77
+ let i = t.tabs.find((t) => e.point.x < t.rect.x + t.rect.width / 2), a = n(e.canonicalRoot, r)?.panels ?? [], c = {
68
78
  kind: "tab",
69
79
  destination: {
70
80
  target: r,
71
81
  position: "tab",
72
- index: g(a, i?.id)
82
+ index: o(a, i?.id)
73
83
  }
74
84
  };
75
- return e.groupable || _({
85
+ return e.groupable || s({
76
86
  root: e.canonicalRoot,
77
87
  source: e.source,
78
- intent: o
79
- }) ? o : void 0;
88
+ intent: c
89
+ }) ? c : void 0;
80
90
  }
81
- function C(e) {
91
+ function w(e) {
82
92
  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);
93
+ if (e.sourceReservation && t?.phase === "detached" && !t.blocked && t.allocation === "reserved" && t.cue.kind === "group") return i(e.sourceReservation, e.bounds);
84
94
  }
85
- function w(e, t, n) {
95
+ function T(e, t, n) {
86
96
  if (!t) return !0;
87
97
  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
98
  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
99
  }
90
- function T({ hit: e, selectedKey: t, boundary: n, nearest: r }) {
91
- if (e && e.scope.key !== t) return e;
100
+ function E({ hit: e, selectedKey: t, boundary: n, nearest: r }) {
101
+ if (e && e.insertion.key !== t) return e;
92
102
  if (!n && r && r.distance <= 24) return r.offer;
93
103
  }
94
- function E(e) {
95
- let t = (e.projectLayout ?? r)(e.currentLayout, e.available).root, n = e.orderingRegions ?? e.regions, i = u({
104
+ function D(e) {
105
+ let t = (e.projectLayout ?? r)(e.currentLayout, e.available).root, n = e.orderingRegions ?? e.regions, i = f({
96
106
  ...e,
97
107
  root: t,
98
108
  regions: n,
99
109
  explorationRegions: e.regions,
100
- existing: j({
110
+ existing: M({
101
111
  ...e,
102
112
  root: t
103
113
  })
104
114
  });
105
- return h({
115
+ return _({
106
116
  offers: i,
107
117
  bounds: e.bounds,
108
118
  point: e.point,
@@ -112,52 +122,54 @@ function E(e) {
112
122
  regions: n,
113
123
  source: e.source,
114
124
  gap: e.gap,
115
- contextRect: e.contextRect
125
+ resolveScopeRect: e.resolveScopeRect
116
126
  }
117
127
  });
118
128
  }
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
129
  function O(e, t) {
130
+ if (t) return h(t);
131
+ if (v(e.bounds, e.point)) return e.sourceReservation && v(e.sourceReservation, e.point) ? e.preview?.intent ?? e.local : e.local;
132
+ }
133
+ function k(e, t) {
124
134
  let n = t.preview;
125
- if (n && n.phase === "detached") return "layout" in n ? c({
135
+ if (n && n.phase === "detached") return "layout" in n ? u({
126
136
  plan: n,
127
137
  source: t.source,
128
138
  available: t.available,
129
- projectLayout: t.projectLayout
130
- })?.key : e.find((e) => a(p(e), n.intent))?.scope.key;
139
+ projectLayout: t.projectLayout,
140
+ placementSession: t.placementSession,
141
+ planPlacement: t.planPlacement
142
+ })?.key : e.find((e) => a(h(e), n.intent))?.insertion.key;
131
143
  }
132
- function k(e, t) {
144
+ function A(e, t) {
133
145
  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
146
  if (!(i >= a && i < a + o)) return Infinity;
135
147
  let s = r ? t.x - n.x : t.y - n.y, c = r ? n.width : n.height;
136
148
  return Math.abs(s - c / 2);
137
149
  }
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({
150
+ function j(t) {
151
+ let { root: r, source: i } = t, a = p(r, i) ?? "root", o = l(r, a), s = n(t.currentLayout.root, i[0]);
152
+ if (o?.type !== "split" || !F(s, i)) return;
153
+ let c = (n) => n.find((e) => e.key === a)?.rect ?? t.resolveScopeRect({
142
154
  members: e(o).filter((e) => !i.includes(e)),
143
155
  allocation: n,
144
156
  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 {
157
+ }), u = c(t.regions), d = c(t.orderingRegions ?? t.regions);
158
+ if (!u || !d) return;
159
+ let f = o.children.findIndex((e) => e.type === "group" && e.panels.some((e) => i.includes(e)));
160
+ if (!(f < 0)) return {
149
161
  key: a,
150
162
  owner: o,
151
163
  rect: u,
152
- adjacencyRect: f,
153
- peers: o.children.flatMap((e, t) => t === p ? [] : [{
164
+ adjacencyRect: d,
165
+ peers: o.children.flatMap((e, t) => t === f ? [] : [{
154
166
  node: e,
155
167
  index: t
156
168
  }])
157
169
  };
158
170
  }
159
- function j(e) {
160
- let t = A(e);
171
+ function M(e) {
172
+ let t = j(e);
161
173
  if (!t) return [];
162
174
  let n = t.peers.map((e) => ({
163
175
  ...e,
@@ -166,74 +178,69 @@ function j(e) {
166
178
  return r && n.push({
167
179
  ...r,
168
180
  after: !0
169
- }), n.flatMap((n, r) => M({
181
+ }), n.flatMap((n, r) => N({
170
182
  input: e,
171
183
  owner: t,
172
184
  entry: n,
173
- slot: r
185
+ insertionIndex: r
174
186
  }));
175
187
  }
176
- function M({ input: n, owner: r, entry: i, slot: a }) {
177
- let o = F({
188
+ function N({ input: n, owner: r, entry: i, insertionIndex: a }) {
189
+ let o = I({
178
190
  input: n,
179
191
  owner: r,
180
192
  entry: i,
181
- slot: a
193
+ insertionIndex: a
182
194
  });
183
195
  if (!o) return [];
184
- let { region: s, before: u } = o, d = {
196
+ let { region: s, before: c } = o, l = {
185
197
  target: e(i.node)[0],
186
198
  region: s.key,
187
199
  position: t(r.owner.axis, i.after ? "after" : "before")
188
- }, p = (n.planPlacement ?? l)({
189
- layout: n.currentLayout,
200
+ }, f = d(n, l, "order");
201
+ if (f?.kind !== "reorder") return [];
202
+ let p = u({
203
+ plan: f,
190
204
  source: n.source,
191
- destination: d,
192
205
  available: n.available,
193
206
  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({
207
+ placementSession: n.placementSession,
208
+ planPlacement: n.planPlacement
209
+ }), h = P(i, a), g = h ? r.rect : r.adjacencyRect, _ = m({
203
210
  owner: g,
204
211
  recipient: s.rect,
205
- previous: u?.rect,
212
+ previous: c?.rect,
206
213
  axis: r.owner.axis,
207
214
  after: i.after,
208
- sourceSlot: n.sourceSlot,
215
+ sourceReservation: n.sourceReservation,
209
216
  boundary: h
210
217
  });
211
- return !_ || !m ? [] : [{
212
- destination: d,
218
+ return !_ || !p ? [] : [{
219
+ destination: l,
213
220
  owner: r.key,
214
221
  boundary: h,
215
222
  rect: _,
216
223
  scopeRect: g,
217
- scope: m,
218
- plan: p,
224
+ insertion: p,
225
+ plan: f,
219
226
  kind: "order"
220
227
  }];
221
228
  }
222
- function N(e, t) {
229
+ function P(e, t) {
223
230
  if (e.after) return "end";
224
231
  if (t === 0) return "start";
225
232
  }
226
- function P(e, t) {
233
+ function F(e, t) {
227
234
  return !!e && e.panels.length === t.length && e.panels.every((e) => t.includes(e));
228
235
  }
229
- function F({ input: e, owner: t, entry: n, slot: r }) {
236
+ function I({ input: e, owner: t, entry: n, insertionIndex: r }) {
230
237
  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
238
  return !a || r > 0 && !n.after && !s ? void 0 : {
232
239
  region: a,
233
240
  before: s
234
241
  };
235
242
  }
236
- function I(e, t) {
243
+ function L(e, t) {
237
244
  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
245
  return Math.abs(s) > Math.abs(c) ? s < 0 ? "left" : "right" : c < 0 ? "top" : "bottom";
239
246
  }
@@ -1 +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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"}
1
+ {"version":3,"file":"placement-decision.utils.js","names":["inside","point","rect","decidePointerPlacement","input","header","placement","local","localPlacementIntent","item","decidePlacement","boundary","placementOffers","createScopeRectResolver","selectedKey","selectedInsertionKey","sourceReservation","getActiveSourceReservation","hints","eligiblePlacementHint","offer","nearest","nearestPlacementHint","candidate","placementOwnsChrome","hit","acquiredIntent","placementHint","nearestOffer","nearestDistance","offerDistance","distance","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","getGroupInsertion","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","resolvePlacementPlan","insertion","orderBoundary","insertionIndex","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 { getGroupInsertion } from '../placement/group-insertion.utils.js';\nimport { resolvePlacementPlan } from '../placement/planner.utils.js';\nimport { findWorkspaceRegion } from '../placement/region.utils.js';\nimport { createScopeRectResolver } from '../placement/scope.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 { WorkspacePlacementPlanner } from '../placement/planner.utils.js';\nimport type { WorkspaceScopeRectResolver } from '../placement/scope.utils.js';\nimport type { WorkspacePlacementSession } from '../placement/session.utils.js';\nimport type { WorkspaceTarget } from '../presentation/groups.utils.js';\nimport type { WorkspacePlacementCatalog } from '../evaluation.utils.js';\n\ninterface WorkspacePlacementQuery {\n resolveScopeRect?: WorkspaceScopeRectResolver;\n gap: number;\n source: string[];\n point: Point;\n regions: WorkspacePlacedRegion[];\n orderingRegions?: WorkspacePlacedRegion[];\n sourceReservation?: 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 placementSession?: WorkspacePlacementSession;\n};\n\ntype OfferInput = DecisionInput & { resolveScopeRect: WorkspaceScopeRectResolver };\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 placementSession?: WorkspacePlacementSession;\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 placementSession: input.placementSession\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, resolveScopeRect: input.resolveScopeRect ?? createScopeRectResolver() });\n const selectedKey = selectedInsertionKey(boundary.offers, input);\n const sourceReservation = getActiveSourceReservation(input);\n const hints = boundary.offers.filter(offer => eligiblePlacementHint(offer, sourceReservation, input.bounds));\n const nearest = nearestPlacementHint(hints, selectedKey, input.point);\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 nearestPlacementHint(hints: WorkspaceInsertionOffer[], selectedKey: string | undefined, point: Point) {\n let nearestOffer: WorkspaceInsertionOffer | undefined;\n let nearestDistance = Infinity;\n for (const offer of hints) {\n if (offer.insertion.key === selectedKey) continue;\n const offerDistance = distance(offer, point);\n if (!nearestOffer || offerDistance < nearestDistance) {\n nearestOffer = offer;\n nearestDistance = offerDistance;\n }\n }\n return nearestOffer && { offer: nearestOffer, distance: nearestDistance };\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 getActiveSourceReservation(input: WorkspacePlacementQuery) {\n const preview = input.preview;\n if (\n !input.sourceReservation ||\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.sourceReservation, input.bounds);\n}\n\nfunction eligiblePlacementHint(offer: WorkspaceInsertionOffer, sourceReservation: Rect | undefined, bounds: Rect) {\n if (!sourceReservation) 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] > sourceReservation[normal] &&\n rect[normal] + rect[normalSize] < sourceReservation[normal] + sourceReservation[normalSize];\n if (!normalInsideSource) return true;\n\n const tangentCoveredBySource =\n rect[tangent] >= sourceReservation[tangent] &&\n rect[tangent] + rect[tangentSize] <= sourceReservation[tangent] + sourceReservation[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.insertion.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, resolveScopeRect: input.resolveScopeRect }\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.sourceReservation && inside(input.sourceReservation, input.point))\n return input.preview?.intent ?? input.local;\n return input.local;\n}\n\nfunction selectedInsertionKey(offers: WorkspaceInsertionOffer[], input: DecisionInput) {\n const preview = input.preview;\n if (!preview || preview.phase !== 'detached') return undefined;\n if ('layout' in preview)\n return getGroupInsertion({\n plan: preview,\n source: input.source,\n available: input.available,\n projectLayout: input.projectLayout,\n placementSession: input.placementSession,\n planPlacement: input.planPlacement\n })?.key;\n return offers.find(offer => matchesPlacementIntent(getPlacementOfferIntent(offer), preview.intent))?.insertion.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.resolveScopeRect({\n members: getPanelIds(owner).filter(id => !source.includes(id)),\n allocation: regions,\n source\n });\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, insertionIndex) => orderOffer({ input, owner, entry, insertionIndex }));\n}\n\ninterface OrderOfferInput {\n input: OfferInput;\n owner: OrderOwner;\n entry: { node: WorkspaceNode; index: number; after: boolean };\n insertionIndex: number;\n}\n\nfunction orderOffer({ input, owner, entry, insertionIndex }: OrderOfferInput): WorkspaceInsertionOffer[] {\n const neighbors = orderNeighbors({ input, owner, entry, insertionIndex });\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 = resolvePlacementPlan(input, destination, 'order');\n if (plan?.kind !== 'reorder') return [];\n const insertion = getGroupInsertion({\n plan,\n source: input.source,\n available: input.available,\n projectLayout: input.projectLayout,\n placementSession: input.placementSession,\n planPlacement: input.planPlacement\n });\n const boundary = orderBoundary(entry, insertionIndex);\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 sourceReservation: input.sourceReservation,\n boundary\n });\n if (!area || !insertion) return [];\n return [\n {\n destination,\n owner: owner.key,\n boundary,\n rect: area,\n scopeRect: ownerRect,\n insertion,\n plan,\n kind: 'order'\n }\n ];\n}\n\nfunction orderBoundary(entry: OrderOfferInput['entry'], insertionIndex: number): WorkspaceInsertionOffer['boundary'] {\n if (entry.after) return 'end';\n if (insertionIndex === 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, insertionIndex }: 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[insertionIndex - 1];\n const before = previous && regions.find(candidate => candidate.key === `${owner.key}.${previous.index}`);\n return !region || (insertionIndex > 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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"}
@@ -19,4 +19,5 @@ export declare function getPanelIds(node: WorkspaceNode | null): string[];
19
19
  export declare function getSplitSide(axis: WorkspaceSplit['axis'], position: 'before' | 'after'): 'left' | 'right' | 'top' | 'bottom';
20
20
  /** Converts consecutive splits on the same axis into siblings. */
21
21
  export declare function normalizeLayout(node: WorkspaceNode): WorkspaceNode;
22
- export declare function normalizeOwnedLayout(node: WorkspaceNode): WorkspaceNode;
22
+ /** Reuses unchanged nodes in canonical split graphs produced by mapGroups. */
23
+ export declare function normalizeLayoutWithSharing(node: WorkspaceNode): WorkspaceNode;
@@ -9,33 +9,35 @@ function n(e) {
9
9
  return i(e, "copy");
10
10
  }
11
11
  function r(e) {
12
- return i(e, "owned");
12
+ return i(e, "share-nodes");
13
13
  }
14
14
  function i(e, t) {
15
15
  if (e.type === "group") return t === "copy" ? {
16
- ...e,
17
- panels: [...e.panels]
16
+ type: "group",
17
+ panels: [...e.panels],
18
+ active: e.active
18
19
  } : e;
19
- let n = e.weights.reduce((e, t) => e + t, 0), r = [], a = t === "copy" ? [] : void 0;
20
+ let n = e.weights.reduce((e, t) => e + t, 0), r = t === "copy" ? [] : void 0, a = t === "copy" ? [] : void 0;
20
21
  e.children.forEach((o, s) => {
21
22
  let c = i(o, t), l = e.weights[s] / n;
22
23
  if (!(l > 0)) throw TypeError("Split proportions exceed the supported range");
23
24
  if (c.type === "split" && c.axis === e.axis) {
24
25
  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);
26
+ c.children.forEach((i, a) => {
27
+ (r ??= e.children.slice(0, s)).push(i), t.push(l * c.weights[a] / n);
27
28
  });
28
- } else !a && l !== e.weights[s] && (a = e.weights.slice(0, s)), r.push(c), a?.push(l);
29
+ } else !a && l !== e.weights[s] && (a = e.weights.slice(0, s)), r ? r.push(c) : c !== o && (r = e.children.slice(0, s), r.push(c)), a?.push(l);
29
30
  });
30
31
  let o = a ?? e.weights;
31
32
  if (!o.every((e) => Number.isFinite(e) && e > 0)) throw TypeError("Split proportions exceed the supported range");
32
- return {
33
+ let s = r ?? e.children;
34
+ return s === e.children && o === e.weights ? e : {
33
35
  type: "split",
34
36
  axis: e.axis,
35
- children: r,
37
+ children: s,
36
38
  weights: o
37
39
  };
38
40
  }
39
- export { e as getPanelIds, t as getSplitSide, n as normalizeLayout, r as normalizeOwnedLayout };
41
+ export { e as getPanelIds, t as getSplitSide, n as normalizeLayout, r as normalizeLayoutWithSharing };
40
42
 
41
43
  //# sourceMappingURL=layout.utils.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"layout.utils.js","names":["getPanelIds","node","getSplitSide","axis","position","normalizeLayout","normalizeNode","normalizeLayoutWithSharing","mode","total","a","b","children","weights","normalized","child","share","index","shares","sum","nested","i","normalizedWeights","weight","normalizedChildren"],"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\n/** Reuses unchanged nodes in canonical split graphs produced by mapGroups. */\nexport function normalizeLayoutWithSharing(node: WorkspaceNode): WorkspaceNode {\n return normalizeNode(node, 'share-nodes');\n}\n\nfunction normalizeNode(node: WorkspaceNode, mode: 'copy' | 'share-nodes'): WorkspaceNode {\n if (node.type === 'group')\n return mode === 'copy' ? { type: 'group', panels: [...node.panels], active: node.active } : node;\n const total = node.weights.reduce((a, b) => a + b, 0);\n let children: WorkspaceNode[] | undefined = mode === 'copy' ? [] : undefined;\n let weights: number[] | undefined = mode === 'copy' ? [] : undefined;\n node.children.forEach((child, index) => {\n const normalized = normalizeNode(child, mode);\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 ??= node.children.slice(0, index)).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 if (children) {\n children.push(normalized);\n } else if (normalized !== child) {\n children = node.children.slice(0, index);\n children.push(normalized);\n }\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 const normalizedChildren = children ?? node.children;\n if (normalizedChildren === node.children && normalizedWeights === node.weights) return node;\n return { type: 'split', axis: node.axis, children: normalizedChildren, 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;AAGA,SAAgBM,EAA2B,GAAoC;CAC7E,OAAOD,EAAcL,GAAM,aAAa;AAC1C;AAEA,SAASK,EAAc,GAAqB,GAA6C;CACvF,IAAIL,EAAK,SAAS,SAChB,OAAOO,MAAS,SAAS;EAAE,MAAM;EAAS,QAAQ,CAAC,GAAGP,EAAK,MAAM;EAAG,QAAQA,EAAK;CAAO,IAAIA;CAC9F,IAAMQ,IAAQR,EAAK,QAAQ,QAAQ,GAAG,MAAMS,IAAIC,GAAG,CAAC,GAChDC,IAAwCJ,MAAS,SAAS,CAAC,IAAI,KAAA,GAC/DK,IAAgCL,MAAS,SAAS,CAAC,IAAI,KAAA;CAC3D,EAAK,SAAS,SAAS,GAAO,MAAU;EACtC,IAAMM,IAAaR,EAAcS,GAAOP,CAAI,GACtCQ,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,CADC,MAAaV,EAAK,SAAS,MAAM,GAAGgB,CAAK,EAAA,CAAG,KAAKG,CAAM,GACxDF,EAAO,KAAMF,IAAQF,EAAW,QAAQO,KAAOF,CAAG;GACpD,CAAC;EACH,OAUE,AATI,CAACN,KAAWG,MAAUf,EAAK,QAAQgB,OACrC,IAAUhB,EAAK,QAAQ,MAAM,GAAGgB,CAAK,IAEnCL,IACFA,EAAS,KAAKE,CAAU,IACfA,MAAeC,MACxB,IAAWd,EAAK,SAAS,MAAM,GAAGgB,CAAK,GACvCL,EAAS,KAAKE,CAAU,IAE1BD,GAAS,KAAKG,CAAK;CAEvB,CAAC;CACD,IAAMM,IAAoBT,KAAWZ,EAAK;CAC1C,IAAI,CAACqB,EAAkB,OAAM,MAAU,OAAO,SAASC,CAAM,KAAKA,IAAS,CAAC,GAC1E,MAAU,UAAU,8CAA8C;CACpE,IAAMC,IAAqBZ,KAAYX,EAAK;CAE5C,OADIuB,MAAuBvB,EAAK,YAAYqB,MAAsBrB,EAAK,UAAgBA,IAChF;EAAE,MAAM;EAAS,MAAMA,EAAK;EAAM,UAAUuB;EAAoB,SAASF;CAAkB;AACpG"}
@@ -1,5 +1,9 @@
1
1
  import type { WorkspacePlacementIntent } from '../interaction/command.utils.js';
2
2
  import type { WorkspaceLayout, WorkspaceNode } from './layout.utils.js';
3
+ /** Identifies panel membership independently of its order. */
4
+ export declare function getPanelMembershipKey(members: readonly string[]): string;
5
+ /** Compares unique panel IDs independently of their order. */
6
+ export declare function samePanelMembership(left: readonly string[], right: readonly string[]): boolean;
3
7
  export declare function preservesGroupMembership(input: {
4
8
  root: WorkspaceNode | null;
5
9
  source: string[];
@@ -1,17 +1,26 @@
1
1
  import { findGroup as e } from "./operations.utils.js";
2
2
  // src/workspace/utils/model/membership.utils.ts
3
- function t(t) {
3
+ function t(e) {
4
+ return JSON.stringify([...e].sort());
5
+ }
6
+ function n(e, t) {
7
+ if (e === t) return !0;
8
+ if (e.length !== t.length) return !1;
9
+ for (let n of e) if (!t.includes(n)) return !1;
10
+ return !0;
11
+ }
12
+ function r(t) {
4
13
  let n = e(t.root, t.source[0]);
5
14
  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
15
  }
7
- function n(t) {
16
+ function i(t) {
8
17
  let n = e(t.layout?.root ?? null, t.anchor);
9
18
  return n && n.panels.filter((e) => !t.layout?.closed.includes(e) && t.available.includes(e)).length === 1 ? [...n.panels] : [t.anchor];
10
19
  }
11
- function r(e, t) {
20
+ function a(e, t) {
12
21
  let n = t === void 0 ? e.length : e.indexOf(t);
13
22
  return n < 0 ? e.length : n;
14
23
  }
15
- export { r as getTabInsertionIndex, n as getWorkspacePanelSource, t as preservesGroupMembership };
24
+ export { t as getPanelMembershipKey, a as getTabInsertionIndex, i as getWorkspacePanelSource, r as preservesGroupMembership, n as samePanelMembership };
16
25
 
17
26
  //# sourceMappingURL=membership.utils.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"membership.utils.js","names":["getPanelMembershipKey","members","samePanelMembership","left","right","id","preservesGroupMembership","origin","findGroup","input","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\n/** Identifies panel membership independently of its order. */\nexport function getPanelMembershipKey(members: readonly string[]): string {\n return JSON.stringify([...members].sort());\n}\n\n/** Compares unique panel IDs independently of their order. */\nexport function samePanelMembership(left: readonly string[], right: readonly string[]): boolean {\n if (left === right) return true;\n if (left.length !== right.length) return false;\n for (const id of left) {\n if (!right.includes(id)) return false;\n }\n return true;\n}\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":";;AASA,SAAgBA,EAAsB,GAAoC;CACxE,OAAO,KAAK,UAAU,CAAC,GAAGC,CAAO,CAAC,CAAC,KAAK,CAAC;AAC3C;AAGA,SAAgBC,EAAoB,GAAyB,GAAmC;CAC9F,IAAIC,MAASC,GAAO,OAAO;CAC3B,IAAID,EAAK,WAAWC,EAAM,QAAQ,OAAO;CACzC,KAAK,IAAMC,KAAMF,GACf,IAAI,CAACC,EAAM,SAASC,CAAE,GAAG,OAAO;CAElC,OAAO;AACT;AAEA,SAAgBC,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,SAASJ,CAAE,CAAC;AAC5D;AAEA,SAAgBK,EAAwB,GAI3B;CACX,IAAMC,IAAQH,EAAUC,EAAM,QAAQ,QAAQ,MAAMA,EAAM,MAAM;CAChE,OAAOE,KACLA,EAAM,OAAO,QAAO,MAAM,CAACF,EAAM,QAAQ,OAAO,SAASJ,CAAE,KAAKI,EAAM,UAAU,SAASJ,CAAE,CAAC,CAAC,CAAC,WAAW,IACvG,CAAC,GAAGM,EAAM,MAAM,IAChB,CAACF,EAAM,MAAM;AACnB;AAGA,SAAgBG,EAAqB,GAAqB,GAAoC;CAC5F,IAAMC,IAAQC,MAAW,KAAA,IAAYC,EAAU,SAASA,EAAU,QAAQD,CAAM;CAChF,OAAOD,IAAQ,IAAIE,EAAU,SAASF;AACxC"}
@@ -6,6 +6,7 @@ export interface WorkspaceDestination {
6
6
  position: 'tab' | 'left' | 'right' | 'top' | 'bottom';
7
7
  index?: number;
8
8
  }
9
+ export declare function sameDestination(left: WorkspaceDestination, right: WorkspaceDestination): boolean;
9
10
  export declare function findGroup(node: WorkspaceNode | null, id?: string): WorkspaceGroup | undefined;
10
11
  export declare function isValidInsertionIndex(index: number | undefined): boolean;
11
12
  /** Removes carried panels from the arrangement and closed list without changing the saved layout. */