@firsthandjs/dom 0.7.1 → 0.9.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.
@@ -0,0 +1 @@
1
+ import{p as d,q as i}from"./chunk-NNHZJMZS.js";import{createRoot as r,onCleanup as s,untrack as u}from"@firsthandjs/core";function y(o,e=document.body){return f(o,e,null)}function f(o,e,l){let t;return r(n=>{t=n;let p=()=>{c(e,u(o),l!==null)};l===null?p():l(p)}),t}function c(o,e,l){if(typeof e=="function"){d(o,e);return}let t=null;if(l){let n=[...o.childNodes];t=n.length===1?n[0]:n}t=i(o,null,t,e),s(()=>{i(o,null,t,null)})}export{y as a,f as b};
@@ -0,0 +1 @@
1
+ function z(n,i,e){return n}var a={current:null};function J(n){let i=n.firstChild,e=a.current;return e===null?i:e.step(i)}function K(n){let i=n.nextSibling,e=a.current;return e===null?i:e.step(i)}import{bind as O,createOwner as q,signal as P,disposeOwner as B,getOwner as S,onCleanup as H,runWithOwner as R,setOwner as D}from"@firsthandjs/core";var w=0;function tn(n){w++;try{n()}finally{w--}}var M=3;function E(n){return typeof n.nodeType=="number"}var I=Symbol("firsthand.part"),L=Symbol("firsthand.flat");function on(n){return{[I]:!0,anchor:document.createTextNode(""),thunk:n,owner:S()}}function C(n){return I in n}function ln(n=""){return{slots:[],owner:S(),generation:0,name:n}}function b(n){n.busy=!0}function F(n,i){let e=n.slots[i];if(e!==void 0)return e.seen=n.generation,e;let o={seen:n.generation};return n.slots[i]=o,o}function rn(n,i){let e=q(n.owner);return i.owner=e,D(e)}function dn(n){D(n)}function sn(n,i){let e=n.generation,o=n.slots;for(let t=0;t<o.length;t++){let l=o[t];l===void 0||l.seen===e||(l.owner!==void 0&&B(l.owner),o[t]=void 0)}return n.generation=e+1,i}function un(n,i,e){let o=F(n,i),t=o.cell;if(t===void 0){let l=P(e);return o.cell=l,l}return t.peek()!==e&&(b(n),t.value=e),t}function fn(n,i,e,o,t){let l=F(n,i);if(l.node===void 0&&a.current!==null){let r=a.current.claim(e,o);if(r!==null){if(typeof t=="object"&&t!==null&&C(t)){l.last=t,a.current.keep(l,e,t.anchor,r),R(t.owner,()=>{p(e,t.thunk,t.anchor)});return}l.node=r.nodes,l.text=r.text}}let d=typeof t;if(d==="string"||d==="number"){let r=String(t);if(r===l.text)return;b(n),l.text=r,l.node=h(e,o,l.node??null,r);return}l.text=void 0,t!==l.last&&(b(n),l.last=t,l.node=h(e,o,l.node??null,t))}function p(n,i,e=null,o){if(typeof i!="function"){h(n,e,null,i);return}let t=null,l,d=o!==void 0?o:a.current===null?null:a.current.claim(n,e),r=d!==null;d!==null&&(t=d.nodes,l=d.text);let u=()=>{let f=i(),c=typeof f;if(c==="string"||c==="number"){let y=String(f);y!==l&&(l=y,t=h(n,e,t,y));return}if(l=void 0,c==="function"){if(r){t=null,p(n,f,e,d);return}t=N(t),p(n,f,e,null);return}t=h(n,e,t,f)};d===null?O(u):a.current.within(d.region,()=>{O(u)}),r=!1,H(()=>{t=w>0?null:N(t)})}function h(n,i,e,o){let t=typeof o;if(o==null||t==="boolean")return x(n,i,e);if(t==="string"||t==="number"){let l=String(o);return e!==null&&!Array.isArray(e)&&e.nodeType===M?(e.data=l,e):k(n,i,e,document.createTextNode(l))}if(t==="function")return h(n,i,e,o());if(Array.isArray(o)){if(L in o){let r=o;return r.length===0?x(n,i,e):(v(n,i,e===null?[]:Array.isArray(e)?e:[e],r),r)}let l=[],d=[];if(W(o,l,d),l.length===0)return x(n,i,e);v(n,i,e===null?[]:Array.isArray(e)?e:[e],l);for(let r=0;r<d.length;r++){let u=d[r];R(u.owner??S(),()=>{p(n,u.thunk,u.anchor)})}return l}return C(o)?h(n,i,e,[o]):E(o)?k(n,i,e,o):h(n,i,e,String(o))}function W(n,i,e){for(let o=0;o<n.length;o++){let t=n[o];if(typeof t=="object"&&t!==null&&C(t)){i.push(t.anchor),e.push(t);continue}for(;typeof t=="function";)t=t();t==null||typeof t=="boolean"||(Array.isArray(t)?W(t,i,e):typeof t=="object"&&E(t)?i.push(t):i.push(document.createTextNode(String(t))))}}function j(n){let i=n.parentNode;i!==null&&i.removeChild(n)}function x(n,i,e){return i===null&&Array.isArray(e)&&e.length>1&&n.childNodes.length===e.length?(n.textContent="",null):N(e)}function N(n){if(n!==null)if(Array.isArray(n))for(let i=0;i<n.length;i++)j(n[i]);else j(n);return null}function k(n,i,e,o){return e===o?o:e!==null&&!Array.isArray(e)?(n.replaceChild(o,e),o):(N(e),n.insertBefore(o,i),o)}function v(n,i,e,o){let t=0,l=0,d=e.length-1,r=o.length-1;for(;t<=d&&l<=r&&e[t]===o[l];)t++,l++;for(;t<=d&&l<=r&&e[d]===o[r];)d--,r--;let u=r+1<o.length?o[r+1]:i;if(t>d){for(let s=l;s<=r;s++)n.insertBefore(o[s],u);return}if(l>r){for(let s=t;s<=d;s++)n.removeChild(e[s]);return}let f=new Map;for(let s=t;s<=d;s++)f.set(e[s],s);let c=r-l+1,y=new Int32Array(c).fill(-1);for(let s=0;s<c;s++){let g=o[l+s],_=f.get(g);_!==void 0&&(y[s]=_,f.delete(g))}for(let s of f.keys())n.removeChild(s);let A=X(y),m=A.length-1,T=u;for(let s=c-1;s>=0;s--){let g=o[l+s];m>=0&&A[m]===s?m--:n.insertBefore(g,T),T=g}}function X(n){let i=n.length,e=new Int32Array(i).fill(-1),o=[];for(let d=0;d<i;d++){let r=n[d];if(r===-1)continue;let u=0,f=o.length;for(;u<f;){let c=u+f>>1;n[o[c]]<r?u=c+1:f=c}u>0&&(e[d]=o[u-1]),o[u]=d}let t=[],l=o.length>0?o[o.length-1]:-1;for(;l!==-1;)t.push(l),l=e[l];return t.reverse()}export{z as a,a as b,J as c,K as d,tn as e,L as f,on as g,ln as h,b as i,F as j,rn as k,dn as l,sn as m,un as n,fn as o,p,h as q,v as r};
@@ -0,0 +1 @@
1
+ import{e as v,f as $,g as O,q as A}from"./chunk-NNHZJMZS.js";var b=null,k=new WeakMap;function yn(n){b=n,k=new WeakMap}var h=class extends Error{constructor(e){super(`${e} is not a Firsthand component. If it is a React component, import '@firsthandjs/react/auto' once at startup to render React components directly, or wrap it with fromReact(). Otherwise, declare it with component().`),this.name="FirsthandComponentError"}};function S(n){let e=k.get(n);if(e!==void 0)return e;if(b===null){let o=typeof n=="function"&&n.name!==""?n.name:"The value";throw new h(o)}let t=b(n);return k.set(n,t),t}import{signal as Q,createOwner as T,devEnterSetup as j,devExitSetup as m,disposeOwner as U,getOwner as N,handleError as L,setOwner as f,untrack as H}from"@firsthandjs/core";var M=Symbol.for("firsthand.component"),V=Symbol.for("firsthand.view"),X=0,F="firsthand";function Pn(n){F=n}function vn(n,e,t,o){let s=Object.assign(i=>nn(s,i),{[M]:!0,setup:n,options:e,id:t??`c${String(++X)}`,tag:void 0});return Object.defineProperty(s,"name",{configurable:!0,value:o??(n.name===""?"Component":n.name)}),t===void 0&&(`${s.name}`,void 0),(e?.tag!==void 0||e?.shadow===!0)&&tn(s,typeof e.tag=="string"?e.tag:void 0),s}function $n(n){return typeof n=="function"&&M in n}function On(n){return n[V]=!0,n}function nn(n,e){if(Object.freeze(e),n.setup===void 0)return V in n?O(()=>n(e)):S(n)(e);if(n.tag!==void 0)return sn(n,e);let t=T(N());n.name;let o=f(t);try{j(n.id);let r=H(()=>n.setup(e));return m(),f(o),r}catch(r){return m(),f(o),L(r,t),null}}function en(n){let e=n.name.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9-]/g,"-").toLowerCase();return`${F}-${e}`}function tn(n,e){let t=n;if(t.tag!==void 0)return t.tag;let o=e??en(t);return customElements.get(o)!==void 0&&(o=`${o}-${t.id.replace(/[^a-zA-Z0-9]/g,"").toLowerCase()}`),t.tag=o,customElements.define(o,on(t)),o}function on(n){let e=n.options?.shadow===!0,t=n.options?.attributes,o=t!==void 0?Object.keys(t):[];return class extends HTMLElement{static observedAttributes=o;constructor(){super(),this.$owner=null,this.$props=null,this.$attrs=null,this.$standalone=!1}connectedCallback(){this.$owner===null&&(this.$standalone=!0,this.$attrs={},this.$props=rn(this,t,this.$attrs),W(this,n,e))}disconnectedCallback(){!this.$standalone||this.$owner===null||(U(this.$owner),this.$owner=null)}attributeChangedCallback(s,i,u){let c=this.$attrs?.[s];c!==void 0&&(c.value=t[s]?.(u))}}}function rn(n,e,t){let o={};if(e!==void 0)for(let r in e){let s=Q(e[r](n.getAttribute(r)));t[r]=s,Object.defineProperty(o,r,{enumerable:!0,get:()=>s.value})}return Object.freeze(o)}function W(n,e,t){let o=T(N());e.name,n.$owner=o;let r=f(o);try{j(e.id);let s=t?n.attachShadow({mode:"open"}):n,i=H(()=>e.setup(n.$props));m(),A(s,null,null,i)}catch(s){m(),L(s,o)}finally{f(r)}}function sn(n,e){let t=document.createElement(n.tag);return t.$props=e,W(t,n,n.options?.shadow===!0),t}import{batch as un,createOwner as z,disposeOwner as dn,getOwner as cn,setOwner as C,signal as I,untrack as D}from"@firsthandjs/core";function Hn(n,e,t){let o=z(cn()),r=new Map;return()=>{let s=n(),i=new Map,u=[];return u[$]=!0,D(()=>{un(()=>{c()})}),r=i,u;function c(){for(let d=0;d<s.length;d++){let a=s[d],p=e(a,d);if(i.has(p)){`${String(p)}`;continue}let l=r.get(p);l===void 0?l=ln(o,a,d,t):(r.delete(p),l.item.value=a,l.index.value=d),i.set(p,l);for(let y=0;y<l.nodes.length;y++)u.push(l.nodes[y])}v(()=>{for(let d of r.values())dn(d.owner)})}}}function ln(n,e,t,o){let r=z(n),s=I(e),i=I(t),u=C(r),c;try{c=D(()=>o(s,i)),C(u)}catch(a){throw C(u),a}let d=[];return K(c,d),{owner:r,item:s,index:i,nodes:d}}function K(n,e){if(!(n==null||typeof n=="boolean")){if(Array.isArray(n)){for(let t=0;t<n.length;t++)K(n[t],e);return}if(typeof n=="object"&&typeof n.nodeType=="number"){e.push(n);return}e.push(document.createTextNode(String(n)))}}var an=new Set(["click","dblclick","contextmenu","input","beforeinput","change","keydown","keyup","keypress","pointerdown","pointerup","pointermove","mousedown","mouseup","mouseover","mouseout","submit","focusin","focusout","touchstart","touchend"]),Z=new Set;function w(n){return`$firsthand$${n}`}function pn(n){let e=w(n.type),t=n.composedPath(),o=null;Object.defineProperty(n,"currentTarget",{configurable:!0,get:()=>o});for(let r=0;r<t.length;r++){let s=t[r],i=s[e];if(i!==void 0&&(o=s,i.call(s,n),n.cancelBubble)||s===document)break}o=null}function g(n,e,t,o){if(o!==void 0||!an.has(e)){let r=n,s=o===!0?void 0:o,i=`${w(e)}$${s===void 0?"":Object.keys(s).sort().join(",")}`,u=r[i];u!==void 0&&n.removeEventListener(e,u.handler,u.options),r[i]={handler:t,options:s},n.addEventListener(e,t,s);return}n[w(e)]=t,Z.has(e)||(Z.add(e),document.addEventListener(e,pn))}function Vn(n,e){n[w(e)]=void 0}var fn={class:"className",for:"htmlFor"};function R(n,e,t){t==null||t===!1?n.removeAttribute(e):n.setAttribute(e,t===!0?"":String(t))}function zn(n,e,t,o){o==null||o===!1?n.removeAttributeNS(e,t):n.setAttributeNS(e,t,o===!0?"":String(o))}function x(n,e,t){n[fn[e]??e]=t}function Dn(n,e,t){n[e]=!!t}function P(n,e){e==null?n.removeAttribute("class"):n.className=String(e)}function B(n,e,t){let o=n.classList;if(t!==void 0)for(let r in t)r in e||o.remove(r);for(let r in e){let s=!!e[r];(t===void 0||!!t[r]!==s)&&o.toggle(r,s)}}function _(n,e){e==null?n.style.cssText="":n.style.cssText=String(e)}function Y(n,e,t){let o=n.style;if(t!==void 0)for(let r in t)r in e||o.removeProperty(E(r));for(let r in e){let s=e[r];(t===void 0||t[r]!==s)&&(s==null?o.removeProperty(E(r)):o.setProperty(E(r),String(s)))}}var mn=/[A-Z]/g,q=new Map;function E(n){let e=q.get(n);return e===void 0&&(e=n.startsWith("--")?n:n.replace(mn,t=>`-${t.toLowerCase()}`),q.set(n,e)),e}function wn(n,e,t){if(e==="class"||e==="className"){Array.isArray(t)?P(n,t.filter(Boolean).join(" ")):t!==null&&typeof t=="object"?B(n,t,J(n,"class",t)):P(n,t);return}if(e==="style"){t!==null&&typeof t=="object"?Y(n,t,J(n,"style",t)):_(n,t);return}if(e==="ref"){t(n);return}if(e.startsWith("prop:")){x(n,e.slice(5),t);return}if(e.startsWith("attr:")){R(n,e.slice(5),t);return}if(e.startsWith("on")&&e.length>2&&/[A-Z:]/.test(e[2])){gn(n,e,t);return}if(e in n&&typeof t!="string"){x(n,e,t);return}R(n,e,t)}function gn(n,e,t){let o=e.slice(2).split(":"),r=o[0]==="",s=r?o[1]:o[0].toLowerCase(),i=o[r?2:1];i===void 0?g(n,s,t):i==="native"?g(n,s,t,!0):g(n,s,t,{[i]:!0})}function Bn(n,e){for(let t in e)t!=="children"&&wn(n,t,e[t])}function _n(...n){let e={};for(let t=0;t<n.length;t++){let o=n[t];for(let r of Object.keys(o))Object.defineProperty(e,r,{enumerable:!0,configurable:!0,get:()=>o[r]})}return e}function Yn(n,e){let t={};for(let o of Object.keys(n))e.includes(o)||Object.defineProperty(t,o,{enumerable:!0,get:()=>n[o]});return Object.freeze(t)}var G=new WeakMap;function J(n,e,t){let o=G.get(n);o===void 0&&(o={},G.set(n,o));let r=o[e];return o[e]=t,r}export{yn as a,h as b,M as c,V as d,Pn as e,vn as f,$n as g,On as h,nn as i,tn as j,Hn as k,g as l,Vn as m,R as n,zn as o,x as p,Dn as q,P as r,B as s,_ as t,Y as u,wn as v,Bn as w,_n as x,Yn as y};
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The seam hydration is installed through.
3
+ *
4
+ * `template` and `insert` have to be able to adopt nodes a server sent, and
5
+ * an application that has no server must not pay for the machinery that does
6
+ * it. So they do not import it. They read one holder, which is empty until
7
+ * `@firsthandjs/dom/hydrate` fills it — and a bundle that never imports that
8
+ * module never contains the machinery at all, because nothing references it.
9
+ *
10
+ * What is left behind in the ordinary path is one property read and one
11
+ * comparison against `null`, in two places.
12
+ */
13
+ /** What a region of server markup turned out to hold. */
14
+ export type Claimed = {
15
+ /** The nodes the region holds, as a child slot. */
16
+ nodes: Node | Node[] | null;
17
+ /** The text already there, when the region is one text node. */
18
+ text: string | undefined;
19
+ /** The region itself, for the calls made while a child's first run happens. */
20
+ region: Region;
21
+ };
22
+ /** Where a claim has got to. */
23
+ export type Region = {
24
+ /** The next unclaimed node, or null when the region is used up. */
25
+ node: Node | null;
26
+ /** The node the region stops before. */
27
+ end: Node | null;
28
+ };
29
+ /**
30
+ * The part of a site hydration fills in.
31
+ *
32
+ * Structural, so that the holder does not have to import `insert.ts` and
33
+ * `insert.ts` does not have to export its record type to reach through it.
34
+ */
35
+ export type Filled = {
36
+ node?: Node | Node[] | null;
37
+ };
38
+ export type Claimer = {
39
+ /** The element name a template's markup makes. */
40
+ tag(html: string): string;
41
+ /** The next node of the current region, if it is a `tag`. */
42
+ adopt(tag: string): Node | null;
43
+ /**
44
+ * Gives a child a run keeps the nodes the run claimed for it.
45
+ *
46
+ * Puts `anchor` at the end of the region and offers the region to whoever
47
+ * claims against that anchor next, which is the child's own `insert`.
48
+ */
49
+ keep(slot: Filled, parent: Node, anchor: Node, claimed: Claimed): void;
50
+ /** The region belonging to the next dynamic child of `parent`. */
51
+ claim(parent: Node, marker: Node | null): Claimed | null;
52
+ /** Makes `region` the one nodes are adopted from while `body` runs. */
53
+ within<T>(region: Region, body: () => T): T;
54
+ /** A step through the template that goes over a whole region at a time. */
55
+ step(node: Node): Node;
56
+ };
57
+ /**
58
+ * The installed claimer, or nothing.
59
+ *
60
+ * A holder rather than an exported binding, so that every reader sees the
61
+ * same value however the module is bundled.
62
+ */
63
+ export declare const hydration: {
64
+ current: Claimer | null;
65
+ };
66
+ /**
67
+ * The first child of `node`, stepping over a dynamic child's content.
68
+ *
69
+ * Emitted by the compiler in place of `.firstChild` for a build that can
70
+ * hydrate. `.firstChild` would walk into the content of a dynamic child,
71
+ * because the content has a length the template does not.
72
+ */
73
+ export declare function first(node: Node): Node;
74
+ /** The next sibling of `node`, stepping over a dynamic child's content. */
75
+ export declare function next(node: Node): Node;
76
+ //# sourceMappingURL=claim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../src/claim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,yDAAyD;AACzD,MAAM,MAAM,OAAO,GAAG;IACpB,mDAAmD;IACnD,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,gCAAgC;AAChC,MAAM,MAAM,MAAM,GAAG;IACnB,mEAAmE;IACnE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,wCAAwC;IACxC,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,kDAAkD;IAClD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACvE,kEAAkE;IAClE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;IACzD,uEAAuE;IACvE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5C,2EAA2E;IAC3E,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE;IAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAAsB,CAAC;AAExE;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAItC;AAED,2EAA2E;AAC3E,wBAAgB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAIrC"}
@@ -2,6 +2,14 @@ import type { ReadonlyProps } from '@firsthandjs/core';
2
2
  import { type DynamicChild } from './insert.js';
3
3
  /** Marks a value as a Firsthand component; used by the JSX runtime and compiler. */
4
4
  export declare const COMPONENT: unique symbol;
5
+ /**
6
+ * Marks a plain function that returns markup.
7
+ *
8
+ * `Symbol.for` rather than a local symbol: the mark has to survive a module
9
+ * boundary, so a view function compiled in one package is recognised in
10
+ * another that may hold its own copy of this module.
11
+ */
12
+ export declare const VIEW: unique symbol;
5
13
  export type ComponentOptions = {
6
14
  /** Attach a shadow root to the element host. Implies `tag` (ADR-0007). */
7
15
  shadow?: boolean;
@@ -23,7 +31,20 @@ export type AttributeCodec = (raw: string | null) => unknown;
23
31
  * fragment, and what a component returns when it renders something that has to
24
32
  * be bound after it is placed — a route outlet, for instance.
25
33
  */
26
- export type View = Node | string | number | boolean | null | undefined | DynamicChild | readonly View[];
34
+ export type View = Node | string | number | boolean | null | undefined | DynamicChild | readonly View[] | Render;
35
+ /**
36
+ * A view that is evaluated as a whole, again, when something it read changes.
37
+ *
38
+ * This is what a setup returns when it has statements above its markup — an
39
+ * `if`, a value derived from several signals — and it is an ordinary function,
40
+ * which is the point: it is a reactive scope like `effect` and `computed`, one
41
+ * level up.
42
+ *
43
+ * ```tsx
44
+ * component(() => () => (signedIn.value ? <Page /> : <SignIn />));
45
+ * ```
46
+ */
47
+ export type Render = () => View;
27
48
  /**
28
49
  * Props as a *caller* may write them.
29
50
  *
@@ -73,6 +94,20 @@ export declare function setElementPrefix(value: string): void;
73
94
  */
74
95
  export declare function component<P>(setup: (props: ReadonlyProps<P>) => View, options?: ComponentOptions, id?: string, name?: string): Component<P>;
75
96
  export declare function isComponent(value: unknown): value is Component<never>;
97
+ /**
98
+ * Declares a plain function to be a view.
99
+ *
100
+ * A function that returns markup is a view, and a view is a reactive scope:
101
+ * `<Badge user={user} />` calls it where it stands, and calls it again when
102
+ * something it read changes. It has no setup, so it owns nothing that has to
103
+ * survive a run — `signal`, `effect` and their kind belong in a `component`.
104
+ *
105
+ * The compiler emits this for every module-level function it compiled markup
106
+ * into, so that a view imported from another module is still recognised as
107
+ * ours rather than handed to whatever adapter is installed. Inside one module
108
+ * the compiler resolves the call itself and this is never consulted.
109
+ */
110
+ export declare function view<T extends (props: never) => unknown>(target: T): T;
76
111
  /**
77
112
  * Instantiates a component.
78
113
  *
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5D,oFAAoF;AACpF,eAAO,MAAM,SAAS,EAAE,OAAO,MAA0C,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACpB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CACvD,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC;AAE7D;;;;;;;;;;GAUG;AACH,MAAM,MAAM,IAAI,GACd,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,IAAI,EAAE,CAAC;AAEvF;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;KAC5B,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;CACjE,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB;;;;;;;OAOG;IACH,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC/C,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,CAAC;AAKF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EACzB,KAAK,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,EACxC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,EAAE,CAAC,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,GACZ,SAAS,CAAC,CAAC,CAAC,CAgCd;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,CAErE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAgCvE;AAcD,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,MAAM,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAc5E"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import {
2
+ applyChild,
3
+ insert
4
+ } from "./dev-chunk-HTXIHAW7.js";
5
+
6
+ // packages/dom/src/render.ts
7
+ import { createRoot, onCleanup, untrack } from "@firsthandjs/core";
8
+ function render(view, container = document.body) {
9
+ return mount(view, container, null);
10
+ }
11
+ function mount(view, container, around) {
12
+ let dispose;
13
+ createRoot((stop) => {
14
+ dispose = stop;
15
+ const run = () => {
16
+ attach(container, untrack(view), around !== null);
17
+ };
18
+ if (around === null) {
19
+ run();
20
+ } else {
21
+ around(run);
22
+ }
23
+ });
24
+ return dispose;
25
+ }
26
+ function attach(container, result, adopting) {
27
+ if (typeof result === "function") {
28
+ insert(container, result);
29
+ return;
30
+ }
31
+ let slot = null;
32
+ if (adopting) {
33
+ const children = [...container.childNodes];
34
+ slot = children.length === 1 ? children[0] : children;
35
+ }
36
+ slot = applyChild(container, null, slot, result);
37
+ onCleanup(() => {
38
+ applyChild(container, null, slot, null);
39
+ });
40
+ }
41
+
42
+ export {
43
+ render,
44
+ mount
45
+ };
@@ -1,3 +1,14 @@
1
+ import {
2
+ FLAT,
3
+ applyChild,
4
+ devComponent,
5
+ devPart,
6
+ devWarn,
7
+ devWarnOnce,
8
+ discard,
9
+ part
10
+ } from "./dev-chunk-HTXIHAW7.js";
11
+
1
12
  // packages/dom/src/adapter.ts
2
13
  var adapter = null;
3
14
  var adapted = /* @__PURE__ */ new WeakMap();
@@ -27,263 +38,6 @@ function adapt(target) {
27
38
  return component_;
28
39
  }
29
40
 
30
- // packages/dom/src/dev.ts
31
- function devWarn(message) {
32
- console.warn(`[firsthand] ${message}`);
33
- }
34
- var seen = /* @__PURE__ */ new Set();
35
- function devWarnOnce(key2, message) {
36
- if (!seen.has(key2)) {
37
- seen.add(key2);
38
- devWarn(message);
39
- }
40
- }
41
- function devWarnRenderedObject(value) {
42
- const cellish = "peek" in value && typeof value.peek === "function" && "value" in value;
43
- devWarnOnce(
44
- cellish ? "rendered-cell" : "rendered-object",
45
- cellish ? 'A signal or computed was rendered directly, so the page shows "[object Object]". Read it instead: {count.value} rather than {count}.' : `An object was rendered as text, so the page shows "${String(value)}". Render a string, a number or a node.`
46
- );
47
- }
48
- function hook() {
49
- const installed2 = globalThis.__FIRSTHAND_DEVTOOLS__;
50
- return installed2 !== void 0 && installed2.attached ? installed2 : void 0;
51
- }
52
- function devPart(node, property) {
53
- hook()?.part(node, property);
54
- }
55
- function devComponent(owner, name) {
56
- hook()?.component(owner, name);
57
- }
58
- function label(value, kind, name) {
59
- if (typeof value === "object" && value !== null) {
60
- hook()?.label(value, kind, name);
61
- }
62
- return value;
63
- }
64
-
65
- // packages/dom/src/insert.ts
66
- import { bind, getOwner, onCleanup, runWithOwner } from "@firsthandjs/core";
67
- var TEXT_NODE = 3;
68
- function isNode(value) {
69
- return typeof value.nodeType === "number";
70
- }
71
- var PART = /* @__PURE__ */ Symbol("firsthand.part");
72
- function part(thunk) {
73
- return { [PART]: true, anchor: document.createTextNode(""), thunk, owner: getOwner() };
74
- }
75
- function isDynamicChild(value) {
76
- return PART in value;
77
- }
78
- function insert(parent, value, marker = null) {
79
- if (typeof value !== "function") {
80
- applyChild(parent, marker, null, value);
81
- return;
82
- }
83
- let current = null;
84
- bind(() => {
85
- const next = value();
86
- if (typeof next === "function") {
87
- current = clear(current);
88
- insert(parent, next, marker);
89
- return;
90
- }
91
- current = applyChild(parent, marker, current, next);
92
- });
93
- onCleanup(() => {
94
- current = clear(current);
95
- });
96
- }
97
- function applyChild(parent, marker, current, value) {
98
- const type = typeof value;
99
- if (value == null || type === "boolean") {
100
- devPart(parent, "text");
101
- return clear(current);
102
- }
103
- if (type === "string" || type === "number") {
104
- devPart(parent, "text");
105
- const text = String(value);
106
- if (current !== null && !Array.isArray(current) && current.nodeType === TEXT_NODE) {
107
- current.data = text;
108
- return current;
109
- }
110
- return single(parent, marker, current, document.createTextNode(text));
111
- }
112
- if (type === "function") {
113
- return applyChild(parent, marker, current, value());
114
- }
115
- if (Array.isArray(value)) {
116
- const next = [];
117
- const dynamic = [];
118
- flatten(value, next, dynamic);
119
- if (next.length === 0) {
120
- return clear(current);
121
- }
122
- reconcile(
123
- parent,
124
- marker,
125
- current === null ? [] : Array.isArray(current) ? current : [current],
126
- next
127
- );
128
- for (let i = 0; i < dynamic.length; i++) {
129
- const child = dynamic[i];
130
- runWithOwner(child.owner ?? getOwner(), () => {
131
- insert(parent, child.thunk, child.anchor);
132
- });
133
- }
134
- return next;
135
- }
136
- if (isDynamicChild(value)) {
137
- return applyChild(parent, marker, current, [value]);
138
- }
139
- if (isNode(value)) {
140
- return single(parent, marker, current, value);
141
- }
142
- devWarnRenderedObject(value);
143
- return applyChild(parent, marker, current, String(value));
144
- }
145
- function flatten(value, out, dynamic) {
146
- for (let i = 0; i < value.length; i++) {
147
- let item = value[i];
148
- if (typeof item === "object" && item !== null && isDynamicChild(item)) {
149
- out.push(item.anchor);
150
- dynamic.push(item);
151
- continue;
152
- }
153
- while (typeof item === "function") {
154
- item = item();
155
- }
156
- if (item == null || typeof item === "boolean") {
157
- continue;
158
- }
159
- if (Array.isArray(item)) {
160
- flatten(item, out, dynamic);
161
- } else if (typeof item === "object" && isNode(item)) {
162
- out.push(item);
163
- } else {
164
- out.push(document.createTextNode(String(item)));
165
- }
166
- }
167
- }
168
- function detach(node) {
169
- const owner = node.parentNode;
170
- if (owner !== null) {
171
- owner.removeChild(node);
172
- }
173
- }
174
- function clear(current) {
175
- if (current !== null) {
176
- if (Array.isArray(current)) {
177
- for (let i = 0; i < current.length; i++) {
178
- detach(current[i]);
179
- }
180
- } else {
181
- detach(current);
182
- }
183
- }
184
- return null;
185
- }
186
- function single(parent, marker, current, node) {
187
- if (current === node) {
188
- return node;
189
- }
190
- if (current !== null && !Array.isArray(current)) {
191
- parent.replaceChild(node, current);
192
- return node;
193
- }
194
- clear(current);
195
- parent.insertBefore(node, marker);
196
- return node;
197
- }
198
- function reconcile(parent, marker, a, b) {
199
- let aStart = 0;
200
- let bStart = 0;
201
- let aEnd = a.length - 1;
202
- let bEnd = b.length - 1;
203
- while (aStart <= aEnd && bStart <= bEnd && a[aStart] === b[bStart]) {
204
- aStart++;
205
- bStart++;
206
- }
207
- while (aStart <= aEnd && bStart <= bEnd && a[aEnd] === b[bEnd]) {
208
- aEnd--;
209
- bEnd--;
210
- }
211
- const after = bEnd + 1 < b.length ? b[bEnd + 1] : marker;
212
- if (aStart > aEnd) {
213
- for (let i = bStart; i <= bEnd; i++) {
214
- parent.insertBefore(b[i], after);
215
- }
216
- return;
217
- }
218
- if (bStart > bEnd) {
219
- for (let i = aStart; i <= aEnd; i++) {
220
- parent.removeChild(a[i]);
221
- }
222
- return;
223
- }
224
- const oldIndex = /* @__PURE__ */ new Map();
225
- for (let i = aStart; i <= aEnd; i++) {
226
- oldIndex.set(a[i], i);
227
- }
228
- const middle = bEnd - bStart + 1;
229
- const sources = new Int32Array(middle).fill(-1);
230
- for (let j = 0; j < middle; j++) {
231
- const node = b[bStart + j];
232
- const found = oldIndex.get(node);
233
- if (found !== void 0) {
234
- sources[j] = found;
235
- oldIndex.delete(node);
236
- }
237
- }
238
- for (const node of oldIndex.keys()) {
239
- parent.removeChild(node);
240
- }
241
- const keep = longestIncreasing(sources);
242
- let k = keep.length - 1;
243
- let anchor = after;
244
- for (let j = middle - 1; j >= 0; j--) {
245
- const node = b[bStart + j];
246
- if (k >= 0 && keep[k] === j) {
247
- k--;
248
- } else {
249
- parent.insertBefore(node, anchor);
250
- }
251
- anchor = node;
252
- }
253
- }
254
- function longestIncreasing(sources) {
255
- const length = sources.length;
256
- const predecessor = new Int32Array(length).fill(-1);
257
- const tails = [];
258
- for (let i = 0; i < length; i++) {
259
- const value = sources[i];
260
- if (value === -1) {
261
- continue;
262
- }
263
- let low = 0;
264
- let high = tails.length;
265
- while (low < high) {
266
- const mid = low + high >> 1;
267
- if (sources[tails[mid]] < value) {
268
- low = mid + 1;
269
- } else {
270
- high = mid;
271
- }
272
- }
273
- if (low > 0) {
274
- predecessor[i] = tails[low - 1];
275
- }
276
- tails[low] = i;
277
- }
278
- const result = [];
279
- let cursor = tails.length > 0 ? tails[tails.length - 1] : -1;
280
- while (cursor !== -1) {
281
- result.push(cursor);
282
- cursor = predecessor[cursor];
283
- }
284
- return result.reverse();
285
- }
286
-
287
41
  // packages/dom/src/component.ts
288
42
  import {
289
43
  signal,
@@ -291,12 +45,13 @@ import {
291
45
  devEnterSetup,
292
46
  devExitSetup,
293
47
  disposeOwner,
294
- getOwner as getOwner2,
48
+ getOwner,
295
49
  handleError,
296
50
  setOwner,
297
51
  untrack
298
52
  } from "@firsthandjs/core";
299
53
  var COMPONENT = /* @__PURE__ */ Symbol.for("firsthand.component");
54
+ var VIEW = /* @__PURE__ */ Symbol.for("firsthand.view");
300
55
  var sequence = 0;
301
56
  var prefix = "firsthand";
302
57
  function setElementPrefix(value) {
@@ -333,15 +88,22 @@ function component(setup, options, id, name) {
333
88
  function isComponent(value) {
334
89
  return typeof value === "function" && COMPONENT in value;
335
90
  }
91
+ function view(target) {
92
+ target[VIEW] = true;
93
+ return target;
94
+ }
336
95
  function createComponent(target, props) {
337
96
  Object.freeze(props);
338
97
  if (target.setup === void 0) {
98
+ if (VIEW in target) {
99
+ return part(() => target(props));
100
+ }
339
101
  return adapt(target)(props);
340
102
  }
341
103
  if (target.tag !== void 0) {
342
104
  return createHost(target, props);
343
105
  }
344
- const owner = createOwner(getOwner2());
106
+ const owner = createOwner(getOwner());
345
107
  devComponent(owner, target.name);
346
108
  const previous = setOwner(owner);
347
109
  try {
@@ -427,7 +189,7 @@ function attributeProps(element, codecs, cells) {
427
189
  return Object.freeze(props);
428
190
  }
429
191
  function mountHost(element, target, shadow) {
430
- const owner = createOwner(getOwner2());
192
+ const owner = createOwner(getOwner());
431
193
  devComponent(owner, target.name);
432
194
  element.$owner = owner;
433
195
  const previous = setOwner(owner);
@@ -456,22 +218,30 @@ import {
456
218
  batch,
457
219
  createOwner as createOwner2,
458
220
  disposeOwner as disposeOwner2,
459
- getOwner as getOwner3,
221
+ getOwner as getOwner2,
460
222
  setOwner as setOwner2,
461
223
  signal as signal2,
462
224
  untrack as untrack2
463
225
  } from "@firsthandjs/core";
464
226
  function list(each, keyOf, render) {
465
- const host = createOwner2(getOwner3());
227
+ const host = createOwner2(getOwner2());
466
228
  let rows = /* @__PURE__ */ new Map();
467
229
  return () => {
468
230
  const items = each();
469
231
  const next = /* @__PURE__ */ new Map();
470
232
  const nodes = [];
471
- batch(() => {
233
+ nodes[FLAT] = true;
234
+ untrack2(() => {
235
+ batch(() => {
236
+ buildRows();
237
+ });
238
+ });
239
+ rows = next;
240
+ return nodes;
241
+ function buildRows() {
472
242
  for (let i = 0; i < items.length; i++) {
473
243
  const item = items[i];
474
- const key2 = untrack2(() => keyOf(item, i));
244
+ const key2 = keyOf(item, i);
475
245
  if (next.has(key2)) {
476
246
  devWarn(
477
247
  `Duplicate list key ${String(key2)}. Keys must be unique, or rows will be dropped.`
@@ -491,12 +261,12 @@ function list(each, keyOf, render) {
491
261
  nodes.push(row.nodes[n]);
492
262
  }
493
263
  }
494
- for (const row of rows.values()) {
495
- disposeOwner2(row.owner);
496
- }
497
- });
498
- rows = next;
499
- return nodes;
264
+ discard(() => {
265
+ for (const row of rows.values()) {
266
+ disposeOwner2(row.owner);
267
+ }
268
+ });
269
+ }
500
270
  };
501
271
  }
502
272
  function createRow(host, item, index, render) {
@@ -587,7 +357,15 @@ function dispatch(event) {
587
357
  }
588
358
  function on(node, type, handler, options) {
589
359
  if (options !== void 0 || !DELEGATED.has(type)) {
590
- node.addEventListener(type, handler, options === true ? void 0 : options);
360
+ const host = node;
361
+ const resolved = options === true ? void 0 : options;
362
+ const slot = `${key(type)}$${resolved === void 0 ? "" : Object.keys(resolved).sort().join(",")}`;
363
+ const previous = host[slot];
364
+ if (previous !== void 0) {
365
+ node.removeEventListener(type, previous.handler, previous.options);
366
+ }
367
+ host[slot] = { handler, options: resolved };
368
+ node.addEventListener(type, handler, resolved);
591
369
  return;
592
370
  }
593
371
  node[key(type)] = handler;
@@ -694,7 +472,9 @@ function hyphenate(name) {
694
472
  // packages/dom/src/props.ts
695
473
  function applyProp(node, name, value) {
696
474
  if (name === "class" || name === "className") {
697
- if (value !== null && typeof value === "object") {
475
+ if (Array.isArray(value)) {
476
+ setClass(node, value.filter(Boolean).join(" "));
477
+ } else if (value !== null && typeof value === "object") {
698
478
  setClassList(node, value, remember(node, "class", value));
699
479
  } else {
700
480
  setClass(node, value);
@@ -796,15 +576,12 @@ function remember(node, slot, value) {
796
576
  export {
797
577
  setComponentAdapter,
798
578
  FirsthandComponentError,
799
- label,
800
- part,
801
- insert,
802
- applyChild,
803
- reconcile,
804
579
  COMPONENT,
580
+ VIEW,
805
581
  setElementPrefix,
806
582
  component,
807
583
  isComponent,
584
+ view,
808
585
  createComponent,
809
586
  defineElement,
810
587
  list,