INTEGRATION

Element Editor with React

Built for React 19. One component, typed props, standard GeoJSON out.

Install

npm install @element-editor/react maplibre-gl

@element-editor/react needs React and React DOM ^19.2 (peer dependencies), plus maplibre-gl ^5.5. React 18 is not supported: the data table (react-data-grid) requires React 19.2.

Upgrading from the Leaflet version? Import from @element-editor/react/leaflet and @element-editor/react/leaflet/style.css, and install @element-editor/adapter-leaflet leaflet react-leaflet. See the quickstart.

Minimal example

import { ElementEditor } from '@element-editor/react'
import '@element-editor/react/style.css' // includes MapLibre's CSS

export default function App() {
  return (
    <div style={{ height: 600 }}>
      <ElementEditor
        onChange={(data) => console.log(data)}
      />
    </div>
  )
}

That's the entire setup. No provider wrapping, no store configuration, no route config. Element owns its own state.

React 19

Element needs React 19.2 or newer. React 19 features such as Actions, the use() hook and the form-status APIs are app-level concerns and compose normally with Element's callbacks.

Using the ref API

import { useRef } from 'react'
import { ElementEditor, type ElementEditorRef } from '@element-editor/react'

export default function App() {
  const ref = useRef<ElementEditorRef>(null)

  return (
    <>
      <div style={{ height: 600 }}>
        <ElementEditor ref={ref} />
      </div>
      <button onClick={() => ref.current?.exportAs('geojson')}>
        Download GeoJSON
      </button>
      <button onClick={() => ref.current?.undo()}>Undo</button>
    </>
  )
}

ElementEditorRef surfaces imperative methods: getFeatureCollection, getFeature, setFeatureCollection, importGeoJSON, exportGeoJSON, exportAs, addFeature, updateFeature(s), removeFeatures, select, setTool / getTool, getMap, flyTo, fitBounds, setZoom, undo / redo, canUndo / canRedo, clearSelection, validate and submit.

TypeScript

Types ship in the package. All props, callbacks, and types (FeatureCollection, GeoJSONFeature, Schema, etc.) are fully typed:

import type {
  ElementEditorProps,
  ElementEditorRef,
  FeatureCollection,
  Schema,
} from '@element-editor/react'

Known gotchas

  • Strict Mode double-renders. Element is tolerant — the map instance is created once, state stays consistent. If you see duplicate features, check your import logic for side effects.
  • Hot Module Replacement. Works. If you see the map container shrink to zero height after HMR, it's usually a CSS rule your dev reload is stripping — the height must survive HMR.
  • Build output. Element doesn't bundle React or its own @element-editor/* packages: @element-editor/core, @element-editor/ui and @element-editor/adapter-maplibre are installed as regular dependencies, so there is one copy of each store. The geometry worker is inlined, so no bundler configuration is needed.
  • Your page styles are safe. The stylesheet only styles the editor (elements under [data-elm-theme]); it doesn't reset your headings, buttons or SVGs.

Ready to ship?