@praxisjs/runtime
Changelog for @praxisjs/runtime — DOM renderer, component mounting, and reactive scopes.
@praxisjs/runtime
0.5.0
Bug fix: onToggle, onClose, and onCancel are now wired as event listeners.
These handlers were declared in DetailsHTMLAttributes and DialogHTMLAttributes but were absent from EVENT_MAP. The runtime was treating them as reactive getters instead of calling addEventListener. They now work correctly.
EVENT_MAP expanded from 24 to 82 entries.
New event categories wired by the runtime:
- Pointer —
onPointerDown,onPointerUp,onPointerMove,onPointerEnter,onPointerLeave,onPointerOver,onPointerOut,onPointerCancel,onGotPointerCapture,onLostPointerCapture - Mouse —
onMouseOver,onMouseOut - Drag —
onDrag,onDragEnter,onDragLeave - Form —
onBeforeInput,onSelect,onInvalid - Clipboard —
onCopy,onCut,onPaste - Composition (IME) —
onCompositionStart,onCompositionUpdate,onCompositionEnd - Resource —
onLoad,onError - Scroll —
onScrollEnd - Element-specific —
onBeforeToggle - Media —
onAbort,onCanPlay,onCanPlayThrough,onDurationChange,onEmptied,onEnded,onLoadedData,onLoadedMetadata,onLoadStart,onPause,onPlay,onPlaying,onProgress,onRateChange,onSeeked,onSeeking,onStalled,onSuspend,onTimeUpdate,onVolumeChange,onWaiting
0.4.1
Bug fix: disposed components no longer run stale mount callbacks.
If a component is disposed before the queued mount microtask runs, mountComponent now skips onMount and ref(instance). The unmount cleanup still runs and calls ref(null), preventing stale instance refs after early disposal.
Cleanup improvements for reactive children and portals.
Reactive child updates no longer register a new parent cleanup on every rerender. Portal cleanup also tolerates anchors that were removed externally before disposal, avoiding teardown errors when a target container is cleared outside PraxisJS.
0.4.0
onError return value is now mounted as fallback DOM.
When a component's render() throws, mountComponent now captures the return value of onError. If it returns a Node or Node[], those nodes are passed to mountChildren and inserted into the DOM in place of the failed render output. Returning null or void continues to produce an empty mount (previous behavior).
This pairs with the updated onError signature in @praxisjs/core — see its changelog for details.
0.2.19
New: Portal — renders a JSX subtree into a target DOM node outside the component's natural parent. Useful for modals, tooltips, toasts, and drawers that must escape overflow or stacking context constraints.
import { Portal } from '@praxisjs/runtime'
// Mounts children into document.body
<Portal>
<Modal />
</Portal>
// Mounts into a specific element or CSS selector
<Portal to="#toast-root">
<Toast message={this.message} />
</Portal>Portal integrates with PraxisJS's scope system — content is removed from the target automatically when the surrounding component or reactive condition unmounts. Reactive children update normally via fine-grained reactivity.
Internal: resolvePortalTarget exported as a named function (not re-exported from the package index) to allow direct unit testing of the SSR guard branch.
0.2.18
innerHTML prop support — <div innerHTML={html} /> now correctly sets element.innerHTML (DOM property assignment) instead of calling setAttribute. Supports reactive values: innerHTML={() => this.html}.
0.2.17
DOM patching optimizations — lower allocation and fewer reflows:
- Prop iteration uses
for...ininstead ofObject.entries(), avoiding an intermediate array per element mount. - Node insertion batched through
DocumentFragment— multiple nodes inserted with a singleinsertBeforecall. - Bulk node removal uses
Range.deleteContents()instead of individualremoveChildcalls. normalizeToNodesreplaced bycollectNodes(accumulates into a caller-supplied array), removing one allocation per reactive update.
0.2.16
Bug fix: reactive expressions ({() => ...}) inside components were silently dropping DOM updates.
mountReactive captured the DocumentFragment container by closure. After the fragment's nodes are transferred to the real DOM, the fragment is empty — so insertBefore on the stale parent reference had no effect. Fixed by always resolving the live DOM parent via end.parentNode.
0.2.9
Bug fix: mountComponent now runs inside untrack(). Static prop reads like label={this.count} inside a reactive context (e.g. the router) were accidentally subscribing the outer effect to those signals, causing the router to re-mount the component on every signal change and reset its state.
0.2.6
- CSS custom properties (
--*keys) are now applied viasetProperty(). - Scope cleanup errors are collected into
AggregateError— all cleanups run even when one throws.
0.2.0
Implemented mountChildren, mountComponent, and reactive scope management. Introduced StatefulComponent/StatelessComponent. Migrated to TC39 decorator API.
0.1.0
Initial beta release.