0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 08:20:45 -05:00
penpot/frontend/uxbox/ui/mixins.cljs
2015-12-30 00:19:47 +02:00

89 lines
2.4 KiB
Clojure
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(ns uxbox.ui.mixins
(:refer-clojure :exclude [derive])
(:require [rum.core :as rum]
[cats.labs.lens :as l]
[goog.dom.forms :as gforms]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Cursored & Lenses
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- cursored-key
[state]
(str ":rum/cursored-" (:rum/id state)))
(def ^:private
deref-xform
(map (fn [x] (if (satisfies? IDeref x) @x x))))
(defn- deref-props
[data]
(into [] deref-xform data))
(defn- cursored-did-mount
[state]
(doseq [v (:rum/props state)
:when (satisfies? IWatchable v)]
(add-watch v (cursored-key state)
(fn [_ _ _ _]
(rum/request-render (:rum/react-component state)))))
state)
(defn- cursored-will-umount
[state]
(doseq [v (:rum/props state)
:when (satisfies? IWatchable v)]
(remove-watch v (cursored-key state)))
state)
(defn- cursored-transfer-state
[old new]
(assoc new :rum/old-props (:rum/old-props old)))
(defn- cursored-should-update
[old-state new-state]
(not= (:rum/old-props old-state) (deref-props (:rum/props new-state))))
(defn- cursored-wrap-render
[render-fn]
(fn [state]
(let [[dom next-state] (render-fn state)]
[dom (assoc next-state :rum/old-props (deref-props (:rum/props state)))])))
(def cursored
"A cursor like mixin that works with
the `component` sugar syntax and lenses
from the cats library."
{:did-mount cursored-did-mount
:will-unmount cursored-will-umount
:transfer-state cursored-transfer-state
:should-update cursored-should-update
:wrap-render cursored-wrap-render})
(defn local
"Adds an atom to components state that can be used as local state.
Atom is stored under key `:rum/local`.
Component will be automatically re-rendered if atoms value changes"
([]
(local {} :rum/local))
([initial]
(local initial :rum/local))
([initial key]
{:transfer-state
(fn [old new]
(assoc new key (old key)))
:will-mount
(fn [state]
(let [local-state (atom initial)
component (:rum/react-component state)]
(add-watch local-state key
(fn [_ _ _ _]
(rum/request-render component)))
(assoc state key local-state)))
}))
(def static
{:should-update
(fn [old-state new-state]
(not= (:rum/props old-state) (:rum/props new-state)))})