Skip to content

Commit

Permalink
pass string props keys verbatim
Browse files Browse the repository at this point in the history
this allows passing non-standard or not yet supported DOM props that
will not be camelCased, e.g. `(d/div {"test-id" 42})`.
  • Loading branch information
lilactown committed Apr 19, 2023
1 parent 6d86748 commit ebe00d0
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 33 deletions.
19 changes: 16 additions & 3 deletions src/helix/impl/props.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,13 @@
:style (set-obj o "style" (dom-style v))
:value (set-obj o "value" #?(:clj `(or-undefined ~v)
:cljs (or-undefined v)))
(set-obj o (camel-case (kw->str k)) v))))
(set-obj
o
(cond
(or (keyword? k) (symbol? k)) (camel-case (kw->str k))
(string? k) k
:else (throw (ex-info "Invalid DOM prop key" {:key k :val v})))
v))))
#?(:clj (list* o)
:cljs o))))

Expand Down Expand Up @@ -183,8 +189,15 @@
([m o]
(if (seq m)
(recur (rest m)
(let [entry (first m)]
(set-obj o (kw->str (key entry)) (val entry))))
(let [entry (first m)
k (key entry)
v (val entry)]
(set-obj
o
(cond (or (keyword? k) (symbol? k)) (kw->str k)
(string? k) k
:else (throw (ex-info "Invalid prop key" {:key k :val v})))
(val entry))))
#?(:clj (list* o)
:cljs o))))

Expand Down
92 changes: 62 additions & 30 deletions test/helix/impl/props_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -46,57 +46,80 @@
(t/testing "Literal styles"
(let [handler #?(:clj '(fn [])
:cljs (fn []))]
(t/is (eq (impl/-dom-props {:foo-bar "baz" :style {:color "blue" :--custom-property "1px"} :on-click handler})
#?(:clj `(cljs.core/js-obj "fooBar" "baz"
"style" (cljs.core/js-obj "color" (helix.impl.props/->js "blue")
"--custom-property" (helix.impl.props/->js "1px"))
"onClick" ~handler)
:cljs #js {:fooBar "baz", :style #js {:color "blue"
:--custom-property "1px"}, :onClick handler}))
(t/is (eq (impl/-dom-props {:foo-bar "baz"
"baz-qux" 42
:style {:color "blue"
:--custom-property "1px"}
:on-click handler})
#?(:clj `(cljs.core/js-obj
"fooBar" "baz"
"baz-qux" 42
"style" (cljs.core/js-obj
"color" (helix.impl.props/->js "blue")
"--custom-property" (helix.impl.props/->js "1px"))
"onClick" ~handler)
:cljs #js {:fooBar "baz"
:baz-qux 42
:style #js {:color "blue"
:--custom-property "1px"}
:onClick handler}))
"Dom props with nested literal style"))
(t/is (eq (impl/-dom-props {:style [{:color "blue"} {:asdf 'jkl} {:--custom-property "1px"}]})
#?(:clj `(cljs.core/js-obj
"style" (cljs.core/array
(cljs.core/js-obj "color" (helix.impl.props/->js "blue"))
(cljs.core/js-obj "asdf" (helix.impl.props/->js ~'jkl))
(cljs.core/js-obj "--custom-property" (helix.impl.props/->js "1px"))))
:cljs #js {:style #js [#js {:color "blue"} #js {:asdf "jkl"} #js {:--custom-property "1px"}]}))
(cljs.core/js-obj
"color" (helix.impl.props/->js "blue"))
(cljs.core/js-obj
"asdf" (helix.impl.props/->js ~'jkl))
(cljs.core/js-obj
"--custom-property" (helix.impl.props/->js "1px"))))
:cljs #js {:style #js [#js {:color "blue"} #js {:asdf "jkl"}
#js {:--custom-property "1px"}]}))
"Dom props with nested literal vector style"))
#?(:cljs (t/testing "JS object"
(t/is (let [obj #js {:a 1 :b 2 :fooBar #js {:baz "jkl"}}]
(eq (impl/-dom-props obj)
obj)))))
#?(:clj (t/testing "Spread props"
(t/is (eq (impl/-dom-props '{:a 1 :b 2 & foo})
`(impl/merge-obj (cljs.core/js-obj "a" 1 "b" 2)
(t/is (eq (impl/-dom-props '{:a 1 :b 2 "c-d" 3 & foo})
`(impl/merge-obj (cljs.core/js-obj "a" 1 "b" 2 "c-d" 3)
(impl/-dom-props ~'foo)))))))

#?(:cljs
(t/deftest dom-props
(t/is (eq (impl/dom-props {:foo-bar "baz"
:foo-bar-baz "asdf"})
#js {:fooBar "baz" :fooBarBaz "asdf"}))
:foo-bar-baz "asdf"
"foo-bar-baz" "jkl"})
#js {:fooBar "baz" :fooBarBaz "asdf" :foo-bar-baz "jkl"}))
(t/is (eq (impl/dom-props {:foo-bar "baz"
:style {:color "blue"
:background-color "red"
:display :flex
:--custom-property "1px"}})
#js {:fooBar "baz" :style #js {:color "blue" :backgroundColor "red" :display "flex" :--custom-property "1px"}})
:style {:color "blue"
:background-color "red"
:display :flex
:--custom-property "1px"}})
#js {:fooBar "baz"
:style #js {:color "blue"
:backgroundColor "red"
:display "flex"
:--custom-property "1px"}})
"literal styles")
(t/is (eq (impl/dom-props {:foo-bar "baz"
:style [{:color "blue"}
{:background-color "red"}
{:display :flex}
{:--custom-property "1px"}]})
:style [{:color "blue"}
{:background-color "red"}
{:display :flex}
{:--custom-property "1px"}]})
#js {:fooBar "baz"
:style #js [#js {:color "blue"}
#js {:backgroundColor "red"}
#js {:display "flex"}
#js {:--custom-property "1px"}]}))
(t/is (eq (let [extra-props {:foo-bar :extra-foo-bar
:b :extra-b}]
:b :extra-b
"baz-qux" 42}]
(impl/dom-props {:foo-bar :a :b :b :c :c :d :d & extra-props}))
#js {:fooBar :extra-foo-bar :b :extra-b :c :c :d :d}))
#js {:fooBar :extra-foo-bar
:b :extra-b
"baz-qux" 42
:c :c :d :d}))
(t/is (eq (let [dynamic-style {:background-color "blue"
:--custom-property "1px"}]
(impl/dom-props {:style dynamic-style}))
Expand Down Expand Up @@ -125,10 +148,19 @@

#?(:cljs
(t/deftest props
(t/is (eq (impl/props {:foo-bar "baz"})
#js {:foo-bar "baz"}))
(t/is (eq (impl/props {:foo-bar "baz" :style {:color "blue" :background-color "red" :display :flex :--custom-property "1px"}})
#js {:foo-bar "baz" :style {:color "blue" :background-color "red" :display :flex :--custom-property "1px"}})
(t/is (eq (impl/props {:foo-bar "baz"
"baz-qux" 42})
#js {:foo-bar "baz"
"baz-qux" 42}))
(t/is (eq (impl/props {:foo-bar "baz"
:style {:color "blue"
:background-color "red"
:display :flex
:--custom-property "1px"}})
#js {:foo-bar "baz" :style {:color "blue"
:background-color "red"
:display :flex
:--custom-property "1px"}})
"doesn't recurse into style")
(t/is (eq (impl/props {:foo-bar "baz"
:style [{:color "blue"}
Expand Down

0 comments on commit ebe00d0

Please sign in to comment.