Releases: zeixcom/le-truc
Releases · zeixcom/le-truc
Version 0.16.3
Immutable
release. Only release title and notes can be modified.
What's Changed
Added
- New re-exports from
@zeix/cause-effect:createSignal,unown,untrack,isObjectOfType,SKIP_EQUALITY, and error classesReadonlySignalError,RequiredOwnerError,UnsetSignalValueError— previously omitted from Le Truc's public API surface.
Changed
@zeix/cause-effectupgraded to0.18.5: Addsunown()and fixes a scope disposal bug in components connected inside re-runnable effects (see Fixed below).form-checkbox,form-radiogroup, andform-spinbuttonexamples updated: All three examples now support controlled component usage, accepting externally managed state in addition to their built-in uncontrolled behaviour.
Fixed
- Scope disposal bug when
connectedCallbackfires inside a re-runnable effect:createScopeinside a reactive effect (e.g. a list-sync effect) registered its dispose on that effect's cleanup list. When the effect re-ran — for example because aMutationObserverfired — it disposed all child scopes including those of already-connected components, silently removing their live event listeners and reactive subscriptions. Fixed by wrapping theconnectedCallbackbody inunown(), detaching each component's scope from the surrounding effect's ownership tree so effect re-runs no longer dispose it.
Full Changelog: v0.16.2...v0.16.3
Version 0.16.2
Immutable
release. Only release title and notes can be modified.
What's Changed
Added
asParser(fn): Brands a custom parser withPARSER_BRANDsoisParser()can identify it reliably regardless offunction.length. Use this for any custom two-argument parser (especially those using default parameters or destructuring).asMethod(fn): Brands a side-effect initializer withMETHOD_BRAND, producing aMethodProducerthatdefineComponentdispatches explicitly rather than treating as aReader.isMethodProducer(value): Type guard that checks forMETHOD_BRAND. Replaces the old implicitisFunctionfallback for method producers.
Changed
isParser()checksPARSER_BRANDfirst: Falls back tofn.length >= 2for backward compatibility, but emits aconsole.warninDEV_MODEwhen the fallback path is taken. Migrate custom parsers toasParser()to silence the warning.defineComponentsignal dispatch is explicit: Initialization order is nowParser → MethodProducer → Reader → static/Signal. Previously, method producers and readers were both handled by anisFunctionbranch with no distinction.on()andpass()wrap their body increateScope(): Both effects now own a reactive scope internally. This ensures proper child-effect disposal and signal restoration when the component disconnects, without requiring callers to manage scopes.pass()captures and restores the original Slot signal on cleanup: When the parent disconnects, the child's Slot is restored to the signal it held beforepass()ran, so the child regains its own independent state after detachment.pass()is scoped to Le Truc components only: The[Reactive, callback]two-way binding form has been removed fromPassedProp. For non-Le Truc custom elements, usesetProperty()instead.RESETsentinel replaced byundefined:resolveReactive()now returnsundefinedon error.updateElementtreatsundefinedthe same way it treatedRESET— restoring the original DOM fallback value.resolveReactive()warns on missing property names inDEV_MODE: When a string reactive refers to a property that does not exist on the host, aconsole.warnis emitted. This catches typos for JavaScript consumers not covered by TypeScript'skeyof Pguard.EventHandlertype is now documented: JSDoc onEventHandlerexplains both the side-effect-only (void) and property-update-shortcut ({ prop: value }) return modes.on()JSDoc includes@exampleblocks for both forms.
Fixed
pass()no longer silently drops bindings on child detach: The original Slot signal is captured before replacement and restored on cleanup, preventing stale parent signals from persisting in detached children.pass()warns inDEV_MODEwhen target property is not Slot-backed: Emitsconsole.warnand skips the binding (instead of silently doing nothing) whenpass()is used on a non-Le Truc element.MethodProducercleanup correctly composed with effect cleanup: Cleanup functions returned by method producers are now composed with the surrounding effect cleanup indefineComponent, preventing disposal leaks.
Full Changelog: v0.16.1...v0.16.2
Version 0.16.1
Immutable
release. Only release title and notes can be modified.
What's Changed
Changed
createElementsMemomutation filtering: TheMutationObservercallback now uses acouldMatchhelper to filter mutations, only invalidating when added/removed nodes match or contain matches for the selector. This prevents spurious effect re-runs caused by mutations inside matched elements (e.g.,innerHTMLchanges on option buttons).createElementsMemocustomequals: The memo now compares arrays by element identity (length+every).- Effect system simplified:
runEffectsnow usescreateScope()to own all child effects. Dynamic collections are handled by a singlecreateEffect()whose ownership graph automatically disposes per-element effects on re-run. The formerrunElementsEffectsandrunElementEffectshelpers have been inlined.
Removed
runEffectsandrunElementEffectsremoved from public API: These were never intended for userland use and calling them directly could corrupt disposal.runEffectsremains as internal helper.
Fixed
innerHTMLon matched elements no longer destroys reactivity: SettinginnerHTMLon elements matched bycreateElementsMemo(e.g.,button[role="option"]) previously caused theMutationObserverto fire spuriously, re-running and disposing effects without properly re-attaching them. Fixed by combining mutation filtering with ownership-based cleanup.
Full Changelog: v0.16.0...v0.16.1
Version 0.16.0
Immutable
release. Only release title and notes can be modified.
What's Changed
Added
createElementsMemo(parent, selector): New function returning aMemo<E[]>of elements matching a CSS selector, backed by a lazyMutationObserverthat activates only when read from within a reactive effect.createEventsSensor(init, key, events): New function producing an event-drivenSensorfrom transformed event data, replacing the old Le Truc-specificcreateSensor.- New re-exports from
@zeix/cause-effectv0.18:createCollection,createList,createMemo,createMutableSignal,createScope,createSensor,createTask,createStore,match, and their associated types and type guards. - New type exports:
MethodProducer,ContextCallback,UpdateOperation,SensorEventHandler,AllElements,FirstElement,ElementFromSelector, and CSS selector type utilities (ElementFromSingleSelector,ElementsFromSelectorArray,ExtractRightmostSelector,ExtractTag,KnownTag,SplitByComma,TrimWhitespace). MaybeSignal<T>now acceptsTaskCallback<T>, enabling async task-based property initializers.
Changed
@zeix/cause-effectupgraded from^0.16.1to^0.18.3. This drives most API changes below.- Element queries use
Memo<E[]>instead ofCollection<E>: Theall()query helper returnsMemo<ElementFromSelector<S>[]>. TheUItype is nowRecord<string, Element | Memo<Element[]>>. pass()effect rewritten to use Slot signals: UsesgetSignals()andslot.replace()instead of overwriting property descriptors. Works regardless of descriptor configurability and avoids state leaks on cleanup.requestContextreturnsMemo<T>instead ofComputed<T>.- Component property accessors use Slot signals:
#setAccessorindefineComponentnow usescreateSlotfor mutable signals, withslot.replace()for signal swapping. Computedrenamed toMemoandComputedCallbackrenamed toMemoCallbackin type signatures (from upstreamcause-effectv0.18).updateElement: The unset sentinel changed fromUNSETtonull.- Eliminated
index.dev.ts: Bothindex.js(minified) andindex.dev.js(unminified) are now built from the singleindex.tsentry point.
Removed
src/signals/collection.ts: The Le Truc-specificCollectionsignal type withMutationObserver,Proxy, and add/remove listeners has been removed. Element collection functionality is replaced bycreateElementsMemo.Collectionis now re-exported fromcause-effect(a different, upstream type).src/signals/sensor.ts: The Le Truc-specificcreateSensorandSensorEventstype have been removed, replaced bycreateEventsSensorand the upstreamcreateSensorfromcause-effect.- Removed re-exports:
diff,resolve,toError,toSignal,UNSET,isAbortError,isNumber,isRecordOrArray,isString,isSymbol,Computed,ComputedCallback,DiffResult,ResolveResult,StoreKeyExistsError,StoreKeyRangeError,StoreKeyReadonlyError.
Fixed
pass()no longer requiresconfigurableproperty descriptors on the target element and no longer leaks state on cleanup.pass()now warns in dev mode when a property doesn't exist on the target (likely a typo) or has no Slot (non-Le Truc element), instead of silently doing nothing.dangerouslySetInnerHTMLscript cloning now copies all functional and security-hardening attributes (src,async,defer,nomodule,crossorigin,integrity,referrerpolicy,fetchpriority) instead of onlytype. External scripts withsrcno longer become empty inline scripts.createEventsSensornow reacts to collection changes: ForMemo-backed element collections,getTarget()reads the current elements on each event instead of a stale snapshot captured at sensor creation time. Static single-element targets use a fast path with no array overhead.- Dependency resolution no longer swallows errors silently:
DependencyTimeoutErroris now logged viaconsole.warnin dev mode. Previously, the.catchhandler discarded all errors without any output. - Dependency resolution filters out already-defined components: A microtask defer before
Promise.racefilters out components that were defined synchronously after queries ran (e.g. co-bundled components), avoiding unnecessary waits. - Dependency timeout increased from 50ms to 200ms: Now that structural (CSS-only) custom elements and co-bundled components are filtered out, the timeout only applies to genuinely pending async dependencies and gives them a more realistic window.
module-dialogeffect cleanup no longer resetshost.opentofalse, which was causing all dialog tests to fail.form-listboxkeyboard navigation now uses directquerySelectorAllinstead of a watchedMemothat never activated itsMutationObserveroutside reactive contexts.
Full Changelog: v0.15.0...v0.16.0
Version 0.15.0
Immutable
release. Only release title and notes can be modified.
What's Changed
- First release under the new name "Le Truc" (was UIElement in v0.14.2: https://github.com/zeixcom/ui-element)
- Release Candidate for Version 1.0