@treasuryspatial/map-react 0.1.4 → 0.1.6

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.
@@ -7,6 +7,7 @@ export type MapModeCandidate = {
7
7
  feature: Feature<Polygon>;
8
8
  pointsLocal: number[][];
9
9
  stats: FootprintStats;
10
+ address?: string;
10
11
  };
11
12
  export type MapModeViewportHandle = {
12
13
  setLightingPreset: (presetKey: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"MapModeViewport.d.ts","sourceRoot":"","sources":["../src/MapModeViewport.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgF,MAAM,OAAO,CAAC;AAErG,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EASL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,qBAAqB,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,EAAE,MAAM,MAAM,CAAC;CACjC,CAAC;AAIF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAClF,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;AAEpF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,iBAAiB,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAMF,eAAO,MAAM,eAAe,oGAuU1B,CAAC"}
1
+ {"version":3,"file":"MapModeViewport.d.ts","sourceRoot":"","sources":["../src/MapModeViewport.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgF,MAAM,OAAO,CAAC;AAErG,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EASL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,qBAAqB,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,EAAE,MAAM,MAAM,CAAC;CACjC,CAAC;AAIF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;AAClF,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;AAEpF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,iBAAiB,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACzD,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAMF,eAAO,MAAM,eAAe,oGA8W1B,CAAC"}
@@ -14,12 +14,15 @@ export const MapModeViewport = forwardRef(function MapModeViewport({ active, geo
14
14
  const layerControllerRef = useRef(null);
15
15
  const threeLayerRef = useRef(null);
16
16
  const sceneRef = useRef(null);
17
+ const rendererRef = useRef(null);
17
18
  const opacityCacheRef = useRef(new Map());
18
19
  const lightingPresetRef = useRef(lightingPreset);
19
20
  const handlersBoundRef = useRef(false);
20
21
  const confirmedSelectionRef = useRef(confirmedSelection ?? null);
21
22
  const onCandidateSelectRef = useRef(onCandidateSelect);
22
23
  const onCandidateClearRef = useRef(onCandidateClear);
24
+ const lastGeocodeLabelRef = useRef(null);
25
+ const reverseGeocodeRequestRef = useRef(0);
23
26
  const [mapReady, setMapReady] = useState(false);
24
27
  const [mapError, setMapError] = useState('');
25
28
  useEffect(() => {
@@ -127,6 +130,7 @@ export const MapModeViewport = forwardRef(function MapModeViewport({ active, geo
127
130
  const center = event?.result?.center;
128
131
  if (!Array.isArray(center) || center.length < 2)
129
132
  return;
133
+ lastGeocodeLabelRef.current = event?.result?.place_name ?? event?.result?.text ?? null;
130
134
  map.easeTo({ center: [Number(center[0]), Number(center[1])], zoom: Math.max(map.getZoom(), 17) });
131
135
  });
132
136
  }
@@ -219,8 +223,11 @@ export const MapModeViewport = forwardRef(function MapModeViewport({ active, geo
219
223
  threeLayerRef.current = createMapThreeLayer({
220
224
  id: 'courtyard-mesh',
221
225
  zOffsetMeters: 0.05,
222
- onInit: (scene) => {
226
+ onInit: (scene, renderer) => {
223
227
  sceneRef.current = scene;
228
+ rendererRef.current = renderer;
229
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
230
+ renderer.toneMappingExposure = 1.2;
224
231
  (applyLightingPreset ?? defaultApplyLightingPreset)(scene, lightingPresetRef.current);
225
232
  },
226
233
  });
@@ -266,7 +273,9 @@ export const MapModeViewport = forwardRef(function MapModeViewport({ active, geo
266
273
  },
267
274
  };
268
275
  const stats = computeFootprintStats(pointsLocal);
269
- onCandidateSelectRef.current({ selection, feature: poly, pointsLocal, stats });
276
+ const initialAddress = lastGeocodeLabelRef.current ?? '';
277
+ onCandidateSelectRef.current({ selection, feature: poly, pointsLocal, stats, address: initialAddress });
278
+ void reverseGeocodeAddress(centroid, selection, poly, pointsLocal, stats, initialAddress);
270
279
  });
271
280
  map.on('click', (e) => {
272
281
  const features = map.queryRenderedFeatures(e.point, { layers: ['building-footprints-fill'] });
@@ -275,6 +284,33 @@ export const MapModeViewport = forwardRef(function MapModeViewport({ active, geo
275
284
  }
276
285
  });
277
286
  };
287
+ const reverseGeocodeAddress = async (center, selection, feature, pointsLocal, stats, initialAddress) => {
288
+ if (!accessToken)
289
+ return;
290
+ const requestId = ++reverseGeocodeRequestRef.current;
291
+ try {
292
+ const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${center.lng},${center.lat}.json?access_token=${accessToken}&types=address,place&limit=1`;
293
+ const res = await fetch(url);
294
+ if (!res.ok)
295
+ return;
296
+ const data = await res.json();
297
+ if (requestId !== reverseGeocodeRequestRef.current)
298
+ return;
299
+ const nextAddress = data?.features?.[0]?.place_name;
300
+ if (!nextAddress || nextAddress === initialAddress)
301
+ return;
302
+ onCandidateSelectRef.current({
303
+ selection,
304
+ feature,
305
+ pointsLocal,
306
+ stats,
307
+ address: nextAddress,
308
+ });
309
+ }
310
+ catch {
311
+ // ignore geocode errors
312
+ }
313
+ };
278
314
  return (_jsxs("div", { className: "absolute inset-0", children: [_jsx("div", { ref: containerRef, className: "w-full h-full" }), !accessToken && (_jsx("div", { className: "absolute inset-0 z-[2] flex items-center justify-center bg-black/70 text-xs text-white font-nunito", children: "Mapbox access token missing." })), mapError && (_jsx("div", { className: "absolute inset-0 z-[2] flex items-center justify-center bg-black/70 text-xs text-white font-nunito", children: mapError })), !mapReady && !mapError && accessToken && (_jsx("div", { className: "absolute inset-0 z-[2] flex items-center justify-center bg-black/60 text-xs text-white font-nunito", children: "loading map\u2026" }))] }));
279
315
  });
280
316
  function applyMaterialOverrides(group, settings) {
@@ -303,11 +339,14 @@ function applyMaterialOverrides(group, settings) {
303
339
  }
304
340
  mesh.material = new THREE.MeshStandardMaterial({
305
341
  color,
306
- roughness: 0.75,
342
+ roughness: 0.6,
307
343
  metalness: 0,
308
344
  side: THREE.DoubleSide,
309
345
  map: texture ?? null,
310
346
  });
347
+ mesh.material.polygonOffset = true;
348
+ mesh.material.polygonOffsetFactor = 1.0;
349
+ mesh.material.polygonOffsetUnits = 1.0;
311
350
  });
312
351
  }
313
352
  function defaultApplyLightingPreset(scene, _presetKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treasuryspatial/map-react",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "main": "./dist/index.js",