~severeoverfl0w/helix-sev

cb0e637b18c1eee68a24b5b29b45f6cbf011a035 — Dominic Monroe 1 year, 29 days ago 8a6cbc1 master
Add initial version
A .gitignore => .gitignore +1 -0
@@ 0,0 1,1 @@
/.cpcache

A README.md => README.md +7 -0
@@ 0,0 1,7 @@
# helix-sev

Helix extensions which SevereOverfl0w likes:

* A version of `$d` that allows including classes and ids in the string as a convenient shorthand [[helix#81](https://github.com/lilactown/helix/issues/81)]
* A macro which generates a custom defnc & defnc- with your provided default options
* My preferred defnc/defnc- with it's features

A deps.edn => deps.edn +2 -0
@@ 0,0 1,2 @@
{:deps
 {lilactown/helix {:mvn/version "0.1.1"}}}

A src/io/dominic/helix_sev/core.clj => src/io/dominic/helix_sev/core.clj +46 -0
@@ 0,0 1,46 @@
(ns io.dominic.helix-sev.core
  (:require
    helix.core))

(defmacro defdefnc
  "Generate a defnc & defnc- macro, with `default-opts` as the default options
  to defnc.  Passed options will be merged, and :helix/features will be merged
  together also."
  [default-opts]
  (list 'do
        '(declare defnc)
        '(defmacro defnc- "Like defnc but private"
           [type params & body]
           `(defnc ~(vary-meta type assoc :private true) ~params ~@body))
        (list 'let `[~'default-opts ~default-opts]
              (list
                'defmacro 'defnc '[type params & body]
                '(let [[docstring params body] (if (string? params)
                                                 [params (first body) (rest body)]
                                                 [nil params body])
                       opts? (map? (first body)) ;; whether an opts map was passed in
                       opts (if opts?
                              (first body)
                              {})
                       body (if opts?
                              (rest body)
                              body)]
                   `(helix.core/defnc ~type ~@(when docstring [docstring]) ~params
                      ;; we use `merge` here to allow indidivual consumers to override feature
                      ;; flags in special cases
                      ~(assoc (merge default-opts opts)
                              :helix/features
                              (merge (:helix/features default-opts) (:helix/features opts)))
                      ~@body))))))

(alter-meta!
  (defdefnc
    {:helix/features
     {:define-factory true
      :fast-refresh true
      :check-invalid-hooks-usage true}})
  merge
  {:doc
   "defnc to the library author's taste, with these features
  enabled by default: :define-factory true, :fast-refresh
  true, :check-invalid-hooks-usage true"})

A src/io/dominic/helix_sev/core.cljs => src/io/dominic/helix_sev/core.cljs +4 -0
@@ 0,0 1,4 @@
(ns io.dominic.helix-sev.core
  (:require helix.core)
  (:require-macros
    [io.dominic.helix-sev.core :refer [defnc defnc-]]))

A src/io/dominic/helix_sev/dom.clj => src/io/dominic/helix_sev/dom.clj +36 -0
@@ 0,0 1,36 @@
(ns io.dominic.helix-sev.dom)

(defn- concat-classes-gen
  [clazz clazzs]
  `(io.dominic.helix-sev.impl.dom/concat-classes ~clazz ~clazzs))

(defmacro $d
  [type & args]
  (if (or (keyword? type) (string? type))
    (let [[_ type css-query] (re-matches #"([^#.]*)(.*)" (name type))
          id (some-> (last ;; only one id per element
                           (re-seq #"#[^#.]*" css-query))
                     (subs 1))
          classes (mapv #(subs % 1) (re-seq #"\.[^#.]*" css-query))
          [props args] (if (map? (first args))
                         [(first args) (rest args)]
                         [nil args])

          props (if (and id
                         ;; Allow id in props to take precedence
                         (not (contains? props :id)))
                  (assoc props :id id)
                  props)

          props (cond
                  (empty? classes)
                  props

                  (contains? props :class)
                  (update props :class concat-classes-gen classes)
                  
                  :else
                  (assoc props :class classes))]

    `(helix.dom/$d ~type ~@(when props [props]) ~@args))
    `(helix.dom/$d ~type ~@args)))

A src/io/dominic/helix_sev/dom.cljs => src/io/dominic/helix_sev/dom.cljs +5 -0
@@ 0,0 1,5 @@
(ns io.dominic.helix-sev.dom
  (:require-macros [io.dominic.helix-sev.dom :refer [$d]])
  (:require
    io.dominic.helix-sev.impl.dom
    helix.dom))

A src/io/dominic/helix_sev/impl/dom.cljs => src/io/dominic/helix_sev/impl/dom.cljs +7 -0
@@ 0,0 1,7 @@
(ns io.dominic.helix-sev.impl.dom)

(defn concat-classes
  [clazz clazzs]
  (if (string? clazz)
    (cons clazz clazzs)
    (apply conj clazz clazzs)))