@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.
- package/README.md +296 -0
- package/index.cjs.js +9851 -0
- package/index.d.ts +1 -0
- package/index.esm.js +9752 -0
- package/package.json +34 -0
- package/src/annotations/getDescriptorContentKey.d.ts +14 -0
- package/src/annotations/mapAnnotations.d.ts +76 -0
- package/src/annotations/useMapAnnotation.d.ts +16 -0
- package/src/annotations/useMapAnnotations.d.ts +17 -0
- package/src/appearance/AppearancePreview.d.ts +27 -0
- package/src/appearance/AppearancePreviewGrid.d.ts +29 -0
- package/src/appearance/appearanceTypes.d.ts +84 -0
- package/src/appearance/useMapAppearanceControls.d.ts +29 -0
- package/src/clusters/ClusterMarker.d.ts +41 -0
- package/src/clusters/ClusterStick.d.ts +97 -0
- package/src/clusters/formatClusterCount.d.ts +11 -0
- package/src/clusters/stories/ClusterMarkerCompactFormatsDemo.d.ts +7 -0
- package/src/clusters/stories/ClusterMarkerCountOnlyDemo.d.ts +7 -0
- package/src/clusters/stories/ClusterMarkerDefaultDemo.d.ts +12 -0
- package/src/clusters/stories/ClusterMarkerPlaygroundDemo.d.ts +10 -0
- package/src/clusters/stories/ClusterMarkerStateDemo.d.ts +9 -0
- package/src/clusters/stories/ClusterMarkerWithSegmentsDemo.d.ts +7 -0
- package/src/clusters/stories/ClusterMarkerWithSticksDemo.d.ts +10 -0
- package/src/clusters/useClusterCountFormat.d.ts +19 -0
- package/src/controls/AnnotationRenderer.d.ts +17 -0
- package/src/controls/AnnotationStack.d.ts +21 -0
- package/src/controls/ControlRenderer.d.ts +20 -0
- package/src/controls/Controls.d.ts +15 -0
- package/src/controls/annotationButtonClasses.d.ts +13 -0
- package/src/controls/collapseControls.d.ts +37 -0
- package/src/controls/defineControlStack.d.ts +10 -0
- package/src/controls/deriveResponsiveMode.d.ts +19 -0
- package/src/controls/longitudeToGlobeIcon.d.ts +3 -0
- package/src/controls/renderers/boolean/BooleanButton.d.ts +16 -0
- package/src/controls/renderers/boolean/MenuBooleanItem.d.ts +20 -0
- package/src/controls/renderers/boolean/MenuCheckbox.d.ts +14 -0
- package/src/controls/renderers/boolean/MenuToggle.d.ts +14 -0
- package/src/controls/renderers/button/Button.d.ts +14 -0
- package/src/controls/renderers/button/MenuButton.d.ts +16 -0
- package/src/controls/renderers/custom/Custom.d.ts +22 -0
- package/src/controls/renderers/menu/Menu.d.ts +23 -0
- package/src/controls/renderers/menu/Modal.d.ts +21 -0
- package/src/controls/renderers/menu/SectionHeader.d.ts +14 -0
- package/src/controls/renderers/menu/Separator.d.ts +11 -0
- package/src/controls/renderers/radio-group/MenuRadioGroup.d.ts +15 -0
- package/src/controls/renderers/radio-group/RadioGroup.d.ts +19 -0
- package/src/controls/renderers/radio-group/RadioGroupField.d.ts +17 -0
- package/src/controls/renderers/search/MenuSearch.d.ts +15 -0
- package/src/controls/renderers/search/Search.d.ts +14 -0
- package/src/controls/renderers/select/MenuSelect.d.ts +15 -0
- package/src/controls/renderers/select/Select.d.ts +14 -0
- package/src/controls/renderers/stepper/MenuStepper.d.ts +17 -0
- package/src/controls/renderers/stepper/Stepper.d.ts +18 -0
- package/src/controls/renderers/toggle-group/MenuToggleGroup.d.ts +17 -0
- package/src/controls/renderers/toggle-group/ToggleGroup.d.ts +15 -0
- package/src/controls/renderers/toggle-group/ToggleGroupField.d.ts +19 -0
- package/src/controls/renderingRules.d.ts +26 -0
- package/src/controls/types.d.ts +395 -0
- package/src/controls/useAnimatedPresence.d.ts +15 -0
- package/src/controls/useAnnotationPresence.d.ts +16 -0
- package/src/controls/useControlStack.d.ts +21 -0
- package/src/controls/useControlsConfig.d.ts +27 -0
- package/src/controls/usePopoverPlacement.d.ts +33 -0
- package/src/core/LoadingIndicatorPill.d.ts +9 -0
- package/src/core/MapLoadingState.d.ts +17 -0
- package/src/core/SafeAreaLayoutContext.d.ts +5 -0
- package/src/core/__testHelpers.d.ts +23 -0
- package/src/core/createMapComponent.d.ts +32 -0
- package/src/core/loadingIndicator.d.ts +21 -0
- package/src/core/padWithInsets.d.ts +5 -0
- package/src/core/types.d.ts +208 -0
- package/src/core/useCameraIdle.d.ts +2 -0
- package/src/core/useCameraState.d.ts +3 -0
- package/src/core/useMap.d.ts +57 -0
- package/src/core/useMapAdapterState.d.ts +14 -0
- package/src/core/useMapKeyboardNavigation.d.ts +38 -0
- package/src/core/usePreviewMap.d.ts +43 -0
- package/src/index.d.ts +69 -0
- package/src/interactions/interactionReducer.d.ts +31 -0
- package/src/layers/Layers.d.ts +32 -0
- package/src/layers/__testHelpers.d.ts +24 -0
- package/src/layers/buildExpandedIds.d.ts +17 -0
- package/src/layers/image-overlay/useImageOverlay.d.ts +39 -0
- package/src/layers/internal/MapLayerContext.d.ts +24 -0
- package/src/layers/internal/adaptiveMarkerResolution.d.ts +33 -0
- package/src/layers/internal/computeBounds.d.ts +34 -0
- package/src/layers/internal/countFeaturesInViewport.d.ts +14 -0
- package/src/layers/internal/createLazyGetter.d.ts +16 -0
- package/src/layers/internal/layerHelpers.d.ts +18 -0
- package/src/layers/internal/markerPortalZIndex.d.ts +17 -0
- package/src/layers/internal/useDblClickFit.d.ts +13 -0
- package/src/layers/internal/useEntityInteraction.d.ts +21 -0
- package/src/layers/internal/useFitFeatureBounds.d.ts +19 -0
- package/src/layers/internal/useLayerHandleSync.d.ts +18 -0
- package/src/layers/internal/useLayerReady.d.ts +25 -0
- package/src/layers/internal/useMarkerMountBridge.d.ts +41 -0
- package/src/layers/internal/useViewportContext.d.ts +34 -0
- package/src/layers/mapFocus.d.ts +29 -0
- package/src/layers/routes/useRoute.d.ts +39 -0
- package/src/layers/shared/measureLabelWidth.d.ts +11 -0
- package/src/layers/types.d.ts +131 -0
- package/src/layers/useExpandedIds.d.ts +20 -0
- package/src/layers/useFitToContent.d.ts +57 -0
- package/src/layers/useLayers.d.ts +58 -0
- package/src/layers/useMarkers/adaptiveHelpers.d.ts +156 -0
- package/src/layers/useMarkers/resolveServerClusters.d.ts +26 -0
- package/src/layers/useMarkers/useAdaptiveMarkerHelpers.d.ts +38 -0
- package/src/layers/useMarkers/useMarkers.d.ts +127 -0
- package/src/layers/useShapes/InteractiveDecoration.d.ts +23 -0
- package/src/layers/useShapes/MultiGeometryPlusBadge.d.ts +17 -0
- package/src/layers/useShapes/MultiPartBadge.d.ts +11 -0
- package/src/layers/useShapes/ShapeAnnotationLabel.d.ts +30 -0
- package/src/layers/useShapes/ShapeIcon.d.ts +21 -0
- package/src/layers/useShapes/ShapeLabelPill.d.ts +25 -0
- package/src/layers/useShapes/buildShapeLabelResolutionContext.d.ts +23 -0
- package/src/layers/useShapes/decorationFactories.d.ts +47 -0
- package/src/layers/useShapes/edge/ShapeEdgeLabel.d.ts +13 -0
- package/src/layers/useShapes/edge/computeEdgeAutoPlacement.d.ts +69 -0
- package/src/layers/useShapes/edge/computeEdgeProperties.d.ts +21 -0
- package/src/layers/useShapes/edge/edgeInsetsForFeature.d.ts +27 -0
- package/src/layers/useShapes/edge/edgeReservations.d.ts +36 -0
- package/src/layers/useShapes/edge/findBestEdgePosition.d.ts +247 -0
- package/src/layers/useShapes/extractMultiParts.d.ts +25 -0
- package/src/layers/useShapes/findBestVisibleVertex.d.ts +18 -0
- package/src/layers/useShapes/multiPartDecorations.d.ts +19 -0
- package/src/layers/useShapes/shapeDecorations.d.ts +154 -0
- package/src/layers/useShapes/shapeFeatureBuilders.d.ts +25 -0
- package/src/layers/useShapes/shapeLabelPolicy.d.ts +42 -0
- package/src/layers/useShapes/shapeLabelResolution.d.ts +45 -0
- package/src/layers/useShapes/shapeSyntheticMarkerRender.d.ts +16 -0
- package/src/layers/useShapes/useShapeDecorations.d.ts +56 -0
- package/src/layers/useShapes/useShapeLabelHelpers.d.ts +29 -0
- package/src/layers/useShapes/useShapes.d.ts +50 -0
- package/src/markers/MapMarker.d.ts +115 -0
- package/src/markers/MapMarkerIcon.d.ts +21 -0
- package/src/markers/animation/applyStickFrame.d.ts +15 -0
- package/src/markers/animation/spring.d.ts +45 -0
- package/src/markers/animation/stickFrame.d.ts +82 -0
- package/src/markers/animation/usePillBackgroundPaint.d.ts +15 -0
- package/src/markers/animation/useStickAnimation.d.ts +21 -0
- package/src/markers/animation/useStickTween.d.ts +28 -0
- package/src/markers/geometry/stickPositioning.d.ts +69 -0
- package/src/markers/geometry/useDirectionIndicator.d.ts +8 -0
- package/src/markers/internal/MapMarkerStickSurface.d.ts +47 -0
- package/src/markers/model/mapMarkerDomPortalStacking.d.ts +22 -0
- package/src/markers/model/markerDomTypes.d.ts +68 -0
- package/src/markers/model/markerResolvers.d.ts +34 -0
- package/src/markers/model/markerSizeMap.d.ts +82 -0
- package/src/markers/model/markerTuningParams.d.ts +60 -0
- package/src/markers/model/useMarkerStateResolvers.d.ts +25 -0
- package/src/markers/shared/MarkerAnimatedSurface.d.ts +20 -0
- package/src/markers/shared/MarkerDiscContent.d.ts +11 -0
- package/src/markers/shared/mapMarkerVariants.d.ts +35 -0
- package/src/markers/shared/markerColors.d.ts +55 -0
- package/src/markers/shared/useMarkerColors.d.ts +23 -0
- package/src/markers/stories/demoes/AnimationCircleVsPillDemo.d.ts +7 -0
- package/src/markers/stories/demoes/CircleIconGuidanceDemo.d.ts +2 -0
- package/src/markers/stories/demoes/DefaultDemo.d.ts +14 -0
- package/src/markers/stories/demoes/DirectionBehaviorDemo.d.ts +2 -0
- package/src/markers/stories/demoes/PillLabelLengthsDemo.d.ts +2 -0
- package/src/markers/stories/demoes/StatesDemo.d.ts +7 -0
- package/src/markers/stories/demoes/StickModeDemo.d.ts +2 -0
- package/src/markers/stories/demoes/StickModePlaygroundDemo.d.ts +10 -0
- package/src/markers/stories/helpers/AbsoluteGridPicker.d.ts +17 -0
- package/src/markers/stories/helpers/InlineLabel.d.ts +4 -0
- package/src/markers/stories/helpers/InlineSlider.d.ts +11 -0
- package/src/markers/stories/helpers/LabeledMarker.d.ts +7 -0
- package/src/markers/stories/helpers/MarkerRow.d.ts +4 -0
- package/src/markers/stories/helpers/SectionHeader.d.ts +4 -0
- package/src/markers/stories/helpers/StatesMarkerCell.d.ts +15 -0
- package/src/markers/stories/helpers/ThemedPreview.d.ts +10 -0
- package/src/markers/stories/helpers/mapMarkerStoryConstants.d.ts +4 -0
- package/src/panel/Panel.d.ts +60 -0
- package/src/panel/PanelOrchestrator.d.ts +24 -0
- package/src/panel/preload/preloadInitiators.d.ts +44 -0
- package/src/panel/preload/useHoverPreloadInitiator.d.ts +8 -0
- package/src/panel/preload/usePanelPreload.d.ts +46 -0
- package/src/panel/preload/useProximityPreloadInitiator.d.ts +13 -0
- package/src/panel/store/panels.d.ts +76 -0
- package/src/panel/storyHelpers.d.ts +9 -0
- package/src/panel/usePanel.d.ts +81 -0
- package/src/panel/utils/autoPan.d.ts +78 -0
- package/src/panel/utils/panelShellConstants.d.ts +8 -0
- package/src/panel/utils/useAutoPanResolver.d.ts +23 -0
- package/src/panel/utils/useWheelForwarding.d.ts +18 -0
- package/src/stories/InteractionDisplay.d.ts +9 -0
- package/src/stories/PositionDisplay.d.ts +9 -0
- package/src/stories/_storyCoordUtils.d.ts +8 -0
- package/src/testing/mockMapApi.d.ts +29 -0
- package/src/translation.d.ts +30 -0
- package/translation.cjs.js +30 -0
- package/translation.cjs10.js +30 -0
- package/translation.cjs11.js +30 -0
- package/translation.cjs12.js +30 -0
- package/translation.cjs13.js +30 -0
- package/translation.cjs14.js +30 -0
- package/translation.cjs15.js +30 -0
- package/translation.cjs16.js +30 -0
- package/translation.cjs17.js +30 -0
- package/translation.cjs2.js +30 -0
- package/translation.cjs3.js +30 -0
- package/translation.cjs4.js +30 -0
- package/translation.cjs5.js +30 -0
- package/translation.cjs6.js +30 -0
- package/translation.cjs7.js +30 -0
- package/translation.cjs8.js +30 -0
- package/translation.cjs9.js +30 -0
- package/translation.esm.js +28 -0
- package/translation.esm10.js +28 -0
- package/translation.esm11.js +28 -0
- package/translation.esm12.js +28 -0
- package/translation.esm13.js +28 -0
- package/translation.esm14.js +28 -0
- package/translation.esm15.js +28 -0
- package/translation.esm16.js +28 -0
- package/translation.esm17.js +28 -0
- package/translation.esm2.js +28 -0
- package/translation.esm3.js +28 -0
- package/translation.esm4.js +28 -0
- package/translation.esm5.js +28 -0
- package/translation.esm6.js +28 -0
- package/translation.esm7.js +28 -0
- package/translation.esm8.js +28 -0
- package/translation.esm9.js +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# @trackunit/react-map
|
|
2
|
+
|
|
3
|
+
Contains core map components.
|
|
4
|
+
|
|
5
|
+
Checklist:
|
|
6
|
+
[x]Both Google Maps and Mapbox adapters are implemented.
|
|
7
|
+
|
|
8
|
+
-----
|
|
9
|
+
|
|
10
|
+
Provider-agnostic map library for React applications. Switch between Google Maps and Mapbox seamlessly without code changes.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Provider Agnostic**: Use Google Maps or Mapbox with the same API
|
|
15
|
+
- **Type Safe**: Full TypeScript support with zero type assertions
|
|
16
|
+
- **Reactive**: Automatic state updates using `useSyncExternalStore`
|
|
17
|
+
- **Accessible**: ARIA labels and keyboard navigation built-in
|
|
18
|
+
- **Extensible**: Easy to add new map providers
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
The library is part of the monorepo. Dependencies are:
|
|
23
|
+
- `@vis.gl/react-google-maps` - Google Maps integration
|
|
24
|
+
- `mapbox-gl` - Mapbox GL JS integration
|
|
25
|
+
- `@trackunit/geo-json-utils` - GeoJSON type definitions
|
|
26
|
+
|
|
27
|
+
Import map providers from the adapter packages, not from `@trackunit/react-map`:
|
|
28
|
+
- Google Maps: `@trackunit/react-map-adapter-google` (`googleMapsAdapter`, `GoogleApiProvider`, …)
|
|
29
|
+
- Mapbox: `@trackunit/react-map-adapter-mapbox` (`mapboxAdapter`, …)
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Google Maps
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { useCameraState, useMap } from "@trackunit/react-map";
|
|
37
|
+
import { googleMapsAdapter } from "@trackunit/react-map-adapter-google";
|
|
38
|
+
|
|
39
|
+
const MyMap = () => {
|
|
40
|
+
const [Map, api] = useMap(googleMapsAdapter({
|
|
41
|
+
apiKey: process.env.GOOGLE_MAPS_API_KEY,
|
|
42
|
+
theme: "light",
|
|
43
|
+
language: "en",
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
const { center, zoom } = useCameraState(api);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className="relative h-full">
|
|
50
|
+
<p>Center: {center[0]}, {center[1]}</p>
|
|
51
|
+
<p>Zoom: {zoom}</p>
|
|
52
|
+
<Map className="h-full w-full">
|
|
53
|
+
{/* Children render inside the map */}
|
|
54
|
+
</Map>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Mapbox
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { useCameraState, useMap } from "@trackunit/react-map";
|
|
64
|
+
import { mapboxAdapter } from "@trackunit/react-map-adapter-mapbox";
|
|
65
|
+
|
|
66
|
+
const MyMap = () => {
|
|
67
|
+
const [Map, api] = useMap(mapboxAdapter({
|
|
68
|
+
accessToken: process.env.MAPBOX_ACCESS_TOKEN,
|
|
69
|
+
theme: "dark",
|
|
70
|
+
language: "en",
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
const { center, zoom } = useCameraState(api);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="relative h-full">
|
|
77
|
+
<p>Center: {center[0]}, {center[1]}</p>
|
|
78
|
+
<p>Zoom: {zoom}</p>
|
|
79
|
+
<Map className="h-full w-full">
|
|
80
|
+
{/* Same children work with both Google and Mapbox! */}
|
|
81
|
+
</Map>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## API
|
|
88
|
+
|
|
89
|
+
### `useMap(adapter)`
|
|
90
|
+
|
|
91
|
+
Returns a tuple `[Map, api]`:
|
|
92
|
+
|
|
93
|
+
- `Map` - React component to render the map
|
|
94
|
+
- `api.state` - Map status (isReady, initializationFailed, appearance, rasterResolution)
|
|
95
|
+
- `useCameraState(api)` - Reactive camera state (center, zoom, bounds, isIdle — changes at up to 60fps)
|
|
96
|
+
- `api.actions.setCenter(position)` - Set map center (returns promise)
|
|
97
|
+
- `api.actions.setZoom(zoom)` - Set zoom level (returns promise)
|
|
98
|
+
- `api.actions.zoomBy(delta)` - Adjust zoom by delta (returns promise)
|
|
99
|
+
- `api.actions.fitBounds(bounds, options)` - Fit map to bounds (returns promise)
|
|
100
|
+
- `api.actions.panTo(position)` - Pan to position with animation (returns promise)
|
|
101
|
+
- `api.on(event, handler)` - Subscribe to map events (returns unsubscribe function)
|
|
102
|
+
|
|
103
|
+
### Coordinates
|
|
104
|
+
|
|
105
|
+
All coordinates use GeoJSON format: `[longitude, latitude]`
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
const berlin: GeoJsonPosition = [13.405, 52.52]; // [lng, lat]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Bounding Boxes
|
|
112
|
+
|
|
113
|
+
All bounding boxes use GeoJSON format: `[minLng, minLat, maxLng, maxLat]`
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
const europeBounds: GeoJsonBbox = [-10, 35, 40, 70];
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Map Actions
|
|
120
|
+
|
|
121
|
+
All actions return promises that resolve when the map finishes moving:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
await api.actions.setCenter([13.405, 52.52]);
|
|
125
|
+
await api.actions.setZoom(12);
|
|
126
|
+
await api.actions.fitBounds([-10, 35, 40, 70], { padding: 50, maxZoom: 15 });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Map State
|
|
130
|
+
|
|
131
|
+
`api.state` contains low-frequency MapStatus (readiness, initialization failure, appearance, raster resolution). For CameraState that changes during panning/zooming, use `useCameraState(api)`:
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
// Initialization state — rarely changes
|
|
135
|
+
const { isReady, appearance } = api.state;
|
|
136
|
+
|
|
137
|
+
// Camera state — changes at up to 60fps during panning
|
|
138
|
+
const { center, zoom, bounds, isIdle } = useCameraState(api);
|
|
139
|
+
|
|
140
|
+
// Only re-renders when zoom changes (opt-in)
|
|
141
|
+
const { zoom } = useCameraState(api);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
console.log("Zoom changed:", zoom);
|
|
144
|
+
}, [zoom]);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Map Events
|
|
148
|
+
|
|
149
|
+
Subscribe to map events with type-safe handlers:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const unsubscribe = api.on("click", (e) => {
|
|
154
|
+
console.log("Clicked at:", e.position);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
return unsubscribe;
|
|
158
|
+
}, [api.on]);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Available events:
|
|
162
|
+
- `idle` - Map finished moving
|
|
163
|
+
- `movestart` - Map started moving
|
|
164
|
+
- `moveend` - Map finished moving (includes final state)
|
|
165
|
+
- `click` - Map clicked (includes position and original event)
|
|
166
|
+
|
|
167
|
+
## Switching Providers
|
|
168
|
+
|
|
169
|
+
To switch providers, only change the adapter configuration:
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
// Before: Google Maps
|
|
173
|
+
const [Map, api] = useMap(googleMapsAdapter({ apiKey: "..." }));
|
|
174
|
+
|
|
175
|
+
// After: Mapbox
|
|
176
|
+
const [Map, api] = useMap(mapboxAdapter({ accessToken: "..." }));
|
|
177
|
+
|
|
178
|
+
// Everything else stays the same!
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Configuration Options
|
|
182
|
+
|
|
183
|
+
### Google Maps Config
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
type GoogleMapsConfig = {
|
|
187
|
+
apiKey: string; // Required
|
|
188
|
+
theme?: "light" | "dark"; // Default: "light"
|
|
189
|
+
language?: string; // Map labels language
|
|
190
|
+
initialViewport?: InitialViewport; // Initial view: center+zoom or bounds
|
|
191
|
+
restrictBounds?: GeoJsonBbox | null; // Default: no restriction; null = no restriction
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Mapbox Config
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
type MapboxConfig = {
|
|
199
|
+
accessToken: string; // Required
|
|
200
|
+
theme?: "light" | "dark"; // Default: "light"
|
|
201
|
+
language?: string; // Map labels language
|
|
202
|
+
initialViewport?: InitialViewport; // Initial view: center+zoom or bounds
|
|
203
|
+
restrictBounds?: GeoJsonBbox | null; // Default: no restriction; null = no restriction
|
|
204
|
+
};
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`restrictBounds` controls panning/zoom bounds. GeoJSON format: `[minLng, minLat, maxLng, maxLat]`.
|
|
208
|
+
- `undefined` (default): no restriction (infinite horizontal scroll)
|
|
209
|
+
- `null`: no restriction (infinite horizontal scroll)
|
|
210
|
+
- `GeoJsonBbox`: restrict to custom region (e.g. Europe: `[-10, 35, 40, 70]`)
|
|
211
|
+
|
|
212
|
+
Invalid bboxes are validated with `geoJsonBboxSchema`; on failure, a console warning is emitted and no restriction is applied (fallback to `null`).
|
|
213
|
+
|
|
214
|
+
`InitialViewport` is a discriminated union:
|
|
215
|
+
- `{ type: "center"; center: [lng, lat]; zoom?: number }` — center with optional zoom
|
|
216
|
+
- `{ type: "bounds"; bounds: GeoJsonBbox; padding?: number; maxZoom?: number }` — fit to bounds
|
|
217
|
+
|
|
218
|
+
## Accessibility
|
|
219
|
+
|
|
220
|
+
Maps include built-in accessibility features:
|
|
221
|
+
|
|
222
|
+
- ARIA labels and roles
|
|
223
|
+
- Keyboard navigation:
|
|
224
|
+
- Arrow keys: Pan map (100px)
|
|
225
|
+
- +/-: Zoom in/out (1 level)
|
|
226
|
+
- Home: Reset to default view
|
|
227
|
+
- Tab: Focus map
|
|
228
|
+
- Escape: Deselect/close popups
|
|
229
|
+
|
|
230
|
+
## Architecture
|
|
231
|
+
|
|
232
|
+
For the high-level architecture, motivation, design principles, and rollout strategy, see the **[Map 2026 Design Doc](https://github.com/niceideas/design-docs/blob/main/docs/202602-Manager-Map2026/202602-Manager-Map2026.md)** in the design-docs repo.
|
|
233
|
+
|
|
234
|
+
Implementation detail in this repo is split between **[CONTEXT.md](CONTEXT.md)** (domain language and how concepts relate) and **[docs/adr/](docs/adr/)** (short architecture decision records).
|
|
235
|
+
|
|
236
|
+
| Document | What it covers |
|
|
237
|
+
|----------|---------------|
|
|
238
|
+
| [CONTEXT.md](CONTEXT.md) | Glossary: Adapter, Layer Hook, Layer Handle, Layer Port, Entity, Control Config, Annotation, Decoration, and relationships between them |
|
|
239
|
+
| [ADR 0001 — Hook-first map API](docs/adr/0001-hook-first-api.md) | `useMap(adapter)` tuple as the primary API; tuple vs object vs component-first |
|
|
240
|
+
| [ADR 0002 — Adapter factory pattern](docs/adr/0002-adapter-factory-pattern.md) | Adapter factories, `defineAdapter`, `derive`, keeping provider knowledge at the call site |
|
|
241
|
+
| [ADR 0003 — Controls as data](docs/adr/0003-controls-as-data.md) | Control configs as data, discriminated union, middleware pipeline, presentational renderers |
|
|
242
|
+
| [ADR 0004 — Declarative LayerPort snapshot](docs/adr/0004-layer-port-declarative-snapshot.md) | `LayerPort.setSnapshot`, single write path, adapter-owned diffing |
|
|
243
|
+
| [ADR 0005 — Annotation store on MapApi](docs/adr/0005-annotation-store-on-map-api.md) | `MapApi.annotations`, explicit `api` at call sites, renderer claims |
|
|
244
|
+
| [ADR 0006 — Adapters own DOM marker positioning](docs/adr/0006-marker-anchor-ownership.md) | Marker anchors owned by the adapter; no competing transforms in DOM content |
|
|
245
|
+
| [ADR 0007 — Antimeridian shapes merged in adapters](docs/adr/0007-antimeridian-merge-in-adapters.md) | Merging split GeoJSON at render time inside adapters, not in app state |
|
|
246
|
+
| [ADR 0008 — Map panel store on MapApi](docs/adr/0008-map-panel-store-on-map-api.md) | `MapApi.panels`, `usePanel`, `PanelOrchestrator`, menu presentation via panels |
|
|
247
|
+
| [ADR 0009 — Declarative MarkerState](docs/adr/0009-declarative-marker-state.md) | State-driven union prop over imperative marker API |
|
|
248
|
+
| [ADR 0010 — Unified marker render tree](docs/adr/0010-unified-marker-render-tree.md) | Always-mounted slots animated via CSS; no separate circle/pill components |
|
|
249
|
+
| [ADR 0011 — Stick mode anchor-zero + transform animation](docs/adr/0011-stick-anchor-zero-transform-animation.md) | Zero-size anchor container; CSS three-function transform; no JS width measurement |
|
|
250
|
+
| [ADR 0012 — Fixed size ladder with locked pill tier](docs/adr/0012-marker-size-ladder-fixed-pill-tier.md) | Five-tier `MarkerDomSize` enum; pill layout fixed to `md` tier |
|
|
251
|
+
| [ADR 0013 — GpsArrowNorth icon](docs/adr/0013-gps-arrow-north-icon.md) | North-facing SVG variant eliminates `heading - 45` magic offset at call sites |
|
|
252
|
+
| [ADR 0020 — Map state is split by update frequency](docs/adr/0020-map-state-channels.md) | `MapStatus` on `api.state`, `CameraState` via `useCameraState(api)`, and separate adapter notification channels |
|
|
253
|
+
| [@trackunit/react-map-adapter-google README](../map-adapter-google/README.md) | Google Maps adapter: exports, `GoogleApiProvider`, multiple maps |
|
|
254
|
+
| [@trackunit/react-map-adapter-mapbox README](../map-adapter-mapbox/README.md) | Mapbox adapter: exports, configuration, typical usage |
|
|
255
|
+
|
|
256
|
+
## Testing
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Run all tests
|
|
260
|
+
yarn nx test react-map
|
|
261
|
+
|
|
262
|
+
# Run type checking
|
|
263
|
+
yarn nx run react-map:tsc-validate
|
|
264
|
+
|
|
265
|
+
# Run linting
|
|
266
|
+
yarn nx lint react-map
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Adding New Providers
|
|
270
|
+
|
|
271
|
+
To add a new map provider:
|
|
272
|
+
|
|
273
|
+
1. Create adapter instance implementing `AdapterInstance<TConfig>`
|
|
274
|
+
2. Create type converters (GeoJSON ↔ provider types)
|
|
275
|
+
3. Create renderer component
|
|
276
|
+
4. Create adapter factory using `defineAdapter()`
|
|
277
|
+
5. Export from `index.ts`
|
|
278
|
+
|
|
279
|
+
Example structure:
|
|
280
|
+
```
|
|
281
|
+
src/adapters/leaflet/
|
|
282
|
+
├── leafletAdapter.ts
|
|
283
|
+
├── LeafletAdapterInstance.ts
|
|
284
|
+
├── LeafletRenderer.tsx
|
|
285
|
+
├── leafletTypeConverters.ts
|
|
286
|
+
└── constants.ts
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
For more info and a full guide on Iris App SDK Development, please visit our [Developer Hub](https://developers.trackunit.com/).
|
|
290
|
+
|
|
291
|
+
## Trackunit
|
|
292
|
+
|
|
293
|
+
This package was developed by Trackunit ApS.
|
|
294
|
+
Trackunit is the leading SaaS-based IoT solution for the construction industry, offering an ecosystem of hardware, fleet management software & telematics.
|
|
295
|
+
|
|
296
|
+

|