polarvo-layout 1.0.20 → 1.0.21

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.20",
3
+ "version": "1.0.21",
4
4
  "type": "module",
5
5
  "author": "unigence <unigencelab@gmail.com>",
6
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  name="px"
23
23
  aria-label="픽셀 단위 크기"
24
24
  min="600"
25
- max="2400"
25
+ max="1200"
26
26
  step="50"
27
27
  :value="displaySize?.px"
28
28
  class="border-b-2 pr-1 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
@@ -34,7 +34,7 @@
34
34
  name="percent"
35
35
  aria-label="퍼센트 단위 크기"
36
36
  min="0"
37
- max="100"
37
+ max="200"
38
38
  step="10"
39
39
  :value="displaySize?.percent"
40
40
  class="border-b-2 pr-1 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
@@ -19,7 +19,7 @@
19
19
  <input
20
20
  type="checkbox"
21
21
  :checked="activeConfig?.showGuideLine"
22
- @change="setSectionConfig('guideLine', $event.target.checked)"
22
+ @change="handleSectionConfigChange('guideLine', $event.target.checked)"
23
23
  />
24
24
  </div>
25
25
  </template>
@@ -34,7 +34,7 @@
34
34
  max="50"
35
35
  class="text-sm text-center w-6 border-b-2 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
36
36
  :value="activeConfig?.gridRows"
37
- @change="setSectionConfig('row', $event.target.value)"
37
+ @change="handleSectionConfigChange('row', $event.target.value)"
38
38
  />
39
39
  </div>
40
40
  <div class="flex items-center gap-1">
@@ -46,7 +46,7 @@
46
46
  max="12"
47
47
  class="text-sm text-center w-6 border-b-2 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
48
48
  :value="activeConfig?.gridColumns"
49
- @change="setSectionConfig('column', $event.target.value)"
49
+ @change="handleSectionConfigChange('column', $event.target.value)"
50
50
  />
51
51
  </div>
52
52
  <div class="flex items-center gap-1">
@@ -58,7 +58,7 @@
58
58
  max="12"
59
59
  class="text-sm text-center w-6 border-b-2 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
60
60
  :value="activeConfig?.gridGap"
61
- @change="setSectionConfig('gap', $event.target.value)"
61
+ @change="handleSectionConfigChange('gap', $event.target.value)"
62
62
  />
63
63
  </div>
64
64
  </div>
@@ -80,6 +80,14 @@ const props = defineProps({
80
80
  const { activeSection, activeMode, activeConfig } = toRefs(props.polarvo.layout.state);
81
81
  const { setSectionMode, setSectionConfig } = props.polarvo.layout;
82
82
  const sectionMode = computed(() => activeMode.value);
83
+
84
+ function handleSectionConfigChange(type, value) {
85
+ const { result, message } = setSectionConfig(type, value)
86
+
87
+ if (!result) {
88
+ alert(message)
89
+ }
90
+ }
83
91
  </script>
84
92
 
85
93
  <style scoped lang="scss">
@@ -23,10 +23,16 @@ const props = defineProps({
23
23
  },
24
24
  });
25
25
 
26
+ const DEFAULT_DISPLAY_SIZE = {
27
+ px: 1200,
28
+ percent: 100,
29
+ gridSize: 16,
30
+ aspectRatio: '16/9',
31
+ };
32
+
26
33
  // height 관련 여유 공간 추가하여 계산함 (50, 200)
27
34
  const { displaySize } = toRefs(props.polarvo.display.state);
28
35
  const { elements } = toRefs(props.polarvo.layout.state);
29
- const gridSize = computed(() => displaySize.value?.gridSize || 16);
30
36
  const defaultHeight = computed(() => {
31
37
  return (
32
38
  elements.value?.reduce((max, el) => {
@@ -52,19 +58,37 @@ function expandContainer() {
52
58
  }
53
59
 
54
60
  const containerStyle = computed(() => {
61
+ if (!displaySize.value) {
62
+ return {
63
+ aspectRatio: DEFAULT_DISPLAY_SIZE.aspectRatio,
64
+ width: `${DEFAULT_DISPLAY_SIZE.px}px`,
65
+ height: `${displayHeight.value}px`,
66
+ margin: '0 auto',
67
+ transform: `scale(${DEFAULT_DISPLAY_SIZE.percent / 100})`,
68
+ transformOrigin: 'top center',
69
+ backgroundImage: `
70
+ linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px),
71
+ linear-gradient(90deg, rgba(0,0,0,0.05) 1px, transparent 1px)
72
+ `,
73
+ backgroundSize: `${DEFAULT_DISPLAY_SIZE.gridSize}px ${DEFAULT_DISPLAY_SIZE.gridSize}px`,
74
+ }
75
+ }
76
+
55
77
  return {
56
- aspectRatio: displaySize.value?.aspectRatio,
57
- width: `${displaySize.value?.px}px`,
78
+ aspectRatio: displaySize.value.aspectRatio,
79
+ width: `${displaySize.value.px}px`,
58
80
  height: `${displayHeight.value}px`,
59
- margin: `0 auto`,
60
- transform: `scale(${displaySize.value?.percent / 100})`,
81
+ margin: '0 auto',
82
+ transform: `scale(${displaySize.value.percent / 100})`,
61
83
  transformOrigin: 'top center',
62
84
  backgroundImage: `
63
85
  linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px),
64
86
  linear-gradient(90deg, rgba(0,0,0,0.05) 1px, transparent 1px)
65
87
  `,
66
- backgroundSize: `${gridSize.value}px ${gridSize.value}px`,
88
+ backgroundSize: `${displaySize.value.gridSize}px ${displaySize.value.gridSize}px`,
67
89
  };
90
+
91
+
68
92
  });
69
93
 
70
94
  // 전체 elements
@@ -26,7 +26,7 @@
26
26
  min="1"
27
27
  max="50"
28
28
  :value="activeConfig.gridRows"
29
- @change="setSectionConfig('row', $event.target.value)"
29
+ @change="handleSectionConfigChange('row', $event.target.value)"
30
30
  />
31
31
  </div>
32
32
  <div class="flex flex-row items-center gap-4">
@@ -38,7 +38,7 @@
38
38
  min="1"
39
39
  max="12"
40
40
  :value="activeConfig.gridColumns"
41
- @change="setSectionConfig('column', $event.target.value)"
41
+ @change="handleSectionConfigChange('column', $event.target.value)"
42
42
  />
43
43
  </div>
44
44
  <div class="flex flex-row items-center gap-4">
@@ -50,7 +50,7 @@
50
50
  min="0"
51
51
  max="12"
52
52
  :value="activeConfig.gridGap"
53
- @change="setSectionConfig('gap', $event.target.value)"
53
+ @change="handleSectionConfigChange('gap', $event.target.value)"
54
54
  />
55
55
  </div>
56
56
  </div>
@@ -64,7 +64,7 @@
64
64
  type="checkbox"
65
65
  id="guide-line"
66
66
  :checked="activeConfig.showGuideLine"
67
- @change="setSectionConfig('guideLine', $event.target.checked)"
67
+ @change="handleSectionConfigChange('guideLine', $event.target.checked)"
68
68
  />
69
69
  </div>
70
70
  </div>
@@ -85,6 +85,14 @@ const { activeMode, activeConfig } = toRefs(props.polarvo.layout.state);
85
85
  const { setSectionMode, setSectionConfig } = props.polarvo.layout;
86
86
 
87
87
  const sectionMode = computed(() => activeMode.value);
88
+
89
+ function handleSectionConfigChange(type, value) {
90
+ const { result, message } = setSectionConfig(type, value)
91
+
92
+ if (!result) {
93
+ alert(message)
94
+ }
95
+ }
88
96
  </script>
89
97
 
90
98
  <style lang="scss" scoped></style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div>
3
- <div class="aspect-[3/2] border border-gray-200 rounded-md bg-white ">
3
+ <div class="aspect-[3/2] border border-gray-200 rounded-md bg-white">
4
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"
@@ -35,7 +35,7 @@
35
35
  type="number"
36
36
  :id="`col-ratio-${column}`"
37
37
  :value="gridRatio.column[column - 1]"
38
- @change="setRatio('column', column - 1, $event.target.value)"
38
+ @change="handleGridRatio('column', column - 1, $event)"
39
39
  />
40
40
  </template>
41
41
  </div>
@@ -48,7 +48,7 @@
48
48
  type="number"
49
49
  :id="`row-ratio-${row}`"
50
50
  :value="gridRatio.row[row - 1]"
51
- @change="setRatio('row', row - 1, $event.target.value)"
51
+ @change="handleGridRatio('row', row - 1, $event)"
52
52
  />
53
53
  </template>
54
54
  </div>
@@ -60,11 +60,7 @@
60
60
  현재 활성화 섹션:
61
61
  <span class="text-sm text-red-400 font-medium cursor-default">{{ activeSection }}</span>
62
62
  </h5>
63
- <LayoutSetting
64
- v-if="activeSection !== null"
65
- :polarvo="polarvo"
66
- class="mt-2 border border-gray-200 rounded-md bg-white"
67
- />
63
+ <LayoutSetting v-if="activeSection !== null" :polarvo="polarvo" class="mt-2 border border-gray-200 rounded-md bg-white" />
68
64
  <div v-else>
69
65
  <div class="text-center text-sm text-red-400 bg-red-50 mt-1 py-1 cursor-default">선택된 섹션이 없습니다.</div>
70
66
  </div>
@@ -86,4 +82,19 @@ const props = defineProps({
86
82
  });
87
83
  const { layoutName, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.polarvo.layout.state);
88
84
  const { setGapSize, setRatio, setActiveSection } = props.polarvo.layout;
85
+
86
+ function handleGridRatio(type, index, event) {
87
+ const value = event.target.value;
88
+ if (Number(value) > 100 || Number(value) < 0 || isNaN(Number(value))) {
89
+ alert('비율은 0에서 100 사이의 숫자여야 합니다.');
90
+ event.target.value = gridRatio.value[type][index]; // 원래 값으로 복원
91
+ return;
92
+ }
93
+
94
+ const { result, message } = setRatio(type, index, value)
95
+
96
+ if (!result) {
97
+ alert(message)
98
+ }
99
+ }
89
100
  </script>
@@ -1,4 +1,16 @@
1
1
  // event 발행 시 'display'으로 시작하는 이름 사용
2
+ const DISPLAY_LIMITS = {
3
+ percent: { max: 200, min: 0, unit: '%', name: '배율' },
4
+ px: { max: 1200, min: 1, unit: 'px', name: '크기' },
5
+ };
6
+
7
+ const DEFAULT_DISPLAY_SIZE = {
8
+ px: 1200,
9
+ percent: 100,
10
+ gridSize: 16,
11
+ aspectRatio: '16/9',
12
+ };
13
+
2
14
  class DisplayEngine {
3
15
  constructor({ eventBus, options }) {
4
16
  this.eventBus = eventBus;
@@ -9,6 +21,8 @@ class DisplayEngine {
9
21
  this.displayMode = 'desktop'; // 현재 디스플레이 모드 (초기값 = 'desktop')
10
22
  this.displaySize = null;
11
23
 
24
+ this._resetDisplaySizeByMode(this.displayMode);
25
+
12
26
  this._subscriptions = []; // 구독 해제 함수 저장용
13
27
  this._setupSubscriptions();
14
28
  }
@@ -29,8 +43,6 @@ class DisplayEngine {
29
43
  _setupSubscriptions() {
30
44
  // 초기화 완료 이벤트 구독 - from EngineManager
31
45
  this._subscribe('system:engineInitialized', () => {
32
- this._resetDisplaySizeByMode(this.displayMode);
33
-
34
46
  this.eventBus.emit('display:engineInitialized', {
35
47
  $displaySize: this.displaySize,
36
48
  timestamp: Date.now(),
@@ -71,8 +83,6 @@ class DisplayEngine {
71
83
  this.displayMode = 'desktop';
72
84
  this._resetDisplaySizeByMode(this.displayMode);
73
85
 
74
- console.log('[DisplayEngine] 리셋 완료');
75
-
76
86
  this.eventBus.emit('display:enginesReset', {
77
87
  $displaySize: this.displaySize,
78
88
  timestamp: Date.now(),
@@ -124,7 +134,6 @@ class DisplayEngine {
124
134
  }
125
135
 
126
136
  /** ---------------------------------- 공통 메소드 ---------------------------------- **/
127
-
128
137
  /** 아이콘바 메뉴 변경
129
138
  * @param {string} name - 메뉴 이름
130
139
  */
@@ -180,14 +189,19 @@ class DisplayEngine {
180
189
  * @param {string} mode - 디스플레이 모드
181
190
  */
182
191
  _resetDisplaySizeByMode(mode) {
183
- if (this.resource[mode]) {
184
- this.displaySize = {
185
- px: this.resource[mode]?.defaultWidth || 1200,
186
- percent: 100,
187
- gridSize: this.resource[mode]?.gridSize || 16,
188
- aspectRatio: this.resource[mode]?.aspectRatio || '16/9',
189
- };
192
+ const defaults = DEFAULT_DISPLAY_SIZE;
193
+ if (!this.resource[mode]) {
194
+ this.displaySize = { ...defaults };
195
+ return;
190
196
  }
197
+
198
+ const resource = this.resource[mode];
199
+ this.displaySize = {
200
+ px: resource.defaultWidth ?? defaults.px,
201
+ percent: defaults.percent,
202
+ gridSize: resource.gridSize ?? defaults.gridSize,
203
+ aspectRatio: resource.aspectRatio ?? defaults.aspectRatio,
204
+ };
191
205
  }
192
206
 
193
207
  /** displaySize 변경
@@ -196,29 +210,24 @@ class DisplayEngine {
196
210
  */
197
211
  setDisplaySize(type, size) {
198
212
  if (!['px', 'percent'].includes(type)) {
199
- console.error('[DisplayEngine] 잘못된 사이즈 타입:', type);
200
- return;
213
+ return { result: false, message: '입력할 없는 사이즈 타입입니다.' };
201
214
  }
202
-
203
215
  const numSize = Number(size);
204
- if (isNaN(numSize) || numSize <= 0) {
205
- console.error('[DisplayEngine] 잘못된 사이즈 값:', size);
206
- return;
207
- }
216
+ const limit = DISPLAY_LIMITS[type];
217
+ const result = {result: true, message: '사이즈가 성공적으로 변경되었습니다.'};
208
218
 
209
- const limits = {
210
- percent: { max: 200, unit: '%', name: '배율' },
211
- px: { max: 1200, unit: 'px', name: '크기' },
212
- };
219
+ if (isNaN(numSize) || numSize <= limit.min) {
220
+ result.result = false;
221
+ result.message = `설정 가능한 최소 ${limit.name}는 ${limit.min}${limit.unit}입니다.`;
222
+ }
213
223
 
214
- const typeLimit = limits[type];
215
- if (numSize > typeLimit.max) {
216
- alert(`설정 가능한 최대 ${typeLimit.name}는 ${typeLimit.max}${typeLimit.unit}입니다.`);
224
+ if (isNaN(numSize) || numSize > limit.max) {
225
+ result.result = false;
226
+ result.message = `설정 가능한 최대 ${limit.name}는 ${limit.max}${limit.unit}입니다.`;
217
227
  }
218
228
 
219
229
  const prevDisplaySize = { ...this.displaySize };
220
- this.displaySize[type] = Math.min(Math.max(0, numSize), typeLimit.max);
221
-
230
+ this.displaySize[type] = Math.min(Math.max(0, numSize), limit.max);
222
231
  this.eventBus.emit('display:displayChanged', {
223
232
  type: 'size',
224
233
  $displayMode: this.displayMode,
@@ -226,6 +235,8 @@ class DisplayEngine {
226
235
  prev: { displaySize: prevDisplaySize },
227
236
  timestamp: Date.now(),
228
237
  });
238
+
239
+ return result;
229
240
  }
230
241
  }
231
242
 
@@ -153,7 +153,6 @@ class FreeDropEngine {
153
153
  /** 엔진 초기화 */
154
154
  reset() {
155
155
  this._initialize();
156
- console.log('[FreeDropEngine] 리셋 완료');
157
156
  }
158
157
 
159
158
  /** 삭제 및 정리 */
@@ -123,7 +123,6 @@ class GridDropEngine {
123
123
  /** 엔진 초기화 */
124
124
  reset() {
125
125
  this._initialize();
126
- console.log('[GridDropEngine] 리셋 완료');
127
126
  }
128
127
 
129
128
  /** 삭제 및 정리 */
@@ -134,7 +134,6 @@ class HistoryEngine {
134
134
  /** 엔진 초기화 */
135
135
  reset() {
136
136
  this._initialize();
137
- console.log('[HistoryEngine] 리셋 완료');
138
137
  }
139
138
 
140
139
  /** 삭제 및 정리 */
@@ -32,7 +32,7 @@ class LayoutEngine {
32
32
  /** [내부함수] 구독 설정 */
33
33
  _setupSubscriptions() {
34
34
  // 초기화 완료 이벤트 구독 - from EngineManager
35
- this._subscribe('system:engineInitialized', () => {});
35
+ // this._subscribe('system:engineInitialized', () => {});
36
36
 
37
37
  this._subscribe('system:updateActiveSectionConfig', ({ $section, changes }) => {
38
38
  Object.keys(changes).forEach((key) => {
@@ -63,6 +63,7 @@ class LayoutEngine {
63
63
  });
64
64
 
65
65
  this._subscribe('system:restoredState', ({ stateData }) => {
66
+ if (!stateData?.layoutData) return;
66
67
  Object.assign(this.layoutData, stateData.layoutData);
67
68
  });
68
69
  }
@@ -209,27 +210,17 @@ class LayoutEngine {
209
210
 
210
211
  const newLayoutData = cloneDeep(this.resource[name].sections);
211
212
 
212
- // userData 있는 경우 우선 병합
213
- if (userData) {
214
- Object.keys(newLayoutData).forEach((sectionKey) => {
215
- if (userData[sectionKey]) {
216
- newLayoutData[sectionKey] = { ...newLayoutData[sectionKey], ...userData[sectionKey] };
217
- }
218
- });
219
- }
220
- // 기존 데이터 있는 경우 병합
221
- else if (this.layoutData) {
222
- {
223
- Object.keys(newLayoutData).forEach((sectionKey) => {
224
- if (this.layoutData[sectionKey]) {
225
- newLayoutData[sectionKey] = {
226
- ...newLayoutData[sectionKey],
227
- ...this.layoutData[sectionKey],
228
- };
229
- }
230
- });
213
+ // userData 있는 경우 우선 병합 - 기존 데이터 유지하면서 userData로 덮어쓰기
214
+ const mergeSource = userData || this.layoutData;
215
+
216
+ Object.keys(newLayoutData).forEach((sectionKey) => {
217
+ if (mergeSource[sectionKey]) {
218
+ newLayoutData[sectionKey] = {
219
+ ...newLayoutData[sectionKey],
220
+ ...mergeSource[sectionKey],
221
+ };
231
222
  }
232
- }
223
+ });
233
224
 
234
225
  this.layoutData = newLayoutData;
235
226
  }
@@ -248,18 +239,26 @@ class LayoutEngine {
248
239
  this.gridRatio.column = gridRatio.column;
249
240
  } else {
250
241
  this.gridRatio.column = columnNumber === 1 ? [100] : Array(columnNumber).fill(Math.floor(100 / columnNumber));
242
+
243
+ if (columnNumber === 3) {
244
+ this.gridRatio.column[2] = 100 - this.gridRatio.column[0] - this.gridRatio.column[1];
245
+ }
251
246
  }
252
247
 
253
248
  if (gridRatio?.row) {
254
249
  this.gridRatio.row = gridRatio.row;
255
250
  } else {
256
251
  this.gridRatio.row = rowNumber === 1 ? [100] : Array(rowNumber).fill(Math.floor(100 / rowNumber));
252
+
253
+ if (rowNumber === 3) {
254
+ this.gridRatio.row[2] = 100 - this.gridRatio.row[0] - this.gridRatio.row[1];
255
+ }
257
256
  }
258
257
 
259
258
  this.gridNumber.column = columnNumber;
260
259
  this.gridNumber.row = rowNumber;
261
260
 
262
- if (gapSize) {
261
+ if (gapSize != null) {
263
262
  this.gapSize = gapSize;
264
263
  }
265
264
  }
@@ -268,6 +267,8 @@ class LayoutEngine {
268
267
  * @param {number} size - 새로운 갭 사이즈
269
268
  */
270
269
  setGapSize(size) {
270
+ if (Number(size) < 0 || isNaN(Number(size))) return;
271
+
271
272
  this.gapSize = size;
272
273
 
273
274
  this.eventBus.emit('layout:updateGapSize', {
@@ -282,7 +283,7 @@ class LayoutEngine {
282
283
  * @param {number} ratio - 새로운 비율 값
283
284
  */
284
285
  setRatio(type, index, ratio) {
285
- const ratioArray = type === 'column' ? this.gridRatio.column : this.gridRatio.row;
286
+ const ratioArray = this.gridRatio[type];
286
287
  ratioArray[index] = Number(ratio);
287
288
 
288
289
  const totalWithout = ratioArray.reduce((sum, val, idx) => {
@@ -295,34 +296,42 @@ class LayoutEngine {
295
296
  }
296
297
 
297
298
  const total = totalWithout + ratioArray[index];
299
+ const result = { result: true, message: '비율이 성공적으로 변경되었습니다.' };
300
+
298
301
  if (total == 100) {
299
- return;
300
- } else {
301
- if (ratioArray.length == 2) {
302
- index == 0 ? (ratioArray[1] = 100 - ratioArray[0]) : (ratioArray[0] = 100 - ratioArray[1]);
303
- } else if (ratioArray.length == 3) {
304
- const remaining = 100 - total;
305
- if (remaining < 0) {
306
- alert('비율의 합은 100을 초과할 수 없습니다.');
307
- }
302
+ return result;
303
+ }
308
304
 
309
- if (index == 2) {
310
- ratioArray[0] = remaining < 0 ? ratioArray[0] + remaining : ratioArray[0] - remaining;
311
- } else {
312
- ratioArray[index + 1] = remaining < 0 ? ratioArray[index + 1] + remaining : ratioArray[index + 1] - remaining;
305
+ if (ratioArray.length == 2) {
306
+ index == 0 ? (ratioArray[1] = 100 - ratioArray[0]) : (ratioArray[0] = 100 - ratioArray[1]);
307
+ } else if (ratioArray.length == 3) {
308
+ const remaining = 100 - total;
309
+ if (remaining < 0) {
310
+ result.result = false;
311
+ result.message = '비율의 합은 100을 초과할 수 없습니다.';
312
+ }
313
+
314
+ if (index == 2) {
315
+ ratioArray[0] = ratioArray[0] - Math.abs(remaining);
316
+ } else {
317
+ ratioArray[index + 1] = ratioArray[index + 1] - Math.abs(remaining);
318
+
319
+ if (ratioArray[index + 1] < 0) {
320
+ ratioArray[index + 1] = 0;
321
+ ratioArray[2] = 100 - ratioArray[0] - ratioArray[1];
313
322
  }
314
323
  }
315
324
  }
316
- if (type === 'column') {
317
- this.gridRatio.column = ratioArray;
318
- } else if (type === 'row') {
319
- this.gridRatio.row = ratioArray;
320
- }
325
+
326
+ this.gridRatio[type] = ratioArray;
321
327
 
322
328
  this.eventBus.emit('layout:updateRatio', {
329
+ $type: type,
323
330
  $gridRatio: this.gridRatio,
324
331
  timestamp: Date.now(),
325
332
  });
333
+
334
+ return result;
326
335
  }
327
336
  }
328
337
 
@@ -9,6 +9,11 @@ const { dataConverter, calculateAspectRatio } = utils;
9
9
  import createDefaultConfig from '../../configs/index.js';
10
10
  const { initialState, resource } = createDefaultConfig();
11
11
 
12
+ const CONFIG_LIMITS = {
13
+ column: { min: 1, max: 12, name: '열 개수' },
14
+ row: { min: 1, max: 50, name: '행 개수' },
15
+ gap: { min: 0, max: 12, name: '갭 크기' },
16
+ };
12
17
  // event 발행 시 'system'으로 시작하는 이름 사용
13
18
  class EngineManager {
14
19
  constructor(config = {}) {
@@ -241,7 +246,7 @@ class EngineManager {
241
246
  if (!this.activeData || this.activeData.mode === mode) return;
242
247
  const updates = {
243
248
  mode: mode,
244
- elementIds: this.state.elements.filter((x) => x.mode === mode).map((x) => x.id),
249
+ elementIds: this.state.elements.filter((x) => x.section === this.state.activeSection && x.mode === mode).map((x) => x.id),
245
250
  };
246
251
 
247
252
  if (mode === 'grid') {
@@ -267,17 +272,18 @@ class EngineManager {
267
272
  */
268
273
  setSectionConfig(type, config) {
269
274
  if (!['column', 'row', 'gap', 'guideLine'].includes(type)) {
270
- console.error('[EngineManager] 잘못된 config 타입:', type);
271
- return;
275
+ return { result: false, message: '입력할 없는 config 타입입니다.' };
272
276
  }
273
277
 
274
278
  if (!this.activeData) return;
275
279
 
276
- const limits = {
277
- column: { min: 1, max: 12, name: ' 개수' },
278
- row: { min: 1, max: 50, name: '행 개수' },
279
- gap: { min: 0, max: 12, name: ' 크기' },
280
- };
280
+ const limit = CONFIG_LIMITS[type];
281
+ const result = { result: true, message: 'config가 성공적으로 변경되었습니다.' };
282
+ // const limits = {
283
+ // column: { min: 1, max: 12, name: ' 개수' },
284
+ // row: { min: 1, max: 50, name: '행 개수' },
285
+ // gap: { min: 0, max: 12, name: '갭 크기' },
286
+ // };
281
287
 
282
288
  let newConfig = {};
283
289
  let value = config;
@@ -285,13 +291,15 @@ class EngineManager {
285
291
  if (type === 'guideLine') {
286
292
  newConfig = { showGuideLine: value };
287
293
  } else {
288
- if (value < limits[type].min) {
289
- alert(`설정 가능한 최소 ${limits[type].name}는 ${limits[type].min}입니다.`);
294
+ if (value < limit.min) {
295
+ result.result = false;
296
+ result.message = `설정 가능한 최소 ${limit.name}는 ${limit.min}입니다.`;
290
297
  }
291
- if (value > limits[type].max) {
292
- alert(`설정 가능한 최대 ${limits[type].name}는 ${limits[type].max}입니다.`);
298
+ if (value > limit.max) {
299
+ result.result = false;
300
+ result.message = `설정 가능한 최대 ${limit.name}는 ${limit.max}입니다.`;
293
301
  }
294
- value = Math.min(Math.max(limits[type].min, value), limits[type].max);
302
+ value = Math.min(Math.max(limit.min, value), limit.max);
295
303
 
296
304
  if (type === 'column') {
297
305
  newConfig = { gridColumns: value };
@@ -304,6 +312,8 @@ class EngineManager {
304
312
 
305
313
  const updates = { config: { ...this.activeData.config, ...newConfig } };
306
314
  this._updateActiveSectionConfig('config', updates);
315
+
316
+ return result;
307
317
  }
308
318
 
309
319
  /** ---------------------------------- freeDrop Engine ---------------------------------- **/
@@ -115,9 +115,9 @@ function useDisplay(api) {
115
115
 
116
116
  const setDisplaySize = (type, size) => {
117
117
  try {
118
- api.display.setDisplaySize(type, size);
118
+ return api.display.setDisplaySize(type, size);
119
119
  } catch (error) {
120
- console.error('[useDisplay] setDisplaySize 실행 중 오류 발생:', error);
120
+ console.error('[DisplayLibrary] setDisplaySize 실행 중 오류 발생:', error);
121
121
  }
122
122
  };
123
123
 
@@ -65,7 +65,7 @@ function useLayout(api) {
65
65
  state.layoutData = $layoutData;
66
66
  state.gridNumber = $gridNumber;
67
67
  state.gridRatio = $gridRatio;
68
- if ($gapSize) {
68
+ if ($gapSize != null) {
69
69
  state.gapSize = $gapSize;
70
70
  }
71
71
  });
@@ -76,8 +76,8 @@ function useLayout(api) {
76
76
  });
77
77
 
78
78
  // gridRatio 변경 감지
79
- _subscribe('layout:updateRatio', ({ $gridRatio }) => {
80
- state.gridRatio = $gridRatio;
79
+ _subscribe('layout:updateRatio', ({ $type, $gridRatio }) => {
80
+ state.gridRatio[$type] = [...$gridRatio[$type]];
81
81
  });
82
82
 
83
83
  // activeSection 변경 감지 (activeData가 함께 초기화됨)
@@ -118,9 +118,6 @@ function useLayout(api) {
118
118
  state.elements = stateData.elements;
119
119
  state.layoutData = stateData.layoutData;
120
120
  state.activeSection = stateData.activeSection;
121
-
122
- // state.layoutData = cloneDeep(api.layout.getLayoutData());
123
- // state.activeData = cloneDeep(api.layout.getActiveData());
124
121
  });
125
122
 
126
123
  _subscribe('layout:restoredState', ({ stateData }) => {
@@ -188,20 +185,12 @@ function useLayout(api) {
188
185
 
189
186
  const setRatio = (type, index, ratio) => {
190
187
  try {
191
- api.layout.setRatio(type, index, ratio);
188
+ return api.layout.setRatio(type, index, ratio);
192
189
  } catch (error) {
193
190
  console.error('[useLayout] setRatio 실행 중 오류 발생:', error);
194
191
  }
195
192
  };
196
193
 
197
- // const setUserLayoutData = (userData) => {
198
- // try {
199
- // api.layout.setUserLayoutData(userData);
200
- // } catch (error) {
201
- // console.error('[useLayout] setUserLayoutData 실행 중 오류 발생:', error);
202
- // }
203
- // };
204
-
205
194
  const setActiveSection = (name) => {
206
195
  try {
207
196
  api.layout.setActiveSection(name);
@@ -236,7 +225,7 @@ function useLayout(api) {
236
225
 
237
226
  const setSectionConfig = (type, config) => {
238
227
  try {
239
- api.layout.setSectionConfig(type, config);
228
+ return api.layout.setSectionConfig(type, config);
240
229
  } catch (error) {
241
230
  console.error('[useLayout] setSectionConfig 실행 중 오류 발생:', error);
242
231
  }
@@ -250,7 +239,6 @@ function useLayout(api) {
250
239
  setLayoutName,
251
240
  setGapSize,
252
241
  setRatio,
253
- // setUserLayoutData,
254
242
  setActiveSection,
255
243
  setElements,
256
244
  updateActiveElement,