SX docs: configurable shell, SX-native event handlers, nav fixes

- Configurable page shell (~sx-page-shell kwargs + SX_SHELL app config)
  so each app controls its own assets — sx docs loads only sx-browser.js
- SX-evaluated sx-on:* handlers (eval-expr instead of new Function)
  with DOM primitives registered in PRIMITIVES table
- data-init boot mode for pure SX initialization scripts
- Jiggle animation on links while fetching
- Nav: 3-column grid for centered alignment, is-leaf sizing,
  fix map-indexed param order (index, item), guard mod-by-zero
- Async route eval failure now falls back to server fetch
  instead of silently rendering nothing
- Remove duplicate h1 title from ~doc-page
- Re-bootstrap sx-ref.js + sx-browser.js

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 11:00:59 +00:00
parent 31a6e708fc
commit 8a5c115557
20 changed files with 5763 additions and 3046 deletions

View File

@@ -420,6 +420,8 @@ class JSEmitter:
"promise-delayed": "promiseDelayed",
"abort-previous": "abortPrevious",
"track-controller": "trackController",
"abort-previous-target": "abortPreviousTarget",
"track-controller-target": "trackControllerTarget",
"new-abort-controller": "newAbortController",
"controller-signal": "controllerSignal",
"abort-error?": "isAbortError",
@@ -470,7 +472,6 @@ class JSEmitter:
"try-async-eval-content": "tryAsyncEvalContent",
"register-io-deps": "registerIoDeps",
"url-pathname": "urlPathname",
"bind-inline-handler": "bindInlineHandler",
"bind-preload": "bindPreload",
"mark-processed!": "markProcessed",
"is-processed?": "isProcessed",
@@ -584,6 +585,7 @@ class JSEmitter:
"scan-io-refs-walk": "scanIoRefsWalk",
"transitive-io-refs": "transitiveIoRefs",
"compute-all-io-refs": "computeAllIoRefs",
"component-io-refs-cached": "componentIoRefsCached",
"component-pure?": "componentPure_p",
"render-target": "renderTarget",
"page-render-plan": "pageRenderPlan",
@@ -3091,6 +3093,19 @@ PLATFORM_ORCHESTRATION_JS = """
if (_controllers) _controllers.set(el, ctrl);
}
var _targetControllers = typeof WeakMap !== "undefined" ? new WeakMap() : null;
function abortPreviousTarget(el) {
if (_targetControllers) {
var prev = _targetControllers.get(el);
if (prev) prev.abort();
}
}
function trackControllerTarget(el, ctrl) {
if (_targetControllers) _targetControllers.set(el, ctrl);
}
function newAbortController() {
return typeof AbortController !== "undefined" ? new AbortController() : { signal: null, abort: function() {} };
}
@@ -3769,12 +3784,6 @@ PLATFORM_ORCHESTRATION_JS = """
}
}
// --- Inline handlers ---
function bindInlineHandler(el, eventName, body) {
el.addEventListener(eventName, new Function("event", body));
}
// --- Preload binding ---
function bindPreload(el, events, debounceMs, fn) {
@@ -4088,7 +4097,24 @@ def fixups_js(has_html, has_sx, has_dom, has_signals=False):
PRIMITIVES["schedule-idle"] = scheduleIdle;
PRIMITIVES["invoke"] = invoke;
PRIMITIVES["error"] = function(msg) { throw new Error(msg); };
PRIMITIVES["filter"] = filter;''')
PRIMITIVES["filter"] = filter;
// DOM primitives for sx-on:* handlers and data-init scripts
if (typeof domBody === "function") PRIMITIVES["dom-body"] = domBody;
if (typeof domQuery === "function") PRIMITIVES["dom-query"] = domQuery;
if (typeof domQueryAll === "function") PRIMITIVES["dom-query-all"] = domQueryAll;
if (typeof domQueryById === "function") PRIMITIVES["dom-query-by-id"] = domQueryById;
if (typeof domSetAttr === "function") PRIMITIVES["dom-set-attr"] = domSetAttr;
if (typeof domGetAttr === "function") PRIMITIVES["dom-get-attr"] = domGetAttr;
if (typeof domRemoveAttr === "function") PRIMITIVES["dom-remove-attr"] = domRemoveAttr;
if (typeof domHasAttr === "function") PRIMITIVES["dom-has-attr?"] = domHasAttr;
if (typeof domAddClass === "function") PRIMITIVES["dom-add-class"] = domAddClass;
if (typeof domRemoveClass === "function") PRIMITIVES["dom-remove-class"] = domRemoveClass;
if (typeof domHasClass === "function") PRIMITIVES["dom-has-class?"] = domHasClass;
if (typeof domClosest === "function") PRIMITIVES["dom-closest"] = domClosest;
if (typeof domMatches === "function") PRIMITIVES["dom-matches?"] = domMatches;
if (typeof preventDefault_ === "function") PRIMITIVES["prevent-default"] = preventDefault_;
if (typeof elementValue === "function") PRIMITIVES["element-value"] = elementValue;
if (typeof domOuterHtml === "function") PRIMITIVES["dom-outer-html"] = domOuterHtml;''')
return "\n".join(lines)