From 0614d63b722a37192c68448ad912e9b5b5b98f3d Mon Sep 17 00:00:00 2001 From: "James N. V. Cash" Date: Sat, 4 May 2024 22:52:12 -0400 Subject: [PATCH 1/2] Factor media query min-width into rule-comparator In order for larger sizes to override smaller ones and thus allow examples like `grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6` to work, the larger minimum sizes need to come later in the output file. --- lib/girouette/src/girouette/garden/util.cljc | 21 ++++++++++++++++--- .../test/girouette/garden/util_test.cljc | 21 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/girouette/src/girouette/garden/util.cljc b/lib/girouette/src/girouette/garden/util.cljc index a1e6b93..dcac157 100644 --- a/lib/girouette/src/girouette/garden/util.cljc +++ b/lib/girouette/src/girouette/garden/util.cljc @@ -1,5 +1,6 @@ (ns girouette.garden.util (:require [clojure.spec.alpha :as s] + [clojure.string :as string] [clojure.walk :as walk] #?(:clj [garden.types] :cljs [garden.types :refer [CSSAtRule]]) @@ -58,6 +59,19 @@ gi-class-names) merge-rules)) +(defn- px-str->int + [s] + (some-> s + (string/replace #"px$" "") + #?(:clj (Long.) + :cljs (js/parseInt 10)))) + +(defn- media-query-priority + [rule] + (or (some-> (get-in rule [:value :media-queries :min-width]) + px-str->int) + 0)) + (defn rule-comparator "Compares the Garden rules provided by Girouette, so they can be ordered correctly in a style file." @@ -66,6 +80,7 @@ (= (:identifier rule1) :media)) is-media-query2 (and (instance? CSSAtRule rule2) (= (:identifier rule2) :media))] - (compare [is-media-query1 (-> rule1 meta :girouette/component :ordering-level)] - [is-media-query2 (-> rule2 meta :girouette/component :ordering-level)]))) - + (compare [is-media-query1 (if is-media-query1 (media-query-priority rule1) 0) + (-> rule1 meta :girouette/component :ordering-level)] + [is-media-query2 (if is-media-query2 (media-query-priority rule2) 0) + (-> rule2 meta :girouette/component :ordering-level)]))) diff --git a/lib/girouette/test/girouette/garden/util_test.cljc b/lib/girouette/test/girouette/garden/util_test.cljc index 2529117..dcf792d 100644 --- a/lib/girouette/test/girouette/garden/util_test.cljc +++ b/lib/girouette/test/girouette/garden/util_test.cljc @@ -2,7 +2,7 @@ (:require [clojure.test :refer [deftest testing is are]] [girouette.tw.default-api :refer [tw-v3-class-name->garden]] [girouette.tw.common :refer [dot]] - [girouette.garden.util :refer [apply-class-rules]])) + [girouette.garden.util :refer [apply-class-rules rule-comparator]])) (deftest apply-class-rules-test (are [target-class-name gi-class-names expected-garden] @@ -26,3 +26,22 @@ :rules [[".my-class" {:padding "0.25rem" :margin "0.25rem"}] [".my-class" [:&:hover {:padding "0.5rem"}]]]}}))) + +(deftest rule-comparator-sorting-test + (are [rule1 rule2 comparison] + (= (rule-comparator + (tw-v3-class-name->garden rule1) + (tw-v3-class-name->garden rule2)) + comparison) + + "md:grid-cols-1" + "lg:grid-cols-1" + -1 + + "md:grid-cols-2" + "grid-cols-1" + 1 + + "md:grid-cols-1" + "dark:text-white" + 1)) From c7b7fa7754400d5fdba06b7e16d9e1409ac41812 Mon Sep 17 00:00:00 2001 From: "James N. V. Cash" Date: Mon, 17 Jun 2024 15:13:37 -0400 Subject: [PATCH 2/2] Also output some state variants in required order Active needs to come after hover to display correctly; this mechanism is now extensible so other rule orderings can be enforced as well --- lib/girouette/src/girouette/garden/util.cljc | 43 ++++++++++++++++--- .../test/girouette/garden/util_test.cljc | 18 +++++++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/lib/girouette/src/girouette/garden/util.cljc b/lib/girouette/src/girouette/garden/util.cljc index dcac157..009c028 100644 --- a/lib/girouette/src/girouette/garden/util.cljc +++ b/lib/girouette/src/girouette/garden/util.cljc @@ -72,15 +72,46 @@ px-str->int) 0)) +(def variant-priority-order + {"hover" 1 + "active" 2}) + +(defn- state-prefix-priority + [rule] + (if-let [variants (get-in (meta rule) [:girouette/props :prefixes :state-variants])] + (->> (keep (fn [[v-type variant]] + (when (= v-type :plain-state-variant) variant)) + variants) + (map-indexed + (fn [idx variant] + (if-let [priority (get variant-priority-order variant)] + (+ priority (* idx (count variant-priority-order))) + 0))) + (apply +)) + 0)) + +(defn- prefix-priority + [rule] + [(media-query-priority rule) (state-prefix-priority rule)]) + (defn rule-comparator "Compares the Garden rules provided by Girouette, so they can be ordered correctly in a style file." [rule1 rule2] - (let [is-media-query1 (and (instance? CSSAtRule rule1) - (= (:identifier rule1) :media)) - is-media-query2 (and (instance? CSSAtRule rule2) - (= (:identifier rule2) :media))] - (compare [is-media-query1 (if is-media-query1 (media-query-priority rule1) 0) + (let [has-prefix-1? (->> (get-in (meta rule1) [:girouette/props :prefixes]) + vals + (some some?) + boolean) + has-prefix-2? (->> (get-in (meta rule1) [:girouette/props :prefixes]) + vals + (some some?) + boolean)] + (compare [has-prefix-1? (if has-prefix-1? (prefix-priority rule1) 0) (-> rule1 meta :girouette/component :ordering-level)] - [is-media-query2 (if is-media-query2 (media-query-priority rule2) 0) + [has-prefix-2? (if has-prefix-2? (prefix-priority rule2) 0) (-> rule2 meta :girouette/component :ordering-level)]))) + +(comment + + (compare [0 [1 2]] + [0 [2 1]])) diff --git a/lib/girouette/test/girouette/garden/util_test.cljc b/lib/girouette/test/girouette/garden/util_test.cljc index dcf792d..241cb98 100644 --- a/lib/girouette/test/girouette/garden/util_test.cljc +++ b/lib/girouette/test/girouette/garden/util_test.cljc @@ -44,4 +44,20 @@ "md:grid-cols-1" "dark:text-white" - 1)) + 1 + + "hover:bg-red-500" + "active:bg-blue-500" + -1 + + "active:hover:bg-red-500" + "active:bg-blue-500" + 1 + + "disabled:bg-red-500" + "hover:bg-red-200" + -1 + + "focus:disabled:bg-red-500" + "hover:bg-red-200" + -1))