@mint-ui/map 1.2.0-test.62 → 1.2.0-test.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -3935,28 +3935,48 @@ var CanvasMarkerClaude = React.memo(function CanvasMarkerClaude(_a) {
3935
3935
  });
3936
3936
 
3937
3937
  var CanvasMarkerLayer = function (props) {
3938
+ // 타입 가드: renderEvent가 있는지 확인
3939
+ var hasRenderEvent = 'renderEvent' in props && props.renderEvent !== undefined; // renderEvent가 있는 경우와 없는 경우를 구분하여 props 추출
3940
+
3938
3941
  var data = props.data,
3939
- onClick = props.onClick,
3940
- onMouseOver = props.onMouseOver,
3941
- onMouseOut = props.onMouseOut,
3942
- _a = props.enableMultiSelect,
3943
- enableMultiSelect = _a === void 0 ? false : _a,
3944
- _b = props.topOnHover,
3945
- topOnHover = _b === void 0 ? false : _b,
3946
- _c = props.enableViewportCulling,
3947
- enableViewportCulling = _c === void 0 ? false : _c,
3948
- _d = props.cullingMargin,
3949
- cullingMargin = _d === void 0 ? DEFAULT_CULLING_MARGIN : _d,
3950
- _e = props.maxCacheSize,
3951
- maxCacheSize = _e === void 0 ? DEFAULT_MAX_CACHE_SIZE : _e,
3952
- externalSelectedItems = props.selectedItems,
3953
- externalSelectedItem = props.selectedItem,
3954
- _f = props.disableInteraction,
3955
- disableInteraction = _f === void 0 ? false : _f,
3942
+ _a = props.enableViewportCulling,
3943
+ enableViewportCulling = _a === void 0 ? false : _a,
3944
+ _b = props.cullingMargin,
3945
+ cullingMargin = _b === void 0 ? DEFAULT_CULLING_MARGIN : _b,
3946
+ _c = props.maxCacheSize,
3947
+ maxCacheSize = _c === void 0 ? DEFAULT_MAX_CACHE_SIZE : _c,
3956
3948
  renderBase = props.renderBase,
3957
- renderEvent = props.renderEvent,
3958
- options = __rest(props, ["data", "onClick", "onMouseOver", "onMouseOut", "enableMultiSelect", "topOnHover", "enableViewportCulling", "cullingMargin", "maxCacheSize", "selectedItems", "selectedItem", "disableInteraction", "renderBase", "renderEvent"]);
3959
-
3949
+ options = __rest(props, ["data", "enableViewportCulling", "cullingMargin", "maxCacheSize", "renderBase"]); // renderEvent가 있는 경우에만 인터랙션 관련 props 추출
3950
+
3951
+
3952
+ var _d = hasRenderEvent && 'renderEvent' in props ? props : {
3953
+ disableInteraction: false,
3954
+ enableMultiSelect: false,
3955
+ onClick: undefined,
3956
+ onMouseOut: undefined,
3957
+ onMouseOver: undefined,
3958
+ renderEvent: undefined,
3959
+ selectedItem: undefined,
3960
+ selectedItems: undefined,
3961
+ topOnHover: false,
3962
+ topStageZIndex: undefined
3963
+ },
3964
+ _e = _d.disableInteraction,
3965
+ disableInteraction = _e === void 0 ? false : _e,
3966
+ _f = _d.enableMultiSelect,
3967
+ enableMultiSelect = _f === void 0 ? false : _f,
3968
+ onClick = _d.onClick,
3969
+ onMouseOut = _d.onMouseOut,
3970
+ onMouseOver = _d.onMouseOver,
3971
+ renderEvent = _d.renderEvent,
3972
+ externalSelectedItem = _d.selectedItem,
3973
+ externalSelectedItems = _d.selectedItems,
3974
+ rawTopStageZIndex = _d.topStageZIndex,
3975
+ _g = _d.topOnHover,
3976
+ topOnHover = _g === void 0 ? false : _g; // topOnHover가 false이거나 없으면 topStageZIndex를 사용하지 못하도록 제한
3977
+
3978
+
3979
+ var topStageZIndex = topOnHover && rawTopStageZIndex !== undefined ? rawTopStageZIndex : undefined;
3960
3980
  var controller = useMintMapController();
3961
3981
  var context = useCanvasContext();
3962
3982
  var currentZIndex = options.zIndex !== undefined ? options.zIndex : 0; // DOM Refs
@@ -3964,11 +3984,18 @@ var CanvasMarkerLayer = function (props) {
3964
3984
  var divRef = useRef(document.createElement('div'));
3965
3985
  var divElement = divRef.current;
3966
3986
  var containerRef = useRef(null);
3967
- var markerRef = useRef(); // Konva Refs
3987
+ var markerRef = useRef(); // Top Layer용 별도 DOM Refs (topStageZIndex가 설정된 경우에만 사용)
3988
+
3989
+ var topDivRef = useRef(document.createElement('div'));
3990
+ var topDivElement = topDivRef.current;
3991
+ var topContainerRef = useRef(null);
3992
+ var topMarkerRef = useRef(); // Konva Refs
3968
3993
 
3969
3994
  var stageRef = useRef(null);
3970
3995
  var baseLayerRef = useRef(null);
3971
- var eventLayerRef = useRef(null); // 상태 관리 Refs (React 리렌더링 최소화)
3996
+ var eventLayerRef = useRef(null);
3997
+ var topStageRef = useRef(null);
3998
+ var topLayerRef = useRef(null); // 상태 관리 Refs (React 리렌더링 최소화)
3972
3999
 
3973
4000
  var dataRef = useRef(data);
3974
4001
  var disableInteractionRef = useRef(disableInteraction);
@@ -4059,24 +4086,34 @@ var CanvasMarkerLayer = function (props) {
4059
4086
 
4060
4087
  var visibleItems = enableViewportCullingRef.current ? dataRef.current.filter(function (item) {
4061
4088
  return isInViewport$1(item);
4062
- }) : dataRef.current; // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
4089
+ }) : dataRef.current; // topStageZIndex가 설정되고 topOnHover true인 경우 hover된 항목은 Top Layer에서 처리
4090
+ // topOnHover 옵션: hover된 항목을 나중에 그려서 최상위에 표시
4063
4091
 
4064
- if (topOnHover && !renderEvent && hovered) {
4092
+ if (topStageZIndex !== undefined && topOnHover && hovered) {
4093
+ visibleItems = visibleItems.filter(function (item) {
4094
+ return item.id !== hovered.id;
4095
+ });
4096
+ } else if (topOnHover && !renderEvent && hovered) {
4065
4097
  visibleItems = visibleItems.filter(function (item) {
4066
4098
  return item.id !== hovered.id;
4067
4099
  });
4068
4100
  } // 일반 항목들 먼저 렌더링
4101
+ // topOnHover가 false이고 renderEvent가 있으면 선택된 항목도 Base Layer에서 렌더링
4102
+ // (Event Layer에서 선택된 항목을 렌더링하지 않으므로)
4103
+ // topOnHover가 true이거나 renderEvent가 없으면 선택된 항목은 Base Layer에서 스킵됨
4069
4104
 
4070
4105
 
4106
+ var baseSelectedIds = !topOnHover && renderEvent ? selectedIdsRef.current : new Set();
4071
4107
  renderBase({
4072
4108
  ctx: ctx,
4073
4109
  hoveredItem: hovered,
4074
4110
  items: visibleItems,
4075
- selectedIds: selectedIdsRef.current,
4111
+ selectedIds: baseSelectedIds,
4076
4112
  utils: renderUtils
4077
- }); // hover된 항목을 마지막에 렌더링하여 최상위에 표시
4113
+ }); // topStageZIndex가 설정된 경우 hover된 항목은 Top Layer에서 처리하므로 여기서는 스킵
4114
+ // hover된 항목을 마지막에 렌더링하여 최상위에 표시
4078
4115
 
4079
- if (topOnHover && !renderEvent && hovered) {
4116
+ if (topStageZIndex === undefined && topOnHover && !renderEvent && hovered) {
4080
4117
  if (!enableViewportCullingRef.current || isInViewport$1(hovered)) {
4081
4118
  renderBase({
4082
4119
  ctx: ctx,
@@ -4110,9 +4147,24 @@ var CanvasMarkerLayer = function (props) {
4110
4147
  sceneFunc: function (konvaContext) {
4111
4148
  var ctx = konvaContext;
4112
4149
  var selectedItems = mapValuesToArray(selectedItemsMapRef.current);
4113
- var hovered = hoveredItemRef.current;
4150
+ var hovered = hoveredItemRef.current; // topStageZIndex가 설정되고 topOnHover가 true이면 hover된 항목은 Top Layer에서 처리
4151
+ // event 레이어에서는 hover된 항목을 완전히 제외하고 선택된 항목만 렌더링
4152
+
4153
+ if (topStageZIndex !== undefined && topOnHover && hovered) {
4154
+ // hover된 항목을 제외한 선택된 항목들
4155
+ var selectedItemsWithoutHovered = selectedItems.filter(function (item) {
4156
+ return item.id !== hovered.id;
4157
+ }); // 선택된 항목만 그리기 (hover된 항목은 Top Layer에서 처리)
4114
4158
 
4115
- if (topOnHover && hovered) {
4159
+ renderEvent({
4160
+ ctx: ctx,
4161
+ hoveredItem: null,
4162
+ selectedItem: selectedItemRef.current,
4163
+ selectedItems: selectedItemsWithoutHovered,
4164
+ topOnHover: topOnHover,
4165
+ utils: renderUtils
4166
+ });
4167
+ } else if (topOnHover && hovered) {
4116
4168
  renderEvent({
4117
4169
  ctx: ctx,
4118
4170
  hoveredItem: null,
@@ -4120,6 +4172,7 @@ var CanvasMarkerLayer = function (props) {
4120
4172
  selectedItems: selectedItems.filter(function (item) {
4121
4173
  return item.id !== hovered.id;
4122
4174
  }),
4175
+ topOnHover: topOnHover,
4123
4176
  utils: renderUtils
4124
4177
  });
4125
4178
 
@@ -4133,15 +4186,25 @@ var CanvasMarkerLayer = function (props) {
4133
4186
  hoveredItem: hovered,
4134
4187
  selectedItem: selectedItemRef.current,
4135
4188
  selectedItems: hoverSelectedItems,
4189
+ topOnHover: topOnHover,
4136
4190
  utils: renderUtils
4137
4191
  });
4138
4192
  }
4139
4193
  } else {
4194
+ // topOnHover가 false일 때는 hover된 항목을 나중에 그리지 않음
4195
+ // 하지만 hover 스타일은 적용해야 하므로, hover된 항목이 selectedItems에 포함되어 있지 않으면 추가
4196
+ // renderEvent 함수에 topOnHover 정보를 전달하여,
4197
+ // renderEvent 함수 내부에서 topOnHover가 false일 때는 hover된 항목을 마지막에 그리지 않도록 함
4198
+ var hoveredIsSelected = hovered ? selectedItems.some(function (item) {
4199
+ return item.id === hovered.id;
4200
+ }) : false;
4201
+ var finalSelectedItems = hovered && !hoveredIsSelected && !topOnHover ? __spreadArray(__spreadArray([], selectedItems, true), [hovered], false) : selectedItems;
4140
4202
  renderEvent({
4141
4203
  ctx: ctx,
4142
4204
  hoveredItem: hovered,
4143
4205
  selectedItem: selectedItemRef.current,
4144
- selectedItems: selectedItems,
4206
+ selectedItems: finalSelectedItems,
4207
+ topOnHover: topOnHover,
4145
4208
  utils: renderUtils
4146
4209
  });
4147
4210
  }
@@ -4150,6 +4213,79 @@ var CanvasMarkerLayer = function (props) {
4150
4213
  layer.add(shape);
4151
4214
  }
4152
4215
 
4216
+ layer.batchDraw();
4217
+ }; // Top Layer 렌더링 (hover된 항목만, 별도 캔버스 DOM에 그리기)
4218
+
4219
+
4220
+ var doRenderTop = function () {
4221
+ var stage = topStageRef.current;
4222
+ var layer = topLayerRef.current;
4223
+ if (!stage || !layer || topStageZIndex === undefined || !topOnHover) return;
4224
+ var hovered = hoveredItemRef.current;
4225
+ var shape = layer.findOne('.top-render-shape'); // hover된 항목이 없으면 shape 제거
4226
+
4227
+ if (!hovered) {
4228
+ if (shape) {
4229
+ shape.destroy();
4230
+ }
4231
+
4232
+ layer.batchDraw();
4233
+ return;
4234
+ } // shape가 없으면 생성
4235
+
4236
+
4237
+ if (!shape) {
4238
+ shape = new Konva.Shape({
4239
+ hitStrokeWidth: 0,
4240
+ listening: false,
4241
+ name: 'top-render-shape',
4242
+ perfectDrawEnabled: false,
4243
+ sceneFunc: function () {} // 초기화만
4244
+
4245
+ });
4246
+ layer.add(shape);
4247
+ } // sceneFunc를 매번 업데이트하여 최신 상태 반영
4248
+
4249
+
4250
+ shape.sceneFunc(function (konvaContext) {
4251
+ var ctx = konvaContext;
4252
+ var currentHovered = hoveredItemRef.current; // hover된 항목이 없으면 아무것도 그리지 않음
4253
+
4254
+ if (!currentHovered) return; // 뷰포트 컬링 확인
4255
+
4256
+ if (enableViewportCullingRef.current && !isInViewport$1(currentHovered)) {
4257
+ return;
4258
+ }
4259
+
4260
+ var selectedItems = mapValuesToArray(selectedItemsMapRef.current);
4261
+ var hoveredIsSelected = selectedItems.some(function (item) {
4262
+ return item.id === currentHovered.id;
4263
+ }); // Top Layer에서는 hover된 마커만 hover 스타일로 그리기
4264
+ // renderEvent가 있으면: base는 그리지 않고 event만 그리기 (hover 스타일 적용)
4265
+ // renderEvent가 없으면: base를 hover 스타일로 그리기
4266
+
4267
+ if (renderEvent) {
4268
+ // renderEvent가 있으면 hover 스타일로만 그리기
4269
+ var hoverSelectedItems = hoveredIsSelected ? [currentHovered] : [];
4270
+ renderEvent({
4271
+ ctx: ctx,
4272
+ hoveredItem: currentHovered,
4273
+ selectedItem: selectedItemRef.current,
4274
+ selectedItems: hoverSelectedItems,
4275
+ topOnHover: topOnHover,
4276
+ utils: renderUtils
4277
+ });
4278
+ } else {
4279
+ // renderEvent가 없으면 base를 hover 스타일로 그리기
4280
+ renderBase({
4281
+ ctx: ctx,
4282
+ hoveredItem: currentHovered,
4283
+ items: [currentHovered],
4284
+ selectedIds: selectedIdsRef.current,
4285
+ utils: renderUtils
4286
+ });
4287
+ }
4288
+ });
4153
4289
  layer.batchDraw();
4154
4290
  }; // 전체 즉시 렌더링
4155
4291
 
@@ -4161,11 +4297,19 @@ var CanvasMarkerLayer = function (props) {
4161
4297
 
4162
4298
  buildSpatialIndex$1();
4163
4299
  doRenderBase();
4164
- doRenderEvent();
4300
+ doRenderEvent(); // 메인 stage의 transform을 topStage에도 동기화
4301
+
4302
+ if (topStageZIndex !== undefined && topContainerRef.current && containerRef.current) {
4303
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4304
+ }
4305
+
4306
+ if (topStageZIndex !== undefined && topOnHover) {
4307
+ doRenderTop();
4308
+ }
4165
4309
  }; // 지도 이벤트 핸들러 생성
4166
4310
 
4167
4311
 
4168
- var _g = createMapEventHandlers({
4312
+ var _h = createMapEventHandlers({
4169
4313
  accumTranslateRef: accumTranslateRef,
4170
4314
  boundingBoxCacheRef: boundingBoxCacheRef,
4171
4315
  containerRef: containerRef,
@@ -4176,19 +4320,23 @@ var CanvasMarkerLayer = function (props) {
4176
4320
  prevCenterOffsetRef: prevCenterOffsetRef,
4177
4321
  renderAllImmediate: renderAllImmediate
4178
4322
  }),
4179
- handleIdle = _g.handleIdle,
4180
- handleZoomStart = _g.handleZoomStart,
4181
- handleZoomEnd = _g.handleZoomEnd,
4182
- handleCenterChanged = _g.handleCenterChanged,
4183
- handleDragStartShared = _g.handleDragStart,
4184
- handleDragEndShared = _g.handleDragEnd;
4323
+ handleIdle = _h.handleIdle,
4324
+ handleZoomStart = _h.handleZoomStart,
4325
+ handleZoomEnd = _h.handleZoomEnd,
4326
+ handleCenterChanged = _h.handleCenterChanged,
4327
+ handleDragStartShared = _h.handleDragStart,
4328
+ handleDragEndShared = _h.handleDragEnd;
4185
4329
 
4186
4330
  var handleDragStart = function () {
4187
4331
  handleDragStartShared(); // 드래그 시작 시점의 hover 상태 저장
4188
4332
 
4189
4333
  dragStartHoveredItemRef.current = hoveredItemRef.current;
4190
4334
  draggingRef.current = true;
4191
- controller.setMapCursor('grabbing');
4335
+ controller.setMapCursor('grabbing'); // 메인 stage의 transform을 topStage에도 동기화
4336
+
4337
+ if (topStageZIndex !== undefined && topContainerRef.current && containerRef.current) {
4338
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4339
+ }
4192
4340
  };
4193
4341
 
4194
4342
  var handleDragEnd = function () {
@@ -4196,7 +4344,11 @@ var CanvasMarkerLayer = function (props) {
4196
4344
  draggingRef.current = false; // 드래그 종료 후 hover 상태 초기화 (다음 MOUSEMOVE에서 업데이트됨)
4197
4345
 
4198
4346
  dragStartHoveredItemRef.current = null;
4199
- controller.setMapCursor('grab');
4347
+ controller.setMapCursor('grab'); // 메인 stage의 transform을 topStage에도 동기화
4348
+
4349
+ if (topStageZIndex !== undefined && topContainerRef.current && containerRef.current) {
4350
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4351
+ }
4200
4352
  }; // Hit Test: 특정 좌표의 마커 찾기
4201
4353
 
4202
4354
 
@@ -4239,7 +4391,19 @@ var CanvasMarkerLayer = function (props) {
4239
4391
  controller.setMapCursor(hoveredData ? 'pointer' : 'grab');
4240
4392
  }
4241
4393
 
4242
- if (renderEvent) {
4394
+ if (topStageZIndex !== undefined && topOnHover) {
4395
+ // topStageZIndex가 설정되고 topOnHover가 true인 경우 Top Layer에서 hover된 항목 렌더링
4396
+ // base 레이어와 event 레이어도 업데이트 (hover된 항목 제외)
4397
+ doRenderBase();
4398
+ doRenderEvent();
4399
+ doRenderTop();
4400
+ } else if (renderEvent) {
4401
+ // renderEvent가 있을 때는 Event Layer 업데이트
4402
+ // topOnHover가 false일 때는 Base Layer에서도 hover 스타일을 적용해야 하므로 Base Layer도 업데이트
4403
+ if (!topOnHover) {
4404
+ doRenderBase();
4405
+ }
4406
+
4243
4407
  doRenderEvent();
4244
4408
  } else if (topOnHover) {
4245
4409
  doRenderBase();
@@ -4276,6 +4440,10 @@ var CanvasMarkerLayer = function (props) {
4276
4440
 
4277
4441
  doRenderBase();
4278
4442
  doRenderEvent();
4443
+
4444
+ if (topStageZIndex !== undefined && topOnHover) {
4445
+ doRenderTop();
4446
+ }
4279
4447
  }; // 클릭 이벤트 핸들러
4280
4448
 
4281
4449
 
@@ -4336,13 +4504,33 @@ var CanvasMarkerLayer = function (props) {
4336
4504
  if (!prevHovered) return;
4337
4505
  hoveredItemRef.current = null;
4338
4506
  controller.setMapCursor('grab');
4339
- doRenderEvent();
4507
+
4508
+ if (topStageZIndex !== undefined && topOnHover) {
4509
+ // base 레이어와 event 레이어도 업데이트 (hover된 항목 다시 표시)
4510
+ doRenderBase();
4511
+ doRenderEvent();
4512
+ doRenderTop();
4513
+ } else if (renderEvent) {
4514
+ // renderEvent가 있을 때는 Event Layer 업데이트
4515
+ // topOnHover가 false일 때는 Base Layer에서도 hover 스타일을 제거해야 하므로 Base Layer도 업데이트
4516
+ if (!topOnHover) {
4517
+ doRenderBase();
4518
+ }
4519
+
4520
+ doRenderEvent();
4521
+ }
4522
+
4340
4523
  onMouseOut === null || onMouseOut === void 0 ? void 0 : onMouseOut(prevHovered);
4341
4524
  }; // DOM 초기화
4342
4525
 
4343
4526
 
4344
4527
  useEffect(function () {
4345
- divElement.style.width = 'fit-content';
4528
+ divElement.style.width = 'fit-content'; // Top Layer용 div도 초기화 (topStageZIndex가 설정되고 topOnHover가 true인 경우)
4529
+
4530
+ if (topStageZIndex !== undefined && topOnHover) {
4531
+ topDivElement.style.width = 'fit-content';
4532
+ }
4533
+
4346
4534
  return function () {
4347
4535
  if (!markerRef.current) return;
4348
4536
  controller.clearDrawable(markerRef.current);
@@ -4360,19 +4548,18 @@ var CanvasMarkerLayer = function (props) {
4360
4548
 
4361
4549
  if (markerRef.current) {
4362
4550
  controller.updateMarker(markerRef.current, markerOptions);
4363
- return;
4364
- }
4365
-
4366
- markerRef.current = new Marker(markerOptions);
4367
- markerRef.current.element = divElement;
4368
- controller.createMarker(markerRef.current);
4551
+ } else {
4552
+ markerRef.current = new Marker(markerOptions);
4553
+ markerRef.current.element = divElement;
4554
+ controller.createMarker(markerRef.current);
4369
4555
 
4370
- if (divElement.parentElement) {
4371
- divElement.parentElement.style.pointerEvents = 'none';
4372
- }
4556
+ if (divElement.parentElement) {
4557
+ divElement.parentElement.style.pointerEvents = 'none';
4558
+ }
4373
4559
 
4374
- if (options.zIndex !== undefined) {
4375
- controller.setMarkerZIndex(markerRef.current, options.zIndex);
4560
+ if (options.zIndex !== undefined) {
4561
+ controller.setMarkerZIndex(markerRef.current, options.zIndex);
4562
+ }
4376
4563
  }
4377
4564
  }, [options]); // Konva 초기화 및 이벤트 리스너 등록
4378
4565
 
@@ -4526,19 +4713,179 @@ var CanvasMarkerLayer = function (props) {
4526
4713
 
4527
4714
  renderAllImmediate();
4528
4715
  }
4529
- }, [enableViewportCulling]); // 외부 selectedItems 동기화
4716
+ }, [enableViewportCulling]); // Top Layer용 별도 캔버스 DOM 생성 (topStageZIndex가 설정되고 topOnHover가 true인 경우)
4717
+
4718
+ useEffect(function () {
4719
+ if (topStageZIndex === undefined || !topOnHover) return;
4720
+ if (!topContainerRef.current) return;
4721
+ var mapDiv = controller.mapDivElement; // Top Layer용 div 요소 설정
4722
+
4723
+ topDivElement.style.width = 'fit-content';
4724
+ var bounds = controller.getCurrBounds();
4725
+
4726
+ var topMarkerOptions = __assign({
4727
+ position: bounds.nw,
4728
+ zIndex: topStageZIndex
4729
+ }, options); // Top Layer용 Marker 생성 (zIndex: topStageZIndex로 DOM 마커보다 위에 위치)
4730
+
4731
+
4732
+ var topMarker = new Marker(topMarkerOptions);
4733
+ topMarker.element = topDivElement;
4734
+ controller.createMarker(topMarker);
4735
+ topMarkerRef.current = topMarker;
4736
+
4737
+ if (topDivElement.parentElement) {
4738
+ topDivElement.parentElement.style.pointerEvents = 'none';
4739
+ } // Top Layer Marker의 zIndex 명시적으로 설정
4740
+
4741
+
4742
+ controller.setMarkerZIndex(topMarker, topStageZIndex); // Top Layer용 Konva Stage 생성
4743
+
4744
+ var topStage = new Konva.Stage({
4745
+ container: topContainerRef.current,
4746
+ height: mapDiv.offsetHeight,
4747
+ width: mapDiv.offsetWidth
4748
+ });
4749
+ topStageRef.current = topStage;
4750
+ var topLayer = new Konva.Layer({
4751
+ listening: false
4752
+ });
4753
+ topLayerRef.current = topLayer;
4754
+ topStage.add(topLayer); // ResizeObserver: 맵 크기 변경 감지 (RAF로 debounce)
4755
+
4756
+ var topResizeRafId = null;
4757
+ var topResizeObserver = new ResizeObserver(function () {
4758
+ if (topResizeRafId !== null) {
4759
+ cancelAnimationFrame(topResizeRafId);
4760
+ }
4761
+
4762
+ topResizeRafId = requestAnimationFrame(function () {
4763
+ topStage.width(mapDiv.offsetWidth);
4764
+ topStage.height(mapDiv.offsetHeight);
4765
+ doRenderTop();
4766
+ topResizeRafId = null;
4767
+ });
4768
+ });
4769
+ topResizeObserver.observe(mapDiv); // topMarker position 업데이트 함수
4770
+
4771
+ var updateTopMarkerPosition = function () {
4772
+ if (topMarkerRef.current && markerRef.current) {
4773
+ var currentBounds = controller.getCurrBounds();
4774
+
4775
+ var updatedOptions = __assign(__assign({}, options), {
4776
+ position: currentBounds.nw,
4777
+ zIndex: topStageZIndex
4778
+ });
4779
+
4780
+ controller.updateMarker(topMarkerRef.current, updatedOptions); // zIndex 명시적으로 설정
4781
+
4782
+ controller.setMarkerZIndex(topMarkerRef.current, topStageZIndex);
4783
+ }
4784
+ }; // 지도 이벤트 핸들러 등록 (topStage 업데이트용)
4785
+
4786
+
4787
+ var handleTopIdle = function () {
4788
+ // topMarker의 position을 메인 marker와 동일하게 업데이트
4789
+ updateTopMarkerPosition(); // topStage 크기 업데이트
4790
+
4791
+ if (topStageRef.current) {
4792
+ topStageRef.current.width(mapDiv.offsetWidth);
4793
+ topStageRef.current.height(mapDiv.offsetHeight);
4794
+ } // 메인 stage의 transform을 topStage에도 동기화
4795
+
4796
+
4797
+ if (topContainerRef.current && containerRef.current) {
4798
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4799
+ }
4800
+
4801
+ doRenderTop();
4802
+ };
4803
+
4804
+ var handleTopZoomStart = function () {
4805
+ // 메인 stage의 transform을 topStage에도 동기화
4806
+ if (topContainerRef.current && containerRef.current) {
4807
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4808
+ }
4809
+
4810
+ doRenderTop();
4811
+ };
4812
+
4813
+ var handleTopZoomEnd = function () {
4814
+ // 메인 stage의 transform을 topStage에도 동기화
4815
+ if (topContainerRef.current && containerRef.current) {
4816
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4817
+ }
4818
+
4819
+ doRenderTop();
4820
+ };
4821
+
4822
+ var handleTopCenterChanged = function () {
4823
+ // topMarker의 position을 메인 marker와 동일하게 업데이트
4824
+ updateTopMarkerPosition(); // topStage 크기 업데이트
4825
+
4826
+ if (topStageRef.current) {
4827
+ topStageRef.current.width(mapDiv.offsetWidth);
4828
+ topStageRef.current.height(mapDiv.offsetHeight);
4829
+ } // 메인 stage의 transform을 topStage에도 동기화
4830
+
4831
+
4832
+ if (topContainerRef.current && containerRef.current) {
4833
+ topContainerRef.current.style.transform = containerRef.current.style.transform || '';
4834
+ }
4835
+
4836
+ doRenderTop();
4837
+ };
4838
+
4839
+ controller.addEventListener('IDLE', handleTopIdle);
4840
+ controller.addEventListener('ZOOMSTART', handleTopZoomStart);
4841
+ controller.addEventListener('ZOOM_CHANGED', handleTopZoomEnd);
4842
+ controller.addEventListener('CENTER_CHANGED', handleTopCenterChanged);
4843
+ doRenderTop();
4844
+ return function () {
4845
+ if (topResizeRafId !== null) {
4846
+ cancelAnimationFrame(topResizeRafId);
4847
+ }
4848
+
4849
+ topResizeObserver.disconnect();
4850
+ controller.removeEventListener('IDLE', handleTopIdle);
4851
+ controller.removeEventListener('ZOOMSTART', handleTopZoomStart);
4852
+ controller.removeEventListener('ZOOM_CHANGED', handleTopZoomEnd);
4853
+ controller.removeEventListener('CENTER_CHANGED', handleTopCenterChanged);
4854
+
4855
+ if (topLayerRef.current) {
4856
+ topLayerRef.current.destroyChildren();
4857
+ }
4858
+
4859
+ if (topStageRef.current) {
4860
+ topStageRef.current.destroy();
4861
+ }
4862
+
4863
+ if (topMarkerRef.current) {
4864
+ controller.clearDrawable(topMarkerRef.current);
4865
+ topMarkerRef.current = undefined;
4866
+ }
4867
+ };
4868
+ }, [topStageZIndex, renderEvent, options]); // 외부 selectedItems 동기화
4530
4869
 
4531
4870
  useEffect(function () {
4532
4871
  if (!stageRef.current) return;
4533
4872
  syncExternalSelectedItems(externalSelectedItems, selectedIdsRef, selectedItemsMapRef);
4534
4873
  doRenderBase();
4535
4874
  doRenderEvent();
4875
+
4876
+ if (topStageZIndex !== undefined && topOnHover) {
4877
+ doRenderTop();
4878
+ }
4536
4879
  }, [externalSelectedItems]); // 외부 selectedItem 변경 시 Event Layer 리렌더링
4537
4880
 
4538
4881
  useEffect(function () {
4539
4882
  if (!stageRef.current) return;
4540
4883
  selectedItemRef.current = externalSelectedItem;
4541
4884
  doRenderEvent();
4885
+
4886
+ if (topStageZIndex !== undefined && topOnHover) {
4887
+ doRenderTop();
4888
+ }
4542
4889
  }, [externalSelectedItem]); // 데이터 변경 시 렌더링 (캐시 정리 및 선택 상태 동기화)
4543
4890
 
4544
4891
  useEffect(function () {
@@ -4559,14 +4906,21 @@ var CanvasMarkerLayer = function (props) {
4559
4906
  selectedItemsMapRef.current = syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
4560
4907
  renderAllImmediate();
4561
4908
  }, [data]);
4562
- return createPortal(React.createElement("div", {
4909
+ return React.createElement(React.Fragment, null, createPortal(React.createElement("div", {
4563
4910
  ref: containerRef,
4564
4911
  style: {
4565
4912
  height: '100%',
4566
4913
  position: 'absolute',
4567
4914
  width: '100%'
4568
4915
  }
4569
- }), divElement);
4916
+ }), divElement), topStageZIndex !== undefined && createPortal(React.createElement("div", {
4917
+ ref: topContainerRef,
4918
+ style: {
4919
+ height: '100%',
4920
+ position: 'absolute',
4921
+ width: '100%'
4922
+ }
4923
+ }), topDivElement));
4570
4924
  };
4571
4925
 
4572
4926
  /* eslint-disable no-restricted-syntax */
@@ -5667,9 +6021,12 @@ var CanvasPolygonLayer = function (props) {
5667
6021
  var isObjectMode = 'renderStyle' in props && props.renderStyle !== undefined;
5668
6022
  var isIndividualMode = 'baseFillColor' in props && props.baseFillColor !== undefined; // 각 방식별 props 추출
5669
6023
 
5670
- var customStyle = hasCustomStyle ? props.customStyle : undefined;
6024
+ var customStyleProp = hasCustomStyle ? props.customStyle : undefined;
5671
6025
  var individualProps = isIndividualMode ? props : undefined;
5672
- var objectProps = isObjectMode ? props : undefined; // --------------------------------------------------------------------------
6026
+ var objectProps = isObjectMode ? props : undefined; // customStyle 객체에서 callback과 deps 추출
6027
+
6028
+ var customStyle = customStyleProp === null || customStyleProp === void 0 ? void 0 : customStyleProp.callback;
6029
+ var customStyleDeps = customStyleProp === null || customStyleProp === void 0 ? void 0 : customStyleProp.deps; // --------------------------------------------------------------------------
5673
6030
  // Hooks & Context
5674
6031
  // --------------------------------------------------------------------------
5675
6032
 
@@ -6225,7 +6582,17 @@ var CanvasPolygonLayer = function (props) {
6225
6582
  boundingBoxCacheRef.current.clear();
6226
6583
  selectedItemsMapRef.current = syncSelectedItems(data, selectedIdsRef.current, selectedItemsMapRef.current);
6227
6584
  renderAllImmediate();
6228
- }, [data]);
6585
+ }, [data]); // customStyle deps 변경 시 Canvas 재렌더링
6586
+
6587
+ useEffect(function () {
6588
+ var _a, _b, _c, _d;
6589
+
6590
+ if (!stageRef.current || !customStyleDeps) return; // Shape 재생성을 위해 기존 shape 제거
6591
+
6592
+ (_b = (_a = baseLayerRef.current) === null || _a === void 0 ? void 0 : _a.findOne('.base-render-shape')) === null || _b === void 0 ? void 0 : _b.destroy();
6593
+ (_d = (_c = eventLayerRef.current) === null || _c === void 0 ? void 0 : _c.findOne('.event-render-shape')) === null || _d === void 0 ? void 0 : _d.destroy();
6594
+ renderAllImmediate(); // eslint-disable-next-line react-hooks/exhaustive-deps
6595
+ }, customStyleDeps || []);
6229
6596
  return createPortal(React.createElement("div", {
6230
6597
  ref: containerRef,
6231
6598
  style: {