svedit 0.9.0 → 0.11.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 (72) hide show
  1. package/README.md +476 -364
  2. package/dist/AnnotatedTextProperty.svelte +40 -10
  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 +48 -6
  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 +59 -48
  13. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  14. package/dist/NodeCaret.svelte +0 -7
  15. package/dist/NodeGap.svelte +208 -118
  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 +496 -221
  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 +69 -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 +6 -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/paste_utils.d.ts +46 -0
  40. package/dist/paste_utils.d.ts.map +1 -0
  41. package/dist/paste_utils.js +167 -0
  42. package/dist/styles/svedit-animations.css +8 -0
  43. package/dist/styles/svedit-colors.css +1 -0
  44. package/dist/types.d.ts +46 -3
  45. package/dist/utils.d.ts +52 -0
  46. package/dist/utils.d.ts.map +1 -1
  47. package/dist/utils.js +109 -3
  48. package/package.json +3 -2
  49. package/src/lib/AnnotatedTextProperty.svelte +40 -10
  50. package/src/lib/Command.svelte.js +48 -6
  51. package/src/lib/CustomProperty.svelte +20 -9
  52. package/src/lib/Node.svelte +7 -5
  53. package/src/lib/NodeArrayProperty.svelte +59 -48
  54. package/src/lib/NodeCaret.svelte +0 -7
  55. package/src/lib/NodeGap.svelte +208 -118
  56. package/src/lib/NodeGapMarkers.svelte +251 -84
  57. package/src/lib/NodeSelectionMarkers.svelte +4 -3
  58. package/src/lib/Session.svelte.js +40 -3
  59. package/src/lib/Svedit.svelte +496 -221
  60. package/src/lib/Transaction.svelte.js +103 -61
  61. package/src/lib/doc_utils.js +276 -10
  62. package/src/lib/index.js +6 -1
  63. package/src/lib/node_visibility.svelte.js +718 -0
  64. package/src/lib/paste_utils.js +167 -0
  65. package/src/lib/styles/svedit-animations.css +8 -0
  66. package/src/lib/styles/svedit-colors.css +1 -0
  67. package/src/lib/types.d.ts +46 -3
  68. package/src/lib/utils.js +109 -3
  69. package/dist/node_gap_computation.svelte.d.ts +0 -5
  70. package/dist/node_gap_computation.svelte.d.ts.map +0 -1
  71. package/dist/node_gap_computation.svelte.js +0 -621
  72. package/src/lib/node_gap_computation.svelte.js +0 -621
@@ -1,5 +1,33 @@
1
+ <script module>
2
+ function cycle_z_index(/** @type {MouseEvent} */ e) {
3
+ const el = /** @type {HTMLElement} */ (e.currentTarget);
4
+ if (el.hasAttribute('data-sent-to-back')) {
5
+ document.querySelectorAll('.svedit-selectable[data-sent-to-back]').forEach((prev) => {
6
+ prev.removeAttribute('data-sent-to-back');
7
+ });
8
+ }
9
+ el.setAttribute('data-sent-to-back', '');
10
+ }
11
+ </script>
12
+
1
13
  <script>
14
+ import { serialize_path } from './utils.js';
15
+ import { getContext } from 'svelte';
16
+
2
17
  /**
18
+ * ┌─────────────────────────────────────────────────────────────────┐
19
+ * │ MUST RULES — do not violate when modifying this file │
20
+ * ├─────────────────────────────────────────────────────────────────┤
21
+ * │ 1. Edge gaps (gap-before at offset 0 / gap-after.last) MUST │
22
+ * │ render OUTSIDE the node-array container — they extend into │
23
+ * │ the whitespace above/below (column) or left/right (row) of │
24
+ * │ the first/last node. They only clamp when the consumer │
25
+ * │ explicitly opts in via --node-caret-boundary(-x/-y). │
26
+ * │ 2. Gaps MUST NEVER overlap nodes. They render strictly in the │
27
+ * │ whitespace between nodes (mid gaps) or outside the node │
28
+ * │ array bounds (edge gaps). Never on top of a node. │
29
+ * └─────────────────────────────────────────────────────────────────┘
30
+ *
3
31
  * Invisible keyboard caret selectable and gap hit area.
4
32
  *
5
33
  * Rendered as a sibling of Node elements inside NodeArrayProperty,
@@ -9,9 +37,10 @@
9
37
  *
10
38
  * Always present in the DOM when editable (stable structure for
11
39
  * selection anchoring, scrollTo, etc.). Anchor positioning is
12
- * activated lazily via the `positioned` prop — only gaps near the
13
- * viewport pay the layout cost of anchor() resolution. Off-screen
14
- * gaps are zero-size static elements with no layout cost.
40
+ * activated lazily via the `.positioned` class, toggled imperatively
41
+ * by the IO callback / MO / bootstrap in node_visibility — keeps
42
+ * NodeGap allocation-free of per-instance Svelte signals, which
43
+ * matters at 1000+ NodeGaps per scroll frame.
15
44
  *
16
45
  * `position-visibility: anchors-visible` does NOT skip anchor
17
46
  * resolution — the browser resolves all anchor() then hides the
@@ -20,42 +49,57 @@
20
49
  *
21
50
  * Row/column detection uses var(--row, 1) with the * 99999 multiplier
22
51
  * trick — no @container style() queries, works in all browsers.
52
+ *
53
+ * If you override this component via `system_components.node_gap`, make
54
+ * sure your custom component also handles read-only mode by rendering a
55
+ * plain `.node-gap` placeholder without editable internals.
23
56
  */
24
- let { array_path, offset, count, empty = false, positioned = true } = $props();
57
+ const svedit = getContext('svedit');
58
+ let { array_path, offset, count, empty = false } = $props();
59
+ let is_editable = $derived(svedit.editable);
25
60
 
26
61
  let is_first = $derived(offset === 0);
27
62
  let is_last = $derived(offset === count);
28
63
  let type = $derived(is_first ? 'gap-before' : 'gap-after');
29
64
 
30
65
  let gap_style = $derived.by(() => {
31
- const arr = array_path.join('-');
66
+ if (!is_editable) return '';
32
67
  const prev_idx = offset - 1;
33
- const pa = is_first ? `--${arr}-0` : `--${arr}-${prev_idx}`;
34
- const next = `--${arr}-${offset}`;
35
- const container = `--${arr}`;
68
+ const pa = is_first
69
+ ? `--${serialize_path([...array_path, 0])}`
70
+ : `--${serialize_path([...array_path, prev_idx])}`;
71
+ const next = `--${serialize_path([...array_path, offset])}`;
72
+ const container = `--${serialize_path(array_path)}`;
36
73
  return `--_pa:${pa};--_next:${next};--_container:${container}`;
37
74
  });
38
75
 
39
76
  let anchor_name = $derived.by(() => {
40
- const arr = array_path.join('-');
41
- if (is_first) return `--g-${arr}-0-gap-before`;
42
- return `--g-${arr}-${offset - 1}-gap-after`;
77
+ if (!is_editable) return '';
78
+ if (is_first) return `--g-${serialize_path([...array_path, 0])}-gap-before`;
79
+ return `--g-${serialize_path([...array_path, offset - 1])}-gap-after`;
43
80
  });
44
81
  </script>
45
82
 
46
- <div
47
- class="node-gap {type}"
48
- class:empty
49
- class:last={is_last}
50
- class:positioned
51
- data-type={type}
52
- data-gap-array-path={array_path.join('.')}
53
- data-gap-offset={offset}
54
- style={gap_style}
55
- >
56
- <div class="svedit-selectable" style="anchor-name:{anchor_name}"><br /></div>
57
- </div>
58
-
83
+ {#if is_editable}
84
+ <div
85
+ class="node-gap"
86
+ class:gap-before={is_first}
87
+ class:gap-after={!is_first}
88
+ class:empty
89
+ class:last={is_last}
90
+ data-type={type}
91
+ data-gap-array-path={serialize_path(array_path)}
92
+ data-gap-offset={offset}
93
+ style={gap_style}
94
+ >
95
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
96
+ <div class="svedit-selectable" style="anchor-name:{anchor_name}" onpointerdown={cycle_z_index}>
97
+ <br />
98
+ </div>
99
+ </div>
100
+ {:else}
101
+ <div class="node-gap"></div>
102
+ {/if}
59
103
 
60
104
  <style>
61
105
  .node-gap {
@@ -70,7 +114,7 @@
70
114
  /* Un-positioned: minimal in-DOM presence, no anchor resolution */
71
115
  /* ------------------------------------------------------------------ */
72
116
 
73
- .node-gap:not(.positioned) .svedit-selectable {
117
+ :global(.node-gap:not(.positioned) .svedit-selectable) {
74
118
  position: absolute;
75
119
  pointer-events: none;
76
120
  width: 0;
@@ -100,34 +144,64 @@
100
144
  * --node-caret-boundary-y override per-axis, falling back to
101
145
  * --node-caret-boundary when unset.
102
146
  */
103
- .node-gap.positioned {
104
- --_s-t: anchor(var(--_pa) top);
105
- --_s-b: anchor(var(--_pa) bottom);
106
- --_s-l: anchor(var(--_pa) left);
107
- --_s-r: anchor(var(--_pa) right);
147
+ :global(.node-gap.positioned) {
148
+ /* Fallback 9999999px: when --_pa is orphan (node briefly missing during
149
+ edits), anchor() without a fallback invalidates the custom property
150
+ and `top` falls back to 0, placing the gap at viewport top as a
151
+ giant overlay. 9999999px ensures orphan anchors produce huge values
152
+ that min() excludes instead.
153
+ LIMIT: documents taller or wider than 9999999px will re-surface
154
+ the reported giant-overlay bug — the fallback must exceed the
155
+ containing block's dimensions to land off-screen. If you need to
156
+ support larger documents, bump this value here and in the matching
157
+ `* 9999999px` branch-disable trick throughout this file (and in
158
+ NodeGapMarkers.svelte). Stay below ~33M px to avoid Blink's
159
+ LayoutUnit ceiling. */
160
+ --_s-t: anchor(var(--_pa) top, 9999999px);
161
+ --_s-b: anchor(var(--_pa) bottom, 9999999px);
162
+ --_s-l: anchor(var(--_pa) left, 9999999px);
163
+ --_s-r: anchor(var(--_pa) right, 9999999px);
108
164
  }
109
- .positioned.gap-before:not(.empty) {
110
- --_b-t: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) top, 0px);
111
- --_b-l: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) left, 0px);
165
+ :global(.node-gap.positioned.gap-before:not(.empty)) {
166
+ --_b-t: anchor(
167
+ var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) top,
168
+ 0px
169
+ );
170
+ --_b-l: anchor(
171
+ var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) left,
172
+ 0px
173
+ );
112
174
  }
113
- .positioned.gap-after:not(.last) {
175
+ :global(.node-gap.positioned.gap-after:not(.last)) {
114
176
  --_n-t: anchor(var(--_next) top);
115
177
  --_n-l: anchor(var(--_next) left);
116
178
  --_c-r: anchor(var(--_container) right);
117
179
  }
118
- .positioned.gap-after.last,
119
- .positioned.gap-before.empty {
180
+ :global(.node-gap.positioned.gap-after.last),
181
+ :global(.node-gap.positioned.gap-before.empty) {
120
182
  --_c-t: anchor(var(--_container) top);
121
183
  --_c-b: anchor(var(--_container) bottom);
122
184
  --_c-l: anchor(var(--_container) left);
123
185
  --_c-r: anchor(var(--_container) right);
124
- --_b-b: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom, 0px);
125
- --_b-r: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right, 0px);
126
- --_b-bt: anchor(var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom, 99999px);
127
- --_b-rl: anchor(var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right, 99999px);
186
+ --_b-b: anchor(
187
+ var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom,
188
+ 0px
189
+ );
190
+ --_b-r: anchor(
191
+ var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right,
192
+ 0px
193
+ );
194
+ --_b-bt: anchor(
195
+ var(--node-caret-boundary-y, var(--node-caret-boundary, --_no-boundary)) bottom,
196
+ 9999999px
197
+ );
198
+ --_b-rl: anchor(
199
+ var(--node-caret-boundary-x, var(--node-caret-boundary, --_no-boundary)) right,
200
+ 9999999px
201
+ );
128
202
  }
129
203
 
130
- .positioned .svedit-selectable {
204
+ :global(.node-gap.positioned .svedit-selectable) {
131
205
  --_eg: var(--node-caret-edge-gap, 24px);
132
206
  --_gm: var(--node-caret-gap-min-size, 16px);
133
207
  --_R: var(--row, 1);
@@ -141,64 +215,65 @@
141
215
  cursor: pointer;
142
216
  }
143
217
 
218
+ :global(.node-gap.positioned .svedit-selectable[data-sent-to-back]) {
219
+ z-index: 0;
220
+ }
221
+
144
222
  /* ------------------------------------------------------------------ */
145
223
  /* Merged column / row layout positioning */
146
224
  /* */
147
225
  /* Uses var(--row, 1) with the * 99999 multiplier trick: */
148
226
  /* --_R = var(--row, 1) → 1 in row, 0 in column */
149
227
  /* --_C = calc(1 - var(--row, 1))→ 1 in column, 0 in row */
150
- /* Inside min(), + var(--_R) * 99999px disables a col branch in row, */
151
- /* + var(--_C) * 99999px disables a row branch in column. */
228
+ /* Inside min(), + var(--_R) * 9999999px disables a col branch in row, */
229
+ /* + var(--_C) * 9999999px disables a row branch in column. */
152
230
  /* ------------------------------------------------------------------ */
153
231
 
154
232
  /* Between two siblings: col centers vertically, row centers horizontally */
155
- .positioned.gap-after:not(.last) .svedit-selectable {
233
+ :global(.node-gap.positioned.gap-after:not(.last) .svedit-selectable) {
156
234
  --_mid: calc((var(--_s-b) + var(--_n-t)) / 2 - var(--_gm) / 2);
157
235
  top: min(
158
- calc(var(--_s-b) + var(--_R) * 99999px),
159
- calc(var(--_mid) + var(--_R) * 99999px),
160
- calc(var(--_s-t) + var(--_C) * 99999px)
236
+ calc(var(--_s-b) + var(--_R) * 9999999px),
237
+ calc(var(--_mid) + var(--_R) * 9999999px),
238
+ calc(var(--_s-t) + var(--_C) * 9999999px)
161
239
  );
162
240
  bottom: min(
163
- calc(var(--_n-t) + var(--_R) * 99999px),
164
- calc(var(--_mid) + var(--_R) * 99999px),
165
- calc(var(--_s-b) + var(--_C) * 99999px)
241
+ calc(var(--_n-t) + var(--_R) * 9999999px),
242
+ calc(var(--_mid) + var(--_R) * 9999999px),
243
+ calc(var(--_s-b) + var(--_C) * 9999999px)
166
244
  );
167
245
  left: min(
168
- calc(var(--_s-l) + var(--_R) * 99999px),
169
- calc(var(--_s-r) + var(--_C) * 99999px),
246
+ calc(var(--_s-l) + var(--_R) * 9999999px),
247
+ calc(var(--_s-r) + var(--_C) * 9999999px),
170
248
  calc(
171
- (var(--_s-r) + var(--_n-l)) / 2
172
- - var(--_gm) / 2
173
- + max(0px, var(--_s-r) - var(--_n-l)) * 999
174
- + var(--_C) * 99999px
249
+ (var(--_s-r) + var(--_n-l)) / 2 - var(--_gm) / 2 + max(0px, var(--_s-r) - var(--_n-l)) *
250
+ 999 + var(--_C) * 9999999px
175
251
  ),
176
- calc(100% - var(--_eg) + var(--_C) * 99999px)
252
+ /* Safety clamp for wrap: pins gap inside CB when current/next
253
+ wrap across rows. Disabled in nowrap/horizontal-scroll where
254
+ next is side-by-side on the same row (n-l > s-r) — there
255
+ the other branches position correctly and this clamp would
256
+ wrongly force the gap to CB right minus eg. */
257
+ calc(
258
+ 100% - var(--_eg) + max(0px, var(--_n-l) - var(--_s-r) + 0.5px) * 9999 + var(--_C) *
259
+ 9999999px
260
+ )
177
261
  );
178
262
  right: min(
179
- calc(var(--_s-r) + var(--_R) * 99999px),
263
+ calc(var(--_s-r) + var(--_R) * 9999999px),
180
264
  calc(
181
265
  max(
182
- 0px,
183
- min(
184
- var(--_n-l),
185
- calc(
186
- (var(--_s-r) + var(--_n-l)) / 2
187
- - var(--_gm) / 2
188
- ),
189
- max(
190
- min(
191
- calc(var(--_c-r) - var(--_eg)),
192
- calc(var(--_s-r) - var(--_eg))
193
- ),
194
- calc(
195
- var(--_s-r)
196
- - (var(--_n-l) - var(--_s-r)) * 999
266
+ 0px,
267
+ min(
268
+ var(--_n-l),
269
+ calc((var(--_s-r) + var(--_n-l)) / 2 - var(--_gm) / 2),
270
+ max(
271
+ min(calc(var(--_c-r) - var(--_eg)), calc(var(--_s-r) - var(--_eg))),
272
+ calc(var(--_s-r) - (var(--_n-l) - var(--_s-r)) * 999)
197
273
  )
198
274
  )
199
- )
200
- )
201
- + var(--_C) * 99999px
275
+ ) +
276
+ var(--_C) * 9999999px
202
277
  )
203
278
  );
204
279
  min-height: calc(var(--_gm) * var(--_C));
@@ -210,32 +285,43 @@
210
285
  /* After last node: col extends down, row extends right.
211
286
  top also clamps to boundary_bottom - eg so that min-height
212
287
  (which wins over bottom in overconstrained abs-pos) cannot
213
- push the element past the boundary. */
214
- .positioned.gap-after.last .svedit-selectable {
288
+ push the element past the boundary.
289
+
290
+ left's third branch (100% - --_eg + max(0, --_s-r - 100% + 0.5px) * 9999)
291
+ is the wrap-layout safety clamp: in column or row+wrap layouts
292
+ where the last node sits WITHIN the CB (--_s-r < 100%), it pins
293
+ the gap inside the CB so it doesn't extend past the right edge.
294
+ The * 9999 multiplier disables this branch in nowrap horizontal-
295
+ scroll (where --_s-r > 100% — the trailing node has overflowed
296
+ the CB and the gap is expected to follow it).
297
+
298
+ right's `min(--_c-r - --_eg, --_s-r - --_eg)` is what fills the
299
+ gap into the whitespace between the last node and the container
300
+ in non-overflow layouts. In non-overflow, --_c-r < --_s-r in the
301
+ `right` axis (container right is further left than node right
302
+ from the CB right edge), so min picks --_c-r - --_eg and the gap
303
+ ends at container.right + --_eg (the MUST-RULE overshoot). In
304
+ overflow, --_s-r < --_c-r and min picks --_s-r - --_eg — the gap
305
+ follows the node out past the container. */
306
+ :global(.node-gap.positioned.gap-after.last .svedit-selectable) {
215
307
  top: min(
216
- calc(min(var(--_s-b), calc(var(--_b-bt) - var(--_eg))) + var(--_R) * 99999px),
217
- calc(var(--_s-t) + var(--_C) * 99999px)
308
+ calc(min(var(--_s-b), calc(var(--_b-bt) - var(--_eg))) + var(--_R) * 9999999px),
309
+ calc(var(--_s-t) + var(--_C) * 9999999px)
218
310
  );
219
311
  bottom: min(
220
- calc(max(var(--_b-b), var(--_s-b) - var(--_eg)) + var(--_R) * 99999px),
221
- calc(var(--_s-b) + var(--_C) * 99999px)
312
+ calc(max(var(--_b-b), var(--_s-b) - var(--_eg)) + var(--_R) * 9999999px),
313
+ calc(var(--_s-b) + var(--_C) * 9999999px)
222
314
  );
223
315
  left: min(
224
- calc(var(--_s-l) + var(--_R) * 99999px),
225
- calc(min(var(--_s-r), calc(var(--_b-rl) - var(--_eg))) + var(--_C) * 99999px),
226
- calc(100% - var(--_eg) + var(--_C) * 99999px)
316
+ calc(var(--_s-l) + var(--_R) * 9999999px),
317
+ calc(min(var(--_s-r), calc(var(--_b-rl) - var(--_eg))) + var(--_C) * 9999999px),
318
+ calc(100% - var(--_eg) + max(0px, var(--_s-r) - 100% + 0.5px) * 9999 + var(--_C) * 9999999px)
227
319
  );
228
320
  right: min(
229
- calc(var(--_s-r) + var(--_R) * 99999px),
321
+ calc(var(--_s-r) + var(--_R) * 9999999px),
230
322
  calc(
231
- max(
232
- var(--_b-r),
233
- min(
234
- calc(var(--_c-r) - var(--_eg)),
235
- calc(var(--_s-r) - var(--_eg))
236
- )
237
- )
238
- + var(--_C) * 99999px
323
+ max(var(--_b-r), min(calc(var(--_c-r) - var(--_eg)), calc(var(--_s-r) - var(--_eg)))) +
324
+ var(--_C) * 9999999px
239
325
  )
240
326
  );
241
327
  min-height: calc(var(--_eg) * var(--_C));
@@ -243,44 +329,48 @@
243
329
  }
244
330
 
245
331
  /* Before first node: col extends up, row extends left */
246
- .positioned.gap-before:not(.empty) .svedit-selectable {
332
+ :global(.node-gap.positioned.gap-before:not(.empty) .svedit-selectable) {
247
333
  top: min(
248
- calc(
249
- max(var(--_b-t), var(--_s-t) - var(--_eg))
250
- + var(--_R) * 99999px
251
- ),
252
- calc(var(--_s-t) + var(--_C) * 99999px)
334
+ calc(max(var(--_b-t), var(--_s-t) - var(--_eg)) + var(--_R) * 9999999px),
335
+ calc(var(--_s-t) + var(--_C) * 9999999px)
253
336
  );
254
337
  bottom: min(
255
- calc(var(--_s-t) + var(--_R) * 99999px),
256
- calc(var(--_s-b) + var(--_C) * 99999px)
338
+ calc(var(--_s-t) + var(--_R) * 9999999px),
339
+ calc(var(--_s-b) + var(--_C) * 9999999px)
257
340
  );
258
341
  left: min(
259
- calc(var(--_s-l) + var(--_R) * 99999px),
260
- calc(
261
- max(var(--_b-l), var(--_s-l) - var(--_eg))
262
- + var(--_C) * 99999px
263
- )
342
+ calc(var(--_s-l) + var(--_R) * 9999999px),
343
+ calc(max(var(--_b-l), var(--_s-l) - var(--_eg)) + var(--_C) * 9999999px)
264
344
  );
265
345
  right: min(
266
- calc(var(--_s-r) + var(--_R) * 99999px),
267
- calc(var(--_s-l) + var(--_C) * 99999px)
346
+ calc(var(--_s-r) + var(--_R) * 9999999px),
347
+ calc(var(--_s-l) + var(--_C) * 9999999px)
268
348
  );
269
349
  min-height: calc(var(--_eg) * var(--_C));
270
350
  min-width: calc(var(--_eg) * var(--_R));
271
351
  }
272
352
 
273
- /* Empty array: spans the outermost edges of placeholder and container. */
274
- .positioned.gap-before.empty .svedit-selectable {
275
- top: min(var(--_s-t), var(--_c-t));
276
- bottom: min(var(--_s-b), var(--_c-b));
277
- left: min(var(--_s-l), var(--_c-l));
278
- right: min(var(--_s-r), var(--_c-r));
353
+ /* Empty array: the gap fills its placeholder, which is this
354
+ selectable's containing block (NodeArrayProperty sets it
355
+ position: relative). inset:0 fills it with no anchor() — so no
356
+ .positioned gating and no anchor cost. The width:auto, height:auto
357
+ and pointer-events:auto override the :not(.positioned) 0×0
358
+ collapse; position-visibility:always overrides the .positioned
359
+ rule's anchors-visible, so a transient positioned toggle can't
360
+ hide the gap. */
361
+ :global(.node-gap.gap-before.empty .svedit-selectable) {
362
+ position: absolute;
363
+ inset: 0;
364
+ width: auto;
365
+ height: auto;
366
+ pointer-events: auto;
367
+ position-visibility: always;
279
368
  }
280
369
 
281
- /* Debugging styles */
282
- /* .positioned .svedit-selectable {
283
- outline: 0.1px solid rgba(238, 0, 255, 0.5);
370
+ /* Debugging styles - DO NOT CHANGE OR REMOVE */
371
+ /* :global(.node-gap.positioned .svedit-selectable) {
372
+ outline: 2px solid rgba(238, 0, 255, 0.5);
373
+ background-color: rgba(238, 0, 255, 0.5);
284
374
  outline-offset: -0.5px;
285
375
  } */
286
376
  </style>