Skip to content

Instantly share code, notes, and snippets.

@Deraen
Created December 13, 2023 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Deraen/5853704bed8d76d539685e49516adcd8 to your computer and use it in GitHub Desktop.
Save Deraen/5853704bed8d76d539685e49516adcd8 to your computer and use it in GitHub Desktop.
UIx spread props
(ns common.util
(:require [clojure.string :as str]
[uix.compiler.attributes :as attr]
[uix.compiler.js :as js]))
;; Could also just emit Object.assign, a bit simpler and doesn't need js*.
;; Spread operator might be a bit faster in some cases, but depends on
;; the browser and many variables probably.
;; https://clojurians.slack.com/archives/CNMR41NKB/p1701179422380989
;; We might not want to keep this optimized version in the repo and
;; just use simpler code, this isn't needed probably that often anyway.
;; Right now this is here for testing and investigation.
(defmacro spread-props
"Combines some Cljs and JS properties into one JS object.
This works for element properties.
NOTE: Uses shallow transform."
[& props]
;; One optimization idea: if the first attr is static cljs map, emit
;; the converted JS object and spread rest into that (cljs.compiler/emit-js-object)
(list* 'js*
(str "({"
(str/join ", " (repeat (count props) "...~{}"))
"})")
(for [attrs props]
;; Similar to uix.compiler.aot/compile-attrs :element
;; If we have a static value, we can convert it into JS form in macro-compilation,
;; but check if the style attr is dynamic and convert that runtime if needed.
(if (or (map? attrs) (nil? attrs))
(cond-> attrs
(and (some? (:style attrs))
(not (map? (:style attrs))))
(assoc :style `(uix.compiler.attributes/convert-props ~(:style attrs) (cljs.core/array) false))
:always (attr/compile-attrs)
:always (js/to-js))
`(uix.compiler.attributes/convert-props ~attrs (cljs.core/array) false)))))
;; (binding [*out* *err*]
;; (println (clojure.walk/macroexpand-all '(let [z {:b 2}]
;; (spread-props {:style (merge {:font "123"} {:margin 5})} z)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment