@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,395 @@
1
+ import type { BasicToggleGroupListProps, CommonProps, Icon, Size } from "@trackunit/react-components";
2
+ import type { ComponentProps, ReactNode } from "react";
3
+ /** Extract IconName from Icon component props */
4
+ export type IconName = ComponentProps<typeof Icon>["name"];
5
+ /** Where the control appears in the UI hierarchy */
6
+ export type Placement = "standalone" | "menu";
7
+ /** Raw environment signal -- how much space the container has */
8
+ export type AvailableSpace = "constrained" | "comfortable";
9
+ /** Computed sizing decision -- set by the sizing middleware from placement + availableSpace */
10
+ export type Compactness = "compact" | "spacious";
11
+ /** The full rendering context that drives all layout decisions */
12
+ export type RenderContext = Readonly<{
13
+ placement: Placement;
14
+ availableSpace: AvailableSpace;
15
+ }>;
16
+ /** Shared resolved fields set by cross-cutting middleware (before type-specific resolution) */
17
+ export type ResolvedControlPropsBase = Readonly<{
18
+ /** Physical size of the control -- aligns with component library Size type */
19
+ size: Size;
20
+ /** Whether the control should be rendered at all */
21
+ visible: boolean;
22
+ /** Spacing between sub-elements (e.g. stepper buttons) */
23
+ gap: string;
24
+ /** Sizing decision: "compact" when in a menu or constrained container, "spacious" otherwise */
25
+ compactness: Compactness;
26
+ /** Resolved icon (state-dependent for toggles, static for buttons) */
27
+ icon?: IconName;
28
+ }>;
29
+ /** All control type discriminants (derived from config unions + separator) */
30
+ type ControlType = ControlConfig["type"] | SeparatorItemConfig["type"];
31
+ /**
32
+ * Discriminated union of resolved control props.
33
+ *
34
+ * Discriminant: `controlType` -- mirrors the config's `type` field.
35
+ * Flat mapped type: every control type resolves to `ResolvedControlPropsBase`
36
+ * plus a `controlType` discriminant.
37
+ */
38
+ export type ResolvedControlProps = {
39
+ [K in ControlType]: ResolvedControlPropsBase & Readonly<{
40
+ controlType: K;
41
+ }>;
42
+ }[ControlType];
43
+ /**
44
+ * What happens to a control when responsive collapsing moves it into a menu.
45
+ *
46
+ * - `"menu"` (default) -- the control is placed inside the overflow menu
47
+ * - `"hide"` -- the control is fully removed instead of being menued
48
+ *
49
+ * Use `"hide"` for controls that only make sense as standalone map overlays
50
+ * and would be confusing or useless inside a menu (e.g. a visual indicator
51
+ * that has no interactive menu representation).
52
+ */
53
+ export type OverflowBehavior = "menu" | "hide";
54
+ /** Base fields shared by all controls */
55
+ type BaseControlConfig<TType extends string> = Readonly<CommonProps & {
56
+ type: TType;
57
+ id: string;
58
+ /**
59
+ * What happens when responsive collapsing would move this control into a menu.
60
+ *
61
+ * - `"menu"` (default) -- placed inside the overflow menu alongside other controls
62
+ * - `"hide"` -- fully hidden instead of being menued
63
+ *
64
+ * @default "menu"
65
+ */
66
+ overflowBehavior?: OverflowBehavior;
67
+ }>;
68
+ /** Simple icon button - click action */
69
+ export type ButtonControlConfig = BaseControlConfig<"button"> & Readonly<{
70
+ icon: IconName;
71
+ label: string;
72
+ onClick: () => void;
73
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
74
+ section?: string;
75
+ }>;
76
+ /** Two connected buttons for increment/decrement (zoom) */
77
+ export type StepperControlConfig = BaseControlConfig<"stepper"> & Readonly<{
78
+ /** Display label for the whole stepper control (e.g. "Zoom") */
79
+ label: string;
80
+ increment: () => void;
81
+ decrement: () => void;
82
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
83
+ section?: string;
84
+ }>;
85
+ /** Shared fields for boolean (on/off) controls: toggle and checkbox */
86
+ type BooleanControlFields = Readonly<{
87
+ label: string;
88
+ value: boolean;
89
+ onChange: (value: boolean) => void;
90
+ /**
91
+ * State-dependent icons shown when the control is on or off (standalone only).
92
+ * Both must be provided together — this prevents partial-icon bugs where
93
+ * only one state has a visible icon.
94
+ *
95
+ * - **Standalone**: the state-appropriate icon is shown on the button; omitted falls back to Check/XMark
96
+ * - **Menu**: icon is never shown (not exposed; would look cluttered)
97
+ */
98
+ icon?: Readonly<{
99
+ on: IconName;
100
+ off: IconName;
101
+ }>;
102
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
103
+ section?: string;
104
+ }>;
105
+ /** Toggle switch - boolean value (renders ToggleSwitch in menus) */
106
+ export type ToggleControlConfig = BaseControlConfig<"toggle"> & BooleanControlFields;
107
+ /** Checkbox - boolean value (renders Checkbox in menus) */
108
+ export type CheckboxControlConfig = BaseControlConfig<"checkbox"> & BooleanControlFields;
109
+ /** Union of all boolean (on/off) control configs */
110
+ export type BooleanControlConfig = ToggleControlConfig | CheckboxControlConfig;
111
+ /** Select dropdown - string options */
112
+ export type SelectControlConfig<TValue extends string = string> = BaseControlConfig<"select"> & Readonly<{
113
+ label: string;
114
+ value: TValue;
115
+ options: ReadonlyArray<Readonly<{
116
+ value: TValue;
117
+ label: string;
118
+ }>>;
119
+ onChange: (value: TValue) => void;
120
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
121
+ section?: string;
122
+ }>;
123
+ /** Radio group - mutually exclusive string options (RadioGroup + RadioItem in the design system) */
124
+ export type RadioGroupControlConfig<TValue extends string = string> = BaseControlConfig<"radioGroup"> & Readonly<{
125
+ label: string;
126
+ value: TValue;
127
+ options: ReadonlyArray<Readonly<{
128
+ value: TValue;
129
+ label: string;
130
+ }>>;
131
+ onChange: (value: TValue) => void;
132
+ /** Icon on the standalone trigger button (menu uses labeled RadioGroup only) */
133
+ icon: IconName;
134
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
135
+ section?: string;
136
+ }>;
137
+ /**
138
+ * One segment in a toggle group — matches {@link BasicToggleGroupListProps} for the design-system `ToggleGroup` `list` prop.
139
+ */
140
+ export type ToggleGroupOption<TValue extends string = string> = Readonly<BasicToggleGroupListProps<TValue>>;
141
+ /**
142
+ * Segmented toggle group — mutually exclusive options (design-system `ToggleGroup`).
143
+ * Standalone uses icon-only styling per map controls patterns (every option must define `iconName`);
144
+ * menu supports text-only segments and icons.
145
+ */
146
+ export type ToggleGroupControlConfig<TValue extends string = string> = BaseControlConfig<"toggleGroup"> & Readonly<{
147
+ /** Accessible name for the control (group label). */
148
+ label: string;
149
+ value: TValue;
150
+ options: ReadonlyArray<ToggleGroupOption<TValue>>;
151
+ onChange: (value: TValue) => void;
152
+ disabled?: boolean;
153
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
154
+ section?: string;
155
+ }>;
156
+ /** Search control - string value with search/filter UI */
157
+ export type SearchControlConfig = BaseControlConfig<"search"> & Readonly<{
158
+ label: string;
159
+ value: string;
160
+ placeholder?: string;
161
+ onChange: (value: string) => void;
162
+ onClear?: () => void;
163
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
164
+ section?: string;
165
+ }>;
166
+ /** Separator between items in a menu */
167
+ export type SeparatorItemConfig = Readonly<{
168
+ type: "separator";
169
+ }>;
170
+ /** Items that can appear inside a menu (excludes menu itself -- menus cannot nest) */
171
+ export type MenuItemConfig = Readonly<ToggleControlConfig | CheckboxControlConfig | ButtonControlConfig | SelectControlConfig | RadioGroupControlConfig | ToggleGroupControlConfig | SearchControlConfig | StepperControlConfig | SeparatorItemConfig | CustomControlConfig>;
172
+ /** Menu control - groups other controls in a popover */
173
+ export type MenuControlConfig = BaseControlConfig<"menu"> & Readonly<{
174
+ /** Icon shown on the menu trigger button */
175
+ icon: IconName;
176
+ /** Tooltip/label for the menu trigger button */
177
+ label: string;
178
+ /** Items in the menu */
179
+ items: ReadonlyArray<MenuItemConfig>;
180
+ }>;
181
+ /**
182
+ * Context passed to custom control render functions.
183
+ *
184
+ * Contains all environment information needed to adapt rendering.
185
+ * Built-in control types handle these concerns automatically through
186
+ * the middleware pipeline. With custom controls, **you** are responsible
187
+ * for adapting to placement and compactness.
188
+ *
189
+ * @see {@link CustomControlConfig} for full usage guidance.
190
+ */
191
+ export type CustomControlRenderContext = Readonly<{
192
+ /**
193
+ * Resolved rendering props from the middleware pipeline.
194
+ * Contains pre-computed decisions (size, gap, compactness, visible)
195
+ * that you should respect for visual consistency with built-in controls.
196
+ */
197
+ resolved: ResolvedControlProps;
198
+ /** Current placement -- "standalone" (floating on the map) or "menu" (inside a popover) */
199
+ placement: Placement;
200
+ }>;
201
+ /**
202
+ * Custom React component control -- **escape hatch** for cases not covered
203
+ * by the built-in control types (button, toggle, stepper, select, radioGroup, toggleGroup, search, menu).
204
+ *
205
+ * Custom controls can appear both **standalone** (floating on the map) and
206
+ * **inside menus** (as a menu item). At narrow screen widths the system may
207
+ * collapse any control into a menu, so your render function **must** handle
208
+ * both placements.
209
+ *
210
+ * ---
211
+ *
212
+ * **PREFER BUILT-IN TYPES.** Custom controls bypass the type-safe rendering
213
+ * pipeline and require you to manually handle:
214
+ *
215
+ * - **Compactness** -- use `resolved.compactness` to adapt sizing/spacing
216
+ * - **Placement** -- standalone (icon button + tooltip) vs menu (labeled item).
217
+ * When `placement === "menu"`, render a menu-compatible layout: use `px-3 py-2`
218
+ * padding, `role="menuitem"`, and ensure the control is keyboard-navigable.
219
+ * - **Tooltips** -- show tooltip when `placement === "standalone"`
220
+ * - **Sizing** -- use `resolved.size` for consistency with other controls
221
+ * - **Accessibility** -- keyboard navigation, ARIA attributes, focus management
222
+ * - **Pointer events** -- in standalone mode your content is inside a
223
+ * `pointer-events-none` overlay (the container re-enables `pointer-events-auto`)
224
+ *
225
+ * If a built-in type can achieve what you need, use it instead. This escape
226
+ * hatch exists for genuinely novel UI that no config-driven type can express.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * const customControl: CustomControlConfig = {
231
+ * type: "custom",
232
+ * id: "battery-indicator",
233
+ * label: "Battery Level",
234
+ * render: ({ placement, resolved }) => {
235
+ * // Menu placement -- render as a labeled row matching other menu items
236
+ * if (placement === "menu") {
237
+ * return (
238
+ * <div className="px-3 py-2" role="menuitem">
239
+ * <BatteryGauge level={72} size="small" showLabel />
240
+ * </div>
241
+ * );
242
+ * }
243
+ * // Standalone placement -- compact icon-style widget
244
+ * return (
245
+ * <BatteryGauge
246
+ * size={resolved.size}
247
+ * compact={resolved.compactness === "compact"}
248
+ * />
249
+ * );
250
+ * },
251
+ * };
252
+ * ```
253
+ */
254
+ export type CustomControlConfig = BaseControlConfig<"custom"> & Readonly<{
255
+ /**
256
+ * Required label for accessibility -- used as tooltip text in standalone
257
+ * placement (when {@link autoTooltip} is `"standalone"`). Even custom
258
+ * controls need an accessible name.
259
+ */
260
+ label: string;
261
+ /**
262
+ * Controls automatic tooltip wrapping in standalone placement.
263
+ * - `"standalone"` (default): wraps output in `Tooltip` using `label`.
264
+ * - `"none"`: suppresses auto-tooltip — use when the rendered content manages its own label.
265
+ */
266
+ autoTooltip?: "standalone" | "none";
267
+ /** Section name for grouping in menus (consecutive items with same section get a header) */
268
+ section?: string;
269
+ /**
270
+ * Render function that produces the custom control's UI.
271
+ *
272
+ * Receives the full rendering context so the control can adapt to the
273
+ * environment. You **must** handle compactness and placement changes --
274
+ * the pipeline provides the information but cannot enforce its use.
275
+ *
276
+ * The returned ReactNode is rendered inside the controls overlay.
277
+ * It will already have `pointer-events-auto` applied on its container.
278
+ */
279
+ render: (context: CustomControlRenderContext) => ReactNode;
280
+ /**
281
+ * Optional custom resolver that runs after the standard middleware pipeline
282
+ * but before your render function receives the resolved props.
283
+ *
284
+ * Use this to transform or extend the resolved props based on the environment.
285
+ * For example, override size decisions or add custom visibility logic.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * resolve: (resolved, renderContext) => ({
290
+ * ...resolved,
291
+ * // Hide in constrained containers -- too detailed for small spaces
292
+ * visible: renderContext.availableSpace !== "constrained",
293
+ * })
294
+ * ```
295
+ */
296
+ resolve?: (resolved: ResolvedControlPropsBase, renderContext: RenderContext) => ResolvedControlPropsBase;
297
+ }>;
298
+ /**
299
+ * Discriminated union of all control types (top-level).
300
+ *
301
+ * Prefer the built-in types (button, stepper, toggle, checkbox, select, radioGroup, toggleGroup, search, menu)
302
+ * which participate fully in the rendering pipeline. Use "custom" only as an
303
+ * escape hatch for genuinely novel UI.
304
+ */
305
+ export type ControlConfig = Readonly<ButtonControlConfig | StepperControlConfig | ToggleControlConfig | CheckboxControlConfig | SelectControlConfig | RadioGroupControlConfig | ToggleGroupControlConfig | SearchControlConfig | MenuControlConfig | CustomControlConfig>;
306
+ /** Navigation area - array of controls */
307
+ export type NavigationConfig = Readonly<{
308
+ controls: ReadonlyArray<ControlConfig>;
309
+ }>;
310
+ /** Settings area - array of controls */
311
+ export type SettingsConfig = Readonly<{
312
+ controls: ReadonlyArray<ControlConfig>;
313
+ }>;
314
+ /** Statistics area - array of controls */
315
+ export type StatisticsConfig = Readonly<{
316
+ controls: ReadonlyArray<ControlConfig>;
317
+ }>;
318
+ /** Complete controls configuration */
319
+ export type ControlsConfig = Readonly<{
320
+ /** Navigation controls: zoom, fullscreen, compass (future), reset view (future) */
321
+ navigation: NavigationConfig;
322
+ /** Settings: layer toggles, layer settings (future), map style (future) */
323
+ settings: SettingsConfig;
324
+ /** Tools: drawing, measurement, selection (future) */
325
+ tools: null;
326
+ /** Statistics: data summaries, counts */
327
+ statistics: StatisticsConfig;
328
+ }>;
329
+ /**
330
+ * Built-in navigation controls returned by `useControlsConfig`.
331
+ *
332
+ * Consumers composing custom control stacks can use these named handles instead
333
+ * of re-identifying built-ins by their string ids after the controls are built.
334
+ */
335
+ export interface BuiltInNavigationConfig extends NavigationConfig {
336
+ readonly zoom: StepperControlConfig | undefined;
337
+ readonly fullscreen: ToggleControlConfig | undefined;
338
+ readonly myLocation: ButtonControlConfig | undefined;
339
+ }
340
+ /** Built-in settings controls returned by `useControlsConfig`. */
341
+ export interface BuiltInSettingsConfig extends SettingsConfig {
342
+ readonly mapStyle: MenuControlConfig | undefined;
343
+ }
344
+ /** Controls config with named handles for the controls built by `useControlsConfig`. */
345
+ export interface BuiltInControlsConfig extends ControlsConfig {
346
+ readonly navigation: BuiltInNavigationConfig;
347
+ readonly settings: BuiltInSettingsConfig;
348
+ }
349
+ /**
350
+ * How a menu presents its content.
351
+ *
352
+ * - `"popover"` — floating `MoreMenu` popover anchored to the trigger button.
353
+ * - `"modal"` — bottom `Sheet` dialog (`variant="modal"`) with a backdrop.
354
+ *
355
+ * `Controls` derives this from `availableSpace`: `"constrained"` containers get
356
+ * `"modal"` (Sheet bottom-sheet, better on small screens); `"comfortable"` containers
357
+ * get `"popover"` (floating popover, better when there is room).
358
+ */
359
+ export type MenuPresentation = "popover" | "modal";
360
+ /**
361
+ * How aggressively controls are collapsed based on available space.
362
+ *
363
+ * - `"full"` -- all standalone controls shown as-is (wide containers)
364
+ * - `"categorized"` -- controls within each category grouped into a per-category
365
+ * menu when >1 control exists in that category (medium containers)
366
+ * - `"collapsed"` -- all controls collapsed into a single menu button with
367
+ * named sections per category (narrow containers)
368
+ */
369
+ export type ResponsiveMode = "full" | "categorized" | "collapsed";
370
+ /** The four semantic control areas used for categorization and section headers */
371
+ export type CategoryKey = "navigation" | "settings" | "tools" | "statistics";
372
+ /**
373
+ * Options for configuring controls when calling useMap
374
+ */
375
+ export type ControlsOptions = Readonly<{
376
+ zoom?: Readonly<{
377
+ enabled?: boolean;
378
+ }>;
379
+ fullscreen?: Readonly<{
380
+ enabled?: boolean;
381
+ }>;
382
+ mapStyle?: Readonly<{
383
+ enabled?: boolean;
384
+ }>;
385
+ myLocation?: Readonly<{
386
+ enabled?: boolean;
387
+ }>;
388
+ }>;
389
+ /**
390
+ * Options passed to useMap for configuring map behavior
391
+ */
392
+ export type UseMapOptions = Readonly<{
393
+ controls?: ControlsOptions;
394
+ }>;
395
+ export {};
@@ -0,0 +1,15 @@
1
+ type AnimatedPresenceResult = Readonly<{
2
+ shouldRender: boolean;
3
+ isExiting: boolean;
4
+ }>;
5
+ /**
6
+ * Delays unmounting by `durationMs` after `isPresent` becomes false,
7
+ * giving consumers time to run an exit animation before the element
8
+ * is removed from the DOM.
9
+ *
10
+ * Returns `shouldRender: true` while the element should remain mounted
11
+ * (including during the exit window) and `isExiting: true` during the
12
+ * exit animation window.
13
+ */
14
+ export declare const useAnimatedPresence: (isPresent: boolean, durationMs: number) => AnimatedPresenceResult;
15
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { MapAnnotationDescriptor, MapAnnotationStore } from "../annotations/mapAnnotations";
2
+ type AnnotationPresenceResult = Readonly<{
3
+ displayAnnotations: ReadonlyArray<MapAnnotationDescriptor>;
4
+ isExiting: boolean;
5
+ shouldRender: boolean;
6
+ }>;
7
+ /**
8
+ * Subscribes to a `MapAnnotationStore` and drives animated enter/exit
9
+ * for the AnnotationStack.
10
+ *
11
+ * During the exit window the hook keeps serving the last non-empty
12
+ * snapshot so the stack can animate out before the DOM elements are
13
+ * removed.
14
+ */
15
+ export declare const useAnnotationPresence: (store: MapAnnotationStore) => AnnotationPresenceResult;
16
+ export {};
@@ -0,0 +1,21 @@
1
+ import { collapseControls } from "./collapseControls";
2
+ import { defineControlStack } from "./defineControlStack";
3
+ export type ControlStackHelpers = Readonly<{
4
+ defineControlStack: typeof defineControlStack;
5
+ collapseControls: typeof collapseControls;
6
+ }>;
7
+ /**
8
+ * Build-your-own hook: stable references to control composition/layout helpers.
9
+ *
10
+ * Returns `defineControlStack` and `collapseControls` for consumers building
11
+ * custom control layouts without duplicating the stack-ordering and responsive-
12
+ * collapse logic already used by `Controls`.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const { defineControlStack, collapseControls } = useControlStack();
17
+ * const controls = defineControlStack([myControl, undefined, otherControl]);
18
+ * const collapsed = collapseControls(config, responsiveMode, metadata);
19
+ * ```
20
+ */
21
+ export declare const useControlStack: () => ControlStackHelpers;
@@ -0,0 +1,27 @@
1
+ import type { AdapterConfig } from "@trackunit/react-map-adapter-shared";
2
+ import type { ContainerRefHolder, MapActions, MapStatus } from "../core/types";
3
+ import type { BuiltInControlsConfig, UseMapOptions } from "./types";
4
+ /**
5
+ * Partial MapApi type used by useControlsConfig.
6
+ * Includes only the fields this hook (and its sub-hooks) actually need,
7
+ * avoiding a direct dependency on the full MapApi type.
8
+ */
9
+ type MapApiWithoutControls = Readonly<{
10
+ state: MapStatus;
11
+ actions: MapActions;
12
+ adapterConfig: AdapterConfig;
13
+ containerRef: ContainerRefHolder;
14
+ }>;
15
+ type UseControlsConfigParams = Readonly<{
16
+ options?: UseMapOptions;
17
+ api: MapApiWithoutControls;
18
+ }>;
19
+ /**
20
+ * Builds the controls configuration from useMap options and api.
21
+ *
22
+ * Creates control config objects with bound callbacks for each enabled control.
23
+ * The Controls component uses this configuration to render controls.
24
+ * Consumers can compose custom stacks from the named built-in handles.
25
+ */
26
+ export declare const useControlsConfig: ({ options, api }: UseControlsConfigParams) => BuiltInControlsConfig;
27
+ export {};
@@ -0,0 +1,33 @@
1
+ import type { PopoverPlacement } from "@trackunit/react-components";
2
+ import { type RefObject } from "react";
3
+ type UsePopoverPlacementOptions = Readonly<{
4
+ skip?: boolean;
5
+ }>;
6
+ /**
7
+ * Compute the ideal popover placement for a trigger element based on its
8
+ * physical position inside a container (e.g. the map controls overlay).
9
+ *
10
+ * The popover opens *toward the center* of the container so it stays inside
11
+ * the map square:
12
+ *
13
+ * | Trigger position | Popover direction | Placement |
14
+ * |------------------|-------------------|------------------|
15
+ * | top-left | down-right | `"bottom-start"` |
16
+ * | top-center | down | `"bottom"` |
17
+ * | top-right | down-left | `"bottom-end"` |
18
+ * | bottom-left | up-right | `"top-start"` |
19
+ * | bottom-center | up | `"top"` |
20
+ * | bottom-right | up-left | `"top-end"` |
21
+ *
22
+ * Recomputes when the container resizes (via ResizeObserver).
23
+ */
24
+ export declare const computePlacement: (triggerEl: HTMLElement, containerEl: HTMLElement) => PopoverPlacement;
25
+ /**
26
+ * Returns the ideal `PopoverPlacement` for a trigger element based on its
27
+ * physical position within a container element.
28
+ *
29
+ * Purely position-based — not tied to semantic area names. If the layout
30
+ * changes or controls move, the placement adapts automatically.
31
+ */
32
+ export declare const usePopoverPlacement: (triggerRef: RefObject<HTMLElement | null>, containerRef: RefObject<HTMLElement | null>, options?: UsePopoverPlacementOptions) => PopoverPlacement;
33
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { ReactElement } from "react";
2
+ /**
3
+ * Small pill that displays a loading spinner on the map.
4
+ * Styled to visually match the control buttons (secondary variant)
5
+ * while remaining non-interactive.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare const LoadingIndicatorPill: () => ReactElement;
@@ -0,0 +1,17 @@
1
+ import type { CSSProperties, ReactElement } from "react";
2
+ type MapLoadingStateProps = {
3
+ /** Whether the map is currently loading */
4
+ isLoading: boolean;
5
+ /** Whether there was an error loading the map */
6
+ error?: boolean;
7
+ /** CSS class name */
8
+ className?: string;
9
+ /** Inline styles */
10
+ style?: CSSProperties;
11
+ };
12
+ /**
13
+ * Accessible loading state component for the map
14
+ * Shows a spinner while loading, error message on failure
15
+ */
16
+ export declare const MapLoadingState: ({ isLoading, error, className, style }: MapLoadingStateProps) => ReactElement;
17
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { AvailableSpace, ResponsiveMode } from "../controls/types";
2
+ export declare const SafeAreaLayoutContext: import("react").Context<Readonly<{
3
+ availableSpace: AvailableSpace;
4
+ responsiveMode: ResponsiveMode;
5
+ }> | null>;
@@ -0,0 +1,23 @@
1
+ import type { AdapterConfig, AdapterInstance, AdapterRendererProps, CameraState, MapStatus, SafeAreaInsets } from "@trackunit/react-map-adapter-shared";
2
+ import type { ReactElement } from "react";
3
+ import type { MapApi, MapState } from "./types";
4
+ export type MockConfig = {
5
+ readonly apiKey: string;
6
+ };
7
+ export declare const INITIAL_MOCK_MAP_STATE: MapState;
8
+ export declare const READY_MOCK_MAP_STATE: MapState;
9
+ export type MockAdapterInstance = AdapterInstance<MockConfig> & {
10
+ readonly _setState: (state: Partial<MapState>) => void;
11
+ readonly _connect: () => void;
12
+ };
13
+ export type MockAdapterConfig = AdapterConfig<MockConfig> & {
14
+ readonly instance: MockAdapterInstance;
15
+ };
16
+ export type MutableMockMapApi = Readonly<{
17
+ api: MapApi;
18
+ setCameraState: (cameraState: Partial<CameraState>) => void;
19
+ }>;
20
+ export declare const TestHelpers: ({ children }: AdapterRendererProps) => ReactElement;
21
+ export declare const createMockAdapter: (config: MockConfig, initialState?: MapState) => MockAdapterInstance;
22
+ export declare const createMockAdapterConfig: (config: MockConfig, initialState?: MapState, safeAreaInsets?: SafeAreaInsets | null) => MockAdapterConfig;
23
+ export declare const createMutableMockMapApi: (initialCameraState?: Partial<CameraState>, initialStatus?: MapStatus) => MutableMockMapApi;
@@ -0,0 +1,32 @@
1
+ import type { AdapterInstance, AdapterRendererProps, SafeAreaInsets } from "@trackunit/react-map-adapter-shared";
2
+ import { type ComponentType } from "react";
3
+ import type { MapAnnotationStore } from "../annotations/mapAnnotations";
4
+ import type { PanelStore } from "../panel/store/panels";
5
+ import { MapLoadingIndicatorStore } from "./loadingIndicator";
6
+ import type { ContainerRefHolder, MapComponentProps } from "./types";
7
+ type CreateMapComponentConfig = Readonly<{
8
+ adapter: AdapterInstance;
9
+ Renderer: ComponentType<AdapterRendererProps>;
10
+ adapterName: string;
11
+ containerRefHolder?: ContainerRefHolder;
12
+ containerId?: string;
13
+ annotationStore?: MapAnnotationStore;
14
+ loadingIndicatorStore?: MapLoadingIndicatorStore;
15
+ panelStore?: PanelStore;
16
+ safeAreaInsets?: SafeAreaInsets | null;
17
+ }>;
18
+ /**
19
+ * Creates a named Map component for the given adapter.
20
+ *
21
+ * When a `containerRefHolder` is provided (from `useMap`), the component renders a
22
+ * wrapper div that owns the container ref and applies ZStack grid classes
23
+ * so children (e.g. Controls) can overlay the map.
24
+ * The adapter/Renderer never receives container-related props.
25
+ *
26
+ * When no `containerRefHolder` is provided (from `usePreviewMap`), the component
27
+ * still wraps the Renderer in a relative container and draws the readiness overlay on top (SAGA-374).
28
+ *
29
+ * @internal
30
+ */
31
+ export declare const createMapComponent: ({ adapter, Renderer, adapterName, containerRefHolder, containerId, annotationStore, loadingIndicatorStore, panelStore, safeAreaInsets, }: CreateMapComponentConfig) => ComponentType<MapComponentProps>;
32
+ export {};
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Subscription-based store for the map loading indicator.
3
+ * Compatible with `useSyncExternalStore(subscribe, getSnapshot)`.
4
+ *
5
+ * `useLayers` pushes its aggregated `loading` boolean into this store.
6
+ * `createMapComponent` subscribes and renders a spinner overlay when active.
7
+ */
8
+ export type MapLoadingIndicatorStore = Readonly<{
9
+ setLoading: (loading: boolean) => void;
10
+ subscribe: (callback: () => void) => () => void;
11
+ getSnapshot: () => boolean;
12
+ }>;
13
+ /**
14
+ * Creates a `MapLoadingIndicatorStore` instance.
15
+ *
16
+ * Internally tracks a single boolean. `setLoading` only notifies subscribers
17
+ * when the value actually changes, preventing unnecessary re-renders.
18
+ *
19
+ * @internal
20
+ */
21
+ export declare const createMapLoadingIndicatorStore: () => MapLoadingIndicatorStore;
@@ -0,0 +1,5 @@
1
+ import type { CSSProperties } from "react";
2
+ import type { SafeAreaInsets } from "@trackunit/react-map-adapter-shared";
3
+ import type { AvailableSpace } from "../controls/types";
4
+ /** Build padding style that combines spacing with safe area insets. */
5
+ export declare const padWithInsets: (availableSpace: AvailableSpace, insets: SafeAreaInsets | null) => CSSProperties;