what-core 0.12.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{V as m,c as f,e as p,h as w,l as b}from"./chunk-M5GDJRVX.min.js";import{a as h}from"./chunk-O3SKPRTY.min.js";var l=null;function E(){return typeof document<"u"&&(l=document.createElement("div"),l.id="test-root",document.body.appendChild(l)),l}function v(){l&&(l.innerHTML="",l.parentNode&&l.parentNode.removeChild(l),l=null)}function N(e,t={}){let{container:n}=t,o=n||E();if(!o)throw new Error("No DOM container available. Are you running in Node.js without jsdom?");let s=m(e,o);return{container:o,unmount:s,getByText:r=>d(o,r),getByTestId:r=>o.querySelector(`[data-testid="${r}"]`),getByRole:r=>o.querySelector(`[role="${r}"]`),getAllByText:r=>g(o,r),queryByText:r=>d(o,r),queryByTestId:r=>o.querySelector(`[data-testid="${r}"]`),debug:()=>console.log(o.innerHTML),findByText:(r,u)=>y(()=>d(o,r),{timeout:u}),findByTestId:(r,u)=>y(()=>o.querySelector(`[data-testid="${r}"]`),{timeout:u})}}function q(e,t){let n=E();if(!n)throw new Error("No DOM container available. Are you running in Node.js without jsdom?");let o={},s=null,r;return b(u=>{s=u;let c=h(e,t||{});r=m(c,n)}),{container:n,signals:new Proxy(o,{get(u,c){if(c in u)return u[c]},set(u,c,i){return u[c]=i,!0}}),update(){w()},unmount(){r&&r(),s&&s(),v()},getByText:u=>d(n,u),getByTestId:u=>n.querySelector(`[data-testid="${u}"]`),queryByText:u=>d(n,u),debug:()=>console.log(n.innerHTML)}}function C(){w()}function M(e){let t=[],n=[],o=f,s=new Map,r=i=>{t.includes(i)||t.push(i)},u=i=>{n.includes(i)||n.push(i)},c;return b(i=>{c=i;let a=p(()=>{e()})}),c&&c(),{accessed:t,written:n}}function D(e,t){let n=[t],o=0,s=f(t,e),r=s.set;s.set=function(i){let a=typeof i=="function"?i(s.peek()):i;return Object.is(s.peek(),a)||(o++,n.push(a)),r(a)};let u=s,c=function(...i){if(i.length===0)return u();let a=typeof i[0]=="function"?i[0](u.peek()):i[0];return Object.is(u.peek(),a)||(o++,n.push(a)),u(a)};return c._signal=!0,c.peek=s.peek,c.set=s.set,c.subscribe=s.subscribe,s._debugName&&(c._debugName=s._debugName),s._subs&&(c._subs=s._subs),Object.defineProperty(c,"history",{get(){return n}}),Object.defineProperty(c,"setCount",{get(){return o}}),c.reset=function(i){let a=i!==void 0?i:t;n.length=0,n.push(a),o=0,u(a)},c}function d(e,t){let n=t instanceof RegExp?t:null,o=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null,!1);for(;o.nextNode();){let s=o.currentNode;if(n?n.test(s.textContent):s.textContent.includes(t))return s.parentElement}return null}function g(e,t){let n=[],o=t instanceof RegExp?t:null,s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null,!1);for(;s.nextNode();){let r=s.currentNode;(o?o.test(r.textContent):r.textContent.includes(t))&&n.push(r.parentElement)}return n}var H={click(e){let t=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:typeof window<"u"?window:void 0});return e.dispatchEvent(t),t},change(e,t){e.value=t;let n=new Event("input",{bubbles:!0});e.dispatchEvent(n);let o=new Event("change",{bubbles:!0});return e.dispatchEvent(o),o},input(e,t){e.value=t;let n=new Event("input",{bubbles:!0});return e.dispatchEvent(n),n},submit(e){let t=new Event("submit",{bubbles:!0,cancelable:!0});return e.dispatchEvent(t),t},focus(e){e.focus();let t=new FocusEvent("focus",{bubbles:!0});return e.dispatchEvent(t),t},blur(e){e.blur();let t=new FocusEvent("blur",{bubbles:!0});return e.dispatchEvent(t),t},keyDown(e,t,n={}){let o=new KeyboardEvent("keydown",{bubbles:!0,cancelable:!0,key:t,...n});return e.dispatchEvent(o),o},keyUp(e,t,n={}){let o=new KeyboardEvent("keyup",{bubbles:!0,cancelable:!0,key:t,...n});return e.dispatchEvent(o),o},mouseEnter(e){let t=new MouseEvent("mouseenter",{bubbles:!0});return e.dispatchEvent(t),t},mouseLeave(e){let t=new MouseEvent("mouseleave",{bubbles:!0});return e.dispatchEvent(t),t}};async function y(e,t={}){let{timeout:n=1e3,interval:o=50}=t,s=Date.now();for(;Date.now()-s<n;){try{let r=e();if(r)return r}catch{}await new Promise(r=>setTimeout(r,o))}throw new Error(`waitFor timed out after ${n}ms`)}async function O(e,t={}){let{timeout:n=1e3,interval:o=50}=t,s=Date.now(),r=e();if(!r)throw new Error("Element not found");for(;Date.now()-s<n;){if(r=e(),!r)return;await new Promise(u=>setTimeout(u,o))}throw new Error(`Element still present after ${n}ms`)}async function _(e){let t=await e();return w(),await new Promise(n=>queueMicrotask(n)),await new Promise(n=>setTimeout(n,0)),t}function F(e){let t=f(e),n=[e];return p(()=>{n.push(t())}),{signal:t,get value(){return t()},set value(o){t.set(o)},history:n,reset(){n.length=0,n.push(t())}}}function R(e="MockComponent"){let t=[];function n(o){return t.push({props:o,timestamp:Date.now()}),h("div",{"data-testid":`mock-${e}`},JSON.stringify(o,null,2))}return n.displayName=e,n.calls=t,n.lastCall=()=>t[t.length-1],n.reset=()=>{t.length=0},n}var j={toBeInTheDocument(e){if(!e||!e.parentNode)throw new Error("Expected element to be in the document")},toHaveTextContent(e,t){if(!e)throw new Error("Element not found");let n=e.textContent;if(!(t instanceof RegExp?t.test(n):n.includes(t)))throw new Error(`Expected "${n}" to contain "${t}"`)},toHaveAttribute(e,t,n){if(!e)throw new Error("Element not found");let o=e.getAttribute(t);if(n!==void 0&&o!==n)throw new Error(`Expected attribute "${t}" to be "${n}", got "${o}"`);if(n===void 0&&o===null)throw new Error(`Expected element to have attribute "${t}"`)},toHaveClass(e,t){if(!e)throw new Error("Element not found");if(!e.classList.contains(t))throw new Error(`Expected element to have class "${t}"`)},toBeVisible(e){if(!e)throw new Error("Element not found");let t=window.getComputedStyle(e);if(t.display==="none"||t.visibility==="hidden"||t.opacity==="0")throw new Error("Expected element to be visible")},toBeDisabled(e){if(!e)throw new Error("Element not found");if(!e.disabled)throw new Error("Expected element to be disabled")},toHaveValue(e,t){if(!e)throw new Error("Element not found");if(e.value!==t)throw new Error(`Expected value to be "${t}", got "${e.value}"`)}},A={getByText:e=>d(document.body,e),getByTestId:e=>document.querySelector(`[data-testid="${e}"]`),getByRole:e=>document.querySelector(`[role="${e}"]`),getAllByText:e=>g(document.body,e),queryByText:e=>d(document.body,e),queryByTestId:e=>document.querySelector(`[data-testid="${e}"]`),debug:()=>console.log(document.body.innerHTML)};export{_ as act,v as cleanup,F as createTestSignal,j as expect,H as fireEvent,C as flushEffects,R as mockComponent,D as mockSignal,N as render,q as renderTest,A as screen,E as setupDOM,M as trackSignals,y as waitFor,O as waitForElementToBeRemoved};
1
+ import{W as x,a as k,b as _,c as E,d as b,f as y,i as h,m as g}from"./chunk-OKM3GKVP.min.js";import{a as v}from"./chunk-O3SKPRTY.min.js";var f=null;function N(){return typeof document<"u"&&(f=document.createElement("div"),f.id="test-root",document.body.appendChild(f)),f}function q(){f&&(f.innerHTML="",f.parentNode&&f.parentNode.removeChild(f),f=null)}function H(e,t={}){let{container:n}=t,o=n||N();if(!o)throw new Error("No DOM container available. Are you running in Node.js without jsdom?");let s=x(e,o);return{container:o,unmount:s,getByText:r=>p(o,r),getByTestId:r=>o.querySelector(`[data-testid="${r}"]`),getByRole:r=>o.querySelector(`[role="${r}"]`),getAllByText:r=>$(o,r),queryByText:r=>p(o,r),queryByTestId:r=>o.querySelector(`[data-testid="${r}"]`),debug:()=>console.log(o.innerHTML),findByText:(r,u)=>S(()=>p(o,r),{timeout:u}),findByTestId:(r,u)=>S(()=>o.querySelector(`[data-testid="${r}"]`),{timeout:u})}}function O(e,t){let n=N();if(!n)throw new Error("No DOM container available. Are you running in Node.js without jsdom?");let o={},s=null,r;return g(u=>{s=u;let c=v(e,t||{});r=x(c,n)}),{container:n,signals:new Proxy(o,{get(u,c){if(c in u)return u[c]},set(u,c,i){return u[c]=i,!0}}),update(){h()},unmount(){r&&r(),s&&s(),q()},getByText:u=>p(n,u),getByTestId:u=>n.querySelector(`[data-testid="${u}"]`),queryByText:u=>p(n,u),debug:()=>console.log(n.innerHTML)}}function R(){h()}var B="(unnamed)";function F(e){if(!k)throw new Error('[what] trackSignals() requires a development build. Signal debug names and subscriber back-references are stripped in production, so there is nothing to report. Run your tests with NODE_ENV !== "production".');let t=[],n=[],o=(l,d)=>{l.includes(d)||l.push(d)},s=_,r={...s||{},onSignalUpdate(l){o(n,l?._debugName||B),s?.onSignalUpdate?.(l)}};delete r.__isPreinstallBuffer;let u=b(0,"__trackSignals_probe__"),c={current:null},i=null,a=(l,d)=>{for(let w of l||[]){if(d.has(w))continue;d.add(w);let m=w._signalOwner;if(m){m!==u&&o(t,m._debugName||B);continue}let T=w._owner;T?.deps&&a(T.deps,d)}};E(r);try{g(d=>{c.current=d,y(()=>{u(),e()})});let l=new Set;for(let d of u._subs)a(d.deps,l)}catch(l){i=l}finally{c.current?.(),E(s)}if(i)throw i;return{accessed:t,written:n}}function A(e,t){let n=[t],o=0,s=b(t,e),r=s.set;s.set=function(i){let a=typeof i=="function"?i(s.peek()):i;return Object.is(s.peek(),a)||(o++,n.push(a)),r(a)};let u=s,c=function(...i){if(i.length===0)return u();let a=typeof i[0]=="function"?i[0](u.peek()):i[0];return Object.is(u.peek(),a)||(o++,n.push(a)),u(a)};return c._signal=!0,c.peek=s.peek,c.set=s.set,c.subscribe=s.subscribe,s._debugName&&(c._debugName=s._debugName),s._subs&&(c._subs=s._subs),Object.defineProperty(c,"history",{get(){return n}}),Object.defineProperty(c,"setCount",{get(){return o}}),c.reset=function(i){let a=i!==void 0?i:t;n.length=0,n.push(a),o=0,u(a)},c}function p(e,t){let n=t instanceof RegExp?t:null,o=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);for(;o.nextNode();){let s=o.currentNode,r=s.textContent||"";if(n?n.test(r):r.includes(t))return s.parentElement}return null}function $(e,t){let n=[],o=t instanceof RegExp?t:null,s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);for(;s.nextNode();){let r=s.currentNode,u=r.textContent||"";(o?o.test(u):u.includes(t))&&n.push(r.parentElement)}return n}var P={click(e){let t=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:typeof window<"u"?window:void 0});return e.dispatchEvent(t),t},change(e,t){e.value=t;let n=new Event("input",{bubbles:!0});e.dispatchEvent(n);let o=new Event("change",{bubbles:!0});return e.dispatchEvent(o),o},input(e,t){e.value=t;let n=new Event("input",{bubbles:!0});return e.dispatchEvent(n),n},submit(e){let t=new Event("submit",{bubbles:!0,cancelable:!0});return e.dispatchEvent(t),t},focus(e){e.focus();let t=new FocusEvent("focus",{bubbles:!0});return e.dispatchEvent(t),t},blur(e){e.blur();let t=new FocusEvent("blur",{bubbles:!0});return e.dispatchEvent(t),t},keyDown(e,t,n={}){let o=new KeyboardEvent("keydown",{bubbles:!0,cancelable:!0,key:t,...n});return e.dispatchEvent(o),o},keyUp(e,t,n={}){let o=new KeyboardEvent("keyup",{bubbles:!0,cancelable:!0,key:t,...n});return e.dispatchEvent(o),o},mouseEnter(e){let t=new MouseEvent("mouseenter",{bubbles:!0});return e.dispatchEvent(t),t},mouseLeave(e){let t=new MouseEvent("mouseleave",{bubbles:!0});return e.dispatchEvent(t),t}};async function S(e,t={}){let{timeout:n=1e3,interval:o=50}=t,s=Date.now();for(;Date.now()-s<n;){try{let r=e();if(r)return r}catch{}await new Promise(r=>setTimeout(r,o))}throw new Error(`waitFor timed out after ${n}ms`)}async function j(e,t={}){let{timeout:n=1e3,interval:o=50}=t,s=Date.now(),r=e();if(!r)throw new Error("Element not found");for(;Date.now()-s<n;){if(r=e(),!r)return;await new Promise(u=>setTimeout(u,o))}throw new Error(`Element still present after ${n}ms`)}async function I(e){let t=await e();return h(),await new Promise(n=>queueMicrotask(()=>n())),await new Promise(n=>setTimeout(()=>n(),0)),t}function L(e){let t=b(e),n=[e];return y(()=>{n.push(t())}),{signal:t,get value(){return t()},set value(o){t.set(o)},history:n,reset(){n.length=0,n.push(t())}}}function V(e="MockComponent"){let t=[];function n(o){return t.push({props:o,timestamp:Date.now()}),v("div",{"data-testid":`mock-${e}`},JSON.stringify(o,null,2))}return n.displayName=e,n.calls=t,n.lastCall=()=>t[t.length-1],n.reset=()=>{t.length=0},n}var U={toBeInTheDocument(e){if(!e||!e.parentNode)throw new Error("Expected element to be in the document")},toHaveTextContent(e,t){if(!e)throw new Error("Element not found");let n=e.textContent;if(!(t instanceof RegExp?t.test(n):n.includes(t)))throw new Error(`Expected "${n}" to contain "${t}"`)},toHaveAttribute(e,t,n){if(!e)throw new Error("Element not found");let o=e.getAttribute(t);if(n!==void 0&&o!==n)throw new Error(`Expected attribute "${t}" to be "${n}", got "${o}"`);if(n===void 0&&o===null)throw new Error(`Expected element to have attribute "${t}"`)},toHaveClass(e,t){if(!e)throw new Error("Element not found");if(!e.classList.contains(t))throw new Error(`Expected element to have class "${t}"`)},toBeVisible(e){if(!e)throw new Error("Element not found");let t=window.getComputedStyle(e);if(t.display==="none"||t.visibility==="hidden"||t.opacity==="0")throw new Error("Expected element to be visible")},toBeDisabled(e){if(!e)throw new Error("Element not found");if(!e.disabled)throw new Error("Expected element to be disabled")},toHaveValue(e,t){if(!e)throw new Error("Element not found");if(e.value!==t)throw new Error(`Expected value to be "${t}", got "${e.value}"`)}},W={getByText:e=>p(document.body,e),getByTestId:e=>document.querySelector(`[data-testid="${e}"]`),getByRole:e=>document.querySelector(`[role="${e}"]`),getAllByText:e=>$(document.body,e),queryByText:e=>p(document.body,e),queryByTestId:e=>document.querySelector(`[data-testid="${e}"]`),debug:()=>console.log(document.body.innerHTML)};export{I as act,q as cleanup,L as createTestSignal,U as expect,P as fireEvent,R as flushEffects,V as mockComponent,A as mockSignal,H as render,O as renderTest,W as screen,N as setupDOM,F as trackSignals,S as waitFor,j as waitForElementToBeRemoved};
package/index.d.ts CHANGED
@@ -52,10 +52,17 @@ export function onRootCleanup(fn: () => void): void;
52
52
  // --- Virtual DOM ---
53
53
 
54
54
  export type PrimitiveChild = string | number | boolean | null | undefined;
55
- export type VNodeChild = PrimitiveChild | VNode | (() => VNodeChild) | VNodeChild[];
55
+
56
+ // `VNode<any>`, not `VNode`. VNode is invariant in P (its `tag` holds a
57
+ // `Component<P>`, whose parameter position is contravariant under
58
+ // strictFunctionTypes), so `VNode` — which means `VNode<Record<string, any>>` —
59
+ // rejects every specifically-typed node. `h('div', {}, h('h1', { style: '' }))`
60
+ // did not compile for any TypeScript user before 0.12.5, and neither did
61
+ // passing that tree to mount().
62
+ export type VNodeChild = PrimitiveChild | VNode<any> | (() => VNodeChild) | VNodeChild[];
56
63
 
57
64
  /** A component may legitimately render nothing, so `null` is part of the contract. */
58
- export type Component<P = {}> = ((props: P & { children?: VNodeChild }) => VNode | null) & {
65
+ export type Component<P = {}> = ((props: P & { children?: VNodeChild }) => VNode<any> | null) & {
59
66
  /**
60
67
  * Opt out of realizing compiled children before the component runs.
61
68
  *
@@ -89,7 +96,7 @@ export function html(strings: TemplateStringsArray, ...values: any[]): VNode | V
89
96
 
90
97
  // --- DOM ---
91
98
 
92
- export function mount(vnode: VNodeChild, container: string | Element): () => void;
99
+ export function mount(vnode: VNodeChild, container: string | Element | DocumentFragment): () => void;
93
100
 
94
101
  /** Attach reactive bindings to server-rendered DOM instead of creating it. */
95
102
  export function hydrate(vnode: VNodeChild, container: Element): Node | null;
@@ -867,6 +874,15 @@ export interface ErrorCodeDefinition {
867
874
 
868
875
  export const ERROR_CODES: Record<string, ErrorCodeDefinition>;
869
876
 
877
+ /**
878
+ * Look up a catalogue entry by its `ERR_*` code.
879
+ *
880
+ * Errors thrown outside what-core carry only their code — the suggestion and
881
+ * the worked example live once, in the catalogue, so that the client bundle
882
+ * does not have to ship the prose. This is how they are recovered.
883
+ */
884
+ export function getErrorDefinition(code: string): ErrorCodeDefinition | undefined;
885
+
870
886
  export interface WhatErrorJSON {
871
887
  code: string;
872
888
  message: string;
@@ -965,3 +981,24 @@ export function getMountedComponents(): unknown[];
965
981
  export function registerSignal(sig: unknown): void;
966
982
  export function unregisterSignal(sig: unknown): void;
967
983
  export function getActiveSignals(): unknown[];
984
+
985
+ // --- Internal cross-package exports ---
986
+ // Underscore-prefixed names are not public API and carry no compatibility
987
+ // promise. They are declared here because sibling packages in this repo import
988
+ // them across the package boundary (what-server, what-text), and an
989
+ // undeclared cross-package import is exactly the rename that ships broken:
990
+ // `hygiene:types` skips `_`-prefixed names in its reverse direction, so
991
+ // nothing else would have caught it. Application code should not use these.
992
+
993
+ /** @internal Used by what-server. True for `aria-*` and `data-*` attribute names. */
994
+ export function _isAriaAttr(name: string): boolean;
995
+ /** @internal Used by what-server. Opens an SSR component scope. */
996
+ export function _beginComponentSSR(...args: unknown[]): unknown;
997
+ /** @internal Used by what-server. Closes the scope opened by `_beginComponentSSR`. */
998
+ export function _endComponentSSR(...args: unknown[]): unknown;
999
+ /** @internal Used by what-server. The keyed-array mapping `<For>` compiles down to. */
1000
+ export function _mapArrayToArray(...args: unknown[]): unknown;
1001
+ /** @internal Used by what-server/node. Installs the Node AsyncLocalStorage backend. */
1002
+ export function __installServerContextStorage(storage: unknown): void;
1003
+ /** @internal Used by what-text. Lets the text engine intercept text-node insertion. */
1004
+ export function _setTextInsertHook(hook: unknown): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-core",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
4
4
  "description": "What Framework - Signal-based UI framework built for AI agents",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/render.d.ts CHANGED
@@ -42,3 +42,10 @@ export function isHydrating(): boolean;
42
42
  // SVG counterpart to template(): elements are created in the SVG namespace, which
43
43
  // a plain innerHTML template cannot do.
44
44
  export function svgTemplate(html: string): () => Element;
45
+
46
+ /**
47
+ * @internal The component-call helper the compiler emits for `<Component />`.
48
+ * Re-exported by what-framework/render so compiled output can import it from
49
+ * the package a scaffolded app actually depends on.
50
+ */
51
+ export function _$createComponent(component: unknown, props?: unknown, ...args: unknown[]): unknown;
package/src/a11y.js CHANGED
@@ -21,7 +21,7 @@ export function useFocus() {
21
21
  return {
22
22
  current: () => focusedElement(),
23
23
  focus: (element) => element?.focus(),
24
- blur: () => document.activeElement?.blur(),
24
+ blur: () => /** @type {HTMLElement | null} */ (document.activeElement)?.blur(),
25
25
  };
26
26
  }
27
27
 
@@ -241,7 +241,7 @@ export function SkipLink({ href = '#main', children = 'Skip to content' }) {
241
241
  class: 'what-skip-link',
242
242
  onClick: (e) => {
243
243
  e.preventDefault();
244
- const target = document.querySelector(href);
244
+ const target = /** @type {HTMLElement | null} */ (document.querySelector(href));
245
245
  if (target) {
246
246
  target.focus();
247
247
  target.scrollIntoView();
@@ -683,7 +683,7 @@ export function useDescribedBy(description) {
683
683
 
684
684
  // --- Labelledby ---
685
685
 
686
- export function useLabelledBy(label) {
686
+ export function useLabelledBy(_label) {
687
687
  const id = useId('label');
688
688
 
689
689
  return {
@@ -8,7 +8,7 @@ import { getCollectedErrors } from './errors.js';
8
8
  // --- Version ---
9
9
  // Keep in sync with packages/core/package.json (checked by
10
10
  // core/test/guardrails.test.js so it can't silently go stale again).
11
- const VERSION = '0.12.4';
11
+ const VERSION = '0.13.0';
12
12
 
13
13
  // --- Component Registry ---
14
14
  // Tracks mounted components for agent inspection.
package/src/animation.js CHANGED
@@ -213,7 +213,7 @@ export function useTransition(options = {}) {
213
213
  isTransitioning.set(true);
214
214
  progress.set(0);
215
215
 
216
- return new Promise((resolve) => {
216
+ return /** @type {Promise<void>} */ (new Promise((resolve) => {
217
217
  const startTime = performance.now();
218
218
 
219
219
  function tick(time) {
@@ -231,7 +231,7 @@ export function useTransition(options = {}) {
231
231
  }
232
232
 
233
233
  requestAnimationFrame(tick);
234
- });
234
+ }));
235
235
  }
236
236
 
237
237
  return {
@@ -339,7 +339,7 @@ export function useGesture(element, handlers = {}) {
339
339
  }
340
340
  }
341
341
 
342
- function handleEnd(e) {
342
+ function handleEnd(_e) {
343
343
  if (!state.isDragging.peek()) return;
344
344
 
345
345
  if (longPressTimer) {
@@ -453,7 +453,6 @@ export function useGesture(element, handlers = {}) {
453
453
 
454
454
  export function useAnimatedValue(initialValue) {
455
455
  const value = signal(initialValue);
456
- const animations = [];
457
456
 
458
457
  return {
459
458
  value: () => value(),
@@ -531,7 +530,7 @@ export function createTransitionClasses(name) {
531
530
  export async function cssTransition(element, name, type = 'enter', duration = 300) {
532
531
  const classes = createTransitionClasses(name);
533
532
 
534
- return new Promise((resolve) => {
533
+ return /** @type {Promise<void>} */ (new Promise((resolve) => {
535
534
  scheduleWrite(() => {
536
535
  // Initial state
537
536
  element.classList.add(classes[type]);
@@ -554,5 +553,5 @@ export async function cssTransition(element, name, type = 'enter', duration = 30
554
553
  });
555
554
  });
556
555
  });
557
- });
556
+ }));
558
557
  }
package/src/components.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // memo, lazy, Suspense, ErrorBoundary
3
3
 
4
4
  import { h } from './h.js';
5
- import { signal, effect, untrack, __DEV__ } from './reactive.js';
5
+ import { signal, __DEV__ } from './reactive.js';
6
6
  import { isServerRender } from './server-context.js';
7
7
 
8
8
  // Legacy errorBoundaryStack removed — tree-based resolution via _parentCtx._errorBoundary
package/src/data.js CHANGED
@@ -288,16 +288,7 @@ export function useFetch(url, options = {}) {
288
288
  // Stale-while-revalidate pattern with caching
289
289
 
290
290
  export function useSWR(rawKey, fetcher, options = {}) {
291
- const {
292
- revalidateOnFocus = true,
293
- revalidateOnReconnect = true,
294
- refreshInterval = 0,
295
- dedupingInterval = 2000,
296
- fallbackData,
297
- onSuccess,
298
- onError,
299
- suspense = false,
300
- } = options;
291
+ const { revalidateOnFocus = true, revalidateOnReconnect = true, refreshInterval = 0, dedupingInterval = 2000, fallbackData, onSuccess, onError } = options;
301
292
 
302
293
  // Support null/undefined/false key for conditional/dependent fetching
303
294
  // When key is falsy, don't fetch — return idle state
package/src/dom.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // Components run ONCE. Signals create individual DOM effects.
3
3
  // No VDOM reconciler, no diffing — direct DOM manipulation driven by signals.
4
4
 
5
- import { effect, batch, untrack, signal, __DEV__, __devtools } from './reactive.js';
6
- import { reportError, _injectGetCurrentComponent, shallowEqual } from './components.js';
5
+ import { effect, untrack, signal, __DEV__, __devtools } from './reactive.js';
6
+ import { reportError, _injectGetCurrentComponent } from './components.js';
7
7
  import { _setComponentRef } from './helpers.js';
8
8
  // SVG elements that need namespace
9
9
  const SVG_ELEMENTS = new Set([
@@ -119,7 +119,7 @@ function disposeComponent(ctx) {
119
119
  // Run effect disposals
120
120
  if (ctx.effects) {
121
121
  for (const dispose of ctx.effects) {
122
- try { dispose(); } catch (e) { /* already disposed */ }
122
+ try { dispose(); } catch { /* already disposed */ }
123
123
  }
124
124
  }
125
125
 
@@ -139,7 +139,7 @@ function disposeComponent(ctx) {
139
139
  }
140
140
  }
141
141
 
142
- if (__DEV__ && __devtools?.onComponentUnmount) __devtools.onComponentUnmount(ctx);
142
+ if (__DEV__ && __devtools?.onComponentUnmount) __devtools.onComponentUnmount?.(ctx);
143
143
  mountedComponents.delete(ctx);
144
144
  }
145
145
 
@@ -169,7 +169,7 @@ export function disposeTree(node) {
169
169
  const disposers = node._hydrationDisposers;
170
170
  node._hydrationDisposers = null;
171
171
  for (let i = 0; i < disposers.length; i++) {
172
- try { disposers[i](); } catch (e) { /* already disposed */ }
172
+ try { disposers[i](); } catch { /* already disposed */ }
173
173
  }
174
174
  }
175
175
  // Check comment node WeakMap for component context — only for comment nodes
@@ -181,12 +181,12 @@ export function disposeTree(node) {
181
181
  }
182
182
  // Dispose reactive function child effects ({() => ...} wrappers)
183
183
  if (node._dispose) {
184
- try { node._dispose(); } catch (e) { /* already disposed */ }
184
+ try { node._dispose(); } catch { /* already disposed */ }
185
185
  }
186
186
  // Dispose reactive prop effects (value: () => ..., class: () => ..., etc.)
187
187
  if (node._propEffects) {
188
188
  for (const key in node._propEffects) {
189
- try { node._propEffects[key](); } catch (e) { /* already disposed */ }
189
+ try { node._propEffects[key](); } catch { /* already disposed */ }
190
190
  }
191
191
  }
192
192
  // Recursively dispose children
@@ -384,7 +384,7 @@ const _propsProxyHandler = {
384
384
  }
385
385
  return undefined;
386
386
  },
387
- set(target, key) {
387
+ set(_target, _key) {
388
388
  // Props are read-only from the component's perspective.
389
389
  // Reject all writes — especially dangerous prototype-chain keys.
390
390
  return false;
@@ -436,6 +436,7 @@ export function _beginComponentSSR(Component) {
436
436
  const ctx = {
437
437
  hooks: [],
438
438
  hookIndex: 0,
439
+ /** @type {Array<() => void>} */
439
440
  effects: [],
440
441
  cleanups: [],
441
442
  mounted: false,
@@ -563,6 +564,7 @@ function createComponent(vnode, parent, isSvg) {
563
564
  const ctx = {
564
565
  hooks: [],
565
566
  hookIndex: 0,
567
+ /** @type {Array<() => void>} */
566
568
  effects: [],
567
569
  cleanups: [],
568
570
  mounted: false,
@@ -587,7 +589,7 @@ function createComponent(vnode, parent, isSvg) {
587
589
 
588
590
  // Track for disposal
589
591
  mountedComponents.add(ctx);
590
- if (__DEV__ && __devtools?.onComponentMount) __devtools.onComponentMount(ctx);
592
+ if (__DEV__ && __devtools?.onComponentMount) __devtools.onComponentMount?.(ctx);
591
593
 
592
594
  // Props signal for reactive updates from parent
593
595
  const propsChildren = children.length === 0 ? undefined : children.length === 1 ? children[0] : children;
@@ -699,7 +701,9 @@ function createErrorBoundary(vnode, parent) {
699
701
  const endComment = document.createComment('eb:end');
700
702
 
701
703
  const boundaryCtx = {
702
- hooks: [], hookIndex: 0, effects: [], cleanups: [],
704
+ hooks: /** @type {any[]} */ ([]), hookIndex: 0,
705
+ effects: /** @type {Array<() => void>} */ ([]),
706
+ cleanups: /** @type {Array<() => void>} */ ([]),
703
707
  mounted: false, disposed: false,
704
708
  _parentCtx: componentStack[componentStack.length - 1] || null,
705
709
  _errorBoundary: handleError,
@@ -719,11 +723,12 @@ function createErrorBoundary(vnode, parent) {
719
723
  componentStack.push(boundaryCtx);
720
724
 
721
725
  // Remove old content between comment boundaries
722
- if (startComment.parentNode) {
726
+ const openParent = startComment.parentNode;
727
+ if (openParent) {
723
728
  while (startComment.nextSibling && startComment.nextSibling !== endComment) {
724
729
  const old = startComment.nextSibling;
725
730
  disposeTree(old);
726
- old.parentNode.removeChild(old);
731
+ openParent.removeChild(old);
727
732
  }
728
733
  }
729
734
 
@@ -767,7 +772,9 @@ function createSuspenseBoundary(vnode, parent) {
767
772
  const endComment = document.createComment('sb:end');
768
773
 
769
774
  const boundaryCtx = {
770
- hooks: [], hookIndex: 0, effects: [], cleanups: [],
775
+ hooks: /** @type {any[]} */ ([]), hookIndex: 0,
776
+ effects: /** @type {Array<() => void>} */ ([]),
777
+ cleanups: /** @type {Array<() => void>} */ ([]),
771
778
  mounted: false, disposed: false,
772
779
  _parentCtx: componentStack[componentStack.length - 1] || null,
773
780
  _suspenseBoundary: boundary,
@@ -795,11 +802,12 @@ function createSuspenseBoundary(vnode, parent) {
795
802
  componentStack.push(boundaryCtx);
796
803
 
797
804
  // Remove old content between comment boundaries
798
- if (startComment.parentNode) {
805
+ const openParent = startComment.parentNode;
806
+ if (openParent) {
799
807
  while (startComment.nextSibling && startComment.nextSibling !== endComment) {
800
808
  const old = startComment.nextSibling;
801
809
  disposeTree(old);
802
- old.parentNode.removeChild(old);
810
+ openParent.removeChild(old);
803
811
  }
804
812
  }
805
813
 
@@ -830,7 +838,7 @@ function createSuspenseBoundary(vnode, parent) {
830
838
  }
831
839
 
832
840
  // Portal component handler
833
- function createPortalDOM(vnode, parent) {
841
+ function createPortalDOM(vnode, _parent) {
834
842
  const { container } = vnode.props;
835
843
  const children = vnode.children;
836
844
 
@@ -840,7 +848,9 @@ function createPortalDOM(vnode, parent) {
840
848
  }
841
849
 
842
850
  const portalCtx = {
843
- hooks: [], hookIndex: 0, effects: [], cleanups: [],
851
+ hooks: /** @type {any[]} */ ([]), hookIndex: 0,
852
+ effects: /** @type {Array<() => void>} */ ([]),
853
+ cleanups: /** @type {Array<() => void>} */ ([]),
844
854
  mounted: false, disposed: false,
845
855
  _parentCtx: componentStack[componentStack.length - 1] || null,
846
856
  };
@@ -942,7 +952,7 @@ function setProp(el, key, value, isSvg) {
942
952
  if (typeof value === 'function' && !_isEventProp(key) && key !== 'ref') {
943
953
  if (!el._propEffects) el._propEffects = {};
944
954
  if (el._propEffects[key]) {
945
- try { el._propEffects[key](); } catch (e) { /* already disposed */ }
955
+ try { el._propEffects[key](); } catch { /* already disposed */ }
946
956
  }
947
957
  el._propEffects[key] = effect(() => {
948
958
  const resolved = value();
@@ -1056,7 +1066,7 @@ function setProp(el, key, value, isSvg) {
1056
1066
  // reset first so removeAttribute() clears both the attribute and the property.
1057
1067
  if (value == null) {
1058
1068
  if (key in el) {
1059
- try { el[key] = ''; } catch (e) { /* read-only reflected prop */ }
1069
+ try { el[key] = ''; } catch { /* read-only reflected prop */ }
1060
1070
  }
1061
1071
  el.removeAttribute(key);
1062
1072
  return;