@accelint/map-toolkit 0.6.0 → 1.0.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.
- package/CHANGELOG.md +68 -0
- package/catalog-info.yaml +5 -4
- package/dist/camera/index.d.ts +2 -2
- package/dist/camera/index.js +2 -2
- package/dist/camera/store.d.ts +120 -0
- package/dist/camera/store.js +279 -0
- package/dist/camera/store.js.map +1 -0
- package/dist/deckgl/base-map/constants.d.ts +1 -6
- package/dist/deckgl/base-map/constants.js +1 -6
- package/dist/deckgl/base-map/constants.js.map +1 -1
- package/dist/deckgl/base-map/controls.js +2 -0
- package/dist/deckgl/base-map/controls.js.map +1 -1
- package/dist/deckgl/base-map/index.d.ts +2 -2
- package/dist/deckgl/base-map/index.js +10 -11
- package/dist/deckgl/base-map/index.js.map +1 -1
- package/dist/deckgl/base-map/provider.js +1 -1
- package/dist/deckgl/index.d.ts +4 -4
- package/dist/deckgl/index.js +4 -4
- package/dist/deckgl/saved-viewports/storage.js +10 -2
- package/dist/deckgl/saved-viewports/storage.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/constants.js +5 -8
- package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/index.d.ts +18 -14
- package/dist/deckgl/shapes/display-shape-layer/index.js +63 -30
- package/dist/deckgl/shapes/display-shape-layer/index.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js +2 -16
- package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/store.js +58 -272
- package/dist/deckgl/shapes/display-shape-layer/store.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/types.d.ts +22 -11
- package/dist/deckgl/shapes/display-shape-layer/{use-shape-selection.d.ts → use-select-shape.d.ts} +9 -9
- package/dist/deckgl/shapes/display-shape-layer/{use-shape-selection.js → use-select-shape.js} +12 -12
- package/dist/deckgl/shapes/display-shape-layer/use-select-shape.js.map +1 -0
- package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +5 -66
- package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +2 -65
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +3 -121
- package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -1
- package/dist/deckgl/shapes/draw-shape-layer/constants.js +46 -0
- package/dist/deckgl/shapes/draw-shape-layer/constants.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/events.d.ts +92 -0
- package/dist/deckgl/shapes/draw-shape-layer/events.js +56 -0
- package/dist/deckgl/shapes/draw-shape-layer/events.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/fiber.d.ts +11 -0
- package/dist/{maplibre/constants.js → deckgl/shapes/draw-shape-layer/fiber.js} +6 -12
- package/dist/deckgl/shapes/draw-shape-layer/fiber.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/index.d.ts +53 -0
- package/dist/deckgl/shapes/draw-shape-layer/index.js +95 -0
- package/dist/deckgl/shapes/draw-shape-layer/index.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js +51 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js +73 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js +87 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js +88 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js +77 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/index.js +64 -0
- package/dist/deckgl/shapes/draw-shape-layer/modes/index.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/store.js +175 -0
- package/dist/deckgl/shapes/draw-shape-layer/store.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/types.d.ts +86 -0
- package/dist/{viewport/constants.js → deckgl/shapes/draw-shape-layer/types.js} +1 -12
- package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.d.ts +82 -0
- package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js +112 -0
- package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js.map +1 -0
- package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js +147 -0
- package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/constants.js +41 -0
- package/dist/deckgl/shapes/edit-shape-layer/constants.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/events.d.ts +92 -0
- package/dist/deckgl/shapes/edit-shape-layer/events.js +56 -0
- package/dist/deckgl/shapes/edit-shape-layer/events.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/fiber.d.ts +13 -0
- package/dist/deckgl/shapes/edit-shape-layer/fiber.js +14 -0
- package/dist/deckgl/shapes/edit-shape-layer/index.d.ts +63 -0
- package/dist/deckgl/shapes/edit-shape-layer/index.js +162 -0
- package/dist/deckgl/shapes/edit-shape-layer/index.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js +154 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js +147 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js +87 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/index.js +61 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/index.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js +109 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js +289 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js +121 -0
- package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/store.js +194 -0
- package/dist/deckgl/shapes/edit-shape-layer/store.js.map +1 -0
- package/dist/deckgl/shapes/edit-shape-layer/types.d.ts +93 -0
- package/dist/deckgl/shapes/edit-shape-layer/types.js +14 -0
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.d.ts +82 -0
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js +114 -0
- package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js.map +1 -0
- package/dist/deckgl/shapes/index.d.ts +15 -6
- package/dist/deckgl/shapes/index.js +12 -5
- package/dist/deckgl/shapes/shared/constants.d.ts +27 -32
- package/dist/deckgl/shapes/shared/constants.js +189 -25
- package/dist/deckgl/shapes/shared/constants.js.map +1 -1
- package/dist/deckgl/shapes/shared/events.d.ts +1 -20
- package/dist/deckgl/shapes/shared/events.js +1 -31
- package/dist/deckgl/shapes/shared/events.js.map +1 -1
- package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js +84 -0
- package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js.map +1 -0
- package/dist/deckgl/shapes/shared/types.d.ts +187 -28
- package/dist/deckgl/shapes/shared/types.js +55 -1
- package/dist/deckgl/shapes/shared/types.js.map +1 -1
- package/dist/deckgl/shapes/shared/utils/geometry-measurements.js +128 -0
- package/dist/deckgl/shapes/shared/utils/geometry-measurements.js.map +1 -0
- package/dist/deckgl/shapes/shared/utils/layer-config.js +50 -0
- package/dist/deckgl/shapes/shared/utils/layer-config.js.map +1 -0
- package/dist/deckgl/shapes/shared/utils/mode-utils.js +113 -0
- package/dist/deckgl/shapes/shared/utils/mode-utils.js.map +1 -0
- package/dist/deckgl/shapes/shared/utils/pick-filtering.js +57 -0
- package/dist/deckgl/shapes/shared/utils/pick-filtering.js.map +1 -0
- package/dist/deckgl/shapes/shared/utils/style-utils.d.ts +64 -0
- package/dist/deckgl/shapes/shared/utils/style-utils.js +101 -0
- package/dist/deckgl/shapes/shared/utils/style-utils.js.map +1 -0
- package/dist/deckgl/text-layer/default-settings.js +4 -24
- package/dist/deckgl/text-layer/default-settings.js.map +1 -1
- package/dist/deckgl/text-settings.d.ts +77 -0
- package/dist/deckgl/text-settings.js +83 -0
- package/dist/deckgl/text-settings.js.map +1 -0
- package/dist/map-cursor/index.d.ts +2 -2
- package/dist/map-cursor/index.js +2 -2
- package/dist/map-cursor/store.d.ts +32 -61
- package/dist/map-cursor/store.js +165 -294
- package/dist/map-cursor/store.js.map +1 -1
- package/dist/map-cursor/use-map-cursor.d.ts +5 -2
- package/dist/map-cursor/use-map-cursor.js +33 -15
- package/dist/map-cursor/use-map-cursor.js.map +1 -1
- package/dist/map-mode/index.d.ts +2 -2
- package/dist/map-mode/index.js +2 -2
- package/dist/map-mode/store.d.ts +36 -37
- package/dist/map-mode/store.js +131 -237
- package/dist/map-mode/store.js.map +1 -1
- package/dist/map-mode/use-map-mode.js +6 -5
- package/dist/map-mode/use-map-mode.js.map +1 -1
- package/dist/maplibre/index.d.ts +2 -2
- package/dist/maplibre/index.js +2 -2
- package/dist/shared/constants.d.ts +19 -0
- package/dist/shared/constants.js +33 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/create-map-store.d.ts +202 -0
- package/dist/shared/create-map-store.js +223 -0
- package/dist/shared/create-map-store.js.map +1 -0
- package/dist/shared/units.d.ts +39 -0
- package/dist/shared/units.js +49 -0
- package/dist/shared/units.js.map +1 -0
- package/dist/viewport/index.d.ts +3 -3
- package/dist/viewport/index.js +3 -3
- package/dist/viewport/store.d.ts +69 -0
- package/dist/viewport/store.js +125 -0
- package/dist/viewport/store.js.map +1 -0
- package/dist/viewport/types.d.ts +2 -2
- package/dist/viewport/utils.js +2 -2
- package/dist/viewport/utils.js.map +1 -1
- package/dist/viewport/viewport-size.d.ts +2 -2
- package/dist/viewport/viewport-size.js +2 -2
- package/dist/viewport/viewport-size.js.map +1 -1
- package/package.json +36 -18
- package/dist/camera/use-camera-state.d.ts +0 -153
- package/dist/camera/use-camera-state.js +0 -418
- package/dist/camera/use-camera-state.js.map +0 -1
- package/dist/deckgl/shapes/display-shape-layer/constants.d.ts +0 -44
- package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.d.ts +0 -66
- package/dist/deckgl/shapes/display-shape-layer/store.d.ts +0 -87
- package/dist/deckgl/shapes/display-shape-layer/use-shape-selection.js.map +0 -1
- package/dist/deckgl/shapes/display-shape-layer/utils/display-style.d.ts +0 -61
- package/dist/maplibre/constants.d.ts +0 -13
- package/dist/maplibre/constants.js.map +0 -1
- package/dist/viewport/constants.d.ts +0 -11
- package/dist/viewport/constants.js.map +0 -1
- package/dist/viewport/use-viewport-state.d.ts +0 -100
- package/dist/viewport/use-viewport-state.js +0 -222
- package/dist/viewport/use-viewport-state.js.map +0 -1
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
|
|
14
14
|
'use client';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import { useMapCamera } from "../../camera/store.js";
|
|
17
17
|
import { MapEvents } from "./events.js";
|
|
18
18
|
import { getCursor } from "../../map-cursor/store.js";
|
|
19
19
|
import { MapProvider } from "./provider.js";
|
|
20
|
-
import {
|
|
20
|
+
import { DEFAULT_VIEW_STATE } from "../../shared/constants.js";
|
|
21
|
+
import { DARK_BASE_MAP_STYLE, PARAMETERS, PICKING_RADIUS } from "./constants.js";
|
|
21
22
|
import { MapControls } from "./controls.js";
|
|
22
23
|
import { useCallback, useId, useMemo, useRef } from "react";
|
|
23
24
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -128,14 +129,11 @@ function BaseMap({ id, className, children, controller = true, enableControlEven
|
|
|
128
129
|
const deckglInstance = useDeckgl();
|
|
129
130
|
const container = useId();
|
|
130
131
|
const mapRef = useRef(null);
|
|
131
|
-
const { cameraState, setCameraState } =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,
|
|
137
|
-
longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude
|
|
138
|
-
}
|
|
132
|
+
const { cameraState, setCameraState } = useMapCamera(id, {
|
|
133
|
+
view: defaultView,
|
|
134
|
+
zoom: initialViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom,
|
|
135
|
+
latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,
|
|
136
|
+
longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude
|
|
139
137
|
});
|
|
140
138
|
const viewState = useMemo(() => ({
|
|
141
139
|
...deckglInstance?._deck?._getViewState(),
|
|
@@ -230,12 +228,13 @@ function BaseMap({ id, className, children, controller = true, enableControlEven
|
|
|
230
228
|
}), /* @__PURE__ */ jsx(MapProvider, {
|
|
231
229
|
id,
|
|
232
230
|
children: /* @__PURE__ */ jsx(Map, {
|
|
233
|
-
onMove: (evt) => setCameraState(
|
|
231
|
+
onMove: (evt) => setCameraState(evt.viewState),
|
|
234
232
|
mapStyle: styleUrl,
|
|
235
233
|
ref: mapRef,
|
|
236
234
|
...mapOptions,
|
|
237
235
|
children: /* @__PURE__ */ jsxs(Deckgl, {
|
|
238
236
|
...rest,
|
|
237
|
+
controller,
|
|
239
238
|
interleaved,
|
|
240
239
|
getCursor: handleGetCursor,
|
|
241
240
|
useDevicePixels,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["MapLibre"],"sources":["../../../src/deckgl/base-map/index.tsx"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport 'client-only';\nimport { useEffectEvent, useEmit } from '@accelint/bus/react';\nimport { Deckgl, useDeckgl } from '@deckgl-fiber-renderer/dom';\nimport { useCallback, useId, useMemo, useRef } from 'react';\nimport {\n Map as MapLibre,\n type MapRef,\n useControl,\n type ViewState,\n} from 'react-map-gl/maplibre';\nimport { useCameraState } from '../../camera';\nimport { getCursor } from '../../map-cursor/store';\nimport {\n DARK_BASE_MAP_STYLE,\n DEFAULT_VIEW_STATE,\n PARAMETERS,\n PICKING_RADIUS,\n} from './constants';\nimport { MapControls } from './controls';\nimport { MapEvents } from './events';\nimport { MapProvider } from './provider';\nimport type { PickingInfo, ViewStateChangeParameters } from '@deck.gl/core';\nimport type { IControl } from 'maplibre-gl';\nimport type { MjolnirGestureEvent, MjolnirPointerEvent } from 'mjolnir.js';\nimport type {\n BaseMapProps,\n MapClickEvent,\n MapHoverEvent,\n MapViewportEvent,\n SerializablePickingInfo,\n} from './types';\n\n/**\n * Serializes PickingInfo for event bus transmission.\n * Omits viewport, layer, and sourceLayer (contain functions) but preserves layer IDs.\n */\nfunction serializePickingInfo(info: PickingInfo): SerializablePickingInfo {\n const { viewport, layer, sourceLayer, ...infoRest } = info;\n return {\n layerId: layer?.id,\n sourceLayerId: sourceLayer?.id,\n ...infoRest,\n };\n}\n\n/**\n * Strips non-serializable properties from MjolnirGestureEvent for event bus transmission.\n * Removes functions, DOM elements, and PointerEvent objects that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent,\n): Omit<\n MjolnirGestureEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n | 'changedPointers'\n | 'pointers'\n>;\n/**\n * Strips non-serializable properties from MjolnirPointerEvent for event bus transmission.\n * Removes functions and DOM elements that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirPointerEvent,\n): Omit<\n MjolnirPointerEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n>;\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent | MjolnirPointerEvent,\n) {\n const {\n stopImmediatePropagation,\n stopPropagation,\n preventDefault,\n srcEvent,\n rootElement,\n target,\n ...rest\n } = event;\n\n // Remove pointer arrays if present (only on MjolnirGestureEvent)\n if ('changedPointers' in rest) {\n const { changedPointers, pointers, ...gestureRest } = rest;\n return gestureRest;\n }\n\n return rest;\n}\n\nfunction AddDeckglControl() {\n const deckglInstance = useDeckgl();\n useControl(() => deckglInstance as IControl);\n\n return null;\n}\n\n/**\n * A React component that provides a Deck.gl-powered base map with MapLibre GL integration.\n *\n * This component serves as the foundation for building interactive map applications with\n * support for click and hover events through a centralized event bus. It integrates\n * Deck.gl for 3D visualizations with MapLibre GL for the base map tiles.\n *\n * **Map Mode Integration**: BaseMap automatically creates a `MapProvider` internally,\n * which sets up the map mode state management for this instance.\n * - **Children**: Only Deck.gl layer components can be rendered as children. Custom Deck.gl\n * layers can use `useMapMode()` without parameters to access context.\n * - **Siblings**: UI components (buttons, toolbars, etc.) must be rendered as siblings\n * and pass `id` to `useMapMode(id)`.\n *\n * **Event Bus**: Click and hover events are emitted through the event bus with the `id`\n * included in the payload, allowing multiple map instances to coexist without interference.\n *\n * @param props - Component props including id (required), className, onClick, onHover, and all Deck.gl props\n * @returns A map component with Deck.gl and MapLibre GL integration\n *\n * @example\n * Basic usage with id (recommended: module-level constant):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { View } from '@deckgl-fiber-renderer/dom';\n * import { uuid } from '@accelint/core';\n *\n * // Create id at module level for stability and easy sharing\n * const MAIN_MAP_ID = uuid();\n *\n * export function MapView() {\n * return (\n * <BaseMap className=\"w-full h-full\" id={MAIN_MAP_ID}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * );\n * }\n * ```\n *\n * @example\n * With map mode and event handlers (module-level constant for sharing):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { useMapMode } from '@accelint/map-toolkit/map-mode';\n * import { uuid } from '@accelint/core';\n * import type { PickingInfo } from '@deck.gl/core';\n * import type { MjolnirGestureEvent } from 'mjolnir.js';\n *\n * // Module-level constant - stable and shareable across all components\n * const MAIN_MAP_ID = uuid();\n *\n * function Toolbar() {\n * // Access map mode using the shared id\n * const { mode, requestModeChange } = useMapMode(MAIN_MAP_ID);\n * return <div>Current mode: {mode}</div>;\n * }\n *\n * export function InteractiveMap() {\n * const handleClick = (info: PickingInfo, event: MjolnirGestureEvent) => {\n * console.log('Clicked:', info.object);\n * };\n *\n * return (\n * <div className=\"relative w-full h-full\">\n * <BaseMap className=\"absolute inset-0\" id={MAIN_MAP_ID} onClick={handleClick}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * <Toolbar />\n * </div>\n * );\n * }\n * ```\n */\nexport function BaseMap({\n id,\n className,\n children,\n controller = true,\n enableControlEvents = true,\n interleaved = true,\n parameters = {},\n styleUrl = DARK_BASE_MAP_STYLE,\n useDevicePixels = false,\n widgets: widgetsProp = [],\n defaultView = '2D',\n initialViewState,\n onClick,\n onHover,\n onViewStateChange,\n pickingRadius,\n ...rest\n}: BaseMapProps) {\n const deckglInstance = useDeckgl();\n const container = useId();\n const mapRef = useRef<MapRef>(null);\n\n const { cameraState, setCameraState } = useCameraState({\n instanceId: id,\n initialCameraState: {\n view: defaultView,\n zoom: initialViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom,\n latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,\n longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude,\n },\n });\n\n const viewState = useMemo<ViewState>(\n () => ({\n // @ts-expect-error squirrelly deckglInstance typing\n ...(deckglInstance?._deck?._getViewState() as ViewState),\n ...cameraState,\n bearing: cameraState.rotation,\n }),\n // @ts-expect-error squirrelly deckglInstance typing\n [cameraState, deckglInstance?._deck?._getViewState],\n );\n\n // Memoize MapLibre options to avoid creating new object on every render\n const mapOptions = useMemo(\n () => ({\n container,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n latitude: viewState.latitude,\n longitude: viewState.longitude,\n doubleClickZoom: false,\n dragRotate: false,\n pitchWithRotate: false,\n rollEnabled: false,\n attributionControl: { compact: true },\n projection: cameraState.projection,\n maxPitch: cameraState.view === '2D' ? 0 : 85,\n }),\n [viewState, container, cameraState.projection, cameraState.view],\n );\n\n const emitClick = useEmit<MapClickEvent>(MapEvents.click);\n const emitHover = useEmit<MapHoverEvent>(MapEvents.hover);\n const emitViewport = useEmit<MapViewportEvent>(MapEvents.viewport);\n\n const handleClick = useCallback(\n (info: PickingInfo, event: MjolnirGestureEvent) => {\n // send full pickingInfo and event to user-defined onClick\n onClick?.(info, event);\n\n emitClick({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitClick, id, onClick],\n );\n\n const handleHover = useCallback(\n (info: PickingInfo, event: MjolnirPointerEvent) => {\n // send full pickingInfo and event to user-defined onHover\n onHover?.(info, event);\n\n emitHover({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitHover, id, onHover],\n );\n\n const handleGetCursor = useCallback(() => {\n return getCursor(id);\n }, [id]);\n\n const handleViewStateChange = useEffectEvent(\n (params: ViewStateChangeParameters) => {\n onViewStateChange?.(params);\n\n const {\n viewId,\n viewState: { latitude, longitude, zoom },\n } = params;\n\n // @ts-expect-error squirrelly deckglInstance typing\n const viewport = deckglInstance._deck\n .getViewports()\n // @ts-expect-error squirrelly deckglInstance typing\n ?.find((vp) => vp.id === viewId);\n\n emitViewport({\n id,\n bounds: viewport?.getBounds(),\n latitude,\n longitude,\n zoom,\n width: viewport?.width ?? 0,\n height: viewport?.height ?? 0,\n });\n },\n );\n\n const handleLoad = useEffectEvent(() => {\n //--- force update viewport state once all viewports initialized ---\n // @ts-expect-error squirrelly deckglInstance typing\n const viewports = deckglInstance._deck.getViewports() ?? [];\n for (const vp of viewports) {\n handleViewStateChange({\n viewId: vp.id,\n viewState: {\n latitude: vp.latitude,\n longitude: vp.longitude,\n zoom: vp.zoom,\n id: vp.id,\n bounds: vp.getBounds(),\n width: vp.width,\n height: vp.height,\n },\n } as ViewStateChangeParameters);\n }\n });\n\n return (\n <div id={container} className={className}>\n {enableControlEvents && <MapControls id={id} mapRef={mapRef} />}\n <MapProvider id={id}>\n <MapLibre\n onMove={(evt) => setCameraState(id, evt.viewState)}\n mapStyle={styleUrl}\n ref={mapRef}\n {...mapOptions}\n >\n <Deckgl\n {...rest}\n interleaved={interleaved}\n getCursor={handleGetCursor}\n useDevicePixels={useDevicePixels}\n onClick={handleClick}\n pickingRadius={pickingRadius ?? PICKING_RADIUS}\n onHover={handleHover}\n onLoad={handleLoad}\n onViewStateChange={handleViewStateChange}\n // @ts-expect-error - DeckglProps parameters type is overly strict for WebGL parameter spreading.\n // The merged object is valid at runtime but TypeScript cannot verify all possible parameter combinations.\n parameters={{ ...PARAMETERS, ...parameters }}\n >\n <AddDeckglControl />\n {children}\n </Deckgl>\n </MapLibre>\n </MapProvider>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["MapLibre"],"sources":["../../../src/deckgl/base-map/index.tsx"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport 'client-only';\nimport { useEffectEvent, useEmit } from '@accelint/bus/react';\nimport { Deckgl, useDeckgl } from '@deckgl-fiber-renderer/dom';\nimport { useCallback, useId, useMemo, useRef } from 'react';\nimport {\n Map as MapLibre,\n type MapRef,\n useControl,\n type ViewState,\n} from 'react-map-gl/maplibre';\nimport { useMapCamera } from '../../camera';\nimport { getCursor } from '../../map-cursor/store';\nimport { DEFAULT_VIEW_STATE } from '../../shared/constants';\nimport { DARK_BASE_MAP_STYLE, PARAMETERS, PICKING_RADIUS } from './constants';\nimport { MapControls } from './controls';\nimport { MapEvents } from './events';\nimport { MapProvider } from './provider';\nimport type { PickingInfo, ViewStateChangeParameters } from '@deck.gl/core';\nimport type { IControl } from 'maplibre-gl';\nimport type { MjolnirGestureEvent, MjolnirPointerEvent } from 'mjolnir.js';\nimport type {\n BaseMapProps,\n MapClickEvent,\n MapHoverEvent,\n MapViewportEvent,\n SerializablePickingInfo,\n} from './types';\n\n/**\n * Serializes PickingInfo for event bus transmission.\n * Omits viewport, layer, and sourceLayer (contain functions) but preserves layer IDs.\n */\nfunction serializePickingInfo(info: PickingInfo): SerializablePickingInfo {\n const { viewport, layer, sourceLayer, ...infoRest } = info;\n return {\n layerId: layer?.id,\n sourceLayerId: sourceLayer?.id,\n ...infoRest,\n };\n}\n\n/**\n * Strips non-serializable properties from MjolnirGestureEvent for event bus transmission.\n * Removes functions, DOM elements, and PointerEvent objects that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent,\n): Omit<\n MjolnirGestureEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n | 'changedPointers'\n | 'pointers'\n>;\n/**\n * Strips non-serializable properties from MjolnirPointerEvent for event bus transmission.\n * Removes functions and DOM elements that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirPointerEvent,\n): Omit<\n MjolnirPointerEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n>;\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent | MjolnirPointerEvent,\n) {\n const {\n stopImmediatePropagation,\n stopPropagation,\n preventDefault,\n srcEvent,\n rootElement,\n target,\n ...rest\n } = event;\n\n // Remove pointer arrays if present (only on MjolnirGestureEvent)\n if ('changedPointers' in rest) {\n const { changedPointers, pointers, ...gestureRest } = rest;\n return gestureRest;\n }\n\n return rest;\n}\n\nfunction AddDeckglControl() {\n const deckglInstance = useDeckgl();\n useControl(() => deckglInstance as IControl);\n\n return null;\n}\n\n/**\n * A React component that provides a Deck.gl-powered base map with MapLibre GL integration.\n *\n * This component serves as the foundation for building interactive map applications with\n * support for click and hover events through a centralized event bus. It integrates\n * Deck.gl for 3D visualizations with MapLibre GL for the base map tiles.\n *\n * **Map Mode Integration**: BaseMap automatically creates a `MapProvider` internally,\n * which sets up the map mode state management for this instance.\n * - **Children**: Only Deck.gl layer components can be rendered as children. Custom Deck.gl\n * layers can use `useMapMode()` without parameters to access context.\n * - **Siblings**: UI components (buttons, toolbars, etc.) must be rendered as siblings\n * and pass `id` to `useMapMode(id)`.\n *\n * **Event Bus**: Click and hover events are emitted through the event bus with the `id`\n * included in the payload, allowing multiple map instances to coexist without interference.\n *\n * @param props - Component props including id (required), className, onClick, onHover, and all Deck.gl props\n * @returns A map component with Deck.gl and MapLibre GL integration\n *\n * @example\n * Basic usage with id (recommended: module-level constant):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { View } from '@deckgl-fiber-renderer/dom';\n * import { uuid } from '@accelint/core';\n *\n * // Create id at module level for stability and easy sharing\n * const MAIN_MAP_ID = uuid();\n *\n * export function MapView() {\n * return (\n * <BaseMap className=\"w-full h-full\" id={MAIN_MAP_ID}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * );\n * }\n * ```\n *\n * @example\n * With map mode and event handlers (module-level constant for sharing):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { useMapMode } from '@accelint/map-toolkit/map-mode';\n * import { uuid } from '@accelint/core';\n * import type { PickingInfo } from '@deck.gl/core';\n * import type { MjolnirGestureEvent } from 'mjolnir.js';\n *\n * // Module-level constant - stable and shareable across all components\n * const MAIN_MAP_ID = uuid();\n *\n * function Toolbar() {\n * // Access map mode using the shared id\n * const { mode, requestModeChange } = useMapMode(MAIN_MAP_ID);\n * return <div>Current mode: {mode}</div>;\n * }\n *\n * export function InteractiveMap() {\n * const handleClick = (info: PickingInfo, event: MjolnirGestureEvent) => {\n * console.log('Clicked:', info.object);\n * };\n *\n * return (\n * <div className=\"relative w-full h-full\">\n * <BaseMap className=\"absolute inset-0\" id={MAIN_MAP_ID} onClick={handleClick}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * <Toolbar />\n * </div>\n * );\n * }\n * ```\n */\nexport function BaseMap({\n id,\n className,\n children,\n controller = true,\n enableControlEvents = true,\n interleaved = true,\n parameters = {},\n styleUrl = DARK_BASE_MAP_STYLE,\n useDevicePixels = false,\n widgets: widgetsProp = [],\n defaultView = '2D',\n initialViewState,\n onClick,\n onHover,\n onViewStateChange,\n pickingRadius,\n ...rest\n}: BaseMapProps) {\n const deckglInstance = useDeckgl();\n const container = useId();\n const mapRef = useRef<MapRef>(null);\n\n const { cameraState, setCameraState } = useMapCamera(id, {\n view: defaultView,\n zoom: initialViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom,\n latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,\n longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude,\n });\n\n const viewState = useMemo<ViewState>(\n () => ({\n // @ts-expect-error squirrelly deckglInstance typing\n ...(deckglInstance?._deck?._getViewState() as ViewState),\n ...cameraState,\n bearing: cameraState.rotation,\n }),\n // @ts-expect-error squirrelly deckglInstance typing\n [cameraState, deckglInstance?._deck?._getViewState],\n );\n\n // Memoize MapLibre options to avoid creating new object on every render\n const mapOptions = useMemo(\n () => ({\n container,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n latitude: viewState.latitude,\n longitude: viewState.longitude,\n doubleClickZoom: false,\n dragRotate: false,\n pitchWithRotate: false,\n rollEnabled: false,\n attributionControl: { compact: true },\n projection: cameraState.projection,\n maxPitch: cameraState.view === '2D' ? 0 : 85,\n }),\n [viewState, container, cameraState.projection, cameraState.view],\n );\n\n const emitClick = useEmit<MapClickEvent>(MapEvents.click);\n const emitHover = useEmit<MapHoverEvent>(MapEvents.hover);\n const emitViewport = useEmit<MapViewportEvent>(MapEvents.viewport);\n\n const handleClick = useCallback(\n (info: PickingInfo, event: MjolnirGestureEvent) => {\n // send full pickingInfo and event to user-defined onClick\n onClick?.(info, event);\n\n emitClick({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitClick, id, onClick],\n );\n\n const handleHover = useCallback(\n (info: PickingInfo, event: MjolnirPointerEvent) => {\n // send full pickingInfo and event to user-defined onHover\n onHover?.(info, event);\n\n emitHover({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitHover, id, onHover],\n );\n\n const handleGetCursor = useCallback(() => {\n return getCursor(id);\n }, [id]);\n\n const handleViewStateChange = useEffectEvent(\n (params: ViewStateChangeParameters) => {\n onViewStateChange?.(params);\n\n const {\n viewId,\n viewState: { latitude, longitude, zoom },\n } = params;\n\n // @ts-expect-error squirrelly deckglInstance typing\n const viewport = deckglInstance._deck\n .getViewports()\n // @ts-expect-error squirrelly deckglInstance typing\n ?.find((vp) => vp.id === viewId);\n\n emitViewport({\n id,\n bounds: viewport?.getBounds(),\n latitude,\n longitude,\n zoom,\n width: viewport?.width ?? 0,\n height: viewport?.height ?? 0,\n });\n },\n );\n\n const handleLoad = useEffectEvent(() => {\n //--- force update viewport state once all viewports initialized ---\n // @ts-expect-error squirrelly deckglInstance typing\n const viewports = deckglInstance._deck.getViewports() ?? [];\n for (const vp of viewports) {\n handleViewStateChange({\n viewId: vp.id,\n viewState: {\n latitude: vp.latitude,\n longitude: vp.longitude,\n zoom: vp.zoom,\n id: vp.id,\n bounds: vp.getBounds(),\n width: vp.width,\n height: vp.height,\n },\n } as ViewStateChangeParameters);\n }\n });\n\n return (\n <div id={container} className={className}>\n {enableControlEvents && <MapControls id={id} mapRef={mapRef} />}\n <MapProvider id={id}>\n <MapLibre\n onMove={(evt) => setCameraState(evt.viewState)}\n mapStyle={styleUrl}\n ref={mapRef}\n {...mapOptions}\n >\n <Deckgl\n {...rest}\n controller={controller}\n interleaved={interleaved}\n getCursor={handleGetCursor}\n useDevicePixels={useDevicePixels}\n onClick={handleClick}\n pickingRadius={pickingRadius ?? PICKING_RADIUS}\n onHover={handleHover}\n onLoad={handleLoad}\n onViewStateChange={handleViewStateChange}\n // @ts-expect-error - DeckglProps parameters type is overly strict for WebGL parameter spreading.\n // The merged object is valid at runtime but TypeScript cannot verify all possible parameter combinations.\n parameters={{ ...PARAMETERS, ...parameters }}\n >\n <AddDeckglControl />\n {children}\n </Deckgl>\n </MapLibre>\n </MapProvider>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
'use client';
|
|
15
15
|
|
|
16
|
-
import { clearMapModeState } from "../../map-mode/store.js";
|
|
17
16
|
import { clearCursorState } from "../../map-cursor/store.js";
|
|
17
|
+
import { clearMapModeState } from "../../map-mode/store.js";
|
|
18
18
|
import { createContext, useEffect } from "react";
|
|
19
19
|
import { jsx } from "react/jsx-runtime";
|
|
20
20
|
|
package/dist/deckgl/index.d.ts
CHANGED
|
@@ -15,11 +15,11 @@ import { BaseMapProps, MapClickEvent, MapClickPayload, MapControlPayload, MapDis
|
|
|
15
15
|
import { DARK_BASE_MAP_STYLE, LIGHT_BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
|
|
16
16
|
import { BaseMap } from "./base-map/index.js";
|
|
17
17
|
import { SavedViewportOptions, createSavedViewport } from "./saved-viewports/index.js";
|
|
18
|
-
import { CircleProperties, CircleRadius,
|
|
18
|
+
import { CircleProperties, CircleRadius, EllipseProperties, Shape, ShapeFeature, ShapeFeatureProperties, ShapeFeatureType, ShapeFeatureTypeValues, ShapeId, StyleProperties } from "./shapes/shared/types.js";
|
|
19
19
|
import { DisplayShapeLayerProps, StyledFeature, StyledFeatureProperties } from "./shapes/display-shape-layer/types.js";
|
|
20
20
|
import { DisplayShapeLayer } from "./shapes/display-shape-layer/index.js";
|
|
21
|
-
import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES,
|
|
22
|
-
import {
|
|
21
|
+
import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, LINE_PATTERNS, LINE_WIDTHS, SHAPE_LAYER_IDS } from "./shapes/shared/constants.js";
|
|
22
|
+
import { ShapeEventType, ShapeEvents } from "./shapes/shared/events.js";
|
|
23
23
|
import "./shapes/index.js";
|
|
24
24
|
import { SymbolLayer, SymbolLayerProps } from "./symbol-layer/index.js";
|
|
25
|
-
export { BaseMap, type BaseMapProps, type CircleProperties, type CircleRadius, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES,
|
|
25
|
+
export { BaseMap, type BaseMapProps, type CircleProperties, type CircleRadius, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, DisplayShapeLayer, type DisplayShapeLayerProps, type EllipseProperties, LIGHT_BASE_MAP_STYLE, LINE_PATTERNS, LINE_WIDTHS, type MapClickEvent, type MapClickPayload, type MapControlPayload, type MapDisablePanEvent, type MapDisableZoomEvent, type MapEnablePanEvent, type MapEnableZoomEvent, type MapEventType, MapEvents, MapEventsNamespace, type MapHoverEvent, type MapHoverPayload, PARAMETERS, SHAPE_LAYER_IDS, type SavedViewportOptions, type Shape, type ShapeEventType, ShapeEvents, type ShapeFeature, type ShapeFeatureProperties, ShapeFeatureType, type ShapeFeatureTypeValues, type ShapeId, type StyleProperties, type StyledFeature, type StyledFeatureProperties, SymbolLayer, type SymbolLayerProps, createSavedViewport };
|
package/dist/deckgl/index.js
CHANGED
|
@@ -15,10 +15,10 @@ import { MapEvents, MapEventsNamespace } from "./base-map/events.js";
|
|
|
15
15
|
import { DARK_BASE_MAP_STYLE, LIGHT_BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
|
|
16
16
|
import { BaseMap } from "./base-map/index.js";
|
|
17
17
|
import { createSavedViewport } from "./saved-viewports/index.js";
|
|
18
|
-
import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES,
|
|
19
|
-
import {
|
|
20
|
-
import { DisplayShapeLayer } from "./shapes/display-shape-layer/index.js";
|
|
18
|
+
import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, LINE_PATTERNS, LINE_WIDTHS, SHAPE_LAYER_IDS } from "./shapes/shared/constants.js";
|
|
19
|
+
import { ShapeEvents } from "./shapes/shared/events.js";
|
|
21
20
|
import { ShapeFeatureType } from "./shapes/shared/types.js";
|
|
21
|
+
import { DisplayShapeLayer } from "./shapes/display-shape-layer/index.js";
|
|
22
22
|
import { SymbolLayer } from "./symbol-layer/index.js";
|
|
23
23
|
|
|
24
|
-
export { BaseMap, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, DisplayShapeLayer, LIGHT_BASE_MAP_STYLE, MapEvents, MapEventsNamespace, PARAMETERS,
|
|
24
|
+
export { BaseMap, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, DisplayShapeLayer, LIGHT_BASE_MAP_STYLE, LINE_PATTERNS, LINE_WIDTHS, MapEvents, MapEventsNamespace, PARAMETERS, SHAPE_LAYER_IDS, ShapeEvents, ShapeFeatureType, SymbolLayer, createSavedViewport };
|
|
@@ -11,14 +11,22 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
import { getLogger } from "@accelint/logger";
|
|
15
|
+
|
|
14
16
|
//#region src/deckgl/saved-viewports/storage.ts
|
|
17
|
+
const logger = getLogger({
|
|
18
|
+
enabled: process.env.NODE_ENV !== "production" && process.env.NODE_ENV !== "test",
|
|
19
|
+
level: "warn",
|
|
20
|
+
prefix: "[SavedViewports]",
|
|
21
|
+
pretty: true
|
|
22
|
+
});
|
|
15
23
|
const STORAGE_ID = "deckgl-saved-viewports";
|
|
16
24
|
const getContainerKey = (uniqueIdentifier) => uniqueIdentifier ? `${STORAGE_ID}-${uniqueIdentifier}` : STORAGE_ID;
|
|
17
25
|
const getContainer = (containerKey) => {
|
|
18
26
|
try {
|
|
19
27
|
return JSON.parse(localStorage.getItem(containerKey) ?? "{}");
|
|
20
28
|
} catch {
|
|
21
|
-
|
|
29
|
+
logger.warn(`Failed to parse storage container for key: ${containerKey}, returning empty container.`);
|
|
22
30
|
return {};
|
|
23
31
|
}
|
|
24
32
|
};
|
|
@@ -30,7 +38,7 @@ const persist = (id, obj, uniqueIdentifier) => {
|
|
|
30
38
|
};
|
|
31
39
|
const retrieve = (id, uniqueIdentifier) => {
|
|
32
40
|
const obj = getContainer(getContainerKey(uniqueIdentifier))[id];
|
|
33
|
-
if (!obj)
|
|
41
|
+
if (!obj) logger.warn(`Object with id: ${id} does not exist`);
|
|
34
42
|
return obj;
|
|
35
43
|
};
|
|
36
44
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","names":[],"sources":["../../../src/deckgl/saved-viewports/storage.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { MapViewState } from '@deck.gl/core';\n\nexport const STORAGE_ID = 'deckgl-saved-viewports';\n\nconst getContainerKey = (uniqueIdentifier?: string) =>\n uniqueIdentifier ? `${STORAGE_ID}-${uniqueIdentifier}` : STORAGE_ID;\n\nconst getContainer = (containerKey: string) => {\n try {\n return JSON.parse(localStorage.getItem(containerKey) ?? '{}');\n } catch {\n
|
|
1
|
+
{"version":3,"file":"storage.js","names":[],"sources":["../../../src/deckgl/saved-viewports/storage.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { getLogger } from '@accelint/logger';\nimport type { MapViewState } from '@deck.gl/core';\n\nconst logger = getLogger({\n enabled:\n process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test',\n level: 'warn',\n prefix: '[SavedViewports]',\n pretty: true,\n});\n\nexport const STORAGE_ID = 'deckgl-saved-viewports';\n\nconst getContainerKey = (uniqueIdentifier?: string) =>\n uniqueIdentifier ? `${STORAGE_ID}-${uniqueIdentifier}` : STORAGE_ID;\n\nconst getContainer = (containerKey: string) => {\n try {\n return JSON.parse(localStorage.getItem(containerKey) ?? '{}');\n } catch {\n logger.warn(\n `Failed to parse storage container for key: ${containerKey}, returning empty container.`,\n );\n return {};\n }\n};\n\nexport const persist = (\n id: string,\n obj: MapViewState,\n uniqueIdentifier?: string,\n) => {\n const containerKey = getContainerKey(uniqueIdentifier);\n const container = getContainer(containerKey);\n container[id] = obj;\n localStorage.setItem(containerKey, JSON.stringify(container));\n};\n\nexport const retrieve = (id: string, uniqueIdentifier?: string) => {\n const containerKey = getContainerKey(uniqueIdentifier);\n const container = getContainer(containerKey);\n const obj = container[id];\n if (!obj) {\n logger.warn(`Object with id: ${id} does not exist`);\n }\n return obj;\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,MAAM,SAAS,UAAU;CACvB,SACE,QAAQ,IAAI,aAAa,gBAAgB,QAAQ,IAAI,aAAa;CACpE,OAAO;CACP,QAAQ;CACR,QAAQ;CACT,CAAC;AAEF,MAAa,aAAa;AAE1B,MAAM,mBAAmB,qBACvB,mBAAmB,GAAG,WAAW,GAAG,qBAAqB;AAE3D,MAAM,gBAAgB,iBAAyB;AAC7C,KAAI;AACF,SAAO,KAAK,MAAM,aAAa,QAAQ,aAAa,IAAI,KAAK;SACvD;AACN,SAAO,KACL,8CAA8C,aAAa,8BAC5D;AACD,SAAO,EAAE;;;AAIb,MAAa,WACX,IACA,KACA,qBACG;CACH,MAAM,eAAe,gBAAgB,iBAAiB;CACtD,MAAM,YAAY,aAAa,aAAa;AAC5C,WAAU,MAAM;AAChB,cAAa,QAAQ,cAAc,KAAK,UAAU,UAAU,CAAC;;AAG/D,MAAa,YAAY,IAAY,qBAA8B;CAGjE,MAAM,MADY,aADG,gBAAgB,iBAAiB,CACV,CACtB;AACtB,KAAI,CAAC,IACH,QAAO,KAAK,mBAAmB,GAAG,iBAAiB;AAErD,QAAO"}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
'use client';
|
|
15
15
|
|
|
16
|
+
import { DEFAULT_COLORS } from "../shared/constants.js";
|
|
17
|
+
|
|
16
18
|
//#region src/deckgl/shapes/display-shape-layer/constants.ts
|
|
17
19
|
/**
|
|
18
20
|
* Map interaction constants
|
|
@@ -27,12 +29,7 @@ const MAP_INTERACTION = {
|
|
|
27
29
|
* Selection highlight configuration
|
|
28
30
|
*/
|
|
29
31
|
const SELECTION_HIGHLIGHT = {
|
|
30
|
-
COLOR:
|
|
31
|
-
40,
|
|
32
|
-
245,
|
|
33
|
-
190,
|
|
34
|
-
100
|
|
35
|
-
],
|
|
32
|
+
COLOR: DEFAULT_COLORS.highlight,
|
|
36
33
|
ICON_SIZE_INCREASE: 8
|
|
37
34
|
};
|
|
38
35
|
/**
|
|
@@ -50,12 +47,12 @@ const COFFIN_CORNERS = {
|
|
|
50
47
|
*/
|
|
51
48
|
const DEFAULT_DISPLAY_PROPS = {
|
|
52
49
|
pickable: true,
|
|
53
|
-
showLabels:
|
|
50
|
+
showLabels: "always",
|
|
54
51
|
showHighlight: false,
|
|
55
52
|
applyBaseOpacity: true,
|
|
56
53
|
highlightColor: SELECTION_HIGHLIGHT.COLOR
|
|
57
54
|
};
|
|
58
55
|
|
|
59
56
|
//#endregion
|
|
60
|
-
export { COFFIN_CORNERS, DEFAULT_DISPLAY_PROPS, MAP_INTERACTION
|
|
57
|
+
export { COFFIN_CORNERS, DEFAULT_DISPLAY_PROPS, MAP_INTERACTION };
|
|
61
58
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/deckgl/shapes/display-shape-layer/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\n/**\n * Map interaction constants\n * Values derived from ngc2 for consistency\n */\nexport const MAP_INTERACTION = {\n LINE_WIDTH_MIN_PIXELS: 1, // Minimum line width in pixels\n ICON_SIZE: 38, // Size of shape icons\n ICON_HOVER_SIZE_INCREASE: 5, // Additional pixels added on hover\n} as const;\n\n/**\n * Selection highlight configuration\n */\nexport const SELECTION_HIGHLIGHT = {\n
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/deckgl/shapes/display-shape-layer/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { DEFAULT_COLORS } from '../shared/constants';\n\n/**\n * Map interaction constants\n * Values derived from ngc2 for consistency\n */\nexport const MAP_INTERACTION = {\n LINE_WIDTH_MIN_PIXELS: 1, // Minimum line width in pixels\n ICON_SIZE: 38, // Size of shape icons\n ICON_HOVER_SIZE_INCREASE: 5, // Additional pixels added on hover\n} as const;\n\n/**\n * Selection highlight configuration\n */\nexport const SELECTION_HIGHLIGHT = {\n /** Uses DEFAULT_COLORS.highlight from shared constants */\n COLOR: DEFAULT_COLORS.highlight,\n ICON_SIZE_INCREASE: 8, // Additional pixels for highlight icon\n} as const;\n\n/**\n * Coffin corners configuration for Point selection/hover feedback\n * Coffin corners are bracket-like corners that appear around points\n */\nexport const COFFIN_CORNERS = {\n /** Icon name for hover state (white corners with background fill) */\n HOVER_ICON: 'coffin-corners-hover',\n /** Icon name for selected state (blue corners, no fill) */\n SELECTED_ICON: 'coffin-corners-selected',\n /** Icon name for selected+hover state (blue corners with background fill) */\n SELECTED_HOVER_ICON: 'coffin-corners-selected-hover',\n /** Size of the coffin corners icon */\n SIZE: 38,\n} as const;\n\n/**\n * Default props for DisplayShapeLayer\n */\nexport const DEFAULT_DISPLAY_PROPS = {\n pickable: true,\n showLabels: 'always' as const,\n showHighlight: false,\n applyBaseOpacity: true,\n highlightColor: SELECTION_HIGHLIGHT.COLOR,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,kBAAkB;CAC7B,uBAAuB;CACvB,WAAW;CACX,0BAA0B;CAC3B;;;;AAKD,MAAa,sBAAsB;CAEjC,OAAO,eAAe;CACtB,oBAAoB;CACrB;;;;;AAMD,MAAa,iBAAiB;CAE5B,YAAY;CAEZ,eAAe;CAEf,qBAAqB;CAErB,MAAM;CACP;;;;AAKD,MAAa,wBAAwB;CACnC,UAAU;CACV,YAAY;CACZ,eAAe;CACf,kBAAkB;CAClB,gBAAgB,oBAAoB;CACrC"}
|
|
@@ -17,16 +17,16 @@ import { CompositeLayer, Layer, PickingInfo } from "@deck.gl/core";
|
|
|
17
17
|
|
|
18
18
|
//#region src/deckgl/shapes/display-shape-layer/index.d.ts
|
|
19
19
|
/**
|
|
20
|
-
* State
|
|
20
|
+
* State type for DisplayShapeLayer
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
type DisplayShapeLayerState = {
|
|
23
23
|
/** Index of currently hovered shape, undefined when not hovering */
|
|
24
24
|
hoverIndex?: number;
|
|
25
25
|
/** ID of the last hovered shape for event deduplication */
|
|
26
26
|
lastHoveredId?: ShapeId | null;
|
|
27
27
|
/** Allow additional properties from base layer state */
|
|
28
28
|
[key: string]: unknown;
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
30
|
/**
|
|
31
31
|
* DisplayShapeLayer - Read-only shapes visualization layer
|
|
32
32
|
*
|
|
@@ -37,15 +37,15 @@ interface DisplayShapeLayerState {
|
|
|
37
37
|
* - **Multiple geometry types**: Point, LineString, Polygon, and Circle
|
|
38
38
|
* - **Icon support**: Custom icons for Point geometries via icon atlases
|
|
39
39
|
* - **Interactive selection**: Click handling with dotted border and optional highlight
|
|
40
|
-
* - **Hover effects**:
|
|
40
|
+
* - **Hover effects**: Border/outline width increases on hover for better UX
|
|
41
41
|
* - **Customizable labels**: Flexible label positioning with per-shape or global options
|
|
42
|
-
* - **Style properties**: Full control over colors,
|
|
42
|
+
* - **Style properties**: Full control over colors, border/outline patterns, and opacity
|
|
43
43
|
* - **Event bus integration**: Automatically emits shape events via @accelint/bus
|
|
44
44
|
* - **Multi-map support**: Events include map instance ID for isolation
|
|
45
45
|
*
|
|
46
46
|
* ## Selection Visual Feedback
|
|
47
47
|
* When a shape is selected via `selectedShapeId`:
|
|
48
|
-
* - The shape's
|
|
48
|
+
* - The shape's border/outline pattern changes to dotted
|
|
49
49
|
* - An optional highlight renders underneath (controlled by `showHighlight` prop)
|
|
50
50
|
*
|
|
51
51
|
* ## Layer Structure
|
|
@@ -65,19 +65,19 @@ interface DisplayShapeLayerState {
|
|
|
65
65
|
* - `shapes:selected` - Emitted when a shape is clicked (includes mapId)
|
|
66
66
|
* - `shapes:hovered` - Emitted when the hovered shape changes (deduplicated, includes mapId)
|
|
67
67
|
*
|
|
68
|
-
* For selection with auto-deselection, use the companion `
|
|
68
|
+
* For selection with auto-deselection, use the companion `useSelectShape` hook which handles
|
|
69
69
|
* all the event wiring automatically. See the example below.
|
|
70
70
|
*
|
|
71
|
-
* @example Basic usage with
|
|
71
|
+
* @example Basic usage with useSelectShape hook (recommended)
|
|
72
72
|
* ```tsx
|
|
73
73
|
* import '@accelint/map-toolkit/deckgl/shapes/display-shape-layer/fiber';
|
|
74
|
-
* import {
|
|
74
|
+
* import { useSelectShape } from '@accelint/map-toolkit/deckgl/shapes';
|
|
75
75
|
* import { uuid } from '@accelint/core';
|
|
76
76
|
*
|
|
77
77
|
* const MAP_ID = uuid();
|
|
78
78
|
*
|
|
79
79
|
* function MapWithShapes() {
|
|
80
|
-
* const { selectedId } =
|
|
80
|
+
* const { selectedId } = useSelectShape(MAP_ID);
|
|
81
81
|
*
|
|
82
82
|
* return (
|
|
83
83
|
* <BaseMap id={MAP_ID}>
|
|
@@ -86,7 +86,7 @@ interface DisplayShapeLayerState {
|
|
|
86
86
|
* mapId={MAP_ID}
|
|
87
87
|
* data={shapes}
|
|
88
88
|
* selectedShapeId={selectedId}
|
|
89
|
-
* showLabels=
|
|
89
|
+
* showLabels="always"
|
|
90
90
|
* pickable={true}
|
|
91
91
|
* />
|
|
92
92
|
* </BaseMap>
|
|
@@ -99,7 +99,7 @@ interface DisplayShapeLayerState {
|
|
|
99
99
|
* <displayShapeLayer
|
|
100
100
|
* id="my-shapes"
|
|
101
101
|
* data={shapes}
|
|
102
|
-
* showLabels=
|
|
102
|
+
* showLabels="always"
|
|
103
103
|
* labelOptions={{
|
|
104
104
|
* // Position circle labels at the top
|
|
105
105
|
* circleLabelCoordinateAnchor: 'top',
|
|
@@ -118,10 +118,10 @@ declare class DisplayShapeLayer extends CompositeLayer<DisplayShapeLayerProps> {
|
|
|
118
118
|
static layerName: string;
|
|
119
119
|
static defaultProps: {
|
|
120
120
|
pickable: boolean;
|
|
121
|
-
showLabels:
|
|
121
|
+
showLabels: "always";
|
|
122
122
|
showHighlight: boolean;
|
|
123
123
|
applyBaseOpacity: boolean;
|
|
124
|
-
highlightColor:
|
|
124
|
+
highlightColor: _deck_gl_core0.Color;
|
|
125
125
|
};
|
|
126
126
|
/**
|
|
127
127
|
* Clean up state and caches when layer is destroyed
|
|
@@ -194,6 +194,10 @@ declare class DisplayShapeLayer extends CompositeLayer<DisplayShapeLayerProps> {
|
|
|
194
194
|
private renderMainLayer;
|
|
195
195
|
/**
|
|
196
196
|
* Render labels layer
|
|
197
|
+
* Supports three modes:
|
|
198
|
+
* - 'always': Show labels for all shapes
|
|
199
|
+
* - 'hover': Show label only for the currently hovered shape
|
|
200
|
+
* - 'never': No labels
|
|
197
201
|
*/
|
|
198
202
|
private renderLabelsLayer;
|
|
199
203
|
/**
|
|
@@ -15,15 +15,23 @@
|
|
|
15
15
|
|
|
16
16
|
import { DASH_ARRAYS, SHAPE_LAYER_IDS } from "../shared/constants.js";
|
|
17
17
|
import { ShapeEvents } from "../shared/events.js";
|
|
18
|
+
import { getDashArray, getFillColor, getLineColor } from "../shared/utils/style-utils.js";
|
|
18
19
|
import { COFFIN_CORNERS, DEFAULT_DISPLAY_PROPS, MAP_INTERACTION } from "./constants.js";
|
|
19
20
|
import { createShapeLabelLayer } from "./shape-label-layer.js";
|
|
20
|
-
import {
|
|
21
|
+
import { getHighlightColor, getHighlightLineWidth, getHoverLineWidth } from "./utils/display-style.js";
|
|
21
22
|
import { Broadcast } from "@accelint/bus";
|
|
23
|
+
import { getLogger } from "@accelint/logger";
|
|
22
24
|
import { CompositeLayer } from "@deck.gl/core";
|
|
23
25
|
import { PathStyleExtension } from "@deck.gl/extensions";
|
|
24
26
|
import { GeoJsonLayer, IconLayer } from "@deck.gl/layers";
|
|
25
27
|
|
|
26
28
|
//#region src/deckgl/shapes/display-shape-layer/index.ts
|
|
29
|
+
const logger = getLogger({
|
|
30
|
+
enabled: process.env.NODE_ENV !== "production",
|
|
31
|
+
level: "warn",
|
|
32
|
+
prefix: "[DisplayShapeLayer]",
|
|
33
|
+
pretty: true
|
|
34
|
+
});
|
|
27
35
|
/**
|
|
28
36
|
* Typed event bus instance for shape events.
|
|
29
37
|
* Provides type-safe event emission for shape interactions.
|
|
@@ -39,15 +47,15 @@ const shapeBus = Broadcast.getInstance();
|
|
|
39
47
|
* - **Multiple geometry types**: Point, LineString, Polygon, and Circle
|
|
40
48
|
* - **Icon support**: Custom icons for Point geometries via icon atlases
|
|
41
49
|
* - **Interactive selection**: Click handling with dotted border and optional highlight
|
|
42
|
-
* - **Hover effects**:
|
|
50
|
+
* - **Hover effects**: Border/outline width increases on hover for better UX
|
|
43
51
|
* - **Customizable labels**: Flexible label positioning with per-shape or global options
|
|
44
|
-
* - **Style properties**: Full control over colors,
|
|
52
|
+
* - **Style properties**: Full control over colors, border/outline patterns, and opacity
|
|
45
53
|
* - **Event bus integration**: Automatically emits shape events via @accelint/bus
|
|
46
54
|
* - **Multi-map support**: Events include map instance ID for isolation
|
|
47
55
|
*
|
|
48
56
|
* ## Selection Visual Feedback
|
|
49
57
|
* When a shape is selected via `selectedShapeId`:
|
|
50
|
-
* - The shape's
|
|
58
|
+
* - The shape's border/outline pattern changes to dotted
|
|
51
59
|
* - An optional highlight renders underneath (controlled by `showHighlight` prop)
|
|
52
60
|
*
|
|
53
61
|
* ## Layer Structure
|
|
@@ -67,19 +75,19 @@ const shapeBus = Broadcast.getInstance();
|
|
|
67
75
|
* - `shapes:selected` - Emitted when a shape is clicked (includes mapId)
|
|
68
76
|
* - `shapes:hovered` - Emitted when the hovered shape changes (deduplicated, includes mapId)
|
|
69
77
|
*
|
|
70
|
-
* For selection with auto-deselection, use the companion `
|
|
78
|
+
* For selection with auto-deselection, use the companion `useSelectShape` hook which handles
|
|
71
79
|
* all the event wiring automatically. See the example below.
|
|
72
80
|
*
|
|
73
|
-
* @example Basic usage with
|
|
81
|
+
* @example Basic usage with useSelectShape hook (recommended)
|
|
74
82
|
* ```tsx
|
|
75
83
|
* import '@accelint/map-toolkit/deckgl/shapes/display-shape-layer/fiber';
|
|
76
|
-
* import {
|
|
84
|
+
* import { useSelectShape } from '@accelint/map-toolkit/deckgl/shapes';
|
|
77
85
|
* import { uuid } from '@accelint/core';
|
|
78
86
|
*
|
|
79
87
|
* const MAP_ID = uuid();
|
|
80
88
|
*
|
|
81
89
|
* function MapWithShapes() {
|
|
82
|
-
* const { selectedId } =
|
|
90
|
+
* const { selectedId } = useSelectShape(MAP_ID);
|
|
83
91
|
*
|
|
84
92
|
* return (
|
|
85
93
|
* <BaseMap id={MAP_ID}>
|
|
@@ -88,7 +96,7 @@ const shapeBus = Broadcast.getInstance();
|
|
|
88
96
|
* mapId={MAP_ID}
|
|
89
97
|
* data={shapes}
|
|
90
98
|
* selectedShapeId={selectedId}
|
|
91
|
-
* showLabels=
|
|
99
|
+
* showLabels="always"
|
|
92
100
|
* pickable={true}
|
|
93
101
|
* />
|
|
94
102
|
* </BaseMap>
|
|
@@ -101,7 +109,7 @@ const shapeBus = Broadcast.getInstance();
|
|
|
101
109
|
* <displayShapeLayer
|
|
102
110
|
* id="my-shapes"
|
|
103
111
|
* data={shapes}
|
|
104
|
-
* showLabels=
|
|
112
|
+
* showLabels="always"
|
|
105
113
|
* labelOptions={{
|
|
106
114
|
* // Position circle labels at the top
|
|
107
115
|
* circleLabelCoordinateAnchor: 'top',
|
|
@@ -150,16 +158,22 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
150
158
|
getFeaturesWithId() {
|
|
151
159
|
const { data } = this.props;
|
|
152
160
|
if (this.featuresCache?.data === data) return this.featuresCache.features;
|
|
153
|
-
const features =
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
const features = [];
|
|
162
|
+
const shapeIdToIndex = /* @__PURE__ */ new Map();
|
|
163
|
+
for (const [i, shape] of data.entries()) {
|
|
164
|
+
features.push({
|
|
165
|
+
...shape.feature,
|
|
166
|
+
properties: {
|
|
167
|
+
...shape.feature.properties,
|
|
168
|
+
shapeId: shape.id
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
shapeIdToIndex.set(shape.id, i);
|
|
172
|
+
}
|
|
160
173
|
this.featuresCache = {
|
|
161
174
|
data,
|
|
162
|
-
features
|
|
175
|
+
features,
|
|
176
|
+
shapeIdToIndex
|
|
163
177
|
};
|
|
164
178
|
return features;
|
|
165
179
|
}
|
|
@@ -242,19 +256,25 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
242
256
|
*/
|
|
243
257
|
renderCoffinCornersLayer(features) {
|
|
244
258
|
const { selectedShapeId } = this.props;
|
|
259
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
260
|
+
const shapeIdToIndex = this.featuresCache?.shapeIdToIndex;
|
|
261
|
+
if (!shapeIdToIndex) return null;
|
|
245
262
|
const pointFeatures = features.filter((f) => {
|
|
246
263
|
if (f.geometry.type !== "Point") return false;
|
|
247
264
|
if (!!!f.properties?.styleProperties?.icon) return false;
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
265
|
+
const shapeId = f.properties?.shapeId;
|
|
266
|
+
const isSelected = shapeId === selectedShapeId;
|
|
267
|
+
const featureIndex = shapeId ? shapeIdToIndex.get(shapeId) : void 0;
|
|
268
|
+
return isSelected || hoverIndex !== void 0 && featureIndex === hoverIndex;
|
|
251
269
|
});
|
|
252
270
|
if (pointFeatures.length === 0) return null;
|
|
253
271
|
const firstPointIcon = pointFeatures[0]?.properties?.styleProperties?.icon;
|
|
254
272
|
const iconAtlas = firstPointIcon?.atlas;
|
|
255
273
|
const iconMapping = firstPointIcon?.mapping;
|
|
256
|
-
if (!iconAtlas)
|
|
257
|
-
|
|
274
|
+
if (!(iconAtlas && iconMapping)) {
|
|
275
|
+
logger.warn("Point shape has icon style but missing iconAtlas or iconMapping - coffin corners will not render");
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
258
278
|
const extendedMapping = {
|
|
259
279
|
...iconMapping,
|
|
260
280
|
[COFFIN_CORNERS.HOVER_ICON]: {
|
|
@@ -285,9 +305,10 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
285
305
|
iconAtlas,
|
|
286
306
|
iconMapping: extendedMapping,
|
|
287
307
|
getIcon: (d) => {
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
|
|
308
|
+
const shapeId = d.properties?.shapeId;
|
|
309
|
+
const isSelected = shapeId === selectedShapeId;
|
|
310
|
+
const featureIndex = shapeId ? shapeIdToIndex.get(shapeId) : void 0;
|
|
311
|
+
if (isSelected && hoverIndex !== void 0 && featureIndex === hoverIndex) return COFFIN_CORNERS.SELECTED_HOVER_ICON;
|
|
291
312
|
if (isSelected) return COFFIN_CORNERS.SELECTED_ICON;
|
|
292
313
|
return COFFIN_CORNERS.HOVER_ICON;
|
|
293
314
|
},
|
|
@@ -338,7 +359,7 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
338
359
|
filled: true,
|
|
339
360
|
stroked: true,
|
|
340
361
|
getFillColor: (d) => getFillColor(d, applyBaseOpacity),
|
|
341
|
-
getLineColor
|
|
362
|
+
getLineColor,
|
|
342
363
|
getLineWidth: (d, info) => {
|
|
343
364
|
return getHoverLineWidth(d, info?.index === this.state?.hoverIndex);
|
|
344
365
|
},
|
|
@@ -357,7 +378,7 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
357
378
|
getIconSize: (d) => {
|
|
358
379
|
return d.properties?.styleProperties?.icon?.size ?? MAP_INTERACTION.ICON_SIZE;
|
|
359
380
|
},
|
|
360
|
-
getIconColor:
|
|
381
|
+
getIconColor: getLineColor,
|
|
361
382
|
getIconPixelOffset: (d) => {
|
|
362
383
|
return [-1, -(d.properties?.styleProperties?.icon?.size ?? MAP_INTERACTION.ICON_SIZE) / 2];
|
|
363
384
|
},
|
|
@@ -387,13 +408,25 @@ var DisplayShapeLayer = class extends CompositeLayer {
|
|
|
387
408
|
}
|
|
388
409
|
/**
|
|
389
410
|
* Render labels layer
|
|
411
|
+
* Supports three modes:
|
|
412
|
+
* - 'always': Show labels for all shapes
|
|
413
|
+
* - 'hover': Show label only for the currently hovered shape
|
|
414
|
+
* - 'never': No labels
|
|
390
415
|
*/
|
|
391
416
|
renderLabelsLayer() {
|
|
392
417
|
const { showLabels, data, labelOptions } = this.props;
|
|
393
|
-
if (
|
|
418
|
+
if (showLabels === "never") return null;
|
|
419
|
+
let labelData = data;
|
|
420
|
+
if (showLabels === "hover") {
|
|
421
|
+
const hoverIndex = this.state?.hoverIndex;
|
|
422
|
+
if (hoverIndex === void 0) return null;
|
|
423
|
+
const hoveredShape = data[hoverIndex];
|
|
424
|
+
labelData = hoveredShape ? [hoveredShape] : [];
|
|
425
|
+
}
|
|
426
|
+
if (labelData.length === 0) return null;
|
|
394
427
|
return createShapeLabelLayer({
|
|
395
428
|
id: `${this.props.id}-${SHAPE_LAYER_IDS.DISPLAY_LABELS}`,
|
|
396
|
-
data,
|
|
429
|
+
data: labelData,
|
|
397
430
|
labelOptions
|
|
398
431
|
});
|
|
399
432
|
}
|