Remove CSSX style dictionary infrastructure — styling is just components

The entire parallel CSS system (StyleValue type, style dictionary,
keyword atom resolver, content-addressed class generation, runtime
CSS injection, localStorage caching) was built but never adopted —
the codebase already uses :class strings with defcomp components
for all styling. Remove ~3,000 lines of unused infrastructure.

Deleted:
- cssx.sx spec module (317 lines)
- style_dict.py (782 lines) and style_resolver.py (254 lines)
- StyleValue type, defkeyframes special form, build-keyframes platform fn
- Style dict JSON delivery (<script type="text/sx-styles">), cookies, localStorage
- css/merge-styles primitives, inject-style-value, fnv1a-hash platform interface

Simplified:
- defstyle now binds any value (string, function) — no StyleValue type needed
- render-attrs no longer special-cases :style StyleValue → class conversion
- Boot sequence skips style dict init step

Preserved:
- tw.css parsing + CSS class delivery (SX-Css headers, <style id="sx-css">)
- All component infrastructure (defcomp, caching, bundling, deps)
- defstyle as a binding form for reusable class strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 00:00:23 +00:00
parent 81d8e55fb0
commit a8bfff9e0b
30 changed files with 109 additions and 3164 deletions

View File

@@ -493,9 +493,9 @@ def _sf_define(expr: list, env: dict) -> Any:
def _sf_defstyle(expr: list, env: dict) -> Any:
"""``(defstyle card-base (css :rounded-xl :bg-white :shadow))``
"""``(defstyle card-base ...)``
Evaluates body → StyleValue, binds to name in env.
Evaluates body and binds to name in env.
"""
if len(expr) < 3:
raise EvalError("defstyle requires name and body")
@@ -507,63 +507,6 @@ def _sf_defstyle(expr: list, env: dict) -> Any:
return value
def _sf_defkeyframes(expr: list, env: dict) -> Any:
"""``(defkeyframes fade-in (from (css :opacity-0)) (to (css :opacity-100)))``
Builds @keyframes rule from steps, registers it, and binds the animation.
"""
from .types import StyleValue
from .css_registry import register_generated_rule
from .style_dict import KEYFRAMES
if len(expr) < 3:
raise EvalError("defkeyframes requires name and at least one step")
name_sym = expr[1]
if not isinstance(name_sym, Symbol):
raise EvalError(f"defkeyframes name must be symbol, got {type(name_sym).__name__}")
kf_name = name_sym.name
# Build @keyframes rule from steps
steps: list[str] = []
for step_expr in expr[2:]:
if not isinstance(step_expr, list) or len(step_expr) < 2:
raise EvalError("defkeyframes step must be (selector (css ...))")
selector = step_expr[0]
if isinstance(selector, Symbol):
selector = selector.name
else:
selector = str(selector)
body = _trampoline(_eval(step_expr[1], env))
if isinstance(body, StyleValue):
decls = body.declarations
elif isinstance(body, str):
decls = body
else:
raise EvalError(f"defkeyframes step body must be css/string, got {type(body).__name__}")
steps.append(f"{selector}{{{decls}}}")
kf_rule = f"@keyframes {kf_name}{{{' '.join(steps)}}}"
# Register in KEYFRAMES so animate-{name} works
KEYFRAMES[kf_name] = kf_rule
# Clear resolver cache so new keyframes are picked up
from .style_resolver import _resolve_cached
_resolve_cached.cache_clear()
# Create a StyleValue for the animation property
import hashlib
h = hashlib.sha256(kf_rule.encode()).hexdigest()[:6]
sv = StyleValue(
class_name=f"sx-{h}",
declarations=f"animation-name:{kf_name}",
keyframes=((kf_name, kf_rule),),
)
register_generated_rule(sv)
env[kf_name] = sv
return sv
def _sf_defcomp(expr: list, env: dict) -> Component:
"""``(defcomp ~name (&key param1 param2 &rest children) body)``"""
if len(expr) < 4:
@@ -1060,7 +1003,6 @@ _SPECIAL_FORMS: dict[str, Any] = {
"fn": _sf_lambda,
"define": _sf_define,
"defstyle": _sf_defstyle,
"defkeyframes": _sf_defkeyframes,
"defcomp": _sf_defcomp,
"defrelation": _sf_defrelation,
"begin": _sf_begin,