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.
- package/README.md +35 -22
- package/dist/Command.svelte.d.ts +38 -30
- package/dist/Command.svelte.d.ts.map +1 -1
- package/dist/Command.svelte.js +271 -326
- package/dist/CustomProperty.svelte +3 -5
- package/dist/CustomProperty.svelte.d.ts +3 -6
- package/dist/CustomProperty.svelte.d.ts.map +1 -1
- package/dist/KeyMapper.svelte.d.ts +19 -6
- package/dist/KeyMapper.svelte.d.ts.map +1 -1
- package/dist/KeyMapper.svelte.js +95 -112
- package/dist/Node.svelte +16 -13
- package/dist/Node.svelte.d.ts +3 -5
- package/dist/Node.svelte.d.ts.map +1 -1
- package/dist/NodeArrayProperty.svelte +39 -22
- package/dist/NodeArrayProperty.svelte.d.ts +3 -5
- package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
- package/dist/NodeCaret.svelte +2 -2
- package/dist/NodeCaret.svelte.d.ts +6 -14
- package/dist/NodeCaret.svelte.d.ts.map +1 -1
- package/dist/NodeGap.svelte +12 -6
- package/dist/NodeGap.svelte.d.ts +7 -14
- package/dist/NodeGap.svelte.d.ts.map +1 -1
- package/dist/NodeGapMarkers.svelte +36 -14
- package/dist/NodeGapMarkers.svelte.d.ts +6 -11
- package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
- package/dist/NodeSelectionMarkers.svelte +21 -7
- package/dist/NodeSelectionMarkers.svelte.d.ts +2 -5
- package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.d.ts +81 -129
- package/dist/Session.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.js +542 -648
- package/dist/Svedit.svelte +146 -140
- package/dist/Svedit.svelte.d.ts +30 -10
- package/dist/Svedit.svelte.d.ts.map +1 -1
- package/dist/TextProperty.svelte +37 -23
- package/dist/TextProperty.svelte.d.ts +3 -5
- package/dist/TextProperty.svelte.d.ts.map +1 -1
- package/dist/Transaction.svelte.d.ts +64 -127
- package/dist/Transaction.svelte.d.ts.map +1 -1
- package/dist/Transaction.svelte.js +839 -1001
- package/dist/UnknownNode.svelte +4 -3
- package/dist/UnknownNode.svelte.d.ts +5 -9
- package/dist/UnknownNode.svelte.d.ts.map +1 -1
- package/dist/doc_utils.d.ts +67 -155
- package/dist/doc_utils.d.ts.map +1 -1
- package/dist/doc_utils.js +619 -863
- package/dist/index.d.ts +20 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -17
- package/dist/node_visibility.svelte.d.ts +110 -9
- package/dist/node_visibility.svelte.d.ts.map +1 -1
- package/dist/node_visibility.svelte.js +473 -544
- package/dist/paste_utils.d.ts +11 -44
- package/dist/paste_utils.d.ts.map +1 -1
- package/dist/paste_utils.js +111 -152
- package/dist/styles/svedit-colors.css +8 -5
- package/dist/transforms.svelte.d.ts +9 -7
- package/dist/transforms.svelte.d.ts.map +1 -1
- package/dist/transforms.svelte.js +125 -150
- package/dist/types.d.ts +294 -309
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +40 -119
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +346 -473
- package/package.json +70 -70
- package/src/lib/{Command.svelte.js → Command.svelte.ts} +29 -17
- package/src/lib/CustomProperty.svelte +3 -5
- package/src/lib/{KeyMapper.svelte.js → KeyMapper.svelte.ts} +28 -11
- package/src/lib/Node.svelte +16 -13
- package/src/lib/NodeArrayProperty.svelte +39 -22
- package/src/lib/NodeCaret.svelte +2 -2
- package/src/lib/NodeGap.svelte +12 -6
- package/src/lib/NodeGapMarkers.svelte +36 -14
- package/src/lib/NodeSelectionMarkers.svelte +21 -7
- package/src/lib/{Session.svelte.js → Session.svelte.ts} +130 -127
- package/src/lib/Svedit.svelte +146 -140
- package/src/lib/TextProperty.svelte +37 -23
- package/src/lib/{Transaction.svelte.js → Transaction.svelte.ts} +139 -143
- package/src/lib/UnknownNode.svelte +4 -3
- package/src/lib/{doc_utils.js → doc_utils.ts} +247 -206
- package/src/lib/{index.js → index.ts} +48 -0
- package/src/lib/{node_visibility.svelte.js → node_visibility.svelte.ts} +68 -92
- package/src/lib/{paste_utils.js → paste_utils.ts} +47 -58
- package/src/lib/styles/svedit-colors.css +8 -5
- package/src/lib/{transforms.svelte.js → transforms.svelte.ts} +39 -21
- package/src/lib/{types.d.ts → types.ts} +161 -66
- package/src/lib/{utils.js → utils.ts} +110 -129
package/dist/NodeGap.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
function cycle_z_index(
|
|
3
|
-
const el =
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
function cycle_z_index(e: MouseEvent) {
|
|
3
|
+
const el = e.currentTarget as HTMLElement;
|
|
4
4
|
if (el.hasAttribute('data-sent-to-back')) {
|
|
5
5
|
document.querySelectorAll('.svedit-selectable[data-sent-to-back]').forEach((prev) => {
|
|
6
6
|
prev.removeAttribute('data-sent-to-back');
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
}
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
|
-
<script>
|
|
13
|
+
<script lang="ts">
|
|
14
14
|
import { serialize_path } from './utils.js';
|
|
15
15
|
import { getContext } from 'svelte';
|
|
16
16
|
import { should_position_gap } from './node_visibility.svelte.js';
|
|
17
|
+
import type { DocumentPath, SveditRenderContext } from './types.js';
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* ┌─────────────────────────────────────────────────────────────────┐
|
|
@@ -58,8 +59,13 @@
|
|
|
58
59
|
* sure your custom component also handles read-only mode by rendering a
|
|
59
60
|
* plain `.node-gap` placeholder without editable internals.
|
|
60
61
|
*/
|
|
61
|
-
const svedit = getContext('svedit');
|
|
62
|
-
let {
|
|
62
|
+
const svedit = getContext<SveditRenderContext>('svedit');
|
|
63
|
+
let {
|
|
64
|
+
array_path,
|
|
65
|
+
offset,
|
|
66
|
+
count,
|
|
67
|
+
empty = false
|
|
68
|
+
}: { array_path: DocumentPath; offset: number; count: number; empty?: boolean } = $props();
|
|
63
69
|
let is_editable = $derived(svedit.editable);
|
|
64
70
|
|
|
65
71
|
let is_first = $derived(offset === 0);
|
package/dist/NodeGap.svelte.d.ts
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
type NodeGap = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
-
};
|
|
6
|
-
declare const NodeGap: import("svelte").Component<{
|
|
7
|
-
array_path: any;
|
|
8
|
-
offset: any;
|
|
9
|
-
count: any;
|
|
10
|
-
empty?: boolean;
|
|
11
|
-
}, {}, "">;
|
|
1
|
+
import type { DocumentPath } from './types.js';
|
|
12
2
|
type $$ComponentProps = {
|
|
13
|
-
array_path:
|
|
14
|
-
offset:
|
|
15
|
-
count:
|
|
3
|
+
array_path: DocumentPath;
|
|
4
|
+
offset: number;
|
|
5
|
+
count: number;
|
|
16
6
|
empty?: boolean;
|
|
17
7
|
};
|
|
8
|
+
declare const NodeGap: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type NodeGap = ReturnType<typeof NodeGap>;
|
|
10
|
+
export default NodeGap;
|
|
18
11
|
//# sourceMappingURL=NodeGap.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeGap.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGap.svelte.
|
|
1
|
+
{"version":3,"file":"NodeGap.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGap.svelte.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,YAAY,CAAC;AAEnE,KAAK,gBAAgB,GAAI;IAAE,UAAU,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAkHvG,QAAA,MAAM,OAAO,sDAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
|
|
@@ -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
|
-
|
|
55
|
-
|
|
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(--
|
|
606
|
-
border-left: calc(var(--_R) * 1px) dashed var(--node-caret-gap-color, var(--
|
|
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(--
|
|
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(--
|
|
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,14 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
type NodeGapMarkers = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
-
};
|
|
6
|
-
declare const NodeGapMarkers: import("svelte").Component<{
|
|
7
|
-
path: any;
|
|
8
|
-
count: any;
|
|
9
|
-
}, {}, "">;
|
|
1
|
+
import type { DocumentPath } from './types.js';
|
|
10
2
|
type $$ComponentProps = {
|
|
11
|
-
path:
|
|
12
|
-
count:
|
|
3
|
+
path: DocumentPath;
|
|
4
|
+
count: number;
|
|
13
5
|
};
|
|
6
|
+
declare const NodeGapMarkers: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type NodeGapMarkers = ReturnType<typeof NodeGapMarkers>;
|
|
8
|
+
export default NodeGapMarkers;
|
|
14
9
|
//# sourceMappingURL=NodeGapMarkers.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeGapMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGapMarkers.svelte.
|
|
1
|
+
{"version":3,"file":"NodeGapMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeGapMarkers.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,YAAY,CAAC;AAEnE,KAAK,gBAAgB,GAAI;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAgLhE,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -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(--
|
|
41
|
-
|
|
42
|
-
|
|
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);
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export default NodeSelectionMarkers;
|
|
2
|
-
type NodeSelectionMarkers = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<Record<string, never>>): void;
|
|
5
|
-
};
|
|
6
1
|
declare const NodeSelectionMarkers: import("svelte").Component<Record<string, never>, {}, "">;
|
|
2
|
+
type NodeSelectionMarkers = ReturnType<typeof NodeSelectionMarkers>;
|
|
3
|
+
export default NodeSelectionMarkers;
|
|
7
4
|
//# sourceMappingURL=NodeSelectionMarkers.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeSelectionMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeSelectionMarkers.svelte.
|
|
1
|
+
{"version":3,"file":"NodeSelectionMarkers.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeSelectionMarkers.svelte.ts"],"names":[],"mappings":"AA4CA,QAAA,MAAM,oBAAoB,2DAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
|
package/dist/Session.svelte.d.ts
CHANGED
|
@@ -1,72 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
selection?: Selection;
|
|
15
|
-
});
|
|
16
|
-
/** @type {DocumentSchema} */
|
|
17
|
-
schema: DocumentSchema;
|
|
18
|
-
/** @type {Document} */
|
|
1
|
+
import Transaction from './Transaction.svelte.js';
|
|
2
|
+
import type { SelectedAttachment } from './doc_utils.js';
|
|
3
|
+
import type { NodeId, DocumentPath, Selection, Attachment, NodeKind, DocumentSchema, DocumentNode, Document, AnyNode, Text, CommandRegistry, Inspection, SessionConfig, SveditContext } from './types.js';
|
|
4
|
+
import type { Keymap } from './KeyMapper.svelte.js';
|
|
5
|
+
type HistoryEntry = {
|
|
6
|
+
ops: Transaction['ops'];
|
|
7
|
+
inverse_ops: Transaction['inverse_ops'];
|
|
8
|
+
selection_before: Selection | null;
|
|
9
|
+
selection_after: Selection | null;
|
|
10
|
+
};
|
|
11
|
+
export default class Session<S extends DocumentSchema = DocumentSchema> {
|
|
12
|
+
#private;
|
|
13
|
+
schema: S;
|
|
19
14
|
doc: Document;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
history: any[];
|
|
15
|
+
config: SessionConfig;
|
|
16
|
+
history: HistoryEntry[];
|
|
23
17
|
history_index: number;
|
|
24
|
-
last_batch_started:
|
|
25
|
-
commands:
|
|
26
|
-
keymap:
|
|
18
|
+
last_batch_started: number | undefined;
|
|
19
|
+
commands: CommandRegistry;
|
|
20
|
+
keymap: Keymap;
|
|
27
21
|
can_undo: boolean;
|
|
28
22
|
can_redo: boolean;
|
|
29
|
-
selected_node:
|
|
30
|
-
available_mark_types:
|
|
31
|
-
available_annotation_types:
|
|
32
|
-
selected_marks:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
23
|
+
selected_node: AnyNode<S> | null;
|
|
24
|
+
available_mark_types: string[];
|
|
25
|
+
available_annotation_types: string[];
|
|
26
|
+
selected_marks: SelectedAttachment[];
|
|
27
|
+
active_mark: SelectedAttachment | null;
|
|
28
|
+
selected_annotations: SelectedAttachment[];
|
|
29
|
+
active_annotation: SelectedAttachment | null;
|
|
30
|
+
/**
|
|
31
|
+
* @param schema - The document schema
|
|
32
|
+
* @param doc - The document
|
|
33
|
+
* @param config - configuration object
|
|
34
|
+
* @param options - Optional settings (e.g. initial selection state)
|
|
35
|
+
*/
|
|
36
|
+
constructor(schema: S, doc: Document, config: SessionConfig, options?: {
|
|
37
|
+
selection?: Selection | null;
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Gets the current selection
|
|
41
|
+
*/
|
|
42
|
+
get selection(): Selection | null;
|
|
48
43
|
/**
|
|
49
44
|
* Sets the selection with validation
|
|
50
|
-
* @param {Selection | null} value - The new selection
|
|
51
45
|
* @throws {Error} Throws if the selection is invalid
|
|
52
46
|
*/
|
|
53
47
|
set selection(value: Selection | null);
|
|
54
|
-
/**
|
|
55
|
-
* Gets the current selection
|
|
56
|
-
* @returns {Selection | null}
|
|
57
|
-
*/
|
|
58
|
-
get selection(): Selection | null;
|
|
59
48
|
/**
|
|
60
49
|
* Validates that a selection is within bounds and refers to valid paths.
|
|
61
50
|
*
|
|
62
|
-
* @param {Selection} selection - The selection to validate
|
|
63
51
|
* @throws {Error} Throws if the selection is invalid
|
|
64
|
-
* @private
|
|
65
52
|
*/
|
|
66
53
|
private _validate_selection;
|
|
67
54
|
/**
|
|
68
55
|
* Gets the document_id from the doc
|
|
69
|
-
* @returns {string}
|
|
70
56
|
*/
|
|
71
57
|
get document_id(): string;
|
|
72
58
|
/**
|
|
@@ -77,11 +63,10 @@ export default class Session {
|
|
|
77
63
|
* deleted nodes. That catches local node invariants and dangling references left
|
|
78
64
|
* behind by deletes without scanning every node on every apply.
|
|
79
65
|
*
|
|
80
|
-
* @param {Transaction} transaction - The transaction result to validate
|
|
81
66
|
* @throws {Error} Throws if the transaction result is invalid
|
|
82
67
|
*/
|
|
83
68
|
validate_transaction_result(transaction: Transaction): void;
|
|
84
|
-
generate_id():
|
|
69
|
+
generate_id(): string;
|
|
85
70
|
/**
|
|
86
71
|
* Initialize commands and keymap for this session.
|
|
87
72
|
* Called by Svedit component when it has the necessary context.
|
|
@@ -90,35 +75,34 @@ export default class Session {
|
|
|
90
75
|
* For multiple editors on the same document, this architecture would need
|
|
91
76
|
* to be refactored to support multiple sessions per document.
|
|
92
77
|
*
|
|
93
|
-
* @param
|
|
78
|
+
* @param context - The svedit context with session, editable, canvas, etc.
|
|
94
79
|
*/
|
|
95
|
-
initialize_commands(context:
|
|
96
|
-
get_available_mark_types():
|
|
97
|
-
get_available_annotation_types():
|
|
98
|
-
get_selected_node():
|
|
80
|
+
initialize_commands(context: SveditContext<S>): void;
|
|
81
|
+
get_available_mark_types(): string[];
|
|
82
|
+
get_available_annotation_types(): string[];
|
|
83
|
+
get_selected_node(): AnyNode<S> | null;
|
|
99
84
|
/**
|
|
100
85
|
* Creates a new transaction for making atomic changes to the document.
|
|
101
|
-
*
|
|
102
|
-
* @returns {Transaction} A new transaction instance
|
|
103
86
|
*/
|
|
104
87
|
get tr(): Transaction;
|
|
105
88
|
/**
|
|
106
89
|
* Applies a transaction to the document.
|
|
107
|
-
* Auto-batches history entries with debounced behavior (max one entry per
|
|
90
|
+
* Auto-batches history entries with debounced behavior (max one entry per second) when batch is true.
|
|
108
91
|
*
|
|
109
|
-
* @param
|
|
110
|
-
* @param
|
|
111
|
-
* @param {boolean} [options.batch=false] - Whether to allow batching with previous transaction
|
|
92
|
+
* @param transaction - The transaction to apply
|
|
93
|
+
* @param options - Optional configuration (batch: whether to allow batching with previous transaction)
|
|
112
94
|
*/
|
|
113
95
|
apply(transaction: Transaction, { batch }?: {
|
|
114
96
|
batch?: boolean;
|
|
115
97
|
}): this;
|
|
116
|
-
undo(): this;
|
|
117
|
-
redo(): this;
|
|
98
|
+
undo(): this | undefined;
|
|
99
|
+
redo(): this | undefined;
|
|
118
100
|
/**
|
|
119
101
|
* Gets a node instance or property value at the specified path.
|
|
120
|
-
*
|
|
121
|
-
*
|
|
102
|
+
*
|
|
103
|
+
* The result type defaults to `any` because a path can address a node or
|
|
104
|
+
* any property value. Annotate the target to type the result.
|
|
105
|
+
*
|
|
122
106
|
* @example
|
|
123
107
|
* // Get a node by ID
|
|
124
108
|
* session.get('list_1') // => { type: 'list', id: 'list_1', ... }
|
|
@@ -135,7 +119,7 @@ export default class Session {
|
|
|
135
119
|
* // Get a text property
|
|
136
120
|
* session.get(['page_1', 'cover', 'title']) // => {content: 'Hello world', marks: [], annotations: []}
|
|
137
121
|
*/
|
|
138
|
-
get(path: DocumentPath | string):
|
|
122
|
+
get<T = any>(path: DocumentPath | string): T;
|
|
139
123
|
/**
|
|
140
124
|
* While .get gives you the value of a path, inspect gives you
|
|
141
125
|
* the type info of that value.
|
|
@@ -158,49 +142,40 @@ export default class Session {
|
|
|
158
142
|
* type: 'paragraph',
|
|
159
143
|
* properties: {...}
|
|
160
144
|
* }
|
|
161
|
-
*
|
|
162
|
-
* @param {DocumentPath} path
|
|
163
|
-
* @returns {{kind: 'property'|'node', [key: string]: any}}
|
|
164
145
|
*/
|
|
165
|
-
inspect(path: DocumentPath):
|
|
166
|
-
kind: "property" | "node";
|
|
167
|
-
[key: string]: any;
|
|
168
|
-
};
|
|
146
|
+
inspect(path: DocumentPath): Inspection;
|
|
169
147
|
/**
|
|
170
|
-
* Determines the kind of a node ('
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* @returns {NodeKind}
|
|
148
|
+
* Determines the kind of a node ('document' for root nodes, 'block' for
|
|
149
|
+
* structured blocks, 'text' for pure text nodes, 'mark' for mark nodes or
|
|
150
|
+
* 'annotation' for annotation nodes).
|
|
174
151
|
*/
|
|
175
|
-
kind(node:
|
|
152
|
+
kind(node: DocumentNode): NodeKind;
|
|
176
153
|
/**
|
|
177
154
|
* Determines whether a node type can be inserted at a given selection.
|
|
178
|
-
*
|
|
179
|
-
* @param
|
|
180
|
-
* @
|
|
155
|
+
*
|
|
156
|
+
* @param node_type - The type of node to insert.
|
|
157
|
+
* @param selection - The selection at which to insert the node.
|
|
158
|
+
* @returns True if the node type can be inserted, false otherwise.
|
|
181
159
|
*/
|
|
182
|
-
can_insert(node_type: string, selection?: Selection): boolean;
|
|
160
|
+
can_insert(node_type: string, selection?: Selection | null): boolean;
|
|
183
161
|
/**
|
|
184
162
|
* Compute next possible insert position from a given selection
|
|
185
163
|
*
|
|
186
|
-
* @param
|
|
187
|
-
* @returns
|
|
164
|
+
* @param selection - Reference selection
|
|
165
|
+
* @returns The next node insert caret selection, or null if none is available
|
|
188
166
|
*/
|
|
189
|
-
get_next_node_insert_caret(selection?: Selection): Selection | null;
|
|
190
|
-
get_selected_text(): {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
annotations: any;
|
|
194
|
-
nodes: {};
|
|
195
|
-
};
|
|
167
|
+
get_next_node_insert_caret(selection?: Selection | null): Selection | null;
|
|
168
|
+
get_selected_text(): (Text & {
|
|
169
|
+
nodes: Record<string, DocumentNode>;
|
|
170
|
+
}) | null;
|
|
196
171
|
get_selected_annotated_nodes(): {
|
|
197
|
-
nodes:
|
|
198
|
-
main_nodes:
|
|
199
|
-
marks:
|
|
200
|
-
annotations:
|
|
201
|
-
};
|
|
202
|
-
get_selected_plain_text(): string;
|
|
203
|
-
get_selected_nodes():
|
|
172
|
+
nodes: Record<string, DocumentNode>;
|
|
173
|
+
main_nodes: NodeId[];
|
|
174
|
+
marks: Attachment[];
|
|
175
|
+
annotations: Attachment[];
|
|
176
|
+
} | null;
|
|
177
|
+
get_selected_plain_text(): string | null;
|
|
178
|
+
get_selected_nodes(): NodeId[] | null;
|
|
204
179
|
select_parent(): void;
|
|
205
180
|
/**
|
|
206
181
|
* Traverses the document and returns a list of nodes in depth-first order.
|
|
@@ -210,9 +185,7 @@ export default class Session {
|
|
|
210
185
|
* 2. Branch nodes second
|
|
211
186
|
* 3. Root node (entry point) last
|
|
212
187
|
*
|
|
213
|
-
*
|
|
214
|
-
* @returns {Array<DocumentNode>} Array of nodes in depth-first order
|
|
215
|
-
* @note Nodes that are not reachable from the entry point node will not be included
|
|
188
|
+
* Nodes that are not reachable from the entry point node will not be included.
|
|
216
189
|
*/
|
|
217
190
|
traverse(node_id: string): Array<DocumentNode>;
|
|
218
191
|
/**
|
|
@@ -220,32 +193,11 @@ export default class Session {
|
|
|
220
193
|
*
|
|
221
194
|
* We make a traversal to ensure that orphaned nodes are not included,
|
|
222
195
|
* and that leaf nodes go first, followed by branches and the root node at last.
|
|
223
|
-
*
|
|
224
|
-
* @returns {Document} The document
|
|
225
196
|
*/
|
|
226
197
|
to_json(): Document;
|
|
227
|
-
property_type(type:
|
|
228
|
-
count_references(node_id:
|
|
229
|
-
/**
|
|
230
|
-
* @param {NodeId} node_id
|
|
231
|
-
* @returns {NodeId[]}
|
|
232
|
-
*/
|
|
198
|
+
property_type(type: string, property: string): string;
|
|
199
|
+
count_references(node_id: NodeId): number;
|
|
233
200
|
get_referenced_nodes(node_id: NodeId): NodeId[];
|
|
234
|
-
#private;
|
|
235
201
|
}
|
|
236
|
-
export
|
|
237
|
-
/**
|
|
238
|
-
* - Initial selection state
|
|
239
|
-
*/
|
|
240
|
-
selection?: Selection;
|
|
241
|
-
};
|
|
242
|
-
import type { DocumentSchema } from './types.d.ts';
|
|
243
|
-
import type { Document } from './types.d.ts';
|
|
244
|
-
import type { Attachment } from './types.d.ts';
|
|
245
|
-
import type { Selection } from './types.d.ts';
|
|
246
|
-
import Transaction from './Transaction.svelte.js';
|
|
247
|
-
import type { DocumentPath } from './types.d.ts';
|
|
248
|
-
import type { NodeKind } from './types.d.ts';
|
|
249
|
-
import type { DocumentNode } from './types.d.ts';
|
|
250
|
-
import type { NodeId } from './types.d.ts';
|
|
202
|
+
export {};
|
|
251
203
|
//# sourceMappingURL=Session.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Session.svelte.
|
|
1
|
+
{"version":3,"file":"Session.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Session.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,yBAAyB,CAAC;AAoBlD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EACX,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,IAAI,EAEJ,eAAe,EACf,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAIpD,KAAK,YAAY,GAAG;IACnB,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IACxC,gBAAgB,EAAE,SAAS,GAAG,IAAI,CAAC;IACnC,eAAe,EAAE,SAAS,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,OAAO,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;;IAGrE,MAAM,EAAE,CAAC,CAAqB;IAE9B,GAAG,EAAE,QAAQ,CAA4B;IAEzC,MAAM,EAAE,aAAa,CAAkB;IAEvC,OAAO,EAAE,YAAY,EAAE,CAAkB;IACzC,aAAa,SAAkB;IAC/B,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAyB;IAI/D,QAAQ,EAAE,eAAe,CAAkB;IAC3C,MAAM,EAAE,MAAM,CAAkB;IAGhC,QAAQ,UAAqC;IAC7C,QAAQ,UAA0D;IAGlE,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAsC;IACtE,oBAAoB,WAA6C;IACjE,0BAA0B,WAAmD;IAC7E,cAAc,uBAAuE;IACrF,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAEpC;IACF,oBAAoB,uBAA6E;IACjG,iBAAiB,EAAE,kBAAkB,GAAG,IAAI,CAE1C;IAEF;;;;;OAKG;gBAEF,MAAM,EAAE,CAAC,EACT,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;KAAO;IAe/C;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAEhC;IAED;;;OAGG;IACH,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAGpC;IAED;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;;;;;;;OASG;IACH,2BAA2B,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAoC3D,WAAW,IAAI,MAAM;IAUrB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAQpD,wBAAwB,IAAI,MAAM,EAAE;IAMpC,8BAA8B,IAAI,MAAM,EAAE;IAO1C,iBAAiB,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAoBtC;;OAEG;IACH,IAAI,EAAE,IAAI,WAAW,CAGpB;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,KAAa,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAoDlF,IAAI,IAAI,IAAI,GAAG,SAAS;IAuBxB,IAAI,IAAI,IAAI,GAAG,SAAS;IAiBxB;;;;;;;;;;;;;;;;;;;;;OAqBG;IAEH,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,CAAC;IAI5C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU;IAIvC;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ;IAIlC;;;;;;OAMG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,GAAE,SAAS,GAAG,IAAqB,GAAG,OAAO;IAcpF;;;;;OAKG;IACH,0BAA0B,CAAC,SAAS,GAAE,SAAS,GAAG,IAAqB,GAAG,SAAS,GAAG,IAAI;IAe1F,iBAAiB,IAAI,CAAC,IAAI,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;KAAE,CAAC,GAAG,IAAI;IAuC5E,4BAA4B,IAAI;QAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACpC,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,KAAK,EAAE,UAAU,EAAE,CAAC;QACpB,WAAW,EAAE,UAAU,EAAE,CAAC;KAC1B,GAAG,IAAI;IA2CR,uBAAuB,IAAI,MAAM,GAAG,IAAI;IASxC,kBAAkB,IAAI,MAAM,EAAE,GAAG,IAAI;IAWrC,aAAa,IAAI,IAAI;IAqCrB;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC;IAQ9C;;;;;OAKG;IACH,OAAO,IAAI,QAAQ;IAanB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAKrD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAKzC,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;CAI/C"}
|