svedit 0.9.0 → 0.10.0

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 (68) hide show
  1. package/README.md +113 -4
  2. package/dist/AnnotatedTextProperty.svelte +41 -8
  3. package/dist/AnnotatedTextProperty.svelte.d.ts.map +1 -1
  4. package/dist/Command.svelte.d.ts +0 -1
  5. package/dist/Command.svelte.d.ts.map +1 -1
  6. package/dist/Command.svelte.js +18 -3
  7. package/dist/CustomProperty.svelte +20 -9
  8. package/dist/CustomProperty.svelte.d.ts +2 -1
  9. package/dist/CustomProperty.svelte.d.ts.map +1 -1
  10. package/dist/Node.svelte +7 -5
  11. package/dist/Node.svelte.d.ts.map +1 -1
  12. package/dist/NodeArrayProperty.svelte +65 -42
  13. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  14. package/dist/NodeCaret.svelte +0 -7
  15. package/dist/NodeGap.svelte +179 -81
  16. package/dist/NodeGap.svelte.d.ts +0 -2
  17. package/dist/NodeGap.svelte.d.ts.map +1 -1
  18. package/dist/NodeGapMarkers.svelte +251 -84
  19. package/dist/NodeGapMarkers.svelte.d.ts +2 -0
  20. package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
  21. package/dist/NodeSelectionMarkers.svelte +4 -3
  22. package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -1
  23. package/dist/Session.svelte.d.ts +12 -1
  24. package/dist/Session.svelte.d.ts.map +1 -1
  25. package/dist/Session.svelte.js +40 -3
  26. package/dist/Svedit.svelte +336 -165
  27. package/dist/Svedit.svelte.d.ts.map +1 -1
  28. package/dist/Transaction.svelte.d.ts +24 -5
  29. package/dist/Transaction.svelte.d.ts.map +1 -1
  30. package/dist/Transaction.svelte.js +103 -61
  31. package/dist/doc_utils.d.ts +64 -3
  32. package/dist/doc_utils.d.ts.map +1 -1
  33. package/dist/doc_utils.js +276 -10
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +5 -1
  36. package/dist/node_visibility.svelte.d.ts +9 -0
  37. package/dist/node_visibility.svelte.d.ts.map +1 -0
  38. package/dist/node_visibility.svelte.js +718 -0
  39. package/dist/styles/svedit-animations.css +8 -0
  40. package/dist/styles/svedit-colors.css +1 -0
  41. package/dist/types.d.ts +46 -3
  42. package/dist/utils.d.ts +52 -0
  43. package/dist/utils.d.ts.map +1 -1
  44. package/dist/utils.js +109 -3
  45. package/package.json +3 -2
  46. package/src/lib/AnnotatedTextProperty.svelte +41 -8
  47. package/src/lib/Command.svelte.js +18 -3
  48. package/src/lib/CustomProperty.svelte +20 -9
  49. package/src/lib/Node.svelte +7 -5
  50. package/src/lib/NodeArrayProperty.svelte +65 -42
  51. package/src/lib/NodeCaret.svelte +0 -7
  52. package/src/lib/NodeGap.svelte +179 -81
  53. package/src/lib/NodeGapMarkers.svelte +251 -84
  54. package/src/lib/NodeSelectionMarkers.svelte +4 -3
  55. package/src/lib/Session.svelte.js +40 -3
  56. package/src/lib/Svedit.svelte +336 -165
  57. package/src/lib/Transaction.svelte.js +103 -61
  58. package/src/lib/doc_utils.js +276 -10
  59. package/src/lib/index.js +5 -1
  60. package/src/lib/node_visibility.svelte.js +718 -0
  61. package/src/lib/styles/svedit-animations.css +8 -0
  62. package/src/lib/styles/svedit-colors.css +1 -0
  63. package/src/lib/types.d.ts +46 -3
  64. package/src/lib/utils.js +109 -3
  65. package/dist/node_gap_computation.svelte.d.ts +0 -5
  66. package/dist/node_gap_computation.svelte.d.ts.map +0 -1
  67. package/dist/node_gap_computation.svelte.js +0 -621
  68. package/src/lib/node_gap_computation.svelte.js +0 -621
@@ -1,26 +1,143 @@
1
1
  <script>
2
2
  import { getContext } from 'svelte';
3
3
  import NodeCaret from './NodeCaret.svelte';
4
+ import { PATH_SEPARATOR, serialize_path } from './utils.js';
4
5
 
5
6
  /**
7
+ * ┌─────────────────────────────────────────────────────────────────┐
8
+ * │ MUST RULES — do not violate when modifying this file │
9
+ * ├─────────────────────────────────────────────────────────────────┤
10
+ * │ 1. Edge markers (gap-edge.first / gap-edge.last) MUST render │
11
+ * │ OUTSIDE the node-array container — they extend into the │
12
+ * │ whitespace above/below (column) or left/right (row) of the │
13
+ * │ first/last node. They only clamp inward when the consumer │
14
+ * │ explicitly opts in via --node-caret-boundary(-x/-y). │
15
+ * │ 2. Markers MUST NEVER overlap nodes. They render strictly in │
16
+ * │ the whitespace between nodes (mid markers) or outside the │
17
+ * │ node array bounds (edge markers). Never on top of a node. │
18
+ * └─────────────────────────────────────────────────────────────────┘
19
+ *
6
20
  * Renders insertion gap markers for a single node_array.
7
21
  *
8
22
  * Lives inside NodeArrayProperty so it inherits the --row CSS variable.
9
- * Uses var(--row, 1) with the * 99999 multiplier trick to switch between
23
+ * Uses var(--row, 1) with the * 9999999 multiplier trick to switch between
10
24
  * column and row positioning/visuals in pure CSS — no container queries.
11
25
  *
12
- * Gap data is produced by node_gap_computation and published to the
13
- * svedit context. This component reads and renders it.
26
+ * Reads visibility state directly from the registry. SvelteSet's per-key
27
+ * tracking on `.has()` and iteration means this component only
28
+ * re-evaluates when THIS array's visible-index set changes.
14
29
  */
15
30
 
16
- let { path } = $props();
31
+ let { path, count } = $props();
17
32
 
18
33
  const svedit = getContext('svedit');
19
- let path_str = $derived(path.join('.'));
20
- // Per-path signal: only re-evaluates when THIS path's gaps change.
21
- let gap_signal = $derived(svedit.insertion_gap_data?.get_gaps(path_str));
22
- let my_gaps = $derived(gap_signal?.gaps ?? []);
23
- let caret_gap_key = $derived(svedit.insertion_gap_data?.caret_gap_key);
34
+ let path_str = $derived(serialize_path(path));
35
+ let visible = $derived(svedit.visibility_registry.get_array_indices(path_str));
36
+
37
+ let caret_gap_key = $derived.by(() => {
38
+ const s = svedit.session.selection;
39
+ if (s?.type !== 'node' || s.anchor_offset !== s.focus_offset) return null;
40
+ return `${serialize_path(s.path)}-gap-${s.anchor_offset}`;
41
+ });
42
+
43
+ let my_gaps = $derived.by(() => {
44
+ const registry = svedit.visibility_registry;
45
+ const edge_state = registry.edge_map.get(path_str);
46
+ const anchor_prefix = `--${path_str}`;
47
+ const g_prefix = `--g-${path_str}`;
48
+ const container_var = `;--_c:${anchor_prefix}`;
49
+ const has_pair = count >= 2;
50
+ const pair_vars = has_pair
51
+ ? `;--_f:${anchor_prefix}${PATH_SEPARATOR}0;--_s:${anchor_prefix}${PATH_SEPARATOR}1`
52
+ : '';
53
+
54
+ /** @type {Array<{key:string,offset:number,type:string,vars:string,is_first:boolean,is_last:boolean,has_pair:boolean}>} */
55
+ const result = [];
56
+
57
+ if (count === 0) {
58
+ if (visible.has(0)) {
59
+ result.push({
60
+ key: `${path_str}-gap-0`,
61
+ offset: 0,
62
+ type: 'gap-empty',
63
+ vars: `--_ct:${g_prefix}${PATH_SEPARATOR}0-gap-before;--_a:${anchor_prefix}${PATH_SEPARATOR}0${container_var}`,
64
+ is_first: true,
65
+ is_last: true,
66
+ has_pair: false
67
+ });
68
+ }
69
+ return result;
70
+ }
71
+
72
+ // Iterate visible indices (O(K)) instead of 0..count (O(N)) — at
73
+ // 1000 nodes with ~30 visible, this drops 1001 SvelteSet/SvelteMap
74
+ // reads per re-derivation to ~30. Filter stale indices >= count
75
+ // that may briefly remain after a node delete (until MO fires).
76
+ const sorted = [];
77
+ for (const i of visible) {
78
+ if (i >= 0 && i < count) sorted.push(i);
79
+ }
80
+ sorted.sort((a, b) => a - b);
81
+ if (sorted.length === 0) return result;
82
+
83
+ const offsets = [];
84
+ function add_offset(offset) {
85
+ if (!offsets.includes(offset)) offsets.push(offset);
86
+ }
87
+
88
+ // Emissions accumulate in ascending offset order, so iterating
89
+ // `offsets` later doesn't need a sort.
90
+ // Edge gap-before: emit if node 0 is in the near set AND the
91
+ // edge_map says the first node has reached the array's leading
92
+ // edge. edge_map is the scroll-aware BCR check that replaces
93
+ // the stale IO clip_map for edge nodes.
94
+ if (sorted[0] === 0 && edge_state?.first === true) {
95
+ add_offset(0);
96
+ }
97
+ // Mid gaps: between consecutive visible nodes. The gap at offset N
98
+ // sits between node N-1 and node N — emit when both are visible.
99
+ for (let i = 0; i < sorted.length - 1; i++) {
100
+ if (sorted[i + 1] === sorted[i] + 1) add_offset(sorted[i + 1]);
101
+ }
102
+ // Edge gap-after.last: same gate as gap-before but on the trailing edge.
103
+ if (sorted[sorted.length - 1] === count - 1 && edge_state?.last === true) {
104
+ add_offset(count);
105
+ }
106
+
107
+ for (const offset of offsets) {
108
+ const is_first = offset === 0;
109
+ const is_last = offset === count;
110
+
111
+ const g_anchor = is_first
112
+ ? `${g_prefix}${PATH_SEPARATOR}0-gap-before`
113
+ : `${g_prefix}${PATH_SEPARATOR}${offset - 1}-gap-after`;
114
+
115
+ let type, vars;
116
+ if (is_first || is_last) {
117
+ type = 'gap-edge';
118
+ const adjacent = is_first
119
+ ? `${anchor_prefix}${PATH_SEPARATOR}0`
120
+ : `${anchor_prefix}${PATH_SEPARATOR}${count - 1}`;
121
+ vars = `--_ct:${g_anchor};--_a:${adjacent}${container_var}${pair_vars}`;
122
+ } else {
123
+ type = 'gap-mid';
124
+ const p_anchor = `${anchor_prefix}${PATH_SEPARATOR}${offset - 1}`;
125
+ const n_anchor = `${anchor_prefix}${PATH_SEPARATOR}${offset}`;
126
+ vars = `--_ct:${g_anchor};--_p:${p_anchor};--_n:${n_anchor}${container_var}${pair_vars}`;
127
+ }
128
+
129
+ result.push({
130
+ key: `${path_str}-gap-${offset}`,
131
+ offset,
132
+ type,
133
+ vars,
134
+ is_first,
135
+ is_last,
136
+ has_pair
137
+ });
138
+ }
139
+ return result;
140
+ });
24
141
  </script>
25
142
 
26
143
  {#each my_gaps as gap (gap.key)}
@@ -30,7 +147,9 @@
30
147
  class:first={gap.is_first}
31
148
  class:last={gap.is_last}
32
149
  class:pair={gap.has_pair}
33
- style={gap.vars}
150
+ style={`${gap.vars};anchor-name:--gm-${gap.key}`}
151
+ data-gap-array-path={path_str}
152
+ data-gap-offset={gap.offset}
34
153
  contenteditable="false"
35
154
  >
36
155
  {#if gap.key === caret_gap_key}
@@ -73,15 +192,15 @@
73
192
  * --node-caret-boundary-x (per-axis override; clamps left/right only)
74
193
  * --node-caret-boundary-y (per-axis override; clamps top/bottom only)
75
194
  *
76
- * Row/column detection uses var(--row, 1) with the * 99999 multiplier
195
+ * Row/column detection uses var(--row, 1) with the * 9999999 multiplier
77
196
  * trick throughout. Shorthand:
78
197
  * --_R: var(--row, 1) (1 when row, 0 when column)
79
198
  * --_C: calc(1 - var(--row, 1)) (1 when column, 0 when row)
80
199
  *
81
- * Inside min(): + var(--_X) * 99999px makes a branch huge → min ignores it.
82
- * Inside max(): + var(--_X) * -99999px makes a branch tiny → max ignores it.
200
+ * Inside min(): + var(--_X) * 9999999px makes a branch huge → min ignores it.
201
+ * Inside max(): + var(--_X) * -9999999px makes a branch tiny → max ignores it.
83
202
  * Nested min/max inherit the outermost convention: if the root is min(),
84
- * all branches (even inside inner max()) use + 99999px to disable.
203
+ * all branches (even inside inner max()) use + 9999999px to disable.
85
204
  */
86
205
 
87
206
  /* Suppress caret blink during active click on a node gap. */
@@ -120,6 +239,21 @@
120
239
  margin: 0 !important; /* prevent unwanted margin from parent elements */
121
240
  }
122
241
 
242
+ /*
243
+ * position-anchor ties the marker's containing-block/scroll behavior to
244
+ * a specific anchor element, so the marker tracks its anchor's scroll
245
+ * container the same way NodeGap's .svedit-selectable does. Without it,
246
+ * markers inside a nested scroll container stay fixed in viewport space
247
+ * while the anchored nodes scroll away.
248
+ */
249
+ .gap-marker.gap-empty,
250
+ .gap-marker.gap-edge {
251
+ position-anchor: var(--_a);
252
+ }
253
+ .gap-marker.gap-mid {
254
+ position-anchor: var(--_p);
255
+ }
256
+
123
257
  /* --------------------------------------------------------------------- */
124
258
  /* Empty array */
125
259
  /* --------------------------------------------------------------------- */
@@ -130,9 +264,9 @@
130
264
  left: anchor(var(--_a) left);
131
265
  bottom: anchor(var(--_a) bottom);
132
266
  right: max(
133
- calc(anchor(var(--_a) right) + var(--_R) * -99999px),
134
- calc(anchor(var(--_a) right) + var(--_C) * -99999px),
135
- calc(anchor(var(--_a) left) - var(--_eg) + var(--_C) * -99999px)
267
+ calc(anchor(var(--_a) right) + var(--_R) * -9999999px),
268
+ calc(anchor(var(--_a) right) + var(--_C) * -9999999px),
269
+ calc(anchor(var(--_a) left) - var(--_eg) + var(--_C) * -9999999px)
136
270
  );
137
271
  }
138
272
 
@@ -141,37 +275,37 @@
141
275
  /* Column: spans from prev bottom to next top, with a centering branch */
142
276
  /* that guarantees at least --_gm height when the gap is too small. */
143
277
  /* Row: spans prev node. Row left/right use complex narrowing logic; */
144
- /* row branches all get + var(--_C) * 99999px so they're ignored in */
278
+ /* row branches all get + var(--_C) * 9999999px so they're ignored in */
145
279
  /* column layout. */
146
280
  /* --------------------------------------------------------------------- */
147
281
 
148
282
  .gap-marker.gap-mid {
149
283
  top: min(
150
- calc(anchor(var(--_p) bottom) + var(--_R) * 99999px),
284
+ calc(anchor(var(--_p) bottom) + var(--_R) * 9999999px),
151
285
  calc(
152
286
  (anchor(var(--_p) bottom) + anchor(var(--_n) top)) / 2
153
287
  - var(--_gm) / 2
154
- + var(--_R) * 99999px
288
+ + var(--_R) * 9999999px
155
289
  ),
156
- calc(anchor(var(--_p) top) + var(--_C) * 99999px)
290
+ calc(anchor(var(--_p) top) + var(--_C) * 9999999px)
157
291
  );
158
292
  bottom: min(
159
- calc(anchor(var(--_n) top) + var(--_R) * 99999px),
293
+ calc(anchor(var(--_n) top) + var(--_R) * 9999999px),
160
294
  calc(
161
295
  (anchor(var(--_p) bottom) + anchor(var(--_n) top)) / 2
162
296
  - var(--_gm) / 2
163
- + var(--_R) * 99999px
297
+ + var(--_R) * 9999999px
164
298
  ),
165
- calc(anchor(var(--_p) bottom) + var(--_C) * 99999px)
299
+ calc(anchor(var(--_p) bottom) + var(--_C) * 9999999px)
166
300
  );
167
301
  left: min(
168
- calc(anchor(var(--_p) left) + var(--_R) * 99999px),
169
- calc(anchor(var(--_p) right) + var(--_C) * 99999px),
302
+ calc(anchor(var(--_p) left) + var(--_R) * 9999999px),
303
+ calc(anchor(var(--_p) right) + var(--_C) * 9999999px),
170
304
  calc(
171
305
  (anchor(var(--_p) right) + anchor(var(--_n) left)) / 2
172
306
  - var(--_gm) / 2
173
307
  + max(0px, anchor(var(--_p) right) - anchor(var(--_n) left)) * 9999
174
- + var(--_C) * 99999px
308
+ + var(--_C) * 9999999px
175
309
  ),
176
310
  /* Wrap narrowing: centers marker in a gap-width region at prev_right.
177
311
  The + 0.5px disables this branch for zero-gap grids (items touching)
@@ -185,9 +319,19 @@
185
319
  ) / 2
186
320
  + max(0px, anchor(var(--_n) left) - anchor(var(--_p) right)) * 9999
187
321
  + max(0px, anchor(var(--_f) right) - anchor(var(--_s) left) + 0.5px) * 9999
188
- + var(--_C) * 99999px
322
+ + var(--_C) * 9999999px
323
+ ),
324
+ /* Safety clamp for wrap: pins marker inside CB when prev/next wrap
325
+ across rows (so the marker ends at the right edge of row 1).
326
+ Disabled in nowrap/horizontal-scroll where p and n are
327
+ side-by-side on the same row — there the other branches
328
+ position correctly and this clamp would wrongly force the
329
+ marker to the CB right. */
330
+ calc(
331
+ 100% - var(--_gm)
332
+ + max(0px, anchor(var(--_n) left) - anchor(var(--_p) right) + 0.5px) * 9999
333
+ + var(--_C) * 9999999px
189
334
  ),
190
- calc(100% - var(--_gm) + var(--_C) * 99999px),
191
335
  calc(
192
336
  100% - max(
193
337
  max(0px, anchor(var(--_s) left) - anchor(var(--_f) right)),
@@ -199,20 +343,28 @@
199
343
  - 0.5px
200
344
  ) * 9999
201
345
  + max(0px, anchor(var(--_n) left) - anchor(var(--_p) right)) * 9999
202
- + var(--_C) * 99999px
346
+ + var(--_C) * 9999999px
203
347
  )
204
348
  );
205
349
  right: max(
206
- calc(0px + var(--_C) * -99999px),
350
+ /* CB-right floor, disabled in nowrap/horizontal-scroll where n
351
+ extends past CB right (p_right - n_left > 0 in right context,
352
+ equivalent to n_left_body > p_right_body in layout). In that
353
+ case the marker must extend past CB right to reach the gap,
354
+ so right must be allowed to go negative. */
355
+ calc(
356
+ 0px + var(--_C) * -9999999px
357
+ - max(0px, anchor(var(--_p) right) - anchor(var(--_n) left) + 0.5px) * 9999
358
+ ),
207
359
  min(
208
- calc(anchor(var(--_p) right) + var(--_R) * 99999px),
360
+ calc(anchor(var(--_p) right) + var(--_R) * 9999999px),
209
361
  calc(
210
- anchor(var(--_n) left) + var(--_C) * 99999px
362
+ anchor(var(--_n) left) + var(--_C) * 9999999px
211
363
  ),
212
364
  calc(
213
365
  (anchor(var(--_p) right) + anchor(var(--_n) left)) / 2
214
366
  - var(--_gm) / 2
215
- + var(--_C) * 99999px
367
+ + var(--_C) * 9999999px
216
368
  ),
217
369
  max(
218
370
  /* Symmetric right-side narrowing. The + 0.5px mirrors the left
@@ -227,7 +379,7 @@
227
379
  )
228
380
  ) / 2
229
381
  - max(0px, anchor(var(--_s) left) - anchor(var(--_f) right) + 0.5px) * 9999
230
- + var(--_C) * 99999px
382
+ + var(--_C) * 9999999px
231
383
  ),
232
384
  calc(
233
385
  anchor(var(--_p) right) - var(--_gm)
@@ -236,21 +388,21 @@
236
388
  - (max(0px, anchor(var(--_f) right) - anchor(var(--_s) left)))
237
389
  + 0.5px
238
390
  ) * 9999
239
- + var(--_C) * 99999px
391
+ + var(--_C) * 9999999px
240
392
  ),
241
393
  calc(
242
394
  anchor(var(--_p) right) - var(--_gm)
243
395
  - max(0px, anchor(var(--_f) right) - anchor(var(--_s) left)) * 9999
244
- + var(--_C) * 99999px
396
+ + var(--_C) * 9999999px
245
397
  ),
246
398
  calc(
247
399
  anchor(var(--_p) right)
248
400
  - (anchor(var(--_n) left) - anchor(var(--_p) right)) * 9999
249
- + var(--_C) * 99999px
401
+ + var(--_C) * 9999999px
250
402
  ),
251
403
  min(
252
- calc(anchor(var(--_c) right) + var(--_C) * 99999px),
253
- calc(anchor(var(--_p) right) - var(--_eg) + var(--_C) * 99999px)
404
+ calc(anchor(var(--_c) right) + var(--_C) * 9999999px),
405
+ calc(anchor(var(--_p) right) - var(--_eg) + var(--_C) * 9999999px)
254
406
  )
255
407
  )
256
408
  )
@@ -271,20 +423,20 @@
271
423
  --_b-t: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) top, 0px);
272
424
  --_b-l: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) left, 0px);
273
425
  top: min(
274
- calc(anchor(var(--_a) top) + var(--_C) * 99999px),
275
- calc(max(var(--_b-t), calc(anchor(var(--_a) top) - var(--_gm))) + var(--_R) * 99999px)
426
+ calc(anchor(var(--_a) top) + var(--_C) * 9999999px),
427
+ calc(max(var(--_b-t), calc(anchor(var(--_a) top) - var(--_gm))) + var(--_R) * 9999999px)
276
428
  );
277
429
  bottom: min(
278
- calc(anchor(var(--_a) bottom) + var(--_C) * 99999px),
279
- calc(anchor(var(--_a) top) + var(--_R) * 99999px)
430
+ calc(anchor(var(--_a) bottom) + var(--_C) * 9999999px),
431
+ calc(anchor(var(--_a) top) + var(--_R) * 9999999px)
280
432
  );
281
433
  left: min(
282
- calc(anchor(var(--_a) left) + var(--_R) * 99999px),
283
- calc(max(var(--_b-l), calc(anchor(var(--_a) left) - var(--_gm))) + var(--_C) * 99999px)
434
+ calc(anchor(var(--_a) left) + var(--_R) * 9999999px),
435
+ calc(max(var(--_b-l), calc(anchor(var(--_a) left) - var(--_gm))) + var(--_C) * 9999999px)
284
436
  );
285
437
  right: min(
286
- calc(anchor(var(--_a) right) + var(--_R) * 99999px),
287
- calc(anchor(var(--_a) left) + var(--_C) * 99999px)
438
+ calc(anchor(var(--_a) right) + var(--_R) * 9999999px),
439
+ calc(anchor(var(--_a) left) + var(--_C) * 9999999px)
288
440
  );
289
441
  }
290
442
 
@@ -295,51 +447,57 @@
295
447
  .gap-edge.last {
296
448
  --_b-b: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom, 0px);
297
449
  --_b-r: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right, 0px);
298
- --_b-bt: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom, 99999px);
299
- --_b-rl: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right, 99999px);
450
+ --_b-bt: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom, 9999999px);
451
+ --_b-rl: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right, 9999999px);
300
452
  top: min(
301
- calc(anchor(var(--_a) top) + var(--_C) * 99999px),
453
+ calc(anchor(var(--_a) top) + var(--_C) * 9999999px),
302
454
  calc(
303
455
  min(
304
456
  anchor(var(--_a) bottom),
305
457
  calc(var(--_b-bt) - var(--_gm))
306
- ) + var(--_R) * 99999px
458
+ ) + var(--_R) * 9999999px
307
459
  )
308
460
  );
309
461
  bottom: min(
310
- calc(anchor(var(--_a) bottom) + var(--_C) * 99999px),
311
- calc(max(var(--_b-b), calc(anchor(var(--_a) bottom) - var(--_gm))) + var(--_R) * 99999px)
462
+ calc(anchor(var(--_a) bottom) + var(--_C) * 9999999px),
463
+ calc(max(var(--_b-b), calc(anchor(var(--_a) bottom) - var(--_gm))) + var(--_R) * 9999999px)
312
464
  );
313
465
  left: min(
314
- calc(anchor(var(--_a) left) + var(--_R) * 99999px),
466
+ calc(anchor(var(--_a) left) + var(--_R) * 9999999px),
315
467
  calc(
316
468
  min(
317
469
  anchor(var(--_a) right),
318
470
  calc(var(--_b-rl) - var(--_gm))
319
- ) + var(--_C) * 99999px
471
+ ) + var(--_C) * 9999999px
320
472
  ),
321
- calc(100% - var(--_gm) + var(--_C) * 99999px)
473
+ calc(100% - var(--_gm) + var(--_C) * 9999999px)
322
474
  );
323
475
  right: max(
324
- calc(var(--_b-r) + var(--_C) * -99999px),
325
- calc(anchor(var(--_a) right) + var(--_R) * -99999px),
326
- calc(anchor(var(--_a) right) - var(--_gm) + var(--_C) * -99999px),
327
- calc(anchor(var(--_c) right) + var(--_C) * -99999px)
476
+ calc(var(--_b-r) + var(--_C) * -9999999px),
477
+ calc(anchor(var(--_a) right) + var(--_R) * -9999999px),
478
+ calc(anchor(var(--_a) right) - var(--_gm) + var(--_C) * -9999999px),
479
+ /* Column / wrap-layout fill: when the last item sits within
480
+ the container (non-overflow), max picks anchor(--_c right)
481
+ and the marker stretches to the containers trailing edge.
482
+ In row-overflow this branch is dominated by anchor(--_a right)
483
+ which is smaller, so the marker follows the trailing node
484
+ past the container. */
485
+ calc(anchor(var(--_c) right) + var(--_C) * -9999999px)
328
486
  );
329
487
  }
330
488
 
331
489
  /* --------------------------------------------------------------------- */
332
490
  /* Trailing gap in row with 2+ items: complex narrowing using --_f/--_s */
333
491
  /* Overrides .gap-edge.last — must re-include col branch for both left */
334
- /* (min: + 99999px to disable) and right (max: * -99999px to disable). */
492
+ /* (min: + 9999999px to disable) and right (max: * -9999999px to disable). */
335
493
  /* --------------------------------------------------------------------- */
336
494
 
337
495
  /* Purpose of this + 0.5px: disable for zero-gap grids (see .gap-mid comment). */
338
496
  .gap-marker.gap-edge.last.pair {
339
497
  left: min(
340
- calc(anchor(var(--_a) left) + var(--_R) * 99999px),
341
- calc(anchor(var(--_a) right) + var(--_C) * 99999px),
342
- calc(var(--_b-rl) - var(--_gm) + var(--_C) * 99999px),
498
+ calc(anchor(var(--_a) left) + var(--_R) * 9999999px),
499
+ calc(anchor(var(--_a) right) + var(--_C) * 9999999px),
500
+ calc(var(--_b-rl) - var(--_gm) + var(--_C) * 9999999px),
343
501
  calc(
344
502
  anchor(var(--_a) right)
345
503
  + (max(0px, anchor(var(--_s) left) - anchor(var(--_f) right))) / 2
@@ -349,9 +507,18 @@
349
507
  ) / 2
350
508
  + max(0px, anchor(var(--_f) right) - anchor(var(--_s) left)) * 9999
351
509
  + max(0px, anchor(var(--_a) right) - anchor(var(--_c) right) + 0.5px) * 9999
352
- + var(--_C) * 99999px
510
+ + var(--_C) * 9999999px
511
+ ),
512
+ /* Safety clamp for wrap: pins marker inside CB when items 0 and 1
513
+ wrap across rows. Disabled in nowrap/horizontal-scroll where
514
+ items 0 and 1 are side-by-side on the same row — there the
515
+ anchor-based branches position correctly and this clamp would
516
+ wrongly force the marker to the CB right. */
517
+ calc(
518
+ 100% - var(--_gm)
519
+ + max(0px, anchor(var(--_s) left) - anchor(var(--_f) right) + 0.5px) * 9999
520
+ + var(--_C) * 9999999px
353
521
  ),
354
- calc(100% - var(--_gm) + var(--_C) * 99999px),
355
522
  calc(
356
523
  100% - max(
357
524
  max(0px, anchor(var(--_s) left) - anchor(var(--_f) right)),
@@ -362,12 +529,12 @@
362
529
  - (anchor(var(--_c) right) - anchor(var(--_a) right))
363
530
  - 0.5px
364
531
  ) * 9999
365
- + var(--_C) * 99999px
532
+ + var(--_C) * 9999999px
366
533
  )
367
534
  );
368
535
  right: max(
369
- calc(anchor(var(--_a) right) + var(--_R) * -99999px),
370
- calc(var(--_b-r) + var(--_C) * -99999px),
536
+ calc(anchor(var(--_a) right) + var(--_R) * -9999999px),
537
+ calc(var(--_b-r) + var(--_C) * -9999999px),
371
538
  calc(
372
539
  anchor(var(--_a) right)
373
540
  - (
@@ -379,7 +546,7 @@
379
546
  ) / 2
380
547
  - max(0px, anchor(var(--_s) left) - anchor(var(--_f) right)) * 9999
381
548
  - max(0px, anchor(var(--_c) right) - anchor(var(--_a) right) + 0.5px) * 9999
382
- + var(--_C) * -99999px
549
+ + var(--_C) * -9999999px
383
550
  ),
384
551
  calc(
385
552
  anchor(var(--_a) right) - var(--_gm)
@@ -388,16 +555,16 @@
388
555
  - (max(0px, anchor(var(--_f) right) - anchor(var(--_s) left)))
389
556
  + 0.5px
390
557
  ) * 9999
391
- + var(--_C) * -99999px
558
+ + var(--_C) * -9999999px
392
559
  ),
393
560
  calc(
394
561
  anchor(var(--_a) right) - var(--_gm)
395
562
  - max(0px, anchor(var(--_f) right) - anchor(var(--_s) left)) * 9999
396
- + var(--_C) * -99999px
563
+ + var(--_C) * -9999999px
397
564
  ),
398
565
  min(
399
- calc(anchor(var(--_c) right) + var(--_C) * -99999px),
400
- calc(anchor(var(--_a) right) - var(--_eg) + var(--_C) * -99999px)
566
+ calc(anchor(var(--_c) right) + var(--_C) * -9999999px),
567
+ calc(anchor(var(--_a) right) - var(--_eg) + var(--_C) * -9999999px)
401
568
  )
402
569
  );
403
570
  }
@@ -420,20 +587,20 @@
420
587
  &:not(.gap-empty)::before {
421
588
  --_mi: var(--node-caret-marker-inset, 2px);
422
589
  top: min(
423
- calc(50% + var(--_R) * 99999px),
424
- calc(var(--_mi) + var(--_C) * 99999px)
590
+ calc(50% + var(--_R) * 9999999px),
591
+ calc(var(--_mi) + var(--_C) * 9999999px)
425
592
  );
426
593
  bottom: min(
427
- calc(50% + var(--_R) * 99999px),
428
- calc(var(--_mi) + var(--_C) * 99999px)
594
+ calc(50% + var(--_R) * 9999999px),
595
+ calc(var(--_mi) + var(--_C) * 9999999px)
429
596
  );
430
597
  left: min(
431
- calc(var(--_mi) + var(--_R) * 99999px),
432
- calc(50% + var(--_C) * 99999px)
598
+ calc(var(--_mi) + var(--_R) * 9999999px),
599
+ calc(50% + var(--_C) * 9999999px)
433
600
  );
434
601
  right: min(
435
- calc(var(--_mi) + var(--_R) * 99999px),
436
- calc(50% + var(--_C) * 99999px)
602
+ calc(var(--_mi) + var(--_R) * 9999999px),
603
+ calc(50% + var(--_C) * 9999999px)
437
604
  );
438
605
  border-top: calc(var(--_C) * 1px) dashed var(--node-caret-gap-color, var(--svedit-canvas-stroke));
439
606
  border-left: calc(var(--_R) * 1px) dashed var(--node-caret-gap-color, var(--svedit-canvas-stroke));
@@ -471,7 +638,7 @@
471
638
  }
472
639
  }
473
640
 
474
- /* Debugging styles */
641
+ /* Debugging styles - DO NOT CHANGE OR REMOVE */
475
642
  /* :global([data-type="node_array"]) {
476
643
  outline: 0.1px solid green;
477
644
  }
@@ -5,8 +5,10 @@ type NodeGapMarkers = {
5
5
  };
6
6
  declare const NodeGapMarkers: import("svelte").Component<{
7
7
  path: any;
8
+ count: any;
8
9
  }, {}, "">;
9
10
  type $$ComponentProps = {
10
11
  path: any;
12
+ count: any;
11
13
  };
12
14
  //# sourceMappingURL=NodeGapMarkers.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeGapMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGapMarkers.svelte.js"],"names":[],"mappings":";;;;;AA0CA;UArB0B,GAAG;WAqBgC;wBArB3C;IAAE,IAAI,EAAE,GAAG,CAAA;CAAE"}
1
+ {"version":3,"file":"NodeGapMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGapMarkers.svelte.js"],"names":[],"mappings":";;;;;AAgKA;UA3H0B,GAAG;WAAS,GAAG;WA2HoB;wBA3H3C;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE"}
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import { getContext } from 'svelte';
3
+ import { serialize_path } from './utils.js';
3
4
 
4
5
  const svedit = getContext('svedit');
5
6
  let selected_node_paths = $derived(get_selected_node_paths());
@@ -22,13 +23,13 @@
22
23
  {#if svedit.session.selection?.type === 'property'}
23
24
  <div
24
25
  class="selected-property-overlay"
25
- style="position-anchor: --{svedit.session.selection.path.join('-')};"
26
+ style="position-anchor: --{serialize_path(svedit.session.selection.path)};"
26
27
  ></div>
27
28
  {/if}
28
29
 
29
30
  {#if selected_node_paths}
30
- {#each selected_node_paths as path (path.join('-'))}
31
- <div class="selected-node-overlay" style="position-anchor: --{path.join('-')};"></div>
31
+ {#each selected_node_paths as path (serialize_path(path))}
32
+ <div class="selected-node-overlay" style="position-anchor: --{serialize_path(path)};"></div>
32
33
  {/each}
33
34
  {/if}
34
35
 
@@ -1 +1 @@
1
- {"version":3,"file":"NodeSelectionMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeSelectionMarkers.svelte.js"],"names":[],"mappings":";;;;;AAwCA,8FAAmE"}
1
+ {"version":3,"file":"NodeSelectionMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeSelectionMarkers.svelte.js"],"names":[],"mappings":";;;;;AA0CA,8FAAmE"}
@@ -52,7 +52,18 @@ export default class Session {
52
52
  * @returns {string}
53
53
  */
54
54
  get document_id(): string;
55
- validate_doc(): void;
55
+ /**
56
+ * Validates the parts of a transaction result that can be affected by the transaction.
57
+ *
58
+ * This is intentionally narrower than full document validation. It validates all
59
+ * created/modified nodes, plus nodes that still reference created, modified, or
60
+ * deleted nodes. That catches local node invariants and dangling references left
61
+ * behind by deletes without scanning every node on every apply.
62
+ *
63
+ * @param {Transaction} transaction - The transaction result to validate
64
+ * @throws {Error} Throws if the transaction result is invalid
65
+ */
66
+ validate_transaction_result(transaction: Transaction): void;
56
67
  generate_id(): any;
57
68
  /**
58
69
  * Initialize commands and keymap for this session.
@@ -1 +1 @@
1
- {"version":3,"file":"Session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Session.svelte.js"],"names":[],"mappings":"AA8BA;;;GAGG;AAEH;IA8BC;;;;;;OAMG;IACH,oBANW,cAAc,OACd,QAAQ,UACR,MAAM,YAEd;QAA4B,SAAS,GAA7B,SAAS;KACnB,EAWA;IA3CD,6BAA6B;IAC7B,QADW,cAAc,CACH;IAEtB,uBAAuB;IACvB,KADW,QAAQ,CACA;IAEnB,kBAAkB;IAClB,QADW,GAAG,CACQ;IAEtB,eAAyB;IACzB,sBAA+B;IAC/B,wBAA2C;IAI3C,aAA0B;IAC1B,WAAwB;IAGxB,kBAA6C;IAC7C,kBAAkE;IAGlE,mBAAmD;IACnD,gCAA6E;IA6B7E;;;;OAIG;IACH,qBAHW,SAAS,GAAG,IAAI,EAM1B;IAhBD;;;OAGG;IACH,iBAFa,SAAS,GAAG,IAAI,CAI5B;IAYD;;;;;;OAMG;IACH,4BAEC;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED,qBAIC;IAED,mBAMC;IAED;;;;;;;;;OASG;IACH,6BAFW,MAAM,QAQhB;IAED,sCAKC;IAGD,yBAkBC;IAED;;;;OAIG;IACH,UAFa,WAAW,CAKvB;IAED;;;;;;;OAOG;IACH,mBAJW,WAAW,cAEnB;QAA0B,KAAK,GAAvB,OAAO;KACjB,QA4CA;IAED,aAgBC;IAED,aAaC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAlBW,YAAY,GAAC,MAAM,GACjB,GAAG,CAmBf;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAHW,YAAY,GACV;QAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAIzD;IAED;;;;;OAKG;IACH,WAHW,GAAG,GACD,QAAQ,CAIpB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,cACN,SAAS,GACP,OAAO,CAcnB;IAED;;;;;OAKG;IACH,uCAHW,SAAS,GACP,SAAS,GAAC,IAAI,CAe1B;IAED;;;;;;OAMG;IACH,oCAHW,MAAM,GACJ,UAAU,GAAC,IAAI,CAI3B;IAED;;;;MA6BC;IAGD,kCAOC;IAED,0BAOC;IAED,sBAmCC;IAED;;;;;;;;;;;OAWG;IACH,kBAJW,MAAM,GACJ,KAAK,CAAC,YAAY,CAAC,CAK/B;IAED;;;;;;;OAOG;IACH,WAFa,QAAQ,CAWpB;IAID,gDAEC;IAGD,uCAEC;IAGD;;;OAGG;IACH,8BAHW,MAAM,GACJ,MAAM,EAAE,CAOpB;;CACD;;;;;gBAzfa,SAAS;;oCAPb,cAAc;8BAAd,cAAc;+BAAd,cAAc;wBAzBA,yBAAyB;kCAyBvC,cAAc;8BAAd,cAAc;gCAAd,cAAc;kCAAd,cAAc;4BAAd,cAAc"}
1
+ {"version":3,"file":"Session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Session.svelte.js"],"names":[],"mappings":"AAgCA;;;GAGG;AAEH;IA+BC;;;;;;OAMG;IACH,oBANW,cAAc,OACd,QAAQ,UACR,MAAM,YAEd;QAA4B,SAAS,GAA7B,SAAS;KACnB,EAYA;IA7CD,6BAA6B;IAC7B,QADW,cAAc,CACH;IAEtB,uBAAuB;IACvB,KADW,QAAQ,CACA;IAEnB,kBAAkB;IAClB,QADW,GAAG,CACQ;IAEtB,eAAyB;IACzB,sBAA+B;IAC/B,wBAA2C;IAI3C,aAA0B;IAC1B,WAAwB;IAGxB,kBAA6C;IAC7C,kBAAkE;IAGlE,mBAAmD;IACnD,gCAA6E;IA+B7E;;;;OAIG;IACH,qBAHW,SAAS,GAAG,IAAI,EAM1B;IAhBD;;;OAGG;IACH,iBAFa,SAAS,GAAG,IAAI,CAI5B;IAYD;;;;;;OAMG;IACH,4BAEC;IAED;;;OAGG;IACH,mBAFa,MAAM,CAIlB;IAED;;;;;;;;;;OAUG;IACH,yCAHW,WAAW,QA4BrB;IAED,mBAMC;IAED;;;;;;;;;OASG;IACH,6BAFW,MAAM,QAQhB;IAED,sCAKC;IAGD,yBAkBC;IAED;;;;OAIG;IACH,UAFa,WAAW,CAKvB;IAED;;;;;;;OAOG;IACH,mBAJW,WAAW,cAEnB;QAA0B,KAAK,GAAvB,OAAO;KACjB,QA6CA;IAED,aAgBC;IAED,aAaC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAlBW,YAAY,GAAC,MAAM,GACjB,GAAG,CAmBf;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAHW,YAAY,GACV;QAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAIzD;IAED;;;;;OAKG;IACH,WAHW,GAAG,GACD,QAAQ,CAIpB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,cACN,SAAS,GACP,OAAO,CAcnB;IAED;;;;;OAKG;IACH,uCAHW,SAAS,GACP,SAAS,GAAC,IAAI,CAe1B;IAED;;;;;;OAMG;IACH,oCAHW,MAAM,GACJ,UAAU,GAAC,IAAI,CAI3B;IAED;;;;MA6BC;IAGD,kCAOC;IAED,0BAOC;IAED,sBAmCC;IAED;;;;;;;;;;;OAWG;IACH,kBAJW,MAAM,GACJ,KAAK,CAAC,YAAY,CAAC,CAK/B;IAED;;;;;;;OAOG;IACH,WAFa,QAAQ,CAWpB;IAID,gDAEC;IAGD,uCAEC;IAGD;;;OAGG;IACH,8BAHW,MAAM,GACJ,MAAM,EAAE,CAOpB;;CACD;;;;;gBA5hBa,SAAS;;oCAPb,cAAc;8BAAd,cAAc;+BAAd,cAAc;wBA3BA,yBAAyB;kCA2BvC,cAAc;8BAAd,cAAc;gCAAd,cAAc;kCAAd,cAAc;4BAAd,cAAc"}