fix(carto): show map UI before loading map styles
This commit is contained in:
parent
022fb04e2b
commit
2a42690388
7 changed files with 45 additions and 40 deletions
|
@ -57,7 +57,8 @@ module.exports = {
|
|||
'prettier/prettier': 'error',
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'error'
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'error'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
import React from 'react';
|
||||
import type { Point } from 'geojson';
|
||||
import { fire } from '@utils';
|
||||
|
||||
import ComboAdresseSearch from '../../ComboAdresseSearch';
|
||||
import { useFlyTo } from '../../shared/maplibre/hooks';
|
||||
|
||||
export function AddressInput() {
|
||||
const flyTo = useFlyTo();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
|
@ -17,9 +14,8 @@ export function AddressInput() {
|
|||
className="no-margin"
|
||||
placeholder="Rechercher une adresse : saisissez au moins 2 caractères"
|
||||
allowInputValues={false}
|
||||
onChange={(_, result) => {
|
||||
const geometry = result?.geometry as Point;
|
||||
flyTo(17, geometry.coordinates as [number, number]);
|
||||
onChange={(_, feature) => {
|
||||
fire(document, 'map:zoom', { feature });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,8 @@ import { useMapLibre } from '../../shared/maplibre/MapLibre';
|
|||
import {
|
||||
useFitBounds,
|
||||
useEvent,
|
||||
useMapEvent
|
||||
useMapEvent,
|
||||
useFlyTo
|
||||
} from '../../shared/maplibre/hooks';
|
||||
import {
|
||||
filterFeatureCollection,
|
||||
|
@ -116,6 +117,7 @@ function useExternalEvents(
|
|||
}
|
||||
) {
|
||||
const fitBounds = useFitBounds();
|
||||
const flyTo = useFlyTo();
|
||||
|
||||
const onFeatureFocus = useCallback(
|
||||
({ detail }) => {
|
||||
|
@ -132,6 +134,16 @@ function useExternalEvents(
|
|||
[featureCollection, fitBounds]
|
||||
);
|
||||
|
||||
const onZoomFocus = useCallback(
|
||||
({ detail }) => {
|
||||
const { feature } = detail;
|
||||
if (feature) {
|
||||
flyTo(17, feature.geometry.coordinates);
|
||||
}
|
||||
},
|
||||
[flyTo]
|
||||
);
|
||||
|
||||
const onFeatureCreate = useCallback(
|
||||
({ detail }) => {
|
||||
const { geometry, properties } = detail;
|
||||
|
@ -181,6 +193,7 @@ function useExternalEvents(
|
|||
useEvent('map:feature:create', onFeatureCreate);
|
||||
useEvent('map:feature:update', onFeatureUpdate);
|
||||
useEvent('map:feature:delete', onFeatureDelete);
|
||||
useEvent('map:zoom', onZoomFocus);
|
||||
}
|
||||
|
||||
const translations = [
|
||||
|
|
|
@ -5,11 +5,7 @@ import { PlusIcon, LocationMarkerIcon } from '@heroicons/react/outline';
|
|||
import { useId } from '@reach/auto-id';
|
||||
import CoordinateInput from 'react-coordinate-input';
|
||||
|
||||
import { useFlyTo } from '../../shared/maplibre/hooks';
|
||||
|
||||
export function PointInput() {
|
||||
const flyTo = useFlyTo();
|
||||
|
||||
const inputId = useId();
|
||||
const [value, setValue] = useState('');
|
||||
const [feature, setFeature] = useState<Feature | null>(null);
|
||||
|
@ -60,15 +56,13 @@ export function PointInput() {
|
|||
setValue(value);
|
||||
if (dd.length) {
|
||||
const coordinates: [number, number] = [dd[1], dd[0]];
|
||||
setFeature({
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates
|
||||
},
|
||||
const feature = {
|
||||
type: 'Feature' as const,
|
||||
geometry: { type: 'Point' as const, coordinates },
|
||||
properties: {}
|
||||
});
|
||||
flyTo(17, coordinates);
|
||||
};
|
||||
setFeature(feature);
|
||||
fire(document, 'map:zoom', { feature });
|
||||
} else {
|
||||
setFeature(null);
|
||||
}
|
||||
|
|
|
@ -46,19 +46,11 @@ export default function MapEditor({
|
|||
</p>
|
||||
</div>
|
||||
{error && <FlashMessage message={error} level="alert" fixed={true} />}
|
||||
<MapLibre
|
||||
layers={options.layers}
|
||||
header={
|
||||
<>
|
||||
<ImportFileInput
|
||||
featureCollection={featureCollection}
|
||||
{...actions}
|
||||
/>
|
||||
|
||||
<ImportFileInput featureCollection={featureCollection} {...actions} />
|
||||
<AddressInput />
|
||||
</>
|
||||
}
|
||||
footer={<PointInput />}
|
||||
>
|
||||
|
||||
<MapLibre layers={options.layers}>
|
||||
<DrawLayer
|
||||
featureCollection={featureCollection}
|
||||
{...actions}
|
||||
|
@ -86,6 +78,7 @@ export default function MapEditor({
|
|||
</>
|
||||
) : null}
|
||||
</MapLibre>
|
||||
<PointInput />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ import {
|
|||
useFitBounds,
|
||||
useEvent,
|
||||
EventHandler,
|
||||
useMapEvent
|
||||
useMapEvent,
|
||||
useFlyTo
|
||||
} from '../../shared/maplibre/hooks';
|
||||
import {
|
||||
filterFeatureCollection,
|
||||
|
@ -99,6 +100,7 @@ export function GeoJSONLayer({
|
|||
|
||||
function useExternalEvents(featureCollection: FeatureCollection) {
|
||||
const fitBounds = useFitBounds();
|
||||
const flyTo = useFlyTo();
|
||||
const onFeatureFocus = useCallback(
|
||||
({ detail }) => {
|
||||
const { id } = detail;
|
||||
|
@ -109,6 +111,15 @@ function useExternalEvents(featureCollection: FeatureCollection) {
|
|||
},
|
||||
[featureCollection, fitBounds]
|
||||
);
|
||||
const onZoomFocus = useCallback(
|
||||
({ detail }) => {
|
||||
const { feature } = detail;
|
||||
if (feature) {
|
||||
flyTo(17, feature.geometry.coordinates);
|
||||
}
|
||||
},
|
||||
[flyTo]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fitBounds(featureCollection.bbox as LngLatBoundsLike);
|
||||
|
@ -117,6 +128,7 @@ function useExternalEvents(featureCollection: FeatureCollection) {
|
|||
}, [fitBounds]);
|
||||
|
||||
useEvent('map:feature:focus', onFeatureFocus);
|
||||
useEvent('map:zoom', onZoomFocus);
|
||||
}
|
||||
|
||||
function LineStringLayer({
|
||||
|
|
|
@ -19,8 +19,6 @@ const Context = createContext<{ map?: Map | null }>({});
|
|||
|
||||
type MapLibreProps = {
|
||||
layers: string[];
|
||||
header?: ReactNode;
|
||||
footer?: ReactNode;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
|
@ -30,7 +28,7 @@ export function useMapLibre() {
|
|||
return context.map;
|
||||
}
|
||||
|
||||
export function MapLibre({ children, header, footer, layers }: MapLibreProps) {
|
||||
export function MapLibre({ children, layers }: MapLibreProps) {
|
||||
const isSupported = useMemo(
|
||||
() => maplibre.supported({ failIfMajorPerformanceCaveat: true }) && !isIE(),
|
||||
[]
|
||||
|
@ -90,12 +88,10 @@ export function MapLibre({ children, header, footer, layers }: MapLibreProps) {
|
|||
|
||||
return (
|
||||
<Context.Provider value={{ map }}>
|
||||
{map ? header : null}
|
||||
<div ref={containerRef} style={{ height: '500px' }}>
|
||||
<StyleControl styleId={style.id} {...mapStyleProps} />
|
||||
{map ? children : null}
|
||||
</div>
|
||||
{map ? footer : null}
|
||||
</Context.Provider>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue