import { ReactElement, useState, useCallback, useRef, useEffect } from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; // import { action } from '@storybook/addon-actions'; import { BoundsViewport } from '../map/Types'; import { BoundsDriftMarkerProps } from '../map/BoundsDriftMarker'; import { defaultAnimationDuration } from '../map/config/map'; import { leafletZoomLevelToGeohashLevel, tinyLeafletZoomLevelToGeohashLevel, } from '../map/utils/leaflet-geohash'; import { getSpeciesDonuts } from './api/getMarkersFromFixtureData'; import { LeafletMouseEvent } from 'leaflet'; import { Viewport } from '../map/MapVEuMap'; // sidebar & legend import MapVEuMap, { MapVEuMapProps } from '../map/MapVEuMap'; import MapVEuMapSidebar from '../map/MapVEuMapSidebar'; // import legend import MapVEuLegendSampleList, { LegendProps, } from '../map/MapVEuLegendSampleList'; import { Checkbox } from '@material-ui/core'; import geohashAnimation from '../map/animation_functions/geohash'; import { MouseMode } from '../map/MouseTools'; import { PlotRef } from '../types/plots'; export default { title: 'Map/General', component: MapVEuMapSidebar, } as Meta; const defaultAnimation = { method: 'geohash', animationFunction: geohashAnimation, duration: defaultAnimationDuration, }; const legendType = 'categorical'; const dropdownTitle: string = 'Species'; const dropdownHref: string[] = [ '#/link-1', '#/link-2', '#/link-3', '#/link-4', '#/link-5', '#/link-6', '#/link-7', ]; const dropdownItemText: string[] = [ 'Locus', 'Allele', 'Species', 'Sample type', 'Collection Protocol', 'Project', 'Protocol', ]; const legendInfoNumberText: string = 'Species'; // a generic function to remove a class: here it is used for removing highlight-marker function removeClassName(targetClass: string) { let targetElement = document.getElementsByClassName(targetClass)[0]; if (targetElement != null) { targetElement.classList.remove(targetClass); } } // this onClick event may need to be changed in the future like onMouseOver event const handleMarkerClick = (e: LeafletMouseEvent) => { /** * this only works when selecting other marker: not working when clicking map * it may be achieved by setting all desirable events (e.g., map click, preserving highlight, etc.) * just stop here and leave detailed events to be handled later */ // use a resuable function to remove a class removeClassName('highlight-marker'); e.target._icon.classList.add('highlight-marker'); }; const defaultMouseMode: MouseMode = 'default'; export const Spinner: Story = (args) => { const [markerElements, setMarkerElements] = useState< ReactElement[] >([]); const [legendData, setLegendData] = useState([]); const [viewport] = useState({ center: [13, 16], zoom: 4 }); const handleViewportChanged = useCallback( async (bvp: BoundsViewport) => { const markers = await getSpeciesDonuts( bvp, defaultAnimationDuration, setLegendData, handleMarkerClick ); setMarkerElements(markers); }, [setMarkerElements] ); // define mouseMode const [mouseMode, setMouseMode] = useState(defaultMouseMode); return ( <> ); }; Spinner.args = { height: '100vh', width: '100vw', showGrid: true, showMouseToolbar: true, showSpinner: true, }; export const NoDataOverlay: Story = (args) => { const [markerElements, setMarkerElements] = useState< ReactElement[] >([]); const [legendData, setLegendData] = useState([]); const [viewport] = useState({ center: [13, 16], zoom: 4 }); const handleViewportChanged = useCallback( async (bvp: BoundsViewport) => { const markers = await getSpeciesDonuts( bvp, defaultAnimationDuration, setLegendData, handleMarkerClick ); setMarkerElements(markers); }, [setMarkerElements] ); // define mouseMode const [mouseMode, setMouseMode] = useState(defaultMouseMode); return ( <> ); }; NoDataOverlay.args = { height: '100vh', width: '100vw', showGrid: true, showMouseToolbar: true, showNoDataOverlay: true, }; export const Windowed: Story = (args) => { const [markerElements, setMarkerElements] = useState< ReactElement[] >([]); const [legendData, setLegendData] = useState([]); const [viewport] = useState({ center: [2, 16], zoom: 4 }); const handleViewportChanged = useCallback( async (bvp: BoundsViewport) => { const markers = await getSpeciesDonuts( bvp, defaultAnimationDuration, setLegendData, handleMarkerClick ); setMarkerElements(markers); }, [setMarkerElements] ); // define mouseMode const [mouseMode, setMouseMode] = useState(defaultMouseMode); return ( <> ); }; Windowed.args = { height: 500, width: 700, style: { marginTop: 100, marginLeft: 'auto', marginRight: 'auto', }, showGrid: true, showMouseToolbar: true, }; export const ScreenshotOnLoad: Story = function ScreenhotOnLoad( args ) { const mapRef = useRef(null); const [image, setImage] = useState(''); useEffect(() => { // We're converting the base64 encoding of the image to an object url // because the size of the base64 encoding causes "too much recursion". mapRef.current ?.toImage({ height: args.height as number, width: args.width as number, format: 'png', }) .then(fetch) .then((res) => res.blob()) .then(URL.createObjectURL) .then(setImage); }, []); return (
); }; ScreenshotOnLoad.args = { height: 500, width: 700, showGrid: true, showMouseToolbar: true, markers: [], viewport: { center: [13, 16], zoom: 4 }, onBoundsChanged: () => {}, }; export const Tiny: Story = (args) => { const [markerElements, setMarkerElements] = useState< ReactElement[] >([]); const [legendData, setLegendData] = useState([]); const [viewport] = useState({ center: [8, 10], zoom: 2 }); const handleViewportChanged = useCallback( async (bvp: BoundsViewport) => { const markers = await getSpeciesDonuts( bvp, defaultAnimationDuration, setLegendData, handleMarkerClick, 0, tinyLeafletZoomLevelToGeohashLevel, 20 ); setMarkerElements(markers); }, [setMarkerElements] ); return ( <> ); }; Tiny.args = { height: 110, width: 220, style: { marginTop: 100, marginLeft: 'auto', marginRight: 'auto', }, showGrid: false, showMouseToolbar: false, showScale: false, showLayerSelector: false, showAttribution: false, showZoomControl: false, }; export const ScrollAndZoom: Story = (args) => { const [markerElements, setMarkerElements] = useState< ReactElement[] >([]); const [legendData, setLegendData] = useState([]); const [viewport, setViewport] = useState({ center: [13, 16], zoom: 4, }); const handleViewportChanged = useCallback( async (bvp: BoundsViewport) => { const markers = await getSpeciesDonuts( bvp, defaultAnimationDuration, setLegendData, handleMarkerClick ); setMarkerElements(markers); }, [setMarkerElements] ); // add useState for controlling scroll and zoom const [mapScroll, setMapScroll] = useState(false); const textSize = '1.0em'; return ( <>
); }; ScrollAndZoom.args = { height: 500, width: 700, style: { // marginTop: 100, marginLeft: 'auto', marginRight: 'auto', }, showGrid: true, showMouseToolbar: true, };