A route mounting an island ships JavaScript, so reporting it as zero-JS
static would make the framework's performance accounting wrong.
Adds a separate needsIslandRuntime flag rather than reusing
needsClientRuntime: an island needs the island runtime, not WRNexus's
reactive runtime, and conflating them would ship the wrong bundle.
analyzeRuntimeRequirements takes island presence as an optional second
argument, so existing callers are unaffected.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
splitting:true keeps React in one shared chunk so a page with several
islands does not ship react-dom repeatedly.
Island .tsx is compiled against React's JSX runtime via a Bun onLoad
plugin. The repo's root tsconfig sets jsxImportSource to @wrnexus/core,
so islands would otherwise compile to the HTML-string renderer and never
mount. A @jsxImportSource pragma only affects the file carrying it, so
injecting one into the generated entry is not enough — the injection has
to happen per source file. App-authored islands stay plain .tsx.
The JSX test asserts built output rather than generated entry text,
because the entry-text assertion passed while the mechanism did not work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.wrn keeps resolution priority so existing components are unaffected
when a .tsx file shares their name.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Emits the data-wrn-island placeholder, parses client:* strategies, and
rejects non-serializable props at compile time via WRN-ISLAND-PROPS so
the serialization boundary fails where it is cheapest to fix.
Island names become URL path segments when the browser fetches the
island bundle, so they are validated with core's existing
isSafeIslandName rather than relying on escaping alone. This adds
@wrnexus/core to the compiler's dependencies; core has no dependencies
of its own, so no cycle is introduced.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DataTable replaces the 20-line Table scaffold entirely: columns, sorting,
filtering, pagination, selection, bulk actions, comparison layout, sticky
first column, custom HTML cells, and a remote source driven by a `request`
output rather than a function prop (props travel as HTML attributes, so a
function arrives as its own source text).
Toaster replaces the hand-rolled status div: tone icons, actions, hover
pause/resume and a progress bar.
Overlays audit -- Modal and Drawer declared aria-modal="true" but nothing
ever moved focus into the panel, so the @keydown handler on their root
never ran and closeOnEscape did nothing. Focus, focus restore, a Tab trap
and a body scroll lock now live in the reactive runtime, shared by both.
ContextMenu placed pointer menus by subtracting a guessed 340x420 from the
viewport, which pushed every menu that was not that size away from the
pointer; it now positions at the pointer and lets the anchored clamp pull
it back once it can be measured.
The reactive runtime size budget moves 150k -> 175k to cover anchored
overlays, dialog behaviour, the toaster and the DataTable client half.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>