1.1.0-1 • Published 9 months ago

@bqtran/react-sidebar-v2 v1.1.0-1

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

React-Sidebar-v2

GitHub Actions Workflow Status GitHub License NPM Version GitHub Release Date

Sidebar Screenshot

This is a React friendly port of Turbo87's sidebar-v2 map control for React-Leaflet & MapLibre GL JS.

A big shoutout to Andreas Riedmüller for creating the my-component-library scaffolding that this project leverages. You can read his excellent overview article here.

NOTE: These components are in a pre-release stage, so the API will change drastically as it is being refined.

Features

  • Recreates all the original sidebar-v2 functionality (markup, events) in React (leverages the original CSS only)
  • Includes the nifty map autopan functionality found in Norwin's leaflet-sidebar-v2.
  • Includes both components for React-Leaflet and MapLibre GL JS libraries.
  • Sidebar Context Provider for state manipulation from other React components
  • Native Lucide Icons Integration
  • TypeScript declarations

Quick Start

  1. Add <SidebarProvider> to a root component. This example uses 'maplibre' as type, but use 'leaflet' if that is your library of choice.
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import { BrowserRouter as Router } from 'react-router-dom';
import {StrictMode} from "react";
import {SidebarProvider} from "@bqtran/react-sidebar-v2";

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <SidebarProvider type="maplibre">
      <Router>
        <App />
      </Router>
    </SidebarProvider>
  </StrictMode>
)
  1. Add either ReactLeafletSidebar or MaplibreSidebar to your map as a basic example is shown below:

React-Leaflet Example

import "leaflet/dist/leaflet.css"
import {ReactLeafletSidebar} from "@bqtran/react-sidebar-v2";
import {MapContainer, TileLayer} from 'react-leaflet'

export default function LeafletMap() {
  return <div style={{flex:"1 1 auto", height:"100vh", width:"100vw"}} >
      <MapContainer center={[29.648, -95.579]} zoom={13} scrollWheelZoom={false} zoomControl={false} style={{height:"100vh", width:"100vw"}}>
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <ReactLeafletSidebar position="left" autopan={true} tabs={[
          {
            id: "menu",
            title:"Menu",
            icon:"Menu",
            position:"top",
            disabled:false,
            content:<p>Menu Content</p>
          },
          {
            id:"settings",
            title:"Settings",
            icon:"Settings",
            position:"bottom",
            disabled:false,
            content:<p>Settings Content</p>
          }
        ]}/>
      </MapContainer>
  </div>
}

Note: ReactLeafletSidebar needs to be a child component of MapContainer for React-Leaflet's contexts to work properly.

MapLibre GL JS Example

import {MapLibreSidebar} from "@bqtran/react-sidebar-v2";
import maplibre from "maplibre-gl"
import "maplibre-gl/dist/maplibre-gl.css"
import {useEffect, useState} from "react"

export default function MapLibre() { const map, setMap = useState<maplibre.Map|undefined>(undefined);

useEffect(() => { if(map == undefined) { setMap(new maplibre.Map({ container: "map", zoom: 2, style: 'https://demotiles.maplibre.org/style.json' })); } }, []);

return <div style={{flex: "1 1 auto", height: "100vh", width: "100vw"}}>

        <div id="map" style={{height: "100vh", width: "100vw"}}/>
        {map && <MapLibreSidebar map={map} position="left" autopan={true} tabs={[
            {
              id: "menu",
              title: "Menu",
              icon: "Menu",
              position: "top",
              disabled: false,
              content: <p>Menu Content</p>
            },
            {
              id: "settings",
              title: "Settings",
              icon: "Settings",
              position: "bottom",
              disabled: false,
              content: <p>Settings Content</p>
            }
          ]} />
        }
      </div>

}

>Note: The `Map` component needs to exist before it can be passed to `MapLibreSidebar`, so useState is used for this purpose.

3. The sidebar should now be showing up on your map of choice.

## Advanced Usage
A Sidebar Context is provided to expose the Sidebar's API to other React components for state information and manipulation.
You can use this to dynamically style the Sidebar according to the current state. Below is an example that applies/removes
round corners to the sidebar depending on if a tab is expanded or collapsed:

```javascript
import "leaflet/dist/leaflet.css"
import {ReactLeafletSidebar, SidebarContext, SidebarContextType} from "@bqtran/react-sidebar-v2";
import {MapContainer, TileLayer} from 'react-leaflet'
import {useContext} from "react";

export default function LeafletMap() {
  const {collapsed} = useContext(SidebarContext) as SidebarContextType;
  
  return  <div style={{flex:"1 1 auto", height:"100vh", width:"100vw"}} >
            <MapContainer center={[29.648, -95.579]} zoom={13} scrollWheelZoom={false} zoomControl={false} style={{height:"100vh", width:"100vw"}}>
              <TileLayer
                attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
              <ReactLeafletSidebar autopan={true} position="left" tabsClassName={`${collapsed ? 'rounded-lg':'rounded-l-lg'}`} contentsClassName="rounded-r-lg" tabs={[
                {
                  id: "menu",
                  title:"Menu",
                  icon:"Menu",
                  position:"top",
                  disabled:false,
                  content:<p>Menu Content</p>,
                  tabClassName: collapsed ? 'rounded-t-lg': 'rounded-tl-lg'
                },
                {
                  id:"settings",
                  title:"Settings",
                  icon:"Settings",
                  position:"bottom",
                  disabled:false,
                  content:<p>Settings Content</p>
                }
              ]}/>
            </MapContainer>
          </div>
}

API

SidebarProvider Context Provider Properties

  • type: String - Sidebar Type. Values: 'maplibre', 'leaflet'

SidebarContext Context Provider Consumables

  • innerRef: React.Ref - Reference to Sidebar
  • activeTab/setActiveTab: String/React.SetStateAction - get/set current active tab ID
  • collapsed/setCollapsed: Boolean/React.SetStateAction - get/set Sidebar's expanded/collapsed state
  • position/setPosition: String/React.SetStateAction - get/set Sidebar control's orientation on map
  • sidebarTabs/setSidebarTabs: TabType[]/React.SetStateAction - get/set Sidebar tabs
  • toggleTab: String - enable/disable tab by ID
  • type: String - get current Sidebar's configured type

ReactLeafletSidebar / MapLibreSidebar Component Properties

  • className: String (Optional) - Sidebar container styling
  • tabsClassName: String (Optional) - Sidebar tab container styling
  • contentsClassName: String (Optional) - Sidebar tab content container styling
  • position: String - Sidebar control placement. Values: 'left', 'right'
  • autopan: Boolean - Pan map on Sidebar expand/collapse
  • tabs: Tab[]- Array of Sidebar tabs
    • id: String - tab unique identifier
    • tabClassName: String (Optional) - individual tab styling
    • contentClassName: String (Optional) - individual tab content styling
    • title: String/Component - tab header text or component
    • icon: String - icon name from Lucide Icon collection
    • position: String - fix tab icon to 'top' or 'bottom'. Values: 'top', 'bottom'
    • disabled: Boolean - disable/enable sidebar tab
    • content: String/Component - tab content

ReactLeafletSidebar / MapLibreSidebar Events

  • "closing" : (tab_id) - close tab event triggered
  • "opening" : (tab_id) - open tab event triggered
  • "content" : (tab_id) - content event triggered

Attributions

Lucide - ISC License

React-Leaflet - Hippocratic License

MapLibre - 3-Clause BSD license

1.1.0-1

9 months ago

1.1.0-0

10 months ago

1.0.2-7

10 months ago

1.0.2-6

10 months ago

1.0.2-5

10 months ago

1.0.2-4

10 months ago

1.0.2-3

10 months ago

1.0.2-2

10 months ago