dragon-editor 2.0.0-beta.2.1.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +29 -5
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +2 -2
  4. package/dist/runtime/core/components/SvgIcon.d.ts +10 -0
  5. package/dist/runtime/core/components/SvgIcon.mjs +98 -0
  6. package/dist/runtime/core/components/editor/ImageBlock.vue +5 -5
  7. package/dist/runtime/core/components/editor/OlBlock.vue +93 -66
  8. package/dist/runtime/core/components/editor/TextBlock.vue +12 -6
  9. package/dist/runtime/core/components/editor/UlBlock.vue +162 -0
  10. package/dist/runtime/core/style/common.css +18 -1
  11. package/dist/runtime/core/style/viewer.css +14 -0
  12. package/dist/runtime/core/utils/converter.d.ts +2 -0
  13. package/dist/runtime/core/utils/converter.mjs +90 -0
  14. package/dist/runtime/core/utils/global.d.ts +3 -0
  15. package/dist/runtime/core/utils/global.mjs +81 -0
  16. package/dist/runtime/core/utils/index.d.ts +3 -2
  17. package/dist/runtime/core/utils/index.mjs +3 -79
  18. package/dist/runtime/core/utils/keyboard.mjs +22 -14
  19. package/dist/runtime/core/utils/ui.d.ts +4 -0
  20. package/dist/runtime/core/utils/ui.mjs +13 -0
  21. package/dist/runtime/shared/components/DragonEditor.d.ts +16 -0
  22. package/dist/runtime/shared/components/DragonEditor.mjs +62 -0
  23. package/dist/runtime/shared/components/DragonEditor.vue +17 -13
  24. package/dist/runtime/shared/components/DragonEditorComment.vue +60 -27
  25. package/dist/runtime/shared/components/DragonEditorViewer.d.ts +14 -0
  26. package/dist/runtime/shared/components/DragonEditorViewer.mjs +15 -0
  27. package/package.json +57 -57
  28. package/dist/runtime/core/components/SvgIcon.vue +0 -175
  29. package/dist/runtime/core/components/icon/Accept.vue +0 -5
  30. package/dist/runtime/core/components/icon/AlignCenter.vue +0 -6
  31. package/dist/runtime/core/components/icon/AlignLeft.vue +0 -6
  32. package/dist/runtime/core/components/icon/AlignRight.vue +0 -6
  33. package/dist/runtime/core/components/icon/ArrowDown.vue +0 -3
  34. package/dist/runtime/core/components/icon/ArrowUp.vue +0 -3
  35. package/dist/runtime/core/components/icon/Cancel.vue +0 -5
  36. package/dist/runtime/core/components/icon/CodeBlock.vue +0 -6
  37. package/dist/runtime/core/components/icon/DecorationBold.vue +0 -6
  38. package/dist/runtime/core/components/icon/DecorationItalic.vue +0 -6
  39. package/dist/runtime/core/components/icon/DecorationStrikethrough.vue +0 -6
  40. package/dist/runtime/core/components/icon/DecorationUnderline.vue +0 -6
  41. package/dist/runtime/core/components/icon/Delete.vue +0 -3
  42. package/dist/runtime/core/components/icon/ImageBlock.vue +0 -5
  43. package/dist/runtime/core/components/icon/LinkPath.vue +0 -6
  44. package/dist/runtime/core/components/icon/OlBlock.vue +0 -6
  45. package/dist/runtime/core/components/icon/QuotationBlock.vue +0 -6
  46. package/dist/runtime/core/components/icon/TableBlock.vue +0 -8
  47. package/dist/runtime/core/components/icon/TextBlock.vue +0 -5
  48. package/dist/runtime/core/components/icon/UlBlock.vue +0 -6
  49. package/dist/runtime/shared/components/DragonEditorViewer.vue +0 -31
@@ -0,0 +1,162 @@
1
+ <template>
2
+ <ul class="d-ul-block" @keydown="textKeyboardEvent" ref="$ul" :key="updateCount">
3
+ <li class="d-li-item" v-for="(row, i) in data.childList" :key="i" :class="row.classList" contenteditable ref="$item" v-html="row.content"></li>
4
+ </ul>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ // @ts-ignore
9
+ import { ref, unref } from "#imports";
10
+ import { cursorSelection, liItem, ListBlock, styleFunctionArgument } from "../../../../types";
11
+ import { getArrangementCursorData, setCursor, pasteText, styleSettings, keyboardEvent, getCursor, findEditableElement } from "../../utils";
12
+
13
+ const updateCount = ref<number>(0);
14
+ const $ul = ref();
15
+ const $item = ref();
16
+ const itemIdx = ref<number>(0);
17
+ const data = ref<ListBlock>({
18
+ type: "",
19
+ id: "",
20
+ childList: [
21
+ {
22
+ classList: [],
23
+ content: "",
24
+ },
25
+ ],
26
+ });
27
+ const props = defineProps<{ modelValue: ListBlock; cursorData: cursorSelection }>();
28
+ const emit = defineEmits<{
29
+ (e: "update:modelValue", modelValue: ListBlock): void;
30
+ (e: "addBlock", {}: { name: string; value: object }): void;
31
+ (e: "deleteBlockLocal", index?: number): void;
32
+ }>();
33
+ data.value = unref(props.modelValue) as ListBlock;
34
+
35
+ if (data.value.childList.length === 0) {
36
+ }
37
+
38
+ // 키보드 이벤트 할당
39
+ function textKeyboardEvent(e: KeyboardEvent) {
40
+ keyboardEvent("list", e, emit, updateBlockData);
41
+ }
42
+
43
+ /**
44
+ * 외부용 함수
45
+ */
46
+
47
+ // 데이터 정규화 및 검수
48
+ function updateBlockData() {
49
+ const $block = $ul.value;
50
+ const $childList = $block.querySelectorAll("li");
51
+ const childData: liItem[] = [];
52
+ const cursorData = getCursor();
53
+
54
+ $childList.forEach((row) => {
55
+ row.childNodes.forEach((child: ChildNode) => {
56
+ const $child = child as HTMLElement;
57
+
58
+ if (child.constructor.name !== "Text") {
59
+ // 텍스트가 아닐경우
60
+ if (child.constructor.name !== "HTMLBRElement") {
61
+ // br 태그 유지
62
+ if (child.textContent === "") {
63
+ // 빈 태그 삭제
64
+ child.remove();
65
+ } else if ($child.classList.length === 0) {
66
+ // 클레스 없는 엘리먼트 처리
67
+ $child.insertAdjacentHTML("afterend", $child.innerHTML);
68
+ child.remove();
69
+ }
70
+ } else {
71
+ $child.removeAttribute("class");
72
+ }
73
+ }
74
+ });
75
+
76
+ childData.push({
77
+ classList: [...row.classList].splice(1),
78
+ content: row.innerHTML,
79
+ });
80
+ });
81
+
82
+ data.value.childList = childData;
83
+ emit("update:modelValue", data.value);
84
+ updateCount.value += 1;
85
+
86
+ if (cursorData.startNode) {
87
+ const editableNode = findEditableElement(cursorData.startNode);
88
+ let childIdx = -1;
89
+
90
+ $childList.forEach((row, count) => {
91
+ if (row === editableNode) {
92
+ childIdx = count;
93
+ }
94
+ });
95
+
96
+ if (childIdx > -1) {
97
+ // 기본 로직
98
+ itemIdx.value = childIdx;
99
+ setTimeout(() => {
100
+ const afterChildList = $ul.value.querySelectorAll("li");
101
+ setCursor(afterChildList[childIdx], cursorData.startOffset as number);
102
+ }, 100);
103
+ } else {
104
+ // 중간 엔터
105
+ $childList.forEach((row, count) => {
106
+ if (row === (cursorData.startNode as Node).parentNode) {
107
+ childIdx = count;
108
+ }
109
+ });
110
+
111
+ setTimeout(() => {
112
+ const afterChildList = $ul.value.querySelectorAll("li");
113
+ setCursor(afterChildList[childIdx], cursorData.startOffset as number);
114
+ }, 100);
115
+ }
116
+ }
117
+ }
118
+
119
+ // 포커스
120
+ function focus() {
121
+ const childList = $ul.value.querySelectorAll(".d-li-item");
122
+ setCursor(childList[itemIdx.value], 0);
123
+ }
124
+
125
+ // 블럭 위치 주기
126
+ function getBoundingClientRect() {
127
+ return $ul.value.parentNode.getBoundingClientRect();
128
+ }
129
+
130
+ // 타입 전달
131
+ function getType() {
132
+ return data.value.type;
133
+ }
134
+
135
+ // 붙여넣기 이벤트
136
+ function pasteEvent(text: string) {
137
+ pasteText("text", text);
138
+ }
139
+
140
+ // 텍스트 스타일 지정
141
+ function setStyles({ type, url }: styleFunctionArgument) {
142
+ data.value = styleSettings({
143
+ kind: type,
144
+ blockData: data.value,
145
+ $target: $item[itemIdx.value],
146
+ url: url,
147
+ cursorData: props.cursorData,
148
+ });
149
+ setTimeout(() => {
150
+ updateBlockData();
151
+ }, 250);
152
+ }
153
+
154
+ defineExpose({
155
+ updateBlockData,
156
+ focus,
157
+ getType,
158
+ pasteEvent,
159
+ setStyles,
160
+ getBoundingClientRect,
161
+ });
162
+ </script>
@@ -136,7 +136,7 @@
136
136
  background: transparent;
137
137
  transition: background 0.25s ease;
138
138
  }
139
- .dragon-editor .d-row-block:hover {
139
+ .dragon-editor .d-row-block:hover, .dragon-editor .d-row-block.--active {
140
140
  background: #fafafa;
141
141
  }
142
142
  .dragon-editor .d-text-block {
@@ -168,6 +168,23 @@
168
168
  content: "Write text";
169
169
  color: #ccc;
170
170
  }
171
+ .dragon-editor .d-ul-block {
172
+ padding-left: 30px;
173
+ cursor: text;
174
+ list-style: disc;
175
+ }
176
+ .dragon-editor .d-ul-block .d-li-item {
177
+ list-style: inherit;
178
+ outline: 0;
179
+ }
180
+ .dragon-editor .d-ul-block .d-li-item:empty {
181
+ min-height: 1.6em;
182
+ }
183
+ .dragon-editor .d-ul-block .d-li-item:empty::after {
184
+ display: inline;
185
+ content: "Write text";
186
+ color: #ccc;
187
+ }
171
188
  .dragon-editor .d-image-block {
172
189
  display: flex;
173
190
  flex-direction: column;
@@ -189,3 +189,17 @@
189
189
  color: #ccc;
190
190
  font-size: 1rem;
191
191
  }
192
+ .dragon-editor-viewer .d-ol-block {
193
+ padding-left: 30px;
194
+ list-style: decimal;
195
+ }
196
+ .dragon-editor-viewer .d-ol-block .d-li-item {
197
+ list-style: inherit;
198
+ }
199
+ .dragon-editor-viewer .d-ul-block {
200
+ padding-left: 30px;
201
+ list-style: disc;
202
+ }
203
+ .dragon-editor-viewer .d-ul-block .d-li-item {
204
+ list-style: inherit;
205
+ }
@@ -0,0 +1,2 @@
1
+ import type { EditorContentType } from "../../../types/index";
2
+ export declare function convertViewBlock(data: EditorContentType, mediaUrl?: string): any[];
@@ -0,0 +1,90 @@
1
+ import { h } from "vue";
2
+ export function convertViewBlock(data, mediaUrl) {
3
+ const childList = [];
4
+ data.forEach((row) => {
5
+ let hObject;
6
+ switch (row.type) {
7
+ case "text":
8
+ const textBlockData = row;
9
+ hObject = h("p", {
10
+ class: ["d-text-block", ...textBlockData.classList],
11
+ innerHTML: textBlockData.content
12
+ });
13
+ break;
14
+ case "image":
15
+ const imageBlockData = row;
16
+ const imageChildList = [];
17
+ const imageUrl = mediaUrl ? mediaUrl + imageBlockData.src : imageBlockData.src;
18
+ imageChildList.push(
19
+ h(
20
+ "div",
21
+ { class: ["d-image-area"] },
22
+ h("img", {
23
+ class: ["d-img"],
24
+ src: imageUrl,
25
+ width: imageBlockData.width,
26
+ height: imageBlockData.height,
27
+ alt: imageBlockData.caption,
28
+ loading: "lazy"
29
+ })
30
+ )
31
+ );
32
+ if (imageBlockData.caption !== "") {
33
+ imageChildList.push(
34
+ h("p", {
35
+ class: ["d-caption"],
36
+ innerHTML: imageBlockData.caption
37
+ })
38
+ );
39
+ }
40
+ hObject = h("div", { class: ["d-image-block", ...imageBlockData.classList] }, imageChildList);
41
+ break;
42
+ case "ol":
43
+ const olBlockData = row;
44
+ const olChildList = [];
45
+ olBlockData.childList.forEach((child) => {
46
+ olChildList.push(
47
+ h("li", {
48
+ class: ["d-li-item", ...child.classList],
49
+ innerHTML: child.content
50
+ })
51
+ );
52
+ });
53
+ hObject = h(
54
+ "ol",
55
+ {
56
+ class: ["d-ol-block", ...olBlockData.classList]
57
+ },
58
+ olChildList
59
+ );
60
+ break;
61
+ case "ul":
62
+ const ulBlockData = row;
63
+ const ulChildList = [];
64
+ ulBlockData.childList.forEach((child) => {
65
+ ulChildList.push(
66
+ h("li", {
67
+ class: ["d-li-item", ...child.classList],
68
+ innerHTML: child.content
69
+ })
70
+ );
71
+ });
72
+ hObject = h(
73
+ "ul",
74
+ {
75
+ class: ["d-ul-block", ...ulBlockData.classList]
76
+ },
77
+ ulChildList
78
+ );
79
+ break;
80
+ default:
81
+ const defaultData = row;
82
+ hObject = h("div", {
83
+ class: ["d-other-block"],
84
+ innerHTML: defaultData.innerHTML
85
+ });
86
+ }
87
+ childList.push(hObject);
88
+ });
89
+ return childList;
90
+ }
@@ -0,0 +1,3 @@
1
+ import type { allBlock } from "../../../types/index";
2
+ export declare function generateId(): string;
3
+ export declare function createBlock(name: string, value?: object): allBlock;
@@ -0,0 +1,81 @@
1
+ export function generateId() {
2
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3
+ let str = "";
4
+ for (let i = 0; i < 20; i++) {
5
+ str += chars.charAt(Math.floor(Math.random() * chars.length));
6
+ }
7
+ return str;
8
+ }
9
+ function createTextBlock(data) {
10
+ if (data) {
11
+ return {
12
+ type: "text",
13
+ id: generateId(),
14
+ classList: data.classList,
15
+ content: data.content
16
+ };
17
+ } else {
18
+ return {
19
+ type: "text",
20
+ id: generateId(),
21
+ classList: [],
22
+ content: ""
23
+ };
24
+ }
25
+ }
26
+ function createImageBlock(data) {
27
+ const totalSize = data.width + data.height;
28
+ const w = Math.round(100 / totalSize * data.width);
29
+ const h = Math.round(100 / totalSize * data.height);
30
+ const contrast = w - h;
31
+ let classList = ["d-align-center"];
32
+ switch (true) {
33
+ case contrast < -40:
34
+ classList.push("--5");
35
+ break;
36
+ case contrast < -15:
37
+ classList.push("--10");
38
+ break;
39
+ default:
40
+ classList.push("--20");
41
+ }
42
+ return {
43
+ type: "image",
44
+ id: generateId(),
45
+ classList,
46
+ src: data.src,
47
+ width: data.width,
48
+ height: data.height,
49
+ caption: data.caption
50
+ };
51
+ }
52
+ function createListBlock(type = "ul") {
53
+ return {
54
+ type,
55
+ id: generateId(),
56
+ classList: [],
57
+ childList: [
58
+ {
59
+ classList: [],
60
+ content: ""
61
+ }
62
+ ]
63
+ };
64
+ }
65
+ export function createBlock(name, value) {
66
+ let blockData;
67
+ switch (name) {
68
+ case "ul":
69
+ blockData = createListBlock();
70
+ break;
71
+ case "ol":
72
+ blockData = createListBlock("ol");
73
+ break;
74
+ case "image":
75
+ blockData = createImageBlock(value);
76
+ break;
77
+ default:
78
+ blockData = createTextBlock(value);
79
+ }
80
+ return blockData;
81
+ }
@@ -1,6 +1,7 @@
1
- import { allBlock } from "../../../types/index";
2
- export declare function createBlock(name: string, value?: object): allBlock;
1
+ export * from "./global";
3
2
  export * from "./keyboard";
4
3
  export * from "./cursor";
5
4
  export * from "./style";
6
5
  export * from "./element";
6
+ export * from "./converter";
7
+ export * from "./ui";
@@ -1,83 +1,7 @@
1
- function generateId() {
2
- const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3
- let str = "";
4
- for (let i = 0; i < 20; i++) {
5
- str += chars.charAt(Math.floor(Math.random() * chars.length));
6
- }
7
- return str;
8
- }
9
- function createTextBlock(data) {
10
- if (data) {
11
- return {
12
- type: "text",
13
- id: generateId(),
14
- classList: data.classList,
15
- content: data.content
16
- };
17
- } else {
18
- return {
19
- type: "text",
20
- id: generateId(),
21
- classList: [],
22
- content: ""
23
- };
24
- }
25
- }
26
- function createImageBlock(data) {
27
- const totalSize = data.width + data.height;
28
- const w = Math.round(100 / totalSize * data.width);
29
- const h = Math.round(100 / totalSize * data.height);
30
- const contrast = w - h;
31
- let classList = ["d-align-center"];
32
- switch (true) {
33
- case contrast < -40:
34
- classList.push("--5");
35
- break;
36
- case contrast < -15:
37
- classList.push("--10");
38
- break;
39
- default:
40
- classList.push("--20");
41
- }
42
- return {
43
- type: "image",
44
- id: generateId(),
45
- classList,
46
- src: data.src,
47
- width: data.width,
48
- height: data.height,
49
- webp: data.webp,
50
- caption: data.caption
51
- };
52
- }
53
- function createlistBlock(type = "ul") {
54
- return {
55
- type,
56
- id: generateId(),
57
- classList: [],
58
- childList: [
59
- {
60
- classList: [],
61
- content: ""
62
- }
63
- ]
64
- };
65
- }
66
- export function createBlock(name, value) {
67
- let blockData;
68
- switch (name) {
69
- case "ol":
70
- blockData = createlistBlock("ol");
71
- break;
72
- case "image":
73
- blockData = createImageBlock(value);
74
- break;
75
- default:
76
- blockData = createTextBlock(value);
77
- }
78
- return blockData;
79
- }
1
+ export * from "./global.mjs";
80
2
  export * from "./keyboard.mjs";
81
3
  export * from "./cursor.mjs";
82
4
  export * from "./style.mjs";
83
5
  export * from "./element.mjs";
6
+ export * from "./converter.mjs";
7
+ export * from "./ui.mjs";
@@ -2,15 +2,15 @@ import { getCursor, setCursor } from "./cursor.mjs";
2
2
  import { findEditableElement, findChildNumber, findLiElement } from "./element.mjs";
3
3
  import { getTagName } from "./style.mjs";
4
4
  let enterCount = 0;
5
- function enterEvent(type, event, action) {
5
+ function enterEvent(type, event, action, update) {
6
6
  if (event.code === "Enter") {
7
7
  event.preventDefault();
8
8
  const useShift = event.shiftKey;
9
9
  switch (type) {
10
- case "ol":
10
+ case "list":
11
11
  if (useShift === false) {
12
12
  if (enterCount == 0) {
13
- listEnterEvent(event, action);
13
+ listEnterEvent(action, update);
14
14
  }
15
15
  } else {
16
16
  addBrEvent();
@@ -27,7 +27,7 @@ function enterEvent(type, event, action) {
27
27
  default:
28
28
  if (useShift === false) {
29
29
  if (enterCount == 0) {
30
- textEnterEvent(event, action);
30
+ textEnterEvent(action);
31
31
  }
32
32
  } else {
33
33
  addBrEvent();
@@ -39,7 +39,7 @@ function enterEvent(type, event, action) {
39
39
  }, 150);
40
40
  }
41
41
  }
42
- function listEnterEvent(event, action) {
42
+ function listEnterEvent(action, update) {
43
43
  const cursorData = getCursor();
44
44
  if (cursorData.startNode) {
45
45
  const editableElement = findEditableElement(cursorData.startNode);
@@ -74,9 +74,16 @@ function listEnterEvent(event, action) {
74
74
  endOffset = cursorData.endOffset;
75
75
  }
76
76
  if (editableElement.childNodes.length === 0 || endChildIdx === editableElement.childNodes.length - 1 && editableElement.childNodes[endChildIdx].textContent.length === endOffset) {
77
- action("addBlock", {
78
- name: "text"
79
- });
77
+ if (editableElement.childNodes.length === 0) {
78
+ editableElement.remove();
79
+ action("addBlock", {
80
+ name: "text"
81
+ });
82
+ } else {
83
+ editableElement.insertAdjacentHTML("afterend", `<li class="d-li-item" contenteditable></li>`);
84
+ setCursor(editableElement.nextSibling, 0);
85
+ update();
86
+ }
80
87
  } else {
81
88
  editableElement.childNodes.forEach((child, count) => {
82
89
  const text = child.textContent;
@@ -125,14 +132,15 @@ function listEnterEvent(event, action) {
125
132
  }
126
133
  });
127
134
  editableElement.innerHTML = preHTMLStructor;
128
- action("addBlock", {
129
- name: "text",
130
- value: { classList: editableElementClassList, content: nextHTMLStructor }
131
- });
135
+ editableElement.insertAdjacentHTML("afterend", `<li class="d-li-item ${editableElementClassList.join(" ")}">${nextHTMLStructor}</li>`);
136
+ setTimeout(() => {
137
+ setCursor(editableElement.nextSibling.childNodes[0], 0);
138
+ update();
139
+ }, 100);
132
140
  }
133
141
  }
134
142
  }
135
- function textEnterEvent(event, action) {
143
+ function textEnterEvent(action) {
136
144
  const cursorData = getCursor();
137
145
  if (cursorData.startNode) {
138
146
  const editableElement = findEditableElement(cursorData.startNode);
@@ -245,7 +253,7 @@ function backspaceEvent(type, event, action, update) {
245
253
  }
246
254
  }
247
255
  export function keyboardEvent(type, event, action, update) {
248
- enterEvent(type, event, action);
256
+ enterEvent(type, event, action, update);
249
257
  backspaceEvent(type, event, action, update);
250
258
  }
251
259
  export function getClipboardData(data) {
@@ -0,0 +1,4 @@
1
+ import type { EditorContentType } from "../../../types/index";
2
+ export declare function createLeftMenu(modelValue: EditorContentType, top: number, isActive: boolean): import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
3
+ [key: string]: any;
4
+ }>;
@@ -0,0 +1,13 @@
1
+ import { h } from "vue";
2
+ export function createLeftMenu(modelValue, top, isActive) {
3
+ console.log(modelValue);
4
+ return h("div", {
5
+ class: ["d-left-menu", { "--active": isActive }],
6
+ onClick: () => {
7
+ test();
8
+ }
9
+ });
10
+ function test() {
11
+ modelValue = [{ type: "text", classList: [], content: "123" }];
12
+ }
13
+ }
@@ -0,0 +1,16 @@
1
+ import "../../core/style/common.css";
2
+ declare const _default: import("vue").DefineComponent<Readonly<{
3
+ option?: any;
4
+ modelValue?: any;
5
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
6
+ [key: string]: any;
7
+ }>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<Readonly<{
8
+ option?: any;
9
+ modelValue?: any;
10
+ }>>> & {
11
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
12
+ }, {
13
+ readonly option?: any;
14
+ readonly modelValue?: any;
15
+ }, {}>;
16
+ export default _default;
@@ -0,0 +1,62 @@
1
+ import { h, defineComponent, ref, unref, watch } from "vue";
2
+ import { createLeftMenu } from "../../core/utils/index.mjs";
3
+ import "../../core/style/common.css";
4
+ export default defineComponent({
5
+ name: "DragonEditor",
6
+ props: ["modelValue", "option"],
7
+ emits: ["update:modelValue"],
8
+ setup: (props, ctx) => {
9
+ const modelValue = ref([]);
10
+ const option = ref({
11
+ blockMenu: ["text", "ol", "ul"]
12
+ // TODO : 다른 블럭 만들기 "table", "quotation"
13
+ });
14
+ if (props.modelValue) {
15
+ modelValue.value = props.modelValue;
16
+ }
17
+ if (props.option !== void 0) {
18
+ option.value = Object.assign(option.value, props.option);
19
+ }
20
+ const activeLeftMenu = ref(false);
21
+ const leftMenuPosition = ref(0);
22
+ const leftMenuStructure = createLeftMenu(modelValue.value, leftMenuPosition.value, activeLeftMenu.value);
23
+ const customStyleMenu = ref([]);
24
+ if (option.value.customStyleMenu) {
25
+ customStyleMenu.value = unref(option.value.customStyleMenu);
26
+ }
27
+ init(modelValue.value);
28
+ function init(targetData) {
29
+ if (targetData && Array.isArray(targetData)) {
30
+ if (targetData.length == 0) {
31
+ }
32
+ } else {
33
+ throw new Error("[DragonEditor] : You must set 'v-model' attribute and 'v-mode' type is must be Array(EditorContentType).");
34
+ }
35
+ }
36
+ function addImageBlock({ src, width, height, caption = "" }) {
37
+ console.log("addImage");
38
+ }
39
+ watch(
40
+ () => props.modelValue,
41
+ (newData, oldData) => {
42
+ init(newData);
43
+ }
44
+ );
45
+ ctx.expose({ addImageBlock });
46
+ return () => {
47
+ return h(
48
+ "div",
49
+ {
50
+ class: ["dragon-editor"],
51
+ onPaste: () => {
52
+ console.log("paste");
53
+ },
54
+ onCopy: () => {
55
+ console.log("copy");
56
+ }
57
+ },
58
+ [leftMenuStructure]
59
+ );
60
+ };
61
+ }
62
+ });