Last active
June 22, 2023 10:26
-
-
Save theronic/5da57a8c41a8904dab61e33beccec459 to your computer and use it in GitHub Desktop.
Struggling to port DrawControl React component to Reagent
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns ui.map | |
#?(:cljs (:require-macros [ui.map :refer [with-reagent]])) | |
(:require [hyperfiddle.electric :as e] | |
[hyperfiddle.electric-dom2 :as dom] | |
[reagent.core :as r] | |
#?(:cljs ["react" :as React]) | |
#?(:cljs ["react-dom/client" :as ReactDom]) | |
#?(:cljs ["react-map-gl" :as ReactMapGl]) | |
#?(:cljs ["@mapbox/mapbox-gl-draw" :as MapboxDraw]))) | |
;; Please refer https://github.com/visgl/react-map-gl/blob/master/examples/draw-polygon/src/draw-control.ts | |
(def MAPBOX_TOKEN "<token goes here>") | |
#?(:cljs (def ReactRootWrapper | |
(r/create-class | |
{:component-did-mount (fn [this] (js/console.log "mounted")) | |
:render (fn [this] | |
(let [[_ Component & args] (r/argv this)] | |
(into [Component] args)))}))) | |
(def react-root-hook "See `e/with`" | |
#?(:clj dom/unsupported | |
:cljs (fn ([x] (.unmount x)) | |
([x y] (.insertBefore (.-parentNode x) x y))))) | |
#?(:cljs (defn create-root | |
"See https://reactjs.org/docs/react-dom-client.html#createroot" | |
([node] (create-root node (str (gensym)))) | |
([node id-prefix] | |
(ReactDom/createRoot node #js {:identifierPrefix id-prefix})))) | |
#?(:cljs (defn render [root & args] | |
(.render root (r/as-element (into [ReactRootWrapper] args))))) | |
#?(:cljs | |
(defn draw-control [^js props] | |
(let [position (.-position props) | |
onCreate (.-onCreate props) | |
onUpdate (.-onUpdate props) | |
onDelete (.-onDelete props)] | |
(ReactMapGl/useControl | |
(MapboxDraw. props) | |
(fn [{:as args :keys [map]}] | |
(.on map "draw.create" onCreate) | |
(.on map "draw.update" onUpdate) | |
(.on map "draw.delete" onDelete)) | |
(fn [{:keys [map]}] | |
(.off map "draw.create" onCreate) | |
(.off map "draw.update" onUpdate) | |
(.off map "draw.delete" onDelete)) | |
#js {:position position})) | |
; do we need to return null here? | |
nil)) | |
#?(:cljs | |
(defn MyMap [] | |
(let [on-update (React/useCallback | |
(fn [e] | |
;; todo setFeatures here. | |
(prn "onupdate" e) | |
nil) | |
(to-array []))] | |
[:> ReactMapGl/Map {:style {:width "100vw" | |
:height "100vh"} | |
:mapboxAccessToken MAPBOX_TOKEN | |
:initialViewState {:longitude -91.874 | |
:latitude 42.76 | |
:zoom 12} | |
:mapStyle "mapbox://styles/mapbox/light-v9"} | |
[:> draw-control | |
{:position "top-left" | |
:displayControlsDefault false | |
:controls {:polygon true, :trash true} | |
:defaultMode "draw_polygon" | |
:onCreate on-update | |
:onUpdate on-update | |
:onDelete on-update}]]))) | |
(defmacro with-reagent [& args] | |
`(dom/div ; React will hijack this element and empty it. | |
(binding [dom/node (create-root dom/node)] | |
(new (e/hook react-root-hook dom/node | |
(e/fn [] dom/keepalive | |
(render dom/node ~@args))))))) | |
(e/defn App [] | |
(e/client | |
(dom/link (dom/props {:rel :stylesheet :href "/olarm.css"})) | |
(dom/div | |
(with-reagent MyMap)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment