@trackunit/react-map 0.0.4-alpha-9d327375fc1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +296 -0
  2. package/index.cjs.js +9851 -0
  3. package/index.d.ts +1 -0
  4. package/index.esm.js +9752 -0
  5. package/package.json +34 -0
  6. package/src/annotations/getDescriptorContentKey.d.ts +14 -0
  7. package/src/annotations/mapAnnotations.d.ts +76 -0
  8. package/src/annotations/useMapAnnotation.d.ts +16 -0
  9. package/src/annotations/useMapAnnotations.d.ts +17 -0
  10. package/src/appearance/AppearancePreview.d.ts +27 -0
  11. package/src/appearance/AppearancePreviewGrid.d.ts +29 -0
  12. package/src/appearance/appearanceTypes.d.ts +84 -0
  13. package/src/appearance/useMapAppearanceControls.d.ts +29 -0
  14. package/src/clusters/ClusterMarker.d.ts +41 -0
  15. package/src/clusters/ClusterStick.d.ts +97 -0
  16. package/src/clusters/formatClusterCount.d.ts +11 -0
  17. package/src/clusters/stories/ClusterMarkerCompactFormatsDemo.d.ts +7 -0
  18. package/src/clusters/stories/ClusterMarkerCountOnlyDemo.d.ts +7 -0
  19. package/src/clusters/stories/ClusterMarkerDefaultDemo.d.ts +12 -0
  20. package/src/clusters/stories/ClusterMarkerPlaygroundDemo.d.ts +10 -0
  21. package/src/clusters/stories/ClusterMarkerStateDemo.d.ts +9 -0
  22. package/src/clusters/stories/ClusterMarkerWithSegmentsDemo.d.ts +7 -0
  23. package/src/clusters/stories/ClusterMarkerWithSticksDemo.d.ts +10 -0
  24. package/src/clusters/useClusterCountFormat.d.ts +19 -0
  25. package/src/controls/AnnotationRenderer.d.ts +17 -0
  26. package/src/controls/AnnotationStack.d.ts +21 -0
  27. package/src/controls/ControlRenderer.d.ts +20 -0
  28. package/src/controls/Controls.d.ts +15 -0
  29. package/src/controls/annotationButtonClasses.d.ts +13 -0
  30. package/src/controls/collapseControls.d.ts +37 -0
  31. package/src/controls/defineControlStack.d.ts +10 -0
  32. package/src/controls/deriveResponsiveMode.d.ts +19 -0
  33. package/src/controls/longitudeToGlobeIcon.d.ts +3 -0
  34. package/src/controls/renderers/boolean/BooleanButton.d.ts +16 -0
  35. package/src/controls/renderers/boolean/MenuBooleanItem.d.ts +20 -0
  36. package/src/controls/renderers/boolean/MenuCheckbox.d.ts +14 -0
  37. package/src/controls/renderers/boolean/MenuToggle.d.ts +14 -0
  38. package/src/controls/renderers/button/Button.d.ts +14 -0
  39. package/src/controls/renderers/button/MenuButton.d.ts +16 -0
  40. package/src/controls/renderers/custom/Custom.d.ts +22 -0
  41. package/src/controls/renderers/menu/Menu.d.ts +23 -0
  42. package/src/controls/renderers/menu/Modal.d.ts +21 -0
  43. package/src/controls/renderers/menu/SectionHeader.d.ts +14 -0
  44. package/src/controls/renderers/menu/Separator.d.ts +11 -0
  45. package/src/controls/renderers/radio-group/MenuRadioGroup.d.ts +15 -0
  46. package/src/controls/renderers/radio-group/RadioGroup.d.ts +19 -0
  47. package/src/controls/renderers/radio-group/RadioGroupField.d.ts +17 -0
  48. package/src/controls/renderers/search/MenuSearch.d.ts +15 -0
  49. package/src/controls/renderers/search/Search.d.ts +14 -0
  50. package/src/controls/renderers/select/MenuSelect.d.ts +15 -0
  51. package/src/controls/renderers/select/Select.d.ts +14 -0
  52. package/src/controls/renderers/stepper/MenuStepper.d.ts +17 -0
  53. package/src/controls/renderers/stepper/Stepper.d.ts +18 -0
  54. package/src/controls/renderers/toggle-group/MenuToggleGroup.d.ts +17 -0
  55. package/src/controls/renderers/toggle-group/ToggleGroup.d.ts +15 -0
  56. package/src/controls/renderers/toggle-group/ToggleGroupField.d.ts +19 -0
  57. package/src/controls/renderingRules.d.ts +26 -0
  58. package/src/controls/types.d.ts +395 -0
  59. package/src/controls/useAnimatedPresence.d.ts +15 -0
  60. package/src/controls/useAnnotationPresence.d.ts +16 -0
  61. package/src/controls/useControlStack.d.ts +21 -0
  62. package/src/controls/useControlsConfig.d.ts +27 -0
  63. package/src/controls/usePopoverPlacement.d.ts +33 -0
  64. package/src/core/LoadingIndicatorPill.d.ts +9 -0
  65. package/src/core/MapLoadingState.d.ts +17 -0
  66. package/src/core/SafeAreaLayoutContext.d.ts +5 -0
  67. package/src/core/__testHelpers.d.ts +23 -0
  68. package/src/core/createMapComponent.d.ts +32 -0
  69. package/src/core/loadingIndicator.d.ts +21 -0
  70. package/src/core/padWithInsets.d.ts +5 -0
  71. package/src/core/types.d.ts +208 -0
  72. package/src/core/useCameraIdle.d.ts +2 -0
  73. package/src/core/useCameraState.d.ts +3 -0
  74. package/src/core/useMap.d.ts +57 -0
  75. package/src/core/useMapAdapterState.d.ts +14 -0
  76. package/src/core/useMapKeyboardNavigation.d.ts +38 -0
  77. package/src/core/usePreviewMap.d.ts +43 -0
  78. package/src/index.d.ts +69 -0
  79. package/src/interactions/interactionReducer.d.ts +31 -0
  80. package/src/layers/Layers.d.ts +32 -0
  81. package/src/layers/__testHelpers.d.ts +24 -0
  82. package/src/layers/buildExpandedIds.d.ts +17 -0
  83. package/src/layers/image-overlay/useImageOverlay.d.ts +39 -0
  84. package/src/layers/internal/MapLayerContext.d.ts +24 -0
  85. package/src/layers/internal/adaptiveMarkerResolution.d.ts +33 -0
  86. package/src/layers/internal/computeBounds.d.ts +34 -0
  87. package/src/layers/internal/countFeaturesInViewport.d.ts +14 -0
  88. package/src/layers/internal/createLazyGetter.d.ts +16 -0
  89. package/src/layers/internal/layerHelpers.d.ts +18 -0
  90. package/src/layers/internal/markerPortalZIndex.d.ts +17 -0
  91. package/src/layers/internal/useDblClickFit.d.ts +13 -0
  92. package/src/layers/internal/useEntityInteraction.d.ts +21 -0
  93. package/src/layers/internal/useFitFeatureBounds.d.ts +19 -0
  94. package/src/layers/internal/useLayerHandleSync.d.ts +18 -0
  95. package/src/layers/internal/useLayerReady.d.ts +25 -0
  96. package/src/layers/internal/useMarkerMountBridge.d.ts +41 -0
  97. package/src/layers/internal/useViewportContext.d.ts +34 -0
  98. package/src/layers/mapFocus.d.ts +29 -0
  99. package/src/layers/routes/useRoute.d.ts +39 -0
  100. package/src/layers/shared/measureLabelWidth.d.ts +11 -0
  101. package/src/layers/types.d.ts +131 -0
  102. package/src/layers/useExpandedIds.d.ts +20 -0
  103. package/src/layers/useFitToContent.d.ts +57 -0
  104. package/src/layers/useLayers.d.ts +58 -0
  105. package/src/layers/useMarkers/adaptiveHelpers.d.ts +156 -0
  106. package/src/layers/useMarkers/resolveServerClusters.d.ts +26 -0
  107. package/src/layers/useMarkers/useAdaptiveMarkerHelpers.d.ts +38 -0
  108. package/src/layers/useMarkers/useMarkers.d.ts +127 -0
  109. package/src/layers/useShapes/InteractiveDecoration.d.ts +23 -0
  110. package/src/layers/useShapes/MultiGeometryPlusBadge.d.ts +17 -0
  111. package/src/layers/useShapes/MultiPartBadge.d.ts +11 -0
  112. package/src/layers/useShapes/ShapeAnnotationLabel.d.ts +30 -0
  113. package/src/layers/useShapes/ShapeIcon.d.ts +21 -0
  114. package/src/layers/useShapes/ShapeLabelPill.d.ts +25 -0
  115. package/src/layers/useShapes/buildShapeLabelResolutionContext.d.ts +23 -0
  116. package/src/layers/useShapes/decorationFactories.d.ts +47 -0
  117. package/src/layers/useShapes/edge/ShapeEdgeLabel.d.ts +13 -0
  118. package/src/layers/useShapes/edge/computeEdgeAutoPlacement.d.ts +69 -0
  119. package/src/layers/useShapes/edge/computeEdgeProperties.d.ts +21 -0
  120. package/src/layers/useShapes/edge/edgeInsetsForFeature.d.ts +27 -0
  121. package/src/layers/useShapes/edge/edgeReservations.d.ts +36 -0
  122. package/src/layers/useShapes/edge/findBestEdgePosition.d.ts +247 -0
  123. package/src/layers/useShapes/extractMultiParts.d.ts +25 -0
  124. package/src/layers/useShapes/findBestVisibleVertex.d.ts +18 -0
  125. package/src/layers/useShapes/multiPartDecorations.d.ts +19 -0
  126. package/src/layers/useShapes/shapeDecorations.d.ts +154 -0
  127. package/src/layers/useShapes/shapeFeatureBuilders.d.ts +25 -0
  128. package/src/layers/useShapes/shapeLabelPolicy.d.ts +42 -0
  129. package/src/layers/useShapes/shapeLabelResolution.d.ts +45 -0
  130. package/src/layers/useShapes/shapeSyntheticMarkerRender.d.ts +16 -0
  131. package/src/layers/useShapes/useShapeDecorations.d.ts +56 -0
  132. package/src/layers/useShapes/useShapeLabelHelpers.d.ts +29 -0
  133. package/src/layers/useShapes/useShapes.d.ts +50 -0
  134. package/src/markers/MapMarker.d.ts +115 -0
  135. package/src/markers/MapMarkerIcon.d.ts +21 -0
  136. package/src/markers/animation/applyStickFrame.d.ts +15 -0
  137. package/src/markers/animation/spring.d.ts +45 -0
  138. package/src/markers/animation/stickFrame.d.ts +82 -0
  139. package/src/markers/animation/usePillBackgroundPaint.d.ts +15 -0
  140. package/src/markers/animation/useStickAnimation.d.ts +21 -0
  141. package/src/markers/animation/useStickTween.d.ts +28 -0
  142. package/src/markers/geometry/stickPositioning.d.ts +69 -0
  143. package/src/markers/geometry/useDirectionIndicator.d.ts +8 -0
  144. package/src/markers/internal/MapMarkerStickSurface.d.ts +47 -0
  145. package/src/markers/model/mapMarkerDomPortalStacking.d.ts +22 -0
  146. package/src/markers/model/markerDomTypes.d.ts +68 -0
  147. package/src/markers/model/markerResolvers.d.ts +34 -0
  148. package/src/markers/model/markerSizeMap.d.ts +82 -0
  149. package/src/markers/model/markerTuningParams.d.ts +60 -0
  150. package/src/markers/model/useMarkerStateResolvers.d.ts +25 -0
  151. package/src/markers/shared/MarkerAnimatedSurface.d.ts +20 -0
  152. package/src/markers/shared/MarkerDiscContent.d.ts +11 -0
  153. package/src/markers/shared/mapMarkerVariants.d.ts +35 -0
  154. package/src/markers/shared/markerColors.d.ts +55 -0
  155. package/src/markers/shared/useMarkerColors.d.ts +23 -0
  156. package/src/markers/stories/demoes/AnimationCircleVsPillDemo.d.ts +7 -0
  157. package/src/markers/stories/demoes/CircleIconGuidanceDemo.d.ts +2 -0
  158. package/src/markers/stories/demoes/DefaultDemo.d.ts +14 -0
  159. package/src/markers/stories/demoes/DirectionBehaviorDemo.d.ts +2 -0
  160. package/src/markers/stories/demoes/PillLabelLengthsDemo.d.ts +2 -0
  161. package/src/markers/stories/demoes/StatesDemo.d.ts +7 -0
  162. package/src/markers/stories/demoes/StickModeDemo.d.ts +2 -0
  163. package/src/markers/stories/demoes/StickModePlaygroundDemo.d.ts +10 -0
  164. package/src/markers/stories/helpers/AbsoluteGridPicker.d.ts +17 -0
  165. package/src/markers/stories/helpers/InlineLabel.d.ts +4 -0
  166. package/src/markers/stories/helpers/InlineSlider.d.ts +11 -0
  167. package/src/markers/stories/helpers/LabeledMarker.d.ts +7 -0
  168. package/src/markers/stories/helpers/MarkerRow.d.ts +4 -0
  169. package/src/markers/stories/helpers/SectionHeader.d.ts +4 -0
  170. package/src/markers/stories/helpers/StatesMarkerCell.d.ts +15 -0
  171. package/src/markers/stories/helpers/ThemedPreview.d.ts +10 -0
  172. package/src/markers/stories/helpers/mapMarkerStoryConstants.d.ts +4 -0
  173. package/src/panel/Panel.d.ts +60 -0
  174. package/src/panel/PanelOrchestrator.d.ts +24 -0
  175. package/src/panel/preload/preloadInitiators.d.ts +44 -0
  176. package/src/panel/preload/useHoverPreloadInitiator.d.ts +8 -0
  177. package/src/panel/preload/usePanelPreload.d.ts +46 -0
  178. package/src/panel/preload/useProximityPreloadInitiator.d.ts +13 -0
  179. package/src/panel/store/panels.d.ts +76 -0
  180. package/src/panel/storyHelpers.d.ts +9 -0
  181. package/src/panel/usePanel.d.ts +81 -0
  182. package/src/panel/utils/autoPan.d.ts +78 -0
  183. package/src/panel/utils/panelShellConstants.d.ts +8 -0
  184. package/src/panel/utils/useAutoPanResolver.d.ts +23 -0
  185. package/src/panel/utils/useWheelForwarding.d.ts +18 -0
  186. package/src/stories/InteractionDisplay.d.ts +9 -0
  187. package/src/stories/PositionDisplay.d.ts +9 -0
  188. package/src/stories/_storyCoordUtils.d.ts +8 -0
  189. package/src/testing/mockMapApi.d.ts +29 -0
  190. package/src/translation.d.ts +30 -0
  191. package/translation.cjs.js +30 -0
  192. package/translation.cjs10.js +30 -0
  193. package/translation.cjs11.js +30 -0
  194. package/translation.cjs12.js +30 -0
  195. package/translation.cjs13.js +30 -0
  196. package/translation.cjs14.js +30 -0
  197. package/translation.cjs15.js +30 -0
  198. package/translation.cjs16.js +30 -0
  199. package/translation.cjs17.js +30 -0
  200. package/translation.cjs2.js +30 -0
  201. package/translation.cjs3.js +30 -0
  202. package/translation.cjs4.js +30 -0
  203. package/translation.cjs5.js +30 -0
  204. package/translation.cjs6.js +30 -0
  205. package/translation.cjs7.js +30 -0
  206. package/translation.cjs8.js +30 -0
  207. package/translation.cjs9.js +30 -0
  208. package/translation.esm.js +28 -0
  209. package/translation.esm10.js +28 -0
  210. package/translation.esm11.js +28 -0
  211. package/translation.esm12.js +28 -0
  212. package/translation.esm13.js +28 -0
  213. package/translation.esm14.js +28 -0
  214. package/translation.esm15.js +28 -0
  215. package/translation.esm16.js +28 -0
  216. package/translation.esm17.js +28 -0
  217. package/translation.esm2.js +28 -0
  218. package/translation.esm3.js +28 -0
  219. package/translation.esm4.js +28 -0
  220. package/translation.esm5.js +28 -0
  221. package/translation.esm6.js +28 -0
  222. package/translation.esm7.js +28 -0
  223. package/translation.esm8.js +28 -0
  224. package/translation.esm9.js +28 -0
@@ -0,0 +1,24 @@
1
+ import type { PanelStore } from "./store/panels";
2
+ export type PanelOrchestratorProps = Readonly<{
3
+ store: PanelStore;
4
+ /**
5
+ * Map container element. The anchored panel layer mounts here so panels
6
+ * escape the map's overflow.
7
+ */
8
+ containerEl: HTMLElement | null;
9
+ /**
10
+ * Overlay element that hosts anchored panels via portal. When omitted,
11
+ * anchored panels render inline next to the orchestrator (used in tests).
12
+ */
13
+ anchoredPortalEl?: HTMLElement | null;
14
+ }>;
15
+ /**
16
+ * Subscribes to the panel store and renders each descriptor as an
17
+ * `<Panel>` positioned next to its anchor element via Floating UI.
18
+ *
19
+ * @internal
20
+ */
21
+ export declare const PanelOrchestrator: {
22
+ ({ store, containerEl, anchoredPortalEl }: PanelOrchestratorProps): import("react/jsx-runtime").JSX.Element | null;
23
+ displayName: string;
24
+ };
@@ -0,0 +1,44 @@
1
+ import type { GeoJsonPosition } from "../../core/types";
2
+ /**
3
+ * Fires `onPreload` when the given `entityId` has been hovered continuously
4
+ * for `debounceMs` milliseconds. Rapid mouse passes are filtered out.
5
+ *
6
+ * The consumer owns hover state — source `entityId` from
7
+ * `layers.interaction.hoveredEntity?.id ?? null`.
8
+ */
9
+ export type HoverPanelPreloadInitiator = Readonly<{
10
+ type: "hover";
11
+ entityId: string | null;
12
+ /**
13
+ * Milliseconds to wait before firing `onPreload` after hover starts.
14
+ * Default: 150.
15
+ */
16
+ debounceMs?: number;
17
+ }>;
18
+ /**
19
+ * Fires `onPreload` for the `count` entities nearest to `referenceEntityId`
20
+ * whenever the reference changes or the map viewport moves.
21
+ *
22
+ * When `referenceEntityId` is `null` the initiator is skipped — pass the
23
+ * currently-selected entity id to pre-warm data for adjacent assets.
24
+ */
25
+ export type ProximityPanelPreloadInitiator = Readonly<{
26
+ type: "proximity";
27
+ /**
28
+ * ID of the entity to compute proximity from.
29
+ * `null` disables the initiator until a selection is made.
30
+ */
31
+ referenceEntityId: string | null;
32
+ /** All visible entities with their positions for proximity ranking. */
33
+ entities: ReadonlyArray<Readonly<{
34
+ id: string;
35
+ position: GeoJsonPosition;
36
+ }>>;
37
+ /**
38
+ * Maximum number of nearest entities to preload.
39
+ * Default: 5.
40
+ */
41
+ count?: number;
42
+ }>;
43
+ export type PanelPreloadInitiator = HoverPanelPreloadInitiator | ProximityPanelPreloadInitiator;
44
+ export type PanelPreloadInitiatorType = PanelPreloadInitiator["type"];
@@ -0,0 +1,8 @@
1
+ import type { HoverPanelPreloadInitiator, PanelPreloadInitiatorType } from "./preloadInitiators";
2
+ /**
3
+ * Fires `onShouldPreload` for the currently hovered entity after a debounce
4
+ * delay. Rapid mouse passes that do not settle cancel any pending timer.
5
+ *
6
+ * @internal
7
+ */
8
+ export declare const useHoverPreloadInitiator: (initiator: HoverPanelPreloadInitiator | undefined, onShouldPreload: (id: string, type: PanelPreloadInitiatorType) => void) => void;
@@ -0,0 +1,46 @@
1
+ import type { MapApi } from "../../core/types";
2
+ import type { PanelPreloadInitiator, PanelPreloadInitiatorType } from "./preloadInitiators";
3
+ export type UsePanelPreloadOptions = Readonly<{
4
+ /**
5
+ * Called at most once per entity per hook mount when any initiator
6
+ * determines the entity's data should be prefetched.
7
+ *
8
+ * May be called for the same entity from multiple initiators — idempotency
9
+ * is the consumer's responsibility. Apollo's `fetchPolicy: "cache-first"`
10
+ * handles this naturally: a second call is a no-op when data is cached.
11
+ */
12
+ onPreload: (entityId: string, initiator: PanelPreloadInitiatorType) => void;
13
+ /**
14
+ * One or more preload triggers. Each one independently decides which
15
+ * entities to preload — pass both `hover` and `proximity` to get layered
16
+ * coverage.
17
+ */
18
+ initiators: ReadonlyArray<PanelPreloadInitiator>;
19
+ }>;
20
+ /**
21
+ * Registers preload initiators for a map panel.
22
+ *
23
+ * Fires `onPreload` when an initiator determines an entity's data should be
24
+ * fetched before the panel opens — so the Apollo cache is warm by the time
25
+ * the user selects the marker.
26
+ *
27
+ * The hook is data-agnostic: the consumer decides what to fetch in `onPreload`.
28
+ *
29
+ * ```tsx
30
+ * const client = useApolloClient();
31
+ * usePanelPreload(api, {
32
+ * onPreload: (entityId) => {
33
+ * void client.query({
34
+ * query: GetEntityDocument,
35
+ * variables: { entityId },
36
+ * fetchPolicy: "cache-first",
37
+ * });
38
+ * },
39
+ * initiators: [
40
+ * { type: "hover", entityId: layers.interaction.hoveredEntity?.id ?? null },
41
+ * { type: "proximity", referenceEntityId: selectedEntityId, entities: markers, count: 3 },
42
+ * ],
43
+ * });
44
+ * ```
45
+ */
46
+ export declare const usePanelPreload: (api: MapApi, options: UsePanelPreloadOptions) => void;
@@ -0,0 +1,13 @@
1
+ import type { MapApi } from "../../core/types";
2
+ import type { PanelPreloadInitiatorType, ProximityPanelPreloadInitiator } from "./preloadInitiators";
3
+ /**
4
+ * Fires `onShouldPreload` for the `count` entities closest to
5
+ * `referenceEntityId`. Skips entirely when `referenceEntityId` is `null`.
6
+ *
7
+ * Subscribes to `api.on("moveend")` to re-trigger after map pans — entities
8
+ * prop updates when new markers arrive in the viewport, so the nearest set
9
+ * may change after each pan.
10
+ *
11
+ * @internal
12
+ */
13
+ export declare const useProximityPreloadInitiator: (initiator: ProximityPanelPreloadInitiator | undefined, api: MapApi, onShouldPreload: (id: string, type: PanelPreloadInitiatorType) => void) => void;
@@ -0,0 +1,76 @@
1
+ import type { Placement } from "@floating-ui/react";
2
+ import type { ReactNode } from "react";
3
+ /**
4
+ * Internal descriptor describing a map panel registered by a layer.
5
+ *
6
+ * Layers register panels via {@link usePanel}; the orchestrator renders
7
+ * each descriptor as an {@link Panel} positioned next to its anchor.
8
+ *
9
+ * `children` is the panel content. `onDismiss` is the latest closure the
10
+ * orchestrator should invoke when the panel is dismissed (Escape key or
11
+ * outside-press) — the hook ships a stable wrapper that reads from a ref so
12
+ * handler-identity changes do not cause extra store ticks.
13
+ *
14
+ * @internal
15
+ */
16
+ export type PanelDescriptor = Readonly<{
17
+ id: string;
18
+ /**
19
+ * Anchor element. The orchestrator passes this to Floating UI as the
20
+ * reference element. Null until the consumer mounts.
21
+ */
22
+ anchor: HTMLElement | null;
23
+ /** Lower number = higher priority. */
24
+ priority?: number;
25
+ /** Placement preference. Default: "bottom". */
26
+ placement?: Placement;
27
+ onDismiss?: () => void;
28
+ /** Accessible label for the close button. Passed through to Panel. */
29
+ closeLabel?: string;
30
+ /** Accessible label for the panel dialog, announced by screen readers on open. */
31
+ "aria-label"?: string;
32
+ /**
33
+ * Where vertical overflow scrolls. Default `shell` keeps `overflow-auto` on the
34
+ * Panel scroll slot; `internal` uses `overflow-hidden` so consumers own scroll.
35
+ */
36
+ contentScroll?: "shell" | "internal";
37
+ /**
38
+ * Called by the orchestrator (via Panel.onCommit) on first visible
39
+ * placement per open-cycle. Wired by `usePanel` when `resolveAutoPan`
40
+ * is provided. Fourth arg is the natural content height of the inner scroll div.
41
+ */
42
+ onCommit?: (panelRect: DOMRect, anchorRect: DOMRect, placement: Placement, panelScrollHeight: number) => void;
43
+ children: ReactNode;
44
+ }>;
45
+ /**
46
+ * Subscription-based store for map panels.
47
+ *
48
+ * Compatible with `useSyncExternalStore(subscribe, getSnapshot)`.
49
+ *
50
+ * Unlike the annotation store, panels use `upsert` semantics: the consumer
51
+ * hook calls `upsert` on every render where the panel is open. `upsert`
52
+ * replaces the descriptor in place without changing insertion order, so
53
+ * children and other content fields can change without unmounting the
54
+ * orchestrator's slot for that id.
55
+ *
56
+ * @internal
57
+ */
58
+ export type PanelStore = Readonly<{
59
+ upsert: (descriptor: PanelDescriptor) => void;
60
+ remove: (id: string) => void;
61
+ subscribe: (callback: () => void) => () => void;
62
+ getSnapshot: () => ReadonlyArray<PanelDescriptor>;
63
+ }>;
64
+ /**
65
+ * Creates a {@link PanelStore} instance.
66
+ *
67
+ * Uses a `Map<string, PanelDescriptor>` for registration so that
68
+ * insertion order is preserved across `upsert` calls (Map iteration order
69
+ * is insertion order, and `set` on an existing key does not move it).
70
+ *
71
+ * `getSnapshot` returns a stable `ReadonlyArray` reference that only
72
+ * changes when descriptors are actually mutated.
73
+ *
74
+ * @internal
75
+ */
76
+ export declare const createPanelStore: () => PanelStore;
@@ -0,0 +1,9 @@
1
+ import type { MapApi } from "../core/types";
2
+ /**
3
+ * Lightweight `MapApi` mock for Storybook stories that exercise
4
+ * `usePanel` and `PanelOrchestrator` without spinning up a real map
5
+ * adapter.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare const createMockMapApiForStories: () => MapApi;
@@ -0,0 +1,81 @@
1
+ import type { Placement } from "@floating-ui/react";
2
+ import { type ReactNode, type RefCallback } from "react";
3
+ import type { MapApi } from "../core/types";
4
+ import type { AutoPanContext, AutoPanResult } from "./utils/autoPan";
5
+ export type UsePanelOptions = Readonly<{
6
+ /** Stable id used as the descriptor key in the panel store. */
7
+ id: string;
8
+ /**
9
+ * When true, the panel is registered (or upserted) on every render.
10
+ * When false (or after unmount), the panel is removed from the store.
11
+ * Toggle this instead of conditionally calling the hook.
12
+ */
13
+ open: boolean;
14
+ /** Lower number = higher priority. Default active in the Sheet carousel. */
15
+ priority?: number;
16
+ /** Floating-mode placement preference. Default: "bottom". */
17
+ placement?: Placement;
18
+ /**
19
+ * Called on Sheet gesture/ESC dismiss (when this descriptor is the active
20
+ * one in the carousel) or on floating-mode outside-press. The hook captures
21
+ * the latest closure on every render, so consumers do not need to memoize.
22
+ */
23
+ onDismiss?: () => void;
24
+ /**
25
+ * Accessible label for the close button rendered by the panel shell.
26
+ * Pass `t("panel.close")` from the consuming library to keep it translated.
27
+ * Defaults to `"Close"` when omitted.
28
+ */
29
+ closeLabel?: string;
30
+ /**
31
+ * Accessible label for the panel dialog, announced by screen readers on open.
32
+ * Pass `t("panel.label")` from the consuming library to keep it translated.
33
+ */
34
+ "aria-label"?: string;
35
+ /**
36
+ * Where vertical overflow scrolls. Default `shell` keeps the Panel scroll slot
37
+ * as `overflow-auto`; use `internal` when panel content owns its own scroll region.
38
+ */
39
+ contentScroll?: "shell" | "internal";
40
+ /**
41
+ * Optional resolver for auto-panning the map when the panel first commits
42
+ * in anchored mode. Called once per open-cycle with an {@link AutoPanContext}
43
+ * describing the panel's position relative to the map container. Return an
44
+ * `{ x, y }` pixel offset to pan by, or `null` to skip panning.
45
+ *
46
+ * Use {@link defaultAutoPanResolver} for the standard behavior (pan minimum
47
+ * to clear clipping with 12 px padding):
48
+ *
49
+ * ```tsx
50
+ * import { defaultAutoPanResolver } from "@trackunit/react-map";
51
+ *
52
+ * usePanel(api, {
53
+ * id: "my-panel",
54
+ * open: isOpen,
55
+ * resolveAutoPan: defaultAutoPanResolver,
56
+ * children: <MyContent />,
57
+ * });
58
+ * ```
59
+ *
60
+ * Omit to opt out of auto-panning entirely.
61
+ */
62
+ resolveAutoPan?: (ctx: AutoPanContext) => AutoPanResult;
63
+ /**
64
+ * Panel content. Identity may change every render; the hook upserts the
65
+ * descriptor in place so the orchestrator simply re-renders the existing
66
+ * slot for this id without remounting Floating UI or the Sheet.
67
+ */
68
+ children: ReactNode;
69
+ }>;
70
+ /**
71
+ * Registers a panel for the given map and returns a callback ref that the
72
+ * consumer must spread on the anchor element (typically `<MapMarker ref={...}>`).
73
+ *
74
+ * The orchestrator owned by `createMapComponent` decides whether to render
75
+ * the panel as a Sheet (narrow containers) or a floating element anchored
76
+ * to the marker (wide containers).
77
+ *
78
+ * The returned ref callback identity is stable across re-renders; consumers
79
+ * can pass it to multiple refs via `useMergeRefs` if needed.
80
+ */
81
+ export declare const usePanel: (api: MapApi, options: UsePanelOptions) => RefCallback<HTMLElement>;
@@ -0,0 +1,78 @@
1
+ import type { Placement } from "@floating-ui/react";
2
+ /**
3
+ * Context passed to `resolveAutoPan` when an anchored panel first commits.
4
+ *
5
+ * `clipping` values are positive when the panel overflows the map container
6
+ * on that side (e.g. `clipping.right = 20` means the panel extends 20 px
7
+ * beyond the container's right edge).
8
+ *
9
+ * `panelScrollHeight` is the natural content height of the panel's inner scroll
10
+ * div — equal to `panelRect.height` when content fits, greater when the panel
11
+ * is scroll-constrained. Combined with `panelCssMaxHeight`, this lets resolvers
12
+ * compute how much panning would eliminate (or reduce) scrolling.
13
+ *
14
+ * `panelCssMaxHeight` is the effective CSS `max-height` cap on the panel shell
15
+ * (`min(320px, 40vh)` evaluated at commit time). Panning beyond what's needed
16
+ * to reach this cap does not reduce scrolling further.
17
+ */
18
+ export type AutoPanContext = Readonly<{
19
+ panelRect: DOMRect;
20
+ anchorRect: DOMRect;
21
+ containerRect: DOMRect;
22
+ placement: Placement;
23
+ clipping: Readonly<{
24
+ top: number;
25
+ right: number;
26
+ bottom: number;
27
+ left: number;
28
+ }>;
29
+ /** Natural content height of the inner scroll div (from `scrollHeight`). */
30
+ panelScrollHeight: number;
31
+ /** Effective CSS `max-height` on the panel shell at commit time. */
32
+ panelCssMaxHeight: number;
33
+ }>;
34
+ /**
35
+ * Return value from `resolveAutoPan`.
36
+ *
37
+ * `x` and `y` are screen-space pixel offsets for `api.actions.panBy`:
38
+ * - positive x = pan map right (content moves left)
39
+ * - positive y = pan map down (content moves up)
40
+ *
41
+ * Return `null` to skip panning (panel already fits).
42
+ *
43
+ * When `restoreOnDismiss` is `true` (or omitted), `usePanel` captures the
44
+ * map center before panning and calls `panTo(capturedCenter)` when the panel
45
+ * is dismissed — returning the viewport to its pre-pan position.
46
+ * Set to `false` to opt out of the restore.
47
+ */
48
+ export type AutoPanResult = Readonly<{
49
+ x: number;
50
+ y: number;
51
+ restoreOnDismiss?: boolean;
52
+ }> | null;
53
+ /**
54
+ * Default auto-pan resolver: pans the minimum amount to give the panel the
55
+ * best possible screen space. Handles two cases:
56
+ *
57
+ * 1. **Clipping** — panel bleeds outside the map container on any side. Pans
58
+ * to clear the bleed with 12 px of breathing room.
59
+ *
60
+ * 2. **Scroll-squish** — panel is within the container but shift-pressed against
61
+ * an edge, so content overflows and the panel scrolls. Pans to give the panel
62
+ * room to grow, up to the CSS `max-height` cap (`panelCssMaxHeight`).
63
+ *
64
+ * Returns `null` when the panel already fits without scrolling and without
65
+ * clipping — meaning no pan is needed.
66
+ *
67
+ * Pass as `resolveAutoPan` to {@link usePanel} for the standard behavior:
68
+ *
69
+ * ```tsx
70
+ * usePanel(api, {
71
+ * id: "my-panel",
72
+ * open: isOpen,
73
+ * resolveAutoPan: defaultAutoPanResolver,
74
+ * children: <MyPanelContent />,
75
+ * });
76
+ * ```
77
+ */
78
+ export declare const defaultAutoPanResolver: (ctx: AutoPanContext) => AutoPanResult;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CSS `max-height` of the Panel shell — `min(320px, 40vh)`.
3
+ *
4
+ * Both values are kept here so the inline style in `Panel` and the
5
+ * auto-pan cap computation in `usePanel` always stay in sync.
6
+ */
7
+ export declare const PANEL_MAX_HEIGHT_PX = 320;
8
+ export declare const PANEL_MAX_HEIGHT_VH = 40;
@@ -0,0 +1,23 @@
1
+ import { defaultAutoPanResolver } from "./autoPan";
2
+ export type AutoPanResolverHelpers = Readonly<{
3
+ defaultAutoPanResolver: typeof defaultAutoPanResolver;
4
+ }>;
5
+ /**
6
+ * Build-your-own hook: stable reference to the default auto-pan resolver.
7
+ *
8
+ * Returns `defaultAutoPanResolver` for consumers who want to pass it to
9
+ * `usePanel({ resolveAutoPan })` or use it as a baseline to wrap/replace
10
+ * with custom logic.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const { defaultAutoPanResolver } = useAutoPanResolver();
15
+ * usePanel(api, {
16
+ * id: "my-panel",
17
+ * open: isOpen,
18
+ * resolveAutoPan: defaultAutoPanResolver,
19
+ * children: <MyContent />,
20
+ * });
21
+ * ```
22
+ */
23
+ export declare const useAutoPanResolver: () => AutoPanResolverHelpers;
@@ -0,0 +1,18 @@
1
+ import { type RefObject } from "react";
2
+ /**
3
+ * Lets wheel events reach the map natively when a zoom gesture started on the
4
+ * map and the cursor later moves over the panel overlay.
5
+ *
6
+ * Pass-through uses `data-wheel-pass-through` + CSS `pointer-events: none` so
7
+ * the browser delivers trusted wheel events to the map underneath. It is armed
8
+ * only while a map-originated wheel gesture is in progress — panel-initiated
9
+ * wheels and all pointer interaction keep the panel fully interactive.
10
+ *
11
+ * Gesture ownership is decided on the first wheel tick of each burst (after an
12
+ * idle gap): target inside the panel shell → panel; otherwise → map. A
13
+ * `pointerdown` on the panel ends any map wheel gesture immediately so clicks
14
+ * and drags on the panel always win.
15
+ */
16
+ export declare const useWheelForwarding: (shellRef: RefObject<HTMLElement | null>,
17
+ /** Re-run effects when the panel shell mounts or unmounts. */
18
+ isActive: boolean) => void;
@@ -0,0 +1,9 @@
1
+ import type { MapInteractionState } from "@trackunit/react-map-adapter-shared";
2
+ import type { ReactElement } from "react";
3
+ type InteractionDisplayProps = {
4
+ interaction: MapInteractionState;
5
+ label?: string;
6
+ };
7
+ /** Formatted selected/hovered entity display with outlined entity blocks showing all fields. */
8
+ export declare const InteractionDisplay: ({ interaction, label }: InteractionDisplayProps) => ReactElement;
9
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { ReactElement } from "react";
2
+ import type { GeoJsonPosition } from "../core/types";
3
+ type PositionDisplayProps = {
4
+ position: Readonly<GeoJsonPosition>;
5
+ label?: string;
6
+ };
7
+ /** Color-coded Lng/Lat coordinate cells, matching StateDisplay's center rendering. */
8
+ export declare const PositionDisplay: ({ position, label }: PositionDisplayProps) => ReactElement;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ /** Pads numeric string: 3-digit int part + reserved sign column to avoid layout shift when sign flips. */
2
+ export declare const formatPaddedNumber: (n: number, decimals: number) => string;
3
+ export declare const cvaCoordCell: (props?: ({
4
+ variant?: "lng" | "lat" | "we" | "sn" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export declare const cvaStateDisplay: (props?: ({
7
+ expanded?: boolean | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -0,0 +1,29 @@
1
+ import type { MapApi, MapState } from "../core/types";
2
+ /**
3
+ * Builds a full `MapApi` stub for use in unit tests and hook-stability specs.
4
+ *
5
+ * Uses the real `createPanelStore`, `createMapAnnotationStore`, and
6
+ * `createMapLoadingIndicatorStore` so store state can be asserted on
7
+ * (e.g. a test can register an annotation and then assert `getSnapshot()`).
8
+ *
9
+ * Action stubs (setCenter, fitBounds, panTo, etc.) are plain no-ops that
10
+ * return a resolved `Promise<void>`. Pass `actionOverrides` to replace any
11
+ * action with a spy or custom implementation.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // Basic usage — real stores, no-op actions:
16
+ * const api = mockMapApi();
17
+ *
18
+ * // Override specific actions for assertion:
19
+ * const fitBounds = vi.fn().mockResolvedValue(undefined);
20
+ * const api = mockMapApi({ actions: { fitBounds } });
21
+ *
22
+ * // Override state (e.g. a ready map at zoom 15):
23
+ * const api = mockMapApi({ state: { zoom: 15 } });
24
+ * ```
25
+ */
26
+ export declare const mockMapApi: (overrides?: {
27
+ state?: Partial<MapState>;
28
+ actions?: Partial<MapApi["actions"]>;
29
+ }) => MapApi;
@@ -0,0 +1,30 @@
1
+ import { NamespaceTransProps, TransForLibs, TranslationResource, useNamespaceTranslation } from "@trackunit/i18n-library-translation";
2
+ import { ReactElement } from "react";
3
+ import defaultTranslations from "./locales/en/translation.json";
4
+ /** A type for all available translation keys in this library */
5
+ export type TranslationKeys = keyof typeof defaultTranslations;
6
+ /** The translation namespace for this library */
7
+ export declare const namespace = "react-map.map";
8
+ /**
9
+ * The TranslationResource for this Library.
10
+ * Holds lazy loaded imports for all languages supported by the library.
11
+ *
12
+ * This is used to register the translations for this library before initializing i18next.
13
+ */
14
+ export declare const translations: TranslationResource<TranslationKeys>;
15
+ /**
16
+ * Local useTranslation for this specific library
17
+ */
18
+ export declare const useTranslation: () => ReturnType<typeof useNamespaceTranslation<TranslationKeys>>;
19
+ /**
20
+ * Type of the t function for the local useTranslation for this specific library
21
+ */
22
+ export type TranslationFunction = TransForLibs<TranslationKeys>;
23
+ /**
24
+ * Trans for this specific library.
25
+ */
26
+ export declare const Trans: (props: NamespaceTransProps<TranslationKeys>) => ReactElement;
27
+ /**
28
+ * Registers the translations for this library
29
+ */
30
+ export declare const setupLibraryTranslations: () => void;
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var translation = {
4
+ "controls.allControls": "Kartensteuerung",
5
+ "controls.boolean.tooltip": "{{label}} aktivieren/deaktivieren",
6
+ "controls.category.navigation": "Navigation",
7
+ "controls.category.settings": "Einstellungen",
8
+ "controls.category.statistics": "Statistiken",
9
+ "controls.category.tools": "Werkzeuge",
10
+ "controls.enterFullscreen": "Vollbildmodus aktivieren",
11
+ "controls.exitFullscreen": "Vollbildmodus beenden",
12
+ "controls.myLocation": "Meinen Standort anzeigen",
13
+ "controls.stepper.decrease": "Verkleinern",
14
+ "controls.stepper.increase": "Vergrößern",
15
+ "controls.zoom": "Zoom",
16
+ "controls.zoomIn": "Hineinzoomen",
17
+ "controls.zoomOut": "Herauszoomen",
18
+ "map.loading": "Karte wird geladen",
19
+ "map.loadingData": "Loading map data",
20
+ "map.loadingErrorMessage": "Die Karte konnte nicht geladen werden. Bitte versuchen Sie es später erneut.",
21
+ "multiGeometry.badge.tooltip": "Teil eines zusammengesetzten Objekts",
22
+ "settings.mapStyle.dark": "Dunkel",
23
+ "settings.mapStyle.light": "Hell",
24
+ "settings.mapStyle.roadmap": "Straßenkarte",
25
+ "settings.mapStyle.roads": "Straßen",
26
+ "settings.mapStyle.satellite": "Satellit",
27
+ "settings.mapStyle.title": "Kartenstil"
28
+ };
29
+
30
+ exports.default = translation;
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var translation = {
4
+ "controls.allControls": "Sterowanie mapą",
5
+ "controls.boolean.tooltip": "Przełącz: {{label}}",
6
+ "controls.category.navigation": "Nawigacja",
7
+ "controls.category.settings": "Ustawienia",
8
+ "controls.category.statistics": "Statystyki",
9
+ "controls.category.tools": "Narzędzia",
10
+ "controls.enterFullscreen": "Przejdź do trybu pełnoekranowego",
11
+ "controls.exitFullscreen": "Zamknij pełny ekran",
12
+ "controls.myLocation": "Pokaż moją lokalizację",
13
+ "controls.stepper.decrease": "Zmniejsz",
14
+ "controls.stepper.increase": "Zwiększ",
15
+ "controls.zoom": "Powiększ",
16
+ "controls.zoomIn": "Przybliż",
17
+ "controls.zoomOut": "Oddal",
18
+ "map.loading": "Ładowanie mapy",
19
+ "map.loadingData": "Loading map data",
20
+ "map.loadingErrorMessage": "Nie można załadować mapy. Spróbuj ponownie później.",
21
+ "multiGeometry.badge.tooltip": "Część kształtu wieloczęściowego",
22
+ "settings.mapStyle.dark": "Ciemny",
23
+ "settings.mapStyle.light": "Jasny",
24
+ "settings.mapStyle.roadmap": "Mapa drogowa",
25
+ "settings.mapStyle.roads": "Drogi",
26
+ "settings.mapStyle.satellite": "Satelita",
27
+ "settings.mapStyle.title": "Styl mapy"
28
+ };
29
+
30
+ exports.default = translation;
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var translation = {
4
+ "controls.allControls": "Controlos do mapa",
5
+ "controls.boolean.tooltip": "Alternar: {{label}}",
6
+ "controls.category.navigation": "Navegação",
7
+ "controls.category.settings": "Definições",
8
+ "controls.category.statistics": "Estatísticas",
9
+ "controls.category.tools": "Ferramentas",
10
+ "controls.enterFullscreen": "Entrar em ecrã completo",
11
+ "controls.exitFullscreen": "Sair do ecrã completo",
12
+ "controls.myLocation": "Mostrar a minha localização",
13
+ "controls.stepper.decrease": "Diminuir",
14
+ "controls.stepper.increase": "Aumentar",
15
+ "controls.zoom": "Ampliar",
16
+ "controls.zoomIn": "Aumentar zoom",
17
+ "controls.zoomOut": "Diminuir zoom",
18
+ "map.loading": "Carregar mapa",
19
+ "map.loadingData": "Loading map data",
20
+ "map.loadingErrorMessage": "Não foi possível carregar o mapa. Tente novamente mais tarde.",
21
+ "multiGeometry.badge.tooltip": "Parte de uma forma de várias partes",
22
+ "settings.mapStyle.dark": "Escuro",
23
+ "settings.mapStyle.light": "Claro",
24
+ "settings.mapStyle.roadmap": "Mapa de estrada",
25
+ "settings.mapStyle.roads": "Estradas",
26
+ "settings.mapStyle.satellite": "Satélite",
27
+ "settings.mapStyle.title": "Estilo do mapa"
28
+ };
29
+
30
+ exports.default = translation;
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var translation = {
4
+ "controls.allControls": "Элементы управления картой",
5
+ "controls.boolean.tooltip": "Переключатель: {{label}}",
6
+ "controls.category.navigation": "Навигация",
7
+ "controls.category.settings": "Настройки",
8
+ "controls.category.statistics": "Статистика",
9
+ "controls.category.tools": "Инструменты",
10
+ "controls.enterFullscreen": "Войти в полноэкранный режим",
11
+ "controls.exitFullscreen": "Выйти из полноэкранного режима",
12
+ "controls.myLocation": "Показать мое местоположение",
13
+ "controls.stepper.decrease": "Уменьшить",
14
+ "controls.stepper.increase": "Увеличить",
15
+ "controls.zoom": "Масштаб",
16
+ "controls.zoomIn": "Увеличить масштаб",
17
+ "controls.zoomOut": "Уменьшить масштаб",
18
+ "map.loading": "Загрузка карты",
19
+ "map.loadingData": "Loading map data",
20
+ "map.loadingErrorMessage": "Не удается загрузить карту. Повторите попытку позже.",
21
+ "multiGeometry.badge.tooltip": "Часть составной фигуры",
22
+ "settings.mapStyle.dark": "Темная",
23
+ "settings.mapStyle.light": "Светлая",
24
+ "settings.mapStyle.roadmap": "Карта маршрута",
25
+ "settings.mapStyle.roads": "Дороги",
26
+ "settings.mapStyle.satellite": "Спутник",
27
+ "settings.mapStyle.title": "Стиль карты"
28
+ };
29
+
30
+ exports.default = translation;