SPB Git forge

spb/ka-maps

Public
6commits 1branches 0releases
448.0 KBsize
maindefault branch
29 days agolast push
TypeScript 87.7% CSS 12.3%
3.3 KB · 117 lines tsx
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Groupe Ka / Ka Maps5 *6 * <KaSpotlightMap> — la carte « fiche » : une seule propriété, caméra 3D7 * serrée sur l'adresse, et le bâtiment concerné mis en évidence (empreinte8 * 3D du featureset « buildings » de Mapbox Standard, coloré via9 * `buildingColor`). Fond réaliste par défaut (pleine couleur, repères 3D).10 * Gestes coopératifs : la fiche reste défilable au-dessus de la carte.11 */1213import { useEffect, useRef, type CSSProperties, type ReactElement, type ReactNode } from "react";14import type { KaBasemapOptions } from "../styles/kaBaseStyle.js";15import type { KaMapMode, KaMapTheme } from "../theming/tokens.js";16import type { MapProperty } from "../types/index.js";17import { KaMapView, useKaMap } from "./KaMapView.js";1819/** Rouge signal — l'immeuble de la fiche ressort du premier coup d'œil. */20const DEFAULT_BUILDING_COLOR = "#e03131";2122const DEFAULT_ZOOM = 17.1;23const DEFAULT_PITCH = 62;2425function SpotlightBridge({26  property,27  color,28  zoom,29  pitch,30}: {31  property: MapProperty;32  color: string;33  zoom: number;34  pitch: number;35}) {36  const map = useKaMap();37  const firstRun = useRef(true);3839  useEffect(() => {40    if (!map) return;41    const at = { lng: property.longitude, lat: property.latitude };42    // Premier rendu : la caméra est déjà posée par le constructeur ;43    // navigations suivantes (fiche → fiche) : glissement doux.44    if (firstRun.current) firstRun.current = false;45    else map.flyTo(at, { zoom, pitch });46    map.focusBuilding(at, { color });47    return () => map.focusBuilding(null);48    // eslint-disable-next-line react-hooks/exhaustive-deps49  }, [map, property.id, property.longitude, property.latitude, color]);5051  return null;52}5354export interface KaSpotlightMapProps {55  theme: KaMapTheme;56  mapboxToken: string;57  /** La propriété de la fiche — pastille de prix + bâtiment en évidence. */58  property: MapProperty;59  mode?: KaMapMode;60  className?: string;61  style?: CSSProperties;62  /** Couleur de l'empreinte 3D du bâtiment. Défaut : rouge signal. */63  buildingColor?: string;64  zoom?: number;65  pitch?: number;66  /** Surcharge du fond (défaut spotlight : pleine couleur + repères 3D). */67  basemap?: KaBasemapOptions;68  children?: ReactNode;69}7071export function KaSpotlightMap({72  theme,73  mapboxToken,74  property,75  mode,76  className,77  style,78  buildingColor = DEFAULT_BUILDING_COLOR,79  zoom = DEFAULT_ZOOM,80  pitch = DEFAULT_PITCH,81  basemap,82  children,83}: KaSpotlightMapProps): ReactElement {84  const properties = useRef<MapProperty[]>([]);85  if (properties.current[0]?.id !== property.id) properties.current = [property];8687  return (88    <KaMapView89      theme={theme}90      mapboxToken={mapboxToken}91      mode={mode}92      className={className}93      style={style}94      properties={properties.current}95      center={{ lat: property.latitude, lng: property.longitude }}96      zoom={zoom}97      pitch={pitch}98      minZoom={11}99      cooperativeGestures100      basemap={{101        theme: "default",102        showLandmarks: true,103        colorBuildingSelect: buildingColor,104        ...basemap,105      }}106    >107      <SpotlightBridge108        property={property}109        color={buildingColor}110        zoom={zoom}111        pitch={pitch}112      />113      {children}114    </KaMapView>115  );116}117