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

134 lines
4.2 KiB
TypeScript
Raw Normal View History

import React, { useState } from 'react';
import { Popover, RadioGroup } from '@headlessui/react';
import { usePopper } from 'react-popper';
import { MapIcon } from '@heroicons/react/outline';
2021-07-01 18:50:35 +02:00
import { Slider } from '@reach/slider';
2021-07-07 14:12:50 +02:00
import { useId } from '@reach/auto-id';
2021-07-01 18:50:35 +02:00
import '@reach/slider/styles.css';
import { LayersMap, NBS } from './styles';
const STYLES = {
ortho: 'Satellite',
vector: 'Vectoriel',
ign: 'Carte IGN'
};
export function StyleControl({
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
}) {
const [buttonElement, setButtonElement] =
useState<HTMLButtonElement | null>();
const [panelElement, setPanelElement] = useState<HTMLDivElement | null>();
const { styles, attributes } = usePopper(buttonElement, panelElement, {
placement: 'bottom-end'
});
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();
return (
<div
className="form map-style-control mapboxgl-ctrl-group"
style={{ zIndex: 10 }}
>
<Popover>
<Popover.Button
ref={setButtonElement}
className="map-style-button"
title="Sélectionner les couches cartographiques"
>
<MapIcon className="icon-size" />
</Popover.Button>
<Popover.Panel
className="flex map-style-panel mapboxgl-ctrl-group"
ref={setPanelElement}
style={styles.popper}
{...attributes.popper}
>
<RadioGroup
value={styleId}
onChange={setStyle}
className="styles-list"
as="ul"
>
{Object.entries(STYLES).map(([style, title]) => (
<RadioGroup.Option
key={style}
value={style}
as="li"
className="flex"
>
{({ checked }) => (
<>
<input
type="radio"
key={`${style}-${checked}`}
defaultChecked={checked}
name="map-style"
className="m-0 p-0 mr-1"
/>
<RadioGroup.Label>
{title.replace(/\s/g, ' ')}
</RadioGroup.Label>
</>
)}
</RadioGroup.Option>
))}
</RadioGroup>
2021-07-07 14:02:55 +02:00
{configurableLayers.length ? (
<ul className="layers-list">
2021-07-07 14:02:55 +02:00
{configurableLayers.map(([layer, { enabled, opacity, name }]) => (
<li key={layer}>
<div className="flex mb-1">
<input
2021-07-07 14:12:50 +02:00
id={`${mapId}-${layer}`}
2021-07-07 14:02:55 +02:00
className="m-0 p-0 mr-1"
type="checkbox"
checked={enabled}
onChange={(event) => {
setLayerEnabled(layer, event.target.checked);
2021-07-01 18:50:35 +02:00
}}
/>
2021-07-07 14:12:50 +02:00
<label className="m-0" htmlFor={`${mapId}-${layer}`}>
{name}
</label>
2021-07-07 14:02:55 +02:00
</div>
<Slider
min={10}
max={100}
step={5}
value={opacity}
onChange={(value) => {
setLayerOpacity(layer, value);
}}
className="mb-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}%`
}
/>
</li>
))}
</ul>
) : null}
</Popover.Panel>
</Popover>
</div>
);
}