Skip to content

Commit

Permalink
[wip]
Browse files Browse the repository at this point in the history
  • Loading branch information
kimo-k committed Dec 19, 2023
1 parent 9e73017 commit acc4012
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 49 deletions.
121 changes: 73 additions & 48 deletions src/re_com/tree_select.cljs
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
(ns re-com.tree-select
(:require-macros
[re-com.core :refer [handler-fn]])
(:require
[clojure.set :as set]
[reagent.core :as r]
[re-com.config :refer [include-args-desc?]]
[re-com.util :refer [deref-or-value]]
[re-com.box :refer [h-box v-box box]]))
[re-com.box :refer [h-box v-box box gap]]
[re-com.validate :as validate :refer [parts?]]))

(def tree-select-parts-desc [])
(def tree-select-parts-desc nil)

(def tree-select-args-desc [])
(def tree-select-args-desc
(when include-args-desc?
[{:name :choices :required true :type "vector of maps | r/atom" :validate-fn validate/vector-of-maps? :description [:span "Each map represents a choice. Values corresponding to id, & label are extracted by the functions " [:code ":id-fn"] " & " [:code ":label-fn"] ". See below."]}
{:name :model :required true :type "a set of ids | r/atom" :description [:span "The set of the ids for currently selected choices. If nil or empty, see " [:code ":placeholder"] "."]}]))

(defn choice [{:keys [label checked? toggle! level showing? width style disabled?]}]
(def tree-select-dropdown-parts-desc nil)

(def tree-select-dropdown-args-desc
(when include-args-desc?
[{:name :placeholder :required false :type "string" :validate-fn string? :description "Background text shown when there's no selection."}]))

(defn choice [{:keys [label checked? toggle! level showing? disabled?]}]
(when showing?
[h-box
:children
[[box
[[gap :size (str level "rem")]
[box
:attr {:on-click (when-not disabled? toggle!)}
:style {:cursor (if disabled? "default" "pointer")}
:child
Expand Down Expand Up @@ -57,12 +71,12 @@
(some->> path as-v (iterate butlast) (take-while identity) (map vec)))

(defn infer-groups [items]
(into items (comp
(keep :group)
(map #(if (vector? %) % [%]))
(mapcat ancestor-paths)
(map #(do {:type :group :group %}))
(distinct))
(into #{} (comp
(keep :group)
(map #(if (vector? %) % [%]))
(mapcat ancestor-paths)
(map #(do {:type :group :group %}))
(distinct))
items))

(defn toggle [s k]
Expand All @@ -71,54 +85,65 @@
((fnil conj #{}) s k)))

(defn tree-select
[& {:keys [model choice-renderer group-renderer groups]
:or {model (r/atom nil)
[& {:as props
:keys [model choices choice-renderer group-renderer groups open-to id-fn]
:or {open-to :chosen
groups (r/atom nil)
id-fn :id
choice-renderer choice
group-renderer group}}]
(fn [& {:keys [choices group-label-fn disabled? min-width max-width]
(let [open-to (deref-or-value open-to)]
(println open-to)
(when-not (= :none open-to)
(reset! groups (case open-to
:all (infer-groups choices)
(:chosen nil)
(into #{}
(comp
(filter #(contains? (deref-or-value model) (id-fn %)))
(keep :group)
(mapcat ancestor-paths))
choices)))))
(fn [& {:keys [choices group-label-fn disabled? min-width max-width on-change]
:or {group-label-fn {}}}]
(let [choices (deref-or-value choices)
disabled? (deref-or-value disabled?)
items (->> choices
infer-groups
(sort-by (juxt (comp #(apply str %) :group)
(complement group?))))
item (fn [{:keys [group id] :as m}]
(let [group (as-v group)]
(if (group? m)
items (->> choices infer-groups (into choices) (sort-by (juxt (comp #(apply str %) :group)
(complement group?))))
item (fn [{:keys [group id] :as item}]
(let [group-v (as-v group)]
(if (group? item)
[group-renderer
(let [descendant? #(= group (vec (take (count group) (as-v (:group %)))))
descendants (->> choices
(filter descendant?)
(map :id))
(let [descendant? #(= group-v (vec (take (count group-v) (as-v (:group %)))))
descendants (map :id (filter descendant? choices))
checked? (cond
(every? (set (:choices @model)) descendants) :all
(some (set (:choices @model)) descendants) :some)]
(merge m {:label (or (group-label-fn (peek group)) (peek group))
:hide-show! #(swap! groups toggle group)
:toggle! #(swap! model update :choices
(if (= :all checked?) set/difference (fnil into #{}))
descendants)
:open? (contains? @groups group)
:checked? checked?
:model model
:disabled? disabled?
:showing? (every? (set @groups) (rest (ancestor-paths group)))
:level (if (vector? group) (count group) 1)}))]
(every? (deref-or-value model) descendants) :all
(some (deref-or-value model) descendants) :some)]
(merge item
{:label (or (group-label-fn (peek group-v)) (peek group-v))
:hide-show! #(swap! groups toggle group-v)
:toggle! #(swap! model
(if (= :all checked?) set/difference (fnil into #{}))
descendants)
:open? (contains? @groups group-v)
:checked? checked?
:model model
:disabled? disabled?
:showing? (every? (set @groups) (rest (ancestor-paths group-v)))
:level (count group-v)}))]
[choice-renderer
(merge m {:model model
:showing? (if-not group
true
(every? (set @groups) (ancestor-paths group)))
:disabled? disabled?
:toggle! #(swap! model update :choices toggle id)
:checked? (some-> @model :choices (get id))
:level (count group)})])))]
(merge item
{:model model
:showing? (if-not group-v
true
(every? (set @groups) (ancestor-paths group-v)))
:disabled? disabled?
:toggle! (handler-fn (on-change (toggle @model id)))
:checked? (get @model id)
:level (inc (count group-v))})])))]
[:<>
@groups ;; TODO remove. Doesn't update without this.
[v-box
:min-width min-width
:max-width max-width
:children
(map item items)]])))
(mapv item items)]])))
31 changes: 30 additions & 1 deletion src/re_demo/tree_select.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[clojure.string :as string]
[reagent.core :as reagent]
[re-com.core :refer [at h-box box checkbox gap v-box tree-select tag-dropdown hyperlink-href p label line]]
[re-com.radio-button :refer [radio-button]]
[re-com.slider :refer [slider]]
[re-com.tree-select :refer [tree-select-parts-desc tree-select-args-desc]]
[re-com.tag-dropdown :refer [tag-dropdown-parts-desc tag-dropdown-args-desc]]
Expand All @@ -27,8 +28,10 @@

(defn demo
[]
(let [model (reagent/atom nil)
(let [model (reagent/atom #{:sydney :auckland})
groups (reagent/atom nil)
disabled? (reagent/atom false)
open-to (reagent/atom :chosen)
placeholder? (reagent/atom false)
abbrev-fn? (reagent/atom false)
abbrev-threshold? (reagent/atom false)
Expand All @@ -47,9 +50,11 @@
:min-width (when @min-width? (str @min-width "px"))
:max-width (when @max-width? (str @max-width "px"))
:disabled? disabled?
:open-to @open-to
:placeholder (when @placeholder? "placeholder message")
:choices cities
:model model
:groups groups
:abbrev-fn (when @abbrev-fn? #(string/upper-case (first (:label %))))
:abbrev-threshold (when @abbrev-threshold? abbrev-threshold)
:on-change #(reset! model %)]
Expand All @@ -63,6 +68,16 @@
{:class "display-flex"
:style {:flex "1"}}
(with-out-str (pprint/pprint @model))]]]
[h-box :src (at)
:height "45px"
:gap "5px"
:width "100%"
:children [[label :src (at) :label [:code ":groups"]]
[label :src (at) :label " is currently"]
[:code
{:class "display-flex"
:style {:flex "1"}}
(with-out-str (pprint/pprint @groups))]]]
[v-box :src (at)
:gap "10px"
:style {:min-width "550px"
Expand All @@ -84,6 +99,20 @@
:child [:span "Supply the string \"placeholder message\" for the " [:code ":placeholder"] " parameter"]]
:model placeholder?
:on-change #(reset! placeholder? %)]
[v-box :src (at)
:children [[box :src (at) :align :start :child [:code ":open-to"]]
[radio-button :src (at)
:label [:span [:code ":chosen"] ", " [:code "nil"] ", ommitted - reveal every chosen item."]
:value :chosen
:model @open-to
:on-change #(reset! open-to %)
:style {:margin-left "20px"}]
[radio-button :src (at)
:label [:span [:code ":all"] " - expand all groups"]
:value :all
:model @open-to
:on-change #(reset! open-to %)
:style {:margin-left "20px"}]]]
[v-box :src (at)
:gap "11px"
:children [[checkbox :src (at)
Expand Down

0 comments on commit acc4012

Please sign in to comment.