@mint-ui/map 1.2.0-test.8 → 1.2.0

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 (60) hide show
  1. package/.eslintrc.js +11 -4
  2. package/.vscode/settings.json +32 -9
  3. package/dist/components/mint-map/core/MintMapController.d.ts +1 -0
  4. package/dist/components/mint-map/core/MintMapCore.js +5 -6
  5. package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.d.ts +12 -0
  6. package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/CanvasMarkerLayer.js +962 -0
  7. package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/index.d.ts +4 -0
  8. package/dist/components/mint-map/core/advanced/CanvasMarkerLayer/types.d.ts +280 -0
  9. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.d.ts +17 -0
  10. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/CanvasPolygonLayer.js +624 -0
  11. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/index.d.ts +4 -0
  12. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.d.ts +303 -0
  13. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/renderer.js +1091 -0
  14. package/dist/components/mint-map/core/advanced/CanvasPolygonLayer/types.d.ts +284 -0
  15. package/dist/components/mint-map/core/advanced/canvas/CanvasMarker.d.ts +7 -0
  16. package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerClaude.js +7 -7
  17. package/dist/components/mint-map/core/advanced/canvas/index.d.ts +0 -1
  18. package/dist/components/mint-map/core/advanced/index.d.ts +4 -2
  19. package/dist/components/mint-map/core/advanced/shared/context.d.ts +44 -0
  20. package/dist/components/mint-map/core/advanced/shared/context.js +230 -0
  21. package/dist/components/mint-map/core/advanced/shared/helpers.d.ts +20 -0
  22. package/dist/components/mint-map/core/advanced/shared/helpers.js +41 -0
  23. package/dist/components/mint-map/core/advanced/shared/hooks.d.ts +74 -0
  24. package/dist/components/mint-map/core/advanced/shared/hooks.js +196 -0
  25. package/dist/components/mint-map/core/advanced/{woongCanvas/shared → shared}/index.d.ts +5 -2
  26. package/dist/components/mint-map/core/advanced/shared/performance.d.ts +82 -0
  27. package/dist/components/mint-map/core/advanced/shared/performance.js +288 -0
  28. package/dist/components/mint-map/core/advanced/shared/types.d.ts +150 -0
  29. package/dist/components/mint-map/core/advanced/shared/types.js +31 -0
  30. package/dist/components/mint-map/core/advanced/shared/utils.d.ts +173 -0
  31. package/dist/components/mint-map/core/advanced/shared/utils.js +382 -0
  32. package/dist/components/mint-map/core/advanced/shared/viewport.d.ts +42 -0
  33. package/dist/components/mint-map/core/advanced/shared/viewport.js +52 -0
  34. package/dist/components/mint-map/core/wrapper/MapMarkerWrapper.js +22 -1
  35. package/dist/components/mint-map/google/GoogleMintMapController.d.ts +1 -0
  36. package/dist/components/mint-map/google/GoogleMintMapController.js +13 -8
  37. package/dist/components/mint-map/kakao/KakaoMintMapController.d.ts +1 -0
  38. package/dist/components/mint-map/kakao/KakaoMintMapController.js +13 -8
  39. package/dist/components/mint-map/naver/NaverMintMapController.d.ts +3 -0
  40. package/dist/components/mint-map/naver/NaverMintMapController.js +46 -11
  41. package/dist/index.es.js +5605 -4056
  42. package/dist/index.js +47 -27
  43. package/dist/index.umd.js +5621 -4059
  44. package/package.json +1 -1
  45. package/CLAUDE.md +0 -100
  46. package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerHanquf.d.ts +0 -22
  47. package/dist/components/mint-map/core/advanced/canvas/CanvasMarkerHanquf.js +0 -413
  48. package/dist/components/mint-map/core/advanced/woongCanvas/ClusterMarker.d.ts +0 -11
  49. package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.d.ts +0 -53
  50. package/dist/components/mint-map/core/advanced/woongCanvas/WoongKonvaMarker.js +0 -1123
  51. package/dist/components/mint-map/core/advanced/woongCanvas/index.d.ts +0 -3
  52. package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.d.ts +0 -31
  53. package/dist/components/mint-map/core/advanced/woongCanvas/shared/context.js +0 -164
  54. package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.d.ts +0 -161
  55. package/dist/components/mint-map/core/advanced/woongCanvas/shared/performance.js +0 -343
  56. package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.d.ts +0 -131
  57. package/dist/components/mint-map/core/advanced/woongCanvas/shared/types.js +0 -14
  58. package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.d.ts +0 -31
  59. package/dist/components/mint-map/core/advanced/woongCanvas/shared/utils.js +0 -164
  60. package/dist/components/mint-map/core/util/geohash.js +0 -125
@@ -0,0 +1,284 @@
1
+ import type React from 'react';
2
+ import type { MarkerOptions, Offset } from '../../../types';
3
+ import type { CanvasData } from '../shared';
4
+ /**
5
+ * 폴리곤 스타일 정의
6
+ */
7
+ export interface PolygonStyle {
8
+ /** 채우기 색상 */
9
+ fillColor: string;
10
+ /** 테두리 색상 */
11
+ strokeColor: string;
12
+ /** 테두리 두께 */
13
+ lineWidth: number;
14
+ }
15
+ /**
16
+ * 폴리곤 스타일 컨텍스트 (선택/호버/활성 상태 정보)
17
+ */
18
+ export interface PolygonStyleContext {
19
+ /** 선택 여부 */
20
+ isSelected: boolean;
21
+ /** 호버 여부 */
22
+ isHovered: boolean;
23
+ /** 활성 여부 (마지막 선택된 항목) */
24
+ isActive: boolean;
25
+ }
26
+ /**
27
+ * 폴리곤 스타일 객체
28
+ *
29
+ * 상태별 스타일을 정의합니다. 개별 props 방식과 동일한 알고리즘으로 적용됩니다.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * renderStyle={{
34
+ * base: { fillColor: 'gray', strokeColor: 'black', lineWidth: 2 },
35
+ * selected: { fillColor: 'green', strokeColor: 'darkgreen', lineWidth: 4 },
36
+ * active: { fillColor: 'yellow', strokeColor: 'orange', lineWidth: 5 },
37
+ * hovered: { fillColor: 'blue', strokeColor: 'darkblue', lineWidth: 3 }
38
+ * }}
39
+ * ```
40
+ */
41
+ export interface PolygonStyleObject {
42
+ /** 기본 폴리곤 스타일 (필수) */
43
+ base: PolygonStyle;
44
+ /** 선택된 폴리곤 스타일 */
45
+ selected?: PolygonStyle;
46
+ /** 활성 폴리곤 스타일 (마지막 선택된 항목) */
47
+ active?: PolygonStyle;
48
+ /** 호버된 폴리곤 스타일 */
49
+ hovered?: PolygonStyle;
50
+ }
51
+ /**
52
+ * 폴리곤 스타일 커스터마이징 함수 타입
53
+ *
54
+ * item 데이터와 상태 정보를 기반으로 자유롭게 스타일을 커스터마이징할 수 있습니다.
55
+ * 스타일을 반환하지 않거나 null/undefined를 반환하면 해당 폴리곤을 그리지 않습니다.
56
+ *
57
+ * @param item 폴리곤 데이터
58
+ * @param context 선택/호버/활성 상태 정보
59
+ * @returns 커스터마이징된 폴리곤 스타일 (반환하지 않거나 null/undefined면 그리지 않음)
60
+ */
61
+ export declare type PolygonStyleCustomizer<T> = (item: CanvasData<T>, context: PolygonStyleContext) => PolygonStyle | null | undefined;
62
+ /**
63
+ * 폴리곤 스타일 커스터마이징 객체 타입
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // 예시 1: deps 있음 (외부 상태를 참조하는 경우)
68
+ * <CanvasPolygonLayer
69
+ * customStyle={{
70
+ * callback: (item, context) => {
71
+ * // 상태 정보를 기반으로 스타일 결정
72
+ * if (context.isActive) {
73
+ * return { fillColor: 'yellow', strokeColor: 'orange', lineWidth: 5 };
74
+ * }
75
+ * if (context.isHovered) {
76
+ * return { fillColor: 'blue', strokeColor: 'darkblue', lineWidth: 3 };
77
+ * }
78
+ * if (context.isSelected) {
79
+ * return { fillColor: 'green', strokeColor: 'darkgreen', lineWidth: 4 };
80
+ * }
81
+ * return null;
82
+ * },
83
+ * deps: [selectedPolygon] // 외부 상태 변경 시 자동 재렌더링
84
+ * }}
85
+ * />
86
+ *
87
+ * // 예시 2: deps 없음 (외부 상태를 참조하지 않는 경우)
88
+ * <CanvasPolygonLayer
89
+ * customStyle={{
90
+ * callback: (item, context) => {
91
+ * if (item.area > 1000) {
92
+ * return { fillColor: 'red', strokeColor: 'darkred', lineWidth: 2 };
93
+ * }
94
+ * return null;
95
+ * }
96
+ * }}
97
+ * />
98
+ * ```
99
+ */
100
+ export interface PolygonStyleCustomizerWithDeps<T> {
101
+ /** 스타일 커스터마이징 콜백 함수 (필수) */
102
+ callback: PolygonStyleCustomizer<T>;
103
+ /** 외부 상태 의존성 배열 (선택, 변경 시 Canvas 재렌더링) */
104
+ deps?: React.DependencyList;
105
+ }
106
+ /**
107
+ * 공통 Props (모든 방식 공통)
108
+ */
109
+ export interface CanvasPolygonLayerBaseProps<T> extends Pick<MarkerOptions, 'zIndex' | 'anchor' | 'visible'> {
110
+ /** 렌더링할 폴리곤 데이터 배열 */
111
+ data: CanvasData<T>[];
112
+ /** 폴리곤 클릭 시 호출되는 콜백 함수 */
113
+ onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
114
+ /** 다중 선택 활성화 여부 (기본값: false) */
115
+ enableMultiSelect?: boolean;
116
+ /** 뷰포트 컬링 여유 공간 (픽셀 단위, 기본값: 100) */
117
+ cullingMargin?: number;
118
+ /** Queue 캐시 최대 크기 (기본값: 30000) */
119
+ maxCacheSize?: number;
120
+ /** 외부에서 제어하는 선택된 항목 배열 */
121
+ selectedItems?: CanvasData<T>[];
122
+ /** 외부에서 전달된 단일 선택 아이템 */
123
+ selectedItem?: CanvasData<T> | null;
124
+ /** 상호작용 비활성화 여부 (기본값: false) */
125
+ disableInteraction?: boolean;
126
+ /** 최적화 데이터 콜백 (디버깅/모니터링용) */
127
+ onOptimizationDataUpdate?: (data: {
128
+ cacheSize: number;
129
+ cacheEntries: Array<[string, number[][][][] | Offset]>;
130
+ spatialGridCells: Map<string, CanvasData<T>[]>;
131
+ }) => void;
132
+ }
133
+ /**
134
+ * 개별 Props 방식 (기존 방식)
135
+ *
136
+ * baseFillColor, baseStrokeColor, baseLineWidth가 있으면 자동으로 개별 props 방식으로 인식됩니다.
137
+ */
138
+ export interface CanvasPolygonLayerPropsWithIndividualStyles<T> extends CanvasPolygonLayerBaseProps<T> {
139
+ /** 기본 폴리곤 채우기 색상 (필수) */
140
+ baseFillColor: string;
141
+ /** 기본 폴리곤 테두리 색상 (필수) */
142
+ baseStrokeColor: string;
143
+ /** 기본 폴리곤 테두리 두께 (필수) */
144
+ baseLineWidth: number;
145
+ /** 선택된 폴리곤 채우기 색상 */
146
+ selectedFillColor?: string;
147
+ /** 선택된 폴리곤 테두리 색상 */
148
+ selectedStrokeColor?: string;
149
+ /** 선택된 폴리곤 테두리 두께 */
150
+ selectedLineWidth?: number;
151
+ /** 마지막 선택된 폴리곤(Active) 채우기 색상 */
152
+ activeFillColor?: string;
153
+ /** 마지막 선택된 폴리곤(Active) 테두리 색상 */
154
+ activeStrokeColor?: string;
155
+ /** 마지막 선택된 폴리곤(Active) 테두리 두께 */
156
+ activeLineWidth?: number;
157
+ /** Hover 시 폴리곤 채우기 색상 */
158
+ hoveredFillColor?: string;
159
+ /** Hover 시 폴리곤 테두리 색상 */
160
+ hoveredStrokeColor?: string;
161
+ /** Hover 시 폴리곤 테두리 두께 */
162
+ hoveredLineWidth?: number;
163
+ /** 다른 방식 props는 사용 불가 */
164
+ renderStyle?: never;
165
+ /**
166
+ * 폴리곤 스타일 커스터마이징 객체 (선택)
167
+ *
168
+ * customStyle이 제공되면 우선적으로 사용되며, null/undefined를 반환하면 개별 props로 정의된 기본 스타일을 사용합니다.
169
+ * item 데이터와 상태 정보를 기반으로 자유롭게 스타일을 커스터마이징할 수 있습니다.
170
+ */
171
+ customStyle?: PolygonStyleCustomizerWithDeps<T>;
172
+ }
173
+ /**
174
+ * 객체 Props 방식
175
+ *
176
+ * renderStyle 객체가 있으면 자동으로 객체 방식으로 인식됩니다.
177
+ * 상태별 스타일을 정의하면 개별 props 방식과 동일한 알고리즘으로 적용됩니다.
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * renderStyle={{
182
+ * base: { fillColor: 'gray', strokeColor: 'black', lineWidth: 2 },
183
+ * selected: { fillColor: 'green', strokeColor: 'darkgreen', lineWidth: 4 },
184
+ * active: { fillColor: 'yellow', strokeColor: 'orange', lineWidth: 5 },
185
+ * hovered: { fillColor: 'blue', strokeColor: 'darkblue', lineWidth: 3 }
186
+ * }}
187
+ * ```
188
+ */
189
+ export interface CanvasPolygonLayerPropsWithObjectStyle<T> extends CanvasPolygonLayerBaseProps<T> {
190
+ /**
191
+ * 폴리곤 스타일 객체
192
+ *
193
+ * 상태별 스타일을 정의합니다. 개별 props 방식과 동일한 알고리즘으로 적용됩니다.
194
+ */
195
+ renderStyle: PolygonStyleObject;
196
+ /** 다른 방식 props는 사용 불가 */
197
+ activeFillColor?: never;
198
+ activeLineWidth?: never;
199
+ activeStrokeColor?: never;
200
+ baseFillColor?: never;
201
+ baseLineWidth?: never;
202
+ baseStrokeColor?: never;
203
+ hoveredFillColor?: never;
204
+ hoveredLineWidth?: never;
205
+ hoveredStrokeColor?: never;
206
+ selectedFillColor?: never;
207
+ selectedLineWidth?: never;
208
+ selectedStrokeColor?: never;
209
+ /**
210
+ * 폴리곤 스타일 커스터마이징 객체 (선택)
211
+ *
212
+ * customStyle이 제공되면 우선적으로 사용되며, null/undefined를 반환하면 renderStyle로 정의된 기본 스타일을 사용합니다.
213
+ * item 데이터와 상태 정보를 기반으로 자유롭게 스타일을 커스터마이징할 수 있습니다.
214
+ */
215
+ customStyle?: PolygonStyleCustomizerWithDeps<T>;
216
+ }
217
+ /**
218
+ * 함수 Props 방식 (커스터마이징 방식)
219
+ *
220
+ * customStyle 함수가 있으면 자동으로 함수 방식으로 인식됩니다.
221
+ * item 데이터와 상태 정보를 기반으로 자유롭게 스타일을 커스터마이징할 수 있습니다.
222
+ * 스타일을 반환하지 않거나 null/undefined를 반환하면 해당 폴리곤을 그리지 않습니다.
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * customStyle={(item, context) => {
227
+ * // item의 속성에 따라 동적으로 스타일 결정
228
+ * if (item.someProperty > 100) {
229
+ * return { fillColor: 'red', strokeColor: 'darkred', lineWidth: 3 };
230
+ * }
231
+ *
232
+ * // 상태 정보를 기반으로 스타일 결정
233
+ * if (context.isActive) {
234
+ * return { fillColor: 'yellow', strokeColor: 'orange', lineWidth: 5 };
235
+ * }
236
+ * if (context.isHovered) {
237
+ * return { fillColor: 'blue', strokeColor: 'darkblue', lineWidth: 3 };
238
+ * }
239
+ * if (context.isSelected) {
240
+ * return { fillColor: 'green', strokeColor: 'darkgreen', lineWidth: 4 };
241
+ * }
242
+ *
243
+ * // 아무것도 반환하지 않으면 그리지 않음 (return null 또는 return undefined도 가능)
244
+ * }}
245
+ * ```
246
+ */
247
+ export interface CanvasPolygonLayerPropsWithCustomStyle<T> extends CanvasPolygonLayerBaseProps<T> {
248
+ /**
249
+ * 폴리곤 스타일 커스터마이징 객체
250
+ *
251
+ * item 데이터와 상태 정보를 기반으로 자유롭게 스타일을 커스터마이징할 수 있습니다.
252
+ * 스타일을 반환하지 않거나 null/undefined를 반환하면 해당 폴리곤을 그리지 않습니다.
253
+ */
254
+ customStyle: PolygonStyleCustomizerWithDeps<T>;
255
+ /** 다른 방식 props는 사용 불가 */
256
+ activeFillColor?: never;
257
+ activeLineWidth?: never;
258
+ activeStrokeColor?: never;
259
+ baseFillColor?: never;
260
+ baseLineWidth?: never;
261
+ baseStrokeColor?: never;
262
+ hoveredFillColor?: never;
263
+ hoveredLineWidth?: never;
264
+ hoveredStrokeColor?: never;
265
+ renderStyle?: never;
266
+ selectedFillColor?: never;
267
+ selectedLineWidth?: never;
268
+ selectedStrokeColor?: never;
269
+ }
270
+ /**
271
+ * CanvasPolygonLayer Props (Discriminated Union)
272
+ *
273
+ * 세 가지 스타일 지정 방식을 지원:
274
+ * 1. 개별 props 방식: baseFillColor, baseStrokeColor, baseLineWidth가 있으면 자동으로 개별 props 방식
275
+ * 2. 객체 방식: renderStyle 객체가 있으면 자동으로 객체 방식
276
+ * 3. 함수 방식: customStyle 함수가 있으면 자동으로 함수 방식
277
+ *
278
+ * customStyle은 개별 props 방식 또는 renderStyle 객체 방식과 함께 사용할 수 있습니다.
279
+ * customStyle이 제공되면 우선적으로 사용되며, null/undefined를 반환하면 기본 스타일을 사용합니다.
280
+ * styleMode prop은 필요 없으며, 각 prop의 존재 여부로 자동 판단됩니다.
281
+ *
282
+ * @template T 폴리곤 데이터의 추가 속성 타입
283
+ */
284
+ export declare type CanvasPolygonLayerProps<T> = CanvasPolygonLayerPropsWithIndividualStyles<T> | CanvasPolygonLayerPropsWithObjectStyle<T> | CanvasPolygonLayerPropsWithCustomStyle<T>;
@@ -1,5 +1,12 @@
1
1
  import React from "react";
2
2
  import { MarkerOptions, Offset, Position } from "../../../types";
3
+ /**
4
+ * 2026-01-06 장한별
5
+ * 고주영팀장님이 만든 캔버스 마커
6
+ * 클릭, hover 등의 이벤트가 구현되어있지 않는 버전
7
+ * RA 지도 제품에서 CanvasMarker 컴포넌트를 사용하고 있음
8
+ *
9
+ */
3
10
  export interface CanvasMarkerRendererParams<T> {
4
11
  context: CanvasRenderingContext2D;
5
12
  offset: Offset[];
@@ -107,12 +107,12 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
107
107
  var hoveredPolygonRef = React.useRef(null);
108
108
  var clickedPolygonRef = React.useRef(null);
109
109
  var hoveredMarkerRef = React.useRef(null);
110
- var clickedMarkerRef = React.useRef(null); // 🚀 WoongCanvasMarker 방식: 단순한 data ref (geohash 제거)
110
+ var clickedMarkerRef = React.useRef(null); // 🚀 CanvasMarker 방식: 단순한 data ref (geohash 제거)
111
111
 
112
112
  var polygonsRef = React.useRef([]);
113
113
  var markersRef = React.useRef([]); // 마커 경계 정보 저장 (hit-test용)
114
114
 
115
- var markerBoundsRef = React.useRef(new Map()); // 🚀 드래그 추적용 (WoongCanvasMarker 방식)
115
+ var markerBoundsRef = React.useRef(new Map()); // 🚀 드래그 추적용 (CanvasMarker 방식)
116
116
 
117
117
  var draggingRef = React.useRef(false);
118
118
  var prevCenterOffsetRef = React.useRef(null);
@@ -172,7 +172,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
172
172
  if (!baseContextRef.current || !polygonsRef.current || polygonsRef.current.length === 0) return;
173
173
  canvasUtil.clearRect(baseCanvasRef.current, baseContextRef.current);
174
174
  var cacheMissCount = 0; // 캐시 미스 카운트
175
- // 🚀 WoongCanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
175
+ // 🚀 CanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
176
176
 
177
177
  polygonsRef.current.forEach(function (polygon) {
178
178
  if (polygon.visible === false) return; // 🚀 캐시 확인 (ID 기반으로 변경)
@@ -243,7 +243,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
243
243
  if (!markersRef.current || markersRef.current.length === 0) return;
244
244
  canvasUtil.clearRect(baseMarkerCanvasRef.current, baseMarkerContextRef.current); // 마커 경계 정보 초기화
245
245
 
246
- markerBoundsRef.current.clear(); // 🚀 WoongCanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
246
+ markerBoundsRef.current.clear(); // 🚀 CanvasMarker 방식: 전체 데이터 순회 (필터링 제거)
247
247
 
248
248
  markersRef.current.forEach(function (marker) {
249
249
  var _a, _b;
@@ -566,7 +566,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
566
566
  }
567
567
 
568
568
  return null;
569
- }; // IDLE 이벤트 핸들러 (WoongCanvasMarker 최적화 적용)
569
+ }; // IDLE 이벤트 핸들러 (CanvasMarker 최적화 적용)
570
570
 
571
571
 
572
572
  var handleIdle = function () {
@@ -632,7 +632,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
632
632
  x: event.clientX - rect.left,
633
633
  y: event.clientY - rect.top
634
634
  };
635
- }; // 🚀 지도 클릭 이벤트 핸들러 (WoongCanvasMarker 방식 - controller.addEventListener)
635
+ }; // 🚀 지도 클릭 이벤트 핸들러 (CanvasMarker 방식 - controller.addEventListener)
636
636
 
637
637
 
638
638
  var handleMapClick = function (event) {
@@ -724,7 +724,7 @@ var CanvasMarkerClaude = React__default["default"].memo(function CanvasMarkerCla
724
724
  var rafIdRef = React.useRef(); // 마우스 이벤트 핸들러 (requestAnimationFrame으로 최적화)
725
725
 
726
726
  var handleMouseMove = function (e) {
727
- // 🚀 드래그 중이면 호버 처리 스킵 (WoongCanvasMarker 방식)
727
+ // 🚀 드래그 중이면 호버 처리 스킵 (CanvasMarker 방식)
728
728
  if (draggingRef.current) return; // 이미 RAF가 대기 중이면 스킵
729
729
 
730
730
  if (rafIdRef.current) return;
@@ -1,3 +1,2 @@
1
1
  export * from './CanvasMarker';
2
- export * from './CanvasMarkerHanquf';
3
2
  export * from './CanvasMarkerClaude';
@@ -1,5 +1,7 @@
1
- export * from './shapes';
2
1
  export * from './canvas';
2
+ export * from './CanvasMarkerLayer';
3
+ export * from './CanvasPolygonLayer';
3
4
  export * from './MapBuildingProjection';
4
5
  export * from './MapLoadingComponents';
5
- export * from './woongCanvas';
6
+ export * from './shapes';
7
+ export * from './shared';
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { QueueCache } from './performance';
3
+ import { CanvasData } from './types';
4
+ import { Offset } from '../../../types';
5
+ /**
6
+ * Canvas 컴포넌트 인스턴스 인터페이스
7
+ *
8
+ * @template T 마커/폴리곤 데이터의 추가 속성 타입
9
+ */
10
+ export interface ComponentInstance<T> {
11
+ zIndex: number;
12
+ hitTest: (offset: Offset) => boolean;
13
+ onClick?: (payload: CanvasData<T>, selectedIds: Set<string>) => void;
14
+ onMouseOver?: (payload: CanvasData<T>) => void;
15
+ onMouseOut?: (payload: CanvasData<T>) => void;
16
+ findData: (offset: Offset) => CanvasData<T> | null;
17
+ setHovered: (data: CanvasData<T> | null) => void;
18
+ handleLocalClick: (data: CanvasData<T>) => void;
19
+ getSelectedIds: () => Set<string>;
20
+ isInteractionDisabled: () => boolean;
21
+ }
22
+ interface CanvasContextValue {
23
+ registerComponent: <T>(instance: ComponentInstance<T>) => void;
24
+ unregisterComponent: <T>(instance: ComponentInstance<T>) => void;
25
+ sharedMarkerCache: QueueCache<string, Offset>;
26
+ sharedPolygonCache: QueueCache<string, number[][][][]>;
27
+ }
28
+ /**
29
+ * CanvasProvider 컴포넌트
30
+ *
31
+ * 다중 Canvas 인스턴스를 관리하고 zIndex 기반 이벤트 우선순위를 처리합니다.
32
+ */
33
+ export declare const CanvasProvider: React.FC<{
34
+ children: React.ReactNode;
35
+ markerMaxCacheSize?: number;
36
+ polygonMaxCacheSize?: number;
37
+ }>;
38
+ /**
39
+ * Canvas Context Hook
40
+ *
41
+ * @returns CanvasContextValue 또는 null (Provider 없으면)
42
+ */
43
+ export declare const useCanvasContext: () => CanvasContextValue | null;
44
+ export {};
@@ -0,0 +1,230 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var React = require('react');
6
+ var performance = require('./performance.js');
7
+ var MintMapProvider = require('../../provider/MintMapProvider.js');
8
+
9
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
12
+
13
+ var CanvasContext = React.createContext(null);
14
+ /**
15
+ * CanvasProvider 컴포넌트
16
+ *
17
+ * 다중 Canvas 인스턴스를 관리하고 zIndex 기반 이벤트 우선순위를 처리합니다.
18
+ */
19
+
20
+ /* eslint-disable no-restricted-syntax */
21
+
22
+ /* eslint-disable no-continue */
23
+
24
+ var CanvasProvider = function (_a) {
25
+ var children = _a.children,
26
+ _b = _a.markerMaxCacheSize,
27
+ markerMaxCacheSize = _b === void 0 ? 5000 : _b,
28
+ _c = _a.polygonMaxCacheSize,
29
+ polygonMaxCacheSize = _c === void 0 ? 30000 : _c;
30
+ var controller = MintMapProvider.useMintMapController(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+
32
+ var componentsRef = React.useRef([]); // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+
34
+ var currentHoveredRef = React.useRef(null); // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+
36
+ var currentHoveredDataRef = React.useRef(null);
37
+ var draggingRef = React.useRef(false); // 공유 캐시 (모든 레이어가 공유)
38
+
39
+ var sharedMarkerCacheRef = React.useRef(new performance.QueueCache(markerMaxCacheSize));
40
+ var sharedPolygonCacheRef = React.useRef(new performance.QueueCache(polygonMaxCacheSize)); // 컴포넌트 등록 (zIndex 내림차순 정렬)
41
+
42
+ var registerComponent = React.useCallback(function (instance) {
43
+ componentsRef.current.push(instance);
44
+ componentsRef.current.sort(function (a, b) {
45
+ return b.zIndex - a.zIndex;
46
+ });
47
+ }, []); // 컴포넌트 등록 해제
48
+
49
+ var unregisterComponent = React.useCallback(function (instance) {
50
+ if (currentHoveredRef.current === instance) {
51
+ currentHoveredRef.current = null;
52
+ currentHoveredDataRef.current = null;
53
+ }
54
+
55
+ componentsRef.current = componentsRef.current.filter(function (c) {
56
+ return c !== instance;
57
+ });
58
+ }, []); // 전역 클릭 핸들러 (zIndex 우선순위)
59
+
60
+ var handleGlobalClick = React.useCallback(function (event) {
61
+ var _a, _b;
62
+
63
+ try {
64
+ if (!((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
65
+ var clickedOffset = void 0;
66
+
67
+ try {
68
+ clickedOffset = controller.positionToOffset(event.param.position);
69
+ } catch (error) {
70
+ // positionToOffset 실패 시 조용히 종료 (기존 동작 보장)
71
+ console.warn('[CanvasProvider] positionToOffset failed:', error);
72
+ return;
73
+ } // zIndex 내림차순으로 정렬된 컴포넌트 순회 (높은 zIndex가 먼저 처리)
74
+
75
+
76
+ for (var _i = 0, _c = componentsRef.current; _i < _c.length; _i++) {
77
+ var component = _c[_i];
78
+
79
+ try {
80
+ if (component.isInteractionDisabled()) continue;
81
+ var data = component.findData(clickedOffset);
82
+ if (!data) continue; // 첫 번째로 찾은 항목만 처리하고 종료 (zIndex 우선순위)
83
+
84
+ component.handleLocalClick(data);
85
+ (_b = component.onClick) === null || _b === void 0 ? void 0 : _b.call(component, data, component.getSelectedIds());
86
+ return;
87
+ } catch (error) {
88
+ // 개별 컴포넌트 처리 중 에러 발생 시 다음 컴포넌트로 계속 진행
89
+ console.warn('[CanvasProvider] Component click handler error:', error);
90
+ continue;
91
+ }
92
+ }
93
+ } catch (error) {
94
+ // 전체 핸들러 에러 시 조용히 종료 (앱 크래시 방지)
95
+ console.error('[CanvasProvider] handleGlobalClick error:', error);
96
+ }
97
+ }, [controller]); // 전역 마우스 이동 핸들러 (zIndex 우선순위)
98
+
99
+ var handleGlobalMouseMove = React.useCallback(function (event) {
100
+ var _a;
101
+
102
+ try {
103
+ if (draggingRef.current || !((_a = event === null || event === void 0 ? void 0 : event.param) === null || _a === void 0 ? void 0 : _a.position)) return;
104
+ var mouseOffset = void 0;
105
+
106
+ try {
107
+ mouseOffset = controller.positionToOffset(event.param.position);
108
+ } catch (error) {
109
+ // positionToOffset 실패 시 조용히 종료 (기존 동작 보장)
110
+ console.warn('[CanvasProvider] positionToOffset failed:', error);
111
+ return;
112
+ } // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+
114
+
115
+ var newHoveredComponent = null; // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+
117
+ var newHoveredData = null; // zIndex 내림차순으로 정렬된 컴포넌트 순회 (높은 zIndex가 먼저 처리)
118
+
119
+ for (var _i = 0, _b = componentsRef.current; _i < _b.length; _i++) {
120
+ var component = _b[_i];
121
+
122
+ try {
123
+ if (component.isInteractionDisabled()) continue;
124
+ var data = component.findData(mouseOffset);
125
+ if (!data) continue; // 첫 번째로 찾은 항목만 hover 처리 (zIndex 우선순위)
126
+
127
+ newHoveredComponent = component;
128
+ newHoveredData = data;
129
+ break;
130
+ } catch (error) {
131
+ // 개별 컴포넌트 처리 중 에러 발생 시 다음 컴포넌트로 계속 진행
132
+ console.warn('[CanvasProvider] Component mouse move handler error:', error);
133
+ continue;
134
+ }
135
+ } // hover 상태가 변경되지 않았으면 종료 (불필요한 렌더링 방지)
136
+
137
+
138
+ if (currentHoveredRef.current === newHoveredComponent && currentHoveredDataRef.current === newHoveredData) {
139
+ return;
140
+ } // 기존 hover 항목에 mouseOut 이벤트 발생
141
+
142
+
143
+ if (currentHoveredRef.current) {
144
+ try {
145
+ currentHoveredRef.current.setHovered(null);
146
+
147
+ if (currentHoveredRef.current.onMouseOut && currentHoveredDataRef.current) {
148
+ currentHoveredRef.current.onMouseOut(currentHoveredDataRef.current);
149
+ }
150
+ } catch (error) {
151
+ // mouseOut 이벤트 에러 시 조용히 처리 (기존 동작 보장)
152
+ console.warn('[CanvasProvider] mouseOut handler error:', error);
153
+ }
154
+ } // 새 hover 항목에 mouseOver 이벤트 발생
155
+
156
+
157
+ if (newHoveredComponent && newHoveredData) {
158
+ try {
159
+ newHoveredComponent.setHovered(newHoveredData);
160
+
161
+ if (newHoveredComponent.onMouseOver) {
162
+ newHoveredComponent.onMouseOver(newHoveredData);
163
+ }
164
+ } catch (error) {
165
+ // mouseOver 이벤트 에러 시 조용히 처리 (기존 동작 보장)
166
+ console.warn('[CanvasProvider] mouseOver handler error:', error);
167
+ }
168
+ }
169
+
170
+ currentHoveredRef.current = newHoveredComponent;
171
+ currentHoveredDataRef.current = newHoveredData;
172
+ } catch (error) {
173
+ // 전체 핸들러 에러 시 조용히 종료 (앱 크래시 방지)
174
+ console.error('[CanvasProvider] handleGlobalMouseMove error:', error);
175
+ }
176
+ }, [controller]);
177
+ var handleZoomStart = React.useCallback(function () {
178
+ draggingRef.current = true;
179
+ }, []);
180
+ var handleIdle = React.useCallback(function () {
181
+ draggingRef.current = false;
182
+ }, []);
183
+ React.useEffect(function () {
184
+ try {
185
+ controller.addEventListener('CLICK', handleGlobalClick);
186
+ controller.addEventListener('MOUSEMOVE', handleGlobalMouseMove);
187
+ controller.addEventListener('ZOOMSTART', handleZoomStart);
188
+ controller.addEventListener('IDLE', handleIdle);
189
+ } catch (error) {
190
+ // 이벤트 리스너 등록 실패 시 경고만 출력 (기존 동작 보장)
191
+ console.warn('[CanvasProvider] Failed to add event listeners:', error);
192
+ }
193
+
194
+ return function () {
195
+ try {
196
+ controller.removeEventListener('CLICK', handleGlobalClick);
197
+ controller.removeEventListener('MOUSEMOVE', handleGlobalMouseMove);
198
+ controller.removeEventListener('ZOOMSTART', handleZoomStart);
199
+ controller.removeEventListener('IDLE', handleIdle);
200
+ } catch (error) {
201
+ // cleanup 중 에러 발생 시 조용히 처리 (controller가 이미 destroy된 경우 등)
202
+ // 에러를 무시해도 메모리 누수는 발생하지 않음 (이벤트 리스너는 자동으로 정리됨)
203
+ console.warn('[CanvasProvider] Failed to remove event listeners:', error);
204
+ }
205
+ };
206
+ }, [controller, handleGlobalClick, handleGlobalMouseMove, handleZoomStart, handleIdle]);
207
+ var contextValue = React.useMemo(function () {
208
+ return {
209
+ registerComponent: registerComponent,
210
+ sharedMarkerCache: sharedMarkerCacheRef.current,
211
+ sharedPolygonCache: sharedPolygonCacheRef.current,
212
+ unregisterComponent: unregisterComponent
213
+ };
214
+ }, [registerComponent, unregisterComponent]);
215
+ return React__default["default"].createElement(CanvasContext.Provider, {
216
+ value: contextValue
217
+ }, children);
218
+ };
219
+ /**
220
+ * Canvas Context Hook
221
+ *
222
+ * @returns CanvasContextValue 또는 null (Provider 없으면)
223
+ */
224
+
225
+ var useCanvasContext = function () {
226
+ return React.useContext(CanvasContext);
227
+ };
228
+
229
+ exports.CanvasProvider = CanvasProvider;
230
+ exports.useCanvasContext = useCanvasContext;
@@ -0,0 +1,20 @@
1
+ import type { Offset } from '../../../types';
2
+ import { EventParam, MapUIEventParam } from '../../../types';
3
+ import type { MintMapController } from '../../MintMapController';
4
+ /**
5
+ * 이벤트 유효성 검증 및 좌표 변환
6
+ *
7
+ * @param event 이벤트 파라미터
8
+ * @param context CanvasContext 인스턴스
9
+ * @param controller MintMapController 인스턴스
10
+ * @returns 유효한 화면 좌표 또는 null
11
+ */
12
+ export declare const validateEvent: (event: EventParam<MapUIEventParam> | null | undefined, context: any, controller: MintMapController) => Offset | null;
13
+ /**
14
+ * Map의 values를 배열로 변환
15
+ *
16
+ * @template T Map 값의 타입
17
+ * @param map 변환할 Map
18
+ * @returns Map의 값 배열
19
+ */
20
+ export declare const mapValuesToArray: <T>(map: Map<string, T>) => T[];