-
Notifications
You must be signed in to change notification settings - Fork 2
/
utils.cljs
66 lines (59 loc) · 2.89 KB
/
utils.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(ns headlessui-reagent.utils
(:require [clojure.string :as string]
[reagent.core :as r]
[clojure.set :as set]))
(defn props-and-children [args]
(if (or (nil? (first args)) (map? (first args)))
[(first args) (rest args)]
[{} args]))
(defn dashify [kw]
(->> (string/split (name kw) #"(?=[A-Z])")
(map string/lower-case)
(string/join "-")
keyword))
(defn pass-through-props
"We need props appropriate for a reagent component. We receive React style
props that have been shallowly converted to a CLJ hashmap. Finishes the
conversion to reagent props."
[props]
(set/rename-keys (reduce (fn [result [k v]]
;; Is js->clj safe?
(assoc result (dashify k) (js->clj v)))
{}
(dissoc props :children))
{:class-name :class}))
(defn headlessui->reagent
"Convert a @headlessui/react component into a reagent component."
[component]
(fn [& args]
(let [[props children] (props-and-children args)
props (if-not (map? props)
props
(cond-> props
(and (contains? props :as)
;; this interop code would handle strings, but better to avoid it
(not (string? (:as props))))
(update :as (fn [as]
(r/reactify-component
(fn [{:keys [children] :as inner-props}]
[as (pass-through-props inner-props) children]))))
(and (contains? props :class)
(fn? (:class props)))
(update :class (fn [f]
(fn [js-slot]
(r/class-names (f (js->clj js-slot :keywordize-keys true))))))))
children (if (and (= 1 (count children))
(fn? (first children)))
(let [f (first children)]
[(fn [js-slot]
(let [[comp :as comp-and-args] (f (js->clj js-slot :keywordize-keys true))]
(assert (or
;; we are certain a different component will receive the props
(and (map props)
(contains? props :as))
;; we are rendering a hiccup keyword which, for whatever reagent-internal reason, can receive props
(keyword? comp))
"headlessui can't pass props to reagent components; suggestion: return a hiccup keyword-style component")
(r/as-element comp-and-args)))])
children)]
(into [:> component props] children))))