sx-tools: WASM kernel updates, TW/CSSX rework, content refresh, new debugging tools
Build tooling: updated OCaml bootstrapper, compile-modules, bundle.sh, sx-build-all. WASM browser: rebuilt sx_browser.bc.js/wasm, sx-platform-2.js, .sxbc bytecode files. CSSX/Tailwind: reworked cssx.sx templates and tw-layout, added tw-type support. Content: refreshed essays, plans, geography, reactive islands, docs, demos, handlers. New tools: bisect_sxbc.sh, test-spa.js, render-trace.sx, morph playwright spec. Tests: added test-match.sx, test-examples.sx, updated test-tw.sx and web tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,6 +166,22 @@
|
||||
document.cookie = args[0] + "=" + encodeURIComponent(args[1] || "") + ";path=/;max-age=31536000;SameSite=Lax";
|
||||
});
|
||||
|
||||
// IntersectionObserver — native JS to avoid bytecode callback issues
|
||||
K.registerNative("observe-intersection", function(args) {
|
||||
var el = args[0], callback = args[1], once = args[2], delay = args[3];
|
||||
var obs = new IntersectionObserver(function(entries) {
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entries[i].isIntersecting) {
|
||||
var d = (delay && delay !== null) ? delay : 0;
|
||||
setTimeout(function() { K.callFn(callback, []); }, d);
|
||||
if (once) obs.unobserve(el);
|
||||
}
|
||||
}
|
||||
});
|
||||
obs.observe(el);
|
||||
return obs;
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// Load SX web libraries and adapters
|
||||
// ================================================================
|
||||
@@ -398,68 +414,6 @@
|
||||
"children:", islands[j].children.length);
|
||||
}
|
||||
console.log("[sx] boot done");
|
||||
|
||||
// sx-on: inline event handlers — bind from JS because the WASM
|
||||
// CSS selector [sx-on\:] doesn't match. Uses MutationObserver to
|
||||
// also catch elements added after boot (e.g. from swaps).
|
||||
function _bindSxOn(root) {
|
||||
var all = (root || document).querySelectorAll('*');
|
||||
for (var k = 0; k < all.length; k++) {
|
||||
var el = all[k];
|
||||
if (el._sxOnBound) continue;
|
||||
var attrs = el.attributes;
|
||||
var hasSxOn = false;
|
||||
for (var a = 0; a < attrs.length; a++) {
|
||||
var aname = attrs[a].name;
|
||||
if (aname.indexOf('sx-on:') === 0) {
|
||||
hasSxOn = true;
|
||||
var evtName = aname.slice(6);
|
||||
// HTML lowercases attrs: afterSwap → afterswap.
|
||||
// Engine dispatches camelCase: sx:afterSwap.
|
||||
// Listen for both forms.
|
||||
var evtName2 = null;
|
||||
if (evtName.indexOf('after') === 0 || evtName.indexOf('before') === 0) {
|
||||
evtName2 = 'sx:' + evtName; // lowercase form
|
||||
// Also try camelCase form
|
||||
var camel = evtName.replace(/swap|request|settle/gi, function(m) {
|
||||
return m.charAt(0).toUpperCase() + m.slice(1);
|
||||
});
|
||||
evtName = 'sx:' + camel;
|
||||
}
|
||||
(function(el2, evt, evt2, code) {
|
||||
var handler = function(e) {
|
||||
try { new Function('event', code).call(el2, e); }
|
||||
catch(err) { console.warn('[sx] sx-on:' + evt + ' error:', err); }
|
||||
};
|
||||
el2.addEventListener(evt, handler);
|
||||
if (evt2) el2.addEventListener(evt2, handler);
|
||||
})(el, evtName, evtName2, attrs[a].value);
|
||||
}
|
||||
}
|
||||
if (hasSxOn) el._sxOnBound = true;
|
||||
}
|
||||
}
|
||||
_bindSxOn(document);
|
||||
// Re-bind after swaps
|
||||
document.addEventListener('sx:afterSwap', function(e) {
|
||||
if (e.target) _bindSxOn(e.target);
|
||||
});
|
||||
|
||||
// Global keyboard shortcut dispatch — WASM host-callbacks on
|
||||
// document/body don't fire, so handle from:body keyboard
|
||||
// triggers in JS and call execute-request via the SX engine.
|
||||
document.addEventListener("keyup", function(e) {
|
||||
if (e.target && e.target.matches && e.target.matches("input,textarea,select")) return;
|
||||
var sel = '[sx-trigger*="key==\'' + e.key + '\'"]';
|
||||
var els = document.querySelectorAll(sel);
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
var el = els[i];
|
||||
if (!el.id) el.id = "_sx_kbd_" + Math.random().toString(36).slice(2);
|
||||
try {
|
||||
K.eval('(execute-request (dom-query-by-id "' + el.id + '") nil nil)');
|
||||
} catch(err) { console.warn("[sx] keyboard dispatch error:", err); }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user