svedit 0.12.0 → 0.14.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 (88) hide show
  1. package/README.md +35 -22
  2. package/dist/Command.svelte.d.ts +38 -30
  3. package/dist/Command.svelte.d.ts.map +1 -1
  4. package/dist/Command.svelte.js +271 -326
  5. package/dist/CustomProperty.svelte +3 -5
  6. package/dist/CustomProperty.svelte.d.ts +3 -6
  7. package/dist/CustomProperty.svelte.d.ts.map +1 -1
  8. package/dist/KeyMapper.svelte.d.ts +19 -6
  9. package/dist/KeyMapper.svelte.d.ts.map +1 -1
  10. package/dist/KeyMapper.svelte.js +95 -112
  11. package/dist/Node.svelte +16 -13
  12. package/dist/Node.svelte.d.ts +3 -5
  13. package/dist/Node.svelte.d.ts.map +1 -1
  14. package/dist/NodeArrayProperty.svelte +39 -22
  15. package/dist/NodeArrayProperty.svelte.d.ts +3 -5
  16. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  17. package/dist/NodeCaret.svelte +2 -2
  18. package/dist/NodeCaret.svelte.d.ts +6 -14
  19. package/dist/NodeCaret.svelte.d.ts.map +1 -1
  20. package/dist/NodeGap.svelte +12 -6
  21. package/dist/NodeGap.svelte.d.ts +7 -14
  22. package/dist/NodeGap.svelte.d.ts.map +1 -1
  23. package/dist/NodeGapMarkers.svelte +36 -14
  24. package/dist/NodeGapMarkers.svelte.d.ts +6 -11
  25. package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
  26. package/dist/NodeSelectionMarkers.svelte +21 -7
  27. package/dist/NodeSelectionMarkers.svelte.d.ts +2 -5
  28. package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -1
  29. package/dist/Session.svelte.d.ts +81 -129
  30. package/dist/Session.svelte.d.ts.map +1 -1
  31. package/dist/Session.svelte.js +542 -648
  32. package/dist/Svedit.svelte +146 -140
  33. package/dist/Svedit.svelte.d.ts +30 -10
  34. package/dist/Svedit.svelte.d.ts.map +1 -1
  35. package/dist/TextProperty.svelte +37 -23
  36. package/dist/TextProperty.svelte.d.ts +3 -5
  37. package/dist/TextProperty.svelte.d.ts.map +1 -1
  38. package/dist/Transaction.svelte.d.ts +64 -127
  39. package/dist/Transaction.svelte.d.ts.map +1 -1
  40. package/dist/Transaction.svelte.js +839 -1001
  41. package/dist/UnknownNode.svelte +4 -3
  42. package/dist/UnknownNode.svelte.d.ts +5 -9
  43. package/dist/UnknownNode.svelte.d.ts.map +1 -1
  44. package/dist/doc_utils.d.ts +67 -155
  45. package/dist/doc_utils.d.ts.map +1 -1
  46. package/dist/doc_utils.js +619 -863
  47. package/dist/index.d.ts +20 -17
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -17
  50. package/dist/node_visibility.svelte.d.ts +110 -9
  51. package/dist/node_visibility.svelte.d.ts.map +1 -1
  52. package/dist/node_visibility.svelte.js +473 -544
  53. package/dist/paste_utils.d.ts +11 -44
  54. package/dist/paste_utils.d.ts.map +1 -1
  55. package/dist/paste_utils.js +111 -152
  56. package/dist/styles/svedit-colors.css +8 -5
  57. package/dist/transforms.svelte.d.ts +9 -7
  58. package/dist/transforms.svelte.d.ts.map +1 -1
  59. package/dist/transforms.svelte.js +125 -150
  60. package/dist/types.d.ts +294 -309
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/types.js +1 -0
  63. package/dist/utils.d.ts +40 -119
  64. package/dist/utils.d.ts.map +1 -1
  65. package/dist/utils.js +346 -473
  66. package/package.json +70 -70
  67. package/src/lib/{Command.svelte.js → Command.svelte.ts} +29 -17
  68. package/src/lib/CustomProperty.svelte +3 -5
  69. package/src/lib/{KeyMapper.svelte.js → KeyMapper.svelte.ts} +28 -11
  70. package/src/lib/Node.svelte +16 -13
  71. package/src/lib/NodeArrayProperty.svelte +39 -22
  72. package/src/lib/NodeCaret.svelte +2 -2
  73. package/src/lib/NodeGap.svelte +12 -6
  74. package/src/lib/NodeGapMarkers.svelte +36 -14
  75. package/src/lib/NodeSelectionMarkers.svelte +21 -7
  76. package/src/lib/{Session.svelte.js → Session.svelte.ts} +130 -127
  77. package/src/lib/Svedit.svelte +146 -140
  78. package/src/lib/TextProperty.svelte +37 -23
  79. package/src/lib/{Transaction.svelte.js → Transaction.svelte.ts} +139 -143
  80. package/src/lib/UnknownNode.svelte +4 -3
  81. package/src/lib/{doc_utils.js → doc_utils.ts} +247 -206
  82. package/src/lib/{index.js → index.ts} +48 -0
  83. package/src/lib/{node_visibility.svelte.js → node_visibility.svelte.ts} +68 -92
  84. package/src/lib/{paste_utils.js → paste_utils.ts} +47 -58
  85. package/src/lib/styles/svedit-colors.css +8 -5
  86. package/src/lib/{transforms.svelte.js → transforms.svelte.ts} +39 -21
  87. package/src/lib/{types.d.ts → types.ts} +161 -66
  88. package/src/lib/{utils.js → utils.ts} +110 -129
@@ -1,7 +1,8 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte';
3
3
  import NodeCaret from './NodeCaret.svelte';
4
4
  import { PATH_SEPARATOR, serialize_path } from './utils.js';
5
+ import type { DocumentPath, SveditRenderContext } from './types.js';
5
6
 
6
7
  /**
7
8
  * ┌─────────────────────────────────────────────────────────────────┐
@@ -26,11 +27,20 @@
26
27
  * Reads visibility state directly from the registry. SvelteSet's per-key
27
28
  * tracking on `.has()` and iteration means this component only
28
29
  * re-evaluates when THIS array's visible-index set changes.
30
+ *
31
+ * The active marker (the one carrying the caret) additionally renders the
32
+ * consumer's `system_components.node_gap_tools` component when configured
33
+ * — an extension point for gap-scoped tools (e.g. an insert button).
34
+ * Rendering inside the marker means the tool inherits --row for
35
+ * orientation-aware styling and shows/hides together with the caret.
36
+ * The marker has pointer-events: none — interactive tools must set
37
+ * pointer-events: auto themselves.
29
38
  */
30
39
 
31
- let { path, count } = $props();
40
+ let { path, count }: { path: DocumentPath; count: number } = $props();
32
41
 
33
- const svedit = getContext('svedit');
42
+ const svedit = getContext<SveditRenderContext>('svedit');
43
+ let NodeGapTools = $derived(svedit.session.config.system_components?.node_gap_tools);
34
44
  let path_str = $derived(serialize_path(path));
35
45
  let visible = $derived(svedit.visibility_registry.get_array_indices(path_str));
36
46
 
@@ -51,8 +61,16 @@
51
61
  ? `;--_f:${anchor_prefix}${PATH_SEPARATOR}0;--_s:${anchor_prefix}${PATH_SEPARATOR}1`
52
62
  : '';
53
63
 
54
- /** @type {Array<{key:string,offset:number,type:string,vars:string,is_first:boolean,is_last:boolean,has_pair:boolean}>} */
55
- const result = [];
64
+ type GapMarker = {
65
+ key: string;
66
+ offset: number;
67
+ type: string;
68
+ vars: string;
69
+ is_first: boolean;
70
+ is_last: boolean;
71
+ has_pair: boolean;
72
+ };
73
+ const result: GapMarker[] = [];
56
74
 
57
75
  if (count === 0) {
58
76
  if (visible.has(0)) {
@@ -73,15 +91,15 @@
73
91
  // 1000 nodes with ~30 visible, this drops 1001 SvelteSet/SvelteMap
74
92
  // reads per re-derivation to ~30. Filter stale indices >= count
75
93
  // that may briefly remain after a node delete (until MO fires).
76
- const sorted = [];
94
+ const sorted: number[] = [];
77
95
  for (const i of visible) {
78
96
  if (i >= 0 && i < count) sorted.push(i);
79
97
  }
80
98
  sorted.sort((a, b) => a - b);
81
99
  if (sorted.length === 0) return result;
82
100
 
83
- const offsets = [];
84
- function add_offset(offset) {
101
+ const offsets: number[] = [];
102
+ function add_offset(offset: number) {
85
103
  if (!offsets.includes(offset)) offsets.push(offset);
86
104
  }
87
105
 
@@ -112,7 +130,7 @@
112
130
  ? `${g_prefix}${PATH_SEPARATOR}0-gap-before`
113
131
  : `${g_prefix}${PATH_SEPARATOR}${offset - 1}-gap-after`;
114
132
 
115
- let type, vars;
133
+ let type: string, vars: string;
116
134
  if (is_first || is_last) {
117
135
  type = 'gap-edge';
118
136
  const adjacent = is_first
@@ -154,6 +172,9 @@
154
172
  >
155
173
  {#if gap.key === caret_gap_key}
156
174
  <NodeCaret />
175
+ {#if NodeGapTools}
176
+ <NodeGapTools {path} offset={gap.offset} is_first={gap.is_first} is_last={gap.is_last} />
177
+ {/if}
157
178
  {/if}
158
179
  </div>
159
180
  {/each}
@@ -161,6 +182,7 @@
161
182
  <style>
162
183
  /*
163
184
  * Public customization tokens (set on an ancestor or this component):
185
+ * --editing-stroke
164
186
  * --node-caret-gap-color
165
187
  * --node-caret-symbol-size
166
188
  * --node-caret-symbol-stroke
@@ -602,8 +624,8 @@
602
624
  calc(var(--_mi) + var(--_R) * 9999999px),
603
625
  calc(50% + var(--_C) * 9999999px)
604
626
  );
605
- border-top: calc(var(--_C) * 1px) dashed var(--node-caret-gap-color, var(--svedit-canvas-stroke));
606
- border-left: calc(var(--_R) * 1px) dashed var(--node-caret-gap-color, var(--svedit-canvas-stroke));
627
+ border-top: calc(var(--_C) * 1px) dashed var(--node-caret-gap-color, var(--editing-stroke));
628
+ border-left: calc(var(--_R) * 1px) dashed var(--node-caret-gap-color, var(--editing-stroke));
607
629
  transform:
608
630
  translateY(calc(var(--_C) * -0.5px))
609
631
  translateX(calc(var(--_R) * -0.5px));
@@ -617,7 +639,7 @@
617
639
  /* Empty array marker (dashed outline for discoverability). */
618
640
  &.gap-empty::before {
619
641
  inset: 0px;
620
- border: var(--node-caret-empty-border, 1px dashed var(--node-caret-gap-color, var(--svedit-canvas-stroke)));
642
+ border: var(--node-caret-empty-border, 1px dashed var(--node-caret-gap-color, var(--editing-stroke)));
621
643
  border-radius: var(--node-caret-empty-border-radius, 3px);
622
644
  }
623
645
 
@@ -630,7 +652,7 @@
630
652
  top: 50%;
631
653
  left: 50%;
632
654
  transform: translate(-50%, -50%);
633
- background: var(--node-caret-symbol-bg, var(--node-caret-gap-color, var(--svedit-canvas-stroke)));
655
+ background: var(--node-caret-symbol-bg, var(--node-caret-gap-color, var(--editing-stroke)));
634
656
  mask: var(--node-caret-symbol-mask,
635
657
  linear-gradient(black, black) center / 100% var(--node-caret-symbol-stroke, 1px) no-repeat,
636
658
  linear-gradient(black, black) center / var(--node-caret-symbol-stroke, 1px) 100% no-repeat
@@ -646,4 +668,4 @@
646
668
  outline: 1px solid blue;
647
669
  outline-offset: 0.5px;
648
670
  } */
649
- </style>
671
+ </style>
@@ -1,12 +1,13 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte';
3
3
  import { serialize_path } from './utils.js';
4
+ import type { DocumentPath, SveditContext } from './types.js';
4
5
 
5
- const svedit = getContext('svedit');
6
+ const svedit = getContext<SveditContext>('svedit');
6
7
  let selected_node_paths = $derived(get_selected_node_paths());
7
8
 
8
- function get_selected_node_paths() {
9
- const paths = [];
9
+ function get_selected_node_paths(): DocumentPath[] | undefined {
10
+ const paths: DocumentPath[] = [];
10
11
  const selection = svedit.session.selection;
11
12
  if (!selection) return;
12
13
  if (selection.type !== 'node' || selection.anchor_offset === selection.focus_offset) return;
@@ -36,10 +37,23 @@
36
37
  <style>
37
38
  .selected-node-overlay,
38
39
  .selected-property-overlay {
40
+ /* Selection frame: a single 1px outline, offset -0.5px so the
41
+ hairline centers on the node's edge and neighboring frames merge
42
+ into one shared line. Alternatives tried and rejected:
43
+ - Plain 1px border: adjacent selected nodes stack their borders
44
+ into a 2px seam between them, which looks ugly.
45
+ - Thick translucent frame (8px border) plus an inner hairline
46
+ outline: multiple nested lines take more cognitive effort to
47
+ parse than a single line.
48
+ - Inset box-shadow rings (1px stroke + 8px translucent): same
49
+ layered-frame look, same objection.
50
+ Performance note: outlines don't participate in layout, so
51
+ selection changes can't trigger reflows. */
39
52
  position: absolute;
40
- background: var(--svedit-editing-fill);
41
- border: 1px solid var(--svedit-editing-stroke);
42
- border-radius: 2px;
53
+ background: var(--editing-muted);
54
+ outline: 1px solid var(--editing);
55
+ outline-offset: -0.5px;
56
+ border-radius: 1px;
43
57
  top: anchor(top);
44
58
  left: anchor(left);
45
59
  bottom: anchor(bottom);