membrane
membrane copied to clipboard
Add support for composite events
Membrane should do a better job supporting composite events/interactions like mouse-down-and-up, drag-and-drop, double-click, context menus (eg. right click), copy/cut/paste, modals, etc.
I don't think any changes to membrane's event model or state management are required. Off the top of my head, the steps required are something like:
- simplify and break apart membrane.component/top-level-ui
- package support for different interactions like mouse-down-and-up, drag-and-drop, double-click, context menus (eg. right click), copy/cut/paste, modals, etc into reusable pieces
- provide sane defaults
Below is a sketch of a workaround that doesn't require any changes/updates to membrane
(defui wrap-depressed [{:keys [body
^:membrane.component/contextual
depressed]}]
(ui/wrap-on
;; It's unclear whether you want mouse move events to be ignored while
;; a button is depressed. If you do, just uncomment the :mouse-move wrapper
;; here.
#_#_
:mouse-move
(fn [handler pos]
(when (not depressed)
(handler pos)))
:mouse-up
(fn [handler pos]
(concat (handler pos)
[[:set $depressed nil]]))
;; The fixed bounds is a workaround for not being able to catch top level
;; mouse events outside the size of the app.
;; eg. If the user releases the mouse-up event outside the relatively small size of
;; test-app ui, then depressed won't get reset correctly.
(ui/fixed-bounds [4000 4000]
body)))
(defui normal-button [{:keys [text
private
^:membrane.component/contextual
depressed]}]
(let [is-depressed (= depressed $private)]
(ui/on
:mouse-down
(fn [_]
[[:set $depressed $private]])
:mouse-up
(fn [_]
(when is-depressed
[[:do-something]]))
(ui/button text nil is-depressed))))
(defui test-app [{:keys []}]
(wrap-depressed
{:body
(ui/vertical-layout
(basic/textarea {:text (:text extra)})
(basic/button {:text "no depression"})
(ui/on
:do-something
(fn []
[[::e1]])
(normal-button {:text "with depression"}))
(ui/on
:do-something
(fn []
[[::e2]])
(normal-button {:text "with depression 2"}))
(apply
ui/horizontal-layout
(for [text ["a" "b" "c"]]
(ui/on
:do-something
(fn []
[[::e3 text]])
(normal-button {:text text})))))}))
(def app (membrane.component/make-app #'test-app {}) )
(comment
(backend/run app)
,)