@mint-ui/map 1.2.0-test.4 → 1.2.0-test.41

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.
Files changed (42) hide show
  1. package/dist/components/mint-map/core/MintMapCore.js +5 -6
  2. package/dist/components/mint-map/core/advanced/index.d.ts +2 -1
  3. package/dist/components/mint-map/core/advanced/shared/context.d.ts +39 -0
  4. package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/context.js +62 -79
  5. package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +20 -0
  6. package/dist/components/mint-map/core/advanced/shared/helpers.js +40 -0
  7. package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +74 -0
  8. package/dist/components/mint-map/core/advanced/shared/hooks.js +189 -0
  9. package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/index.d.ts +3 -0
  10. package/dist/components/mint-map/core/advanced/shared/performance.d.ts +77 -0
  11. package/dist/components/mint-map/core/advanced/shared/performance.js +262 -0
  12. package/dist/components/mint-map/core/advanced/shared/types.d.ts +126 -0
  13. package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/types.js +4 -1
  14. package/dist/components/mint-map/core/advanced/shared/utils.d.ts +95 -0
  15. package/dist/components/mint-map/core/advanced/shared/utils.js +261 -0
  16. package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +42 -0
  17. package/dist/components/mint-map/core/advanced/shared/viewport.js +51 -0
  18. package/dist/components/mint-map/core/advanced/woongCanvasMarker/WoongCanvasMarker.d.ts +47 -0
  19. package/dist/components/mint-map/core/advanced/woongCanvasMarker/WoongCanvasMarker.js +620 -0
  20. package/dist/components/mint-map/core/advanced/woongCanvasMarker/index.d.ts +3 -0
  21. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.d.ts +61 -0
  22. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/WoongCanvasPolygon.js +582 -0
  23. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/index.d.ts +3 -0
  24. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/renderer.d.ts +120 -0
  25. package/dist/components/mint-map/core/advanced/woongCanvasPolygon/renderer.js +295 -0
  26. package/dist/components/mint-map/google/GoogleMintMapController.js +5 -4
  27. package/dist/components/mint-map/kakao/KakaoMintMapController.js +5 -4
  28. package/dist/components/mint-map/naver/NaverMintMapController.js +5 -4
  29. package/dist/index.es.js +1734 -1041
  30. package/dist/index.js +24 -8
  31. package/dist/index.umd.js +1747 -1042
  32. package/package.json +1 -1
  33. package/dist/components/mint-map/core/advanced/woongCanvas/ClusterMarker.d.ts +0 -11
  34. package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.d.ts +0 -50
  35. package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.js +0 -1065
  36. package/dist/components/mint-map/core/advanced/woongCanvas/index.d.ts +0 -3
  37. package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.d.ts +0 -31
  38. package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.d.ts +0 -161
  39. package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.js +0 -343
  40. package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.d.ts +0 -131
  41. package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.d.ts +0 -23
  42. package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.js +0 -115
@@ -0,0 +1,620 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tslib = require('tslib');
6
+ var React = require('react');
7
+ var Konva = require('konva');
8
+ var MintMapProvider = require('../../provider/MintMapProvider.js');
9
+ var MapDrawables = require('../../../types/MapDrawables.js');
10
+ require('../../../types/MapTypes.js');
11
+ require('../../../types/MapEventTypes.js');
12
+ var reactDom = require('react-dom');
13
+ var types = require('../shared/types.js');
14
+ var utils = require('../shared/utils.js');
15
+ var context = require('../shared/context.js');
16
+ var performance = require('../shared/performance.js');
17
+ var viewport = require('../shared/viewport.js');
18
+ var hooks = require('../shared/hooks.js');
19
+ var helpers = require('../shared/helpers.js');
20
+
21
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
22
+
23
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
24
+ var Konva__default = /*#__PURE__*/_interopDefaultLegacy(Konva);
25
+
26
+ var WoongCanvasMarker = function (props) {
27
+ var data = props.data,
28
+ onClick = props.onClick,
29
+ onMouseOver = props.onMouseOver,
30
+ onMouseOut = props.onMouseOut,
31
+ _a = props.enableMultiSelect,
32
+ enableMultiSelect = _a === void 0 ? false : _a,
33
+ _b = props.topOnHover,
34
+ topOnHover = _b === void 0 ? false : _b,
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,
41
+ externalSelectedItems = props.selectedItems,
42
+ externalSelectedItem = props.selectedItem,
43
+ _f = props.disableInteraction,
44
+ disableInteraction = _f === void 0 ? false : _f,
45
+ renderBase = props.renderBase,
46
+ renderEvent = props.renderEvent,
47
+ options = tslib.__rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
48
+
49
+ var controller = MintMapProvider.useMintMapController();
50
+ var context$1 = context.useWoongCanvasContext();
51
+ var currentZIndex = options.zIndex !== undefined ? options.zIndex : 0; // DOM Refs
52
+
53
+ var divRef = React.useRef(document.createElement('div'));
54
+ var divElement = divRef.current;
55
+ var containerRef = React.useRef(null);
56
+ var markerRef = React.useRef(); // Konva Refs
57
+
58
+ var stageRef = React.useRef(null);
59
+ var baseLayerRef = React.useRef(null);
60
+ var eventLayerRef = React.useRef(null); // 상태 관리 Refs (React 리렌더링 최소화)
61
+
62
+ var dataRef = React.useRef(data);
63
+ var disableInteractionRef = React.useRef(disableInteraction);
64
+ var enableViewportCullingRef = React.useRef(enableViewportCulling);
65
+ var hoveredItemRef = React.useRef(null);
66
+ var selectedItemRef = React.useRef(externalSelectedItem);
67
+ var selectedIdsRef = React.useRef(new Set());
68
+ var selectedItemsMapRef = React.useRef(new Map()); // 드래그 상태 Refs
69
+
70
+ var draggingRef = React.useRef(false);
71
+ var prevCenterOffsetRef = React.useRef(null);
72
+ var accumTranslateRef = React.useRef({
73
+ x: 0,
74
+ y: 0
75
+ }); // 성능 최적화 Refs
76
+
77
+ var offsetCacheRef = React.useRef(new performance.LRUCache(maxCacheSize));
78
+ var spatialIndexRef = React.useRef(new performance.SpatialHashGrid(performance.SPATIAL_GRID_CELL_SIZE));
79
+ var boundingBoxCacheRef = React.useRef(new Map());
80
+ var viewportRef = React.useRef(null); // 뷰포트 영역 계산 (Viewport Culling용)
81
+
82
+ var updateViewport = function () {
83
+ viewport.updateViewport(stageRef.current, cullingMargin, viewportRef);
84
+ }; // 뷰포트 내부 여부 확인 (바운딩 박스 캐싱)
85
+
86
+
87
+ var isInViewport = function (item) {
88
+ return viewport.isInViewport(item, viewportRef, boundingBoxCacheRef, computeBoundingBox);
89
+ }; // 마커 좌표 변환 (위경도 → 화면 좌표, LRU 캐시 사용)
90
+
91
+
92
+ var getOrComputeMarkerOffset = function (markerData) {
93
+ var cached = offsetCacheRef.current.get(markerData.id);
94
+ if (cached && !Array.isArray(cached)) return cached;
95
+ var result = utils.computeMarkerOffset(markerData, controller);
96
+ if (!result) return null;
97
+ offsetCacheRef.current.set(markerData.id, result);
98
+ return result;
99
+ }; // 마커 바운딩 박스 계산 (Viewport Culling 및 Hit Test용, 오프셋 지원)
100
+
101
+
102
+ var computeBoundingBox = function (item) {
103
+ var offset = getOrComputeMarkerOffset(item);
104
+ if (!offset) return null;
105
+ var boxWidth = item.boxWidth || 50;
106
+ var boxHeight = item.boxHeight || 28;
107
+ var tailHeight = item.tailHeight || 0;
108
+ var offsetX = item.offsetX || 0;
109
+ var offsetY = item.offsetY || 0; // 오프셋을 적용한 마커 중심점 기준으로 바운딩 박스 계산
110
+
111
+ return {
112
+ minX: offset.x + offsetX - boxWidth / 2,
113
+ minY: offset.y + offsetY - boxHeight - tailHeight,
114
+ maxX: offset.x + offsetX + boxWidth / 2,
115
+ maxY: offset.y + offsetY
116
+ };
117
+ }; // 공간 인덱스 빌드 (빠른 Hit Test용)
118
+
119
+
120
+ var buildSpatialIndex = function () {
121
+ hooks.buildSpatialIndex(dataRef.current, spatialIndexRef.current, computeBoundingBox);
122
+ }; // 렌더링 유틸리티 객체
123
+
124
+
125
+ var renderUtils = {
126
+ getOrComputePolygonOffsets: function () {
127
+ return null;
128
+ },
129
+ getOrComputeMarkerOffset: getOrComputeMarkerOffset
130
+ }; // Base Layer 렌더링 (뷰포트 컬링 적용, 선택된 마커 제외)
131
+
132
+ var doRenderBase = function () {
133
+ var layer = baseLayerRef.current;
134
+ if (!layer) return;
135
+ var shape = layer.findOne('.base-render-shape');
136
+
137
+ if (!shape) {
138
+ shape = new Konva__default["default"].Shape({
139
+ name: 'base-render-shape',
140
+ sceneFunc: function (context, shape) {
141
+ var ctx = context;
142
+ var hovered = hoveredItemRef.current; // 뷰포트 컬링: 화면에 보이는 항목만 필터링
143
+
144
+ var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
145
+ return isInViewport(item);
146
+ }) : dataRef.current; // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
147
+
148
+ if (topOnHover && !renderEvent && hovered) {
149
+ visibleItems = visibleItems.filter(function (item) {
150
+ return item.id !== hovered.id;
151
+ });
152
+ } // 일반 항목들 먼저 렌더링
153
+
154
+
155
+ renderBase({
156
+ ctx: ctx,
157
+ items: visibleItems,
158
+ selectedIds: selectedIdsRef.current,
159
+ hoveredItem: hovered,
160
+ utils: renderUtils
161
+ }); // hover된 항목을 마지막에 렌더링하여 최상위에 표시
162
+
163
+ if (topOnHover && !renderEvent && hovered) {
164
+ if (!enableViewportCullingRef.current || isInViewport(hovered)) {
165
+ renderBase({
166
+ ctx: ctx,
167
+ items: [hovered],
168
+ selectedIds: selectedIdsRef.current,
169
+ hoveredItem: hovered,
170
+ utils: renderUtils
171
+ });
172
+ }
173
+ }
174
+ },
175
+ perfectDrawEnabled: false,
176
+ listening: false,
177
+ hitStrokeWidth: 0
178
+ });
179
+ layer.add(shape);
180
+ }
181
+
182
+ layer.batchDraw();
183
+ }; // Event Layer 렌더링 (hover 효과 및 선택 상태 표시)
184
+
185
+
186
+ var doRenderEvent = function () {
187
+ var layer = eventLayerRef.current;
188
+ if (!layer || !renderEvent) return;
189
+ var shape = layer.findOne('.event-render-shape');
190
+
191
+ if (!shape) {
192
+ shape = new Konva__default["default"].Shape({
193
+ name: 'event-render-shape',
194
+ sceneFunc: function (context, shape) {
195
+ var ctx = context;
196
+ var selectedItems = helpers.mapValuesToArray(selectedItemsMapRef.current);
197
+ var hovered = hoveredItemRef.current;
198
+
199
+ if (topOnHover && hovered) {
200
+ renderEvent({
201
+ ctx: ctx,
202
+ hoveredItem: null,
203
+ utils: renderUtils,
204
+ selectedItems: selectedItems.filter(function (item) {
205
+ return item.id !== hovered.id;
206
+ }),
207
+ selectedItem: selectedItemRef.current
208
+ });
209
+
210
+ if (!enableViewportCullingRef.current || isInViewport(hovered)) {
211
+ var hoveredIsSelected = selectedItems.some(function (item) {
212
+ return item.id === hovered.id;
213
+ });
214
+ var hoverSelectedItems = hoveredIsSelected ? [hovered] : [];
215
+ renderEvent({
216
+ ctx: ctx,
217
+ hoveredItem: hovered,
218
+ utils: renderUtils,
219
+ selectedItems: hoverSelectedItems,
220
+ selectedItem: selectedItemRef.current
221
+ });
222
+ }
223
+ } else {
224
+ renderEvent({
225
+ ctx: ctx,
226
+ hoveredItem: hovered,
227
+ utils: renderUtils,
228
+ selectedItems: selectedItems,
229
+ selectedItem: selectedItemRef.current
230
+ });
231
+ }
232
+ },
233
+ perfectDrawEnabled: false,
234
+ listening: false,
235
+ hitStrokeWidth: 0
236
+ });
237
+ layer.add(shape);
238
+ }
239
+
240
+ layer.batchDraw();
241
+ }; // 전체 즉시 렌더링
242
+
243
+
244
+ var renderAllImmediate = function () {
245
+ if (enableViewportCullingRef.current) {
246
+ updateViewport();
247
+ }
248
+
249
+ buildSpatialIndex();
250
+ doRenderBase();
251
+ doRenderEvent();
252
+ }; // 지도 이벤트 핸들러 생성
253
+
254
+
255
+ var _g = hooks.createMapEventHandlers({
256
+ controller: controller,
257
+ containerRef: containerRef,
258
+ markerRef: markerRef,
259
+ options: options,
260
+ prevCenterOffsetRef: prevCenterOffsetRef,
261
+ accumTranslateRef: accumTranslateRef,
262
+ offsetCacheRef: offsetCacheRef,
263
+ boundingBoxCacheRef: boundingBoxCacheRef,
264
+ renderAllImmediate: renderAllImmediate
265
+ }),
266
+ handleIdle = _g.handleIdle,
267
+ handleZoomStart = _g.handleZoomStart,
268
+ handleZoomEnd = _g.handleZoomEnd,
269
+ handleCenterChanged = _g.handleCenterChanged,
270
+ handleDragStartShared = _g.handleDragStart,
271
+ handleDragEndShared = _g.handleDragEnd;
272
+
273
+ var handleDragStart = function () {
274
+ handleDragStartShared();
275
+ draggingRef.current = true;
276
+ controller.setMapCursor('grabbing');
277
+ };
278
+
279
+ var handleDragEnd = function () {
280
+ handleDragEndShared();
281
+ draggingRef.current = false;
282
+ controller.setMapCursor('grab');
283
+ }; // Hit Test: 특정 좌표의 마커 찾기
284
+
285
+
286
+ var findData = function (offset) {
287
+ // topOnHover 옵션이 켜져 있으면 hover된 항목을 최우선으로 확인
288
+ if (topOnHover && hoveredItemRef.current) {
289
+ var hovered = hoveredItemRef.current;
290
+
291
+ if (utils.isPointInMarkerData(offset, hovered, getOrComputeMarkerOffset)) {
292
+ return hovered;
293
+ }
294
+ } // 공간 인덱스에서 후보 항목 조회 (O(1) 수준의 빠른 조회)
295
+
296
+
297
+ var candidates = spatialIndexRef.current.queryPoint(offset.x, offset.y); // 역순 순회: 나중에 추가된 항목(최상위)이 먼저 선택되도록
298
+
299
+ for (var i = candidates.length - 1; i >= 0; i--) {
300
+ var item = candidates[i];
301
+
302
+ if (utils.isPointInMarkerData(offset, item, getOrComputeMarkerOffset)) {
303
+ return item;
304
+ }
305
+ }
306
+
307
+ return null;
308
+ }; // Hover 상태 설정 및 렌더링
309
+
310
+
311
+ var setHovered = function (data) {
312
+ hoveredItemRef.current = data;
313
+
314
+ if (draggingRef.current) {
315
+ controller.setMapCursor('grabbing');
316
+ } else {
317
+ controller.setMapCursor(data ? 'pointer' : 'grab');
318
+ }
319
+
320
+ if (renderEvent) {
321
+ doRenderEvent();
322
+ } else if (topOnHover) {
323
+ doRenderBase();
324
+ }
325
+ }; // 클릭 처리: 선택 상태 업데이트
326
+
327
+
328
+ var handleLocalClick = function (data) {
329
+ if (enableMultiSelect) {
330
+ var newSelected = new Set(selectedIdsRef.current);
331
+
332
+ if (newSelected.has(data.id)) {
333
+ newSelected.delete(data.id);
334
+ selectedItemsMapRef.current.delete(data.id);
335
+ } else {
336
+ newSelected.add(data.id);
337
+ selectedItemsMapRef.current.set(data.id, data);
338
+ }
339
+
340
+ selectedIdsRef.current = newSelected;
341
+ } else {
342
+ var newSelected = new Set();
343
+
344
+ if (!selectedIdsRef.current.has(data.id)) {
345
+ newSelected.add(data.id);
346
+ selectedItemsMapRef.current.clear();
347
+ selectedItemsMapRef.current.set(data.id, data);
348
+ } else {
349
+ selectedItemsMapRef.current.clear();
350
+ }
351
+
352
+ selectedIdsRef.current = newSelected;
353
+ }
354
+
355
+ doRenderBase();
356
+ doRenderEvent();
357
+ }; // 클릭 이벤트 핸들러
358
+
359
+
360
+ var handleClick = function (event) {
361
+ if (disableInteractionRef.current) return;
362
+ var clickedOffset = helpers.validateEvent(event, context$1, controller);
363
+ if (!clickedOffset) return;
364
+ var data = findData(clickedOffset);
365
+ if (!data) return;
366
+ handleLocalClick(data);
367
+ onClick === null || onClick === void 0 ? void 0 : onClick(data, selectedIdsRef.current);
368
+ }; // 마우스 이동 이벤트 핸들러 (hover 감지)
369
+
370
+
371
+ var handleMouseMove = function (event) {
372
+ if (disableInteractionRef.current) return;
373
+ var mouseOffset = helpers.validateEvent(event, context$1, controller);
374
+ if (!mouseOffset) return;
375
+ var hoveredItem = findData(mouseOffset);
376
+ var prevHovered = hoveredItemRef.current;
377
+ if (prevHovered === hoveredItem) return;
378
+ setHovered(hoveredItem);
379
+ if (prevHovered) onMouseOut === null || onMouseOut === void 0 ? void 0 : onMouseOut(prevHovered);
380
+ if (hoveredItem) onMouseOver === null || onMouseOver === void 0 ? void 0 : onMouseOver(hoveredItem);
381
+ }; // 마우스가 맵 영역을 벗어날 때 hover 상태 초기화
382
+
383
+
384
+ var handleMouseLeave = function () {
385
+ if (disableInteractionRef.current) return;
386
+ var prevHovered = hoveredItemRef.current;
387
+ if (!prevHovered) return;
388
+ hoveredItemRef.current = null;
389
+ controller.setMapCursor('grab');
390
+ doRenderEvent();
391
+ onMouseOut === null || onMouseOut === void 0 ? void 0 : onMouseOut(prevHovered);
392
+ }; // DOM 초기화
393
+
394
+
395
+ React.useEffect(function () {
396
+ divElement.style.width = 'fit-content';
397
+ return function () {
398
+ if (!markerRef.current) return;
399
+ controller.clearDrawable(markerRef.current);
400
+ markerRef.current = undefined;
401
+ };
402
+ }, []); // 마커 생성/업데이트
403
+
404
+ React.useEffect(function () {
405
+ if (!options) return;
406
+ var bounds = controller.getCurrBounds();
407
+
408
+ var markerOptions = tslib.__assign({
409
+ position: bounds.nw
410
+ }, options);
411
+
412
+ if (markerRef.current) {
413
+ controller.updateMarker(markerRef.current, markerOptions);
414
+ return;
415
+ }
416
+
417
+ markerRef.current = new MapDrawables.Marker(markerOptions);
418
+ markerRef.current.element = divElement;
419
+ controller.createMarker(markerRef.current);
420
+
421
+ if (divElement.parentElement) {
422
+ divElement.parentElement.style.pointerEvents = 'none';
423
+ }
424
+
425
+ if (options.zIndex !== undefined) {
426
+ controller.setMarkerZIndex(markerRef.current, options.zIndex);
427
+ }
428
+ }, [options]); // Konva 초기화 및 이벤트 리스너 등록
429
+
430
+ React.useEffect(function () {
431
+ var mapDiv = controller.mapDivElement;
432
+ var stage = new Konva__default["default"].Stage({
433
+ container: containerRef.current,
434
+ width: mapDiv.offsetWidth,
435
+ height: mapDiv.offsetHeight
436
+ });
437
+ stageRef.current = stage;
438
+ var baseLayer = new Konva__default["default"].Layer({
439
+ listening: false
440
+ });
441
+ var eventLayer = new Konva__default["default"].Layer({
442
+ listening: false
443
+ });
444
+ baseLayerRef.current = baseLayer;
445
+ eventLayerRef.current = eventLayer;
446
+ stage.add(baseLayer);
447
+ stage.add(eventLayer);
448
+
449
+ if (enableViewportCulling) {
450
+ updateViewport();
451
+ } // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
452
+
453
+
454
+ var resizeRafId = null;
455
+ var resizeObserver = new ResizeObserver(function () {
456
+ if (resizeRafId !== null) {
457
+ cancelAnimationFrame(resizeRafId);
458
+ }
459
+
460
+ resizeRafId = requestAnimationFrame(function () {
461
+ stage.width(mapDiv.offsetWidth);
462
+ stage.height(mapDiv.offsetHeight);
463
+ offsetCacheRef.current.clear();
464
+ boundingBoxCacheRef.current.clear();
465
+
466
+ if (enableViewportCullingRef.current) {
467
+ updateViewport();
468
+ }
469
+
470
+ renderAllImmediate();
471
+ resizeRafId = null;
472
+ });
473
+ });
474
+ resizeObserver.observe(mapDiv);
475
+ controller.addEventListener('IDLE', handleIdle);
476
+ controller.addEventListener('ZOOMSTART', handleZoomStart);
477
+ controller.addEventListener('ZOOM_CHANGED', handleZoomEnd);
478
+ controller.addEventListener('CENTER_CHANGED', handleCenterChanged);
479
+ controller.addEventListener('CLICK', handleClick);
480
+ controller.addEventListener('MOUSEMOVE', handleMouseMove);
481
+ controller.addEventListener('DRAGSTART', handleDragStart);
482
+ controller.addEventListener('DRAGEND', handleDragEnd);
483
+ mapDiv.addEventListener('mouseleave', handleMouseLeave);
484
+ renderAllImmediate(); // Context 사용 시 컴포넌트 등록
485
+
486
+ var componentInstance = null;
487
+
488
+ if (context$1) {
489
+ componentInstance = {
490
+ zIndex: currentZIndex,
491
+ hitTest: function (offset) {
492
+ return findData(offset) !== null;
493
+ },
494
+ onClick: onClick,
495
+ onMouseOver: onMouseOver,
496
+ onMouseOut: onMouseOut,
497
+ findData: findData,
498
+ setHovered: setHovered,
499
+ handleLocalClick: handleLocalClick,
500
+ getSelectedIds: function () {
501
+ return selectedIdsRef.current;
502
+ },
503
+ isInteractionDisabled: function () {
504
+ return disableInteractionRef.current;
505
+ }
506
+ };
507
+ context$1.registerComponent(componentInstance);
508
+ }
509
+
510
+ return function () {
511
+ if (resizeRafId !== null) {
512
+ cancelAnimationFrame(resizeRafId);
513
+ }
514
+
515
+ resizeObserver.disconnect();
516
+ controller.removeEventListener('IDLE', handleIdle);
517
+ controller.removeEventListener('ZOOMSTART', handleZoomStart);
518
+ controller.removeEventListener('ZOOM_CHANGED', handleZoomEnd);
519
+ controller.removeEventListener('CENTER_CHANGED', handleCenterChanged);
520
+ controller.removeEventListener('CLICK', handleClick);
521
+ controller.removeEventListener('MOUSEMOVE', handleMouseMove);
522
+ controller.removeEventListener('DRAGSTART', handleDragStart);
523
+ controller.removeEventListener('DRAGEND', handleDragEnd);
524
+ mapDiv.removeEventListener('mouseleave', handleMouseLeave);
525
+
526
+ if (context$1 && componentInstance) {
527
+ context$1.unregisterComponent(componentInstance);
528
+ }
529
+
530
+ baseLayer.destroyChildren();
531
+ eventLayer.destroyChildren();
532
+ stage.destroy();
533
+ offsetCacheRef.current.clear();
534
+ boundingBoxCacheRef.current.clear();
535
+ spatialIndexRef.current.clear();
536
+ };
537
+ }, []); // disableInteraction 동기화
538
+
539
+ React.useEffect(function () {
540
+ disableInteractionRef.current = disableInteraction;
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 동기화
571
+
572
+ React.useEffect(function () {
573
+ if (!stageRef.current) return;
574
+ hooks.syncExternalSelectedItems(externalSelectedItems, selectedIdsRef, selectedItemsMapRef);
575
+ doRenderBase();
576
+ doRenderEvent();
577
+ }, [externalSelectedItems]); // 외부 selectedItem 변경 시 Event Layer 리렌더링
578
+
579
+ React.useEffect(function () {
580
+ if (!stageRef.current) return;
581
+ selectedItemRef.current = externalSelectedItem;
582
+ doRenderEvent();
583
+ }, [externalSelectedItem]); // 데이터 변경 시 렌더링 (캐시 정리 및 선택 상태 동기화)
584
+
585
+ React.useEffect(function () {
586
+ if (!stageRef.current) return;
587
+ dataRef.current = data;
588
+
589
+ if (containerRef.current) {
590
+ containerRef.current.style.transform = '';
591
+ }
592
+
593
+ prevCenterOffsetRef.current = null;
594
+ accumTranslateRef.current = {
595
+ x: 0,
596
+ y: 0
597
+ };
598
+ offsetCacheRef.current.clear();
599
+ boundingBoxCacheRef.current.clear();
600
+ selectedItemsMapRef.current = hooks.syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
601
+ renderAllImmediate();
602
+ }, [data]);
603
+ return reactDom.createPortal(React__default["default"].createElement("div", {
604
+ ref: containerRef,
605
+ style: {
606
+ position: 'absolute',
607
+ width: '100%',
608
+ height: '100%'
609
+ }
610
+ }), divElement);
611
+ };
612
+
613
+ Object.defineProperty(exports, 'CanvasDataType', {
614
+ enumerable: true,
615
+ get: function () { return types.CanvasDataType; }
616
+ });
617
+ exports.WoongCanvasProvider = context.WoongCanvasProvider;
618
+ exports.LRUCache = performance.LRUCache;
619
+ exports.SpatialHashGrid = performance.SpatialHashGrid;
620
+ exports["default"] = WoongCanvasMarker;
@@ -0,0 +1,3 @@
1
+ export { default as WoongCanvasMarker } from "./WoongCanvasMarker";
2
+ export * from "./WoongCanvasMarker";
3
+ export * from "../shared";
@@ -0,0 +1,61 @@
1
+ import React from "react";
2
+ import { MarkerOptions } from "../../../types";
3
+ import { CanvasData } from "../shared";
4
+ export { WoongCanvasProvider, LRUCache, SpatialHashGrid } from "../shared";
5
+ export type { CanvasOption, CanvasData, RenderUtils } from "../shared";
6
+ /**
7
+ * WoongCanvasPolygon Props
8
+ *
9
+ * @template T 폴리곤 데이터의 추가 속성 타입
10
+ */
11
+ export interface WoongCanvasPolygonProps<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
12
+ /** 렌더링할 폴리곤 데이터 배열 */
13
+ data: CanvasData<T>[];
14
+ /** 폴리곤 클릭 시 호출되는 콜백 함수 */
15
+ onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
16
+ /** 다중 선택 활성화 여부 (기본값: false) */
17
+ enableMultiSelect?: boolean;
18
+ /** 뷰포트 컬링 활성화 여부 (기본값: false) */
19
+ enableViewportCulling?: boolean;
20
+ /** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
21
+ cullingMargin?: number;
22
+ /** LRU 캐시 최대 크기 (기본값: 10000) */
23
+ maxCacheSize?: number;
24
+ /** 외부에서 제어하는 선택된 항목 배열 */
25
+ selectedItems?: CanvasData<T>[];
26
+ /** 외부에서 전달된 단일 선택 아이템 */
27
+ selectedItem?: CanvasData<T> | null;
28
+ /** 상호작용 비활성화 여부 (기본값: false) */
29
+ disableInteraction?: boolean;
30
+ /** 기본 폴리곤 채우기 색상 (필수) */
31
+ baseFillColor: string;
32
+ /** 기본 폴리곤 테두리 색상 (필수) */
33
+ baseStrokeColor: string;
34
+ /** 기본 폴리곤 테두리 두께 (필수) */
35
+ baseLineWidth: number;
36
+ /** 선택된 폴리곤 채우기 색상 */
37
+ selectedFillColor?: string;
38
+ /** 선택된 폴리곤 테두리 색상 */
39
+ selectedStrokeColor?: string;
40
+ /** 선택된 폴리곤 테두리 두께 */
41
+ selectedLineWidth?: number;
42
+ /** 마지막 선택된 폴리곤(Active) 채우기 색상 */
43
+ activeFillColor?: string;
44
+ /** 마지막 선택된 폴리곤(Active) 테두리 색상 */
45
+ activeStrokeColor?: string;
46
+ /** 마지막 선택된 폴리곤(Active) 테두리 두께 */
47
+ activeLineWidth?: number;
48
+ /** Hover 시 폴리곤 채우기 색상 */
49
+ hoveredFillColor?: string;
50
+ /** Hover 시 폴리곤 테두리 색상 */
51
+ hoveredStrokeColor?: string;
52
+ /** Hover 시 폴리곤 테두리 두께 */
53
+ hoveredLineWidth?: number;
54
+ }
55
+ declare const WoongCanvasPolygon: <T>(props: WoongCanvasPolygonProps<T>) => React.ReactPortal;
56
+ /**
57
+ * WoongCanvasPolygon - Konva 기반 고성능 폴리곤 렌더링 컴포넌트
58
+ *
59
+ * @template T 폴리곤 데이터의 추가 속성 타입
60
+ */
61
+ export default WoongCanvasPolygon;