dragon-editor 3.8.7 → 4.0.1
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 +10 -9
- package/dist/module.json +1 -1
- package/dist/module.mjs +9 -7
- package/dist/runtime/components/Block/Code.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Code.vue +193 -0
- package/dist/runtime/components/Block/Code.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Custom.d.vue.ts +9 -0
- package/dist/runtime/components/Block/Custom.vue +28 -0
- package/dist/runtime/components/Block/Custom.vue.d.ts +9 -0
- package/dist/runtime/components/Block/Divider.d.vue.ts +9 -0
- package/dist/runtime/components/Block/Divider.vue +27 -0
- package/dist/runtime/components/Block/Divider.vue.d.ts +9 -0
- package/dist/runtime/components/Block/Heading.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Heading.vue +84 -0
- package/dist/runtime/components/Block/Heading.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Image.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Image.vue +146 -0
- package/dist/runtime/components/Block/Image.vue.d.ts +13 -0
- package/dist/runtime/components/Block/List.d.vue.ts +13 -0
- package/dist/runtime/components/Block/List.vue +170 -0
- package/dist/runtime/components/Block/List.vue.d.ts +13 -0
- package/dist/runtime/components/Block/Text.d.vue.ts +13 -0
- package/dist/runtime/components/Block/Text.vue +84 -0
- package/dist/runtime/components/Block/Text.vue.d.ts +13 -0
- package/dist/runtime/components/DragonEditor.d.vue.ts +27 -22
- package/dist/runtime/components/DragonEditor.vue +311 -474
- package/dist/runtime/components/DragonEditor.vue.d.ts +27 -22
- package/dist/runtime/components/DragonEditorViewer.d.vue.ts +12 -5
- package/dist/runtime/components/DragonEditorViewer.vue +200 -227
- package/dist/runtime/components/DragonEditorViewer.vue.d.ts +12 -5
- package/dist/runtime/components/MenuBar.d.vue.ts +3 -0
- package/dist/runtime/components/MenuBar.vue +385 -0
- package/dist/runtime/components/MenuBar.vue.d.ts +3 -0
- package/dist/runtime/scss/editor.css +237 -283
- package/dist/runtime/scss/viewer.css +184 -210
- package/dist/runtime/store/editor.d.ts +2 -0
- package/dist/runtime/store/editor.js +59 -0
- package/dist/runtime/type.d.mts +101 -124
- package/dist/runtime/utils/data/block.d.ts +20 -0
- package/dist/runtime/utils/data/block.js +663 -0
- package/dist/runtime/utils/data/cursor.d.ts +9 -0
- package/dist/runtime/utils/data/cursor.js +137 -0
- package/dist/runtime/utils/data/index.d.ts +5 -0
- package/dist/runtime/utils/data/index.js +17 -0
- package/dist/runtime/utils/data/node.d.ts +9 -0
- package/dist/runtime/utils/data/node.js +101 -0
- package/dist/runtime/utils/event/cursor.d.ts +3 -6
- package/dist/runtime/utils/event/cursor.js +52 -105
- package/dist/runtime/utils/event/index.d.ts +2 -6
- package/dist/runtime/utils/event/index.js +48 -6
- package/dist/runtime/utils/event/keyboard.d.ts +22 -7
- package/dist/runtime/utils/event/keyboard.js +910 -1406
- package/dist/runtime/utils/layout/body.d.ts +3 -4
- package/dist/runtime/utils/layout/body.js +83 -51
- package/dist/runtime/utils/layout/icon.d.ts +1 -2
- package/dist/runtime/utils/layout/icon.js +64 -67
- package/dist/runtime/utils/layout/index.d.ts +0 -3
- package/dist/runtime/utils/layout/index.js +0 -3
- package/dist/runtime/utils/node/element.d.ts +4 -6
- package/dist/runtime/utils/node/element.js +58 -71
- package/dist/runtime/utils/node/index.d.ts +1 -1
- package/dist/runtime/utils/node/index.js +1 -1
- package/dist/runtime/utils/node/style.d.ts +5 -0
- package/dist/runtime/utils/node/style.js +702 -0
- package/package.json +32 -18
- package/dist/runtime/utils/event/block.d.ts +0 -7
- package/dist/runtime/utils/event/block.js +0 -110
- package/dist/runtime/utils/event/data.d.ts +0 -8
- package/dist/runtime/utils/event/data.js +0 -379
- package/dist/runtime/utils/event/mouse.d.ts +0 -11
- package/dist/runtime/utils/event/mouse.js +0 -85
- package/dist/runtime/utils/event/scroll.d.ts +0 -3
- package/dist/runtime/utils/event/scroll.js +0 -29
- package/dist/runtime/utils/event/touch.d.ts +0 -5
- package/dist/runtime/utils/event/touch.js +0 -10
- package/dist/runtime/utils/event/window.d.ts +0 -5
- package/dist/runtime/utils/event/window.js +0 -47
- package/dist/runtime/utils/layout/block.d.ts +0 -7
- package/dist/runtime/utils/layout/block.js +0 -123
- package/dist/runtime/utils/layout/controlbar.d.ts +0 -3
- package/dist/runtime/utils/layout/controlbar.js +0 -99
- package/dist/runtime/utils/layout/menuBar.d.ts +0 -3
- package/dist/runtime/utils/layout/menuBar.js +0 -408
- package/dist/runtime/utils/node/block.d.ts +0 -19
- package/dist/runtime/utils/node/block.js +0 -256
- package/dist/runtime/utils/style/anchor.d.ts +0 -5
- package/dist/runtime/utils/style/anchor.js +0 -245
- package/dist/runtime/utils/style/decoration.d.ts +0 -4
- package/dist/runtime/utils/style/decoration.js +0 -378
- package/dist/runtime/utils/style/index.d.ts +0 -2
- package/dist/runtime/utils/style/index.js +0 -2
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-memo="memoData"
|
|
4
|
+
class="de-block de-image-block"
|
|
5
|
+
:class="props.data.classList"
|
|
6
|
+
@click="setEdit"
|
|
7
|
+
@mousemove="resizingEvent"
|
|
8
|
+
@touchmove="resizingEvent"
|
|
9
|
+
>
|
|
10
|
+
<div
|
|
11
|
+
class="de-image-area"
|
|
12
|
+
:data-maxwidth="props.data.maxWidth"
|
|
13
|
+
>
|
|
14
|
+
<button
|
|
15
|
+
v-if="props.isEdit === true"
|
|
16
|
+
class="de-btn de-btn-left"
|
|
17
|
+
@mousedown="startResizeEvent($event, 'left')"
|
|
18
|
+
@touchstart="startResizeEvent($event, 'left')"
|
|
19
|
+
></button>
|
|
20
|
+
<button
|
|
21
|
+
v-if="props.isEdit === true"
|
|
22
|
+
class="de-btn de-btn-right"
|
|
23
|
+
@mousedown="startResizeEvent($event, 'right')"
|
|
24
|
+
@touchstart="startResizeEvent($event, 'right')"
|
|
25
|
+
></button>
|
|
26
|
+
<img
|
|
27
|
+
class="de-img"
|
|
28
|
+
:src="editorStore.option.mediaHostURL + props.data.src"
|
|
29
|
+
:alt="props.data.caption"
|
|
30
|
+
draggable="false"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<p
|
|
35
|
+
v-html="props.data.caption"
|
|
36
|
+
class="de-caption"
|
|
37
|
+
:contenteditable="props.isEdit === true"
|
|
38
|
+
@focus="setEdit"
|
|
39
|
+
@keydown="keydownEvent"
|
|
40
|
+
@input="updateData"
|
|
41
|
+
@paste="_normalPasteEvent($event, setEdit, abortEdit)"
|
|
42
|
+
></p>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script setup>
|
|
47
|
+
import { computed } from "vue";
|
|
48
|
+
import { useEditorStore } from "../../store/editor";
|
|
49
|
+
import { _imageEnterEvent, _blockTabEvent, _moveBlockDefaultEvent, _normalPasteEvent, _updateCursorData } from "../../utils/event";
|
|
50
|
+
const editorStore = useEditorStore();
|
|
51
|
+
const props = defineProps({
|
|
52
|
+
data: { type: null, required: true },
|
|
53
|
+
isEdit: { type: Boolean, required: true },
|
|
54
|
+
index: { type: Number, required: true }
|
|
55
|
+
});
|
|
56
|
+
const emit = defineEmits(["update"]);
|
|
57
|
+
const memoData = computed(() => {
|
|
58
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
59
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
60
|
+
return [memoKey];
|
|
61
|
+
});
|
|
62
|
+
let mouseXPosition = 0;
|
|
63
|
+
let mouseDuration = "left";
|
|
64
|
+
let startMaxWidth = 0;
|
|
65
|
+
function setEdit() {
|
|
66
|
+
editorStore.selectedBlockIndex = props.index;
|
|
67
|
+
editorStore.selectedBlockId = props.data.id;
|
|
68
|
+
_updateCursorData();
|
|
69
|
+
}
|
|
70
|
+
function abortEdit() {
|
|
71
|
+
editorStore.selectedBlockIndex = -1;
|
|
72
|
+
editorStore.selectedBlockId = "";
|
|
73
|
+
}
|
|
74
|
+
function keydownEvent(event) {
|
|
75
|
+
if (event.isComposing === false) {
|
|
76
|
+
switch (event.key) {
|
|
77
|
+
case "Enter":
|
|
78
|
+
if (event.shiftKey === false) {
|
|
79
|
+
_imageEnterEvent(event, props.data, props.index);
|
|
80
|
+
} else {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case "ArrowUp":
|
|
85
|
+
_moveBlockDefaultEvent(event, "up");
|
|
86
|
+
break;
|
|
87
|
+
case "ArrowDown":
|
|
88
|
+
_moveBlockDefaultEvent(event, "down");
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function updateData(event) {
|
|
96
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
97
|
+
newData.caption = event.target.innerHTML;
|
|
98
|
+
emit("update", newData);
|
|
99
|
+
}
|
|
100
|
+
function startResizeEvent(event, duration) {
|
|
101
|
+
if (editorStore.status.isImageResizeActive === false) {
|
|
102
|
+
editorStore.status.isImageResizeActive = true;
|
|
103
|
+
if ("touches" in event) {
|
|
104
|
+
const touch = event.touches[0] || event.changedTouches[0];
|
|
105
|
+
if (touch !== void 0) {
|
|
106
|
+
mouseXPosition = touch.screenX;
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
mouseXPosition = event.screenX;
|
|
110
|
+
}
|
|
111
|
+
mouseDuration = duration;
|
|
112
|
+
startMaxWidth = props.data.maxWidth;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function resizingEvent(event) {
|
|
116
|
+
if (editorStore.status.isImageResizeActive === true && editorStore.element.body !== null) {
|
|
117
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
118
|
+
const bodyRect = editorStore.element.body.getBoundingClientRect();
|
|
119
|
+
const bodyWidthHalf = bodyRect.width / 2 - 50;
|
|
120
|
+
let currentX = 0;
|
|
121
|
+
if ("touches" in event) {
|
|
122
|
+
const touch = event.touches[0] || event.changedTouches[0];
|
|
123
|
+
if (touch !== void 0) {
|
|
124
|
+
currentX = touch.screenX;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
currentX = event.screenX;
|
|
128
|
+
}
|
|
129
|
+
const diffX = mouseXPosition - currentX;
|
|
130
|
+
let movePercent = 100 / bodyWidthHalf * diffX;
|
|
131
|
+
if (mouseDuration === "right") {
|
|
132
|
+
movePercent = -1 * movePercent;
|
|
133
|
+
}
|
|
134
|
+
let newMaxWidth = startMaxWidth + Math.floor(movePercent);
|
|
135
|
+
if (newMaxWidth < 25) {
|
|
136
|
+
newMaxWidth = 25;
|
|
137
|
+
}
|
|
138
|
+
if (newMaxWidth > 100) {
|
|
139
|
+
newMaxWidth = 100;
|
|
140
|
+
}
|
|
141
|
+
newData.maxWidth = newMaxWidth;
|
|
142
|
+
abortEdit();
|
|
143
|
+
emit("update", newData);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEImageBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEImageBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEImageBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEImageBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEListBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEListBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEListBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEListBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component :is="renderList()" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup>
|
|
6
|
+
import { useEditorStore } from "../../store/editor";
|
|
7
|
+
import { ref, h, withMemo } from "vue";
|
|
8
|
+
import { _listBlockEnterEvent, _listChildTabEvent, _moveListChildEvent, _listBackspaceEvent, _listDeleteEvent, _normalPasteEvent, _updateCursorData } from "../../utils/event";
|
|
9
|
+
const editorStore = useEditorStore();
|
|
10
|
+
const props = defineProps({
|
|
11
|
+
data: { type: null, required: true },
|
|
12
|
+
isEdit: { type: Boolean, required: true },
|
|
13
|
+
index: { type: Number, required: true }
|
|
14
|
+
});
|
|
15
|
+
const emit = defineEmits(["update"]);
|
|
16
|
+
const childIndex = ref(-1);
|
|
17
|
+
const childId = ref("");
|
|
18
|
+
let memoCache = [];
|
|
19
|
+
function setEdit(liIndex, id) {
|
|
20
|
+
editorStore.selectedBlockId = props.data.id;
|
|
21
|
+
editorStore.selectedBlockIndex = props.index;
|
|
22
|
+
childIndex.value = liIndex;
|
|
23
|
+
childId.value = id;
|
|
24
|
+
_updateCursorData();
|
|
25
|
+
}
|
|
26
|
+
function abortEdit() {
|
|
27
|
+
childIndex.value = -1;
|
|
28
|
+
childId.value = "";
|
|
29
|
+
memoCache = [];
|
|
30
|
+
}
|
|
31
|
+
function updateData(event, liIndex) {
|
|
32
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
33
|
+
if (newData.child[liIndex] !== void 0) {
|
|
34
|
+
newData.child[liIndex].textContent = event.target.innerHTML;
|
|
35
|
+
}
|
|
36
|
+
emit("update", newData);
|
|
37
|
+
}
|
|
38
|
+
function keydownEvent(event) {
|
|
39
|
+
if (event.isComposing === false) {
|
|
40
|
+
switch (event.key) {
|
|
41
|
+
case "Enter":
|
|
42
|
+
if (event.shiftKey === false) {
|
|
43
|
+
_listBlockEnterEvent(event, props.data, props.index, childIndex.value, setEdit, abortEdit);
|
|
44
|
+
} else {
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
case "Tab":
|
|
48
|
+
_listChildTabEvent(event, props.data, props.index, childIndex.value, setEdit, abortEdit);
|
|
49
|
+
break;
|
|
50
|
+
case "ArrowUp":
|
|
51
|
+
_moveListChildEvent(event, props.data, props.index, childIndex.value, "up");
|
|
52
|
+
break;
|
|
53
|
+
case "ArrowDown":
|
|
54
|
+
_moveListChildEvent(event, props.data, props.index, childIndex.value, "down");
|
|
55
|
+
break;
|
|
56
|
+
case "Backspace":
|
|
57
|
+
_listBackspaceEvent(event, childIndex.value);
|
|
58
|
+
break;
|
|
59
|
+
case "Delete":
|
|
60
|
+
_listDeleteEvent(event, childIndex.value, setEdit, abortEdit);
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function createTreeStructure(listData) {
|
|
68
|
+
const structure = [];
|
|
69
|
+
function insertNode(parent, node, currentLevel) {
|
|
70
|
+
if (currentLevel >= 5) {
|
|
71
|
+
parent.children.push(node);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const lastChild = parent.children[parent.children.length - 1];
|
|
75
|
+
if (lastChild !== void 0 && node.depth > lastChild.depth) {
|
|
76
|
+
insertNode(lastChild, node, currentLevel + 1);
|
|
77
|
+
} else {
|
|
78
|
+
parent.children.push(node);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
listData.forEach((item, index) => {
|
|
82
|
+
let depth = item.depth || 0;
|
|
83
|
+
if (depth > 5) {
|
|
84
|
+
depth = 5;
|
|
85
|
+
}
|
|
86
|
+
const node = {
|
|
87
|
+
liIndex: index,
|
|
88
|
+
depth,
|
|
89
|
+
child: item,
|
|
90
|
+
children: []
|
|
91
|
+
};
|
|
92
|
+
if (structure.length === 0) {
|
|
93
|
+
structure.push(node);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const lastNode = structure[structure.length - 1];
|
|
97
|
+
if (lastNode !== void 0) {
|
|
98
|
+
if (node.depth === lastNode.depth) {
|
|
99
|
+
structure.push(node);
|
|
100
|
+
} else if (node.depth > lastNode.depth) {
|
|
101
|
+
insertNode(lastNode, node, 1);
|
|
102
|
+
} else {
|
|
103
|
+
if (node.depth === 0) {
|
|
104
|
+
structure.push(node);
|
|
105
|
+
} else {
|
|
106
|
+
let targetParent = lastNode;
|
|
107
|
+
for (let i = 1; i < node.depth; i += 1) {
|
|
108
|
+
const lastChild = targetParent.children[targetParent.children.length - 1];
|
|
109
|
+
if (lastChild !== void 0) {
|
|
110
|
+
targetParent = lastChild;
|
|
111
|
+
} else {
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
targetParent.children.push(node);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return structure;
|
|
121
|
+
}
|
|
122
|
+
function renderTreeNodes(nodes) {
|
|
123
|
+
return nodes.map((node) => {
|
|
124
|
+
const isFrozen = props.isEdit === true && childId.value === node.child.id;
|
|
125
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(node);
|
|
126
|
+
const subListVNode = node.children.length > 0 ? h(props.data.element, { class: "de-list-sub" }, renderTreeNodes(node.children)) : null;
|
|
127
|
+
return withMemo(
|
|
128
|
+
[memoKey],
|
|
129
|
+
() => {
|
|
130
|
+
const children = [
|
|
131
|
+
h("p", {
|
|
132
|
+
class: ["de-item-text", ...node.child.classList],
|
|
133
|
+
innerHTML: node.child.textContent,
|
|
134
|
+
contenteditable: props.isEdit === true,
|
|
135
|
+
onFocus: () => setEdit(node.liIndex, node.child.id),
|
|
136
|
+
onKeydown: keydownEvent,
|
|
137
|
+
onInput: (event) => updateData(event, node.liIndex),
|
|
138
|
+
onPaste: (event) => _normalPasteEvent(event, setEdit, abortEdit),
|
|
139
|
+
onBlur: abortEdit
|
|
140
|
+
})
|
|
141
|
+
];
|
|
142
|
+
if (subListVNode !== null) {
|
|
143
|
+
children.push(subListVNode);
|
|
144
|
+
}
|
|
145
|
+
return h(
|
|
146
|
+
"li",
|
|
147
|
+
{
|
|
148
|
+
key: node.child.id,
|
|
149
|
+
class: ["de-item"]
|
|
150
|
+
},
|
|
151
|
+
children
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
memoCache,
|
|
155
|
+
node.liIndex
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function renderList() {
|
|
160
|
+
const treeStructure = createTreeStructure(props.data.child);
|
|
161
|
+
return h(
|
|
162
|
+
props.data.element,
|
|
163
|
+
{
|
|
164
|
+
class: "de-block de-list-block",
|
|
165
|
+
"data-type": props.data.element === "ul" ? "unordered" : "ordered"
|
|
166
|
+
},
|
|
167
|
+
renderTreeNodes(treeStructure)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DEListBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DEListBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DEListBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DEListBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DETextBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DETextBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DETextBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DETextBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<p
|
|
3
|
+
v-memo="memoData"
|
|
4
|
+
v-html="props.data.textContent"
|
|
5
|
+
class="de-block de-text-block"
|
|
6
|
+
:class="props.data.classList"
|
|
7
|
+
:contenteditable="props.isEdit === true"
|
|
8
|
+
:data-depth="props.data.depth"
|
|
9
|
+
@focus="setEdit"
|
|
10
|
+
@keydown="keydownEvent"
|
|
11
|
+
@input="updateData"
|
|
12
|
+
@paste="_allDataPasteEvent($event, setEdit, abortEdit)"
|
|
13
|
+
></p>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup>
|
|
17
|
+
import { useEditorStore } from "../../store/editor";
|
|
18
|
+
import { computed } from "vue";
|
|
19
|
+
import { _sliceAndNewTextBlock, _blockTabEvent, _moveBlockDefaultEvent, _defaultBackspaceEvent, _defaultDeleteEvent, _allDataPasteEvent, _convertTextBlockType, _convertTextBlockToCodeBlock, _convertTextBlockToDividerBlock, _updateCursorData } from "../../utils/event";
|
|
20
|
+
const editorStore = useEditorStore();
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
data: { type: null, required: true },
|
|
23
|
+
isEdit: { type: Boolean, required: true },
|
|
24
|
+
index: { type: Number, required: true }
|
|
25
|
+
});
|
|
26
|
+
const emit = defineEmits(["update"]);
|
|
27
|
+
const memoData = computed(() => {
|
|
28
|
+
const isFrozen = props.isEdit === true && editorStore.selectedBlockId === props.data.id;
|
|
29
|
+
const memoKey = isFrozen ? "frozen" : JSON.stringify(props.data);
|
|
30
|
+
return [memoKey];
|
|
31
|
+
});
|
|
32
|
+
function setEdit() {
|
|
33
|
+
editorStore.selectedBlockIndex = props.index;
|
|
34
|
+
editorStore.selectedBlockId = props.data.id;
|
|
35
|
+
_updateCursorData();
|
|
36
|
+
}
|
|
37
|
+
function abortEdit() {
|
|
38
|
+
editorStore.selectedBlockIndex = -1;
|
|
39
|
+
editorStore.selectedBlockId = "";
|
|
40
|
+
}
|
|
41
|
+
function keydownEvent(event) {
|
|
42
|
+
if (event.isComposing === false) {
|
|
43
|
+
switch (event.key) {
|
|
44
|
+
case "Enter":
|
|
45
|
+
if (event.shiftKey === false) {
|
|
46
|
+
_sliceAndNewTextBlock(event, props.data, props.index);
|
|
47
|
+
} else {
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case "Tab":
|
|
51
|
+
_blockTabEvent(event, props.data, props.index, setEdit, abortEdit);
|
|
52
|
+
break;
|
|
53
|
+
case "ArrowUp":
|
|
54
|
+
_moveBlockDefaultEvent(event, "up");
|
|
55
|
+
break;
|
|
56
|
+
case "ArrowDown":
|
|
57
|
+
_moveBlockDefaultEvent(event, "down");
|
|
58
|
+
break;
|
|
59
|
+
case "Backspace":
|
|
60
|
+
_defaultBackspaceEvent(event);
|
|
61
|
+
break;
|
|
62
|
+
case "Delete":
|
|
63
|
+
_defaultDeleteEvent(event, setEdit, abortEdit);
|
|
64
|
+
break;
|
|
65
|
+
case "`":
|
|
66
|
+
_convertTextBlockToCodeBlock(event, props.data, props.index);
|
|
67
|
+
break;
|
|
68
|
+
case "-":
|
|
69
|
+
_convertTextBlockToDividerBlock(event, props.data, props.index);
|
|
70
|
+
break;
|
|
71
|
+
case " ":
|
|
72
|
+
_convertTextBlockType(event, props.data, props.index);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function updateData(event) {
|
|
80
|
+
const newData = JSON.parse(JSON.stringify(props.data));
|
|
81
|
+
newData.textContent = event.target.innerHTML;
|
|
82
|
+
emit("update", newData);
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DETextBlock } from "../../type.d.mts.js";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
data: DETextBlock;
|
|
4
|
+
isEdit: boolean;
|
|
5
|
+
index: number;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
update: (data: DETextBlock) => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
10
|
+
onUpdate?: ((data: DETextBlock) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -1,33 +1,38 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { _addBlock, _addImageBlock, _checkDataIsEmpty } from "../utils/data/index.js";
|
|
2
|
+
import { _editorMountedEvent } from "../utils/event/index.js";
|
|
3
|
+
import { _setAlign } from "../utils/node/index.js";
|
|
4
|
+
import type { DEContentData } from "../type.d.mts.js";
|
|
5
|
+
interface DragonEditorOption {
|
|
3
6
|
modelValue: DEContentData;
|
|
4
7
|
useMenuBar?: boolean;
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
mediaHostURL?: string;
|
|
9
|
+
isMobile?: boolean;
|
|
10
|
+
theme?: "dark" | "white";
|
|
11
|
+
codeBlockSpaces?: number;
|
|
12
|
+
acceptImageFormat?: string;
|
|
13
|
+
anchorTagTarget?: string;
|
|
7
14
|
}
|
|
8
|
-
declare
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
addBlock: typeof addBlock;
|
|
16
|
-
setDecoration: typeof setDecoration;
|
|
17
|
-
setAlign: typeof setAlign;
|
|
18
|
-
changeEditorData: typeof changeEditorData;
|
|
19
|
-
updateLayout: typeof updateLayout;
|
|
20
|
-
checkDataEmpty: typeof checkDataEmpty;
|
|
15
|
+
declare const __VLS_export: import("vue").DefineComponent<DragonEditorOption, {
|
|
16
|
+
addBlock: typeof _addBlock;
|
|
17
|
+
addImageBlock: typeof _addImageBlock;
|
|
18
|
+
updateLayout: typeof _editorMountedEvent;
|
|
19
|
+
checkDataIsEmpty: typeof _checkDataIsEmpty;
|
|
20
|
+
setDecoration: (type: "bold" | "italic" | "underline" | "strikethrough" | "code") => void;
|
|
21
|
+
setAlign: typeof _setAlign;
|
|
21
22
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
22
23
|
"update:modelValue": (data: DEContentData) => any;
|
|
23
|
-
uploadImageEvent: (
|
|
24
|
-
}, string, import("vue").PublicProps, Readonly<
|
|
24
|
+
uploadImageEvent: (files: File[]) => any;
|
|
25
|
+
}, string, import("vue").PublicProps, Readonly<DragonEditorOption> & Readonly<{
|
|
25
26
|
"onUpdate:modelValue"?: ((data: DEContentData) => any) | undefined;
|
|
26
|
-
onUploadImageEvent?: ((
|
|
27
|
+
onUploadImageEvent?: ((files: File[]) => any) | undefined;
|
|
27
28
|
}>, {
|
|
28
|
-
|
|
29
|
+
mediaHostURL: string;
|
|
30
|
+
isMobile: boolean;
|
|
31
|
+
codeBlockSpaces: number;
|
|
32
|
+
acceptImageFormat: string;
|
|
33
|
+
anchorTagTarget: string;
|
|
34
|
+
theme: "dark" | "white";
|
|
29
35
|
useMenuBar: boolean;
|
|
30
|
-
screenChangePoint: number;
|
|
31
36
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
32
37
|
declare const _default: typeof __VLS_export;
|
|
33
38
|
export default _default;
|