@aionbuilders/nabu 0.1.0-alpha.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 +131 -0
- package/dist/behaviors/index.d.ts +1 -0
- package/dist/behaviors/index.js +1 -0
- package/dist/behaviors/text/RichText.svelte +33 -0
- package/dist/behaviors/text/RichText.svelte.d.ts +11 -0
- package/dist/behaviors/text/index.d.ts +3 -0
- package/dist/behaviors/text/index.js +3 -0
- package/dist/behaviors/text/rich-text.extension.d.ts +2 -0
- package/dist/behaviors/text/rich-text.extension.js +75 -0
- package/dist/behaviors/text/text.behavior.svelte.d.ts +103 -0
- package/dist/behaviors/text/text.behavior.svelte.js +346 -0
- package/dist/blocks/Block.svelte +18 -0
- package/dist/blocks/Block.svelte.d.ts +11 -0
- package/dist/blocks/Nabu.svelte +31 -0
- package/dist/blocks/Nabu.svelte.d.ts +12 -0
- package/dist/blocks/block.svelte.d.ts +143 -0
- package/dist/blocks/block.svelte.js +364 -0
- package/dist/blocks/container.utils.d.ts +28 -0
- package/dist/blocks/container.utils.js +114 -0
- package/dist/blocks/heading/Heading.svelte +42 -0
- package/dist/blocks/heading/Heading.svelte.d.ts +11 -0
- package/dist/blocks/heading/heading.svelte.d.ts +45 -0
- package/dist/blocks/heading/heading.svelte.js +94 -0
- package/dist/blocks/heading/hooks/onBeforeInput.hook.d.ts +3 -0
- package/dist/blocks/heading/hooks/onBeforeInput.hook.js +58 -0
- package/dist/blocks/heading/index.d.ts +7 -0
- package/dist/blocks/heading/index.js +41 -0
- package/dist/blocks/index.d.ts +10 -0
- package/dist/blocks/index.js +12 -0
- package/dist/blocks/list/List.svelte +25 -0
- package/dist/blocks/list/List.svelte.d.ts +11 -0
- package/dist/blocks/list/ListItem.svelte +45 -0
- package/dist/blocks/list/ListItem.svelte.d.ts +11 -0
- package/dist/blocks/list/index.d.ts +10 -0
- package/dist/blocks/list/index.js +41 -0
- package/dist/blocks/list/list-item.svelte.d.ts +50 -0
- package/dist/blocks/list/list-item.svelte.js +213 -0
- package/dist/blocks/list/list.behavior.svelte.d.ts +23 -0
- package/dist/blocks/list/list.behavior.svelte.js +61 -0
- package/dist/blocks/list/list.svelte.d.ts +39 -0
- package/dist/blocks/list/list.svelte.js +139 -0
- package/dist/blocks/megablock.svelte.d.ts +13 -0
- package/dist/blocks/megablock.svelte.js +64 -0
- package/dist/blocks/nabu.svelte.d.ts +121 -0
- package/dist/blocks/nabu.svelte.js +395 -0
- package/dist/blocks/paragraph/Paragraph.svelte +38 -0
- package/dist/blocks/paragraph/Paragraph.svelte.d.ts +11 -0
- package/dist/blocks/paragraph/index.d.ts +7 -0
- package/dist/blocks/paragraph/index.js +44 -0
- package/dist/blocks/paragraph/paragraph.svelte.d.ts +41 -0
- package/dist/blocks/paragraph/paragraph.svelte.js +86 -0
- package/dist/blocks/selection.svelte.d.ts +38 -0
- package/dist/blocks/selection.svelte.js +143 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/utils/extensions.d.ts +69 -0
- package/dist/utils/extensions.js +43 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/selection.svelte.d.ts +219 -0
- package/dist/utils/selection.svelte.js +611 -0
- package/package.json +74 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { MegaBlock } from "..";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @import {Block, NabuNode} from "..";
|
|
5
|
+
* @import {LoroText} from "loro-crdt";
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {NabuNode<{type: "list", listType: "bullet" | "ordered"}>} ListNode
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export class ListBehavior {
|
|
13
|
+
/** @param {Block} block */
|
|
14
|
+
constructor(block) {
|
|
15
|
+
this.block = block;
|
|
16
|
+
this.node = /** @type {ListNode} */ (block.node);
|
|
17
|
+
this.listType = /** @type {"bullet" | "ordered"} */ (this.node.data.get("listType") || "bullet");
|
|
18
|
+
this.node.data.subscribe(() => {
|
|
19
|
+
this.listType = /** @type {"bullet" | "ordered"} */ (this.node.data.get("listType") || "bullet");
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @type {"bullet" | "ordered"} */
|
|
24
|
+
listType = $state("bullet");
|
|
25
|
+
|
|
26
|
+
/** @param {Block} block */
|
|
27
|
+
absorbs(block) {
|
|
28
|
+
const behavior = block?.behaviors.get("list");
|
|
29
|
+
if (!(behavior && behavior instanceof ListBehavior)) {
|
|
30
|
+
console.warn("Cannot merge: target block is not a list.");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!(block instanceof MegaBlock)) {
|
|
34
|
+
console.warn("Cannot merge: target block is not a mega block.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (behavior.listType !== this.listType) {
|
|
39
|
+
console.warn("Cannot merge lists of different types.");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 1. On fusionne les enfants de l'autre liste dans la nôtre
|
|
44
|
+
const otherChildren = block.node.children() || [];
|
|
45
|
+
otherChildren.forEach(child => {
|
|
46
|
+
console.warn("Merging child with id", child.id.toString(), "from list", block.id, "into list", this.block.id);
|
|
47
|
+
const data = /** @type {LoroText} */ (child.data.get("text"));
|
|
48
|
+
const targetIndex = this.block.node.children()?.length; // On ajoute à la fin de notre liste
|
|
49
|
+
if (targetIndex === undefined || targetIndex === null) {
|
|
50
|
+
console.error("Cannot merge: current block's node has no children array.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
child.move(this.block.node, targetIndex);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// block.destroy();
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Nabu, NabuNode } from "../nabu.svelte";
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {NabuNode<{type: "list", listType: "bullet" | "ordered"}>} ListNode
|
|
6
|
+
*/
|
|
7
|
+
export class List extends MegaBlock {
|
|
8
|
+
/** @param {Nabu} nabu @param {string} type @param {Object} [props={}] @param {string|null} [parentId=null] @param {number|null} [index=null] */
|
|
9
|
+
static create(nabu: Nabu, type: string, props?: Object, parentId?: string | null, index?: number | null): List;
|
|
10
|
+
/** @param {Nabu} nabu @param {ListNode} node */
|
|
11
|
+
constructor(nabu: Nabu, node: ListNode);
|
|
12
|
+
behavior: ListBehavior;
|
|
13
|
+
listType: "bullet" | "ordered";
|
|
14
|
+
component: import("svelte").Component<any, any, string> | import("svelte").Component<{
|
|
15
|
+
block: import("./list.svelte").List;
|
|
16
|
+
}, {}, "">;
|
|
17
|
+
root: boolean;
|
|
18
|
+
/** @param {List} otherList */
|
|
19
|
+
absorbs(otherList: List): true | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* @param {Event | null} event
|
|
22
|
+
* @param {{from: import('./list-item.svelte.js').ListItem, offset: number, delta: import('loro-crdt').Delta<string>}} data
|
|
23
|
+
*/
|
|
24
|
+
onSplit(event: Event | null, data: {
|
|
25
|
+
from: import("./list-item.svelte.js").ListItem;
|
|
26
|
+
offset: number;
|
|
27
|
+
delta: import("loro-crdt").Delta<string>;
|
|
28
|
+
}): {
|
|
29
|
+
block: import("..").Block;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export type ListNode = NabuNode<{
|
|
33
|
+
type: "list";
|
|
34
|
+
listType: "bullet" | "ordered";
|
|
35
|
+
}>;
|
|
36
|
+
import { MegaBlock } from "../megablock.svelte";
|
|
37
|
+
import { ListBehavior } from "./list.behavior.svelte";
|
|
38
|
+
import type { Nabu } from "../nabu.svelte";
|
|
39
|
+
import type { NabuNode } from "../nabu.svelte";
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { MegaBlock } from "../megablock.svelte";
|
|
2
|
+
import { ListBehavior } from "./list.behavior.svelte";
|
|
3
|
+
import ListComponent from "./List.svelte";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @import { Nabu, NabuNode } from "../nabu.svelte";
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {NabuNode<{type: "list", listType: "bullet" | "ordered"}>} ListNode
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export class List extends MegaBlock {
|
|
16
|
+
/** @param {Nabu} nabu @param {ListNode} node */
|
|
17
|
+
constructor(nabu, node) {
|
|
18
|
+
super(nabu, node);
|
|
19
|
+
|
|
20
|
+
this.behavior = new ListBehavior(this);
|
|
21
|
+
this.behaviors.set("list", this.behavior);
|
|
22
|
+
|
|
23
|
+
this.serializers.set('markdown', () =>
|
|
24
|
+
this.children
|
|
25
|
+
.map(child => child.serialize('markdown'))
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.join('\n')
|
|
28
|
+
);
|
|
29
|
+
this.serializers.set('json', () => ({
|
|
30
|
+
id: this.id,
|
|
31
|
+
type: 'list',
|
|
32
|
+
props: { listType: this.listType },
|
|
33
|
+
children: this.children.map(child => child.serialize('json')).filter(Boolean)
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
listType = $derived(this.behavior.listType);
|
|
38
|
+
|
|
39
|
+
component = $derived(this.nabu.components.get("list") || ListComponent);
|
|
40
|
+
|
|
41
|
+
root = $derived(!this.parent);
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/** @param {List} otherList */
|
|
45
|
+
absorbs(otherList) {
|
|
46
|
+
return this.behavior.absorbs(otherList);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {Event | null} event
|
|
51
|
+
* @param {{from: import('./list-item.svelte.js').ListItem, offset: number, delta: import('loro-crdt').Delta<string>}} data
|
|
52
|
+
*/
|
|
53
|
+
onSplit(event, data) {
|
|
54
|
+
const { from: sourceItem, offset, delta } = data;
|
|
55
|
+
|
|
56
|
+
// --- CAS 1 : L'item est vide (Demande de sortie de liste) ---
|
|
57
|
+
if (sourceItem.text.length === 0) {
|
|
58
|
+
const currentIndex = sourceItem.node.index();
|
|
59
|
+
const siblings = this.node.children();
|
|
60
|
+
const followers = siblings.slice(currentIndex + 1);
|
|
61
|
+
|
|
62
|
+
// 1. On identifie le point d'insertion (juste après la liste actuelle)
|
|
63
|
+
const parentNode = this.node.parent();
|
|
64
|
+
const grandParentId = parentNode?.id.toString() || null;
|
|
65
|
+
const myIndexInGrandParent = this.node.index();
|
|
66
|
+
|
|
67
|
+
// 2. On insère le paragraphe de sortie juste après cette liste
|
|
68
|
+
const newParagraph = this.nabu.insert("paragraph", {}, grandParentId, myIndexInGrandParent + 1);
|
|
69
|
+
|
|
70
|
+
// 3. Si on était au milieu de la liste, on crée une nouvelle liste après le paragraphe pour les "followers"
|
|
71
|
+
if (followers.length > 0) {
|
|
72
|
+
const newList = this.nabu.insert("list", { listType: this.listType }, grandParentId, myIndexInGrandParent + 2);
|
|
73
|
+
for (const follower of followers) {
|
|
74
|
+
this.nabu.tree.move(follower.id.toString(), newList.node.id.toString());
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 4. On détruit l'item vide actuel
|
|
79
|
+
sourceItem.destroy();
|
|
80
|
+
|
|
81
|
+
// 5. Si la liste d'origine est devenue vide, on la supprime aussi
|
|
82
|
+
if (currentIndex === 0 && followers.length === 0) {
|
|
83
|
+
this.destroy();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.nabu.commit();
|
|
87
|
+
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
this.nabu.selection.setCursor(newParagraph, 0);
|
|
90
|
+
}, 0);
|
|
91
|
+
|
|
92
|
+
return { block: newParagraph };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// --- CAS 2 : Comportement normal (Créer un nouvel item en dessous) ---
|
|
96
|
+
|
|
97
|
+
// 1. On efface la fin du texte dans l'item source
|
|
98
|
+
sourceItem.delete({from: offset, to: -1});
|
|
99
|
+
|
|
100
|
+
// 2. On trouve l'index de l'item source dans la liste
|
|
101
|
+
const currentIndex = sourceItem.node.index();
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
// 3. On demande à Nabu d'insérer un nouveau list-item au même niveau
|
|
105
|
+
const newItem = this.nabu.insert(
|
|
106
|
+
"list-item",
|
|
107
|
+
{ delta },
|
|
108
|
+
this.node.id.toString(), // Le parent est la liste actuelle
|
|
109
|
+
currentIndex + 1
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// 3.1. On transfère TOUS les enfants du sourceItem vers le newItem
|
|
113
|
+
const sourceChildren = sourceItem.node.children();
|
|
114
|
+
if (sourceChildren && sourceChildren.length > 0) {
|
|
115
|
+
for (const childNode of sourceChildren) {
|
|
116
|
+
// @ts-ignore - Le type string fonctionne avec move()
|
|
117
|
+
this.nabu.tree.move(childNode.id.toString(), newItem.node.id.toString());
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.nabu.commit();
|
|
122
|
+
|
|
123
|
+
// 4. On replace le curseur au début du nouvel item
|
|
124
|
+
setTimeout(() => {
|
|
125
|
+
this.nabu.selection.setCursor(newItem, 0);
|
|
126
|
+
}, 0);
|
|
127
|
+
|
|
128
|
+
return { block: newItem };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** @param {Nabu} nabu @param {string} type @param {Object} [props={}] @param {string|null} [parentId=null] @param {number|null} [index=null] */
|
|
132
|
+
static create(nabu, type, props = {}, parentId = null, index = null) {
|
|
133
|
+
const node = nabu.tree.createNode(parentId || undefined, index || undefined);
|
|
134
|
+
node.data.set("type", "list");
|
|
135
|
+
node.data.set("listType", props.listType || "bullet");
|
|
136
|
+
const block = new List(nabu, node);
|
|
137
|
+
return block;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Nabu, NabuNode } from "./nabu.svelte";
|
|
3
|
+
*/
|
|
4
|
+
export class MegaBlock extends Block {
|
|
5
|
+
/** @type {Block[]} */
|
|
6
|
+
children: Block[];
|
|
7
|
+
updateChildren(): void;
|
|
8
|
+
/** @param {Block[]} children @param {number | null} [index] */
|
|
9
|
+
adoptChildren(children: Block[], index?: number | null): {
|
|
10
|
+
skipped: boolean | Block[];
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
import { Block } from "./block.svelte";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Block } from "./block.svelte";
|
|
2
|
+
import { handleContainerBeforeInput } from "./container.utils.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @import { Nabu, NabuNode } from "./nabu.svelte";
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export class MegaBlock extends Block {
|
|
9
|
+
|
|
10
|
+
/** @param {Nabu} nabu @param {NabuNode} node */
|
|
11
|
+
constructor(nabu, node) {
|
|
12
|
+
super(nabu, node);
|
|
13
|
+
this.updateChildren();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** @type {Block[]} */
|
|
17
|
+
children = $state([]);
|
|
18
|
+
|
|
19
|
+
updateChildren() {
|
|
20
|
+
const childrenNodes = this.node.children();
|
|
21
|
+
if (!childrenNodes) return;
|
|
22
|
+
this.children = childrenNodes.map((childNode, i) => {
|
|
23
|
+
const id = childNode.id.toString();
|
|
24
|
+
let block = this.nabu.blocks.get(id);
|
|
25
|
+
const currentType = childNode.data.get("type");
|
|
26
|
+
|
|
27
|
+
if (!block || block.type !== currentType) {
|
|
28
|
+
if (block) {
|
|
29
|
+
this.nabu.blocks.delete(id);
|
|
30
|
+
this.nabu.blocksByType.get(block.type)?.delete(block);
|
|
31
|
+
}
|
|
32
|
+
block = Block.load(this.nabu, childNode);
|
|
33
|
+
}
|
|
34
|
+
block.parent = this;
|
|
35
|
+
block.index = i;
|
|
36
|
+
return block;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/** @param {Block[]} children @param {number | null} [index] */
|
|
42
|
+
adoptChildren(children, index = null) {
|
|
43
|
+
/** @type {Block[]} */
|
|
44
|
+
let skipped = [];
|
|
45
|
+
children.reverse().forEach(child => {
|
|
46
|
+
const childNode = child.node;
|
|
47
|
+
if (!childNode) return;
|
|
48
|
+
if (false) {
|
|
49
|
+
//TODO: conditions de skip, ex: si le block est déjà dans la mega block, ou si c'est un block parent de la mega block, etc.
|
|
50
|
+
console.warn("Skipping child with id", child.id, "because ...");
|
|
51
|
+
return skipped.push(child);
|
|
52
|
+
}
|
|
53
|
+
this.nabu.tree.move(childNode.id, this.node.id, index);
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return {skipped: skipped.length ? skipped.reverse() : false};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
/** @param {InputEvent} event */
|
|
61
|
+
beforeinput(event) {
|
|
62
|
+
return handleContainerBeforeInput(this, this.nabu, event);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {Component} from "svelte";
|
|
3
|
+
* @import { LoroTreeNode, LoroTree } from "loro-crdt";
|
|
4
|
+
* @import {Extension} from '../utils/extensions.js';
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @template {Object<string, any>} [T={}]
|
|
8
|
+
* @typedef {LoroTreeNode<{type: string} & T>} NabuNode
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} NabuInit
|
|
12
|
+
* @property {Extension[]} [extensions]
|
|
13
|
+
* @property {Uint8Array<ArrayBufferLike>} [snapshot]
|
|
14
|
+
*/
|
|
15
|
+
export class Nabu {
|
|
16
|
+
static BREAK: symbol;
|
|
17
|
+
static CONTINUE: symbol;
|
|
18
|
+
/** @param {NabuInit} init */
|
|
19
|
+
constructor(init?: NabuInit);
|
|
20
|
+
/** @type {LoroDoc} */
|
|
21
|
+
doc: LoroDoc;
|
|
22
|
+
selection: NabuSelection;
|
|
23
|
+
tree: LoroTree<Record<string, NabuNode<{}>>>;
|
|
24
|
+
content: import("loro-crdt").LoroMap<Record<string, unknown>>;
|
|
25
|
+
undoManager: UndoManager;
|
|
26
|
+
extensions: Extension[];
|
|
27
|
+
BREAK: symbol;
|
|
28
|
+
CONTINUE: symbol;
|
|
29
|
+
/** @type {SvelteMap<string, typeof Block>} */
|
|
30
|
+
registry: SvelteMap<string, typeof Block>;
|
|
31
|
+
/** @type {SvelteMap<string, Component>} */
|
|
32
|
+
components: SvelteMap<string, Component>;
|
|
33
|
+
/** @type {SvelteMap<string, Block>} */
|
|
34
|
+
blocks: SvelteMap<string, Block>;
|
|
35
|
+
/** @type {SvelteMap<string, SvelteSet<Block>>} */
|
|
36
|
+
blocksByType: SvelteMap<string, SvelteSet<Block>>;
|
|
37
|
+
/** @type {SvelteMap<string, any>} */
|
|
38
|
+
systems: SvelteMap<string, any>;
|
|
39
|
+
hooks: Map<any, any>;
|
|
40
|
+
/**
|
|
41
|
+
* Root-level serializers. Each function receives the Nabu instance and returns the serialized document.
|
|
42
|
+
* @type {Map<string, (nabu: Nabu) => any>}
|
|
43
|
+
*/
|
|
44
|
+
serializers: Map<string, (nabu: Nabu) => any>;
|
|
45
|
+
/** @type {Block[]} */
|
|
46
|
+
children: Block[];
|
|
47
|
+
get isEmpty(): boolean;
|
|
48
|
+
/** @param {string} format */
|
|
49
|
+
serialize(format: string): any;
|
|
50
|
+
init(): void;
|
|
51
|
+
/** Rafraîchit les blocs racines de l'éditeur */
|
|
52
|
+
updateRoots(): void;
|
|
53
|
+
trigger(hookName: any, ...args: any[]): void;
|
|
54
|
+
commit(): void;
|
|
55
|
+
/**
|
|
56
|
+
* Undo the last operation
|
|
57
|
+
*/
|
|
58
|
+
undo(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Redo the last undone operation
|
|
61
|
+
*/
|
|
62
|
+
redo(): void;
|
|
63
|
+
/** @param {{from: {offset: number, block: Block}, to: {offset: number, block: Block}}} [options={}] */
|
|
64
|
+
focus(options?: {
|
|
65
|
+
from: {
|
|
66
|
+
offset: number;
|
|
67
|
+
block: Block;
|
|
68
|
+
};
|
|
69
|
+
to: {
|
|
70
|
+
offset: number;
|
|
71
|
+
block: Block;
|
|
72
|
+
};
|
|
73
|
+
}): void;
|
|
74
|
+
/**
|
|
75
|
+
* Insère un nouveau bloc dans le document
|
|
76
|
+
* @param {string} type - Le type du bloc (ex: 'paragraph')
|
|
77
|
+
* @param {Object} [props={}] - Les propriétés initiales
|
|
78
|
+
* @param {string|null} [parentId=null] - ID du parent (null pour racine)
|
|
79
|
+
* @param {number|null} [index=null] - Position dans la liste des enfants
|
|
80
|
+
*/
|
|
81
|
+
insert(type: string, props?: Object, parentId?: string | null, index?: number | null): Block;
|
|
82
|
+
/** @param {Block} block */
|
|
83
|
+
delete(block: Block): void;
|
|
84
|
+
/**
|
|
85
|
+
* @param {string} nodeId
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
deleteNode(nodeId: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Route un événement vers le bon bloc en fonction de la sélection courante.
|
|
91
|
+
* @param {string} handlerName - Le nom de la méthode à appeler sur le bloc (ex: 'beforeinput', 'keydown')
|
|
92
|
+
* @param {Event} e - L'événement natif
|
|
93
|
+
* @param {string} [hookName] - Optionnel : Le nom du hook d'extension à vérifier en premier
|
|
94
|
+
*/
|
|
95
|
+
dispatchEventToSelection(handlerName: string, e: Event, hookName?: string): void;
|
|
96
|
+
/** @param {InputEvent} e */
|
|
97
|
+
handleBeforeinput(e: InputEvent): void;
|
|
98
|
+
/** @param {KeyboardEvent} e */
|
|
99
|
+
handleKeydown(e: KeyboardEvent): void;
|
|
100
|
+
/** @param {InputEvent} e */
|
|
101
|
+
beforeinput(e: InputEvent): any;
|
|
102
|
+
}
|
|
103
|
+
export type NabuNode<T extends {
|
|
104
|
+
[x: string]: any;
|
|
105
|
+
} = {}> = LoroTreeNode<{
|
|
106
|
+
type: string;
|
|
107
|
+
} & T>;
|
|
108
|
+
export type NabuInit = {
|
|
109
|
+
extensions?: Extension[] | undefined;
|
|
110
|
+
snapshot?: Uint8Array<ArrayBufferLike> | undefined;
|
|
111
|
+
};
|
|
112
|
+
import { LoroDoc } from 'loro-crdt';
|
|
113
|
+
import { NabuSelection } from './selection.svelte';
|
|
114
|
+
import type { LoroTree } from "loro-crdt";
|
|
115
|
+
import { UndoManager } from 'loro-crdt';
|
|
116
|
+
import type { Extension } from '../utils/extensions.js';
|
|
117
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
118
|
+
import { Block } from './block.svelte';
|
|
119
|
+
import type { Component } from "svelte";
|
|
120
|
+
import { SvelteSet } from 'svelte/reactivity';
|
|
121
|
+
import type { LoroTreeNode } from "loro-crdt";
|