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
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { serialize_path } from './utils.js';
|
|
3
|
+
import type { CustomPropertyProps } from './types.js';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** @type {CustomPropertyProps} */
|
|
7
|
-
let { path, tag = 'div', class: css_class, children, style, ...rest } = $props();
|
|
5
|
+
let { path, tag = 'div', class: css_class, children, style, ...rest }: CustomPropertyProps = $props();
|
|
8
6
|
let path_str = $derived(serialize_path(path));
|
|
9
7
|
|
|
10
8
|
</script>
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
type CustomProperty = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<CustomPropertyProps>): void;
|
|
5
|
-
};
|
|
1
|
+
import type { CustomPropertyProps } from './types.js';
|
|
6
2
|
declare const CustomProperty: import("svelte").Component<CustomPropertyProps, {}, "">;
|
|
7
|
-
|
|
3
|
+
type CustomProperty = ReturnType<typeof CustomProperty>;
|
|
4
|
+
export default CustomProperty;
|
|
8
5
|
//# sourceMappingURL=CustomProperty.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CustomProperty.svelte.
|
|
1
|
+
{"version":3,"file":"CustomProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CustomProperty.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAuBtD,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A command as required by the key mapper: anything with is_enabled/execute.
|
|
3
|
+
*/
|
|
4
|
+
type KeymapCommand = {
|
|
5
|
+
is_enabled: () => boolean;
|
|
6
|
+
execute: () => unknown;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A keymap maps key combo strings to arrays of commands.
|
|
10
|
+
*/
|
|
11
|
+
export type Keymap = Record<string, KeymapCommand[]>;
|
|
1
12
|
/**
|
|
2
13
|
* Validates and defines a keymap.
|
|
3
14
|
* Throws an error if any key combo is invalid.
|
|
4
15
|
* Valid formats: 'meta+e,ctrl+e' or 'meta+shift+a'
|
|
5
16
|
* Invalid: 'meta+e+a' (only one non-modifier key allowed)
|
|
6
17
|
*/
|
|
7
|
-
export function define_keymap(keymap:
|
|
18
|
+
export declare function define_keymap<K extends Keymap>(keymap: K): K;
|
|
8
19
|
/**
|
|
9
20
|
* KeyMapper manages keyboard shortcuts using a stack-based scope system.
|
|
10
21
|
*
|
|
@@ -17,20 +28,22 @@ export function define_keymap(keymap: any): any;
|
|
|
17
28
|
* mapper.push_scope(editor_keymap); // When editor gains focus
|
|
18
29
|
* mapper.pop_scope(); // When editor loses focus
|
|
19
30
|
*/
|
|
20
|
-
export class KeyMapper {
|
|
21
|
-
scope_stack:
|
|
31
|
+
export declare class KeyMapper {
|
|
32
|
+
scope_stack: Keymap[];
|
|
22
33
|
skip_onkeydown: boolean;
|
|
34
|
+
constructor();
|
|
23
35
|
/**
|
|
24
36
|
* Push a new scope onto the stack (becomes highest priority)
|
|
25
37
|
*/
|
|
26
|
-
push_scope(keymap:
|
|
38
|
+
push_scope(keymap: Keymap): void;
|
|
27
39
|
/**
|
|
28
40
|
* Pop the most recent scope from the stack
|
|
29
41
|
*/
|
|
30
|
-
pop_scope():
|
|
42
|
+
pop_scope(): Keymap | undefined;
|
|
31
43
|
/**
|
|
32
44
|
* Handle keyboard event by trying scopes from top to bottom
|
|
33
45
|
*/
|
|
34
|
-
handle_keydown(event:
|
|
46
|
+
handle_keydown(event: KeyboardEvent): void;
|
|
35
47
|
}
|
|
48
|
+
export {};
|
|
36
49
|
//# sourceMappingURL=KeyMapper.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KeyMapper.svelte.d.ts","sourceRoot":"","sources":["../src/lib/KeyMapper.svelte.
|
|
1
|
+
{"version":3,"file":"KeyMapper.svelte.d.ts","sourceRoot":"","sources":["../src/lib/KeyMapper.svelte.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,KAAK,aAAa,GAAG;IAAE,UAAU,EAAE,MAAM,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAA;CAAE,CAAC;AAE3E;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAgB5D;AA2ED;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;;IAOxB;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKhC;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,SAAS;IAM/B;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CAW1C"}
|
package/dist/KeyMapper.svelte.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { is_virtual_keyboard_active } from './utils.js';
|
|
2
|
-
|
|
3
2
|
const MODIFIER_KEYS = ['meta', 'ctrl', 'alt', 'shift'];
|
|
4
3
|
const MODIFIER_EVENT_KEYS = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
meta: 'metaKey',
|
|
5
|
+
ctrl: 'ctrlKey',
|
|
6
|
+
alt: 'altKey',
|
|
7
|
+
shift: 'shiftKey'
|
|
9
8
|
};
|
|
10
|
-
|
|
11
9
|
/**
|
|
12
10
|
* Validates and defines a keymap.
|
|
13
11
|
* Throws an error if any key combo is invalid.
|
|
@@ -15,58 +13,48 @@ const MODIFIER_EVENT_KEYS = {
|
|
|
15
13
|
* Invalid: 'meta+e+a' (only one non-modifier key allowed)
|
|
16
14
|
*/
|
|
17
15
|
export function define_keymap(keymap) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return keymap;
|
|
16
|
+
for (const [key_combo] of Object.entries(keymap)) {
|
|
17
|
+
const alternatives = key_combo.split(',');
|
|
18
|
+
for (const alternative of alternatives) {
|
|
19
|
+
const parts = alternative.trim().toLowerCase().split('+');
|
|
20
|
+
const non_modifiers = parts.filter((part) => !MODIFIER_KEYS.includes(part));
|
|
21
|
+
if (non_modifiers.length !== 1) {
|
|
22
|
+
throw new Error(`Invalid key combo: "${alternative}". Must have exactly one non-modifier key. Found: ${non_modifiers.length}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return keymap;
|
|
33
27
|
}
|
|
34
|
-
|
|
35
28
|
/**
|
|
36
29
|
* Matches a keyboard event against a key combo string.
|
|
37
30
|
* Example: 'meta+e,ctrl+e' matches either (metaKey && key==='e') OR (ctrlKey && key==='e')
|
|
38
31
|
*/
|
|
39
32
|
function matches_key_combo(key_combo, event, virtual_keyboard_active = false) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// Check if the key matches
|
|
65
|
-
const key_matches = event.key.toLowerCase() === non_modifier;
|
|
66
|
-
return modifiers_match && no_extra_modifiers && key_matches;
|
|
67
|
-
});
|
|
33
|
+
const alternatives = key_combo.split(',');
|
|
34
|
+
return alternatives.some((alternative) => {
|
|
35
|
+
const parts = alternative.trim().toLowerCase().split('+');
|
|
36
|
+
const modifiers = parts.filter((part) => MODIFIER_KEYS.includes(part));
|
|
37
|
+
const non_modifier = parts.find((part) => !MODIFIER_KEYS.includes(part));
|
|
38
|
+
if (virtual_keyboard_active && modifiers.length > 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// Check if all specified modifiers are pressed
|
|
42
|
+
const modifiers_match = modifiers.every((mod) => event[MODIFIER_EVENT_KEYS[mod]]);
|
|
43
|
+
// Check if no unspecified modifiers are pressed
|
|
44
|
+
// NOTE: On virtual keyboards (iOS / Anroid) modifier keys are just ignored, because
|
|
45
|
+
// they must be assumed accidental (e.g. Shift activated as a result of auto-capitalization)
|
|
46
|
+
const no_extra_modifiers = virtual_keyboard_active
|
|
47
|
+
? true
|
|
48
|
+
: MODIFIER_KEYS.every((mod) => {
|
|
49
|
+
if (modifiers.includes(mod))
|
|
50
|
+
return true; // This modifier is expected
|
|
51
|
+
return !event[MODIFIER_EVENT_KEYS[mod]]; // This modifier should NOT be pressed
|
|
52
|
+
});
|
|
53
|
+
// Check if the key matches
|
|
54
|
+
const key_matches = event.key.toLowerCase() === non_modifier;
|
|
55
|
+
return modifiers_match && no_extra_modifiers && key_matches;
|
|
56
|
+
});
|
|
68
57
|
}
|
|
69
|
-
|
|
70
58
|
/**
|
|
71
59
|
* Handles a key map by matching keyboard event against registered key combos
|
|
72
60
|
* and executing the first enabled command.
|
|
@@ -75,32 +63,27 @@ function matches_key_combo(key_combo, event, virtual_keyboard_active = false) {
|
|
|
75
63
|
* but don't crash the application.
|
|
76
64
|
*/
|
|
77
65
|
function handle_key_map(key_map, event) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
66
|
+
const virtual_keyboard_active = is_virtual_keyboard_active();
|
|
67
|
+
for (const [key_combo, commands] of Object.entries(key_map)) {
|
|
68
|
+
if (matches_key_combo(key_combo, event, virtual_keyboard_active)) {
|
|
69
|
+
// Find the first enabled command and execute it
|
|
70
|
+
const enabled_command = commands.find((cmd) => cmd.is_enabled());
|
|
71
|
+
if (enabled_command) {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
// Execute command (may be sync or async)
|
|
74
|
+
const result = enabled_command.execute();
|
|
75
|
+
// If it's a promise, handle errors (fire-and-forget)
|
|
76
|
+
if (result instanceof Promise) {
|
|
77
|
+
result.catch((err) => {
|
|
78
|
+
console.error('Command execution failed:', err);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
102
86
|
}
|
|
103
|
-
|
|
104
87
|
/**
|
|
105
88
|
* KeyMapper manages keyboard shortcuts using a stack-based scope system.
|
|
106
89
|
*
|
|
@@ -114,40 +97,40 @@ function handle_key_map(key_map, event) {
|
|
|
114
97
|
* mapper.pop_scope(); // When editor loses focus
|
|
115
98
|
*/
|
|
116
99
|
export class KeyMapper {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
100
|
+
scope_stack;
|
|
101
|
+
skip_onkeydown;
|
|
102
|
+
constructor() {
|
|
103
|
+
this.scope_stack = [];
|
|
104
|
+
this.skip_onkeydown = false;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Push a new scope onto the stack (becomes highest priority)
|
|
108
|
+
*/
|
|
109
|
+
push_scope(keymap) {
|
|
110
|
+
// console.log('pushed keymap', keymap);
|
|
111
|
+
this.scope_stack.push(keymap);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Pop the most recent scope from the stack
|
|
115
|
+
*/
|
|
116
|
+
pop_scope() {
|
|
117
|
+
const keymap = this.scope_stack.pop();
|
|
118
|
+
// console.log('popped keymap', keymap);
|
|
119
|
+
return keymap;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Handle keyboard event by trying scopes from top to bottom
|
|
123
|
+
*/
|
|
124
|
+
handle_keydown(event) {
|
|
125
|
+
// Key handling temporarily disabled (e.g. while character composition takes place)
|
|
126
|
+
if (this.skip_onkeydown)
|
|
127
|
+
return;
|
|
128
|
+
// console.log('KeyMapper.handle_keydown', event);
|
|
129
|
+
// Try from most specific (top of stack) to most general (bottom)
|
|
130
|
+
for (let i = this.scope_stack.length - 1; i >= 0; i--) {
|
|
131
|
+
if (handle_key_map(this.scope_stack[i], event)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
153
136
|
}
|
package/dist/Node.svelte
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte';
|
|
3
3
|
import { serialize_path } from './utils.js';
|
|
4
|
+
import type {
|
|
5
|
+
NodeArrayAttachmentContext,
|
|
6
|
+
NodeArrayRenderContext,
|
|
7
|
+
NodeProps,
|
|
8
|
+
SveditRenderContext
|
|
9
|
+
} from './types.js';
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
const svedit = getContext<SveditRenderContext>('svedit');
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** @type {NodeProps} */
|
|
10
|
-
let { path, children, tag = 'div', class: css_class, style = '', ...rest } = $props();
|
|
13
|
+
let { path, children, tag = 'div', class: css_class, style = '', ...rest }: NodeProps = $props();
|
|
11
14
|
|
|
12
15
|
let node = $derived(svedit.session.get(path));
|
|
13
16
|
let path_str = $derived(serialize_path(path));
|
|
14
17
|
|
|
15
|
-
const node_array_meta = getContext('node_array_meta');
|
|
16
|
-
let child_index = $derived(node_array_meta ?
|
|
18
|
+
const node_array_meta = getContext<NodeArrayRenderContext | undefined>('node_array_meta');
|
|
19
|
+
let child_index = $derived(node_array_meta ? (path.at(-1) as number) : -1);
|
|
17
20
|
let is_first = $derived(node_array_meta && child_index === 0);
|
|
18
21
|
let is_last = $derived(node_array_meta && child_index === node_array_meta.length - 1);
|
|
19
22
|
|
|
@@ -25,9 +28,9 @@
|
|
|
25
28
|
// `annotations` props.
|
|
26
29
|
let range_classes = $derived.by(() => {
|
|
27
30
|
if (child_index < 0 || !node_array_meta?.annotations_for) return '';
|
|
28
|
-
const classes = [];
|
|
31
|
+
const classes: string[] = [];
|
|
29
32
|
|
|
30
|
-
const add_classes = (range, prefix) => {
|
|
33
|
+
const add_classes = (range: NodeArrayAttachmentContext | null | undefined, prefix: string) => {
|
|
31
34
|
const range_type = range?.node?.type;
|
|
32
35
|
if (!range_type) return;
|
|
33
36
|
classes.push(`${prefix}-${range_type}`);
|
|
@@ -46,9 +49,9 @@
|
|
|
46
49
|
<svelte:element
|
|
47
50
|
this={tag}
|
|
48
51
|
id={node.id}
|
|
49
|
-
class="node-{node.type} {css_class}{range_classes
|
|
50
|
-
?
|
|
51
|
-
: ''}{
|
|
52
|
+
class="node-{node.type} {css_class}{range_classes ? ` ${range_classes}` : ''}{is_first
|
|
53
|
+
? ' first'
|
|
54
|
+
: ''}{is_last ? ' last' : ''}"
|
|
52
55
|
data-node-id={node.id}
|
|
53
56
|
data-path={path_str}
|
|
54
57
|
data-type="node"
|
package/dist/Node.svelte.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
+
import type { NodeProps } from './types.js';
|
|
2
|
+
declare const Node: import("svelte").Component<NodeProps, {}, "">;
|
|
3
|
+
type Node = ReturnType<typeof Node>;
|
|
1
4
|
export default Node;
|
|
2
|
-
type Node = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<NodeProps>): void;
|
|
5
|
-
};
|
|
6
|
-
declare const Node: import("svelte").Component<import("./types.d.ts").NodeProps, {}, "">;
|
|
7
5
|
//# sourceMappingURL=Node.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Node.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Node.svelte.
|
|
1
|
+
{"version":3,"file":"Node.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Node.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGV,SAAS,EAET,MAAM,YAAY,CAAC;AAuDrB,QAAA,MAAM,IAAI,+CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
|
|
@@ -1,20 +1,33 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
3
|
import UnknownNode from './UnknownNode.svelte';
|
|
4
4
|
import { serialize_path, calculate_fragment_ranges } from './utils.js';
|
|
5
5
|
import DefaultNodeGap from './NodeGap.svelte';
|
|
6
6
|
import DefaultNodeGapMarkers from './NodeGapMarkers.svelte';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
import type {
|
|
8
|
+
NodeArrayPropertyProps,
|
|
9
|
+
NodeArrayAttachmentContext,
|
|
10
|
+
NodeArrayFragment,
|
|
11
|
+
NodeId,
|
|
12
|
+
Attachment,
|
|
13
|
+
Mark,
|
|
14
|
+
NodeArrayRenderContext,
|
|
15
|
+
SveditRenderContext
|
|
16
|
+
} from './types.js';
|
|
17
|
+
|
|
18
|
+
const svedit = getContext<SveditRenderContext>('svedit');
|
|
11
19
|
let NodeGap = $derived(svedit.session.config.system_components?.node_gap ?? DefaultNodeGap);
|
|
12
20
|
let NodeGapMarkers = $derived(
|
|
13
21
|
svedit.session.config.system_components?.node_gap_markers ?? DefaultNodeGapMarkers
|
|
14
22
|
);
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
let {
|
|
25
|
+
path,
|
|
26
|
+
tag = 'div',
|
|
27
|
+
class: css_class,
|
|
28
|
+
style = '',
|
|
29
|
+
...rest
|
|
30
|
+
}: NodeArrayPropertyProps = $props();
|
|
18
31
|
|
|
19
32
|
// Pre-joined once per path change; reused by data-path and by every
|
|
20
33
|
// NodeGap's should_position_gap call to avoid N+1 joins per render.
|
|
@@ -27,9 +40,9 @@
|
|
|
27
40
|
|
|
28
41
|
let fragments = $derived(get_fragments(node_ids, marks));
|
|
29
42
|
|
|
30
|
-
function get_fragments(node_ids, marks) {
|
|
43
|
+
function get_fragments(node_ids: NodeId[], marks: Mark[]): NodeArrayFragment[] {
|
|
31
44
|
const ranges = calculate_fragment_ranges(node_ids.length, marks);
|
|
32
|
-
|
|
45
|
+
const fragments: NodeArrayFragment[] = [];
|
|
33
46
|
|
|
34
47
|
for (const range of ranges) {
|
|
35
48
|
const nodes_slice = node_ids.slice(range.start_offset, range.end_offset);
|
|
@@ -41,7 +54,7 @@
|
|
|
41
54
|
node,
|
|
42
55
|
nodes: nodes_slice,
|
|
43
56
|
start_index: range.start_offset,
|
|
44
|
-
mark_index: range.mark_index
|
|
57
|
+
mark_index: range.mark_index!
|
|
45
58
|
});
|
|
46
59
|
} else if (range.type === 'content') {
|
|
47
60
|
fragments.push({
|
|
@@ -54,7 +67,7 @@
|
|
|
54
67
|
return fragments;
|
|
55
68
|
}
|
|
56
69
|
|
|
57
|
-
function get_node_key(node_id, index) {
|
|
70
|
+
function get_node_key(node_id: NodeId, index: number): string {
|
|
58
71
|
let occurrence = 0;
|
|
59
72
|
for (let current_index = 0; current_index < index; current_index++) {
|
|
60
73
|
if (node_ids[current_index] === node_id) occurrence += 1;
|
|
@@ -62,10 +75,11 @@
|
|
|
62
75
|
return `${node_id}:${occurrence}`;
|
|
63
76
|
}
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
78
|
+
function get_range_context(
|
|
79
|
+
range: Attachment,
|
|
80
|
+
index: number,
|
|
81
|
+
node_index: number
|
|
82
|
+
): NodeArrayAttachmentContext {
|
|
69
83
|
const node = svedit.session.get(range.node_id);
|
|
70
84
|
const is_start = node_index === range.start_offset;
|
|
71
85
|
const is_end = node_index === range.end_offset - 1;
|
|
@@ -80,18 +94,21 @@
|
|
|
80
94
|
};
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
function get_covering_ranges(
|
|
97
|
+
function get_covering_ranges(
|
|
98
|
+
ranges: Attachment[],
|
|
99
|
+
node_index: number
|
|
100
|
+
): NodeArrayAttachmentContext[] {
|
|
84
101
|
return ranges
|
|
85
102
|
.map((range, index) => ({ range, index }))
|
|
86
103
|
.filter(({ range }) => range.start_offset <= node_index && node_index < range.end_offset)
|
|
87
104
|
.map(({ range, index }) => get_range_context(range, index, node_index));
|
|
88
105
|
}
|
|
89
106
|
|
|
90
|
-
function get_annotation_contexts(node_index) {
|
|
107
|
+
function get_annotation_contexts(node_index: number): NodeArrayAttachmentContext[] {
|
|
91
108
|
return get_covering_ranges(annotations, node_index);
|
|
92
109
|
}
|
|
93
110
|
|
|
94
|
-
function get_mark(node_index) {
|
|
111
|
+
function get_mark(node_index: number): NodeArrayAttachmentContext | null {
|
|
95
112
|
// The single mark wrapping this node, or null. Mark exclusivity
|
|
96
113
|
// guarantees at most one. Annotations never wrap and are exposed via
|
|
97
114
|
// `annotations` instead.
|
|
@@ -107,17 +124,17 @@
|
|
|
107
124
|
serialize_path(svedit.session.selection.path) === path_str
|
|
108
125
|
);
|
|
109
126
|
|
|
110
|
-
setContext('node_array_meta', {
|
|
127
|
+
setContext<NodeArrayRenderContext>('node_array_meta', {
|
|
111
128
|
get length() {
|
|
112
129
|
return node_ids.length;
|
|
113
130
|
},
|
|
114
131
|
// Lets Node self-serve the marks and annotations covering a child, so
|
|
115
132
|
// node wrappers can carry range classes without every node component
|
|
116
133
|
// having to thread the `mark`/`annotations` props through.
|
|
117
|
-
mark_for(node_index) {
|
|
134
|
+
mark_for(node_index: number) {
|
|
118
135
|
return get_mark(node_index);
|
|
119
136
|
},
|
|
120
|
-
annotations_for(node_index) {
|
|
137
|
+
annotations_for(node_index: number) {
|
|
121
138
|
return get_annotation_contexts(node_index);
|
|
122
139
|
}
|
|
123
140
|
});
|
|
@@ -145,7 +162,7 @@
|
|
|
145
162
|
<NodeGap array_path={path} offset={0} count={0} empty />
|
|
146
163
|
</div>
|
|
147
164
|
{/if}
|
|
148
|
-
{#snippet render_nodes(nodes_slice, start_index)}
|
|
165
|
+
{#snippet render_nodes(nodes_slice: NodeId[], start_index: number)}
|
|
149
166
|
{#each nodes_slice as id, slice_index (get_node_key(id, start_index + slice_index))}
|
|
150
167
|
{@const index = start_index + slice_index}
|
|
151
168
|
{@const node = svedit.session.get(id)}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
+
import type { NodeArrayPropertyProps } from './types.js';
|
|
2
|
+
declare const NodeArrayProperty: import("svelte").Component<NodeArrayPropertyProps, {}, "">;
|
|
3
|
+
type NodeArrayProperty = ReturnType<typeof NodeArrayProperty>;
|
|
1
4
|
export default NodeArrayProperty;
|
|
2
|
-
type NodeArrayProperty = {
|
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
-
$set?(props: Partial<NodeArrayPropertyProps>): void;
|
|
5
|
-
};
|
|
6
|
-
declare const NodeArrayProperty: import("svelte").Component<import("./types.d.ts").NodeArrayPropertyProps, {}, "">;
|
|
7
5
|
//# sourceMappingURL=NodeArrayProperty.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeArrayProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeArrayProperty.svelte.
|
|
1
|
+
{"version":3,"file":"NodeArrayProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeArrayProperty.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,sBAAsB,EAQtB,MAAM,YAAY,CAAC;AAwLrB,QAAA,MAAM,iBAAiB,4DAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
package/dist/NodeCaret.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* Visual insertion caret rendered inside the active insertion marker.
|
|
4
4
|
*
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
--_cp: var(--node-caret-row-inline-position, 50%);
|
|
31
31
|
content: '';
|
|
32
32
|
position: absolute;
|
|
33
|
-
background: var(--node-caret-bg, var(--
|
|
33
|
+
background: var(--node-caret-bg, var(--editing));
|
|
34
34
|
/* Increase the visibility of the caret by contrasting it with a box shadow that's the inverted brightness of the current text color. */
|
|
35
35
|
/* Component developers must set their background color and text color on the node itself, not a child element, for this to work. */
|
|
36
36
|
box-shadow: var(--node-caret-shadow, 0 0 0 0.5px oklch(from currentColor calc(1 - l) c h));
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
export default NodeCaret;
|
|
2
|
-
type NodeCaret = SvelteComponent<{
|
|
3
|
-
[x: string]: never;
|
|
4
|
-
}, {
|
|
5
|
-
[evt: string]: CustomEvent<any>;
|
|
6
|
-
}, {}> & {
|
|
7
|
-
$$bindings?: string;
|
|
8
|
-
};
|
|
9
|
-
declare const NodeCaret: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
-
[x: string]: never;
|
|
11
|
-
}, {
|
|
12
|
-
[evt: string]: CustomEvent<any>;
|
|
13
|
-
}, {}, {}, string>;
|
|
14
1
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
-
new (options: import(
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
16
3
|
$$bindings?: Bindings;
|
|
17
4
|
} & Exports;
|
|
18
5
|
(internal: unknown, props: {
|
|
@@ -24,4 +11,9 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
24
11
|
};
|
|
25
12
|
z_$$bindings?: Bindings;
|
|
26
13
|
}
|
|
14
|
+
declare const NodeCaret: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type NodeCaret = InstanceType<typeof NodeCaret>;
|
|
18
|
+
export default NodeCaret;
|
|
27
19
|
//# sourceMappingURL=NodeCaret.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeCaret.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeCaret.svelte.
|
|
1
|
+
{"version":3,"file":"NodeCaret.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NodeCaret.svelte.ts"],"names":[],"mappings":"AAmBA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,SAAS;;kBAA+E,CAAC;AAC7E,KAAK,SAAS,GAAG,YAAY,CAAC,OAAO,SAAS,CAAC,CAAC;AAClD,eAAe,SAAS,CAAC"}
|