@trackunit/react-map 0.0.9 → 0.0.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-map",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -19,11 +19,11 @@ import { type UseMapAppearanceControlsParams } from "./appearanceTypes";
19
19
  * const controlsConfig: ControlsConfig = {
20
20
  * navigation: { controls: navigationControls },
21
21
  * settings: { controls: appearanceControls },
22
- * tools: null,
22
+ * tools: { controls: [] },
23
23
  * statistics: { controls: [] },
24
24
  * };
25
25
  *
26
- * <Controls api={api} controlsConfig={controlsConfig} />
26
+ * <Controls api={api} controls={controlsConfig} />
27
27
  * ```
28
28
  */
29
29
  export declare const useMapAppearanceControls: ({ api, options: appearanceOptions, persistenceKey, }: UseMapAppearanceControlsParams) => ReadonlyArray<MenuControlConfig>;
@@ -3,13 +3,10 @@ import type { ControlsConfig } from "./types";
3
3
  type ControlsProps = Readonly<{
4
4
  /** The map API object from useMap */
5
5
  api: MapApi;
6
+ /** Controls configuration built from useDefaultControls, useControls, or composeControlAreas */
7
+ controls: ControlsConfig;
6
8
  /** Additional CSS classes for the controls container */
7
9
  className?: string;
8
- /**
9
- * Custom controls configuration to override the default.
10
- * If provided, this will be used instead of building from api.options.
11
- */
12
- controlsConfig?: ControlsConfig;
13
10
  }>;
14
- export declare const Controls: import("react").MemoExoticComponent<({ api, className, controlsConfig: controlsConfigProp }: ControlsProps) => import("react/jsx-runtime").JSX.Element>;
11
+ export declare const Controls: import("react").MemoExoticComponent<({ api, controls, className }: ControlsProps) => import("react/jsx-runtime").JSX.Element>;
15
12
  export {};
@@ -0,0 +1,37 @@
1
+ import type { MapApi } from "../core/types";
2
+ import { type UseDefaultControlsOptions } from "./useDefaultControls";
3
+ type DefaultControlsProps = Readonly<{
4
+ /** The map API object from useMap */
5
+ api: MapApi;
6
+ /** Optional configuration to disable individual built-in controls */
7
+ options?: UseDefaultControlsOptions;
8
+ /** Additional CSS classes for the controls container */
9
+ className?: string;
10
+ }>;
11
+ /**
12
+ * Convenience wrapper that calls `useDefaultControls` and passes the result
13
+ * directly to `<Controls>`.
14
+ *
15
+ * Use this for the common case where only the built-in controls (zoom,
16
+ * fullscreen, my location, map style) are needed, with no custom additions.
17
+ * For custom control stacks, call `useDefaultControls` + `useControls` (or
18
+ * `composeControlAreas`) and pass the result to `<Controls>` directly.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * import { useMap, DefaultControls } from "@trackunit/react-map";
23
+ * import { googleMapsAdapter } from "@trackunit/react-map-adapter-google";
24
+ *
25
+ * const MyMap = () => {
26
+ * const [Map, api] = useMap(googleMapsAdapter({ apiKey }));
27
+ *
28
+ * return (
29
+ * <Map>
30
+ * <DefaultControls api={api} />
31
+ * </Map>
32
+ * );
33
+ * };
34
+ * ```
35
+ */
36
+ export declare const DefaultControls: ({ api, options, className }: DefaultControlsProps) => import("react/jsx-runtime").JSX.Element;
37
+ export {};
@@ -0,0 +1,24 @@
1
+ import { type ControlStackItem } from "./defineControlStack";
2
+ import type { CategoryKey, ControlsConfig } from "./types";
3
+ /**
4
+ * Input for `composeControlAreas`: a partial record of per-area control stacks.
5
+ * Omitted areas default to an empty controls array.
6
+ * `undefined` entries in each area array are filtered out by `defineControlStack`.
7
+ */
8
+ export type ControlAreasInput = Partial<Record<CategoryKey, ReadonlyArray<ControlStackItem>>>;
9
+ /**
10
+ * Pure function that builds a `ControlsConfig` from per-area control stacks.
11
+ *
12
+ * Each area in `areas` is passed through `defineControlStack` (which filters
13
+ * `undefined` entries and rejects duplicate ids). Omitted areas default to
14
+ * `{ controls: [] }`.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const controls = composeControlAreas({
19
+ * navigation: [builtIn.navigation.zoom, builtIn.navigation.fullscreen],
20
+ * settings: [builtIn.settings.mapStyle],
21
+ * });
22
+ * ```
23
+ */
24
+ export declare const composeControlAreas: (areas: ControlAreasInput) => ControlsConfig;
@@ -315,6 +315,10 @@ export type SettingsConfig = Readonly<{
315
315
  export type StatisticsConfig = Readonly<{
316
316
  controls: ReadonlyArray<ControlConfig>;
317
317
  }>;
318
+ /** Tools area - array of controls */
319
+ export type ToolsConfig = Readonly<{
320
+ controls: ReadonlyArray<ControlConfig>;
321
+ }>;
318
322
  /** Complete controls configuration */
319
323
  export type ControlsConfig = Readonly<{
320
324
  /** Navigation controls: zoom, fullscreen, compass (future), reset view (future) */
@@ -322,12 +326,12 @@ export type ControlsConfig = Readonly<{
322
326
  /** Settings: layer toggles, layer settings (future), map style (future) */
323
327
  settings: SettingsConfig;
324
328
  /** Tools: drawing, measurement, selection (future) */
325
- tools: null;
329
+ tools: ToolsConfig;
326
330
  /** Statistics: data summaries, counts */
327
331
  statistics: StatisticsConfig;
328
332
  }>;
329
333
  /**
330
- * Built-in navigation controls returned by `useControlsConfig`.
334
+ * Built-in navigation controls returned by `useDefaultControls`.
331
335
  *
332
336
  * Consumers composing custom control stacks can use these named handles instead
333
337
  * of re-identifying built-ins by their string ids after the controls are built.
@@ -337,11 +341,11 @@ export interface BuiltInNavigationConfig extends NavigationConfig {
337
341
  readonly fullscreen: ToggleControlConfig | undefined;
338
342
  readonly myLocation: ButtonControlConfig | undefined;
339
343
  }
340
- /** Built-in settings controls returned by `useControlsConfig`. */
344
+ /** Built-in settings controls returned by `useDefaultControls`. */
341
345
  export interface BuiltInSettingsConfig extends SettingsConfig {
342
346
  readonly mapStyle: MenuControlConfig | undefined;
343
347
  }
344
- /** Controls config with named handles for the controls built by `useControlsConfig`. */
348
+ /** Controls config with named handles for the controls built by `useDefaultControls`. */
345
349
  export interface BuiltInControlsConfig extends ControlsConfig {
346
350
  readonly navigation: BuiltInNavigationConfig;
347
351
  readonly settings: BuiltInSettingsConfig;
@@ -370,26 +374,14 @@ export type ResponsiveMode = "full" | "categorized" | "collapsed";
370
374
  /** The four semantic control areas used for categorization and section headers */
371
375
  export type CategoryKey = "navigation" | "settings" | "tools" | "statistics";
372
376
  /**
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
377
+ * Per-area prepend/append modifiers for `useControls`.
378
+ *
379
+ * Each area key accepts an optional `prepend` and/or `append` array of
380
+ * `ControlConfig | undefined` items (undefined entries are filtered out by
381
+ * `defineControlStack`). Omitted areas are left untouched.
391
382
  */
392
- export type UseMapOptions = Readonly<{
393
- controls?: ControlsOptions;
394
- }>;
383
+ export type UseControlsAreas = Partial<Record<CategoryKey, Readonly<{
384
+ prepend?: ReadonlyArray<ControlConfig | undefined>;
385
+ append?: ReadonlyArray<ControlConfig | undefined>;
386
+ }>>>;
395
387
  export {};
@@ -1,21 +1,23 @@
1
- import { collapseControls } from "./collapseControls";
1
+ import { composeControlAreas } from "./composeControlAreas";
2
2
  import { defineControlStack } from "./defineControlStack";
3
3
  export type ControlStackHelpers = Readonly<{
4
4
  defineControlStack: typeof defineControlStack;
5
- collapseControls: typeof collapseControls;
5
+ composeControlAreas: typeof composeControlAreas;
6
6
  }>;
7
7
  /**
8
- * Build-your-own hook: stable references to control composition/layout helpers.
8
+ * Build-your-own hook: stable references to control composition helpers.
9
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`.
10
+ * Returns `defineControlStack` and `composeControlAreas` for consumers building
11
+ * custom control layouts without duplicating the stack-ordering logic already
12
+ * used by `Controls`.
13
13
  *
14
14
  * @example
15
15
  * ```tsx
16
- * const { defineControlStack, collapseControls } = useControlStack();
17
- * const controls = defineControlStack([myControl, undefined, otherControl]);
18
- * const collapsed = collapseControls(config, responsiveMode, metadata);
16
+ * const { defineControlStack, composeControlAreas } = useControlStack();
17
+ * const controls = composeControlAreas({
18
+ * navigation: [builtIn.navigation.zoom, builtIn.navigation.fullscreen],
19
+ * settings: [builtIn.settings.mapStyle],
20
+ * });
19
21
  * ```
20
22
  */
21
23
  export declare const useControlStack: () => ControlStackHelpers;
@@ -0,0 +1,20 @@
1
+ import type { ControlsConfig, UseControlsAreas } from "./types";
2
+ /**
3
+ * Merges per-area `prepend`/`append` modifier lists into a base `ControlsConfig`.
4
+ *
5
+ * Memoizes internally — stable references are returned when neither `base` nor
6
+ * `areas` has changed. Modifiers are applied via `defineControlStack`, which
7
+ * filters `undefined` entries and rejects duplicate control ids.
8
+ *
9
+ * When `areas` is omitted the `base` reference is returned as-is.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const builtIn = useDefaultControls(api);
14
+ * const controls = useControls(builtIn, {
15
+ * navigation: { append: [layerNavControl] },
16
+ * settings: { prepend: [layerSettingsControl] },
17
+ * });
18
+ * ```
19
+ */
20
+ export declare const useControls: (base: ControlsConfig, areas?: UseControlsAreas) => ControlsConfig;
@@ -0,0 +1,62 @@
1
+ import type { AdapterConfig } from "@trackunit/react-map-adapter-shared";
2
+ import type { ContainerRefHolder, MapActions, MapStatus } from "../core/types";
3
+ import type { BuiltInControlsConfig } from "./types";
4
+ /**
5
+ * Options for `useDefaultControls`.
6
+ * Each control can be individually disabled. Omitting the options object (or any
7
+ * sub-key) means all controls are enabled.
8
+ */
9
+ export type UseDefaultControlsOptions = Readonly<{
10
+ navigation?: Readonly<{
11
+ zoom?: Readonly<{
12
+ enabled?: boolean;
13
+ }>;
14
+ fullscreen?: Readonly<{
15
+ enabled?: boolean;
16
+ }>;
17
+ myLocation?: Readonly<{
18
+ enabled?: boolean;
19
+ }>;
20
+ }>;
21
+ settings?: Readonly<{
22
+ mapStyle?: Readonly<{
23
+ enabled?: boolean;
24
+ }>;
25
+ }>;
26
+ }>;
27
+ /**
28
+ * Minimal slice of `MapApi` consumed by `useDefaultControls`.
29
+ * Using a structural sub-type avoids a direct dependency on the full MapApi.
30
+ */
31
+ type DefaultControlsApi = Readonly<{
32
+ state: MapStatus;
33
+ actions: MapActions;
34
+ adapterConfig: AdapterConfig;
35
+ containerRef: ContainerRefHolder;
36
+ }>;
37
+ /**
38
+ * Builds the default built-in controls configuration (zoom, fullscreen, my
39
+ * location, map style) from the map API.
40
+ *
41
+ * Replaces `useControlsConfig` with a cleaner, flat options structure. Each
42
+ * control can be disabled individually via `options`. Omitting `options`
43
+ * enables all controls.
44
+ *
45
+ * Returns a `BuiltInControlsConfig` — a `ControlsConfig` enriched with named
46
+ * handles for each built-in control so consumers can reference them without
47
+ * searching by id.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * const builtIn = useDefaultControls(api);
52
+ * return <Controls controls={builtIn} api={api} />;
53
+ * ```
54
+ * @example Disable specific controls
55
+ * ```tsx
56
+ * const builtIn = useDefaultControls(api, {
57
+ * navigation: { myLocation: { enabled: false } },
58
+ * });
59
+ * ```
60
+ */
61
+ export declare const useDefaultControls: (api: DefaultControlsApi, options?: UseDefaultControlsOptions) => BuiltInControlsConfig;
62
+ export {};
@@ -3,7 +3,6 @@ export type { CameraState, ContainerRefHolder, FitBoundsOptions, GeoJsonBbox, Ge
3
3
  import type { AdapterConfig, CameraState, ContainerRefHolder, FitBoundsOptions, GeoJsonBbox, GeoJsonPosition, MapComponentProps, MapEvent, MapEventHandler, MapStatus, MapTheme, MapType } from "@trackunit/react-map-adapter-shared";
4
4
  import type { ComponentType } from "react";
5
5
  import type { MapAnnotationStore } from "../annotations/mapAnnotations";
6
- import type { ControlsConfig, UseMapOptions } from "../controls/types";
7
6
  import type { PanelStore } from "../panel/store/panels";
8
7
  import type { MapLoadingIndicatorStore } from "./loadingIndicator";
9
8
  /**
@@ -131,11 +130,6 @@ export type MapApi = Readonly<{
131
130
  * ```
132
131
  */
133
132
  on: <TEventType extends MapEvent["type"]>(event: TEventType, handler: MapEventHandler<TEventType>) => () => void;
134
- /**
135
- * Options passed to useMap for controls configuration.
136
- * Used by the Controls component to build the controls config.
137
- */
138
- options?: UseMapOptions;
139
133
  /**
140
134
  * Stabilized adapter configuration used to create this map instance.
141
135
  * Use `adapterConfig.derive(overrides)` to create variant configs
@@ -174,14 +168,6 @@ export type MapApi = Readonly<{
174
168
  * re-renders.
175
169
  */
176
170
  panels: PanelStore;
177
- /**
178
- * Controls configuration - pure data describing what controls are enabled.
179
- * Used by the Controls component to determine what to render.
180
- *
181
- * @deprecated Use `api.options` for `useMap` options, or pass `controlsConfig`
182
- * directly to `<Controls />` for custom controls.
183
- */
184
- controlsConfig?: ControlsConfig;
185
171
  }>;
186
172
  /**
187
173
  * Result returned by useMap hook as a tuple.
@@ -1,5 +1,4 @@
1
1
  import { type AdapterConfig } from "@trackunit/react-map-adapter-shared";
2
- import type { UseMapOptions } from "../controls/types";
3
2
  import { type UseMapReturn } from "./types";
4
3
  /**
5
4
  * useMap hook - the main entry point for using the map
@@ -15,7 +14,6 @@ import { type UseMapReturn } from "./types";
15
14
  * All action functions and the Map component reference are stable across re-renders.
16
15
  *
17
16
  * @param adapterConfig - Adapter configuration from an adapter factory (e.g., googleMapsAdapter)
18
- * @param options - Optional configuration for controls and other features
19
17
  * @returns Tuple of [Map component, API object]
20
18
  * @example Basic usage
21
19
  * ```tsx
@@ -54,4 +52,4 @@ import { type UseMapReturn } from "./types";
54
52
  * };
55
53
  * ```
56
54
  */
57
- export declare const useMap: <TConfig extends Record<string, unknown>>(adapterConfig: AdapterConfig<TConfig>, options?: UseMapOptions) => UseMapReturn;
55
+ export declare const useMap: <TConfig extends Record<string, unknown>>(adapterConfig: AdapterConfig<TConfig>) => UseMapReturn;
package/src/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type { CameraState, ContainerRefHolder, FitBoundsOptions, GeoJsonBbox, GeoJsonPosition, InitialViewport, MapActions, MapApi, MapAppearance, MapComponentProps, MapEvent, MapEventHandler, MapEventOfType, MapState, MapStatus, MapTheme, MapType, UseMapReturn, } from "./core/types";
2
2
  export { DEFAULT_MAP_APPEARANCE, INITIAL_CAMERA_STATE, INITIAL_MAP_STATE, INITIAL_MAP_STATUS, mapAppearanceSchema, mapThemeSchema, mapTypeSchema, } from "./core/types";
3
- export type { AvailableSpace, BooleanControlConfig, BuiltInControlsConfig, BuiltInNavigationConfig, BuiltInSettingsConfig, ButtonControlConfig, CategoryKey, CheckboxControlConfig, Compactness, ControlConfig, ControlsConfig, ControlsOptions, CustomControlConfig, CustomControlRenderContext, IconName, MenuControlConfig, MenuItemConfig, NavigationConfig, OverflowBehavior, Placement, RadioGroupControlConfig, RenderContext, ResolvedControlProps, ResolvedControlPropsBase, ResponsiveMode, SearchControlConfig, SelectControlConfig, SeparatorItemConfig, SettingsConfig, StatisticsConfig, StepperControlConfig, ToggleControlConfig, ToggleGroupControlConfig, ToggleGroupOption, UseMapOptions, } from "./controls/types";
3
+ export type { AvailableSpace, BooleanControlConfig, BuiltInControlsConfig, BuiltInNavigationConfig, BuiltInSettingsConfig, ButtonControlConfig, CategoryKey, CheckboxControlConfig, Compactness, ControlConfig, ControlsConfig, CustomControlConfig, CustomControlRenderContext, IconName, MenuControlConfig, MenuItemConfig, NavigationConfig, OverflowBehavior, Placement, RadioGroupControlConfig, RenderContext, ResolvedControlProps, ResolvedControlPropsBase, ResponsiveMode, SearchControlConfig, SelectControlConfig, SeparatorItemConfig, SettingsConfig, StatisticsConfig, StepperControlConfig, ToggleControlConfig, ToggleGroupControlConfig, ToggleGroupOption, ToolsConfig, } from "./controls/types";
4
4
  export { defineAdapter } from "@trackunit/react-map-adapter-shared";
5
5
  export type { AdapterConfig, AdapterConfigBase, AdapterInstance, AdapterRendererProps, SafeAreaInsets, } from "@trackunit/react-map-adapter-shared";
6
6
  export { useCameraIdle } from "./core/useCameraIdle";
@@ -9,9 +9,13 @@ export { useMap } from "./core/useMap";
9
9
  export { useMapKeyboardNavigation, type MapKeyboardNavigationApi } from "./core/useMapKeyboardNavigation";
10
10
  export { usePreviewMap, type UsePreviewMapReturn } from "./core/usePreviewMap";
11
11
  export { MapLoadingState } from "./core/MapLoadingState";
12
+ export type { ControlAreasInput } from "./controls/composeControlAreas";
12
13
  export { Controls } from "./controls/Controls";
14
+ export { DefaultControls } from "./controls/DefaultControls";
13
15
  export type { ControlStackItem } from "./controls/defineControlStack";
14
- export { useControlsConfig } from "./controls/useControlsConfig";
16
+ export type { UseControlsAreas } from "./controls/types";
17
+ export { useControls } from "./controls/useControls";
18
+ export { useDefaultControls, type UseDefaultControlsOptions } from "./controls/useDefaultControls";
15
19
  export type { AppearanceAction, AppearanceOption, AppearanceOptions, MapAppearanceApi, PersistedAppearance, UseMapAppearanceControlsParams, } from "./appearance/appearanceTypes";
16
20
  export { useMapAppearanceControls } from "./appearance/useMapAppearanceControls";
17
21
  export type { ControlMiddleware, MiddlewareContext } from "./controls/renderingRules";
@@ -23,16 +27,16 @@ export { computeMarkerDomPortalZIndex } from "./layers/types";
23
27
  export { ANCHOR_SELECTOR, HIT_SURFACE_SELECTOR } from "@trackunit/react-map-adapter-shared";
24
28
  export { ClusterMarker, type ClusterMarkerProps, type ClusterMarkerStickInput, type ClusterSegment, } from "./clusters/ClusterMarker";
25
29
  export { ClusterStick, type ClusterStickProps } from "./clusters/ClusterStick";
26
- export { useDirectionIndicator, type DirectionIndicatorDisplay, } from "./markers/geometry/useDirectionIndicator";
30
+ export { useDirectionIndicator, type DirectionIndicatorDisplay } from "./markers/geometry/useDirectionIndicator";
27
31
  export { MapMarker, type MapMarkerProps } from "./markers/MapMarker";
28
32
  export { MapMarkerIcon } from "./markers/MapMarkerIcon";
29
33
  export type { MapMarkerDomPortalStackingByMarkerState, MapMarkerDomPortalStackingByPromotion, MapMarkerDomPortalStackingParams, } from "./markers/model/mapMarkerDomPortalStacking";
30
34
  export type { ClusterStickState, MarkerDomSize, MarkerForm, MarkerSizeDimensions, MarkerState, StickDistanceMode, StickPositioning, } from "./markers/model/markerDomTypes";
31
35
  export type { MarkerRenderStateInput } from "./markers/model/markerResolvers";
32
- export { MARKER_PILL_CONTENT_LAYOUT_SIZE, MARKER_SIZE_MAP, } from "./markers/model/markerSizeMap";
36
+ export { MARKER_PILL_CONTENT_LAYOUT_SIZE, MARKER_SIZE_MAP } from "./markers/model/markerSizeMap";
33
37
  export { MARKER_TUNING } from "./markers/model/markerTuningParams";
34
38
  export { cvaMapMarker, cvaMarkerIndicator } from "./markers/shared/mapMarkerVariants";
35
- export { MARKER_DARK_PILL, MARKER_LIGHT_PILL, } from "./markers/shared/markerColors";
39
+ export { MARKER_DARK_PILL, MARKER_LIGHT_PILL } from "./markers/shared/markerColors";
36
40
  export type { MarkerColorConfig, MarkerColorCssVars, ResolvedMarkerColors } from "./markers/shared/markerColors";
37
41
  export { type HoverPanelPreloadInitiator, type PanelPreloadInitiator, type PanelPreloadInitiatorType, type ProximityPanelPreloadInitiator, } from "./panel/preload/preloadInitiators";
38
42
  export { usePanelPreload, type UsePanelPreloadOptions } from "./panel/preload/usePanelPreload";
@@ -40,7 +44,7 @@ export { type PanelStore } from "./panel/store/panels";
40
44
  export { usePanel, type UsePanelOptions } from "./panel/usePanel";
41
45
  export { type AutoPanContext, type AutoPanResult } from "./panel/utils/autoPan";
42
46
  export type { DecorationAnchor, EdgeSide, ShapeDecoration } from "./layers/useShapes/shapeDecorations";
43
- export { type AnnotationContext, type ShapeLabelPolicy, } from "./layers/useShapes/shapeLabelPolicy";
47
+ export { type AnnotationContext, type ShapeLabelPolicy } from "./layers/useShapes/shapeLabelPolicy";
44
48
  export type { ResolveShapeLabel, ShapeLabelResolution, ShapeLabelResolutionContext, } from "./layers/useShapes/shapeLabelResolution";
45
49
  export { useImageOverlay, type UseImageOverlayOptions, type UseImageOverlayReturn, } from "./layers/image-overlay/useImageOverlay";
46
50
  export { buildExpandedIds, useExpandedIds, type MapFocus, type MapFocusTier, type MapFocusTierDisplay, } from "./layers/mapFocus";
@@ -52,18 +56,18 @@ export { useMarkers, type UseMarkersOptions, type UseMarkersReturn } from "./lay
52
56
  export { useShapes, type UseShapesOptions, type UseShapesReturn } from "./layers/useShapes/useShapes";
53
57
  export { Layers } from "./layers/Layers";
54
58
  export { type MapLoadingIndicatorStore } from "./core/loadingIndicator";
55
- export { type MapAnnotationDescriptor, type MapAnnotationStore, } from "./annotations/mapAnnotations";
59
+ export { type MapAnnotationDescriptor, type MapAnnotationStore } from "./annotations/mapAnnotations";
56
60
  export { useMapAnnotation } from "./annotations/useMapAnnotation";
57
61
  export { useMapAnnotations } from "./annotations/useMapAnnotations";
58
62
  export { ShapeAnnotationLabel } from "./layers/useShapes/ShapeAnnotationLabel";
59
63
  export { useViewportContext, type ViewportContext } from "./layers/internal/useViewportContext";
60
64
  export type { AnchoredContentConfig, EntityInteractionEvent, EntityInteractionHandler, ImageOverlayConfig as ImageOverlaySourceConfig, InteractiveMarkerConfig, LayerPort, LayerSnapshot, MapLayer, MarkerSourceConfig, RouteSourceConfig, ShapeInteractionState, ShapeSourceConfig, } from "@trackunit/react-map-adapter-shared";
61
- export { useAdaptiveMarkerHelpers, type AdaptiveMarkerHelpers } from "./layers/useMarkers/useAdaptiveMarkerHelpers";
62
- export { useFitFeatureBounds, type FitFeatureBoundsHelpers } from "./layers/internal/useFitFeatureBounds";
63
- export { useAutoPanResolver, type AutoPanResolverHelpers } from "./panel/utils/useAutoPanResolver";
64
65
  export { useClusterCountFormat, type ClusterCountFormatHelpers } from "./clusters/useClusterCountFormat";
65
66
  export { useControlStack, type ControlStackHelpers } from "./controls/useControlStack";
66
- export { useMarkerColors, type MarkerColorHelpers } from "./markers/shared/useMarkerColors";
67
- export { useMarkerStateResolvers, type MarkerStateResolvers } from "./markers/model/useMarkerStateResolvers";
67
+ export { useFitFeatureBounds, type FitFeatureBoundsHelpers } from "./layers/internal/useFitFeatureBounds";
68
+ export { useAdaptiveMarkerHelpers, type AdaptiveMarkerHelpers } from "./layers/useMarkers/useAdaptiveMarkerHelpers";
68
69
  export { useShapeLabelHelpers, type ShapeLabelHelpers } from "./layers/useShapes/useShapeLabelHelpers";
70
+ export { useMarkerStateResolvers, type MarkerStateResolvers } from "./markers/model/useMarkerStateResolvers";
71
+ export { useMarkerColors, type MarkerColorHelpers } from "./markers/shared/useMarkerColors";
72
+ export { useAutoPanResolver, type AutoPanResolverHelpers } from "./panel/utils/useAutoPanResolver";
69
73
  export { mockMapApi } from "./testing/mockMapApi";
@@ -1,5 +1,5 @@
1
1
  import { type GeoJsonBbox } from "@trackunit/geo-json-utils";
2
- import type { ControlConfig } from "../../controls/types";
2
+ import type { CategoryKey, ControlConfig } from "../../controls/types";
3
3
  import type { FitParticipation, ImageOverlayHandle } from "../types";
4
4
  export type UseImageOverlayOptions = Readonly<{
5
5
  /** Unique ID for this layer */
@@ -12,8 +12,11 @@ export type UseImageOverlayOptions = Readonly<{
12
12
  imageBounds: GeoJsonBbox;
13
13
  /** Opacity from 0 to 1. Default: 1 */
14
14
  opacity?: number;
15
- /** Optional controls to contribute to the map UI */
16
- controls?: ReadonlyArray<ControlConfig>;
15
+ /**
16
+ * Controls to contribute to the map UI, keyed by semantic area.
17
+ * Omit entirely (or omit a key) to contribute nothing to that area.
18
+ */
19
+ controls?: Partial<Record<CategoryKey, ReadonlyArray<ControlConfig>>>;
17
20
  /** Whether the layer is currently loading its initial data. Omit for static (non-loading) layers. */
18
21
  loading?: boolean;
19
22
  /** Controls whether this layer's bounds are included in fit-to-content operations. Default: `"all"` */
@@ -1,5 +1,5 @@
1
1
  import { type GeoJsonPosition } from "@trackunit/geo-json-utils";
2
- import type { ControlConfig } from "../../controls/types";
2
+ import type { CategoryKey, ControlConfig } from "../../controls/types";
3
3
  import type { FitParticipation, RouteLayerHandle, RouteStyle } from "../types";
4
4
  export type UseRouteOptions = Readonly<{
5
5
  /** Unique ID for this layer */
@@ -12,8 +12,11 @@ export type UseRouteOptions = Readonly<{
12
12
  style: RouteStyle;
13
13
  /** Whether the route is interactive (clickable/hoverable). Default: true */
14
14
  interactive?: boolean;
15
- /** Optional controls to contribute to the map UI */
16
- controls?: ReadonlyArray<ControlConfig>;
15
+ /**
16
+ * Controls to contribute to the map UI, keyed by semantic area.
17
+ * Omit entirely (or omit a key) to contribute nothing to that area.
18
+ */
19
+ controls?: Partial<Record<CategoryKey, ReadonlyArray<ControlConfig>>>;
17
20
  /** Whether the layer is currently loading its initial data. Omit for static (non-loading) layers. */
18
21
  loading?: boolean;
19
22
  /** Controls whether this layer's bounds are included in fit-to-content operations. Default: `"all"` */
@@ -1,6 +1,6 @@
1
1
  import type { GeoJsonBbox, GeoJsonFeature, GeoJsonFeatureCollection, GeoJsonPosition } from "@trackunit/geo-json-utils";
2
2
  import type { AdaptiveMarkerResolution, ClusterConfig, ClusterRenderConfig, RenderConfig, RouteStyle, ShapeInteractiveMode, ShapeStyle } from "@trackunit/react-map-adapter-shared";
3
- import type { ControlConfig } from "../controls/types";
3
+ import type { CategoryKey, ControlConfig } from "../controls/types";
4
4
  import type { ShapeDecoration } from "./useShapes/shapeDecorations";
5
5
  import type { ShapeLabelResolutionContext } from "./useShapes/shapeLabelResolution";
6
6
  export type { AdaptiveMarkerResolution, AdaptiveRenderConfig, AdaptiveRenderState, AdaptiveResolutionContext, CircleSymbolDescriptor, ClientClusterConfig, ClusterConfig, ClusterDomRenderConfig, ClusterInfo, ClusterRenderConfig, ClusterRenderState, ClusterSymbolRenderConfig, ClusterSymbolStyle, CommonRenderState, DomPortalStackingInput, DomPortalStackingResolver, DomPortalStackingResult, DomRenderConfig, DomRenderState, GeoJsonFeature, GeoJsonFeatureCollection, GeoJsonGeometry, MarkerAnchor, MarkerDomPortalStackGeometry, MarkerDomPortalStackPhase, PixelOffset, RenderConfig, RenderMedium, ResolutionContext, RouteStyle, ServerClusterConfig, ShapeInteractiveMode, ShapeStyle, ShapeStyleOverrides, SymbolDescriptor, SymbolRenderConfig, SymbolRenderState, } from "@trackunit/react-map-adapter-shared";
@@ -35,8 +35,12 @@ export type LayerMeta = Readonly<{
35
35
  getBounds: () => GeoJsonBbox | null;
36
36
  /** Summary counts -- always cheap (derived from .length). Semantics depend on layer type. */
37
37
  counts: Readonly<Record<string, number>>;
38
- /** Controls this layer wants to contribute to the map UI */
39
- controls: ReadonlyArray<ControlConfig>;
38
+ /**
39
+ * Controls this layer wants to contribute to the map UI, keyed by semantic area.
40
+ * Each key maps to an array of controls for that area (navigation, settings, tools, statistics).
41
+ * Omit a key (or provide an empty array) to contribute nothing to that area.
42
+ */
43
+ controls: Readonly<Partial<Record<CategoryKey, ReadonlyArray<ControlConfig>>>>;
40
44
  /**
41
45
  * Controls whether this layer's bounds are included in fit-to-content operations.
42
46
  * Default: `"all"`.
@@ -1,6 +1,6 @@
1
1
  import type { GeoJsonBbox } from "@trackunit/geo-json-utils";
2
2
  import { type Entity, type MapInteractionState } from "@trackunit/react-map-adapter-shared";
3
- import type { ControlConfig } from "../controls/types";
3
+ import type { CategoryKey, ControlConfig } from "../controls/types";
4
4
  import type { MapApi } from "../core/types";
5
5
  import type { LayerHandle } from "./types";
6
6
  /**
@@ -24,8 +24,11 @@ export type UseLayersReturn = Readonly<{
24
24
  loading: boolean;
25
25
  /** Resolves when ALL layers have their initial data */
26
26
  ready: Promise<void>;
27
- /** Aggregated controls from all layers */
28
- controls: ReadonlyArray<ControlConfig>;
27
+ /**
28
+ * Aggregated controls from all layers, keyed by semantic area.
29
+ * All four CategoryKey areas are always present (empty arrays for areas with no controls).
30
+ */
31
+ controls: Readonly<Record<CategoryKey, ReadonlyArray<ControlConfig>>>;
29
32
  /** Layer handles (passed to Layers component for rendering) */
30
33
  handles: ReadonlyArray<LayerHandle>;
31
34
  }>;
@@ -1,5 +1,5 @@
1
1
  import { type GeoJsonPosition } from "@trackunit/geo-json-utils";
2
- import type { ControlConfig } from "../../controls/types";
2
+ import type { CategoryKey, ControlConfig } from "../../controls/types";
3
3
  import type { ClusterConfig, ClusterInfo, ClusterRenderConfig, FitParticipation, MarkerLayerHandle, RenderConfig, ResolutionContext } from "../types";
4
4
  import { type ViewportResolutionContext } from "./resolveServerClusters";
5
5
  /**
@@ -38,8 +38,11 @@ export type UseMarkersOptions<TItem, TCluster = ClusterInfo> = Readonly<{
38
38
  * `data` (DOM mode only — symbol mode receives `memberItems: null`).
39
39
  */
40
40
  clusterRender?: ClusterRenderConfig<TCluster, TItem>;
41
- /** Optional controls to contribute to the map UI */
42
- controls?: ReadonlyArray<ControlConfig>;
41
+ /**
42
+ * Controls to contribute to the map UI, keyed by semantic area.
43
+ * Omit entirely (or omit a key) to contribute nothing to that area.
44
+ */
45
+ controls?: Partial<Record<CategoryKey, ReadonlyArray<ControlConfig>>>;
43
46
  /** Whether the layer is currently loading its initial data. Omit for static (non-loading) layers. */
44
47
  loading?: boolean;
45
48
  /** Controls whether this layer's bounds are included in fit-to-content operations. Default: `"all"` */
@@ -1,5 +1,5 @@
1
1
  import { type GeoJsonFeature, type GeoJsonFeatureCollection } from "@trackunit/geo-json-utils";
2
- import type { ControlConfig } from "../../controls/types";
2
+ import type { CategoryKey, ControlConfig } from "../../controls/types";
3
3
  import type { FitParticipation, ShapeInteractiveMode, ShapeLayerHandle, ShapeStyle } from "../types";
4
4
  import type { ShapeDecoration } from "./shapeDecorations";
5
5
  import type { ShapeLabelResolutionContext } from "./shapeLabelResolution";
@@ -14,8 +14,11 @@ export type UseShapesOptions = Readonly<{
14
14
  resolveStyle: (feature: GeoJsonFeature, ctx?: ShapeLabelResolutionContext) => ShapeStyle;
15
15
  /** Which parts of the shape respond to interaction. Default: `"stroke"` */
16
16
  interactive?: ShapeInteractiveMode;
17
- /** Optional controls to contribute to the map UI */
18
- controls?: ReadonlyArray<ControlConfig>;
17
+ /**
18
+ * Controls to contribute to the map UI, keyed by semantic area.
19
+ * Omit entirely (or omit a key) to contribute nothing to that area.
20
+ */
21
+ controls?: Partial<Record<CategoryKey, ReadonlyArray<ControlConfig>>>;
19
22
  /**
20
23
  * Produce custom decorations for each feature. Called per-feature during the
21
24
  * decoration rendering pass. These are merged with auto-generated decorations
@@ -1,27 +0,0 @@
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 {};