polarvo-layout 1.0.0 → 1.0.2
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 +1 -1
- package/package.json +1 -1
- package/src/components/FastMenu/DesignFastMenu.vue +8 -8
- package/src/components/FastMenu/DisplayFastMenu.vue +3 -3
- package/src/components/FastMenu/LayoutFastMenu.vue +3 -3
- package/src/components/IconBar/IconBar.vue +9 -9
- package/src/components/Layout/BaseLayout.vue +10 -15
- package/src/components/Layout/CanvasContainer.vue +4 -4
- package/src/components/Layout/FreeLayout.vue +28 -41
- package/src/components/Layout/GridLayout.vue +21 -29
- package/src/components/MiniMenu/LayoutMiniMenu.vue +3 -3
- package/src/components/SideBar/ElementSideBar.vue +3 -3
- package/src/components/SideBar/LayoutSettingSideBar.vue +3 -3
- package/src/components/SideBar/LayoutSideBar.vue +6 -6
- package/src/core/engines/FreeDropEngine.js +13 -2
- package/src/core/engines/GridDropEngine.js +90 -40
- package/src/core/managers/EngineManager.js +9 -6
- package/src/index.js +2 -2
- package/src/library/GridDropLibrary.js +4 -0
- package/src/library/LayoutLibrary.js +2 -1
- package/src/library/index.js +2 -2
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -20,22 +20,22 @@
|
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
22
|
<script setup>
|
|
23
|
-
import { toRefs, computed, inject
|
|
23
|
+
import { toRefs, computed, inject } from 'vue';
|
|
24
24
|
|
|
25
25
|
const props = defineProps({
|
|
26
|
-
|
|
26
|
+
polarvo: {
|
|
27
27
|
type: Object,
|
|
28
28
|
required: true,
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
|
-
const { activeDesign } = toRefs(props.
|
|
32
|
-
const { setActiveDesign } = props.
|
|
31
|
+
const { activeDesign } = toRefs(props.polarvo.display.state);
|
|
32
|
+
const { setActiveDesign } = props.polarvo.display;
|
|
33
33
|
|
|
34
|
-
const { activeData, activeSection } = toRefs(props.
|
|
34
|
+
const { activeData, activeSection } = toRefs(props.polarvo.layout.state);
|
|
35
35
|
const sectionMode = computed(() => activeData.value?.mode);
|
|
36
36
|
|
|
37
|
-
const { activeElement: freeActiveElement } = toRefs(props.
|
|
38
|
-
const { activeElement: gridActiveElement } = toRefs(props.
|
|
37
|
+
const { activeElement: freeActiveElement } = toRefs(props.polarvo.freeDrop.state);
|
|
38
|
+
const { activeElement: gridActiveElement } = toRefs(props.polarvo.gridDrop.state);
|
|
39
39
|
|
|
40
40
|
const activeElement = computed(() => {
|
|
41
41
|
if (sectionMode.value === 'free') {
|
|
@@ -65,7 +65,7 @@ function clickDesignBar(designMenu) {
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
function setComponentDefaults(element) {
|
|
68
|
-
const child = props.
|
|
68
|
+
const child = props.polarvo.components.getElement(activeSection.value, element.id);
|
|
69
69
|
if (!child) return;
|
|
70
70
|
selectedChildProps.value = Object.keys(child.$props);
|
|
71
71
|
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
import { toRefs } from 'vue';
|
|
50
50
|
|
|
51
51
|
const props = defineProps({
|
|
52
|
-
|
|
52
|
+
polarvo: {
|
|
53
53
|
type: Object,
|
|
54
54
|
required: true,
|
|
55
55
|
},
|
|
56
56
|
});
|
|
57
|
-
const { displayMode, displaySize } = toRefs(props.
|
|
58
|
-
const { setDisplayMode, setDisplaySize } = props.
|
|
57
|
+
const { displayMode, displaySize } = toRefs(props.polarvo.display.state);
|
|
58
|
+
const { setDisplayMode, setDisplaySize } = props.polarvo.display;
|
|
59
59
|
</script>
|
|
60
60
|
|
|
61
61
|
<style scoped>
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
import { toRefs, computed } from 'vue';
|
|
72
72
|
|
|
73
73
|
const props = defineProps({
|
|
74
|
-
|
|
74
|
+
polarvo: {
|
|
75
75
|
type: Object,
|
|
76
76
|
required: true,
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
const { activeSection, activeData, gapSize } = toRefs(props.
|
|
81
|
-
const { setGapSize, setSectionMode, setSectionConfig } = props.
|
|
80
|
+
const { activeSection, activeData, gapSize } = toRefs(props.polarvo.layout.state);
|
|
81
|
+
const { setGapSize, setSectionMode, setSectionConfig } = props.polarvo.layout;
|
|
82
82
|
const sectionMode = computed(() => activeData.value?.mode);
|
|
83
83
|
</script>
|
|
84
84
|
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
class="icon-wrapper text-2xl text-gray-400 p-2 hover"
|
|
33
33
|
title="내부설정"
|
|
34
34
|
:class="{ active: activeMenu === 'projectSetting' }"
|
|
35
|
-
@click="
|
|
35
|
+
@click="polarvo.display.setActiveMenu('projectSetting')"
|
|
36
36
|
>
|
|
37
37
|
<font-awesome-icon :icon="['fas', 'computer']" />
|
|
38
38
|
<div class="text-xs text-center col-span-1 w-max">내부설정</div>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
class="icon-wrapper text-2xl text-gray-400 p-2 hover"
|
|
42
42
|
title="DB관리"
|
|
43
43
|
:class="{ active: activeMenu === 'dbSetting' }"
|
|
44
|
-
@click="
|
|
44
|
+
@click="polarvo.display.setActiveMenu('dbSetting')"
|
|
45
45
|
>
|
|
46
46
|
<font-awesome-icon :icon="['fas', 'database']" />
|
|
47
47
|
<div class="text-xs text-center col-span-1 w-max">DB관리</div>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
class="icon-wrapper text-2xl text-gray-400 p-2 hover"
|
|
51
51
|
title="화면관리"
|
|
52
52
|
:class="{ active: activeMenu === 'screenSetting' }"
|
|
53
|
-
@click="
|
|
53
|
+
@click="polarvo.display.setActiveMenu('screenSetting')"
|
|
54
54
|
>
|
|
55
55
|
<font-awesome-icon :icon="['far', 'window-restore']" />
|
|
56
56
|
<div class="text-xs text-center col-span-1 w-max">화면관리</div>
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
class="icon-wrapper text-2xl text-gray-400 p-2 hover"
|
|
66
66
|
title="레이아웃"
|
|
67
67
|
:class="{ active: activeMenu === 'layout' }"
|
|
68
|
-
@click="
|
|
68
|
+
@click="polarvo.display.setActiveMenu('layout')"
|
|
69
69
|
>
|
|
70
70
|
<font-awesome-icon :icon="['fas', 'table-columns']" />
|
|
71
71
|
<div class="text-xs text-center col-span-1 w-max">레이아웃</div>
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
class="icon-wrapper text-2xl text-gray-400 p-2 hover"
|
|
76
76
|
title="요소"
|
|
77
77
|
:class="{ active: activeMenu === 'element' }"
|
|
78
|
-
@click="
|
|
78
|
+
@click="polarvo.display.setActiveMenu('element')"
|
|
79
79
|
>
|
|
80
80
|
<font-awesome-icon :icon="['fas', 'shapes']" />
|
|
81
81
|
<div class="text-xs text-center col-span-1 w-max">요소</div>
|
|
@@ -128,7 +128,7 @@ import { ref, toRefs } from 'vue';
|
|
|
128
128
|
import { clickOutside } from '../../utils/index.js';
|
|
129
129
|
|
|
130
130
|
const props = defineProps({
|
|
131
|
-
|
|
131
|
+
polarvo: {
|
|
132
132
|
type: Object,
|
|
133
133
|
required: true,
|
|
134
134
|
},
|
|
@@ -141,8 +141,8 @@ const props = defineProps({
|
|
|
141
141
|
default: false,
|
|
142
142
|
},
|
|
143
143
|
});
|
|
144
|
-
const { activeMenu } = toRefs(props.
|
|
145
|
-
const { activeSection } = toRefs(props.
|
|
144
|
+
const { activeMenu } = toRefs(props.polarvo.display.state);
|
|
145
|
+
const { activeSection } = toRefs(props.polarvo.layout.state);
|
|
146
146
|
|
|
147
147
|
// 디렉티브 등록
|
|
148
148
|
const vClickOutside = clickOutside;
|
|
@@ -156,7 +156,7 @@ import { useRouter } from 'vue-router';
|
|
|
156
156
|
const router = useRouter();
|
|
157
157
|
|
|
158
158
|
async function logout() {
|
|
159
|
-
const result = await props.
|
|
159
|
+
const result = await props.polarvo.userApi.logout();
|
|
160
160
|
if (result) {
|
|
161
161
|
// 로그아웃 성공 시 라우터 이동
|
|
162
162
|
//서브도메인 제거하기위해 아래와 같이 코드 짰습니다
|
|
@@ -2,35 +2,29 @@
|
|
|
2
2
|
<div
|
|
3
3
|
:id="preview ? 'previewLayout' : 'baseLayout'"
|
|
4
4
|
class="grid h-full p-2 bg-transparent rounded-lg"
|
|
5
|
-
:class="[
|
|
6
|
-
layoutType + '-layout',
|
|
7
|
-
`grid-cols-${gridNumber.column}`,
|
|
8
|
-
'mb-4' ? layoutType === 'three-column-split' : '',
|
|
9
|
-
]"
|
|
5
|
+
:class="[layoutType + '-layout', `grid-cols-${gridNumber.column}`, 'mb-4' ? layoutType === 'three-column-split' : '']"
|
|
10
6
|
:style="getBaseStyle"
|
|
11
7
|
>
|
|
12
8
|
<template v-for="(section, key) in layoutData" :key="key">
|
|
13
9
|
<PolarLayout
|
|
14
10
|
:id="preview ? `${key}Preview` : `${key}Layout`"
|
|
15
11
|
:style="getSectionStyle(section)"
|
|
16
|
-
:class="[
|
|
17
|
-
getSectionClass(key, section),
|
|
18
|
-
activeSection === key && preview ? 'text-blue-400 bg-blue-50' : 'text-gray-400',
|
|
19
|
-
]"
|
|
12
|
+
:class="[getSectionClass(key, section), activeSection === key && preview ? 'text-blue-400 bg-blue-50' : 'text-gray-400']"
|
|
20
13
|
@click.stop="emit('click:section', key)"
|
|
21
14
|
>
|
|
22
15
|
<div v-if="preview" class="absolute text-sm top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
|
|
23
16
|
{{ key }}
|
|
24
17
|
</div>
|
|
25
18
|
<template v-if="section.mode === 'grid'">
|
|
26
|
-
<GridLayout :
|
|
19
|
+
<GridLayout :polarvo="polarvo" :preview="preview" :sectionKey="key" :elementIds="section.elementIds" />
|
|
27
20
|
</template>
|
|
28
21
|
|
|
29
22
|
<template v-else>
|
|
30
23
|
<FreeLayout
|
|
31
|
-
:
|
|
24
|
+
:polarvo="polarvo"
|
|
32
25
|
:preview="preview"
|
|
33
26
|
:sectionKey="key"
|
|
27
|
+
:elementIds="section.elementIds"
|
|
34
28
|
:isActive="activeSection === key"
|
|
35
29
|
/>
|
|
36
30
|
</template>
|
|
@@ -40,7 +34,7 @@
|
|
|
40
34
|
</template>
|
|
41
35
|
|
|
42
36
|
<script setup>
|
|
43
|
-
import { toRefs,
|
|
37
|
+
import { toRefs, computed } from 'vue';
|
|
44
38
|
|
|
45
39
|
import PolarLayout from './PolarLayout.vue';
|
|
46
40
|
import FreeLayout from './FreeLayout.vue';
|
|
@@ -53,7 +47,7 @@ window.oncontextmenu = () => {
|
|
|
53
47
|
|
|
54
48
|
const emit = defineEmits(['click:section']);
|
|
55
49
|
const props = defineProps({
|
|
56
|
-
|
|
50
|
+
polarvo: {
|
|
57
51
|
type: Object,
|
|
58
52
|
required: true,
|
|
59
53
|
},
|
|
@@ -93,7 +87,7 @@ const getSectionClass = (key, section) => ({
|
|
|
93
87
|
disabled: activeSection.value != key && !props.preview,
|
|
94
88
|
});
|
|
95
89
|
|
|
96
|
-
const { layoutName, layoutData, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.
|
|
90
|
+
const { layoutName, layoutData, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.polarvo.layout.state);
|
|
97
91
|
</script>
|
|
98
92
|
|
|
99
93
|
<style scoped>
|
|
@@ -109,7 +103,8 @@ const { layoutName, layoutData, activeSection, gapSize, gridNumber, gridRatio }
|
|
|
109
103
|
|
|
110
104
|
[id^='section'].section-active {
|
|
111
105
|
border-width: 1px;
|
|
112
|
-
border-color: #3b82f6;
|
|
106
|
+
border-color: #3b82f6;
|
|
107
|
+
/* blue-500 */
|
|
113
108
|
}
|
|
114
109
|
|
|
115
110
|
[id^='section'].disabled {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="w-full h-full p-4">
|
|
3
3
|
<div id="canvas-container" class="border rounded-md w-full h-full bg-white" :style="containerStyle">
|
|
4
|
-
<BaseLayout ref="baseLayoutRef" :
|
|
4
|
+
<BaseLayout ref="baseLayoutRef" :polarvo="polarvo" />
|
|
5
5
|
</div>
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
@@ -11,13 +11,13 @@ import { toRefs, inject, computed, provide } from 'vue';
|
|
|
11
11
|
import BaseLayout from './BaseLayout.vue';
|
|
12
12
|
|
|
13
13
|
const props = defineProps({
|
|
14
|
-
|
|
14
|
+
polarvo: {
|
|
15
15
|
type: Object,
|
|
16
16
|
required: true,
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
const { displaySize } = toRefs(props.
|
|
20
|
+
const { displaySize } = toRefs(props.polarvo.display.state);
|
|
21
21
|
const gridSize = computed(() => displaySize.value.gridSize || 16);
|
|
22
22
|
|
|
23
23
|
const containerStyle = computed(() => {
|
|
@@ -35,7 +35,7 @@ const containerStyle = computed(() => {
|
|
|
35
35
|
};
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
const { elements } = toRefs(props.
|
|
38
|
+
const { elements } = toRefs(props.polarvo.layout.state);
|
|
39
39
|
|
|
40
40
|
// 전체 elements
|
|
41
41
|
provide('elements', elements)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
2
|
+
<div v-if="!preview">
|
|
3
3
|
<div
|
|
4
|
-
v-for="(item, index) in
|
|
4
|
+
v-for="(item, index) in filteredElements"
|
|
5
5
|
:key="index"
|
|
6
6
|
:id="item.id"
|
|
7
7
|
class="absolute user-select-none"
|
|
8
8
|
:style="getElementStyle(item)"
|
|
9
|
-
:class="{ 'z-50': item.id === activeId, 'bg-white border-2 border-blue-400': item.id === activeId
|
|
10
|
-
@mousedown.stop="startDrag($event,
|
|
9
|
+
:class="{ 'z-50': item.id === activeId, 'bg-white border-2 border-blue-400': item.id === activeId }"
|
|
10
|
+
@mousedown.stop="startDrag($event, item.id)"
|
|
11
11
|
>
|
|
12
12
|
<!-- 리사이즈 핸들 -->
|
|
13
|
-
<div v-if="item.id === activeId
|
|
13
|
+
<div v-if="item.id === activeId" class="absolute inset-0 pointer-events-none">
|
|
14
14
|
<div
|
|
15
15
|
v-for="handle in handles"
|
|
16
16
|
:key="handle.name"
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
<component
|
|
26
|
-
v-if="!preview"
|
|
27
26
|
:is="dynamicComponent(item.type)"
|
|
28
27
|
:id="`${sectionKey}-${index}`"
|
|
29
28
|
:ref="(el) => setComponentRef(el, item.id)"
|
|
@@ -33,22 +32,14 @@
|
|
|
33
32
|
</div>
|
|
34
33
|
|
|
35
34
|
<!-- 가이드라인 -->
|
|
36
|
-
<div v-if="isActive
|
|
37
|
-
<div
|
|
38
|
-
v-if="guides.x !== null"
|
|
39
|
-
class="guide absolute z-10 pointer-events-none vertical"
|
|
40
|
-
:style="{ left: `${guides.x}px` }"
|
|
41
|
-
></div>
|
|
35
|
+
<div v-if="isActive">
|
|
36
|
+
<div v-if="guides.x !== null" class="guide absolute z-10 pointer-events-none vertical" :style="{ left: `${guides.x}px` }"></div>
|
|
42
37
|
<div
|
|
43
38
|
v-if="guides.x !== null"
|
|
44
39
|
class="guide absolute z-10 pointer-events-none vertical"
|
|
45
40
|
:style="{ left: `${guides.x + guides.w}px` }"
|
|
46
41
|
></div>
|
|
47
|
-
<div
|
|
48
|
-
v-if="guides.y !== null"
|
|
49
|
-
class="guide absolute z-10 pointer-events-none horizontal"
|
|
50
|
-
:style="{ top: `${guides.y}px` }"
|
|
51
|
-
></div>
|
|
42
|
+
<div v-if="guides.y !== null" class="guide absolute z-10 pointer-events-none horizontal" :style="{ top: `${guides.y}px` }"></div>
|
|
52
43
|
<div
|
|
53
44
|
v-if="guides.y !== null"
|
|
54
45
|
class="guide absolute z-10 pointer-events-none horizontal"
|
|
@@ -62,21 +53,10 @@
|
|
|
62
53
|
import LockIcon from '../../icons/action/LockIcon.vue';
|
|
63
54
|
import UnlockIcon from '../../icons/action/UnlockIcon.vue';
|
|
64
55
|
|
|
65
|
-
import {
|
|
66
|
-
toRefs,
|
|
67
|
-
defineAsyncComponent,
|
|
68
|
-
markRaw,
|
|
69
|
-
getCurrentInstance,
|
|
70
|
-
onMounted,
|
|
71
|
-
onUnmounted,
|
|
72
|
-
inject,
|
|
73
|
-
watch,
|
|
74
|
-
toRaw,
|
|
75
|
-
computed,
|
|
76
|
-
} from 'vue';
|
|
56
|
+
import { toRefs, defineAsyncComponent, markRaw, getCurrentInstance, onMounted, onUnmounted, inject, watch, toRaw, computed } from 'vue';
|
|
77
57
|
|
|
78
58
|
const props = defineProps({
|
|
79
|
-
|
|
59
|
+
polarvo: {
|
|
80
60
|
type: Object,
|
|
81
61
|
required: true,
|
|
82
62
|
},
|
|
@@ -88,16 +68,23 @@ const props = defineProps({
|
|
|
88
68
|
type: String,
|
|
89
69
|
required: true,
|
|
90
70
|
},
|
|
71
|
+
elementIds: {
|
|
72
|
+
type: Array,
|
|
73
|
+
required: true,
|
|
74
|
+
},
|
|
91
75
|
isActive: {
|
|
92
76
|
type: Boolean,
|
|
93
77
|
default: false,
|
|
94
78
|
},
|
|
95
79
|
});
|
|
96
80
|
|
|
97
|
-
const { setActiveDesign } = props.
|
|
98
|
-
const { updateActiveElement } = props.
|
|
99
|
-
const { elements, activeId, handles, guides, activeElement } = toRefs(props.
|
|
100
|
-
const { getElementStyle, toggleLock, startDrag, startResize } = props.
|
|
81
|
+
const { setActiveDesign } = props.polarvo.display;
|
|
82
|
+
const { updateActiveElement } = props.polarvo.layout;
|
|
83
|
+
const { elements, activeId, handles, guides, activeElement } = toRefs(props.polarvo.freeDrop.state);
|
|
84
|
+
const { getElementStyle, toggleLock, startDrag, startResize } = props.polarvo.freeDrop;
|
|
85
|
+
const filteredElements = computed(() => {
|
|
86
|
+
return elements.value.filter((el) => props.elementIds?.includes(el.id) && el.section === props.sectionKey);
|
|
87
|
+
});
|
|
101
88
|
|
|
102
89
|
function dynamicComponent(elName) {
|
|
103
90
|
const modules = import.meta.glob('@/components/elements/*.vue');
|
|
@@ -114,9 +101,9 @@ function dynamicComponent(elName) {
|
|
|
114
101
|
|
|
115
102
|
function setComponentRef(el, elementId) {
|
|
116
103
|
if (el) {
|
|
117
|
-
props.
|
|
104
|
+
props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
|
|
118
105
|
} else {
|
|
119
|
-
props.
|
|
106
|
+
props.polarvo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
|
|
120
107
|
}
|
|
121
108
|
}
|
|
122
109
|
|
|
@@ -125,9 +112,9 @@ const selectedElement = inject('selectedElement');
|
|
|
125
112
|
watch(
|
|
126
113
|
() => activeElement.value?.id,
|
|
127
114
|
(newId, oldId) => {
|
|
128
|
-
|
|
115
|
+
if (newId === oldId) return;
|
|
129
116
|
if (!newId) {
|
|
130
|
-
setActiveDesign(null)
|
|
117
|
+
setActiveDesign(null);
|
|
131
118
|
}
|
|
132
119
|
selectedElement.value = structuredClone(toRaw(activeElement.value));
|
|
133
120
|
},
|
|
@@ -141,17 +128,17 @@ const selectedElementForWatch = computed(() => omit(selectedElement.value, ['pos
|
|
|
141
128
|
watch(
|
|
142
129
|
() => selectedElementForWatch.value,
|
|
143
130
|
(newElement) => {
|
|
144
|
-
updateActiveElement(selectedElement.value?.id, newElement)
|
|
131
|
+
updateActiveElement(selectedElement.value?.id, newElement);
|
|
145
132
|
},
|
|
146
133
|
{ deep: true }
|
|
147
134
|
);
|
|
148
135
|
|
|
149
136
|
onMounted(() => {
|
|
150
|
-
props.
|
|
137
|
+
props.polarvo.components.register('sections', props.sectionKey, getCurrentInstance());
|
|
151
138
|
});
|
|
152
139
|
|
|
153
140
|
onUnmounted(() => {
|
|
154
|
-
props.
|
|
141
|
+
props.polarvo.components.unregister('sections', props.sectionKey);
|
|
155
142
|
});
|
|
156
143
|
</script>
|
|
157
144
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
v-for="(item, index) in
|
|
3
|
+
v-for="(item, index) in filteredElements"
|
|
4
4
|
:key="index"
|
|
5
5
|
:id="item.id"
|
|
6
6
|
class="relative bg-gray-200"
|
|
@@ -13,10 +13,7 @@
|
|
|
13
13
|
>
|
|
14
14
|
<!-- 리사이즈 핸들 -->
|
|
15
15
|
<div v-if="activeElement?.id === item.id && !preview">
|
|
16
|
-
<div
|
|
17
|
-
class="absolute w-4 h-4 bottom-0 right-0 bg-blue-400 z-10 cursor-se-resize"
|
|
18
|
-
@mousedown="startResize($event, item.id)"
|
|
19
|
-
></div>
|
|
16
|
+
<div class="absolute w-4 h-4 bottom-0 right-0 bg-blue-400 z-10 cursor-se-resize" @mousedown="startResize($event, item.id)"></div>
|
|
20
17
|
<div class="absolute z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
|
|
21
18
|
<LockIcon v-if="item.isLocked" />
|
|
22
19
|
<UnlockIcon v-else />
|
|
@@ -55,21 +52,10 @@
|
|
|
55
52
|
import LockIcon from '../../icons/action/LockIcon.vue';
|
|
56
53
|
import UnlockIcon from '../../icons/action/UnlockIcon.vue';
|
|
57
54
|
|
|
58
|
-
import {
|
|
59
|
-
toRefs,
|
|
60
|
-
defineAsyncComponent,
|
|
61
|
-
markRaw,
|
|
62
|
-
getCurrentInstance,
|
|
63
|
-
onMounted,
|
|
64
|
-
onUnmounted,
|
|
65
|
-
inject,
|
|
66
|
-
watch,
|
|
67
|
-
toRaw,
|
|
68
|
-
computed,
|
|
69
|
-
} from 'vue';
|
|
55
|
+
import { toRefs, defineAsyncComponent, markRaw, getCurrentInstance, onMounted, onUnmounted, inject, watch, toRaw, computed } from 'vue';
|
|
70
56
|
const emit = defineEmits(['click:element']);
|
|
71
57
|
const props = defineProps({
|
|
72
|
-
|
|
58
|
+
polarvo: {
|
|
73
59
|
type: Object,
|
|
74
60
|
required: true,
|
|
75
61
|
},
|
|
@@ -81,12 +67,19 @@ const props = defineProps({
|
|
|
81
67
|
type: String,
|
|
82
68
|
required: true,
|
|
83
69
|
},
|
|
70
|
+
elementIds: {
|
|
71
|
+
type: Array,
|
|
72
|
+
required: true,
|
|
73
|
+
}
|
|
84
74
|
});
|
|
85
75
|
|
|
86
|
-
const { setActiveDesign } = props.
|
|
87
|
-
const { updateActiveElement } = props.
|
|
88
|
-
const { elements, emptyData, activeCell, activeElement } = toRefs(props.
|
|
89
|
-
const { getElementStyle, setActiveCell, toggleLock, startDrag, detectHoverCell, startResize } = props.
|
|
76
|
+
const { setActiveDesign } = props.polarvo.display;
|
|
77
|
+
const { updateActiveElement } = props.polarvo.layout;
|
|
78
|
+
const { elements, emptyData, activeCell, activeElement } = toRefs(props.polarvo.gridDrop.state);
|
|
79
|
+
const { getElementStyle, setActiveCell, toggleLock, startDrag, detectHoverCell, startResize } = props.polarvo.gridDrop;
|
|
80
|
+
const filteredElements = computed(() => {
|
|
81
|
+
return elements.value.filter((el) => props.elementIds?.includes(el.id) && el.section === props.sectionKey);
|
|
82
|
+
});
|
|
90
83
|
|
|
91
84
|
function dynamicComponent(elName) {
|
|
92
85
|
const modules = import.meta.glob('@/components/elements/*.vue');
|
|
@@ -103,21 +96,20 @@ function dynamicComponent(elName) {
|
|
|
103
96
|
|
|
104
97
|
function setComponentRef(el, elementId) {
|
|
105
98
|
if (el) {
|
|
106
|
-
props.
|
|
99
|
+
props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
|
|
107
100
|
} else {
|
|
108
|
-
props.
|
|
101
|
+
props.polarvo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
|
|
109
102
|
}
|
|
110
103
|
}
|
|
111
104
|
|
|
112
105
|
const selectedElement = inject('selectedElement');
|
|
113
106
|
|
|
114
|
-
|
|
115
107
|
watch(
|
|
116
108
|
() => activeElement.value?.id,
|
|
117
109
|
(newId, oldId) => {
|
|
118
110
|
if (newId === oldId) return;
|
|
119
111
|
if (!newId) {
|
|
120
|
-
setActiveDesign(null)
|
|
112
|
+
setActiveDesign(null);
|
|
121
113
|
}
|
|
122
114
|
selectedElement.value = structuredClone(toRaw(activeElement.value));
|
|
123
115
|
},
|
|
@@ -131,16 +123,16 @@ const selectedElementForWatch = computed(() => omit(selectedElement.value, ['pos
|
|
|
131
123
|
watch(
|
|
132
124
|
() => selectedElementForWatch.value,
|
|
133
125
|
(newElement) => {
|
|
134
|
-
updateActiveElement(selectedElement.value?.id, newElement)
|
|
126
|
+
updateActiveElement(selectedElement.value?.id, newElement);
|
|
135
127
|
},
|
|
136
128
|
{ deep: true }
|
|
137
129
|
);
|
|
138
130
|
|
|
139
131
|
onMounted(() => {
|
|
140
|
-
props.
|
|
132
|
+
props.polarvo.components.register('sections', props.sectionKey, getCurrentInstance());
|
|
141
133
|
});
|
|
142
134
|
|
|
143
135
|
onUnmounted(() => {
|
|
144
|
-
props.
|
|
136
|
+
props.polarvo.components.unregister('sections', props.sectionKey);
|
|
145
137
|
});
|
|
146
138
|
</script>
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
import { toRefs, watch } from 'vue';
|
|
33
33
|
|
|
34
34
|
const props = defineProps({
|
|
35
|
-
|
|
35
|
+
polarvo: {
|
|
36
36
|
type: Object,
|
|
37
37
|
required: true,
|
|
38
38
|
},
|
|
39
39
|
});
|
|
40
|
-
const { layoutName, layoutSource } = toRefs(props.
|
|
41
|
-
const { setLayoutName } = props.
|
|
40
|
+
const { layoutName, layoutSource } = toRefs(props.polarvo.layout.state);
|
|
41
|
+
const { setLayoutName } = props.polarvo.layout;
|
|
42
42
|
|
|
43
43
|
const emits = defineEmits(['click:layout']);
|
|
44
44
|
watch(
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { ref, onBeforeMount } from 'vue';
|
|
18
18
|
|
|
19
19
|
const props = defineProps({
|
|
20
|
-
|
|
20
|
+
polarvo: {
|
|
21
21
|
type: Object,
|
|
22
22
|
required: true,
|
|
23
23
|
},
|
|
@@ -27,8 +27,8 @@ const props = defineProps({
|
|
|
27
27
|
default: '',
|
|
28
28
|
},
|
|
29
29
|
});
|
|
30
|
-
const { addElement: addElementToFree } = props.
|
|
31
|
-
const { addElement: addElementToGrid } = props.
|
|
30
|
+
const { addElement: addElementToFree } = props.polarvo.freeDrop;
|
|
31
|
+
const { addElement: addElementToGrid } = props.polarvo.gridDrop;
|
|
32
32
|
|
|
33
33
|
const allElements = ref([]);
|
|
34
34
|
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
import { toRefs, computed } from 'vue';
|
|
77
77
|
|
|
78
78
|
const props = defineProps({
|
|
79
|
-
|
|
79
|
+
polarvo: {
|
|
80
80
|
type: Object,
|
|
81
81
|
required: true,
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
|
-
const { activeData, gapSize, gridNumber, gridRatio } = toRefs(props.
|
|
85
|
-
const { setGapSize, setRatio, setSectionMode, setSectionConfig } = props.
|
|
84
|
+
const { activeData, gapSize, gridNumber, gridRatio } = toRefs(props.polarvo.layout.state);
|
|
85
|
+
const { setGapSize, setRatio, setSectionMode, setSectionConfig } = props.polarvo.layout;
|
|
86
86
|
|
|
87
87
|
const sectionMode = computed(() => activeData.value?.mode);
|
|
88
88
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div class="aspect-[3/2] border border-gray-200 rounded-md bg-white">
|
|
4
|
-
<BaseLayout id="preview" :
|
|
3
|
+
<div class="aspect-[3/2] border border-gray-200 rounded-md bg-white ">
|
|
4
|
+
<BaseLayout id="preview" :polarvo="polarvo" :preview="true" @click:section="setActiveSection($event)" />
|
|
5
5
|
<button
|
|
6
6
|
class="text-sm bg-blue-100 text-center w-full py-1 hover:cursor-pointer hover:bg-blue-200 active:opacity-80"
|
|
7
7
|
@click="setActiveSection(null)"
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
</h5>
|
|
63
63
|
<LayoutSetting
|
|
64
64
|
v-if="activeSection !== null"
|
|
65
|
-
:
|
|
65
|
+
:polarvo="polarvo"
|
|
66
66
|
class="mt-2 border border-gray-200 rounded-md bg-white"
|
|
67
67
|
/>
|
|
68
68
|
<div v-else>
|
|
@@ -79,11 +79,11 @@ import BaseLayout from '../Layout/BaseLayout.vue';
|
|
|
79
79
|
import LayoutSetting from './LayoutSettingSideBar.vue';
|
|
80
80
|
|
|
81
81
|
const props = defineProps({
|
|
82
|
-
|
|
82
|
+
polarvo: {
|
|
83
83
|
type: Object,
|
|
84
84
|
required: true,
|
|
85
85
|
},
|
|
86
86
|
});
|
|
87
|
-
const { layoutName, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.
|
|
88
|
-
const { setGapSize, setRatio, setActiveSection } = props.
|
|
87
|
+
const { layoutName, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.polarvo.layout.state);
|
|
88
|
+
const { setGapSize, setRatio, setActiveSection } = props.polarvo.layout;
|
|
89
89
|
</script>
|
|
@@ -91,6 +91,16 @@ class FreeDropEngine {
|
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
+
this._elements = [];
|
|
95
|
+
this._elementsUpdate = false;
|
|
96
|
+
this._freeElements = [];
|
|
97
|
+
|
|
98
|
+
this._activeData = null;
|
|
99
|
+
this._activeSection = null;
|
|
100
|
+
this._activeElement = null;
|
|
101
|
+
|
|
102
|
+
this.guides = { x: null, y: null, w: null, h: null };
|
|
103
|
+
|
|
94
104
|
this._subscriptions = [];
|
|
95
105
|
this.eventBus = null;
|
|
96
106
|
|
|
@@ -208,7 +218,7 @@ class FreeDropEngine {
|
|
|
208
218
|
console.error('[FreeDropEngine] 충돌 검사를 위한 아이템 정보를 찾을 수 없습니다:', this._activeElement.id);
|
|
209
219
|
return false;
|
|
210
220
|
}
|
|
211
|
-
|
|
221
|
+
|
|
212
222
|
const newElementRect = {
|
|
213
223
|
left: this._activeElement.position.x,
|
|
214
224
|
top: this._activeElement.position.y,
|
|
@@ -216,7 +226,7 @@ class FreeDropEngine {
|
|
|
216
226
|
bottom: this._activeElement.position.y + this._activeElement.size.h,
|
|
217
227
|
};
|
|
218
228
|
|
|
219
|
-
return this.freeElements.some((element) => {
|
|
229
|
+
return this.freeElements.filter((element) => element.section === this._activeElement.section).some((element) => {
|
|
220
230
|
if (element.id === this._activeElement.id) return false; // 자기 자신은 제외
|
|
221
231
|
|
|
222
232
|
const elementRect = {
|
|
@@ -282,6 +292,7 @@ class FreeDropEngine {
|
|
|
282
292
|
mode: 'free',
|
|
283
293
|
position: this._startPos,
|
|
284
294
|
size: elementSource[elName] || { w: 100, h: 100 },
|
|
295
|
+
section: this._activeSection,
|
|
285
296
|
isLocked: false,
|
|
286
297
|
};
|
|
287
298
|
|
|
@@ -7,6 +7,7 @@ class GridDropEngine {
|
|
|
7
7
|
this._elementsUpdate = false; // 원본 요소 목록 변경 플래그
|
|
8
8
|
this._gridElements = []; // 로컬에서 사용하는 요소 목록
|
|
9
9
|
|
|
10
|
+
this._layoutData = null;
|
|
10
11
|
this._activeData = null;
|
|
11
12
|
this._activeSection = null;
|
|
12
13
|
|
|
@@ -47,9 +48,12 @@ class GridDropEngine {
|
|
|
47
48
|
this._initialize();
|
|
48
49
|
});
|
|
49
50
|
|
|
50
|
-
this._subscribe('system:setElements', ({ elements }) => {
|
|
51
|
+
this._subscribe('system:setElements', ({ elements, layoutData }) => {
|
|
52
|
+
this._layoutData = layoutData;
|
|
51
53
|
this._elements = elements;
|
|
52
54
|
this._elementsUpdate = true;
|
|
55
|
+
|
|
56
|
+
this._setEmptyData('all');
|
|
53
57
|
});
|
|
54
58
|
|
|
55
59
|
this._subscribe('system:updateElements', ({ elements }) => {
|
|
@@ -78,6 +82,19 @@ class GridDropEngine {
|
|
|
78
82
|
}
|
|
79
83
|
});
|
|
80
84
|
|
|
85
|
+
this._elements = [];
|
|
86
|
+
this._elementsUpdate = false;
|
|
87
|
+
this._gridElements = [];
|
|
88
|
+
|
|
89
|
+
this._activeData = null;
|
|
90
|
+
this._activeSection = null;
|
|
91
|
+
|
|
92
|
+
this._activeCell = null;
|
|
93
|
+
this._targetCell = null;
|
|
94
|
+
this._activeElement = null;
|
|
95
|
+
|
|
96
|
+
this.emptyData = {};
|
|
97
|
+
|
|
81
98
|
this._subscriptions = [];
|
|
82
99
|
this.eventBus = null;
|
|
83
100
|
|
|
@@ -121,41 +138,72 @@ class GridDropEngine {
|
|
|
121
138
|
}
|
|
122
139
|
|
|
123
140
|
/** 빈 데이터 설정 */
|
|
124
|
-
_setEmptyData() {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
gridColumns: 3,
|
|
132
|
-
gridRows: 3,
|
|
133
|
-
};
|
|
141
|
+
_setEmptyData(type = null) {
|
|
142
|
+
// 공통 로직을 헬퍼 함수로 추출
|
|
143
|
+
const calculateEmptyData = (sectionKey, sectionData) => {
|
|
144
|
+
const { gridColumns, gridRows } = sectionData.config || {
|
|
145
|
+
gridColumns: 3,
|
|
146
|
+
gridRows: 3,
|
|
147
|
+
};
|
|
134
148
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
// 데이터가 존재하는 셀 리스트
|
|
150
|
+
const grid = Array.from({ length: gridRows + 1 }, () => Array(gridColumns + 1).fill(false));
|
|
151
|
+
|
|
152
|
+
this.gridElements
|
|
153
|
+
.filter((element) => element.section === sectionKey)
|
|
154
|
+
.forEach((element) => {
|
|
155
|
+
const { col, row } = element.position;
|
|
156
|
+
const { colSpan, rowSpan } = element.size;
|
|
157
|
+
|
|
158
|
+
for (let r = row; r < row + rowSpan; r++) {
|
|
159
|
+
for (let c = col; c < col + colSpan; c++) {
|
|
160
|
+
if (r >= 1 && c >= 1 && r <= gridRows && c <= gridColumns) {
|
|
161
|
+
grid[r][c] = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
140
166
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
167
|
+
// 빈 셀 찾기
|
|
168
|
+
const result = [];
|
|
169
|
+
for (let r = 1; r <= gridRows; r++) {
|
|
170
|
+
for (let c = 1; c <= gridColumns; c++) {
|
|
171
|
+
if (!grid[r][c]) {
|
|
172
|
+
result.push({ row: r, col: c });
|
|
145
173
|
}
|
|
146
174
|
}
|
|
147
175
|
}
|
|
148
|
-
});
|
|
149
176
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
177
|
+
return result;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// 초기 세팅
|
|
181
|
+
if (type === 'all') {
|
|
182
|
+
if (!this._layoutData) {
|
|
183
|
+
console.error('[GridDropEngine] 레이아웃 데이터가 없습니다.');
|
|
184
|
+
return;
|
|
156
185
|
}
|
|
186
|
+
|
|
187
|
+
// 모든 섹션에 대해 빈 데이터 계산
|
|
188
|
+
Object.entries(this._layoutData).forEach(([sectionKey, sectionData]) => {
|
|
189
|
+
this.emptyData[sectionKey] = calculateEmptyData(sectionKey, sectionData);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
this.eventBus.emit('gridDrop:updateAllEmptyData', {
|
|
193
|
+
emptyData: this.emptyData,
|
|
194
|
+
timestamp: Date.now(),
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 단일 섹션 처리
|
|
201
|
+
if (!this._activeData) {
|
|
202
|
+
console.error('[GridDropEngine] 활성화된 데이터가 없습니다.');
|
|
203
|
+
return;
|
|
157
204
|
}
|
|
158
205
|
|
|
206
|
+
const result = calculateEmptyData(this._activeSection, this._activeData);
|
|
159
207
|
this.emptyData[this._activeSection] = result;
|
|
160
208
|
|
|
161
209
|
this.eventBus.emit('gridDrop:updateEmptyData', {
|
|
@@ -163,8 +211,6 @@ class GridDropEngine {
|
|
|
163
211
|
activeSection: this._activeSection,
|
|
164
212
|
timestamp: Date.now(),
|
|
165
213
|
});
|
|
166
|
-
|
|
167
|
-
return;
|
|
168
214
|
}
|
|
169
215
|
|
|
170
216
|
/** 활성화 배치요소 변경 */
|
|
@@ -263,19 +309,21 @@ class GridDropEngine {
|
|
|
263
309
|
return false;
|
|
264
310
|
}
|
|
265
311
|
|
|
266
|
-
return this.gridElements
|
|
267
|
-
|
|
312
|
+
return this.gridElements
|
|
313
|
+
.filter((item) => item.section === this._activeElement.section)
|
|
314
|
+
.some((item) => {
|
|
315
|
+
if (item.id === this._activeElement.id) return false; // 자기 자신은 무시
|
|
268
316
|
|
|
269
|
-
|
|
270
|
-
|
|
317
|
+
const itemPosition = item.position;
|
|
318
|
+
const itemSize = item.size;
|
|
271
319
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
320
|
+
return !(
|
|
321
|
+
position.row >= itemPosition.row + itemSize.rowSpan ||
|
|
322
|
+
position.row + size.rowSpan <= itemPosition.row ||
|
|
323
|
+
position.col >= itemPosition.col + itemSize.colSpan ||
|
|
324
|
+
position.col + size.colSpan <= itemPosition.col
|
|
325
|
+
);
|
|
326
|
+
});
|
|
279
327
|
}
|
|
280
328
|
|
|
281
329
|
/** ---------------------------------- 배치요소 관련 메소드 ---------------------------------- **/
|
|
@@ -300,10 +348,12 @@ class GridDropEngine {
|
|
|
300
348
|
mode: 'grid',
|
|
301
349
|
position: { col: this._activeCell.col, row: this._activeCell.row },
|
|
302
350
|
size: { colSpan: 1, rowSpan: 1 },
|
|
351
|
+
section: this._activeSection,
|
|
303
352
|
isLocked: false,
|
|
304
353
|
};
|
|
305
354
|
|
|
306
355
|
this.eventBus.emit('gridDrop:requestAddElement', {
|
|
356
|
+
id: element.id,
|
|
307
357
|
element: element,
|
|
308
358
|
timestamp: Date.now(),
|
|
309
359
|
});
|
|
@@ -70,14 +70,16 @@ class EngineManager {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
setElements(elements) {
|
|
73
|
-
|
|
73
|
+
// section 정보가 없는 경우 section1으로 간주
|
|
74
|
+
this.state.elements = elements.map(x => x.section ? x : { ...x, section: 'section1' });
|
|
74
75
|
|
|
75
76
|
// 각 섹션의 elementIds 업데이트
|
|
76
|
-
Object.entries(this.
|
|
77
|
-
section.elementIds = this.state.elements.filter((x) => x.mode === section.mode).map((x) => x.id);
|
|
77
|
+
Object.entries(this._layoutData).forEach(([key, section]) => {
|
|
78
|
+
section.elementIds = this.state.elements.filter((x) => x.mode === section.mode && x.section === key).map((x) => x.id);
|
|
78
79
|
});
|
|
79
|
-
|
|
80
|
+
|
|
80
81
|
this.eventBus.emit('system:setElements', {
|
|
82
|
+
layoutData: this._layoutData,
|
|
81
83
|
elements: this.state.elements,
|
|
82
84
|
timestamp: Date.now(),
|
|
83
85
|
});
|
|
@@ -118,9 +120,10 @@ class EngineManager {
|
|
|
118
120
|
this._layoutData = data.layoutData;
|
|
119
121
|
this._dataUpdate = true;
|
|
120
122
|
});
|
|
123
|
+
|
|
121
124
|
// layoutData 업데이트
|
|
122
125
|
this._subscribe('layout:updateLayoutData', (data) => {
|
|
123
|
-
this.
|
|
126
|
+
this._layoutData = data.layoutData;
|
|
124
127
|
this._dataUpdate = true;
|
|
125
128
|
});
|
|
126
129
|
|
|
@@ -287,7 +290,7 @@ class EngineManager {
|
|
|
287
290
|
this.eventBus.emit('system:closeActiveMenu');
|
|
288
291
|
|
|
289
292
|
this.updateActiveData({
|
|
290
|
-
elementIds: [...this.activeData
|
|
293
|
+
elementIds: [...this.activeData?.elementIds, id],
|
|
291
294
|
});
|
|
292
295
|
});
|
|
293
296
|
|
package/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import './styles.scss';
|
|
3
3
|
|
|
4
4
|
// 라이브러리 함수
|
|
5
|
-
import
|
|
5
|
+
import createPolarvoLayout from './library/index.js';
|
|
6
6
|
|
|
7
7
|
// 컴포넌트
|
|
8
8
|
import IconBar from './components/IconBar/IconBar.vue';
|
|
@@ -19,7 +19,7 @@ import CanvasContainer from './components/Layout/CanvasContainer.vue';
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
export {
|
|
22
|
-
|
|
22
|
+
createPolarvoLayout,
|
|
23
23
|
IconBar,
|
|
24
24
|
DisplayFastMenu,
|
|
25
25
|
HistoryFastMenu,
|
|
@@ -42,6 +42,10 @@ function useGridDrop(api) {
|
|
|
42
42
|
state.elements = cloneDeep(api.gridDrop.getGridElements());
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
+
_subscribe('gridDrop:updateAllEmptyData', ({ emptyData }) => {
|
|
46
|
+
state.emptyData = cloneDeep(emptyData);
|
|
47
|
+
});
|
|
48
|
+
|
|
45
49
|
_subscribe('gridDrop:updateEmptyData', ({ emptyData, activeSection }) => {
|
|
46
50
|
state.emptyData[activeSection] = cloneDeep(emptyData);
|
|
47
51
|
});
|
|
@@ -41,7 +41,8 @@ function useLayout(api) {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
// elements 변경 감지
|
|
44
|
-
_subscribe('system:setElements', ({ elements }) => {
|
|
44
|
+
_subscribe('system:setElements', ({ layoutData, elements }) => {
|
|
45
|
+
state.layoutData = cloneDeep(layoutData);
|
|
45
46
|
state.elements = cloneDeep(elements);
|
|
46
47
|
});
|
|
47
48
|
|
package/src/library/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import useFreeDrop from './FreeDropLibrary.js';
|
|
|
6
6
|
import useGridDrop from './GridDropLibrary.js';
|
|
7
7
|
import useHistory from './HistoryLibrary.js';
|
|
8
8
|
|
|
9
|
-
async function
|
|
9
|
+
async function createPolarvoLayout(config = {}) {
|
|
10
10
|
let manager = new EngineManager(config);
|
|
11
11
|
await manager.initialize();
|
|
12
12
|
|
|
@@ -47,4 +47,4 @@ async function createPolavoLayout(config = {}) {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export default
|
|
50
|
+
export default createPolarvoLayout;
|