dragon-editor 2.1.2 → 3.0.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 (58) hide show
  1. package/README.md +82 -96
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +10 -12
  4. package/dist/runtime/components/DragonEditor.vue +457 -0
  5. package/dist/runtime/components/DragonEditorViewer.vue +228 -0
  6. package/dist/runtime/plugin.d.ts +2 -0
  7. package/dist/runtime/plugin.mjs +10 -0
  8. package/dist/runtime/scss/editor.css +261 -0
  9. package/dist/runtime/scss/viewer.css +198 -0
  10. package/dist/runtime/store.d.ts +7 -0
  11. package/dist/runtime/store.mjs +27 -0
  12. package/dist/runtime/type.d.ts +24 -0
  13. package/dist/runtime/utils/block.d.ts +9 -0
  14. package/dist/runtime/utils/block.mjs +70 -0
  15. package/dist/runtime/utils/convertor.d.ts +2 -0
  16. package/dist/runtime/utils/convertor.mjs +86 -0
  17. package/dist/runtime/utils/cursor.d.ts +6 -0
  18. package/dist/runtime/utils/cursor.mjs +132 -0
  19. package/dist/runtime/utils/element.d.ts +3 -0
  20. package/dist/runtime/utils/element.mjs +39 -0
  21. package/dist/runtime/utils/keyboardEvent.d.ts +10 -0
  22. package/dist/runtime/utils/keyboardEvent.mjs +781 -0
  23. package/dist/runtime/utils/style.d.ts +1 -0
  24. package/dist/runtime/utils/style.mjs +330 -0
  25. package/dist/runtime/utils/ui.d.ts +1 -0
  26. package/dist/runtime/utils/ui.mjs +35 -0
  27. package/package.json +10 -4
  28. package/README_en.md +0 -30
  29. package/dist/runtime/core/components/SvgIcon.d.ts +0 -10
  30. package/dist/runtime/core/components/SvgIcon.mjs +0 -98
  31. package/dist/runtime/core/components/editor/ImageBlock.vue +0 -175
  32. package/dist/runtime/core/components/editor/OlBlock.vue +0 -162
  33. package/dist/runtime/core/components/editor/TextBlock.vue +0 -172
  34. package/dist/runtime/core/components/editor/UlBlock.vue +0 -162
  35. package/dist/runtime/core/style/common.css +0 -496
  36. package/dist/runtime/core/style/viewer.css +0 -205
  37. package/dist/runtime/core/utils/converter.d.ts +0 -2
  38. package/dist/runtime/core/utils/converter.mjs +0 -90
  39. package/dist/runtime/core/utils/cursor.d.ts +0 -4
  40. package/dist/runtime/core/utils/cursor.mjs +0 -84
  41. package/dist/runtime/core/utils/element.d.ts +0 -3
  42. package/dist/runtime/core/utils/element.mjs +0 -40
  43. package/dist/runtime/core/utils/global.d.ts +0 -3
  44. package/dist/runtime/core/utils/global.mjs +0 -81
  45. package/dist/runtime/core/utils/index.d.ts +0 -7
  46. package/dist/runtime/core/utils/index.mjs +0 -7
  47. package/dist/runtime/core/utils/keyboard.d.ts +0 -6
  48. package/dist/runtime/core/utils/keyboard.mjs +0 -565
  49. package/dist/runtime/core/utils/style.d.ts +0 -6
  50. package/dist/runtime/core/utils/style.mjs +0 -374
  51. package/dist/runtime/core/utils/ui.d.ts +0 -4
  52. package/dist/runtime/core/utils/ui.mjs +0 -13
  53. package/dist/runtime/shared/components/DragonEditor.vue +0 -695
  54. package/dist/runtime/shared/components/DragonEditorComment.vue +0 -172
  55. package/dist/runtime/shared/components/DragonEditorNew.d.ts +0 -16
  56. package/dist/runtime/shared/components/DragonEditorNew.mjs +0 -62
  57. package/dist/runtime/shared/components/DragonEditorViewer.d.ts +0 -14
  58. package/dist/runtime/shared/components/DragonEditorViewer.mjs +0 -15
@@ -1,175 +0,0 @@
1
- <template>
2
- <div class="d-image-block" :class="data.classList" ref="$block" @mousemove="resizeMouseEvent" @touchmove="resizeTouchEvent" @mouseup="doneResizeStatus" @touchend="doneResizeStatus">
3
- <div class="d-image-area">
4
- <button class="d-btn-size-left" @mousedown="startResizeEvent" @touchstart="startResizeEvent"></button>
5
- <button class="d-btn-size-right" @mousedown="startResizeEvent" @touchstart="startResizeEvent"></button>
6
-
7
- <template v-if="data.webp">
8
- <picture>
9
- <source :srcset="data.src.replace(/\.(jpg|png|jpeg|apng|gif)/g, '.webp')" />
10
- <img class="d-img" :src="data.src" :width="data.width" :height="data.height" :alt="data.caption" loading="lazy" />
11
- </picture>
12
- </template>
13
-
14
- <template v-else>
15
- <img class="d-img" :src="data.src" :width="data.width" :height="data.height" :alt="data.caption" loading="lazy" />
16
- </template>
17
- </div>
18
- <p class="d-caption" v-html="data.caption" @keydown="textKeyboardEvent" ref="$caption" contenteditable></p>
19
- </div>
20
- </template>
21
-
22
- <script setup lang="ts">
23
- // @ts-ignore
24
- import { ref, unref } from "#imports";
25
- import { keyboardEvent, pasteText, styleSettings } from "../../utils/index";
26
- import { ImageBlock, cursorSelection, styleFunctionArgument } from "../../../../types/index";
27
-
28
- const $block = ref();
29
- const $caption = ref();
30
- const data = ref<ImageBlock>({
31
- type: "",
32
- id: "",
33
- classList: [],
34
- src: "",
35
- width: 0,
36
- height: 0,
37
- webp: false,
38
- caption: "",
39
- });
40
- const props = defineProps<{ modelValue: ImageBlock; cursorData: cursorSelection }>();
41
- const emit = defineEmits<{
42
- (e: "update:modelValue", modelValue: ImageBlock): void;
43
- (e: "addBlock", name: string): void;
44
- (e: "deleteBlockLocal", index?: number): void;
45
- }>();
46
-
47
- data.value = unref(props.modelValue) as ImageBlock;
48
-
49
- /**
50
- * 내부 상수
51
- */
52
- let activeResize = false;
53
- let startX = 0;
54
-
55
- /**
56
- * 내부 이벤트
57
- */
58
- // 키보드 이벤트 할당
59
- function textKeyboardEvent(e: KeyboardEvent) {
60
- keyboardEvent("image", e, emit, updateBlockData);
61
- }
62
-
63
- // 리사이즈 시작
64
- const startResizeStatus = (value) => {
65
- activeResize = true;
66
- startX = value;
67
- };
68
-
69
- function startResizeEvent() {
70
- // startResizeStatus(e.clientX);
71
- activeResize = true;
72
- }
73
-
74
- function activeResizeTouchEvent(e: TouchEvent) {
75
- // startResizeStatus(Math.floor(e.touches[0].clientX));
76
- activeResize = true;
77
- }
78
-
79
- // 리사이즈 이벤트
80
- const resizeEvent = (value) => {
81
- if (activeResize) {
82
- const blockRect = $block.value.getBoundingClientRect();
83
- const bodyRect = document.body.getBoundingClientRect();
84
- const blockLeft = blockRect.left - bodyRect.left;
85
- const centerPoint: number = blockRect.width / 2 + blockLeft;
86
- const blockRight = window.innerWidth - (centerPoint + blockRect.width / 2);
87
- let percent: number = 0;
88
-
89
- // console.log(value);
90
-
91
- if (centerPoint > value) {
92
- // 왼쪽
93
- const leftPercent = (100 / (centerPoint - blockLeft)) * (value - blockLeft);
94
-
95
- percent = Math.floor(100 - leftPercent) + 2;
96
- } else {
97
- // 오른쪽
98
- const right = window.innerWidth - (centerPoint + blockRight);
99
- const valueData = value - centerPoint;
100
- const rightPercent = (100 / right) * valueData;
101
-
102
- percent = Math.floor(rightPercent);
103
- }
104
-
105
- percent = percent - (percent % 5);
106
- percent = percent / 5;
107
-
108
- const classList = data.value.classList.filter((item) => /--\d{1,2}/g.test(item) === false);
109
- classList.push(`--${percent}`);
110
- data.value.classList = classList;
111
- }
112
- };
113
-
114
- function resizeMouseEvent(e: MouseEvent) {
115
- resizeEvent(e.clientX);
116
- }
117
-
118
- function resizeTouchEvent(e: TouchEvent) {
119
- resizeEvent(Math.floor(e.touches[0].clientX));
120
- }
121
-
122
- // 리사이즈 종료
123
- function doneResizeStatus() {
124
- activeResize = false;
125
- }
126
-
127
- /**
128
- * 외부용 함수
129
- */
130
- function focus() {
131
- $caption.value.focus();
132
- }
133
-
134
- // 블럭 위치 주기
135
- function getBoundingClientRect() {
136
- return $block.value.parentNode.getBoundingClientRect();
137
- }
138
-
139
- // 타입 전달
140
- function getType() {
141
- return data.value.type;
142
- }
143
-
144
- // 붙여넣기 이벤트
145
- function pasteEvent(text: string) {
146
- pasteText("text", text);
147
- }
148
-
149
- // 데이터 정규화 및 검수
150
- function updateBlockData() {
151
- emit("update:modelValue", data.value);
152
- }
153
-
154
- // 텍스트 스타일 지정
155
- function setStyles({ type, url }: styleFunctionArgument) {
156
- data.value = styleSettings({
157
- kind: type,
158
- blockData: data.value,
159
- $target: $block.value,
160
- cursorData: props.cursorData,
161
- });
162
- setTimeout(() => {
163
- updateBlockData();
164
- }, 250);
165
- }
166
-
167
- defineExpose({
168
- updateBlockData,
169
- getType,
170
- focus,
171
- pasteEvent,
172
- setStyles,
173
- getBoundingClientRect,
174
- });
175
- </script>
@@ -1,162 +0,0 @@
1
- <template>
2
- <ol class="d-ol-block" @keydown="textKeyboardEvent" ref="$ol" :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
- </ol>
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 $ol = 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 = $ol.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 = $ol.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 = $ol.value.querySelectorAll("li");
113
- setCursor(afterChildList[childIdx], cursorData.startOffset as number);
114
- }, 100);
115
- }
116
- }
117
- }
118
-
119
- // 포커스
120
- function focus() {
121
- const childList = $ol.value.querySelectorAll(".d-li-item");
122
- setCursor(childList[itemIdx.value], 0);
123
- }
124
-
125
- // 블럭 위치 주기
126
- function getBoundingClientRect() {
127
- return $ol.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>
@@ -1,172 +0,0 @@
1
- <template>
2
- <p class="d-text-block" :class="data.classList" contenteditable v-html="data.content" @keydown="textKeyboardEvent" ref="$block"></p>
3
- </template>
4
-
5
- <script setup lang="ts">
6
- // @ts-ignore
7
- import { ref, unref } from "#imports";
8
- import { keyboardEvent, setCursor, pasteText, styleSettings, getArrangementCursorData } from "../../utils/index";
9
- import { TextBlock, styleFunctionArgument, cursorSelection } from "../../../../types/index";
10
-
11
- const $block = ref();
12
- const data = ref<TextBlock>({
13
- type: "",
14
- id: "",
15
- classList: [],
16
- content: "",
17
- });
18
- const props = defineProps<{ modelValue: TextBlock; cursorData: cursorSelection }>();
19
- const emit = defineEmits<{
20
- (e: "update:modelValue", modelValue: TextBlock): void;
21
- (e: "addBlock", {}: { name: string; value: object }): void;
22
- (e: "deleteBlockLocal", index?: number): void;
23
- }>();
24
-
25
- data.value = unref(props.modelValue) as TextBlock;
26
-
27
- // 키보드 이벤트 할당
28
- function textKeyboardEvent(e: KeyboardEvent) {
29
- keyboardEvent("text", e, emit, updateBlockData);
30
- }
31
-
32
- /**
33
- * 외부용 함수
34
- */
35
-
36
- // 데이터 정규화 및 검수
37
- function updateBlockData() {
38
- const blockClassList = [...$block.value.classList];
39
- blockClassList.splice(0, 1);
40
- const pushList = blockClassList.filter((item) => data.value.classList.indexOf(item) === -1);
41
-
42
- data.value.classList = data.value.classList.concat(pushList);
43
-
44
- // 클레스 검수
45
- const checkClassIdx = data.value.classList.indexOf("d-text-block");
46
- if (checkClassIdx > -1) {
47
- data.value.classList.splice(checkClassIdx, 1);
48
- }
49
-
50
- // 커서위치 재지정
51
- if ($block.value.innerHTML.length > 0) {
52
- if (props.cursorData.endOffset !== null) {
53
- const cursorData = getArrangementCursorData(props.cursorData);
54
-
55
- data.value.content = $block.value.innerHTML;
56
- emit("update:modelValue", data.value);
57
-
58
- setTimeout(() => {
59
- if ($block.value) {
60
- setCursor($block.value.childNodes[cursorData.childCount], cursorData.length);
61
-
62
- // 구조 검수
63
- $block.value.childNodes.forEach((child: ChildNode) => {
64
- const $child = child as HTMLElement;
65
-
66
- if (child.constructor.name !== "Text") {
67
- // 텍스트가 아닐경우
68
- if (child.constructor.name !== "HTMLBRElement") {
69
- // br 태그 유지
70
- if (child.textContent === "") {
71
- // 빈 태그 삭제
72
- child.remove();
73
- } else if ($child.classList.length === 0) {
74
- // 클레스 없는 엘리먼트 처리
75
- $child.insertAdjacentHTML("afterend", $child.innerHTML);
76
- child.remove();
77
- }
78
- } else {
79
- $child.removeAttribute("class");
80
- }
81
- }
82
- });
83
- }
84
- }, 100);
85
- } else {
86
- if ($block.value) {
87
- $block.value.childNodes.forEach((child: ChildNode) => {
88
- const $child = child as HTMLElement;
89
-
90
- if (child.constructor.name !== "Text") {
91
- // 텍스트가 아닐경우
92
- if (child.constructor.name !== "HTMLBRElement") {
93
- // br 태그 유지
94
- if (child.textContent === "") {
95
- // 빈 태그 삭제
96
- child.remove();
97
- } else if ($child.classList.length === 0) {
98
- // 클레스 없는 엘리먼트 처리
99
- $child.insertAdjacentHTML("afterend", $child.innerHTML);
100
- child.remove();
101
- }
102
- } else {
103
- $child.removeAttribute("class");
104
- }
105
- }
106
- });
107
-
108
- data.value.content = $block.value.innerHTML;
109
- emit("update:modelValue", data.value);
110
- }
111
- }
112
- } else {
113
- emit("update:modelValue", data.value);
114
- }
115
- }
116
-
117
- // 포커스
118
- function focus(type: string = "first") {
119
- if (type === "first") {
120
- if ($block.value.childNodes.length > 0) {
121
- setTimeout(() => {
122
- setCursor($block.value.childNodes[0], 0);
123
- }, 100);
124
- } else {
125
- setCursor($block.value, 0);
126
- }
127
- } else {
128
- const childCount = $block.value.childNodes.length;
129
- const targetChild = $block.value.childNodes[childCount - 1];
130
-
131
- setCursor(targetChild, 0);
132
- }
133
- }
134
-
135
- // 블럭 위치 주기
136
- function getBoundingClientRect() {
137
- return $block.value.parentNode.getBoundingClientRect();
138
- }
139
-
140
- // 타입 전달
141
- function getType() {
142
- return data.value.type;
143
- }
144
-
145
- // 붙여넣기 이벤트
146
- function pasteEvent(text: string) {
147
- pasteText("text", text);
148
- }
149
-
150
- // 텍스트 스타일 지정
151
- function setStyles({ type, url }: styleFunctionArgument) {
152
- data.value = styleSettings({
153
- kind: type,
154
- blockData: data.value,
155
- $target: $block.value,
156
- url: url,
157
- cursorData: props.cursorData,
158
- });
159
- setTimeout(() => {
160
- updateBlockData();
161
- }, 250);
162
- }
163
-
164
- defineExpose({
165
- updateBlockData,
166
- focus,
167
- getType,
168
- pasteEvent,
169
- setStyles,
170
- getBoundingClientRect,
171
- });
172
- </script>
@@ -1,162 +0,0 @@
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>