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 CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  # 로컬에서 라이브러리 테스트하기
7
7
  1) 라이브러리(polavo-layout)에서 ```npm link```
8
- 2) 라이브러리를 사용하려는 프로젝트에서 ```npm link polavo-layout```
8
+ 2) 라이브러리를 사용하려는 프로젝트에서 ```npm link polarvo-layout```
9
9
 
10
10
  # 폴더구조
11
11
  src/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polarvo-layout",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "author": "unigence <unigencelab@gmail.com>",
6
6
  "repository": {
@@ -20,22 +20,22 @@
20
20
  </template>
21
21
 
22
22
  <script setup>
23
- import { toRefs, computed, inject, watch } from 'vue';
23
+ import { toRefs, computed, inject } from 'vue';
24
24
 
25
25
  const props = defineProps({
26
- polavo: {
26
+ polarvo: {
27
27
  type: Object,
28
28
  required: true,
29
29
  },
30
30
  });
31
- const { activeDesign } = toRefs(props.polavo.display.state);
32
- const { setActiveDesign } = props.polavo.display;
31
+ const { activeDesign } = toRefs(props.polarvo.display.state);
32
+ const { setActiveDesign } = props.polarvo.display;
33
33
 
34
- const { activeData, activeSection } = toRefs(props.polavo.layout.state);
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.polavo.freeDrop.state);
38
- const { activeElement: gridActiveElement } = toRefs(props.polavo.gridDrop.state);
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.polavo.components.getElement(activeSection.value, element.id);
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
- polavo: {
52
+ polarvo: {
53
53
  type: Object,
54
54
  required: true,
55
55
  },
56
56
  });
57
- const { displayMode, displaySize } = toRefs(props.polavo.display.state);
58
- const { setDisplayMode, setDisplaySize } = props.polavo.display;
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
- polavo: {
74
+ polarvo: {
75
75
  type: Object,
76
76
  required: true,
77
77
  },
78
78
  });
79
79
 
80
- const { activeSection, activeData, gapSize } = toRefs(props.polavo.layout.state);
81
- const { setGapSize, setSectionMode, setSectionConfig } = props.polavo.layout;
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="polavo.display.setActiveMenu('projectSetting')"
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="polavo.display.setActiveMenu('dbSetting')"
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="polavo.display.setActiveMenu('screenSetting')"
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="polavo.display.setActiveMenu('layout')"
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="polavo.display.setActiveMenu('element')"
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
- polavo: {
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.polavo.display.state);
145
- const { activeSection } = toRefs(props.polavo.layout.state);
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.polavo.userApi.logout();
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 :polavo="polavo" :preview="preview" :sectionKey="key" />
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
- :polavo="polavo"
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, reactive, computed } from 'vue';
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
- polavo: {
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.polavo.layout.state);
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; /* blue-500 */
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" :polavo="polavo" />
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
- polavo: {
14
+ polarvo: {
15
15
  type: Object,
16
16
  required: true,
17
17
  },
18
18
  });
19
19
 
20
- const { displaySize } = toRefs(props.polavo.display.state);
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.polavo.layout.state);
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 elements"
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 && !preview }"
10
- @mousedown.stop="startDrag($event, item.id)"
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 && !preview" class="absolute inset-0 pointer-events-none">
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 && !preview">
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
- polavo: {
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.polavo.display;
98
- const { updateActiveElement } = props.polavo.layout;
99
- const { elements, activeId, handles, guides, activeElement } = toRefs(props.polavo.freeDrop.state);
100
- const { getElementStyle, toggleLock, startDrag, startResize } = props.polavo.freeDrop;
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.polavo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
104
+ props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
118
105
  } else {
119
- props.polavo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
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
- if (newId === oldId) return;
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.polavo.components.register('sections', props.sectionKey, getCurrentInstance());
137
+ props.polarvo.components.register('sections', props.sectionKey, getCurrentInstance());
151
138
  });
152
139
 
153
140
  onUnmounted(() => {
154
- props.polavo.components.unregister('sections', props.sectionKey);
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 elements"
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
- polavo: {
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.polavo.display;
87
- const { updateActiveElement } = props.polavo.layout;
88
- const { elements, emptyData, activeCell, activeElement } = toRefs(props.polavo.gridDrop.state);
89
- const { getElementStyle, setActiveCell, toggleLock, startDrag, detectHoverCell, startResize } = props.polavo.gridDrop;
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.polavo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
99
+ props.polarvo.components.register('elements', `${props.sectionKey}-${elementId}`, el);
107
100
  } else {
108
- props.polavo.components.unregister('elements', `${props.sectionKey}-${elementId}`);
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.polavo.components.register('sections', props.sectionKey, getCurrentInstance());
132
+ props.polarvo.components.register('sections', props.sectionKey, getCurrentInstance());
141
133
  });
142
134
 
143
135
  onUnmounted(() => {
144
- props.polavo.components.unregister('sections', props.sectionKey);
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
- polavo: {
35
+ polarvo: {
36
36
  type: Object,
37
37
  required: true,
38
38
  },
39
39
  });
40
- const { layoutName, layoutSource } = toRefs(props.polavo.layout.state);
41
- const { setLayoutName } = props.polavo.layout;
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
- polavo: {
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.polavo.freeDrop;
31
- const { addElement: addElementToGrid } = props.polavo.gridDrop;
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
- polavo: {
79
+ polarvo: {
80
80
  type: Object,
81
81
  required: true,
82
82
  },
83
83
  });
84
- const { activeData, gapSize, gridNumber, gridRatio } = toRefs(props.polavo.layout.state);
85
- const { setGapSize, setRatio, setSectionMode, setSectionConfig } = props.polavo.layout;
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" :polavo="polavo" :preview="true" @click:section="setActiveSection($event)" />
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
- :polavo="polavo"
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
- polavo: {
82
+ polarvo: {
83
83
  type: Object,
84
84
  required: true,
85
85
  },
86
86
  });
87
- const { layoutName, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.polavo.layout.state);
88
- const { setGapSize, setRatio, setActiveSection } = props.polavo.layout;
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
- if (!this._activeData) {
126
- console.error('[GridDropEngine] 활성화된 데이터가 없습니다.');
127
- return;
128
- }
129
-
130
- const { gridColumns, gridRows } = this._activeData.config || {
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
- const occupied = new Set();
137
- this.gridElements.forEach((element) => {
138
- const { col, row } = element.position;
139
- const { colSpan, rowSpan } = element.size;
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
- for (let r = row; r < row + rowSpan; r++) {
142
- for (let c = col; c < col + colSpan; c++) {
143
- if (r >= 1 && c >= 1 && r <= gridRows && c <= gridColumns) {
144
- occupied.add(`${r}-${c}`); //row-col 형태로 저장
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
- const result = [];
151
- for (let r = 1; r <= gridRows; r++) {
152
- for (let c = 1; c <= gridColumns; c++) {
153
- if (!occupied.has(`${r}-${c}`)) {
154
- result.push({ row: r, col: c });
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.some((item) => {
267
- if (item.id === this._activeElement.id) return false; // 자기 자신은 무시
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
- const itemPosition = item.position;
270
- const itemSize = item.size;
317
+ const itemPosition = item.position;
318
+ const itemSize = item.size;
271
319
 
272
- return !(
273
- position.row >= itemPosition.row + itemSize.rowSpan ||
274
- position.row + size.rowSpan <= itemPosition.row ||
275
- position.col >= itemPosition.col + itemSize.colSpan ||
276
- position.col + size.colSpan <= itemPosition.col
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
- this.state.elements = elements;
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.state.layoutData).forEach(([key, section]) => {
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.state.layoutData = data.layoutData;
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.elementIds, id],
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 createPolavoLayout from './library/index.js';
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
- createPolavoLayout,
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
 
@@ -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 createPolavoLayout(config = {}) {
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 createPolavoLayout;
50
+ export default createPolarvoLayout;