@marimo-team/islands 0.25.3-dev192 → 0.25.3-dev193

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 (154) hide show
  1. package/dist/{ConnectedDataExplorerComponent-BBbOElk3.js → ConnectedDataExplorerComponent-BRuwLOIx.js} +9 -9
  2. package/dist/{ErrorBoundary-Dw6uRKVk.js → ErrorBoundary-BVu_xT-p.js} +2 -2
  3. package/dist/{abnfDiagram-VCTEODGH-DhMT6Uhd.js → abnfDiagram-VCTEODGH-LlJTOOU_.js} +2 -2
  4. package/dist/{architectureDiagram-5GKGNRK7-BVbEiJLq.js → architectureDiagram-5GKGNRK7-9PQtGLLZ.js} +1 -1
  5. package/dist/{arrays-R6JsImiT.js → arrays-DA6KkLfq.js} +6 -12
  6. package/dist/assets/__vite-browser-external-BCJsx8QS.js +1 -0
  7. package/dist/assets/{worker-C6e9ERyd.js → worker-DodjWT_Z.js} +2 -2
  8. package/dist/{capabilities-CI4xUPsp.js → capabilities-CvWU-ey_.js} +1 -1
  9. package/dist/{chat-ui-BguxTQEL.js → chat-ui-Bl2euMBD.js} +93 -93
  10. package/dist/{chunk-IMKFNOWR-By5hSbJJ.js → chunk-IMKFNOWR-DcXv-BD5.js} +1 -1
  11. package/dist/{chunk-SHT3W25Y-DFrEYG54.js → chunk-SHT3W25Y-VwnELN23.js} +1 -1
  12. package/dist/{chunk-SVP7TREG-DFXGc9ew.js → chunk-SVP7TREG-DgQpI5Zi.js} +1 -1
  13. package/dist/{chunk-TICWLB2K-DZdNIpoZ.js → chunk-TICWLB2K-CTg6VTJT.js} +1 -1
  14. package/dist/{classDiagram-ZZMXUADV-Cgj_eEQA.js → classDiagram-ZZMXUADV-UzmcFrnW.js} +2 -2
  15. package/dist/{classDiagram-v2-VYDZK3BY-DLAUrSqj.js → classDiagram-v2-VYDZK3BY-DhjiI6IQ.js} +2 -2
  16. package/dist/{code-visibility-v_7ijLtx.js → code-visibility-BTVimCUw.js} +38 -42
  17. package/dist/{common-BUwWHpnK.js → common-fTgq7gO-.js} +849 -849
  18. package/dist/{cynefinDiagram-5FMLGOSQ-Cikf9AKa.js → cynefinDiagram-5FMLGOSQ-O4ShIbJX.js} +1 -1
  19. package/dist/{dagre-GXQ25YYZ-C5KEi5_l.js → dagre-GXQ25YYZ-dtHhhcPu.js} +1 -1
  20. package/dist/{data-grid-overlay-editor-4IZymnXZ.js → data-grid-overlay-editor-DAZZkLWg.js} +1 -1
  21. package/dist/{diagram-S7CK7UJ4-BaoBTQjR.js → diagram-S7CK7UJ4-ppPYVZ6W.js} +1 -1
  22. package/dist/{diagram-UQ7AKVKN-DDufBsUA.js → diagram-UQ7AKVKN-CMZDf--k.js} +1 -1
  23. package/dist/{diagram-VX7I27RA-CY6RALJ8.js → diagram-VX7I27RA-CFvJdx-C.js} +1 -1
  24. package/dist/{diagram-Z3DM3KII-Bc-LHsD6.js → diagram-Z3DM3KII-Dt6_uFbv.js} +1 -1
  25. package/dist/{dropdown-menu-drDjxJyV.js → dropdown-menu-CeaOsjWZ.js} +2 -2
  26. package/dist/{ebnfDiagram-PWID7BFC-Cz0J-tcC.js → ebnfDiagram-PWID7BFC-DpRFrKK-.js} +2 -2
  27. package/dist/{erDiagram-RLTQ6QDP-DTXTDgFu.js → erDiagram-RLTQ6QDP-CqAU4b0u.js} +1 -1
  28. package/dist/{error-entries-CZ1NQ6Kv.js → error-entries-CYGwr5-O.js} +5596 -6012
  29. package/dist/feedback-button-DzFFn-n4.js +374 -0
  30. package/dist/{flowDiagram-HODETNUW-RbwWf2zc.js → flowDiagram-HODETNUW-i8-Gw8HO.js} +2 -2
  31. package/dist/{formats-DbXnijtH.js → formats-BtoHHy42.js} +1 -1
  32. package/dist/{glide-data-editor-DU8_EDG5.js → glide-data-editor-DFsqVbWR.js} +5 -5
  33. package/dist/{globals-BeBDOk22.js → globals-Dr0MRANu.js} +2 -2
  34. package/dist/{html-to-image-D_4_hQ8U.js → html-to-image-Cy5UDpQJ.js} +56 -56
  35. package/dist/{infoDiagram-27XIBGKW-DlmzZjmI.js → infoDiagram-27XIBGKW-DpfOKdLL.js} +1 -1
  36. package/dist/{ishikawaDiagram-5VMMS53U-EN3TYP_q.js → ishikawaDiagram-5VMMS53U-Dg7mrMG7.js} +1 -1
  37. package/dist/{kanban-definition-UXKFOSKX-CK_-Ru7Q.js → kanban-definition-UXKFOSKX-QB6e3Jrj.js} +1 -1
  38. package/dist/main.js +5875 -5876
  39. package/dist/{mermaid-DU9ZRmkG.js → mermaid-CeWG4Egr.js} +48 -48
  40. package/dist/{mindmap-definition-YA3MSWOX-C-hqgUvF.js → mindmap-definition-YA3MSWOX-BTz3uTGe.js} +1 -1
  41. package/dist/{number-overlay-editor-BoIkyh6H.js → number-overlay-editor-DupOSYHx.js} +1 -1
  42. package/dist/{once-eG8Vmvjd.js → once-DWGO2mQ2.js} +1 -1
  43. package/dist/{pegDiagram-XKGWAZYB-BiMejYPB.js → pegDiagram-XKGWAZYB-3ZIEa3mB.js} +2 -2
  44. package/dist/{pieDiagram-E7YTZNPT-B1zCZ1eq.js → pieDiagram-E7YTZNPT-BJAlk046.js} +1 -1
  45. package/dist/{process-output-DxSCHBWp.js → process-output-q9MTAIMX.js} +2 -2
  46. package/dist/{railroadDiagram-O6MQD6OU-BLcfaASl.js → railroadDiagram-O6MQD6OU-Dn3bsSRa.js} +2 -2
  47. package/dist/{requirementDiagram-BXWQKSXE-DtBOf52-.js → requirementDiagram-BXWQKSXE-wcOmQQCL.js} +1 -1
  48. package/dist/{reveal-component-5M3a2rpj.js → reveal-component-Bg8rP_Uo.js} +17 -17
  49. package/dist/{sequenceDiagram-WJ2MYXX4-DIwF19_n.js → sequenceDiagram-WJ2MYXX4-DSh_qxoF.js} +1 -1
  50. package/dist/{spec-DZDnnlgT.js → spec-C7Fos-If.js} +1 -1
  51. package/dist/{stateDiagram-D77RDMKH-sWk1AdYL.js → stateDiagram-D77RDMKH-DH_H8NMH.js} +2 -2
  52. package/dist/{stateDiagram-v2-MP3YSRHH-CiNo-OI7.js → stateDiagram-v2-MP3YSRHH-D_JM7MEK.js} +2 -2
  53. package/dist/style.css +1 -1
  54. package/dist/{swimlanes-42K2YHIH-Bj3hiOY5.js → swimlanes-42K2YHIH-CfoTJO-9.js} +1 -1
  55. package/dist/{swimlanesDiagram-VR7AAH4N-BzEo2r_N.js → swimlanesDiagram-VR7AAH4N-Z_QhvK0G.js} +2 -2
  56. package/dist/{swiper-component-BkCm-kLg.js → swiper-component-D2geL1Ku.js} +1 -1
  57. package/dist/{timeline-definition-24CTP7MA-CrPQk42H.js → timeline-definition-24CTP7MA-BFtdScaL.js} +1 -1
  58. package/dist/{toDate-Cu2pIZcC.js → toDate-CQAFSwos.js} +24 -24
  59. package/dist/{useAsyncData-DEhLdRIu.js → useAsyncData-BeyZyjso.js} +1 -1
  60. package/dist/{useDeepCompareMemoize-RjZGVhBV.js → useDeepCompareMemoize-DOQgae0W.js} +1 -1
  61. package/dist/{useIframeCapabilities-CSdWn6NP.js → useIframeCapabilities-DNvaj9wM.js} +1 -1
  62. package/dist/{useLifecycle-DtcB2s1z.js → useLifecycle-n2lnCFS8.js} +1 -1
  63. package/dist/{useTheme-CoEtr4mK.js → useTheme-CY777LXN.js} +303 -99
  64. package/dist/{vega-component-BhjTrP9-.js → vega-component-0nQzA-I8.js} +6 -6
  65. package/dist/{vennDiagram-4TSXK5OY-BaYMoIpj.js → vennDiagram-4TSXK5OY-BXY8IGCA.js} +1 -1
  66. package/dist/{wardleyDiagram-VM6X3IG4-DjHeuj8p.js → wardleyDiagram-VM6X3IG4-D0tFe6eC.js} +1 -1
  67. package/dist/{xychartDiagram-S5SC5T6Z-Bc_hcuXS.js → xychartDiagram-S5SC5T6Z-Dx8wFM-y.js} +1 -1
  68. package/package.json +1 -1
  69. package/src/__mocks__/notebook.ts +0 -1
  70. package/src/__mocks__/partial.ts +26 -0
  71. package/src/__tests__/main.test.tsx +24 -1
  72. package/src/components/app-config/app-config-form.tsx +5 -9
  73. package/src/components/editor/__tests__/data-attributes.test.tsx +0 -1
  74. package/src/components/editor/__tests__/output-persistence.test.tsx +0 -1
  75. package/src/components/editor/actions/useCellActionButton.tsx +6 -5
  76. package/src/components/editor/actions/useConfigActions.tsx +3 -4
  77. package/src/components/editor/actions/useNotebookActions.tsx +5 -4
  78. package/src/components/editor/cell/code/cell-editor.tsx +13 -6
  79. package/src/components/editor/cell/collapse.tsx +6 -1
  80. package/src/components/editor/chrome/components/feedback-button.tsx +1 -7
  81. package/src/components/editor/controls/Controls.tsx +1 -1
  82. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +8 -6
  83. package/src/components/editor/navigation/__tests__/navigation.test.ts +15 -15
  84. package/src/components/editor/navigation/__tests__/selection.test.ts +44 -21
  85. package/src/components/editor/navigation/focus-utils.ts +19 -0
  86. package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +6 -13
  87. package/src/components/editor/navigation/navigation.ts +52 -43
  88. package/src/components/editor/navigation/selection.ts +30 -29
  89. package/src/components/editor/notebook-cell.tsx +10 -18
  90. package/src/components/editor/renderers/cell-array.tsx +6 -5
  91. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
  92. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
  93. package/src/components/pages/edit-page.tsx +0 -13
  94. package/src/components/scratchpad/scratchpad.tsx +0 -1
  95. package/src/components/slides/reveal-component.tsx +1 -1
  96. package/src/components/slides/slide-cell-view.tsx +0 -1
  97. package/src/components/sort/SortableCellsProvider.tsx +6 -5
  98. package/src/core/MarimoApp.tsx +1 -1
  99. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -37
  100. package/src/core/cells/__tests__/actions.test.ts +190 -80
  101. package/src/core/cells/__tests__/arrange.test.ts +263 -0
  102. package/src/core/cells/__tests__/cells.test.ts +11 -1101
  103. package/src/core/cells/__tests__/document.test.ts +3 -32
  104. package/src/core/cells/__tests__/editor.test.ts +57 -0
  105. package/src/core/cells/__tests__/harness.ts +82 -0
  106. package/src/core/cells/__tests__/layout.test.ts +189 -0
  107. package/src/core/cells/__tests__/notebook-outline.test.ts +7 -1
  108. package/src/core/cells/__tests__/session.test.ts +329 -174
  109. package/src/core/cells/__tests__/utils.test.ts +0 -1
  110. package/src/core/cells/actions.ts +247 -82
  111. package/src/core/cells/arrange.ts +341 -0
  112. package/src/core/cells/cells.ts +27 -516
  113. package/src/core/cells/document.ts +6 -5
  114. package/src/core/cells/edit.ts +30 -0
  115. package/src/core/cells/editor.ts +82 -0
  116. package/src/core/cells/layout.ts +152 -0
  117. package/src/core/cells/session.ts +75 -52
  118. package/src/core/cells/types.ts +0 -5
  119. package/src/core/cells/utils.ts +6 -4
  120. package/src/core/config/__tests__/app-config.test.ts +64 -0
  121. package/src/core/config/__tests__/config-schema.test.ts +1 -1
  122. package/src/core/config/config-schema.ts +6 -2
  123. package/src/core/config/config.ts +26 -12
  124. package/src/core/islands/bootstrap.ts +0 -1
  125. package/src/core/kernel/handlers.ts +1 -13
  126. package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
  127. package/src/core/meta/code-visibility.ts +18 -9
  128. package/src/core/notebook/__tests__/operations.test.ts +51 -0
  129. package/src/core/notebook/document/__tests__/codemirror.test.ts +15 -0
  130. package/src/core/notebook/index.ts +2 -1
  131. package/src/core/notebook/operations.ts +30 -0
  132. package/src/core/saving/__tests__/state.test.ts +111 -0
  133. package/src/core/saving/save-component.tsx +19 -33
  134. package/src/core/saving/state.ts +38 -39
  135. package/src/core/saving/useAutoSave.ts +8 -35
  136. package/src/core/session/__tests__/backend.test.ts +1 -0
  137. package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +1 -0
  138. package/src/core/session/active-notebook.ts +11 -0
  139. package/src/core/session/backend.ts +17 -19
  140. package/src/core/session/embedded.ts +7 -0
  141. package/src/core/session/useNotebookReplica.ts +3 -1
  142. package/src/core/session/useNotebookSession.tsx +7 -8
  143. package/src/core/transports/__tests__/static.test.ts +139 -8
  144. package/src/core/transports/static.ts +98 -16
  145. package/src/core/wasm/__tests__/bridge.test.ts +1 -0
  146. package/src/mount.tsx +19 -10
  147. package/src/stories/cell.stories.tsx +0 -2
  148. package/src/stories/layout/vertical/one-column.stories.tsx +0 -2
  149. package/src/utils/__tests__/id-tree.test.ts +20 -1548
  150. package/src/utils/id-tree.tsx +12 -537
  151. package/dist/assets/__vite-browser-external-C8gQho07.js +0 -1
  152. package/dist/feedback-button-MpeoIn1D.js +0 -379
  153. package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
  154. package/src/components/editor/navigation/state.ts +0 -65
@@ -3,7 +3,7 @@
3
3
  import { Memoize } from "typescript-memoize";
4
4
  import { reorderColumnSizes } from "@/components/editor/columns/storage";
5
5
  import { SETUP_CELL_ID } from "@/core/cells/ids";
6
- import { arrayDelete, arrayInsert, arrayInsertMany, arrayMove } from "./arrays";
6
+ import { arrayDelete, arrayInsert, arrayMove } from "./arrays";
7
7
  import { Logger } from "./Logger";
8
8
 
9
9
  /**
@@ -25,79 +25,12 @@ export type CellIndex = number & { __brand?: "CellIndex" };
25
25
  */
26
26
  export class TreeNode<T> {
27
27
  public value: T;
28
- public isCollapsed: boolean;
29
- public children: TreeNode<T>[];
30
28
 
31
- public constructor(value: T, isCollapsed: boolean, children: TreeNode<T>[]) {
29
+ public constructor(value: T) {
32
30
  this.value = value;
33
- this.isCollapsed = isCollapsed;
34
- this.children = children;
35
- }
36
-
37
- /**
38
- * Recursively count the number of nodes in the tree
39
- */
40
- @Memoize()
41
- public geDescendantCount(): number {
42
- let count = 0;
43
- const stack = [...this.children];
44
-
45
- while (stack.length > 0) {
46
- // oxlint-disable-next-line typescript/no-non-null-assertion
47
- const node = stack.pop()!;
48
- count++;
49
-
50
- // Add children to stack
51
- for (let i = node.children.length - 1; i >= 0; i--) {
52
- stack.push(node.children[i]);
53
- }
54
- }
55
-
56
- return count;
57
- }
58
-
59
- @Memoize()
60
- public getDescendants(): T[] {
61
- const result: T[] = [];
62
- const stack = [...this.children];
63
-
64
- while (stack.length > 0) {
65
- // oxlint-disable-next-line typescript/no-non-null-assertion
66
- const node = stack.pop()!;
67
- result.push(node.value);
68
-
69
- // Add children to stack in reverse order to maintain correct traversal order
70
- for (let i = node.children.length - 1; i >= 0; i--) {
71
- stack.push(node.children[i]);
72
- }
73
- }
74
-
75
- return result;
76
- }
77
-
78
- @Memoize()
79
- public get inOrderIds(): T[] {
80
- const result: T[] = [];
81
-
82
- // Use depth-first traversal to preserve logical document order
83
- const traverse = (node: TreeNode<T>) => {
84
- result.push(node.value);
85
- for (const child of node.children) {
86
- traverse(child);
87
- }
88
- };
89
-
90
- for (const child of this.children) {
91
- traverse(child);
92
- }
93
-
94
- return result;
95
31
  }
96
32
 
97
33
  public toString(): string {
98
- if (this.isCollapsed) {
99
- return `${this.value} (collapsed)`;
100
- }
101
34
  return String(this.value);
102
35
  }
103
36
 
@@ -117,52 +50,14 @@ export class CollapsibleTree<T> {
117
50
  this.id = id;
118
51
  }
119
52
 
120
- public static from<T>(ids: T[]): CollapsibleTree<T> {
121
- const id = `tree_${uniqueId++}` as CellColumnId;
53
+ /** A column of `ids`, keeping `id` when a column is rebuilt. */
54
+ public static from<T>(ids: T[], id?: CellColumnId): CollapsibleTree<T> {
122
55
  return new CollapsibleTree(
123
- ids.map((id) => new TreeNode(id, false, [])),
124
- id,
56
+ ids.map((id) => new TreeNode(id)),
57
+ id ?? (`tree_${uniqueId++}` as CellColumnId),
125
58
  );
126
59
  }
127
60
 
128
- /**
129
- * Create a new tree from ids, preserving structure from previous tree if possible
130
- */
131
- public static fromWithPreviousShape<T>(
132
- ids: T[],
133
- previousTree?: CollapsibleTree<T>,
134
- ): CollapsibleTree<T> {
135
- if (!previousTree) {
136
- return CollapsibleTree.from(ids);
137
- }
138
-
139
- // Reuse the previous tree's id if possible
140
- const id = previousTree.id;
141
-
142
- // Create new tree with nothing collapsed
143
- let newTree = new CollapsibleTree(
144
- ids.map((id) => new TreeNode(id, false, [])),
145
- id,
146
- );
147
-
148
- // Collapse nodes that were collapsed in the previous tree
149
- for (const id of ids) {
150
- if (previousTree.isCollapsed(id)) {
151
- const children = previousTree._nodeMap.get(id)?.children ?? [];
152
- // Find the first child that is also in the new tree, going backwards
153
- for (let i = children.length - 1; i >= 0; i--) {
154
- const child = children[i];
155
- if (newTree._nodeMap.has(child.value)) {
156
- newTree = newTree.collapse(id, child.value);
157
- break;
158
- }
159
- }
160
- }
161
- }
162
-
163
- return newTree;
164
- }
165
-
166
61
  public withNodes(nodes: TreeNode<T>[]): CollapsibleTree<T> {
167
62
  return new CollapsibleTree(nodes, this.id);
168
63
  }
@@ -172,9 +67,8 @@ export class CollapsibleTree<T> {
172
67
  return this.nodes.map((n) => n.value);
173
68
  }
174
69
 
175
- @Memoize()
176
70
  public get inOrderIds(): T[] {
177
- return this.nodes.flatMap((n) => [n.value, ...n.inOrderIds]);
71
+ return this.topLevelIds;
178
72
  }
179
73
 
180
74
  @Memoize()
@@ -195,38 +89,6 @@ export class CollapsibleTree<T> {
195
89
  return result;
196
90
  }
197
91
 
198
- /**
199
- * Get the descendants of the given node
200
- *
201
- * Only works for the top-level nodes
202
- */
203
- public getDescendants(id: T): T[] {
204
- const node = this._nodeMap.get(id);
205
- if (!node) {
206
- Logger.warn(
207
- `Node ${id} not found in tree. Valid ids: ${this.topLevelIds}`,
208
- );
209
- return [];
210
- }
211
- return node.getDescendants();
212
- }
213
-
214
- /**
215
- * Check if the given node is collapsed
216
- *
217
- * Only works for the top-level nodes
218
- */
219
- public isCollapsed(id: T): boolean {
220
- const node = this._nodeMap.get(id);
221
- if (!node) {
222
- Logger.warn(
223
- `Node ${id} not found in tree. Valid ids: ${this.topLevelIds}`,
224
- );
225
- return false;
226
- }
227
- return node.isCollapsed;
228
- }
229
-
230
92
  /**
231
93
  * Get the index of the given node, or throw
232
94
  */
@@ -248,173 +110,6 @@ export class CollapsibleTree<T> {
248
110
  return this.nodes.slice(start, end).map((n) => n.value);
249
111
  }
250
112
 
251
- /**
252
- * Move the given node to the front
253
- */
254
- public moveToFront(id: T): CollapsibleTree<T> {
255
- const index = this.indexOfOrThrow(id);
256
- return this.withNodes(arrayMove(this.nodes, index, 0));
257
- }
258
-
259
- /**
260
- * Move the given node to the back
261
- */
262
- public moveToBack(id: T): CollapsibleTree<T> {
263
- const index = this.indexOfOrThrow(id);
264
- return this.withNodes(arrayMove(this.nodes, index, this.nodes.length - 1));
265
- }
266
-
267
- /**
268
- * Collapse everything past the given node @param id
269
- * until @param until or the end of the tree
270
- */
271
- public collapse(id: T, until: T | undefined): CollapsibleTree<T> {
272
- const nodeIndex = this.nodes.findIndex((n) => n.value === id);
273
- if (nodeIndex === -1) {
274
- throw new Error(
275
- `Node ${id} not found in tree. Valid ids: ${this.topLevelIds}`,
276
- );
277
- }
278
-
279
- const untilIndex =
280
- until === undefined
281
- ? this.nodes.length
282
- : this.nodes.findIndex((n) => n.value === until);
283
-
284
- if (untilIndex === -1) {
285
- throw new Error(`Node ${until} not found in tree`);
286
- }
287
- if (untilIndex < nodeIndex) {
288
- throw new Error(`Node ${until} is before node ${id}`);
289
- }
290
-
291
- const nodes = [...this.nodes];
292
- const node = nodes[nodeIndex];
293
- if (node.isCollapsed) {
294
- throw new Error(`Node ${id} is already collapsed`);
295
- }
296
-
297
- // Fold the next nodes into the current node
298
- const children = nodes.splice(nodeIndex + 1, untilIndex - nodeIndex);
299
- nodes[nodeIndex] = new TreeNode(node.value, true, children);
300
-
301
- return this.withNodes(nodes);
302
- }
303
-
304
- /**
305
- * Collapse all nodes in the tree, including nested ones
306
- *
307
- * Only works for the top-level nodes
308
- * Does not collapse the children of already collapsed nodes
309
- */
310
- public collapseAll(
311
- collapseRanges: ({ id: T; until: T | undefined } | null)[],
312
- ): CollapsibleTree<T> {
313
- const nodes = [...this.nodes];
314
- if (collapseRanges.length === 0) {
315
- throw new Error("No collapse ranges provided");
316
- }
317
-
318
- if (collapseRanges.length !== nodes.length) {
319
- throw new Error(
320
- `Collapse ranges length ${collapseRanges.length} does not match tree length ${nodes.length}`,
321
- );
322
- }
323
-
324
- // Start from the end of the list and collapse nodes children first
325
- let nodeIndex = nodes.length - 1;
326
- while (nodeIndex >= 0) {
327
- const node = nodes[nodeIndex];
328
- const range = collapseRanges[nodeIndex];
329
-
330
- if (!node.isCollapsed && range) {
331
- const { id, until } = range;
332
- if (id !== node.value) {
333
- throw new Error(
334
- `Node ${node.value} does not match collapse range id ${id}`,
335
- );
336
- }
337
- const untilIndex =
338
- until === undefined
339
- ? nodes.length
340
- : nodes.findIndex((n) => n.value === until);
341
-
342
- if (untilIndex === -1) {
343
- throw new Error(`Node ${until} not found in tree`);
344
- }
345
- if (untilIndex < nodeIndex) {
346
- throw new Error(`Node ${until} is before node ${id}`);
347
- }
348
-
349
- // Fold the next nodes into the current node
350
- const children = nodes.splice(nodeIndex + 1, untilIndex - nodeIndex);
351
- nodes[nodeIndex] = new TreeNode(node.value, true, children);
352
- nodeIndex--;
353
- } else {
354
- // Move to the next node
355
- nodeIndex--;
356
- }
357
- }
358
-
359
- return this.withNodes(nodes);
360
- }
361
-
362
- /**
363
- * Expand a node and all of its children.
364
- * If the node is already expanded, returns the same tree (no-op).
365
- */
366
- public expand(id: T): CollapsibleTree<T> {
367
- const nodeIndex = this.nodes.findIndex((n) => n.value === id);
368
- if (nodeIndex === -1) {
369
- throw new Error(
370
- `Node ${id} not found in tree. Valid ids: ${this.topLevelIds}`,
371
- );
372
- }
373
-
374
- let nodes = [...this.nodes];
375
- const node = nodes[nodeIndex];
376
- if (!node.isCollapsed) {
377
- // Already expanded, no-op
378
- return this;
379
- }
380
-
381
- nodes[nodeIndex] = new TreeNode(node.value, false, []);
382
- nodes = arrayInsertMany(nodes, nodeIndex + 1, node.children);
383
-
384
- return this.withNodes(nodes);
385
- }
386
-
387
- /**
388
- * Expand all collapsed nodes in the tree, including nested ones
389
- */
390
- public expandAll(): CollapsibleTree<T> {
391
- let nodes = [...this.nodes];
392
- let nodeIndex = 0;
393
-
394
- while (nodeIndex < nodes.length) {
395
- const node = nodes[nodeIndex];
396
- if (node.isCollapsed) {
397
- // Replace the collapsed node with an expanded one
398
- nodes[nodeIndex] = new TreeNode(node.value, false, []);
399
- // Add the children of the collapsed node to the list
400
- nodes = arrayInsertMany(nodes, nodeIndex + 1, node.children);
401
- nodeIndex++;
402
- } else {
403
- // Move to the next node
404
- nodeIndex++;
405
- }
406
- }
407
-
408
- return this.withNodes(nodes);
409
- }
410
-
411
- /**
412
- * Move a node from one index to another
413
- */
414
- public move(fromIdx: number, toIdx: number): CollapsibleTree<T> {
415
- return this.withNodes(arrayMove(this.nodes, fromIdx, toIdx));
416
- }
417
-
418
113
  /**
419
114
  * Get the node at the given index
420
115
  */
@@ -473,9 +168,7 @@ export class CollapsibleTree<T> {
473
168
  * Insert a node at the given index
474
169
  */
475
170
  public insert(id: T, index: number): CollapsibleTree<T> {
476
- return this.withNodes(
477
- arrayInsert(this.nodes, index, new TreeNode(id, false, [])),
478
- );
171
+ return this.withNodes(arrayInsert(this.nodes, index, new TreeNode(id)));
479
172
  }
480
173
 
481
174
  /**
@@ -492,14 +185,9 @@ export class CollapsibleTree<T> {
492
185
  return this.insert(id, 0);
493
186
  }
494
187
 
495
- /**
496
- * Delete a node, expand if it was collapsed
497
- */
498
188
  public deleteAtIndex(idx: number): CollapsibleTree<T> {
499
- const id = this.atOrThrow(idx);
500
- // Expand the node first (if collapsed) to bring children back to top level
501
- const tree = this.expand(id);
502
- return tree.withNodes(arrayDelete(tree.nodes, idx));
189
+ this.atOrThrow(idx);
190
+ return this.withNodes(arrayDelete(this.nodes, idx));
503
191
  }
504
192
 
505
193
  public delete(id: T): CollapsibleTree<T> {
@@ -507,49 +195,6 @@ export class CollapsibleTree<T> {
507
195
  return this.deleteAtIndex(index);
508
196
  }
509
197
 
510
- /**
511
- * Get the number of nodes in the tree, not-including the given node
512
- */
513
- public getCount(id: T): number {
514
- return this._nodeMap.get(id)?.geDescendantCount() ?? 0;
515
- }
516
-
517
- /**
518
- * Find and expand the node and all of its children
519
- */
520
- public findAndExpandDeep(id: T): CollapsibleTree<T> {
521
- const found = this.find(id);
522
- if (found.length === 0) {
523
- return this;
524
- }
525
- return found.reduce<CollapsibleTree<T>>(
526
- (acc, node) => acc.expand(node),
527
- this,
528
- );
529
- }
530
-
531
- /**
532
- * Find a node, returning the path to it
533
- * With the last element being the node itself
534
- */
535
- public find(id: T): T[] {
536
- // We need to recursively find the node
537
- function findNode(nodes: TreeNode<T>[], path: T[]): T[] {
538
- for (const node of nodes) {
539
- if (node.value === id) {
540
- return [...path, id];
541
- }
542
- const result = findNode(node.children, [...path, node.value]);
543
- if (result.length > 0) {
544
- return result;
545
- }
546
- }
547
- return [];
548
- }
549
-
550
- return findNode(this.nodes, []);
551
- }
552
-
553
198
  /**
554
199
  * Split the tree into two trees
555
200
  * @param id the id of the node to split at
@@ -578,18 +223,7 @@ export class CollapsibleTree<T> {
578
223
  }
579
224
 
580
225
  public toString(): string {
581
- let depth = 0;
582
- let result = "";
583
- const asString = (nodes: TreeNode<T>[]) => {
584
- for (const node of nodes) {
585
- result += `${" ".repeat(depth * 2)}${node.toString()}\n`;
586
- depth += 1;
587
- asString(node.children);
588
- depth -= 1;
589
- }
590
- };
591
- asString(this.nodes);
592
- return result;
226
+ return this.nodes.map((node) => `${node.toString()}\n`).join("");
593
227
  }
594
228
  }
595
229
 
@@ -642,7 +276,7 @@ export class MultiColumn<T> {
642
276
  }
643
277
 
644
278
  const newColumns = splitIds.map((ids, idx) =>
645
- CollapsibleTree.fromWithPreviousShape(ids, previousColumns[idx]),
279
+ CollapsibleTree.from(ids, previousColumns[idx].id),
646
280
  );
647
281
 
648
282
  return new MultiColumn(newColumns);
@@ -814,117 +448,6 @@ export class MultiColumn<T> {
814
448
  return new MultiColumn([firstColumn.withNodes(nodes)]);
815
449
  }
816
450
 
817
- public moveWithinColumn(
818
- col: CellColumnId,
819
- fromIdx: CellIndex,
820
- toIdx: CellIndex,
821
- ): MultiColumn<T> {
822
- return this.transform(col, (c) => {
823
- return c.move(fromIdx, toIdx);
824
- });
825
- }
826
-
827
- public moveAcrossColumns(
828
- fromCol: CellColumnId,
829
- fromId: T,
830
- toCol: CellColumnId,
831
- toId: T | undefined,
832
- ): MultiColumn<T> {
833
- // Find indices once to avoid repeated lookups
834
- const fromColumnIndex = this.indexOfOrThrow(fromCol);
835
- const toColumnIndex = this.indexOfOrThrow(toCol);
836
-
837
- // Only copy the columns we're modifying
838
- const newColumns = [...this.columns];
839
- const fromColumn = newColumns[fromColumnIndex];
840
-
841
- // Find the node once
842
- const nodeIndex = fromColumn.nodes.findIndex((n) => n.value === fromId);
843
- if (nodeIndex === -1) {
844
- throw new Error(`Node ${fromId} not found in column ${fromCol}`);
845
- }
846
-
847
- const node = fromColumn.nodes[nodeIndex];
848
-
849
- // Create new columns with the changes
850
- newColumns[fromColumnIndex] = fromColumn.withNodes(
851
- fromColumn.nodes.filter((_, i) => i !== nodeIndex),
852
- );
853
-
854
- const toColumn = newColumns[toColumnIndex];
855
- if (toId) {
856
- const toIndex = toColumn.indexOfOrThrow(toId);
857
- newColumns[toColumnIndex] = toColumn.withNodes(
858
- arrayInsert(toColumn.nodes, toIndex, node),
859
- );
860
- } else {
861
- newColumns[toColumnIndex] = toColumn.withNodes([node, ...toColumn.nodes]);
862
- }
863
-
864
- return new MultiColumn(newColumns);
865
- }
866
-
867
- /**
868
- * Move multiple cells to be immediately before (or after) a target cell.
869
- * Cells are inserted in their original order.
870
- *
871
- * @throws Error if any cellId is not found in any column.
872
- * If targetId is among the moved cells, cells are inserted at the end of the target column.
873
- */
874
- public moveCellsRelativeTo(
875
- cellIds: T[],
876
- targetId: T,
877
- position: "before" | "after",
878
- ): MultiColumn<T> {
879
- if (cellIds.length === 0) {
880
- return this;
881
- }
882
-
883
- const cellIdSet = new Set(cellIds);
884
- const targetColumn = this.findWithId(targetId);
885
- const targetColIndex = this.indexOfOrThrow(targetColumn.id);
886
-
887
- // Collect nodes to move
888
- const nodesToMove: TreeNode<T>[] = [];
889
- for (const id of cellIds) {
890
- const col = this.findWithId(id);
891
- const node = col.nodes.find((n) => n.value === id);
892
- if (!node) {
893
- throw new Error(`Node ${id} not found in column ${col.id}`);
894
- }
895
- nodesToMove.push(node);
896
- }
897
-
898
- // Remove moved cells from all columns
899
- const columnsWithRemovals = this.columns.map((col) =>
900
- col.withNodes(col.nodes.filter((n) => !cellIdSet.has(n.value))),
901
- );
902
-
903
- // Find target index in the cleaned column
904
- const cleanedTargetCol = columnsWithRemovals[targetColIndex];
905
- let insertIndex = cleanedTargetCol.nodes.findIndex(
906
- (n) => n.value === targetId,
907
- );
908
-
909
- // If target was one of the moved cells, insert at end
910
- if (insertIndex === -1) {
911
- insertIndex = cleanedTargetCol.nodes.length;
912
- } else if (position === "after") {
913
- insertIndex += 1;
914
- }
915
-
916
- // Insert all moved nodes at target position
917
- const newTargetNodes = arrayInsertMany(
918
- cleanedTargetCol.nodes,
919
- insertIndex,
920
- nodesToMove,
921
- );
922
- columnsWithRemovals[targetColIndex] =
923
- cleanedTargetCol.withNodes(newTargetNodes);
924
-
925
- return new MultiColumn(columnsWithRemovals);
926
- }
927
-
928
451
  public indexOfOrThrow(id: CellColumnId): number {
929
452
  const index = this.columns.findIndex((c) => c.id === id);
930
453
  if (index === -1) {
@@ -954,22 +477,6 @@ export class MultiColumn<T> {
954
477
  return new MultiColumn(arrayMove([...this.columns], fromIdx, toIdx));
955
478
  }
956
479
 
957
- public moveToNewColumn(cellId: T): MultiColumn<T> {
958
- const fromColumn = this.findWithId(cellId);
959
-
960
- // Create new columns array with the cell removed from its original column
961
- const columns = this.columns.map((c) => {
962
- if (c.id === fromColumn.id) {
963
- return c.delete(cellId);
964
- }
965
- return c;
966
- });
967
-
968
- // Insert into new column
969
- const newColumn = CollapsibleTree.from([cellId]);
970
- return new MultiColumn([...columns, newColumn]);
971
- }
972
-
973
480
  public findWithId(id: T): CollapsibleTree<T> {
974
481
  const found = this.columns.find((c) => {
975
482
  return c.inOrderIds.includes(id);
@@ -1023,38 +530,6 @@ export class MultiColumn<T> {
1023
530
  return this.transform(col, (c) => c.insert(id, index));
1024
531
  }
1025
532
 
1026
- public deleteById(cellId: T): MultiColumn<T> {
1027
- return this.transformWithCellId(cellId, (c) => c.delete(cellId));
1028
- }
1029
-
1030
- /**
1031
- * Remove the given cells from the tree, then re-insert each at its
1032
- * (columnId, index). Used to undo a move (e.g. cut-paste) by restoring
1033
- * cells to their previous positions. Placements are sorted by
1034
- * (columnId, index) so insert order keeps indices valid.
1035
- */
1036
- public placeCells(
1037
- placements: Array<{ id: T; columnId: CellColumnId; index: CellIndex }>,
1038
- ): MultiColumn<T> {
1039
- if (placements.length === 0) {
1040
- return this;
1041
- }
1042
- let result = this.deleteById(placements[0].id);
1043
- for (const { id } of placements.slice(1)) {
1044
- result = result.deleteById(id);
1045
- }
1046
- const sorted = [...placements].toSorted((a, b) => {
1047
- if (a.columnId !== b.columnId) {
1048
- return a.columnId.localeCompare(b.columnId);
1049
- }
1050
- return (a.index as number) - (b.index as number);
1051
- });
1052
- for (const { id, columnId, index } of sorted) {
1053
- result = result.insertId(id, columnId, index);
1054
- }
1055
- return result;
1056
- }
1057
-
1058
533
  public compact(): MultiColumn<T> {
1059
534
  // Don't compact if there's only one column
1060
535
  if (this.columns.length === 1) {
@@ -1 +0,0 @@
1
- import{t as e}from"./worker-C6e9ERyd.js";var t=e(((e,t)=>{t.exports={}}));export default t();