@mint-ui/map 1.2.0-test.39 → 1.2.0-test.40

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.
@@ -33,9 +33,26 @@ export interface CanvasOption {
33
33
  /**
34
34
  * 서버 데이터와 캔버스 옵션을 결합한 타입
35
35
  *
36
+ * 서버 데이터의 필드가 CanvasOption과 충돌하는 경우, CanvasOption의 필드가 우선됩니다.
37
+ *
36
38
  * @template T 서버에서 받은 원본 데이터 타입
39
+ *
40
+ * @example
41
+ * // 서버 데이터에 id가 number 타입인 경우
42
+ * interface ServerData {
43
+ * id: number;
44
+ * name: string;
45
+ * }
46
+ *
47
+ * // CanvasData<ServerData>는 다음과 같이 됩니다:
48
+ * // {
49
+ * // id: string; // CanvasOption의 id가 우선
50
+ * // name: string; // 서버 데이터의 name
51
+ * // position: Position;
52
+ * // ...CanvasOption의 다른 필드들
53
+ * // }
37
54
  */
38
- export declare type CanvasData<T = {}> = T & CanvasOption;
55
+ export declare type CanvasData<T = {}> = Omit<T, keyof CanvasOption> & CanvasOption;
39
56
  /**
40
57
  * 렌더링 유틸리티 함수들 (좌표 변환)
41
58
  *
@@ -21,6 +21,8 @@ export interface WoongCanvasMarkerProps<T> extends Pick<MarkerOptions, 'zIndex'
21
21
  enableMultiSelect?: boolean;
22
22
  /** hover 시 마커를 최상단으로 표시할지 여부 (기본값: false) */
23
23
  topOnHover?: boolean;
24
+ /** 뷰포트 컬링 활성화 여부 (기본값: false) */
25
+ enableViewportCulling?: boolean;
24
26
  /** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
25
27
  cullingMargin?: number;
26
28
  /** LRU 캐시 최대 크기 (기본값: 10000) */
@@ -32,17 +32,19 @@ var WoongCanvasMarker = function (props) {
32
32
  enableMultiSelect = _a === void 0 ? false : _a,
33
33
  _b = props.topOnHover,
34
34
  topOnHover = _b === void 0 ? false : _b,
35
- _c = props.cullingMargin,
36
- cullingMargin = _c === void 0 ? performance.DEFAULT_CULLING_MARGIN : _c,
37
- _d = props.maxCacheSize,
38
- maxCacheSize = _d === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _d,
35
+ _c = props.enableViewportCulling,
36
+ enableViewportCulling = _c === void 0 ? false : _c,
37
+ _d = props.cullingMargin,
38
+ cullingMargin = _d === void 0 ? performance.DEFAULT_CULLING_MARGIN : _d,
39
+ _e = props.maxCacheSize,
40
+ maxCacheSize = _e === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _e,
39
41
  externalSelectedItems = props.selectedItems,
40
42
  externalSelectedItem = props.selectedItem,
41
- _e = props.disableInteraction,
42
- disableInteraction = _e === void 0 ? false : _e,
43
+ _f = props.disableInteraction,
44
+ disableInteraction = _f === void 0 ? false : _f,
43
45
  renderBase = props.renderBase,
44
46
  renderEvent = props.renderEvent,
45
- options = tslib.__rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
47
+ options = tslib.__rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
46
48
 
47
49
  var controller = MintMapProvider.useMintMapController();
48
50
  var context$1 = context.useWoongCanvasContext();
@@ -59,6 +61,7 @@ var WoongCanvasMarker = function (props) {
59
61
 
60
62
  var dataRef = React.useRef(data);
61
63
  var disableInteractionRef = React.useRef(disableInteraction);
64
+ var enableViewportCullingRef = React.useRef(enableViewportCulling);
62
65
  var hoveredItemRef = React.useRef(null);
63
66
  var selectedItemRef = React.useRef(externalSelectedItem);
64
67
  var selectedIdsRef = React.useRef(new Set());
@@ -138,9 +141,9 @@ var WoongCanvasMarker = function (props) {
138
141
  var ctx = context;
139
142
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
140
143
 
141
- var visibleItems = dataRef.current.filter(function (item) {
144
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
142
145
  return isInViewport(item);
143
- }); // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
146
+ }) : dataRef.current; // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
144
147
 
145
148
  if (topOnHover && !renderEvent && hovered) {
146
149
  visibleItems = visibleItems.filter(function (item) {
@@ -158,7 +161,7 @@ var WoongCanvasMarker = function (props) {
158
161
  }); // hover된 항목을 마지막에 렌더링하여 최상위에 표시
159
162
 
160
163
  if (topOnHover && !renderEvent && hovered) {
161
- if (isInViewport(hovered)) {
164
+ if (!enableViewportCullingRef.current || isInViewport(hovered)) {
162
165
  renderBase({
163
166
  ctx: ctx,
164
167
  items: [hovered],
@@ -204,7 +207,7 @@ var WoongCanvasMarker = function (props) {
204
207
  selectedItem: selectedItemRef.current
205
208
  });
206
209
 
207
- if (isInViewport(hovered)) {
210
+ if (!enableViewportCullingRef.current || isInViewport(hovered)) {
208
211
  var hoveredIsSelected = selectedItems.some(function (item) {
209
212
  return item.id === hovered.id;
210
213
  });
@@ -239,14 +242,17 @@ var WoongCanvasMarker = function (props) {
239
242
 
240
243
 
241
244
  var renderAllImmediate = function () {
242
- updateViewport();
245
+ if (enableViewportCullingRef.current) {
246
+ updateViewport();
247
+ }
248
+
243
249
  buildSpatialIndex();
244
250
  doRenderBase();
245
251
  doRenderEvent();
246
252
  }; // 지도 이벤트 핸들러 생성
247
253
 
248
254
 
249
- var _f = hooks.createMapEventHandlers({
255
+ var _g = hooks.createMapEventHandlers({
250
256
  controller: controller,
251
257
  containerRef: containerRef,
252
258
  markerRef: markerRef,
@@ -257,12 +263,12 @@ var WoongCanvasMarker = function (props) {
257
263
  boundingBoxCacheRef: boundingBoxCacheRef,
258
264
  renderAllImmediate: renderAllImmediate
259
265
  }),
260
- handleIdle = _f.handleIdle,
261
- handleZoomStart = _f.handleZoomStart,
262
- handleZoomEnd = _f.handleZoomEnd,
263
- handleCenterChanged = _f.handleCenterChanged,
264
- handleDragStartShared = _f.handleDragStart,
265
- handleDragEndShared = _f.handleDragEnd;
266
+ handleIdle = _g.handleIdle,
267
+ handleZoomStart = _g.handleZoomStart,
268
+ handleZoomEnd = _g.handleZoomEnd,
269
+ handleCenterChanged = _g.handleCenterChanged,
270
+ handleDragStartShared = _g.handleDragStart,
271
+ handleDragEndShared = _g.handleDragEnd;
266
272
 
267
273
  var handleDragStart = function () {
268
274
  handleDragStartShared();
@@ -439,7 +445,11 @@ var WoongCanvasMarker = function (props) {
439
445
  eventLayerRef.current = eventLayer;
440
446
  stage.add(baseLayer);
441
447
  stage.add(eventLayer);
442
- updateViewport(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
448
+
449
+ if (enableViewportCulling) {
450
+ updateViewport();
451
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
452
+
443
453
 
444
454
  var resizeRafId = null;
445
455
  var resizeObserver = new ResizeObserver(function () {
@@ -452,7 +462,11 @@ var WoongCanvasMarker = function (props) {
452
462
  stage.height(mapDiv.offsetHeight);
453
463
  offsetCacheRef.current.clear();
454
464
  boundingBoxCacheRef.current.clear();
455
- updateViewport();
465
+
466
+ if (enableViewportCullingRef.current) {
467
+ updateViewport();
468
+ }
469
+
456
470
  renderAllImmediate();
457
471
  resizeRafId = null;
458
472
  });
@@ -524,7 +538,36 @@ var WoongCanvasMarker = function (props) {
524
538
 
525
539
  React.useEffect(function () {
526
540
  disableInteractionRef.current = disableInteraction;
527
- }, [disableInteraction]); // 외부 selectedItems 동기화
541
+ }, [disableInteraction]); // enableViewportCulling 동기화
542
+
543
+ React.useEffect(function () {
544
+ enableViewportCullingRef.current = enableViewportCulling;
545
+
546
+ if (stageRef.current) {
547
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
548
+ var baseLayer = baseLayerRef.current;
549
+
550
+ if (baseLayer) {
551
+ var shape = baseLayer.findOne('.base-render-shape');
552
+
553
+ if (shape) {
554
+ shape.destroy();
555
+ }
556
+ }
557
+
558
+ var eventLayer = eventLayerRef.current;
559
+
560
+ if (eventLayer) {
561
+ var shape = eventLayer.findOne('.event-render-shape');
562
+
563
+ if (shape) {
564
+ shape.destroy();
565
+ }
566
+ }
567
+
568
+ renderAllImmediate();
569
+ }
570
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
528
571
 
529
572
  React.useEffect(function () {
530
573
  if (!stageRef.current) return;
@@ -15,6 +15,8 @@ export interface WoongCanvasPolygonProps<T> extends Pick<MarkerOptions, 'zIndex'
15
15
  onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
16
16
  /** 다중 선택 활성화 여부 (기본값: false) */
17
17
  enableMultiSelect?: boolean;
18
+ /** 뷰포트 컬링 활성화 여부 (기본값: false) */
19
+ enableViewportCulling?: boolean;
18
20
  /** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
19
21
  cullingMargin?: number;
20
22
  /** LRU 캐시 최대 크기 (기본값: 10000) */
@@ -29,14 +29,16 @@ var WoongCanvasPolygon = function (props) {
29
29
  onClick = props.onClick,
30
30
  _a = props.enableMultiSelect,
31
31
  enableMultiSelect = _a === void 0 ? false : _a,
32
- _b = props.cullingMargin,
33
- cullingMargin = _b === void 0 ? performance.DEFAULT_CULLING_MARGIN : _b,
34
- _c = props.maxCacheSize,
35
- maxCacheSize = _c === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _c,
32
+ _b = props.enableViewportCulling,
33
+ enableViewportCulling = _b === void 0 ? false : _b,
34
+ _c = props.cullingMargin,
35
+ cullingMargin = _c === void 0 ? performance.DEFAULT_CULLING_MARGIN : _c,
36
+ _d = props.maxCacheSize,
37
+ maxCacheSize = _d === void 0 ? performance.DEFAULT_MAX_CACHE_SIZE : _d,
36
38
  externalSelectedItems = props.selectedItems,
37
39
  externalSelectedItem = props.selectedItem,
38
- _d = props.disableInteraction,
39
- disableInteraction = _d === void 0 ? false : _d,
40
+ _e = props.disableInteraction,
41
+ disableInteraction = _e === void 0 ? false : _e,
40
42
  baseFillColor = props.baseFillColor,
41
43
  baseStrokeColor = props.baseStrokeColor,
42
44
  baseLineWidth = props.baseLineWidth,
@@ -49,7 +51,7 @@ var WoongCanvasPolygon = function (props) {
49
51
  hoveredFillColor = props.hoveredFillColor,
50
52
  hoveredStrokeColor = props.hoveredStrokeColor,
51
53
  hoveredLineWidth = props.hoveredLineWidth,
52
- options = tslib.__rest(props, ["data", "onClick", "enableMultiSelect", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
54
+ options = tslib.__rest(props, ["data", "onClick", "enableMultiSelect", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
53
55
  // Hooks & Context
54
56
  // --------------------------------------------------------------------------
55
57
 
@@ -69,6 +71,7 @@ var WoongCanvasPolygon = function (props) {
69
71
 
70
72
  var dataRef = React.useRef(data);
71
73
  var disableInteractionRef = React.useRef(disableInteraction);
74
+ var enableViewportCullingRef = React.useRef(enableViewportCulling);
72
75
  var hoveredItemRef = React.useRef(null);
73
76
  var selectedItemRef = React.useRef(externalSelectedItem);
74
77
  var selectedIdsRef = React.useRef(new Set());
@@ -169,9 +172,9 @@ var WoongCanvasPolygon = function (props) {
169
172
  var ctx = context;
170
173
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
171
174
 
172
- var visibleItems = dataRef.current.filter(function (item) {
175
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
173
176
  return isInViewport(item);
174
- });
177
+ }) : dataRef.current;
175
178
  renderBase({
176
179
  ctx: ctx,
177
180
  items: visibleItems,
@@ -223,14 +226,17 @@ var WoongCanvasPolygon = function (props) {
223
226
 
224
227
 
225
228
  var renderAllImmediate = function () {
226
- updateViewport();
229
+ if (enableViewportCullingRef.current) {
230
+ updateViewport();
231
+ }
232
+
227
233
  buildSpatialIndex();
228
234
  doRenderBase();
229
235
  doRenderEvent();
230
236
  }; // 지도 이벤트 핸들러 생성
231
237
 
232
238
 
233
- var _e = hooks.createMapEventHandlers({
239
+ var _f = hooks.createMapEventHandlers({
234
240
  controller: controller,
235
241
  containerRef: containerRef,
236
242
  markerRef: markerRef,
@@ -241,12 +247,12 @@ var WoongCanvasPolygon = function (props) {
241
247
  boundingBoxCacheRef: boundingBoxCacheRef,
242
248
  renderAllImmediate: renderAllImmediate
243
249
  }),
244
- handleIdle = _e.handleIdle,
245
- handleZoomStart = _e.handleZoomStart,
246
- handleZoomEnd = _e.handleZoomEnd,
247
- handleCenterChanged = _e.handleCenterChanged,
248
- handleDragStartShared = _e.handleDragStart,
249
- handleDragEndShared = _e.handleDragEnd;
250
+ handleIdle = _f.handleIdle,
251
+ handleZoomStart = _f.handleZoomStart,
252
+ handleZoomEnd = _f.handleZoomEnd,
253
+ handleCenterChanged = _f.handleCenterChanged,
254
+ handleDragStartShared = _f.handleDragStart,
255
+ handleDragEndShared = _f.handleDragEnd;
250
256
 
251
257
  var handleDragStart = function () {
252
258
  handleDragStartShared();
@@ -407,7 +413,11 @@ var WoongCanvasPolygon = function (props) {
407
413
  eventLayerRef.current = eventLayer;
408
414
  stage.add(baseLayer);
409
415
  stage.add(eventLayer);
410
- updateViewport(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
416
+
417
+ if (enableViewportCulling) {
418
+ updateViewport();
419
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
420
+
411
421
 
412
422
  var resizeRafId = null;
413
423
  var resizeObserver = new ResizeObserver(function () {
@@ -420,7 +430,11 @@ var WoongCanvasPolygon = function (props) {
420
430
  stage.height(mapDiv.offsetHeight);
421
431
  offsetCacheRef.current.clear();
422
432
  boundingBoxCacheRef.current.clear();
423
- updateViewport();
433
+
434
+ if (enableViewportCullingRef.current) {
435
+ updateViewport();
436
+ }
437
+
424
438
  renderAllImmediate();
425
439
  resizeRafId = null;
426
440
  });
@@ -490,7 +504,36 @@ var WoongCanvasPolygon = function (props) {
490
504
 
491
505
  React.useEffect(function () {
492
506
  disableInteractionRef.current = disableInteraction;
493
- }, [disableInteraction]); // 외부 selectedItems 동기화
507
+ }, [disableInteraction]); // enableViewportCulling 동기화
508
+
509
+ React.useEffect(function () {
510
+ enableViewportCullingRef.current = enableViewportCulling;
511
+
512
+ if (stageRef.current) {
513
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
514
+ var baseLayer = baseLayerRef.current;
515
+
516
+ if (baseLayer) {
517
+ var shape = baseLayer.findOne('.base-render-shape');
518
+
519
+ if (shape) {
520
+ shape.destroy();
521
+ }
522
+ }
523
+
524
+ var eventLayer = eventLayerRef.current;
525
+
526
+ if (eventLayer) {
527
+ var shape = eventLayer.findOne('.event-render-shape');
528
+
529
+ if (shape) {
530
+ shape.destroy();
531
+ }
532
+ }
533
+
534
+ renderAllImmediate();
535
+ }
536
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
494
537
 
495
538
  React.useEffect(function () {
496
539
  if (!stageRef.current) return;
@@ -4,7 +4,7 @@
4
4
  * 이 파일은 폴리곤 렌더링을 위한 헬퍼 함수와 팩토리 함수를 제공합니다.
5
5
  * GeoJSON MultiPolygon 형식을 지원하며, 도넛 폴리곤(구멍이 있는 폴리곤)도 처리할 수 있습니다.
6
6
  */
7
- import { CustomRenderBase, CustomRenderEvent, CanvasData } from "../shared/types";
7
+ import { CustomRenderBase, CustomRenderEvent } from "../shared/types";
8
8
  /**
9
9
  * 폴리곤 그리기 파라미터 인터페이스
10
10
  */
@@ -76,7 +76,7 @@ export declare const drawPolygon: ({ ctx, polygonOffsets, isDonutPolygon, fillCo
76
76
  * );
77
77
  * ```
78
78
  */
79
- export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number) => CustomRenderBase<CanvasData<T>>;
79
+ export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number) => CustomRenderBase<T>;
80
80
  /**
81
81
  * 폴리곤 Event 렌더링 함수 팩토리
82
82
  *
@@ -116,5 +116,5 @@ export declare const renderPolygonBase: <T = any>(baseFillColor: string, baseStr
116
116
  * );
117
117
  * ```
118
118
  */
119
- export declare const renderPolygonEvent: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number, selectedFillColor?: string, selectedStrokeColor?: string, selectedLineWidth?: number, activeFillColor?: string, activeStrokeColor?: string, activeLineWidth?: number, hoveredFillColor?: string, hoveredStrokeColor?: string, hoveredLineWidth?: number) => CustomRenderEvent<CanvasData<T>>;
119
+ export declare const renderPolygonEvent: <T = any>(baseFillColor: string, baseStrokeColor: string, baseLineWidth: number, selectedFillColor?: string, selectedStrokeColor?: string, selectedLineWidth?: number, activeFillColor?: string, activeStrokeColor?: string, activeLineWidth?: number, hoveredFillColor?: string, hoveredStrokeColor?: string, hoveredLineWidth?: number) => CustomRenderEvent<T>;
120
120
  export {};
package/dist/index.es.js CHANGED
@@ -5593,17 +5593,19 @@ var WoongCanvasMarker = function (props) {
5593
5593
  enableMultiSelect = _a === void 0 ? false : _a,
5594
5594
  _b = props.topOnHover,
5595
5595
  topOnHover = _b === void 0 ? false : _b,
5596
- _c = props.cullingMargin,
5597
- cullingMargin = _c === void 0 ? DEFAULT_CULLING_MARGIN : _c,
5598
- _d = props.maxCacheSize,
5599
- maxCacheSize = _d === void 0 ? DEFAULT_MAX_CACHE_SIZE : _d,
5596
+ _c = props.enableViewportCulling,
5597
+ enableViewportCulling = _c === void 0 ? false : _c,
5598
+ _d = props.cullingMargin,
5599
+ cullingMargin = _d === void 0 ? DEFAULT_CULLING_MARGIN : _d,
5600
+ _e = props.maxCacheSize,
5601
+ maxCacheSize = _e === void 0 ? DEFAULT_MAX_CACHE_SIZE : _e,
5600
5602
  externalSelectedItems = props.selectedItems,
5601
5603
  externalSelectedItem = props.selectedItem,
5602
- _e = props.disableInteraction,
5603
- disableInteraction = _e === void 0 ? false : _e,
5604
+ _f = props.disableInteraction,
5605
+ disableInteraction = _f === void 0 ? false : _f,
5604
5606
  renderBase = props.renderBase,
5605
5607
  renderEvent = props.renderEvent,
5606
- options = __rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
5608
+ options = __rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
5607
5609
 
5608
5610
  var controller = useMintMapController();
5609
5611
  var context = useWoongCanvasContext();
@@ -5620,6 +5622,7 @@ var WoongCanvasMarker = function (props) {
5620
5622
 
5621
5623
  var dataRef = useRef(data);
5622
5624
  var disableInteractionRef = useRef(disableInteraction);
5625
+ var enableViewportCullingRef = useRef(enableViewportCulling);
5623
5626
  var hoveredItemRef = useRef(null);
5624
5627
  var selectedItemRef = useRef(externalSelectedItem);
5625
5628
  var selectedIdsRef = useRef(new Set());
@@ -5699,9 +5702,9 @@ var WoongCanvasMarker = function (props) {
5699
5702
  var ctx = context;
5700
5703
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
5701
5704
 
5702
- var visibleItems = dataRef.current.filter(function (item) {
5705
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
5703
5706
  return isInViewport$1(item);
5704
- }); // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
5707
+ }) : dataRef.current; // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
5705
5708
 
5706
5709
  if (topOnHover && !renderEvent && hovered) {
5707
5710
  visibleItems = visibleItems.filter(function (item) {
@@ -5719,7 +5722,7 @@ var WoongCanvasMarker = function (props) {
5719
5722
  }); // hover된 항목을 마지막에 렌더링하여 최상위에 표시
5720
5723
 
5721
5724
  if (topOnHover && !renderEvent && hovered) {
5722
- if (isInViewport$1(hovered)) {
5725
+ if (!enableViewportCullingRef.current || isInViewport$1(hovered)) {
5723
5726
  renderBase({
5724
5727
  ctx: ctx,
5725
5728
  items: [hovered],
@@ -5765,7 +5768,7 @@ var WoongCanvasMarker = function (props) {
5765
5768
  selectedItem: selectedItemRef.current
5766
5769
  });
5767
5770
 
5768
- if (isInViewport$1(hovered)) {
5771
+ if (!enableViewportCullingRef.current || isInViewport$1(hovered)) {
5769
5772
  var hoveredIsSelected = selectedItems.some(function (item) {
5770
5773
  return item.id === hovered.id;
5771
5774
  });
@@ -5800,14 +5803,17 @@ var WoongCanvasMarker = function (props) {
5800
5803
 
5801
5804
 
5802
5805
  var renderAllImmediate = function () {
5803
- updateViewport$1();
5806
+ if (enableViewportCullingRef.current) {
5807
+ updateViewport$1();
5808
+ }
5809
+
5804
5810
  buildSpatialIndex$1();
5805
5811
  doRenderBase();
5806
5812
  doRenderEvent();
5807
5813
  }; // 지도 이벤트 핸들러 생성
5808
5814
 
5809
5815
 
5810
- var _f = createMapEventHandlers({
5816
+ var _g = createMapEventHandlers({
5811
5817
  controller: controller,
5812
5818
  containerRef: containerRef,
5813
5819
  markerRef: markerRef,
@@ -5818,12 +5824,12 @@ var WoongCanvasMarker = function (props) {
5818
5824
  boundingBoxCacheRef: boundingBoxCacheRef,
5819
5825
  renderAllImmediate: renderAllImmediate
5820
5826
  }),
5821
- handleIdle = _f.handleIdle,
5822
- handleZoomStart = _f.handleZoomStart,
5823
- handleZoomEnd = _f.handleZoomEnd,
5824
- handleCenterChanged = _f.handleCenterChanged,
5825
- handleDragStartShared = _f.handleDragStart,
5826
- handleDragEndShared = _f.handleDragEnd;
5827
+ handleIdle = _g.handleIdle,
5828
+ handleZoomStart = _g.handleZoomStart,
5829
+ handleZoomEnd = _g.handleZoomEnd,
5830
+ handleCenterChanged = _g.handleCenterChanged,
5831
+ handleDragStartShared = _g.handleDragStart,
5832
+ handleDragEndShared = _g.handleDragEnd;
5827
5833
 
5828
5834
  var handleDragStart = function () {
5829
5835
  handleDragStartShared();
@@ -6000,7 +6006,11 @@ var WoongCanvasMarker = function (props) {
6000
6006
  eventLayerRef.current = eventLayer;
6001
6007
  stage.add(baseLayer);
6002
6008
  stage.add(eventLayer);
6003
- updateViewport$1(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6009
+
6010
+ if (enableViewportCulling) {
6011
+ updateViewport$1();
6012
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6013
+
6004
6014
 
6005
6015
  var resizeRafId = null;
6006
6016
  var resizeObserver = new ResizeObserver(function () {
@@ -6013,7 +6023,11 @@ var WoongCanvasMarker = function (props) {
6013
6023
  stage.height(mapDiv.offsetHeight);
6014
6024
  offsetCacheRef.current.clear();
6015
6025
  boundingBoxCacheRef.current.clear();
6016
- updateViewport$1();
6026
+
6027
+ if (enableViewportCullingRef.current) {
6028
+ updateViewport$1();
6029
+ }
6030
+
6017
6031
  renderAllImmediate();
6018
6032
  resizeRafId = null;
6019
6033
  });
@@ -6085,7 +6099,36 @@ var WoongCanvasMarker = function (props) {
6085
6099
 
6086
6100
  useEffect(function () {
6087
6101
  disableInteractionRef.current = disableInteraction;
6088
- }, [disableInteraction]); // 외부 selectedItems 동기화
6102
+ }, [disableInteraction]); // enableViewportCulling 동기화
6103
+
6104
+ useEffect(function () {
6105
+ enableViewportCullingRef.current = enableViewportCulling;
6106
+
6107
+ if (stageRef.current) {
6108
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
6109
+ var baseLayer = baseLayerRef.current;
6110
+
6111
+ if (baseLayer) {
6112
+ var shape = baseLayer.findOne('.base-render-shape');
6113
+
6114
+ if (shape) {
6115
+ shape.destroy();
6116
+ }
6117
+ }
6118
+
6119
+ var eventLayer = eventLayerRef.current;
6120
+
6121
+ if (eventLayer) {
6122
+ var shape = eventLayer.findOne('.event-render-shape');
6123
+
6124
+ if (shape) {
6125
+ shape.destroy();
6126
+ }
6127
+ }
6128
+
6129
+ renderAllImmediate();
6130
+ }
6131
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
6089
6132
 
6090
6133
  useEffect(function () {
6091
6134
  if (!stageRef.current) return;
@@ -6421,14 +6464,16 @@ var WoongCanvasPolygon = function (props) {
6421
6464
  onClick = props.onClick,
6422
6465
  _a = props.enableMultiSelect,
6423
6466
  enableMultiSelect = _a === void 0 ? false : _a,
6424
- _b = props.cullingMargin,
6425
- cullingMargin = _b === void 0 ? DEFAULT_CULLING_MARGIN : _b,
6426
- _c = props.maxCacheSize,
6427
- maxCacheSize = _c === void 0 ? DEFAULT_MAX_CACHE_SIZE : _c,
6467
+ _b = props.enableViewportCulling,
6468
+ enableViewportCulling = _b === void 0 ? false : _b,
6469
+ _c = props.cullingMargin,
6470
+ cullingMargin = _c === void 0 ? DEFAULT_CULLING_MARGIN : _c,
6471
+ _d = props.maxCacheSize,
6472
+ maxCacheSize = _d === void 0 ? DEFAULT_MAX_CACHE_SIZE : _d,
6428
6473
  externalSelectedItems = props.selectedItems,
6429
6474
  externalSelectedItem = props.selectedItem,
6430
- _d = props.disableInteraction,
6431
- disableInteraction = _d === void 0 ? false : _d,
6475
+ _e = props.disableInteraction,
6476
+ disableInteraction = _e === void 0 ? false : _e,
6432
6477
  baseFillColor = props.baseFillColor,
6433
6478
  baseStrokeColor = props.baseStrokeColor,
6434
6479
  baseLineWidth = props.baseLineWidth,
@@ -6441,7 +6486,7 @@ var WoongCanvasPolygon = function (props) {
6441
6486
  hoveredFillColor = props.hoveredFillColor,
6442
6487
  hoveredStrokeColor = props.hoveredStrokeColor,
6443
6488
  hoveredLineWidth = props.hoveredLineWidth,
6444
- options = __rest(props, ["data", "onClick", "enableMultiSelect", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
6489
+ options = __rest(props, ["data", "onClick", "enableMultiSelect", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
6445
6490
  // Hooks & Context
6446
6491
  // --------------------------------------------------------------------------
6447
6492
 
@@ -6461,6 +6506,7 @@ var WoongCanvasPolygon = function (props) {
6461
6506
 
6462
6507
  var dataRef = useRef(data);
6463
6508
  var disableInteractionRef = useRef(disableInteraction);
6509
+ var enableViewportCullingRef = useRef(enableViewportCulling);
6464
6510
  var hoveredItemRef = useRef(null);
6465
6511
  var selectedItemRef = useRef(externalSelectedItem);
6466
6512
  var selectedIdsRef = useRef(new Set());
@@ -6561,9 +6607,9 @@ var WoongCanvasPolygon = function (props) {
6561
6607
  var ctx = context;
6562
6608
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
6563
6609
 
6564
- var visibleItems = dataRef.current.filter(function (item) {
6610
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
6565
6611
  return isInViewport$1(item);
6566
- });
6612
+ }) : dataRef.current;
6567
6613
  renderBase({
6568
6614
  ctx: ctx,
6569
6615
  items: visibleItems,
@@ -6615,14 +6661,17 @@ var WoongCanvasPolygon = function (props) {
6615
6661
 
6616
6662
 
6617
6663
  var renderAllImmediate = function () {
6618
- updateViewport$1();
6664
+ if (enableViewportCullingRef.current) {
6665
+ updateViewport$1();
6666
+ }
6667
+
6619
6668
  buildSpatialIndex$1();
6620
6669
  doRenderBase();
6621
6670
  doRenderEvent();
6622
6671
  }; // 지도 이벤트 핸들러 생성
6623
6672
 
6624
6673
 
6625
- var _e = createMapEventHandlers({
6674
+ var _f = createMapEventHandlers({
6626
6675
  controller: controller,
6627
6676
  containerRef: containerRef,
6628
6677
  markerRef: markerRef,
@@ -6633,12 +6682,12 @@ var WoongCanvasPolygon = function (props) {
6633
6682
  boundingBoxCacheRef: boundingBoxCacheRef,
6634
6683
  renderAllImmediate: renderAllImmediate
6635
6684
  }),
6636
- handleIdle = _e.handleIdle,
6637
- handleZoomStart = _e.handleZoomStart,
6638
- handleZoomEnd = _e.handleZoomEnd,
6639
- handleCenterChanged = _e.handleCenterChanged,
6640
- handleDragStartShared = _e.handleDragStart,
6641
- handleDragEndShared = _e.handleDragEnd;
6685
+ handleIdle = _f.handleIdle,
6686
+ handleZoomStart = _f.handleZoomStart,
6687
+ handleZoomEnd = _f.handleZoomEnd,
6688
+ handleCenterChanged = _f.handleCenterChanged,
6689
+ handleDragStartShared = _f.handleDragStart,
6690
+ handleDragEndShared = _f.handleDragEnd;
6642
6691
 
6643
6692
  var handleDragStart = function () {
6644
6693
  handleDragStartShared();
@@ -6799,7 +6848,11 @@ var WoongCanvasPolygon = function (props) {
6799
6848
  eventLayerRef.current = eventLayer;
6800
6849
  stage.add(baseLayer);
6801
6850
  stage.add(eventLayer);
6802
- updateViewport$1(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6851
+
6852
+ if (enableViewportCulling) {
6853
+ updateViewport$1();
6854
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6855
+
6803
6856
 
6804
6857
  var resizeRafId = null;
6805
6858
  var resizeObserver = new ResizeObserver(function () {
@@ -6812,7 +6865,11 @@ var WoongCanvasPolygon = function (props) {
6812
6865
  stage.height(mapDiv.offsetHeight);
6813
6866
  offsetCacheRef.current.clear();
6814
6867
  boundingBoxCacheRef.current.clear();
6815
- updateViewport$1();
6868
+
6869
+ if (enableViewportCullingRef.current) {
6870
+ updateViewport$1();
6871
+ }
6872
+
6816
6873
  renderAllImmediate();
6817
6874
  resizeRafId = null;
6818
6875
  });
@@ -6882,7 +6939,36 @@ var WoongCanvasPolygon = function (props) {
6882
6939
 
6883
6940
  useEffect(function () {
6884
6941
  disableInteractionRef.current = disableInteraction;
6885
- }, [disableInteraction]); // 외부 selectedItems 동기화
6942
+ }, [disableInteraction]); // enableViewportCulling 동기화
6943
+
6944
+ useEffect(function () {
6945
+ enableViewportCullingRef.current = enableViewportCulling;
6946
+
6947
+ if (stageRef.current) {
6948
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
6949
+ var baseLayer = baseLayerRef.current;
6950
+
6951
+ if (baseLayer) {
6952
+ var shape = baseLayer.findOne('.base-render-shape');
6953
+
6954
+ if (shape) {
6955
+ shape.destroy();
6956
+ }
6957
+ }
6958
+
6959
+ var eventLayer = eventLayerRef.current;
6960
+
6961
+ if (eventLayer) {
6962
+ var shape = eventLayer.findOne('.event-render-shape');
6963
+
6964
+ if (shape) {
6965
+ shape.destroy();
6966
+ }
6967
+ }
6968
+
6969
+ renderAllImmediate();
6970
+ }
6971
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
6886
6972
 
6887
6973
  useEffect(function () {
6888
6974
  if (!stageRef.current) return;
package/dist/index.umd.js CHANGED
@@ -5597,17 +5597,19 @@
5597
5597
  enableMultiSelect = _a === void 0 ? false : _a,
5598
5598
  _b = props.topOnHover,
5599
5599
  topOnHover = _b === void 0 ? false : _b,
5600
- _c = props.cullingMargin,
5601
- cullingMargin = _c === void 0 ? DEFAULT_CULLING_MARGIN : _c,
5602
- _d = props.maxCacheSize,
5603
- maxCacheSize = _d === void 0 ? DEFAULT_MAX_CACHE_SIZE : _d,
5600
+ _c = props.enableViewportCulling,
5601
+ enableViewportCulling = _c === void 0 ? false : _c,
5602
+ _d = props.cullingMargin,
5603
+ cullingMargin = _d === void 0 ? DEFAULT_CULLING_MARGIN : _d,
5604
+ _e = props.maxCacheSize,
5605
+ maxCacheSize = _e === void 0 ? DEFAULT_MAX_CACHE_SIZE : _e,
5604
5606
  externalSelectedItems = props.selectedItems,
5605
5607
  externalSelectedItem = props.selectedItem,
5606
- _e = props.disableInteraction,
5607
- disableInteraction = _e === void 0 ? false : _e,
5608
+ _f = props.disableInteraction,
5609
+ disableInteraction = _f === void 0 ? false : _f,
5608
5610
  renderBase = props.renderBase,
5609
5611
  renderEvent = props.renderEvent,
5610
- options = tslib.__rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
5612
+ options = tslib.__rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
5611
5613
 
5612
5614
  var controller = useMintMapController();
5613
5615
  var context = useWoongCanvasContext();
@@ -5624,6 +5626,7 @@
5624
5626
 
5625
5627
  var dataRef = React.useRef(data);
5626
5628
  var disableInteractionRef = React.useRef(disableInteraction);
5629
+ var enableViewportCullingRef = React.useRef(enableViewportCulling);
5627
5630
  var hoveredItemRef = React.useRef(null);
5628
5631
  var selectedItemRef = React.useRef(externalSelectedItem);
5629
5632
  var selectedIdsRef = React.useRef(new Set());
@@ -5703,9 +5706,9 @@
5703
5706
  var ctx = context;
5704
5707
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
5705
5708
 
5706
- var visibleItems = dataRef.current.filter(function (item) {
5709
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
5707
5710
  return isInViewport$1(item);
5708
- }); // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
5711
+ }) : dataRef.current; // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
5709
5712
 
5710
5713
  if (topOnHover && !renderEvent && hovered) {
5711
5714
  visibleItems = visibleItems.filter(function (item) {
@@ -5723,7 +5726,7 @@
5723
5726
  }); // hover된 항목을 마지막에 렌더링하여 최상위에 표시
5724
5727
 
5725
5728
  if (topOnHover && !renderEvent && hovered) {
5726
- if (isInViewport$1(hovered)) {
5729
+ if (!enableViewportCullingRef.current || isInViewport$1(hovered)) {
5727
5730
  renderBase({
5728
5731
  ctx: ctx,
5729
5732
  items: [hovered],
@@ -5769,7 +5772,7 @@
5769
5772
  selectedItem: selectedItemRef.current
5770
5773
  });
5771
5774
 
5772
- if (isInViewport$1(hovered)) {
5775
+ if (!enableViewportCullingRef.current || isInViewport$1(hovered)) {
5773
5776
  var hoveredIsSelected = selectedItems.some(function (item) {
5774
5777
  return item.id === hovered.id;
5775
5778
  });
@@ -5804,14 +5807,17 @@
5804
5807
 
5805
5808
 
5806
5809
  var renderAllImmediate = function () {
5807
- updateViewport$1();
5810
+ if (enableViewportCullingRef.current) {
5811
+ updateViewport$1();
5812
+ }
5813
+
5808
5814
  buildSpatialIndex$1();
5809
5815
  doRenderBase();
5810
5816
  doRenderEvent();
5811
5817
  }; // 지도 이벤트 핸들러 생성
5812
5818
 
5813
5819
 
5814
- var _f = createMapEventHandlers({
5820
+ var _g = createMapEventHandlers({
5815
5821
  controller: controller,
5816
5822
  containerRef: containerRef,
5817
5823
  markerRef: markerRef,
@@ -5822,12 +5828,12 @@
5822
5828
  boundingBoxCacheRef: boundingBoxCacheRef,
5823
5829
  renderAllImmediate: renderAllImmediate
5824
5830
  }),
5825
- handleIdle = _f.handleIdle,
5826
- handleZoomStart = _f.handleZoomStart,
5827
- handleZoomEnd = _f.handleZoomEnd,
5828
- handleCenterChanged = _f.handleCenterChanged,
5829
- handleDragStartShared = _f.handleDragStart,
5830
- handleDragEndShared = _f.handleDragEnd;
5831
+ handleIdle = _g.handleIdle,
5832
+ handleZoomStart = _g.handleZoomStart,
5833
+ handleZoomEnd = _g.handleZoomEnd,
5834
+ handleCenterChanged = _g.handleCenterChanged,
5835
+ handleDragStartShared = _g.handleDragStart,
5836
+ handleDragEndShared = _g.handleDragEnd;
5831
5837
 
5832
5838
  var handleDragStart = function () {
5833
5839
  handleDragStartShared();
@@ -6004,7 +6010,11 @@
6004
6010
  eventLayerRef.current = eventLayer;
6005
6011
  stage.add(baseLayer);
6006
6012
  stage.add(eventLayer);
6007
- updateViewport$1(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6013
+
6014
+ if (enableViewportCulling) {
6015
+ updateViewport$1();
6016
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6017
+
6008
6018
 
6009
6019
  var resizeRafId = null;
6010
6020
  var resizeObserver = new ResizeObserver(function () {
@@ -6017,7 +6027,11 @@
6017
6027
  stage.height(mapDiv.offsetHeight);
6018
6028
  offsetCacheRef.current.clear();
6019
6029
  boundingBoxCacheRef.current.clear();
6020
- updateViewport$1();
6030
+
6031
+ if (enableViewportCullingRef.current) {
6032
+ updateViewport$1();
6033
+ }
6034
+
6021
6035
  renderAllImmediate();
6022
6036
  resizeRafId = null;
6023
6037
  });
@@ -6089,7 +6103,36 @@
6089
6103
 
6090
6104
  React.useEffect(function () {
6091
6105
  disableInteractionRef.current = disableInteraction;
6092
- }, [disableInteraction]); // 외부 selectedItems 동기화
6106
+ }, [disableInteraction]); // enableViewportCulling 동기화
6107
+
6108
+ React.useEffect(function () {
6109
+ enableViewportCullingRef.current = enableViewportCulling;
6110
+
6111
+ if (stageRef.current) {
6112
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
6113
+ var baseLayer = baseLayerRef.current;
6114
+
6115
+ if (baseLayer) {
6116
+ var shape = baseLayer.findOne('.base-render-shape');
6117
+
6118
+ if (shape) {
6119
+ shape.destroy();
6120
+ }
6121
+ }
6122
+
6123
+ var eventLayer = eventLayerRef.current;
6124
+
6125
+ if (eventLayer) {
6126
+ var shape = eventLayer.findOne('.event-render-shape');
6127
+
6128
+ if (shape) {
6129
+ shape.destroy();
6130
+ }
6131
+ }
6132
+
6133
+ renderAllImmediate();
6134
+ }
6135
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
6093
6136
 
6094
6137
  React.useEffect(function () {
6095
6138
  if (!stageRef.current) return;
@@ -6425,14 +6468,16 @@
6425
6468
  onClick = props.onClick,
6426
6469
  _a = props.enableMultiSelect,
6427
6470
  enableMultiSelect = _a === void 0 ? false : _a,
6428
- _b = props.cullingMargin,
6429
- cullingMargin = _b === void 0 ? DEFAULT_CULLING_MARGIN : _b,
6430
- _c = props.maxCacheSize,
6431
- maxCacheSize = _c === void 0 ? DEFAULT_MAX_CACHE_SIZE : _c,
6471
+ _b = props.enableViewportCulling,
6472
+ enableViewportCulling = _b === void 0 ? false : _b,
6473
+ _c = props.cullingMargin,
6474
+ cullingMargin = _c === void 0 ? DEFAULT_CULLING_MARGIN : _c,
6475
+ _d = props.maxCacheSize,
6476
+ maxCacheSize = _d === void 0 ? DEFAULT_MAX_CACHE_SIZE : _d,
6432
6477
  externalSelectedItems = props.selectedItems,
6433
6478
  externalSelectedItem = props.selectedItem,
6434
- _d = props.disableInteraction,
6435
- disableInteraction = _d === void 0 ? false : _d,
6479
+ _e = props.disableInteraction,
6480
+ disableInteraction = _e === void 0 ? false : _e,
6436
6481
  baseFillColor = props.baseFillColor,
6437
6482
  baseStrokeColor = props.baseStrokeColor,
6438
6483
  baseLineWidth = props.baseLineWidth,
@@ -6445,7 +6490,7 @@
6445
6490
  hoveredFillColor = props.hoveredFillColor,
6446
6491
  hoveredStrokeColor = props.hoveredStrokeColor,
6447
6492
  hoveredLineWidth = props.hoveredLineWidth,
6448
- options = tslib.__rest(props, ["data", "onClick", "enableMultiSelect", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
6493
+ options = tslib.__rest(props, ["data", "onClick", "enableMultiSelect", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "baseFillColor", "baseStrokeColor", "baseLineWidth", "selectedFillColor", "selectedStrokeColor", "selectedLineWidth", "activeFillColor", "activeStrokeColor", "activeLineWidth", "hoveredFillColor", "hoveredStrokeColor", "hoveredLineWidth"]); // --------------------------------------------------------------------------
6449
6494
  // Hooks & Context
6450
6495
  // --------------------------------------------------------------------------
6451
6496
 
@@ -6465,6 +6510,7 @@
6465
6510
 
6466
6511
  var dataRef = React.useRef(data);
6467
6512
  var disableInteractionRef = React.useRef(disableInteraction);
6513
+ var enableViewportCullingRef = React.useRef(enableViewportCulling);
6468
6514
  var hoveredItemRef = React.useRef(null);
6469
6515
  var selectedItemRef = React.useRef(externalSelectedItem);
6470
6516
  var selectedIdsRef = React.useRef(new Set());
@@ -6565,9 +6611,9 @@
6565
6611
  var ctx = context;
6566
6612
  var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
6567
6613
 
6568
- var visibleItems = dataRef.current.filter(function (item) {
6614
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
6569
6615
  return isInViewport$1(item);
6570
- });
6616
+ }) : dataRef.current;
6571
6617
  renderBase({
6572
6618
  ctx: ctx,
6573
6619
  items: visibleItems,
@@ -6619,14 +6665,17 @@
6619
6665
 
6620
6666
 
6621
6667
  var renderAllImmediate = function () {
6622
- updateViewport$1();
6668
+ if (enableViewportCullingRef.current) {
6669
+ updateViewport$1();
6670
+ }
6671
+
6623
6672
  buildSpatialIndex$1();
6624
6673
  doRenderBase();
6625
6674
  doRenderEvent();
6626
6675
  }; // 지도 이벤트 핸들러 생성
6627
6676
 
6628
6677
 
6629
- var _e = createMapEventHandlers({
6678
+ var _f = createMapEventHandlers({
6630
6679
  controller: controller,
6631
6680
  containerRef: containerRef,
6632
6681
  markerRef: markerRef,
@@ -6637,12 +6686,12 @@
6637
6686
  boundingBoxCacheRef: boundingBoxCacheRef,
6638
6687
  renderAllImmediate: renderAllImmediate
6639
6688
  }),
6640
- handleIdle = _e.handleIdle,
6641
- handleZoomStart = _e.handleZoomStart,
6642
- handleZoomEnd = _e.handleZoomEnd,
6643
- handleCenterChanged = _e.handleCenterChanged,
6644
- handleDragStartShared = _e.handleDragStart,
6645
- handleDragEndShared = _e.handleDragEnd;
6689
+ handleIdle = _f.handleIdle,
6690
+ handleZoomStart = _f.handleZoomStart,
6691
+ handleZoomEnd = _f.handleZoomEnd,
6692
+ handleCenterChanged = _f.handleCenterChanged,
6693
+ handleDragStartShared = _f.handleDragStart,
6694
+ handleDragEndShared = _f.handleDragEnd;
6646
6695
 
6647
6696
  var handleDragStart = function () {
6648
6697
  handleDragStartShared();
@@ -6803,7 +6852,11 @@
6803
6852
  eventLayerRef.current = eventLayer;
6804
6853
  stage.add(baseLayer);
6805
6854
  stage.add(eventLayer);
6806
- updateViewport$1(); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6855
+
6856
+ if (enableViewportCulling) {
6857
+ updateViewport$1();
6858
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
6859
+
6807
6860
 
6808
6861
  var resizeRafId = null;
6809
6862
  var resizeObserver = new ResizeObserver(function () {
@@ -6816,7 +6869,11 @@
6816
6869
  stage.height(mapDiv.offsetHeight);
6817
6870
  offsetCacheRef.current.clear();
6818
6871
  boundingBoxCacheRef.current.clear();
6819
- updateViewport$1();
6872
+
6873
+ if (enableViewportCullingRef.current) {
6874
+ updateViewport$1();
6875
+ }
6876
+
6820
6877
  renderAllImmediate();
6821
6878
  resizeRafId = null;
6822
6879
  });
@@ -6886,7 +6943,36 @@
6886
6943
 
6887
6944
  React.useEffect(function () {
6888
6945
  disableInteractionRef.current = disableInteraction;
6889
- }, [disableInteraction]); // 외부 selectedItems 동기화
6946
+ }, [disableInteraction]); // enableViewportCulling 동기화
6947
+
6948
+ React.useEffect(function () {
6949
+ enableViewportCullingRef.current = enableViewportCulling;
6950
+
6951
+ if (stageRef.current) {
6952
+ // 뷰포트 컬링 설정이 변경되면 shape 재생성 필요
6953
+ var baseLayer = baseLayerRef.current;
6954
+
6955
+ if (baseLayer) {
6956
+ var shape = baseLayer.findOne('.base-render-shape');
6957
+
6958
+ if (shape) {
6959
+ shape.destroy();
6960
+ }
6961
+ }
6962
+
6963
+ var eventLayer = eventLayerRef.current;
6964
+
6965
+ if (eventLayer) {
6966
+ var shape = eventLayer.findOne('.event-render-shape');
6967
+
6968
+ if (shape) {
6969
+ shape.destroy();
6970
+ }
6971
+ }
6972
+
6973
+ renderAllImmediate();
6974
+ }
6975
+ }, [enableViewportCulling]); // 외부 selectedItems 동기화
6890
6976
 
6891
6977
  React.useEffect(function () {
6892
6978
  if (!stageRef.current) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mint-ui/map",
3
- "version": "1.2.0-test.39",
3
+ "version": "1.2.0-test.40",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "browser": "./dist/index.umd.js",