polarvo-layout 1.0.22 → 1.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polarvo-layout",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "type": "module",
5
5
  "author": "unigence <unigencelab@gmail.com>",
6
6
  "repository": {
@@ -52,7 +52,6 @@ const selectedElement = inject('selectedElement');
52
52
  // const emits = defineEmits(['click:designBar']);
53
53
  function clickDesignBar(designMenu) {
54
54
  if (designMenu == 'option') {
55
- // 테스트용 -> inputForm만 남기고 추후 삭제 예정
56
55
  designMenu = activeElement.value?.type === 'inputForm' ? 'option-form' : 'option-default';
57
56
  }
58
57
 
@@ -79,9 +79,9 @@ const { layoutName, layoutData, activeSection, gapSize, gridNumber, gridRatio }
79
79
 
80
80
  const getBaseStyle = computed(() => {
81
81
  return {
82
- // gridTemplateColumns: gridRatio.value?.column.map((ratio) => `${ratio}%`).join(' '),
83
- // gridTemplateRows: gridRatio.value?.row.map((ratio) => `${ratio}%`).join(' '),
84
- // marginRight: layoutType.value === 'no-split' ? '0' : layoutType.value === 'three-column-split' ? '14px' : '8px',
82
+ gridTemplateColumns: gridRatio.value?.column.map((ratio) => `${ratio}%`).join(' '),
83
+ gridTemplateRows: gridRatio.value?.row.map((ratio) => `${ratio}%`).join(' '),
84
+ marginRight: layoutType.value === 'no-split' ? '0' : layoutType.value === 'three-column-split' ? '14px' : '8px',
85
85
  gap: `${gapSize.value}px`,
86
86
  };
87
87
  });
@@ -0,0 +1,169 @@
1
+ <template>
2
+ <div
3
+ :id="item.id"
4
+ class="absolute user-select-none"
5
+ :style="itemStyle"
6
+ :class="{ 'z-50': item.id === activeId, 'bg-white border-2 border-blue-400': item.id === activeId }"
7
+ @mousedown.stop="activeEditMode ? null : handleMouseDown($event, item.id)"
8
+ >
9
+
10
+ <!-- 리사이즈 핸들 -->
11
+ <div v-if="item.id === activeId" class="absolute inset-0 pointer-events-none">
12
+ <div
13
+ v-for="handle in handles"
14
+ :key="handle.name"
15
+ :class="`handle absolute bg-blue-400 z-10 pointer-events-auto hover:bg-blue-700 ${handle.name}`"
16
+ @mousedown="startResize($event, handle.name)"
17
+ ></div>
18
+ <div class="flex flex-row m-1 gap-1">
19
+ <!-- 잠금 토글-->
20
+ <div class="z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
21
+ <LockIcon v-if="item.isLocked" />
22
+ <UnlockIcon v-else />
23
+ </div>
24
+ <!-- 편집 토글-->
25
+ <div class="z-10 pointer-events-auto cursor-pointer">
26
+ <div v-if="item.type === 'inputForm'" @click="toggleEditMode">
27
+ <div v-if="activeEditMode" class="bg-red-100 text-red-400 px-2 py-1 text-sm rounded-md hover:opacity-80 animate-pulse">
28
+ 편집모드 on
29
+ </div>
30
+ <div v-else class="bg-gray-100 px-2 py-1 text-sm rounded-md hover:bg-gray-200">편집모드 off</div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+
36
+ <component
37
+ :is="dynamicComponent"
38
+ :id="`${sectionKey}-${item.id}`"
39
+ :rootId="item.id"
40
+ :ref="setRef"
41
+ v-bind="item"
42
+ class="hover:opacity-80"
43
+ :class="activeEditMode ? `pointer-events-auto ` : `pointer-events-none`"
44
+ />
45
+ </div>
46
+ </template>
47
+
48
+ <script setup>
49
+ import { computed, inject, toRefs, defineAsyncComponent, markRaw } from 'vue';
50
+ import LockIcon from '../../icons/action/LockIcon.vue';
51
+ import UnlockIcon from '../../icons/action/UnlockIcon.vue';
52
+
53
+ const props = defineProps({
54
+ item: { type: Object, required: true },
55
+ polarvo: { type: Object, required: true },
56
+ sectionKey: { type: String, required: true },
57
+ });
58
+
59
+ const { activeId, handles } = toRefs(props.polarvo.freeDrop.state);
60
+ const { getElementStyle, handleMouseDown, startResize, toggleLock } = props.polarvo.freeDrop;
61
+
62
+ const activeEditMode = inject('activeEditMode');
63
+ function toggleEditMode() {
64
+ activeEditMode.value = !activeEditMode.value;
65
+ }
66
+
67
+ const itemStyle = computed(() => getElementStyle(props.item));
68
+
69
+ const _componentCache = new Map();
70
+ const _modules = import.meta.glob('@/components/elements/*.vue');
71
+
72
+ const dynamicComponent = computed(() => {
73
+ const elName = props.item.type;
74
+ if (_componentCache.has(elName)) return _componentCache.get(elName);
75
+
76
+ const matched = Object.keys(_modules).find((path) => path.includes(elName));
77
+ if (!matched) {
78
+ const fallback = markRaw(defineAsyncComponent(async () => ({ template: '<span style="display:none"></span>' })));
79
+ _componentCache.set(elName, fallback);
80
+ return fallback;
81
+ }
82
+ const component = markRaw(defineAsyncComponent(_modules[matched]));
83
+ _componentCache.set(elName, component);
84
+ return component;
85
+ });
86
+
87
+ function setRef(el) {
88
+ if (el) {
89
+ props.polarvo.components.register('elements', `${props.sectionKey}-${props.item.id}`, el);
90
+ } else {
91
+ props.polarvo.components.unregister('elements', `${props.sectionKey}-${props.item.id}`);
92
+ }
93
+ }
94
+ </script>
95
+
96
+ <style lang="scss" scoped>
97
+
98
+ .handle {
99
+ // 모서리
100
+ &.nw {
101
+ top: -4px;
102
+ left: -4px;
103
+ width: 8px;
104
+ height: 8px;
105
+ cursor: nw-resize;
106
+ }
107
+
108
+ &.ne {
109
+ top: -4px;
110
+ right: -4px;
111
+ width: 8px;
112
+ height: 8px;
113
+ cursor: ne-resize;
114
+ }
115
+
116
+ &.sw {
117
+ bottom: -4px;
118
+ left: -4px;
119
+ width: 8px;
120
+ height: 8px;
121
+ cursor: sw-resize;
122
+ }
123
+
124
+ &.se {
125
+ bottom: -4px;
126
+ right: -4px;
127
+ width: 8px;
128
+ height: 8px;
129
+ cursor: se-resize;
130
+ }
131
+
132
+ // 가장자리
133
+ &.n {
134
+ top: -4px;
135
+ left: 50%;
136
+ transform: translateX(-50%);
137
+ width: 8px;
138
+ height: 8px;
139
+ cursor: n-resize;
140
+ }
141
+
142
+ &.s {
143
+ bottom: -4px;
144
+ left: 50%;
145
+ transform: translateX(-50%);
146
+ width: 8px;
147
+ height: 8px;
148
+ cursor: s-resize;
149
+ }
150
+
151
+ &.w {
152
+ top: 50%;
153
+ left: -4px;
154
+ transform: translateY(-50%);
155
+ width: 8px;
156
+ height: 8px;
157
+ cursor: w-resize;
158
+ }
159
+
160
+ &.e {
161
+ top: 50%;
162
+ right: -4px;
163
+ transform: translateY(-50%);
164
+ width: 8px;
165
+ height: 8px;
166
+ cursor: e-resize;
167
+ }
168
+ }
169
+ </style>
@@ -1,50 +1,12 @@
1
1
  <template>
2
2
  <div v-if="!preview">
3
- <div
3
+ <FreeItem
4
4
  v-for="(item, index) in filteredElements"
5
5
  :key="item.id"
6
- :id="item.id"
7
- class="absolute user-select-none"
8
- :style="getElementStyle(item)"
9
- :class="{ 'z-50': item.id === activeId, 'bg-white border-2 border-blue-400': item.id === activeId }"
10
- @mousedown.stop="activeEditMode ? null : handleMouseDown($event, item.id)"
11
- >
12
- <!-- 리사이즈 핸들 -->
13
- <div v-if="item.id === activeId" class="absolute inset-0 pointer-events-none">
14
- <div
15
- v-for="handle in handles"
16
- :key="handle.name"
17
- :class="`handle absolute bg-blue-400 z-10 pointer-events-auto hover:bg-blue-700 ${handle.name}`"
18
- @mousedown="startResize($event, handle.name)"
19
- ></div>
20
- <div class="flex flex-row m-1 gap-1">
21
- <!-- 잠금 토글-->
22
- <div class="z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
23
- <LockIcon v-if="item.isLocked" />
24
- <UnlockIcon v-else />
25
- </div>
26
- <!-- 편집 토글-->
27
- <div class="z-10 pointer-events-auto cursor-pointer">
28
- <div v-if="item.type === 'inputForm'" @click="toggleEditMode">
29
- <div v-if="activeEditMode" class="bg-red-100 text-red-400 px-2 py-1 text-sm rounded-md hover:opacity-80 animate-pulse">
30
- 편집모드 on
31
- </div>
32
- <div v-else class="bg-gray-100 px-2 py-1 text-sm rounded-md hover:bg-gray-200">편집모드 off</div>
33
- </div>
34
- </div>
35
- </div>
36
- </div>
37
-
38
- <component
39
- :is="dynamicComponent(item.type)"
40
- :id="`${sectionKey}-${item.id}`"
41
- :rootId="item.id"
42
- :ref="(el) => setComponentRef(el, item.id)"
43
- v-bind="item"
44
- class="hover:opacity-80"
45
- :class="activeEditMode ? `pointer-events-auto ` : `pointer-events-none`"
46
- />
47
- </div>
6
+ :item="item"
7
+ :polarvo="props.polarvo"
8
+ :sectionKey="props.sectionKey"
9
+ ></FreeItem>
48
10
 
49
11
  <!-- 오버레이 -->
50
12
  <div v-if="activeEditMode" class="absolute inset-0 bg-black opacity-50"></div>
@@ -68,20 +30,9 @@
68
30
  </template>
69
31
 
70
32
  <script setup>
71
- import LockIcon from '../../icons/action/LockIcon.vue';
72
- import UnlockIcon from '../../icons/action/UnlockIcon.vue';
33
+ import FreeItem from './FreeItem.vue';
73
34
 
74
- import {
75
- toRefs,
76
- defineAsyncComponent,
77
- markRaw,
78
- getCurrentInstance,
79
- onMounted,
80
- onUnmounted,
81
- inject,
82
- watch,
83
- computed,
84
- } from 'vue';
35
+ import { toRefs, getCurrentInstance, onMounted, onUnmounted, inject, watch, computed } from 'vue';
85
36
 
86
37
  const props = defineProps({
87
38
  polarvo: {
@@ -108,48 +59,14 @@ const props = defineProps({
108
59
 
109
60
  const { setActiveDesign } = props.polarvo.display;
110
61
  const { updateActiveElement } = props.polarvo.layout;
111
- const { elements, activeId, handles, guides, activeElement } = toRefs(props.polarvo.freeDrop.state);
112
- const { getElementStyle, toggleLock, handleMouseDown, startResize } = props.polarvo.freeDrop;
62
+ const { elements, guides, activeElement } = toRefs(props.polarvo.freeDrop.state);
113
63
  const filteredElements = computed(() => {
114
64
  return elements.value.filter((el) => props.elementIds?.includes(el.id) && el.section === props.sectionKey);
115
65
  });
116
66
 
117
- const _componentCache = new Map();
118
- const modules = import.meta.glob('@/components/elements/*.vue');
119
-
120
- function dynamicComponent(elName) {
121
- if (_componentCache.has(elName)) {
122
- return _componentCache.get(elName);
123
- }
124
-
125
- const matched = Object.keys(modules).find((path) => {
126
- return path.includes(elName);
127
- });
128
-
129
- if (!matched) {
130
- return markRaw(defineAsyncComponent(async () => ({ template: '<span style="display:none"></span>' })));
131
- }
132
-
133
- const component = markRaw(defineAsyncComponent(modules[matched]));
134
- _componentCache.set(elName, component);
135
- return component;
136
- }
137
-
138
- function setComponentRef(el, elementId) {
139
- if (el) {
140
- props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
141
- } else {
142
- props.polarvo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
143
- }
144
- }
145
-
146
67
  const selectedElement = inject('selectedElement');
147
68
  const activeEditMode = inject('activeEditMode');
148
69
 
149
- function toggleEditMode() {
150
- activeEditMode.value = !activeEditMode.value;
151
- }
152
-
153
70
  let _isElementSwitching = false;
154
71
  import { omit, cloneDeep } from 'lodash-es';
155
72
  watch(
@@ -159,6 +76,7 @@ watch(
159
76
  if (!newId) {
160
77
  setActiveDesign(null);
161
78
  }
79
+
162
80
  _isElementSwitching = true;
163
81
  // selectedElement.value = structuredClone(toRaw(activeElement.value));
164
82
  selectedElement.value = cloneDeep(activeElement.value);
@@ -194,77 +112,6 @@ onUnmounted(() => {
194
112
  </script>
195
113
 
196
114
  <style lang="scss" scoped>
197
- .handle {
198
- // 모서리
199
- &.nw {
200
- top: -4px;
201
- left: -4px;
202
- width: 8px;
203
- height: 8px;
204
- cursor: nw-resize;
205
- }
206
-
207
- &.ne {
208
- top: -4px;
209
- right: -4px;
210
- width: 8px;
211
- height: 8px;
212
- cursor: ne-resize;
213
- }
214
-
215
- &.sw {
216
- bottom: -4px;
217
- left: -4px;
218
- width: 8px;
219
- height: 8px;
220
- cursor: sw-resize;
221
- }
222
-
223
- &.se {
224
- bottom: -4px;
225
- right: -4px;
226
- width: 8px;
227
- height: 8px;
228
- cursor: se-resize;
229
- }
230
-
231
- // 가장자리
232
- &.n {
233
- top: -4px;
234
- left: 50%;
235
- transform: translateX(-50%);
236
- width: 8px;
237
- height: 8px;
238
- cursor: n-resize;
239
- }
240
-
241
- &.s {
242
- bottom: -4px;
243
- left: 50%;
244
- transform: translateX(-50%);
245
- width: 8px;
246
- height: 8px;
247
- cursor: s-resize;
248
- }
249
-
250
- &.w {
251
- top: 50%;
252
- left: -4px;
253
- transform: translateY(-50%);
254
- width: 8px;
255
- height: 8px;
256
- cursor: w-resize;
257
- }
258
-
259
- &.e {
260
- top: 50%;
261
- right: -4px;
262
- transform: translateY(-50%);
263
- width: 8px;
264
- height: 8px;
265
- cursor: e-resize;
266
- }
267
- }
268
115
 
269
116
  .guide {
270
117
  &.vertical {
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <div
3
+ :id="item.id ?? `${item.row}-${item.col}`"
4
+ :class="
5
+ item.id
6
+ ? ['relative bg-gray-200 user-select-none', { 'z-50 bg-white border-2 border-blue-400': item.id === activeId }]
7
+ : 'flex items-center justify-center bg-gray-100 border border-gray-300'
8
+ "
9
+ :style="itemStyle"
10
+ @mousedown.stop="activeEditMode ? null : handleMouseDown($event, item)"
11
+ @mouseenter="item.id ? null : detectHoverCell(item)"
12
+ >
13
+ <template v-if="item.id">
14
+ <!-- 리사이즈 핸들 -->
15
+ <div v-if="item.id === activeId" class="absolute inset-0 pointer-events-none">
16
+ <div
17
+ class="absolute w-4 h-4 bottom-0 right-0 bg-blue-400 z-10 pointer-events-auto cursor-se-resize"
18
+ @mousedown="startResize($event, item.id)"
19
+ ></div>
20
+ <div class="flex gap-1 m-1">
21
+ <!-- 잠금 토글-->
22
+ <div class="z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
23
+ <LockIcon v-if="item.isLocked" />
24
+ <UnlockIcon v-else />
25
+ </div>
26
+ <!-- 편집 토글-->
27
+ <div class="z-10 pointer-events-auto cursor-pointer">
28
+ <div v-if="item.type === 'inputForm'" @click="toggleEditMode">
29
+ <div v-if="activeEditMode" class="bg-red-100 text-red-400 px-2 py-1 text-sm rounded-md hover:opacity-80 animate-pulse">
30
+ 편집모드 on
31
+ </div>
32
+ <div v-else class="bg-gray-100 px-2 py-1 text-sm rounded-md hover:bg-gray-200">편집모드 off</div>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </div>
37
+
38
+ <component
39
+ :is="dynamicComponent"
40
+ :id="`${sectionKey}-${item.id}`"
41
+ :rootId="item.id"
42
+ :ref="setRef"
43
+ v-bind="item"
44
+ class="hover:opacity-80"
45
+ :class="activeEditMode ? `pointer-events-auto ` : `pointer-events-none`"
46
+ />
47
+
48
+ <!-- 오버레이 -->
49
+ <div v-if="activeEditMode && item.id !== activeId" class="absolute inset-0 bg-black opacity-50"></div>
50
+ </template>
51
+
52
+ <template v-else>
53
+ <div
54
+ class="text-sm w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-500 hover:bg-blue-200 hover:text-white transition-colors cursor-pointer"
55
+ >
56
+ +
57
+ </div>
58
+ </template>
59
+ </div>
60
+ </template>
61
+
62
+ <script setup>
63
+ import { computed, inject, toRefs, defineAsyncComponent, markRaw } from 'vue';
64
+ import LockIcon from '../../icons/action/LockIcon.vue';
65
+ import UnlockIcon from '../../icons/action/UnlockIcon.vue';
66
+
67
+ const props = defineProps({
68
+ item: { type: Object, required: true },
69
+ polarvo: { type: Object, required: true },
70
+ sectionKey: { type: String, required: true },
71
+ });
72
+
73
+ const { activeId } = toRefs(props.polarvo.gridDrop.state);
74
+ const { getElementStyle, toggleLock, handleMouseDown, detectHoverCell, startResize } = props.polarvo.gridDrop;
75
+
76
+ const activeEditMode = inject('activeEditMode');
77
+ function toggleEditMode() {
78
+ activeEditMode.value = !activeEditMode.value;
79
+ }
80
+
81
+ const itemStyle = computed(() => getElementStyle(props.item.id ? 'element' : 'empty', props.item));
82
+
83
+ const _componentCache = new Map();
84
+ const _modules = import.meta.glob('@/components/elements/*.vue');
85
+
86
+ const dynamicComponent = computed(() => {
87
+ const elName = props.item.type;
88
+ if (_componentCache.has(elName)) return _componentCache.get(elName);
89
+
90
+ const matched = Object.keys(_modules).find((path) => path.includes(elName));
91
+ if (!matched) {
92
+ const fallback = markRaw(defineAsyncComponent(async () => ({ template: '<span style="display:none"></span>' })));
93
+ _componentCache.set(elName, fallback);
94
+ return fallback;
95
+ }
96
+ const component = markRaw(defineAsyncComponent(_modules[matched]));
97
+ _componentCache.set(elName, component);
98
+ return component;
99
+ });
100
+
101
+ function setRef(el) {
102
+ if (el) {
103
+ props.polarvo.components.register('elements', `${props.sectionKey}-${props.item.id}`, el);
104
+ } else {
105
+ props.polarvo.components.unregister('elements', `${props.sectionKey}-${props.item.id}`);
106
+ }
107
+ }
108
+ </script>
@@ -1,76 +1,23 @@
1
1
  <template>
2
2
  <template v-if="!preview">
3
- <div
3
+ <GridItem
4
4
  v-for="(item, index) in mergedData"
5
- :key="item.id ?? `${item.row}-${item.col}`"
6
- :id="item.id ?? `${item.row}-${item.col}`"
7
- :style="getElementStyle(item.id ? 'element' : 'empty', item)"
8
- :class="
9
- item.id
10
- ? ['relative bg-gray-200', { 'z-50 bg-white border-2 border-blue-400': item.id === activeId }]
11
- : 'flex items-center justify-center bg-gray-100 border border-gray-300'
12
- "
13
- @mousedown="activeEditMode ? null : handleMouseDown($event, item)"
14
- @mouseenter="item.id ? null : detectHoverCell(item)"
15
- >
16
- <template v-if="item.id">
17
- <div>
18
- <!-- 리사이즈 핸들 -->
19
- <div v-if="item.id === activeId">
20
- <div
21
- class="absolute w-4 h-4 bottom-0 right-0 bg-blue-400 z-10 cursor-se-resize"
22
- @mousedown="startResize($event, item.id)"
23
- ></div>
24
- <div class="flex gap-1 m-1">
25
- <!-- 잠금 토글-->
26
- <div class="z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
27
- <LockIcon v-if="item.isLocked" />
28
- <UnlockIcon v-else />
29
- </div>
30
- <!-- 편집 토글-->
31
- <div class="z-10 pointer-events-auto cursor-pointer">
32
- <div v-if="item.type === 'inputForm'" @click="toggleEditMode">
33
- <div v-if="activeEditMode" class="bg-red-100 text-red-400 px-2 py-1 text-sm rounded-md hover:opacity-80 animate-pulse">
34
- 편집모드 on
35
- </div>
36
- <div v-else class="bg-gray-100 px-2 py-1 text-sm rounded-md hover:bg-gray-200">편집모드 off</div>
37
- </div>
38
- </div>
39
- </div>
40
- </div>
41
-
42
- <component
43
- :is="dynamicComponent(item.type)"
44
- :id="`${sectionKey}-${item.id}`"
45
- :rootId="item.id"
46
- :ref="(el) => setComponentRef(el, item.id)"
47
- v-bind="item"
48
- class="hover:opacity-80"
49
- :class="activeEditMode ? `pointer-events-auto ` : `pointer-events-none`"
50
- />
51
- </div>
52
-
53
- <!-- 오버레이 -->
54
- <div v-if="activeEditMode && item.id !== activeId" class="absolute inset-0 bg-black opacity-50"></div>
55
- </template>
56
-
57
- <template v-else>
58
- <div
59
- class="text-sm w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-500 hover:bg-blue-200 hover:text-white transition-colors cursor-pointer"
60
- >
61
- +
62
- </div>
63
- </template>
64
- </div>
5
+ :key="item.id || `empty-${index}`"
6
+ :item="item"
7
+ :polarvo="props.polarvo"
8
+ :sectionKey="props.sectionKey"
9
+ ></GridItem>
10
+
11
+ <!-- 오버레이 -->
12
+ <div v-if="activeEditMode" class="absolute inset-0 bg-black opacity-50"></div>
65
13
  </template>
66
14
  </template>
67
15
 
68
16
  <script setup>
69
- import LockIcon from '../../icons/action/LockIcon.vue';
70
- import UnlockIcon from '../../icons/action/UnlockIcon.vue';
17
+ import GridItem from './GridItem.vue';
18
+
19
+ import { toRefs, getCurrentInstance, onMounted, onUnmounted, inject, watch, computed } from 'vue';
71
20
 
72
- import { toRefs, ref, defineAsyncComponent, markRaw, getCurrentInstance, onMounted, onUnmounted, inject, watch, computed } from 'vue';
73
- const emit = defineEmits(['click:element']);
74
21
  const props = defineProps({
75
22
  polarvo: {
76
23
  type: Object,
@@ -121,42 +68,9 @@ const mergedData = computed(() => {
121
68
  return [...filled, ...empty];
122
69
  });
123
70
 
124
- const _componentCache = new Map();
125
- const modules = import.meta.glob('@/components/elements/*.vue');
126
-
127
- function dynamicComponent(elName) {
128
- if (_componentCache.has(elName)) {
129
- return _componentCache.get(elName);
130
- }
131
-
132
- const matched = Object.keys(modules).find((path) => {
133
- return path.includes(elName);
134
- });
135
-
136
- if (!matched) {
137
- return markRaw(defineAsyncComponent(async () => ({ template: '<span style="display:none"></span>' })));
138
- }
139
-
140
- const component = markRaw(defineAsyncComponent(modules[matched]));
141
- _componentCache.set(elName, component);
142
- return component;
143
- }
144
-
145
- function setComponentRef(el, elementId) {
146
- if (el) {
147
- props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
148
- } else {
149
- props.polarvo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
150
- }
151
- }
152
-
153
71
  const selectedElement = inject('selectedElement');
154
72
  const activeEditMode = inject('activeEditMode');
155
73
 
156
- function toggleEditMode() {
157
- activeEditMode.value = !activeEditMode.value;
158
- }
159
-
160
74
  let _isElementSwitching = false;
161
75
  import { omit, cloneDeep } from 'lodash-es';
162
76
  watch(