HS: hide strategy config (+3 tests)

Three parts: (a) `runtime.sx` hs-hide-one!/hs-show-one! consult a new
`_hs-hide-strategies` dict (and `_hs-default-hide-strategy` override)
before falling through to the built-in display/opacity/etc. cases. The
strategy fn is called directly with (op, el, arg). New setters
`hs-set-hide-strategies!` and `hs-set-default-hide-strategy!`. (b)
`generate-sx-tests.py` `_hs_config_setup_ops` recognises
`_hyperscript.config.defaultHideShowStrategy = "X"`, `delete …default…`,
and `hideShowStrategies = { NAME: function (op, el, arg) { if …
classList.add/remove } }` with brace-matched function body extraction.
(c) Pre-setup emitter handles `__hs_config__` pseudo-name by emitting
the SX expression as-is (not a window.X = Y assignment).

Suite hs-upstream-hide: 12/16 → 15/16. Remaining test
(`hide element then show element retains original display`) needs
`on click 1 hide` / `on click 2 show` count-filtered events — separate
feature. Smoke 0-195: 162/195 unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 06:25:58 +00:00
parent 65d4c70638
commit beb120baf7
4 changed files with 224 additions and 69 deletions

View File

@@ -1722,28 +1722,55 @@
(dom-set-prop el "open" false)))))))
(begin
(define _hs-hide-strategies (dict))
(define _hs-default-hide-strategy nil)
(define
hs-set-hide-strategies!
(fn
(strategies)
(for-each
(fn (k) (dict-set! _hs-hide-strategies k (get strategies k)))
(keys strategies))))
(define
hs-set-default-hide-strategy!
(fn (name) (set! _hs-default-hide-strategy name)))
(define
_hs-resolve-strategy
(fn
(strategy)
(cond
((and (= strategy "display") _hs-default-hide-strategy)
_hs-default-hide-strategy)
(true strategy))))
(define
hs-hide-one!
(fn
(el strategy)
(let
((parts (split strategy ":")) (tag (dom-get-prop el "tagName")))
((resolved (_hs-resolve-strategy strategy)))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(cond
((= tag "DIALOG")
(when (dom-has-attr? el "open") (host-call el "close")))
((= tag "DETAILS") (dom-set-prop el "open" false))
((= prop "opacity")
(dom-set-style el "opacity" (if val val "0")))
((= prop "visibility")
(dom-set-style el "visibility" (if val val "hidden")))
((= prop "hidden") (dom-set-attr el "hidden" ""))
((= prop "twDisplay") (dom-add-class el "hidden"))
((= prop "twVisibility") (dom-add-class el "invisible"))
((= prop "twOpacity") (dom-add-class el "opacity-0"))
(true (dom-set-style el "display" (if val val "none"))))))))
((parts (split resolved ":")))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(cond
((and (not (= prop "display")) (not (= prop "opacity")) (not (= prop "visibility")) (not (= prop "hidden")) (not (= prop "class-hidden")) (not (= prop "class-invisible")) (not (= prop "class-opacity")) (not (= prop "details")) (not (= prop "dialog")) (dict-has? _hs-hide-strategies prop))
(let
((fn-val (get _hs-hide-strategies prop)))
(fn-val "hide" el val)))
((= (dom-get-prop el "tagName") "DIALOG")
(when (dom-has-attr? el "open") (host-call el "close")))
((= (dom-get-prop el "tagName") "DETAILS")
(dom-set-prop el "open" false))
((= prop "opacity")
(dom-set-style el "opacity" (if val val "0")))
((= prop "visibility")
(dom-set-style el "visibility" (if val val "hidden")))
((= prop "hidden") (dom-set-attr el "hidden" ""))
((= prop "class-hidden") (dom-add-class el "hidden"))
((= prop "class-invisible") (dom-add-class el "invisible"))
((= prop "class-opacity") (dom-add-class el "opacity-0"))
(true (dom-set-style el "display" (if val val "none")))))))))
(define
hs-hide!
(fn
@@ -1759,25 +1786,32 @@
(fn
(el strategy)
(let
((parts (split strategy ":")) (tag (dom-get-prop el "tagName")))
((resolved (_hs-resolve-strategy strategy)))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(cond
((= tag "DIALOG")
(when
(not (dom-has-attr? el "open"))
(host-call el "showModal")))
((= tag "DETAILS") (dom-set-prop el "open" true))
((= prop "opacity")
(dom-set-style el "opacity" (if val val "1")))
((= prop "visibility")
(dom-set-style el "visibility" (if val val "visible")))
((= prop "hidden") (dom-remove-attr el "hidden"))
((= prop "twDisplay") (dom-remove-class el "hidden"))
((= prop "twVisibility") (dom-remove-class el "invisible"))
((= prop "twOpacity") (dom-remove-class el "opacity-0"))
(true (dom-set-style el "display" (if val val "block"))))))))
((parts (split resolved ":")))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(cond
((and (not (= prop "display")) (not (= prop "opacity")) (not (= prop "visibility")) (not (= prop "hidden")) (not (= prop "class-hidden")) (not (= prop "class-invisible")) (not (= prop "class-opacity")) (not (= prop "details")) (not (= prop "dialog")) (dict-has? _hs-hide-strategies prop))
(let
((fn-val (get _hs-hide-strategies prop)))
(fn-val "show" el val)))
((= (dom-get-prop el "tagName") "DIALOG")
(when
(not (dom-has-attr? el "open"))
(host-call el "showModal")))
((= (dom-get-prop el "tagName") "DETAILS")
(dom-set-prop el "open" true))
((= prop "opacity")
(dom-set-style el "opacity" (if val val "1")))
((= prop "visibility")
(dom-set-style el "visibility" (if val val "visible")))
((= prop "hidden") (dom-remove-attr el "hidden"))
((= prop "class-hidden") (dom-remove-class el "hidden"))
((= prop "class-invisible") (dom-remove-class el "invisible"))
((= prop "class-opacity") (dom-remove-class el "opacity-0"))
(true (dom-set-style el "display" (if val val "block")))))))))
(define
hs-show!
(fn