Last active
January 15, 2026 01:16
-
-
Save shaunlebron/e3c64e5ab956bc2bff971157b37f27d8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 example.touch-surface | |
| (:require | |
| [applied-science.js-interop :as j] | |
| [reagent.core :as r] | |
| [reagent.hooks :as hooks])) | |
| (defn with-nonpassive-event-listeners | |
| "TODO: remove this when React supports non-passive event listeners: | |
| https://github.com/facebook/react/issues/22794 | |
| Add event listeners that allow `e.preventDefault()` (e.g. for touch and scroll event listeners). | |
| Usage: | |
| 1. Pass the returned Ref prop to the target component. | |
| 2. This function must be called inside a function component (i.e. r/defc). | |
| " | |
| [listeners] | |
| (returning-let [node-ref (hooks/use-ref nil)] | |
| (let [[add-events remove-events] | |
| (for [action [:addEventListener :removeEventListener]] | |
| (fn [node] | |
| (doseq [[k f] listeners] | |
| (j/call node action k f #js{:passive false}))))] | |
| (hooks/use-effect | |
| (fn [] | |
| (let [node (j/get node-ref :current)] | |
| (returning #(remove-events node) | |
| (add-events node)))))))) | |
| (r/defc touch-surface [{:keys [on-start on-move on-end on-cancel]}] | |
| (let [node-ref (with-nonpassive-event-listeners {"touchstart" on-start | |
| "touchmove" on-move})] | |
| [:<> | |
| [:style (garden/css | |
| [:.touch-surface {:position "absolute" | |
| :inset 0 | |
| :user-select "none" ;; try to disable selection | |
| :touch-action "none" ;; try to disable builtin browser behavior like zoom/pan | |
| ;; reagent/react can’t seem to handle vendor prefixes in inline styles, | |
| ;; so we have to attach it as a class rule in a <style> element here: | |
| :-webkit-touch-callout "none" ;; <-- try to prevent long tap on iOS | |
| }])] | |
| [:div.touch-surface {:ref node-ref | |
| :on-touch-end on-end | |
| :on-touch-cancel on-cancel}]])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment