diff --git a/lib/girouette/src/girouette/garden/util.cljc b/lib/girouette/src/girouette/garden/util.cljc index a1e6b93..009c028 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,14 +59,59 @@ 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)) + +(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 (-> rule1 meta :girouette/component :ordering-level)] - [is-media-query2 (-> rule2 meta :girouette/component :ordering-level)]))) + (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)] + [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 2529117..241cb98 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,38 @@ :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 + + "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))