From b9fe9462de8646cfc4f16439b4448be62b90806e Mon Sep 17 00:00:00 2001 From: Kimo Knowles Date: Tue, 21 May 2024 22:17:23 +0200 Subject: [PATCH] [nested-grid] Add :cell-value prop --- src/re_com/nested_grid.cljs | 39 ++++++++++++++-------- src/re_demo/nested_grid.cljs | 63 +++++++++++++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 18 deletions(-) diff --git a/src/re_com/nested_grid.cljs b/src/re_com/nested_grid.cljs index a227e61a..a77985b8 100644 --- a/src/re_com/nested_grid.cljs +++ b/src/re_com/nested_grid.cljs @@ -25,6 +25,14 @@ [:span "String, hiccup or function. When a function, acceps keyword args " [:code ":column-path"] " and " [:code ":row-path"] ". Returns either a string or hiccup, which will appear within a single grid cell."]} + {:name :cell-value + :type "function" + :required false + :validate-fn ifn? + :description + [:span "Before calling " [:code ":cell"] ", " [:code "nested-grid"] " evaluates " + [:code ":cell-value"] "with the same arguments. It then passes the return value to " + [:code ":cell"] ", via a " [:code ":value"] " prop."]} {:name :column-tree :default "[]" :type "vector or seq of column-specs or column-trees" @@ -354,13 +362,16 @@ (defn cell-part [{:keys [column-path row-path]}] nil) -(defn cell-wrapper-part [{:keys [column-path row-path cell theme] - :as args}] - [:div - (-> {:style {:grid-column (path->grid-line-name column-path) - :grid-row (path->grid-line-name row-path)}} - (theme/apply {:state {} :part ::cell-wrapper} theme)) - [u/part cell (dissoc args :cell) cell-part]]) +(defn cell-wrapper-part [{:keys [column-path row-path cell theme cell-value] + :as props}] + (let [props (cond-> props + :do (dissoc :cell) + cell-value (assoc :value (cell-value props)))] + [:div + (-> {:style {:grid-column (path->grid-line-name column-path) + :grid-row (path->grid-line-name row-path)}} + (theme/apply {:state {} :part ::cell-wrapper} theme)) + [u/part cell props cell-part]])) (defn header-label [path] (let [header (last path)] @@ -568,7 +579,7 @@ resize-handler (r/atom #()) theme {:user [theme (theme/parts parts)]}] (fn [& {:keys [column-tree row-tree - cell column-header row-header header-spacer + cell cell-value column-header row-header header-spacer cell-wrapper column-header-wrapper row-header-wrapper header-spacer-wrapper show-branch-paths? max-height max-width @@ -789,11 +800,13 @@ cells (doall (for [column-path showing-column-paths row-path showing-row-paths - :let [props {:column-path column-path - :row-path row-path - :cell cell - :theme theme}]] - ^{:key [::cell (or [column-path row-path] (gensym))]} + :let [props (merge {:column-path column-path + :row-path row-path + :cell cell + :theme theme} + (when cell-value + {:cell-value cell-value}))]] + ^{:key [::cell-wrapper (or [column-path row-path] (gensym))]} [u/part cell-wrapper props cell-wrapper-part])) zebra-stripes (for [i (filter even? (range 1 (inc (count row-paths))))] ^{:key [::zebra-stripe i]} diff --git a/src/re_demo/nested_grid.cljs b/src/re_demo/nested_grid.cljs index 9b97fe45..fb0ffdab 100644 --- a/src/re_demo/nested_grid.cljs +++ b/src/re_demo/nested_grid.cljs @@ -78,7 +78,7 @@ [:code ":column-tree"] "." [:ul [:li "For the " [:code ":column-tree"] " above, " [:code "[:a [1 2] :b [3 4]]"] ", its " [:code ":column-path"] "s are: " - [:pre "[[:a] [:a 1] [:a 2] [:b] [:b 1] [:b 2]]"]]]] + [:pre "[[:a] [:a 1] [:a 2] [:b] [:b 3] [:b 4]]"]]]] [title2 "Row"] [p "Everything described above applies to rows, as well. " [:code ":row-spec"] ", " [:code ":row-tree"] " and " [:code ":row-path"] " have all the same properties as their column equivalents."] @@ -287,6 +287,12 @@ (apply merge))] (operator left right)))]"]]]) +(def lorem-ipsum ["Lorem" "ipsum" "dolor" "sit" "amet" " consectetur" "adipiscing" "elit" " sed" + "do" "eiusmod" "tempor" "incididunt" "ut" "labore" "et" "dolore" "magna" + "aliqua."]) + +(defn rand-color [] (str "rgb(" (* 255 (rand)) "," (* 255 (rand)) "," (* 255 (rand)) ")")) + (defn internals-demo [] [v-box :gap "12px" @@ -304,10 +310,10 @@ {:label "Typed" :tree [:kw 42 "str" {:k :map}]}] :cell (fn [{:keys [column-path] [{:keys [tree]}] :row-path}] (case (:id (last column-path)) - "Tree" (str tree) + "Tree" (str tree) "Leaf Paths" (str (vec (nested-grid/leaf-paths (nested-grid/header-spec->header-paths tree)))) - "All Paths" (str (nested-grid/header-spec->header-paths tree))))] + "All Paths" (str (nested-grid/header-spec->header-paths tree))))] [p "This table demonstrates how " [:code "nested-grid"] " derives a vector of " [:code ":column-path"] "s from a " [:code ":column-tree"] "."] [line] [h-box @@ -359,7 +365,7 @@ :row-header-width 30 :column-width 50 :cell (fn [{:keys [column-path row-path]}] - [:i {:style {:color "grey" + [:i {:style {:color "grey" :font-size 10}} (str column-path row-path)])] [:pre {:style {:margin-top 19}} @@ -555,7 +561,54 @@ [:ul [:li "render complex graphics and UI"] [:li "efficiently update (by dereferencing a reagent atom)"] - [:li "flexibly serialize its value with " [:code ":on-export-cell"]]]]]]) + [:li "flexibly serialize its value with " [:code ":on-export-cell"]]]] + [line] + [nested-grid + {:column-tree ["Longest" "Shortest" "Median" "Random"] + :show-branch-cells? true + :column-width 85 + :row-tree ["Capitalize" "Emphasize" "Colorize"] + :cell (fn [{:keys [row-path value]}] + (case (last row-path) + "Capitalize" [:span {:style {:text-transform "capitalize"}} + value] + "Emphasize" [:i [:strong value]] + "Colorize" [:span {:style {:color (rand-color)}} + value])) + :cell-value (fn [{:keys [column-path]}] + (case (last column-path) + "Longest" (last (sort-by count lorem-ipsum)) + "Shortest" (first (sort-by count lorem-ipsum)) + "Median" (nth (vec (sort-by count lorem-ipsum)) + (/ (count lorem-ipsum) 2)) + "Random" (rand-nth lorem-ipsum)))}] + [:pre {:style {:margin-top 19}} "[nested-grid + :column-tree [\"Longest\" \"Shortest\" \"Median\" \"Random\"] + :row-tree [\"Capitalize\" \"Emphasize\" \"Colorize\"] + :cell (fn [{:keys [row-path value]}] + (case (last row-path) + \"Capitalize\" [:span {:style {:text-transform + \"capitalize\"}} + value] + \"Emphasize\" [:i [:strong value]] + \"Colorize\" [:span {:style {:color (rand-color)}} + value])) + :cell-value (fn [{:keys [column-path]}] + (case (last column-path) + \"Longest\" (last (sort-by count lorem-ipsum)) + \"Shortest\" (first (sort-by count lorem-ipsum)) + \"Median\" (nth (vec (sort-by count lorem-ipsum)) + (/ (count lorem-ipsum) 2)) + \"Random\" (rand-nth lorem-ipsum)))]"] + [p "The " [:code ":cell-value"] " prop offers a semantic separation of data processing from rendering. " + [:code ":cell-value"] " should be a function, with the same signature as " [:code ":cell"] ". " + "When " [:code ":cell-value"] " is provided, " [:code "nested-grid"] + " passes its return value to " [:code ":cell"] + " via a " [:code ":value"] " prop."] + [p + "In this case, " [:code ":cell-value"] + " is responsible for choosing an item of the source data, and " + [:code ":cell"] " is responsible for styling the resulting " [:code ":value."]]]]) (defn demos [] (let [tabs [{:id :basic :label "Basic Demo" :view basic-demo}