From ae081fdcfcf3e44a21fcc47c1da5c74de9ffc246 Mon Sep 17 00:00:00 2001 From: Roman Timashev Date: Tue, 16 Dec 2025 19:54:19 +0300 Subject: [PATCH 1/3] show/hide tile boundaries using spotlight --- src/components/SphereMap/map-body.tsx | 2 ++ src/components/Spotlight/index.tsx | 7 +++++++ src/sphere-hooks/useTileBoundaries.ts | 22 ++++++++++++++++++++++ src/store/actions.ts | 2 ++ src/store/index.ts | 2 ++ src/store/selectors.ts | 8 ++++++++ src/store/tile-boundaries.ts | 27 +++++++++++++++++++++++++++ 7 files changed, 70 insertions(+) create mode 100644 src/sphere-hooks/useTileBoundaries.ts create mode 100644 src/store/tile-boundaries.ts diff --git a/src/components/SphereMap/map-body.tsx b/src/components/SphereMap/map-body.tsx index f2dd7b7..4b90dfc 100644 --- a/src/components/SphereMap/map-body.tsx +++ b/src/components/SphereMap/map-body.tsx @@ -15,6 +15,7 @@ import { SphereSource } from "./SphereSource" import { SphereLayer } from "./SphereLayer" import Draw from "./Draw" import { createSelector } from "@reduxjs/toolkit" +import useTileBoundaries from "@/sphere-hooks/useTileBoundaries" const selectLayers = createSelector([selectors.draw.isDrawing, selectors.layer.items, selectors.layer.allIds], (drawing, items, allIds) => { @@ -52,6 +53,7 @@ export default function MapBody({ mapId }: MapBodyProps) { usePointerHover(mapId) useFeatureSelect(map) useFeatureProperties(map, 50) + useTileBoundaries(map) const drawing = useAppSelector(selectors.draw.isDrawing) const showAttribution = useAppSelector(selectShowAttribution) diff --git a/src/components/Spotlight/index.tsx b/src/components/Spotlight/index.tsx index 1d15a52..6c8d222 100644 --- a/src/components/Spotlight/index.tsx +++ b/src/components/Spotlight/index.tsx @@ -141,6 +141,13 @@ export const Spotlight: React.FC = ({ children, mapId }) => { }, icon: , }, + { + title: "Toggle Show Tile Boundaries", + description: "Toggle visibility of tile boundaries", + onTrigger: async () => { + dispatch(actions.tileBoundaries.toggle()) + }, + }, ]} searchIcon={} searchPlaceholder="Search..." diff --git a/src/sphere-hooks/useTileBoundaries.ts b/src/sphere-hooks/useTileBoundaries.ts new file mode 100644 index 0000000..dd7fafe --- /dev/null +++ b/src/sphere-hooks/useTileBoundaries.ts @@ -0,0 +1,22 @@ +import { MapRef } from "react-map-gl/maplibre" +import { useEffect } from "react" +import { useAppSelector } from "@/store/hooks" +import { selectors } from "@/store" + +export default function useTileBoundaries(ref: MapRef | undefined) { + const val = useAppSelector(selectors.tileBoundaries.view) + + useEffect(() => { + const map = ref?.getMap() + if (!map) { + return + } + const origin = map.showTileBoundaries + map.showTileBoundaries = val + return () => { + map.showTileBoundaries = origin + } + }, [ref, val]) + + return null +} diff --git a/src/store/actions.ts b/src/store/actions.ts index ae00bb7..f291964 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -1,4 +1,5 @@ import { projectionSlice } from "./projection" +import { tileBoundariesSlice } from "./tile-boundaries" import { mapStyleSlice } from "./mapStyle" import { skySlice } from "./sky" import { terrainSlice } from "./terrain" @@ -19,6 +20,7 @@ export const actions = { draw: drawActions, error: errorActions, projection: projectionSlice.actions, + tileBoundaries: tileBoundariesSlice.actions, mapStyle: mapStyleSlice.actions, sky: skySlice.actions, terrain: terrainSlice.actions, diff --git a/src/store/index.ts b/src/store/index.ts index 7d212f5..0ff875f 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,5 +1,6 @@ import { configureStore } from "@reduxjs/toolkit" import projection from "./projection" +import tileBoundaries from "./tile-boundaries" import mapStyle from "./mapStyle" import sky from "./sky" import terrain from "./terrain" @@ -21,6 +22,7 @@ export const store = configureStore({ draw, error, projection, + tileBoundaries, mapStyle, sky, terrain, diff --git a/src/store/selectors.ts b/src/store/selectors.ts index c8f4e43..5e2e4f7 100644 --- a/src/store/selectors.ts +++ b/src/store/selectors.ts @@ -6,6 +6,7 @@ import { drawSlice as draw } from "./draw" import { appSlice as app } from "./app" import { sourceSlice as source } from "./source" import { createSelector } from "@reduxjs/toolkit" +import { tileBoundariesSlice } from "./tile-boundaries" // Other code such as selectors can use the imported `RootState` type const selectProjection = (state: RootState) => { const drawing = draw.selectors.isDrawing(state) @@ -28,6 +29,10 @@ export const selectMapStyle = (state: RootState) => { return state.mapStyle.value } +const viewTileBoundaries = (state: RootState) => { + return state.tileBoundaries.value +} + const visibleIds = createSelector([layer.selectors.items, layer.selectors.allIds], (items, allIds) => allIds.filter(id => items[id].visible), ) @@ -48,4 +53,7 @@ export const selectors = { visibleIds, }, selection: selection.selectors, + tileBoundaries: { + view: viewTileBoundaries, + } } diff --git a/src/store/tile-boundaries.ts b/src/store/tile-boundaries.ts new file mode 100644 index 0000000..fe3f481 --- /dev/null +++ b/src/store/tile-boundaries.ts @@ -0,0 +1,27 @@ +import { createSlice } from "@reduxjs/toolkit" + +type TileBoundariesState = { + value: boolean +} + +const initialState: TileBoundariesState = { + value: false, +} + +export const tileBoundariesSlice = createSlice({ + name: "tileBoundaries", + initialState, + reducers: { + enable: state => { + state.value = true + }, + disable: state => { + state.value = false + }, + toggle: state => { + state.value = !state.value + }, + }, +}) + +export default tileBoundariesSlice.reducer From e440fdb1c77767c77631ca2c7fa854e4953ca7fc Mon Sep 17 00:00:00 2001 From: Roman Timashev Date: Tue, 16 Dec 2025 19:55:02 +0300 Subject: [PATCH 2/3] rename view to show --- src/sphere-hooks/useTileBoundaries.ts | 2 +- src/store/selectors.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sphere-hooks/useTileBoundaries.ts b/src/sphere-hooks/useTileBoundaries.ts index dd7fafe..37a8852 100644 --- a/src/sphere-hooks/useTileBoundaries.ts +++ b/src/sphere-hooks/useTileBoundaries.ts @@ -4,7 +4,7 @@ import { useAppSelector } from "@/store/hooks" import { selectors } from "@/store" export default function useTileBoundaries(ref: MapRef | undefined) { - const val = useAppSelector(selectors.tileBoundaries.view) + const val = useAppSelector(selectors.tileBoundaries.show) useEffect(() => { const map = ref?.getMap() diff --git a/src/store/selectors.ts b/src/store/selectors.ts index 5e2e4f7..3a72556 100644 --- a/src/store/selectors.ts +++ b/src/store/selectors.ts @@ -29,7 +29,7 @@ export const selectMapStyle = (state: RootState) => { return state.mapStyle.value } -const viewTileBoundaries = (state: RootState) => { +const showTileBoundaries = (state: RootState) => { return state.tileBoundaries.value } @@ -54,6 +54,6 @@ export const selectors = { }, selection: selection.selectors, tileBoundaries: { - view: viewTileBoundaries, + show: showTileBoundaries, } } From 58609ca6773f1dc28e197120c9c910e42e59d0ce Mon Sep 17 00:00:00 2001 From: Roman Timashev Date: Tue, 16 Dec 2025 19:57:38 +0300 Subject: [PATCH 3/3] add missing trailing comma --- src/store/selectors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/selectors.ts b/src/store/selectors.ts index 3a72556..c29f48b 100644 --- a/src/store/selectors.ts +++ b/src/store/selectors.ts @@ -55,5 +55,5 @@ export const selectors = { selection: selection.selectors, tileBoundaries: { show: showTileBoundaries, - } + }, }