@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,16 +1,19 @@
1
- import { getPanelIds as e, normalizeLayout as t, normalizeOwnedLayout as n } from "./layout.utils.js";
2
- import { sameSerializedWorkspaceLayout as r } from "./value.utils.js";
1
+ import { getPanelIds as e, normalizeLayout as t, normalizeLayoutWithSharing as n } from "./layout.utils.js";
2
+ import { sameWorkspaceLayout as r } from "./value.utils.js";
3
3
  // src/workspace/utils/model/operations.utils.ts
4
4
  function i(e, t) {
5
+ return e.target === t.target && e.position === t.position && e.region === t.region && e.index === t.index;
6
+ }
7
+ function a(e, t) {
5
8
  if (e) {
6
9
  if (e.type === "group") return t === void 0 || e.panels.includes(t) ? e : void 0;
7
10
  for (let n of e.children) {
8
- let e = i(n, t);
11
+ let e = a(n, t);
9
12
  if (e) return e;
10
13
  }
11
14
  }
12
15
  }
13
- function a(e, t) {
16
+ function o(e, t) {
14
17
  if (!e) return null;
15
18
  if (e.type === "group") {
16
19
  let n = t(e);
@@ -20,8 +23,8 @@ function a(e, t) {
20
23
  };
21
24
  }
22
25
  let r = [], i = [];
23
- return e.children.forEach((n, o) => {
24
- let s = a(n, t), c = e.weights[o];
26
+ return e.children.forEach((n, a) => {
27
+ let s = o(n, t), c = e.weights[a];
25
28
  s && c !== void 0 && (r.push(s), i.push(c));
26
29
  }), r.length ? r.length === 1 ? r[0] ?? null : n({
27
30
  type: "split",
@@ -30,7 +33,7 @@ function a(e, t) {
30
33
  weights: i
31
34
  }) : null;
32
35
  }
33
- function o(e, t) {
36
+ function s(e, t) {
34
37
  let n = e.panels.filter(t), r = n[0];
35
38
  return r === void 0 ? null : {
36
39
  type: "group",
@@ -38,10 +41,10 @@ function o(e, t) {
38
41
  active: n.includes(e.active) ? e.active : r
39
42
  };
40
43
  }
41
- function s(e, t, n) {
44
+ function c(e, t, n) {
42
45
  if (!t.length) return e;
43
- let r = i(e);
44
- return r ? a(e, (e) => ({
46
+ let r = a(e);
47
+ return r ? o(e, (e) => ({
45
48
  ...e,
46
49
  panels: e === r ? [...e.panels, ...t] : [...e.panels],
47
50
  active: e === r ? n ?? e.active : e.active
@@ -51,28 +54,28 @@ function s(e, t, n) {
51
54
  active: n ?? t[0] ?? ""
52
55
  };
53
56
  }
54
- function c(e, t) {
57
+ function l(e, t) {
55
58
  return t.length === 1 || t.length === e.panels.length && t.every((t, n) => e.panels[n] === t);
56
59
  }
57
- function l(e) {
60
+ function u(e) {
58
61
  return e === void 0 || Number.isInteger(e) && e >= 0;
59
62
  }
60
- function u(e, t) {
63
+ function d(e, t) {
61
64
  let n = new Set(t);
62
65
  return {
63
66
  version: 1,
64
- root: a(e.root, (e) => o(e, (e) => !n.has(e))),
67
+ root: o(e.root, (e) => s(e, (e) => !n.has(e))),
65
68
  closed: e.closed.filter((e) => !n.has(e))
66
69
  };
67
70
  }
68
- function d(e) {
71
+ function f(e) {
69
72
  let { layout: t, source: n, destination: r, splitWeights: i = [.5, .5] } = e;
70
73
  if (r.region || !i.every((e) => Number.isFinite(e) && e > 0)) return;
71
- let s = h(t, n, r);
72
- if (!s) return;
73
- let { sourceGroup: c, targetGroup: l } = s, u = n[0], d = new Set(n), g = l.panels.find((e) => !d.has(e));
74
- if (!g) return t;
75
- let _ = a(t.root, (e) => o(e, (e) => !d.has(e))), v = {
74
+ let a = g(t, n, r);
75
+ if (!a) return;
76
+ let { sourceGroup: c, targetGroup: l } = a, u = n[0], d = new Set(n), f = l.panels.find((e) => !d.has(e));
77
+ if (!f) return t;
78
+ let _ = o(t.root, (e) => s(e, (e) => !d.has(e))), v = {
76
79
  source: n,
77
80
  destination: r,
78
81
  sourceGroup: c,
@@ -85,12 +88,12 @@ function d(e) {
85
88
  removed: d,
86
89
  splitWeights: i
87
90
  };
88
- return m(t, a(_, (e) => e.panels.includes(g) ? r.position === "tab" ? f(e, v) : p(e, v) : {
91
+ return h(t, o(_, (e) => e.panels.includes(f) ? r.position === "tab" ? p(e, v) : m(e, v) : {
89
92
  ...e,
90
93
  panels: [...e.panels]
91
94
  }));
92
95
  }
93
- function f(e, { source: t, sourceGroup: n, targetGroup: r, moving: i, destination: a, removed: o }) {
96
+ function p(e, { source: t, sourceGroup: n, targetGroup: r, moving: i, destination: a, removed: o }) {
94
97
  let s = Math.min(a.index ?? r.panels.length, r.panels.length), c = s - r.panels.slice(0, s).filter((e) => o.has(e)).length, l = [...e.panels];
95
98
  return l.splice(c, 0, ...t), {
96
99
  type: "group",
@@ -98,16 +101,16 @@ function f(e, { source: t, sourceGroup: n, targetGroup: r, moving: i, destinatio
98
101
  active: n === r ? n.active : i.active
99
102
  };
100
103
  }
101
- function p(e, { moving: t, destination: n, splitWeights: r }) {
104
+ function m(e, { moving: t, destination: n, splitWeights: r }) {
102
105
  let i = n.position === "left" || n.position === "top";
103
106
  return {
104
107
  type: "split",
105
108
  axis: n.position === "left" || n.position === "right" ? "horizontal" : "vertical",
106
- weights: i ? [...r] : [...r].reverse(),
107
- children: i ? [t, e] : [e, t]
109
+ children: i ? [t, e] : [e, t],
110
+ weights: i ? [...r] : [...r].reverse()
108
111
  };
109
112
  }
110
- function m(e, n) {
113
+ function h(e, n) {
111
114
  let i = {
112
115
  version: 1,
113
116
  root: n ? t(n) : null,
@@ -118,61 +121,63 @@ function m(e, n) {
118
121
  };
119
122
  return r(i, a) ? e : i;
120
123
  }
121
- function h(e, t, n) {
124
+ function g(e, t, n) {
122
125
  let r = t[0];
123
126
  if (r === void 0 || new Set(t).size !== t.length) return;
124
- let a = i(e.root, r), o = i(e.root, n.target);
125
- if (a && o && !(n.position !== "tab" && t.includes(n.target)) && c(a, t) && l(n.index)) return {
126
- sourceGroup: a,
127
+ let i = a(e.root, r), o = a(e.root, n.target);
128
+ if (i && o && !(n.position !== "tab" && t.includes(n.target)) && l(i, t) && u(n.index)) return {
129
+ sourceGroup: i,
127
130
  targetGroup: o
128
131
  };
129
132
  }
130
- function g(e, t) {
131
- if (i(e.root, t) && !e.closed.includes(t)) return {
133
+ function _(e, t) {
134
+ if (a(e.root, t) && !e.closed.includes(t)) return {
132
135
  ...e,
133
136
  closed: [...e.closed, t]
134
137
  };
135
138
  }
136
- function _(e, t) {
139
+ function v(e, t) {
137
140
  if (e.closed.includes(t)) return {
138
141
  ...e,
139
142
  closed: e.closed.filter((e) => e !== t)
140
143
  };
141
144
  }
142
- function v(t, n) {
145
+ function y(t, n) {
143
146
  let r = new Set(e(t.root)), i = n.filter((e) => !r.has(e) && (r.add(e), !0));
144
147
  return i.length ? {
145
148
  version: 1,
146
- root: s(t.root, i),
149
+ root: c(t.root, i),
147
150
  closed: [...t.closed]
148
151
  } : t;
149
152
  }
150
- function y(e, t) {
153
+ function b(e, t) {
151
154
  let n = new Set(t.filter((t) => !e.closed.includes(t)));
152
155
  return {
153
156
  version: 1,
154
- root: a(e.root, (e) => o(e, (e) => n.has(e))),
157
+ root: o(e.root, (e) => s(e, (e) => n.has(e))),
155
158
  closed: []
156
159
  };
157
160
  }
158
- function b(e, t) {
159
- if (e.closed.includes(t) || !i(e.root, t)) return;
160
- let n = a(e.root, (e) => e.panels.includes(t) ? {
161
+ function x(e, t) {
162
+ if (e.closed.includes(t)) return;
163
+ let n = a(e.root, t);
164
+ if (!n || n.active === t) return;
165
+ let i = o(e.root, (e) => e.panels.includes(t) ? {
161
166
  ...e,
162
167
  active: t
163
- } : e), o = {
168
+ } : e), s = {
164
169
  ...e,
165
- root: n
170
+ root: i
166
171
  };
167
- return r(o, e) ? void 0 : o;
172
+ return r(s, e) ? void 0 : s;
168
173
  }
169
- function x(e, t) {
170
- let n = t ? i(e.root, t) : void 0;
174
+ function S(e, t) {
175
+ let n = t ? a(e.root, t) : void 0;
171
176
  return n ? {
172
177
  ...e,
173
178
  root: n
174
179
  } : void 0;
175
180
  }
176
- export { g as closePanel, u as createDetachedLayout, i as findGroup, x as getFullscreenWorkspaceLayout, l as isValidInsertionIndex, _ as openPanel, d as placePanels, y as projectLayout, v as reconcilePanels, b as selectPanel };
181
+ export { _ as closePanel, d as createDetachedLayout, a as findGroup, S as getFullscreenWorkspaceLayout, u as isValidInsertionIndex, v as openPanel, f as placePanels, b as projectLayout, y as reconcilePanels, i as sameDestination, x as selectPanel };
177
182
 
178
183
  //# sourceMappingURL=operations.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"operations.utils.js","names":["findGroup","node","id","child","group","mapGroups","mapped","visit","children","weights","weight","index","normalizeOwnedLayout","filterGroup","panels","keep","first","appendPanels","root","active","validSource","source","isValidInsertionIndex","createDetachedLayout","removed","layout","placePanels","input","destination","splitWeights","match","moveSource","target","targetGroup","stripped","context","sourceGroup","placedLayout","joinTargetGroup","splitTargetGroup","originalIndex","moving","before","result","normalizeLayout","normalized","sameSerializedWorkspaceLayout","closePanel","openPanel","panel","reconcilePanels","saved","getPanelIds","added","available","projectLayout","visible","selectPanel","next","getFullscreenWorkspaceLayout","anchor"],"sources":["../../../../src/workspace/utils/model/operations.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, normalizeLayout, normalizeOwnedLayout } from './layout.utils.js';\nimport { sameSerializedWorkspaceLayout } from './value.utils.js';\n\nimport type { WorkspaceGroup, WorkspaceLayout, WorkspaceNode } from './layout.utils.js';\n\nexport interface WorkspaceDestination {\n target: string;\n /** Region path in the visible projection of the current layout. */\n region?: string;\n position: 'tab' | 'left' | 'right' | 'top' | 'bottom';\n index?: number;\n}\n\ninterface TargetGroupContext {\n source: string[];\n destination: WorkspaceDestination;\n sourceGroup: WorkspaceGroup;\n targetGroup: WorkspaceGroup;\n moving: WorkspaceGroup;\n removed: Set<string>;\n splitWeights: [number, number];\n}\n\nexport function findGroup(node: WorkspaceNode | null, id?: string): WorkspaceGroup | undefined {\n if (!node) return undefined;\n if (node.type === 'group') return id === undefined || node.panels.includes(id) ? node : undefined;\n for (const child of node.children) {\n const group = findGroup(child, id);\n if (group) return group;\n }\n return undefined;\n}\n\nfunction mapGroups(\n node: WorkspaceNode | null,\n visit: (group: WorkspaceGroup) => WorkspaceNode | null\n): WorkspaceNode | null {\n if (!node) return null;\n if (node.type === 'group') {\n const mapped = visit(node);\n if (mapped?.type !== 'group' || mapped.panels !== node.panels) return mapped;\n return { ...mapped, panels: [...mapped.panels] };\n }\n const children: WorkspaceNode[] = [];\n const weights: number[] = [];\n node.children.forEach((child, index) => {\n const mapped = mapGroups(child, visit);\n const weight = node.weights[index];\n if (mapped && weight !== undefined) {\n children.push(mapped);\n weights.push(weight);\n }\n });\n if (!children.length) return null;\n if (children.length === 1) return children[0] ?? null;\n return normalizeOwnedLayout({ type: 'split', axis: node.axis, children, weights });\n}\n\nfunction filterGroup(group: WorkspaceGroup, keep: (id: string) => boolean): WorkspaceGroup | null {\n const panels = group.panels.filter(keep);\n const first = panels[0];\n if (first === undefined) return null;\n return { type: 'group', panels, active: panels.includes(group.active) ? group.active : first };\n}\n\nfunction appendPanels(root: WorkspaceNode | null, panels: string[], active?: string): WorkspaceNode | null {\n if (!panels.length) return root;\n const first = findGroup(root);\n return first\n ? mapGroups(root, group => ({\n ...group,\n panels: group === first ? [...group.panels, ...panels] : [...group.panels],\n active: group === first ? (active ?? group.active) : group.active\n }))\n : { type: 'group', panels: [...panels], active: active ?? panels[0] ?? '' };\n}\n\nfunction validSource(group: WorkspaceGroup, source: string[]): boolean {\n return (\n source.length === 1 ||\n (source.length === group.panels.length && source.every((id, index) => group.panels[index] === id))\n );\n}\n\nexport function isValidInsertionIndex(index: number | undefined): boolean {\n return index === undefined || (Number.isInteger(index) && index >= 0);\n}\n\n/** Removes carried panels from the arrangement and closed list without changing the saved layout. */\nexport function createDetachedLayout(layout: WorkspaceLayout, source: string[]): WorkspaceLayout {\n const removed = new Set(source);\n return {\n version: 1,\n root: mapGroups(layout.root, group => filterGroup(group, id => !removed.has(id))),\n closed: layout.closed.filter(id => !removed.has(id))\n };\n}\n\nexport function placePanels(input: {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n splitWeights?: [number, number];\n}): WorkspaceLayout | undefined {\n const { layout, source, destination, splitWeights = [0.5, 0.5] } = input;\n if (destination.region) return undefined;\n if (!splitWeights.every(weight => Number.isFinite(weight) && weight > 0)) return undefined;\n const match = moveSource(layout, source, destination);\n if (!match) return undefined;\n const { sourceGroup, targetGroup } = match;\n const first = source[0]!;\n const removed = new Set(source);\n const target = targetGroup.panels.find(id => !removed.has(id));\n if (!target) return layout;\n const stripped = mapGroups(layout.root, group => filterGroup(group, id => !removed.has(id)));\n const moving: WorkspaceGroup = {\n type: 'group',\n panels: [...source],\n active: source.includes(sourceGroup.active) ? sourceGroup.active : first\n };\n const context: TargetGroupContext = { source, destination, sourceGroup, targetGroup, moving, removed, splitWeights };\n const root = mapGroups(stripped, group => {\n if (!group.panels.includes(target)) return { ...group, panels: [...group.panels] };\n return destination.position === 'tab' ? joinTargetGroup(group, context) : splitTargetGroup(group, context);\n });\n return placedLayout(layout, root);\n}\n\nfunction joinTargetGroup(\n group: WorkspaceGroup,\n { source, sourceGroup, targetGroup, moving, destination, removed }: TargetGroupContext\n): WorkspaceGroup {\n const originalIndex = Math.min(destination.index ?? targetGroup.panels.length, targetGroup.panels.length);\n const index = originalIndex - targetGroup.panels.slice(0, originalIndex).filter(id => removed.has(id)).length;\n const panels = [...group.panels];\n panels.splice(index, 0, ...source);\n return { type: 'group', panels, active: sourceGroup === targetGroup ? sourceGroup.active : moving.active };\n}\n\nfunction splitTargetGroup(\n group: WorkspaceGroup,\n { moving, destination, splitWeights }: TargetGroupContext\n): WorkspaceNode {\n const before = destination.position === 'left' || destination.position === 'top';\n return {\n type: 'split',\n axis: destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical',\n weights: before ? [...splitWeights] : [...splitWeights].reverse(),\n children: before ? [moving, group] : [group, moving]\n };\n}\n\nfunction placedLayout(layout: WorkspaceLayout, root: WorkspaceNode | null): WorkspaceLayout {\n const result: WorkspaceLayout = { version: 1, root: root ? normalizeLayout(root) : null, closed: [...layout.closed] };\n const normalized = { ...layout, root: layout.root ? normalizeLayout(layout.root) : null };\n return sameSerializedWorkspaceLayout(result, normalized) ? layout : result;\n}\n\nfunction moveSource(layout: WorkspaceLayout, source: string[], destination: WorkspaceDestination) {\n const first = source[0];\n if (first === undefined || new Set(source).size !== source.length) return undefined;\n const sourceGroup = findGroup(layout.root, first);\n const targetGroup = findGroup(layout.root, destination.target);\n if (!sourceGroup || !targetGroup) return undefined;\n if (destination.position !== 'tab' && source.includes(destination.target)) return undefined;\n if (!validSource(sourceGroup, source) || !isValidInsertionIndex(destination.index)) return undefined;\n return { sourceGroup, targetGroup };\n}\n\n/** Retains panel placement and active preference when closing. */\nexport function closePanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (!findGroup(layout.root, id) || layout.closed.includes(id)) return undefined;\n return { ...layout, closed: [...layout.closed, id] };\n}\n\nexport function openPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (!layout.closed.includes(id)) return undefined;\n return { ...layout, closed: layout.closed.filter(panel => panel !== id) };\n}\n\n/** Retains saved panel positions when supplied panels change. */\nexport function reconcilePanels(layout: WorkspaceLayout, available: string[]): WorkspaceLayout {\n const saved = new Set(getPanelIds(layout.root));\n const added = available.filter(id => {\n if (saved.has(id)) return false;\n saved.add(id);\n return true;\n });\n return added.length ? { version: 1, root: appendPanels(layout.root, added), closed: [...layout.closed] } : layout;\n}\n\n/** Creates the visible arrangement while retaining the saved snapshot. */\nexport function projectLayout(layout: WorkspaceLayout, available: string[]): WorkspaceLayout {\n const visible = new Set(available.filter(id => !layout.closed.includes(id)));\n return {\n version: 1,\n root: mapGroups(layout.root, group => filterGroup(group, id => visible.has(id))),\n closed: []\n };\n}\n\nexport function selectPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (layout.closed.includes(id) || !findGroup(layout.root, id)) return undefined;\n const root = mapGroups(layout.root, group => (group.panels.includes(id) ? { ...group, active: id } : group));\n const next = { ...layout, root };\n return sameSerializedWorkspaceLayout(next, layout) ? undefined : next;\n}\n\nexport function getFullscreenWorkspaceLayout(layout: WorkspaceLayout, anchor: string | undefined) {\n const group = anchor ? findGroup(layout.root, anchor) : undefined;\n return group ? { ...layout, root: group } : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"operations.utils.js","names":["sameDestination","left","right","findGroup","node","id","child","group","mapGroups","mapped","visit","children","weights","weight","index","normalizeLayoutWithSharing","filterGroup","panels","keep","first","appendPanels","root","active","validSource","source","isValidInsertionIndex","createDetachedLayout","removed","layout","placePanels","input","destination","splitWeights","match","moveSource","target","targetGroup","stripped","context","sourceGroup","placedLayout","joinTargetGroup","splitTargetGroup","originalIndex","moving","before","result","normalizeLayout","normalized","sameWorkspaceLayout","closePanel","openPanel","panel","reconcilePanels","saved","getPanelIds","added","available","projectLayout","visible","selectPanel","selected","next","getFullscreenWorkspaceLayout","anchor"],"sources":["../../../../src/workspace/utils/model/operations.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds, normalizeLayout, normalizeLayoutWithSharing } from './layout.utils.js';\nimport { sameWorkspaceLayout } from './value.utils.js';\n\nimport type { WorkspaceGroup, WorkspaceLayout, WorkspaceNode } from './layout.utils.js';\n\nexport interface WorkspaceDestination {\n target: string;\n /** Region path in the visible projection of the current layout. */\n region?: string;\n position: 'tab' | 'left' | 'right' | 'top' | 'bottom';\n index?: number;\n}\n\nexport function sameDestination(left: WorkspaceDestination, right: WorkspaceDestination) {\n return (\n left.target === right.target &&\n left.position === right.position &&\n left.region === right.region &&\n left.index === right.index\n );\n}\n\ninterface TargetGroupContext {\n source: string[];\n destination: WorkspaceDestination;\n sourceGroup: WorkspaceGroup;\n targetGroup: WorkspaceGroup;\n moving: WorkspaceGroup;\n removed: Set<string>;\n splitWeights: [number, number];\n}\n\nexport function findGroup(node: WorkspaceNode | null, id?: string): WorkspaceGroup | undefined {\n if (!node) return undefined;\n if (node.type === 'group') return id === undefined || node.panels.includes(id) ? node : undefined;\n for (const child of node.children) {\n const group = findGroup(child, id);\n if (group) return group;\n }\n return undefined;\n}\n\nfunction mapGroups(\n node: WorkspaceNode | null,\n visit: (group: WorkspaceGroup) => WorkspaceNode | null\n): WorkspaceNode | null {\n if (!node) return null;\n if (node.type === 'group') {\n const mapped = visit(node);\n if (mapped?.type !== 'group' || mapped.panels !== node.panels) return mapped;\n return { ...mapped, panels: [...mapped.panels] };\n }\n const children: WorkspaceNode[] = [];\n const weights: number[] = [];\n node.children.forEach((child, index) => {\n const mapped = mapGroups(child, visit);\n const weight = node.weights[index];\n if (mapped && weight !== undefined) {\n children.push(mapped);\n weights.push(weight);\n }\n });\n if (!children.length) return null;\n if (children.length === 1) return children[0] ?? null;\n return normalizeLayoutWithSharing({ type: 'split', axis: node.axis, children, weights });\n}\n\nfunction filterGroup(group: WorkspaceGroup, keep: (id: string) => boolean): WorkspaceGroup | null {\n const panels = group.panels.filter(keep);\n const first = panels[0];\n if (first === undefined) return null;\n return { type: 'group', panels, active: panels.includes(group.active) ? group.active : first };\n}\n\nfunction appendPanels(root: WorkspaceNode | null, panels: string[], active?: string): WorkspaceNode | null {\n if (!panels.length) return root;\n const first = findGroup(root);\n return first\n ? mapGroups(root, group => ({\n ...group,\n panels: group === first ? [...group.panels, ...panels] : [...group.panels],\n active: group === first ? (active ?? group.active) : group.active\n }))\n : { type: 'group', panels: [...panels], active: active ?? panels[0] ?? '' };\n}\n\nfunction validSource(group: WorkspaceGroup, source: string[]): boolean {\n return (\n source.length === 1 ||\n (source.length === group.panels.length && source.every((id, index) => group.panels[index] === id))\n );\n}\n\nexport function isValidInsertionIndex(index: number | undefined): boolean {\n return index === undefined || (Number.isInteger(index) && index >= 0);\n}\n\n/** Removes carried panels from the arrangement and closed list without changing the saved layout. */\nexport function createDetachedLayout(layout: WorkspaceLayout, source: string[]): WorkspaceLayout {\n const removed = new Set(source);\n return {\n version: 1,\n root: mapGroups(layout.root, group => filterGroup(group, id => !removed.has(id))),\n closed: layout.closed.filter(id => !removed.has(id))\n };\n}\n\nexport function placePanels(input: {\n layout: WorkspaceLayout;\n source: string[];\n destination: WorkspaceDestination;\n splitWeights?: [number, number];\n}): WorkspaceLayout | undefined {\n const { layout, source, destination, splitWeights = [0.5, 0.5] } = input;\n if (destination.region) return undefined;\n if (!splitWeights.every(weight => Number.isFinite(weight) && weight > 0)) return undefined;\n const match = moveSource(layout, source, destination);\n if (!match) return undefined;\n const { sourceGroup, targetGroup } = match;\n const first = source[0]!;\n const removed = new Set(source);\n const target = targetGroup.panels.find(id => !removed.has(id));\n if (!target) return layout;\n const stripped = mapGroups(layout.root, group => filterGroup(group, id => !removed.has(id)));\n const moving: WorkspaceGroup = {\n type: 'group',\n panels: [...source],\n active: source.includes(sourceGroup.active) ? sourceGroup.active : first\n };\n const context: TargetGroupContext = { source, destination, sourceGroup, targetGroup, moving, removed, splitWeights };\n const root = mapGroups(stripped, group => {\n if (!group.panels.includes(target)) return { ...group, panels: [...group.panels] };\n return destination.position === 'tab' ? joinTargetGroup(group, context) : splitTargetGroup(group, context);\n });\n return placedLayout(layout, root);\n}\n\nfunction joinTargetGroup(\n group: WorkspaceGroup,\n { source, sourceGroup, targetGroup, moving, destination, removed }: TargetGroupContext\n): WorkspaceGroup {\n const originalIndex = Math.min(destination.index ?? targetGroup.panels.length, targetGroup.panels.length);\n const index = originalIndex - targetGroup.panels.slice(0, originalIndex).filter(id => removed.has(id)).length;\n const panels = [...group.panels];\n panels.splice(index, 0, ...source);\n return { type: 'group', panels, active: sourceGroup === targetGroup ? sourceGroup.active : moving.active };\n}\n\nfunction splitTargetGroup(\n group: WorkspaceGroup,\n { moving, destination, splitWeights }: TargetGroupContext\n): WorkspaceNode {\n const before = destination.position === 'left' || destination.position === 'top';\n // Preserve serialized field order when normalization retains this split wrapper.\n return {\n type: 'split',\n axis: destination.position === 'left' || destination.position === 'right' ? 'horizontal' : 'vertical',\n children: before ? [moving, group] : [group, moving],\n weights: before ? [...splitWeights] : [...splitWeights].reverse()\n };\n}\n\nfunction placedLayout(layout: WorkspaceLayout, root: WorkspaceNode | null): WorkspaceLayout {\n const result: WorkspaceLayout = { version: 1, root: root ? normalizeLayout(root) : null, closed: [...layout.closed] };\n const normalized = { ...layout, root: layout.root ? normalizeLayout(layout.root) : null };\n return sameWorkspaceLayout(result, normalized) ? layout : result;\n}\n\nfunction moveSource(layout: WorkspaceLayout, source: string[], destination: WorkspaceDestination) {\n const first = source[0];\n if (first === undefined || new Set(source).size !== source.length) return undefined;\n const sourceGroup = findGroup(layout.root, first);\n const targetGroup = findGroup(layout.root, destination.target);\n if (!sourceGroup || !targetGroup) return undefined;\n if (destination.position !== 'tab' && source.includes(destination.target)) return undefined;\n if (!validSource(sourceGroup, source) || !isValidInsertionIndex(destination.index)) return undefined;\n return { sourceGroup, targetGroup };\n}\n\n/** Retains panel placement and active preference when closing. */\nexport function closePanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (!findGroup(layout.root, id) || layout.closed.includes(id)) return undefined;\n return { ...layout, closed: [...layout.closed, id] };\n}\n\nexport function openPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (!layout.closed.includes(id)) return undefined;\n return { ...layout, closed: layout.closed.filter(panel => panel !== id) };\n}\n\n/** Retains saved panel positions when supplied panels change. */\nexport function reconcilePanels(layout: WorkspaceLayout, available: string[]): WorkspaceLayout {\n const saved = new Set(getPanelIds(layout.root));\n const added = available.filter(id => {\n if (saved.has(id)) return false;\n saved.add(id);\n return true;\n });\n return added.length ? { version: 1, root: appendPanels(layout.root, added), closed: [...layout.closed] } : layout;\n}\n\n/** Creates the visible arrangement while retaining the saved snapshot. */\nexport function projectLayout(layout: WorkspaceLayout, available: string[]): WorkspaceLayout {\n const visible = new Set(available.filter(id => !layout.closed.includes(id)));\n return {\n version: 1,\n root: mapGroups(layout.root, group => filterGroup(group, id => visible.has(id))),\n closed: []\n };\n}\n\nexport function selectPanel(layout: WorkspaceLayout, id: string): WorkspaceLayout | undefined {\n if (layout.closed.includes(id)) return undefined;\n const selected = findGroup(layout.root, id);\n if (!selected || selected.active === id) return undefined;\n const root = mapGroups(layout.root, group => (group.panels.includes(id) ? { ...group, active: id } : group));\n const next = { ...layout, root };\n return sameWorkspaceLayout(next, layout) ? undefined : next;\n}\n\nexport function getFullscreenWorkspaceLayout(layout: WorkspaceLayout, anchor: string | undefined) {\n const group = anchor ? findGroup(layout.root, anchor) : undefined;\n return group ? { ...layout, root: group } : undefined;\n}\n"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';
2
2
  export type WorkspaceLayoutProjector = (layout: WorkspaceLayout, available: string[]) => WorkspaceLayout;
3
3
  export declare function createWorkspaceLayoutProjector(): WorkspaceLayoutProjector;
4
- export declare function getProjectionSignature(node: WorkspaceNode | null): string;
5
- export declare function findDeepestProjectionCarrier(node: WorkspaceNode | null, expected: string, project: (node: WorkspaceNode) => WorkspaceNode | null): WorkspaceNode | undefined;
4
+ export declare function canReuseLayoutProjection(projector: WorkspaceLayoutProjector | undefined): boolean;
5
+ /** Compares visible topology and panel order, independently of weights and active selection. */
6
+ export declare function sameProjectionShape(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean;
7
+ export declare function findDeepestProjectionCarrier(node: WorkspaceNode | null, expected: WorkspaceNode | null, project: (node: WorkspaceNode) => WorkspaceNode | null): WorkspaceNode | undefined;
6
8
  /** Saves visible split proportions while preserving the shares of missing panels. */
7
9
  export declare function rebaseProjectedSplit(layout: WorkspaceLayout, renderedBranch: WorkspaceSplit, sizes: number[], available: string[], projectLayoutForCandidate?: WorkspaceLayoutProjector): WorkspaceLayout | undefined;
@@ -1,75 +1,84 @@
1
1
  import { getPanelIds as e } from "./layout.utils.js";
2
- import { projectLayout as t } from "./operations.utils.js";
2
+ import { sameArrayItems as t } from "../comparison.utils.js";
3
+ import { findGroup as n, projectLayout as r } from "./operations.utils.js";
3
4
  // src/workspace/utils/model/projection.utils.ts
4
- function n() {
5
- let e = [];
6
- return (n, r) => {
7
- let i = e.find((e) => o(e.available, r) && o(e.closed, n.closed));
8
- i || (i = {
9
- available: r,
5
+ var i = /* @__PURE__ */ new WeakSet();
6
+ function a() {
7
+ let e = [], n = (n, i) => {
8
+ let a = e.find((e) => t(e.available, i) && t(e.closed, n.closed));
9
+ a || (a = {
10
+ available: i,
10
11
  closed: n.closed,
11
12
  roots: /* @__PURE__ */ new Map()
12
- }, e.push(i));
13
- let a = i.roots.get(n.root);
14
- return a || (a = t(n, r), i.roots.set(n.root, a)), a;
13
+ }, e.push(a));
14
+ let o = a.roots.get(n.root);
15
+ return o || (o = r(n, i), a.roots.set(n.root, o)), o;
15
16
  };
17
+ return i.add(n), n;
16
18
  }
17
- function r(e) {
18
- return e ? e.type === "group" ? JSON.stringify(e.panels) : JSON.stringify([e.axis, e.children.map(r)]) : "null";
19
+ function o(e) {
20
+ return e === void 0 || i.has(e);
19
21
  }
20
- function i(e, t, n) {
22
+ function s(e, n) {
23
+ if (e === n) return !0;
24
+ if (!e || !n) return !1;
25
+ if (e.type === "group") return n.type === "group" && t(e.panels, n.panels);
26
+ if (n.type !== "split" || e.axis !== n.axis || e.children.length !== n.children.length) return !1;
27
+ for (let t = 0; t < e.children.length; t++) if (!s(e.children[t], n.children[t])) return !1;
28
+ return !0;
29
+ }
30
+ function c(e, t, n) {
21
31
  if (e) {
22
32
  if (e.type === "split") for (let r of e.children) {
23
- let e = i(r, t, n);
33
+ let e = c(r, t, n);
24
34
  if (e) return e;
25
35
  }
26
- return r(n(e)) === t ? e : void 0;
36
+ return s(n(e), t) ? e : void 0;
27
37
  }
28
38
  }
29
- function a(n, i, a, o, u) {
30
- if (!n.root || !c(i, a)) return;
31
- let d = o.filter((e) => !n.closed.includes(e)), f = /* @__PURE__ */ new Map(), p = (e) => (f.has(e) || f.set(e, (u ?? t)({
39
+ function l(t, i, a, o, c) {
40
+ if (!t.root || !d(i, a)) return;
41
+ let l = o.filter((e) => !t.closed.includes(e)), p = /* @__PURE__ */ new Map(), m = (e) => (p.has(e) || p.set(e, (c ?? r)({
32
42
  version: 1,
33
43
  root: e,
34
44
  closed: []
35
- }, d).root), f.get(e) ?? null), m = r(i), h = new Set(i.children.map(r)), g = /* @__PURE__ */ new Map();
45
+ }, l).root), p.get(e) ?? null), h = /* @__PURE__ */ new Map();
36
46
  i.children.forEach((t, n) => {
37
- e(t).forEach((e) => g.set(e, n));
47
+ e(t).forEach((e) => h.set(e, n));
38
48
  });
39
- let _ = (t) => [...new Set(e(p(t)).flatMap((e) => {
40
- let t = g.get(e);
49
+ let g = (t) => [...new Set(e(m(t)).flatMap((e) => {
50
+ let t = h.get(e);
41
51
  return t === void 0 ? [] : [t];
42
- }))].reduce((e, t) => e + (a[t] ?? 0), 0), v = (e) => {
43
- if (e.type === "group" || h.has(r(p(e)))) return e;
44
- let t = e.children.map((e) => v(e)), n = l(e, _, i.axis);
45
- return n === e.weights && t.every((t, n) => t === e.children[n]) ? e : {
52
+ }))].reduce((e, t) => e + (a[t] ?? 0), 0), _ = (e) => {
53
+ if (e.type === "group") return e;
54
+ let t = m(e), r = n(t)?.panels[0], a = r === void 0 ? void 0 : h.get(r), o = a === void 0 ? void 0 : i.children[a];
55
+ if (o && s(t, o)) return e;
56
+ let c = e.children.map((e) => _(e)), l = f(e, g, i.axis);
57
+ return l === e.weights && c.every((t, n) => t === e.children[n]) ? e : {
46
58
  ...e,
47
- weights: n,
48
- children: t
59
+ weights: l,
60
+ children: c
49
61
  };
50
- }, y = s(n.root, (e) => r(p(e)) === m, v);
51
- return y === n.root ? void 0 : {
62
+ }, v = u(t.root, (e) => s(m(e), i), _);
63
+ return v === t.root ? void 0 : {
52
64
  version: 1,
53
- root: y,
54
- closed: [...n.closed]
65
+ root: v,
66
+ closed: [...t.closed]
55
67
  };
56
68
  }
57
- function o(e, t) {
58
- return e === t || e.length === t.length && e.every((e, n) => e === t[n]);
59
- }
60
- function s(e, t, n) {
69
+ function u(e, t, n) {
61
70
  if (t(e)) return n(e);
62
71
  if (e.type === "group") return e;
63
- let r = e.children.map((e) => s(e, t, n));
72
+ let r = e.children.map((e) => u(e, t, n));
64
73
  return r.some((t, n) => t !== e.children[n]) ? {
65
74
  ...e,
66
75
  children: r
67
76
  } : e;
68
77
  }
69
- function c(e, t) {
78
+ function d(e, t) {
70
79
  return t.length === e.children.length && t.every((e) => Number.isFinite(e) && e > 0) && Number.isFinite(t.reduce((e, t) => e + t, 0));
71
80
  }
72
- function l(e, t, n) {
81
+ function f(e, t, n) {
73
82
  if (e.axis !== n) return e.weights;
74
83
  let r = e.children.map(t), i = r.reduce((e, t) => e + t, 0);
75
84
  if (!i) return e.weights;
@@ -82,6 +91,6 @@ function l(e, t, n) {
82
91
  return Math.abs(t - r) <= 1e-12 * Math.max(t, r);
83
92
  }) ? e.weights : o;
84
93
  }
85
- export { n as createWorkspaceLayoutProjector, i as findDeepestProjectionCarrier, r as getProjectionSignature, a as rebaseProjectedSplit };
94
+ export { o as canReuseLayoutProjection, a as createWorkspaceLayoutProjector, c as findDeepestProjectionCarrier, l as rebaseProjectedSplit, s as sameProjectionShape };
86
95
 
87
96
  //# sourceMappingURL=projection.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projection.utils.js","names":["createWorkspaceLayoutProjector","domains","domain","sameIds","entry","available","layout","projectedLayout","projectLayout","getProjectionSignature","node","findDeepestProjectionCarrier","child","found","expected","project","rebaseProjectedSplit","validSplitSizes","renderedBranch","sizes","visible","id","projections","projectLayoutForCandidate","renderedSignature","childSignatures","allocations","index","mass","getPanelIds","group","sum","rebase","children","weights","rebaseWeights","root","replaceBranch","left","right","matches","branch","size","axis","masses","totalMass","value","visibleShare","weight","childMass","previous"],"sources":["../../../../src/workspace/utils/model/projection.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds } from './layout.utils.js';\nimport { projectLayout } from './operations.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';\nexport type WorkspaceLayoutProjector = (layout: WorkspaceLayout, available: string[]) => WorkspaceLayout;\n\nexport function createWorkspaceLayoutProjector(): WorkspaceLayoutProjector {\n const domains: {\n available: string[];\n closed: string[];\n roots: Map<WorkspaceNode | null, WorkspaceLayout>;\n }[] = [];\n return (layout, available) => {\n let domain = domains.find(entry => sameIds(entry.available, available) && sameIds(entry.closed, layout.closed));\n if (!domain) {\n domain = { available, closed: layout.closed, roots: new Map() };\n domains.push(domain);\n }\n let projectedLayout = domain.roots.get(layout.root);\n if (!projectedLayout) {\n projectedLayout = projectLayout(layout, available);\n domain.roots.set(layout.root, projectedLayout);\n }\n return projectedLayout;\n };\n}\n\nexport function getProjectionSignature(node: WorkspaceNode | null): string {\n if (!node) return 'null';\n return node.type === 'group'\n ? JSON.stringify(node.panels)\n : JSON.stringify([node.axis, node.children.map(getProjectionSignature)]);\n}\n\nexport function findDeepestProjectionCarrier(\n node: WorkspaceNode | null,\n expected: string,\n project: (node: WorkspaceNode) => WorkspaceNode | null\n): WorkspaceNode | undefined {\n if (!node) return undefined;\n if (node.type === 'split') {\n for (const child of node.children) {\n const found = findDeepestProjectionCarrier(child, expected, project);\n if (found) return found;\n }\n }\n return getProjectionSignature(project(node)) === expected ? node : undefined;\n}\n\n/** Saves visible split proportions while preserving the shares of missing panels. */\n// eslint-disable-next-line max-params -- The operation accepts saved and rendered arrangements with scoped projection.\nexport function rebaseProjectedSplit(\n layout: WorkspaceLayout,\n renderedBranch: WorkspaceSplit,\n sizes: number[],\n available: string[],\n projectLayoutForCandidate?: WorkspaceLayoutProjector\n): WorkspaceLayout | undefined {\n if (!layout.root || !validSplitSizes(renderedBranch, sizes)) return undefined;\n\n const visible = available.filter(id => !layout.closed.includes(id));\n const projections = new Map<WorkspaceNode, WorkspaceNode | null>();\n const project = (node: WorkspaceNode): WorkspaceNode | null => {\n if (!projections.has(node)) {\n projections.set(\n node,\n (projectLayoutForCandidate ?? projectLayout)({ version: 1, root: node, closed: [] }, visible).root\n );\n }\n return projections.get(node) ?? null;\n };\n const renderedSignature = getProjectionSignature(renderedBranch);\n const childSignatures = new Set(renderedBranch.children.map(getProjectionSignature));\n const allocations = new Map<string, number>();\n renderedBranch.children.forEach((child, index) => {\n getPanelIds(child).forEach(id => allocations.set(id, index));\n });\n const mass = (node: WorkspaceNode): number => {\n const groups = new Set(\n getPanelIds(project(node)).flatMap(id => {\n const group = allocations.get(id);\n return group === undefined ? [] : [group];\n })\n );\n return [...groups].reduce((sum, group) => sum + (sizes[group] ?? 0), 0);\n };\n const rebase = (node: WorkspaceNode): WorkspaceNode => {\n if (node.type === 'group' || childSignatures.has(getProjectionSignature(project(node)))) return node;\n const children = node.children.map(child => rebase(child));\n const weights = rebaseWeights(node, mass, renderedBranch.axis);\n if (weights === node.weights && children.every((child, index) => child === node.children[index])) return node;\n return { ...node, weights, children };\n };\n const root = replaceBranch(layout.root, node => getProjectionSignature(project(node)) === renderedSignature, rebase);\n return root === layout.root ? undefined : { version: 1, root, closed: [...layout.closed] };\n}\n\nfunction sameIds(left: string[], right: string[]) {\n return left === right || (left.length === right.length && left.every((id, index) => id === right[index]));\n}\n\nfunction replaceBranch(\n node: WorkspaceNode,\n matches: (node: WorkspaceNode) => boolean,\n rebase: (node: WorkspaceNode) => WorkspaceNode\n): WorkspaceNode {\n if (matches(node)) return rebase(node);\n if (node.type === 'group') return node;\n const children = node.children.map(child => replaceBranch(child, matches, rebase));\n return children.some((child, index) => child !== node.children[index]) ? { ...node, children } : node;\n}\n\nfunction validSplitSizes(branch: WorkspaceSplit, sizes: number[]) {\n return (\n sizes.length === branch.children.length &&\n sizes.every(size => Number.isFinite(size) && size > 0) &&\n Number.isFinite(sizes.reduce((sum, size) => sum + size, 0))\n );\n}\n\nfunction rebaseWeights(\n node: WorkspaceSplit,\n mass: (node: WorkspaceNode) => number,\n axis: WorkspaceSplit['axis']\n): number[] {\n if (node.axis !== axis) return node.weights;\n const masses = node.children.map(mass);\n const totalMass = masses.reduce((sum, value) => sum + value, 0);\n if (!totalMass) return node.weights;\n const visibleShare = node.weights.reduce((sum, weight, index) => sum + ((masses[index] ?? 0) > 0 ? weight : 0), 0);\n const weights = node.weights.map((weight, index) => {\n const childMass = masses[index] ?? 0;\n return childMass > 0 ? visibleShare * (childMass / totalMass) : weight;\n });\n return weights.every((weight, index) => {\n const previous = node.weights[index] ?? 0;\n return Math.abs(weight - previous) <= 1e-12 * Math.max(weight, previous);\n })\n ? node.weights\n : weights;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"projection.utils.js","names":["reusableLayoutProjectors","createWorkspaceLayoutProjector","domains","projector","domain","sameArrayItems","entry","available","layout","projectedLayout","projectLayout","canReuseLayoutProjection","sameProjectionShape","left","right","index","findDeepestProjectionCarrier","node","child","found","expected","project","rebaseProjectedSplit","validSplitSizes","renderedBranch","sizes","visible","id","projections","projectLayoutForCandidate","childIndexByPanel","mass","getPanelIds","childIndex","sum","rebase","projected","anchor","findGroup","renderedChild","children","weights","rebaseWeights","root","replaceBranch","matches","branch","size","axis","masses","totalMass","value","visibleShare","weight","childMass","previous"],"sources":["../../../../src/workspace/utils/model/projection.utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { getPanelIds } from './layout.utils.js';\nimport { findGroup, projectLayout } from './operations.utils.js';\nimport { sameArrayItems } from '../comparison.utils.js';\n\nimport type { WorkspaceLayout, WorkspaceNode, WorkspaceSplit } from './layout.utils.js';\nexport type WorkspaceLayoutProjector = (layout: WorkspaceLayout, available: string[]) => WorkspaceLayout;\n\nconst reusableLayoutProjectors = new WeakSet<WorkspaceLayoutProjector>();\n\nexport function createWorkspaceLayoutProjector(): WorkspaceLayoutProjector {\n const domains: {\n available: string[];\n closed: string[];\n roots: Map<WorkspaceNode | null, WorkspaceLayout>;\n }[] = [];\n const projector: WorkspaceLayoutProjector = (layout, available) => {\n let domain = domains.find(\n entry => sameArrayItems(entry.available, available) && sameArrayItems(entry.closed, layout.closed)\n );\n if (!domain) {\n domain = { available, closed: layout.closed, roots: new Map() };\n domains.push(domain);\n }\n let projectedLayout = domain.roots.get(layout.root);\n if (!projectedLayout) {\n projectedLayout = projectLayout(layout, available);\n domain.roots.set(layout.root, projectedLayout);\n }\n return projectedLayout;\n };\n reusableLayoutProjectors.add(projector);\n return projector;\n}\n\nexport function canReuseLayoutProjection(projector: WorkspaceLayoutProjector | undefined) {\n return projector === undefined || reusableLayoutProjectors.has(projector);\n}\n\n/** Compares visible topology and panel order, independently of weights and active selection. */\n// eslint-disable-next-line complexity -- Compare node fields directly without allocating comparison callbacks.\nexport function sameProjectionShape(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n if (left.type === 'group') return right.type === 'group' && sameArrayItems(left.panels, right.panels);\n if (right.type !== 'split' || left.axis !== right.axis || left.children.length !== right.children.length)\n return false;\n for (let index = 0; index < left.children.length; index++) {\n if (!sameProjectionShape(left.children[index]!, right.children[index]!)) return false;\n }\n return true;\n}\n\nexport function findDeepestProjectionCarrier(\n node: WorkspaceNode | null,\n expected: WorkspaceNode | null,\n project: (node: WorkspaceNode) => WorkspaceNode | null\n): WorkspaceNode | undefined {\n if (!node) return undefined;\n if (node.type === 'split') {\n for (const child of node.children) {\n const found = findDeepestProjectionCarrier(child, expected, project);\n if (found) return found;\n }\n }\n return sameProjectionShape(project(node), expected) ? node : undefined;\n}\n\n/** Saves visible split proportions while preserving the shares of missing panels. */\n// eslint-disable-next-line max-params -- The operation accepts saved and rendered arrangements with scoped projection.\nexport function rebaseProjectedSplit(\n layout: WorkspaceLayout,\n renderedBranch: WorkspaceSplit,\n sizes: number[],\n available: string[],\n projectLayoutForCandidate?: WorkspaceLayoutProjector\n): WorkspaceLayout | undefined {\n if (!layout.root || !validSplitSizes(renderedBranch, sizes)) return undefined;\n\n const visible = available.filter(id => !layout.closed.includes(id));\n const projections = new Map<WorkspaceNode, WorkspaceNode | null>();\n const project = (node: WorkspaceNode): WorkspaceNode | null => {\n if (!projections.has(node)) {\n projections.set(\n node,\n (projectLayoutForCandidate ?? projectLayout)({ version: 1, root: node, closed: [] }, visible).root\n );\n }\n return projections.get(node) ?? null;\n };\n const childIndexByPanel = new Map<string, number>();\n renderedBranch.children.forEach((child, index) => {\n getPanelIds(child).forEach(id => childIndexByPanel.set(id, index));\n });\n const mass = (node: WorkspaceNode): number => {\n const childIndices = new Set(\n getPanelIds(project(node)).flatMap(id => {\n const childIndex = childIndexByPanel.get(id);\n return childIndex === undefined ? [] : [childIndex];\n })\n );\n return [...childIndices].reduce((sum, childIndex) => sum + (sizes[childIndex] ?? 0), 0);\n };\n const rebase = (node: WorkspaceNode): WorkspaceNode => {\n if (node.type === 'group') return node;\n const projected = project(node);\n const anchor = findGroup(projected)?.panels[0];\n const childIndex = anchor === undefined ? undefined : childIndexByPanel.get(anchor);\n const renderedChild = childIndex === undefined ? undefined : renderedBranch.children[childIndex];\n if (renderedChild && sameProjectionShape(projected, renderedChild)) return node;\n const children = node.children.map(child => rebase(child));\n const weights = rebaseWeights(node, mass, renderedBranch.axis);\n if (weights === node.weights && children.every((child, index) => child === node.children[index])) return node;\n return { ...node, weights, children };\n };\n const root = replaceBranch(layout.root, node => sameProjectionShape(project(node), renderedBranch), rebase);\n return root === layout.root ? undefined : { version: 1, root, closed: [...layout.closed] };\n}\n\nfunction replaceBranch(\n node: WorkspaceNode,\n matches: (node: WorkspaceNode) => boolean,\n rebase: (node: WorkspaceNode) => WorkspaceNode\n): WorkspaceNode {\n if (matches(node)) return rebase(node);\n if (node.type === 'group') return node;\n const children = node.children.map(child => replaceBranch(child, matches, rebase));\n return children.some((child, index) => child !== node.children[index]) ? { ...node, children } : node;\n}\n\nfunction validSplitSizes(branch: WorkspaceSplit, sizes: number[]) {\n return (\n sizes.length === branch.children.length &&\n sizes.every(size => Number.isFinite(size) && size > 0) &&\n Number.isFinite(sizes.reduce((sum, size) => sum + size, 0))\n );\n}\n\nfunction rebaseWeights(\n node: WorkspaceSplit,\n mass: (node: WorkspaceNode) => number,\n axis: WorkspaceSplit['axis']\n): number[] {\n if (node.axis !== axis) return node.weights;\n const masses = node.children.map(mass);\n const totalMass = masses.reduce((sum, value) => sum + value, 0);\n if (!totalMass) return node.weights;\n const visibleShare = node.weights.reduce((sum, weight, index) => sum + ((masses[index] ?? 0) > 0 ? weight : 0), 0);\n const weights = node.weights.map((weight, index) => {\n const childMass = masses[index] ?? 0;\n return childMass > 0 ? visibleShare * (childMass / totalMass) : weight;\n });\n return weights.every((weight, index) => {\n const previous = node.weights[index] ?? 0;\n return Math.abs(weight - previous) <= 1e-12 * Math.max(weight, previous);\n })\n ? node.weights\n : weights;\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import type { WorkspaceLayout } from './layout.utils.js';
1
+ import type { WorkspaceLayout, WorkspaceNode } from './layout.utils.js';
2
2
  export declare function parseWorkspaceValue(value: string): WorkspaceLayout | undefined;
3
3
  export declare function serializeWorkspaceValue(layout: WorkspaceLayout | undefined): string;
4
- /** Compares serialized layout representations, including property order and supplied group fields. */
5
- export declare function sameSerializedWorkspaceLayout(left: WorkspaceLayout | undefined, right: WorkspaceLayout | undefined): boolean;
4
+ /** Compares known arrangement fields; object property insertion order is irrelevant. */
5
+ export declare function sameWorkspaceLayout(left: WorkspaceLayout | undefined, right: WorkspaceLayout | undefined): boolean;
6
+ export declare function sameWorkspaceNode(left: WorkspaceNode | null, right: WorkspaceNode | null): boolean;
@@ -1,68 +1,33 @@
1
1
  import { normalizeLayout as e } from "./layout.utils.js";
2
+ import { sameArrayItems as t } from "../comparison.utils.js";
2
3
  // src/workspace/utils/model/value.utils.ts
3
- var t = [
4
- "version",
5
- "root",
6
- "closed"
7
- ], n = [
8
- "type",
9
- "panels",
10
- "active"
11
- ], r = [
12
- "type",
13
- "axis",
14
- "children",
15
- "weights"
16
- ];
17
- function i(t) {
4
+ function n(t) {
18
5
  if (!t) return;
19
- let n = JSON.parse(t), r = /* @__PURE__ */ new Set(), i = (e) => typeof e == "object" && !!e, a = (e) => i(e) ? e.type === "group" ? !Array.isArray(e.panels) || !e.panels.length || typeof e.active != "string" || !e.panels.includes(e.active) ? !1 : e.panels.every((e) => typeof e != "string" || !e || r.has(e) ? !1 : (r.add(e), !0)) : s(e) ? e.children.every((e) => a(e)) : !1 : !1;
20
- if (!i(n) || n.version !== 1 || !(n.root === null || a(n.root)) || !Array.isArray(n.closed) || !n.closed.every((e) => typeof e == "string" && r.has(e)) || new Set(n.closed).size !== n.closed.length) throw TypeError("Invalid workspace arrangement");
6
+ let n = JSON.parse(t), r = /* @__PURE__ */ new Set(), a = (e) => typeof e == "object" && !!e, o = (e) => a(e) ? e.type === "group" ? !Array.isArray(e.panels) || !e.panels.length || typeof e.active != "string" || !e.panels.includes(e.active) ? !1 : e.panels.every((e) => typeof e != "string" || !e || r.has(e) ? !1 : (r.add(e), !0)) : i(e) ? e.children.every((e) => o(e)) : !1 : !1;
7
+ if (!a(n) || n.version !== 1 || !(n.root === null || o(n.root)) || !Array.isArray(n.closed) || !n.closed.every((e) => typeof e == "string" && r.has(e)) || new Set(n.closed).size !== n.closed.length) throw TypeError("Invalid workspace arrangement");
21
8
  return {
22
9
  version: 1,
23
10
  root: n.root === null ? null : e(n.root),
24
11
  closed: [...n.closed]
25
12
  };
26
13
  }
27
- function a(e) {
14
+ function r(e) {
28
15
  return e ? JSON.stringify(e) : "";
29
16
  }
30
- function o(e, n) {
31
- return e === n ? !0 : !e || !n ? !1 : !p(e, t) || !p(n, t) ? a(e) === a(n) : e.version === n.version && f(e.closed, n.closed) && c(e.root, n.root);
32
- }
33
- function s(e) {
17
+ function i(e) {
34
18
  return e.type !== "split" || !["horizontal", "vertical"].includes(String(e.axis)) || !Array.isArray(e.children) || e.children.length < 2 || !Array.isArray(e.weights) || e.weights.length !== e.children.length || !e.weights.every((e) => typeof e == "number" && Number.isFinite(e) && e > 0) ? !1 : Number.isFinite(e.weights.reduce((e, t) => e + t, 0));
35
19
  }
36
- function c(e, t) {
37
- if (e === t) return !0;
38
- if (!e || !t || e.type !== t.type) return !1;
39
- let i = e.type === "group" ? n : r;
40
- return !p(e, i) || !p(t, i) ? JSON.stringify(e) === JSON.stringify(t) : e.type === "group" ? l(e, t) : u(e, t);
41
- }
42
- function l(e, t) {
43
- return t.type === "group" && e.active === t.active && f(e.panels, t.panels);
44
- }
45
- function u(e, t) {
46
- return t.type === "split" && e.axis === t.axis && f(e.weights, t.weights) && d(e.children, t.children);
20
+ function a(e, n) {
21
+ return e === n ? !0 : !e || !n ? !1 : e.version === n.version && t(e.closed, n.closed) && o(e.root, n.root);
47
22
  }
48
- function d(e, t) {
49
- if (e === t) return !0;
50
- if (e.length !== t.length) return !1;
51
- for (let n = 0; n < e.length; n++) if (!c(e[n], t[n])) return !1;
52
- return !0;
53
- }
54
- function f(e, t) {
55
- if (e === t) return !0;
56
- if (e.length !== t.length) return !1;
57
- for (let n = 0; n < e.length; n++) if (e[n] !== t[n]) return !1;
23
+ function o(e, n) {
24
+ if (e === n) return !0;
25
+ if (!e || !n) return !1;
26
+ if (e.type === "group") return n.type === "group" && e.active === n.active && t(e.panels, n.panels);
27
+ if (n.type !== "split" || e.axis !== n.axis || !t(e.weights, n.weights) || e.children.length !== n.children.length) return !1;
28
+ for (let t = 0; t < e.children.length; t++) if (!o(e.children[t], n.children[t])) return !1;
58
29
  return !0;
59
30
  }
60
- function p(e, t) {
61
- if ("toJSON" in e) return !1;
62
- let n = 0;
63
- for (let r in e) if (Object.hasOwn(e, r) && r !== t[n++]) return !1;
64
- return n === t.length;
65
- }
66
- export { i as parseWorkspaceValue, o as sameSerializedWorkspaceLayout, a as serializeWorkspaceValue };
31
+ export { n as parseWorkspaceValue, a as sameWorkspaceLayout, o as sameWorkspaceNode, r as serializeWorkspaceValue };
67
32
 
68
33
  //# sourceMappingURL=value.utils.js.map