Add ...props variable

This commit is contained in:
paku 2024-04-15 15:52:40 +09:00
parent cde71666ee
commit 9eed32f46a
2 changed files with 44 additions and 7 deletions

View file

@ -11,12 +11,41 @@ It's
# Differences from Flute
- Added:
- React-like fragment `(<> ...)`. It lets you group elements without a wrapper element.
- New features:
- Fragment `(<> ...)`. It allows you to group elements without a wrapper element.
- Boolean attributes support (e.g. `checked`, `disabled`). If the value is
- `nil`: Nothing is rendered.
- `t`: Only the key is rendered.
- non-boolean: The key/value pair is rendered.
- `...props` alist. It allows you to pass props more flexibly.
```lisp
(<>
(div)
(div))
; <div></div>
: <div></div>
(define-element view-more ()
(a ...props
"View More"))
(view-more :href "/detail" :class "m-1")
; <a href="/detail" class="m-1">View More</a>
(define-element custom-button (variant)
(button `((:class . ,variant)
,@...props)
children))
(custom-button :type "submit" :variant "big" :onclick "doSomething()"
"Submit")
; <button class="big" type="submit" onclick="doSomething()">Submit</button>
```
- Improved:
- Element functions are wrapped in macros for natural indentation.
- Bugfix. https://github.com/ailisp/flute/issues/5, https://github.com/ailisp/flute/issues/7

View file

@ -9,6 +9,7 @@
#:tag
#:children
#:attrs
#:...props
#:attrs-alist
#:make-attrs
#:copy-attrs
@ -192,7 +193,7 @@
style sub summary sup svg table tbody td template textarea tfoot th
thead |time| title tr track u ul var video wbr)
(defmacro define-element (name (&rest args) &body body)
(defmacro define-element (name (&rest props) &body body)
(let ((%name (alx:symbolicate '% name))
(attrs (gensym "attrs"))
(children (gensym "children"))
@ -209,10 +210,17 @@
(declare (ignorable tag attrs))
(let ((children (and ,raw-children (apply #'%<> ,raw-children))))
(declare (ignorable children))
(let ,(mapcar (lambda (arg)
(list arg `(attr attrs (alx:make-keyword ',arg))))
args)
(progn ,@body)))))))
(let ,(mapcar (lambda (prop)
(list prop `(attr attrs (alx:make-keyword ',prop))))
props)
(let ((...props
(loop :for (key . value) in (attrs-alist attrs)
:unless (member key
',(mapcar #'alx:make-keyword
props))
:collect (cons key value))))
(declare (ignorable ...props))
(progn ,@body))))))))
(defmacro ,name (&body attrs-and-children)
`(,',%name ,@attrs-and-children)))))