demarches-normaliennes/app/javascript/components/shared/maplibre/StyleControl.tsx

122 lines
4.1 KiB
TypeScript
Raw Normal View History

2024-09-20 18:22:49 +02:00
import { useId, useRef, useEffect } from 'react';
import { Button, Dialog, DialogTrigger, Popover } from 'react-aria-components';
import { MapIcon } from '@heroicons/react/outline';
2021-07-01 18:50:35 +02:00
import { Slider } from '@reach/slider';
import '@reach/slider/styles.css';
import { LayersMap, NBS } from './styles';
const STYLES = {
ortho: 'Satellite',
vector: 'Vectoriel',
ign: 'Carte IGN'
};
2024-09-20 18:22:49 +02:00
export function StyleSwitch({
styleId,
2021-07-01 18:50:35 +02:00
layers,
setStyle,
setLayerEnabled,
setLayerOpacity
}: {
styleId: string;
setStyle: (style: string) => void;
layers: LayersMap;
setLayerEnabled: (layer: string, enabled: boolean) => void;
setLayerOpacity: (layer: string, opacity: number) => void;
2021-07-01 18:50:35 +02:00
}) {
2021-07-07 14:02:55 +02:00
const configurableLayers = Object.entries(layers).filter(
([, { configurable }]) => configurable
);
2021-07-07 14:12:50 +02:00
const mapId = useId();
2024-09-20 18:22:49 +02:00
const buttonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
if (buttonRef.current) {
buttonRef.current.title = 'Sélectionner les couches cartographiques';
}
}, []);
return (
2024-09-20 18:22:49 +02:00
<DialogTrigger>
<Button ref={buttonRef}>
<MapIcon className="icon-size" />
</Button>
<Popover className="react-aria-popover">
<Dialog className="fr-modal__body">
<form
className="fr-modal__content flex m-2"
onSubmit={(event) => event.preventDefault()}
>
2024-09-20 18:22:49 +02:00
<div className="fr-fieldset">
{Object.entries(STYLES).map(([style, title]) => (
<div className="fr-fieldset__element" key={style}>
<div className="fr-radio-group">
<input
2024-09-20 18:22:49 +02:00
id={`${mapId}-${style}`}
value={style}
type="radio"
name="map-style"
2024-09-20 18:22:49 +02:00
defaultValue={style}
checked={styleId == style}
2021-07-07 14:02:55 +02:00
onChange={(event) => {
2024-09-20 18:22:49 +02:00
setStyle(event.target.value);
2021-07-01 18:50:35 +02:00
}}
/>
2024-09-20 18:22:49 +02:00
<label htmlFor={`${mapId}-${style}`} className="fr-label">
{title.replace(/\s/g, ' ')}
2021-07-07 14:12:50 +02:00
</label>
2021-07-07 14:02:55 +02:00
</div>
2024-09-20 18:22:49 +02:00
</div>
2021-07-07 14:02:55 +02:00
))}
2024-09-20 18:22:49 +02:00
</div>
{configurableLayers.length ? (
<div className="fr-fieldset__element">
{configurableLayers.map(
([layer, { enabled, opacity, name }]) => (
<div key={layer} className="fr-fieldset__element">
<div className="fr-checkbox-group">
<input
id={`${mapId}-${layer}`}
type="checkbox"
checked={enabled}
onChange={(event) => {
setLayerEnabled(layer, event.target.checked);
}}
/>
<label
className="fr-label"
htmlFor={`${mapId}-${layer}`}
>
{name}
</label>
</div>
<Slider
min={10}
max={100}
step={5}
value={opacity}
onChange={(value) => {
setLayerOpacity(layer, value);
}}
className="fr-range fr-range--sm mt-1"
title={`Réglage de lopacité de la couche «${NBS}${name}${NBS}»`}
getAriaLabel={() =>
`Réglage de lopacité de la couche «${NBS}${name}${NBS}»`
}
getAriaValueText={(value) =>
`Lopacité de la couche «${NBS}${name}${NBS}» est à ${value}${NBS}%`
}
/>
</div>
)
)}
</div>
) : null}
</form>
</Dialog>
</Popover>
2024-09-20 18:22:49 +02:00
</DialogTrigger>
);
}