@vielzeug/craftit 1.0.1 → 2.0.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.
- package/README.md +112 -401
- package/dist/core/component.cjs +2 -0
- package/dist/core/component.cjs.map +1 -0
- package/dist/core/component.d.ts +172 -0
- package/dist/core/component.d.ts.map +1 -0
- package/dist/core/component.js +2 -0
- package/dist/core/component.js.map +1 -0
- package/dist/core/host.cjs +2 -0
- package/dist/core/host.cjs.map +1 -0
- package/dist/core/host.d.ts +77 -0
- package/dist/core/host.d.ts.map +1 -0
- package/dist/core/host.js +2 -0
- package/dist/core/host.js.map +1 -0
- package/dist/core/internal.cjs +2 -0
- package/dist/core/internal.cjs.map +1 -0
- package/dist/core/internal.d.ts +105 -0
- package/dist/core/internal.d.ts.map +1 -0
- package/dist/core/internal.js +2 -0
- package/dist/core/internal.js.map +1 -0
- package/dist/core/runtime-bindings.cjs +2 -0
- package/dist/core/runtime-bindings.cjs.map +1 -0
- package/dist/core/runtime-bindings.d.ts +6 -0
- package/dist/core/runtime-bindings.d.ts.map +1 -0
- package/dist/core/runtime-bindings.js +2 -0
- package/dist/core/runtime-bindings.js.map +1 -0
- package/dist/core/runtime-lifecycle.cjs +2 -0
- package/dist/core/runtime-lifecycle.cjs.map +1 -0
- package/dist/core/runtime-lifecycle.d.ts +116 -0
- package/dist/core/runtime-lifecycle.d.ts.map +1 -0
- package/dist/core/runtime-lifecycle.js +2 -0
- package/dist/core/runtime-lifecycle.js.map +1 -0
- package/dist/core/runtime.cjs +1 -0
- package/dist/core/runtime.d.ts +3 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +1 -0
- package/dist/core/template-bindings.cjs +2 -0
- package/dist/core/template-bindings.cjs.map +1 -0
- package/dist/core/template-bindings.d.ts +59 -0
- package/dist/core/template-bindings.d.ts.map +1 -0
- package/dist/core/template-bindings.js +2 -0
- package/dist/core/template-bindings.js.map +1 -0
- package/dist/core/template-compiler.cjs +2 -0
- package/dist/core/template-compiler.cjs.map +1 -0
- package/dist/core/template-compiler.d.ts +25 -0
- package/dist/core/template-compiler.d.ts.map +1 -0
- package/dist/core/template-compiler.js +2 -0
- package/dist/core/template-compiler.js.map +1 -0
- package/dist/core/template-dom.cjs +2 -0
- package/dist/core/template-dom.cjs.map +1 -0
- package/dist/core/template-dom.d.ts +13 -0
- package/dist/core/template-dom.d.ts.map +1 -0
- package/dist/core/template-dom.js +2 -0
- package/dist/core/template-dom.js.map +1 -0
- package/dist/core/template-html.cjs +2 -0
- package/dist/core/template-html.cjs.map +1 -0
- package/dist/core/template-html.d.ts +26 -0
- package/dist/core/template-html.d.ts.map +1 -0
- package/dist/core/template-html.js +2 -0
- package/dist/core/template-html.js.map +1 -0
- package/dist/core/template.cjs +2 -0
- package/dist/core/template.cjs.map +1 -0
- package/dist/core/template.d.ts +11 -0
- package/dist/core/template.d.ts.map +1 -0
- package/dist/core/template.js +2 -0
- package/dist/core/template.js.map +1 -0
- package/dist/core/utilities.cjs +2 -0
- package/dist/core/utilities.cjs.map +1 -0
- package/dist/core/utilities.d.ts +68 -0
- package/dist/core/utilities.d.ts.map +1 -0
- package/dist/core/utilities.js +2 -0
- package/dist/core/utilities.js.map +1 -0
- package/dist/craftit.cjs +2 -18
- package/dist/craftit.cjs.map +1 -1
- package/dist/craftit.js +2 -580
- package/dist/craftit.js.map +1 -1
- package/dist/directives/attr.cjs +2 -0
- package/dist/directives/attr.cjs.map +1 -0
- package/dist/directives/attr.d.ts +14 -0
- package/dist/directives/attr.d.ts.map +1 -0
- package/dist/directives/attr.js +2 -0
- package/dist/directives/attr.js.map +1 -0
- package/dist/directives/bind.cjs +2 -0
- package/dist/directives/bind.cjs.map +1 -0
- package/dist/directives/bind.d.ts +30 -0
- package/dist/directives/bind.d.ts.map +1 -0
- package/dist/directives/bind.js +2 -0
- package/dist/directives/bind.js.map +1 -0
- package/dist/directives/choose.cjs +2 -0
- package/dist/directives/choose.cjs.map +1 -0
- package/dist/directives/choose.d.ts +34 -0
- package/dist/directives/choose.d.ts.map +1 -0
- package/dist/directives/choose.js +2 -0
- package/dist/directives/choose.js.map +1 -0
- package/dist/directives/classes.cjs +2 -0
- package/dist/directives/classes.cjs.map +1 -0
- package/dist/directives/classes.d.ts +20 -0
- package/dist/directives/classes.d.ts.map +1 -0
- package/dist/directives/classes.js +2 -0
- package/dist/directives/classes.js.map +1 -0
- package/dist/directives/each.cjs +2 -0
- package/dist/directives/each.cjs.map +1 -0
- package/dist/directives/each.d.ts +68 -0
- package/dist/directives/each.d.ts.map +1 -0
- package/dist/directives/each.js +2 -0
- package/dist/directives/each.js.map +1 -0
- package/dist/directives/index.cjs +1 -0
- package/dist/directives/index.d.ts +14 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/directives/index.js +1 -0
- package/dist/directives/match.cjs +2 -0
- package/dist/directives/match.cjs.map +1 -0
- package/dist/directives/match.d.ts +31 -0
- package/dist/directives/match.d.ts.map +1 -0
- package/dist/directives/match.js +2 -0
- package/dist/directives/match.js.map +1 -0
- package/dist/directives/memo.cjs +2 -0
- package/dist/directives/memo.cjs.map +1 -0
- package/dist/directives/memo.d.ts +23 -0
- package/dist/directives/memo.d.ts.map +1 -0
- package/dist/directives/memo.js +2 -0
- package/dist/directives/memo.js.map +1 -0
- package/dist/directives/on.cjs +2 -0
- package/dist/directives/on.cjs.map +1 -0
- package/dist/directives/on.d.ts +25 -0
- package/dist/directives/on.d.ts.map +1 -0
- package/dist/directives/on.js +2 -0
- package/dist/directives/on.js.map +1 -0
- package/dist/directives/raw.cjs +2 -0
- package/dist/directives/raw.cjs.map +1 -0
- package/dist/directives/raw.d.ts +25 -0
- package/dist/directives/raw.d.ts.map +1 -0
- package/dist/directives/raw.js +2 -0
- package/dist/directives/raw.js.map +1 -0
- package/dist/directives/spread.cjs +2 -0
- package/dist/directives/spread.cjs.map +1 -0
- package/dist/directives/spread.d.ts +14 -0
- package/dist/directives/spread.d.ts.map +1 -0
- package/dist/directives/spread.js +2 -0
- package/dist/directives/spread.js.map +1 -0
- package/dist/directives/style.cjs +2 -0
- package/dist/directives/style.cjs.map +1 -0
- package/dist/directives/style.d.ts +22 -0
- package/dist/directives/style.d.ts.map +1 -0
- package/dist/directives/style.js +2 -0
- package/dist/directives/style.js.map +1 -0
- package/dist/directives/until.cjs +2 -0
- package/dist/directives/until.cjs.map +1 -0
- package/dist/directives/until.d.ts +26 -0
- package/dist/directives/until.d.ts.map +1 -0
- package/dist/directives/until.js +2 -0
- package/dist/directives/until.js.map +1 -0
- package/dist/directives/when.cjs +2 -0
- package/dist/directives/when.cjs.map +1 -0
- package/dist/directives/when.d.ts +17 -0
- package/dist/directives/when.d.ts.map +1 -0
- package/dist/directives/when.js +2 -0
- package/dist/directives/when.js.map +1 -0
- package/dist/index.cjs +1 -2
- package/dist/index.d.ts +10 -265
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -13
- package/dist/labs/a11y.cjs +2 -0
- package/dist/labs/a11y.cjs.map +1 -0
- package/dist/labs/a11y.d.ts +61 -0
- package/dist/labs/a11y.d.ts.map +1 -0
- package/dist/labs/a11y.js +2 -0
- package/dist/labs/a11y.js.map +1 -0
- package/dist/labs/index.d.ts +8 -0
- package/dist/labs/index.d.ts.map +1 -0
- package/dist/labs/list.cjs +2 -0
- package/dist/labs/list.cjs.map +1 -0
- package/dist/labs/list.d.ts +26 -0
- package/dist/labs/list.d.ts.map +1 -0
- package/dist/labs/list.js +2 -0
- package/dist/labs/list.js.map +1 -0
- package/dist/labs/observers.cjs +2 -0
- package/dist/labs/observers.cjs.map +1 -0
- package/dist/labs/observers.d.ts +42 -0
- package/dist/labs/observers.d.ts.map +1 -0
- package/dist/labs/observers.js +2 -0
- package/dist/labs/observers.js.map +1 -0
- package/dist/labs/overlay.cjs +2 -0
- package/dist/labs/overlay.cjs.map +1 -0
- package/dist/labs/overlay.d.ts +35 -0
- package/dist/labs/overlay.d.ts.map +1 -0
- package/dist/labs/overlay.js +2 -0
- package/dist/labs/overlay.js.map +1 -0
- package/dist/labs/selectable.cjs +2 -0
- package/dist/labs/selectable.cjs.map +1 -0
- package/dist/labs/selectable.d.ts +70 -0
- package/dist/labs/selectable.d.ts.map +1 -0
- package/dist/labs/selectable.js +2 -0
- package/dist/labs/selectable.js.map +1 -0
- package/dist/labs/selection.cjs +2 -0
- package/dist/labs/selection.cjs.map +1 -0
- package/dist/labs/selection.d.ts +68 -0
- package/dist/labs/selection.d.ts.map +1 -0
- package/dist/labs/selection.js +2 -0
- package/dist/labs/selection.js.map +1 -0
- package/dist/labs.cjs +1 -0
- package/dist/labs.js +1 -0
- package/dist/test/index.d.ts +2 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/test.cjs +2 -0
- package/dist/test/test.cjs.map +1 -0
- package/dist/test/test.d.ts +198 -0
- package/dist/test/test.d.ts.map +1 -0
- package/dist/test/test.js +2 -0
- package/dist/test/test.js.map +1 -0
- package/dist/test.cjs +1 -0
- package/dist/test.js +1 -0
- package/package.json +37 -9
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-dom.js","names":[],"sources":["../../src/core/template-dom.ts"],"sourcesContent":["import { CF_ID_ATTR } from './internal';\n\nexport type BindingTargets = {\n comments: Map<string, Comment>;\n elements: Map<string, HTMLElement>;\n};\n\nconst templateCache = new Map<string, HTMLTemplateElement>();\nconst TEMPLATE_CACHE_MAX = 1000;\n\nconst getCachedTemplate = (html: string): HTMLTemplateElement => {\n let tpl = templateCache.get(html);\n\n if (!tpl) {\n tpl = document.createElement('template');\n tpl.innerHTML = html;\n\n if (templateCache.size >= TEMPLATE_CACHE_MAX) {\n const oldestKey = templateCache.keys().next().value as string | undefined;\n\n if (oldestKey !== undefined) templateCache.delete(oldestKey);\n }\n\n templateCache.set(html, tpl);\n }\n\n return tpl;\n};\n\nexport const parseHTML = (html: string): DocumentFragment =>\n getCachedTemplate(html).content.cloneNode(true) as DocumentFragment;\n\nconst collectBindingTarget = (node: Node, targets: BindingTargets): void => {\n if (node.nodeType === Node.COMMENT_NODE) {\n const marker = (node as Comment).nodeValue;\n\n if (marker) targets.comments.set(marker, node as Comment);\n\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n\n const id = (node as Element).getAttribute(CF_ID_ATTR);\n\n if (id) targets.elements.set(id, node as HTMLElement);\n};\n\nexport const indexBindings = (root: Node): BindingTargets => {\n const targets: BindingTargets = { comments: new Map(), elements: new Map() };\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT);\n\n collectBindingTarget(root, targets);\n\n while (walker.nextNode()) collectBindingTarget(walker.currentNode, targets);\n\n return targets;\n};\n\nexport const indexBindingsInNodes = (nodes: Iterable<Node>): BindingTargets => {\n const targets: BindingTargets = { comments: new Map(), elements: new Map() };\n\n for (const node of nodes) {\n const walker = document.createTreeWalker(node, NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT);\n\n collectBindingTarget(node, targets);\n\n while (walker.nextNode()) collectBindingTarget(walker.currentNode, targets);\n }\n\n return targets;\n};\nexport const findCommentMarker = (root: Node, marker: string): Comment | null => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n\n if (comment.nodeValue === marker) return comment;\n }\n\n return null;\n};\n\nexport const isHtmlBindingMarker = (node: Node): boolean =>\n node.nodeType === Node.COMMENT_NODE &&\n ((node as Comment).data === 'html-binding' || (node as Comment).data.startsWith('__h_'));\n\nexport const clearAfterMarker = (marker: Comment): void => {\n let next = marker.nextSibling;\n\n while (next) {\n if (isHtmlBindingMarker(next)) break;\n\n const toRemove = next;\n\n next = next.nextSibling;\n toRemove.remove();\n }\n};\n\nexport const createNodes = (htmlString: string): Node[] => Array.from(parseHTML(htmlString).childNodes);\n\nexport const insertNodes = (marker: Comment, nodes: Node[], before: Node | null): void => {\n if (marker.parentNode) {\n for (const node of nodes) marker.parentNode.insertBefore(node, before);\n }\n};\n"],"mappings":"sBAOA,IAAM,EAAgB,IAAI,IACpB,EAAqB,IAErB,EAAqB,GAAsC,CAC/D,IAAI,EAAM,EAAc,IAAI,EAAK,CAEjC,GAAI,CAAC,EAAK,CAIR,GAHA,EAAM,SAAS,cAAc,WAAW,CACxC,EAAI,UAAY,EAEZ,EAAc,MAAQ,EAAoB,CAC5C,IAAM,EAAY,EAAc,MAAM,CAAC,MAAM,CAAC,MAE1C,IAAc,IAAA,IAAW,EAAc,OAAO,EAAU,CAG9D,EAAc,IAAI,EAAM,EAAI,CAG9B,OAAO,GAGI,EAAa,GACxB,EAAkB,EAAK,CAAC,QAAQ,UAAU,GAAK,CAE3C,GAAwB,EAAY,IAAkC,CAC1E,GAAI,EAAK,WAAa,KAAK,aAAc,CACvC,IAAM,EAAU,EAAiB,UAE7B,GAAQ,EAAQ,SAAS,IAAI,EAAQ,EAAgB,CAEzD,OAGF,GAAI,EAAK,WAAa,KAAK,aAAc,OAEzC,IAAM,EAAM,EAAiB,aAAA,IAAwB,CAEjD,GAAI,EAAQ,SAAS,IAAI,EAAI,EAAoB,EAG1C,EAAiB,GAA+B,CAC3D,IAAM,EAA0B,CAAE,SAAU,IAAI,IAAO,SAAU,IAAI,IAAO,CACtE,EAAS,SAAS,iBAAiB,EAAM,WAAW,aAAe,WAAW,aAAa,CAIjG,IAFA,EAAqB,EAAM,EAAQ,CAE5B,EAAO,UAAU,EAAE,EAAqB,EAAO,YAAa,EAAQ,CAE3E,OAAO,GAGI,EAAwB,GAA0C,CAC7E,IAAM,EAA0B,CAAE,SAAU,IAAI,IAAO,SAAU,IAAI,IAAO,CAE5E,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAS,SAAS,iBAAiB,EAAM,WAAW,aAAe,WAAW,aAAa,CAIjG,IAFA,EAAqB,EAAM,EAAQ,CAE5B,EAAO,UAAU,EAAE,EAAqB,EAAO,YAAa,EAAQ,CAG7E,OAAO,GAEI,GAAqB,EAAY,IAAmC,CAC/E,IAAM,EAAS,SAAS,iBAAiB,EAAM,WAAW,aAAa,CAEvE,KAAO,EAAO,UAAU,EAAE,CACxB,IAAM,EAAU,EAAO,YAEvB,GAAI,EAAQ,YAAc,EAAQ,OAAO,EAG3C,OAAO,MAoBI,EAAe,GAA+B,MAAM,KAAK,EAAU,EAAW,CAAC,WAAW,CAE1F,GAAe,EAAiB,EAAe,IAA8B,CACxF,GAAI,EAAO,WACT,IAAK,IAAM,KAAQ,EAAO,EAAO,WAAW,aAAa,EAAM,EAAO"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require(`./internal.cjs`);const e=require(`./utilities.cjs`),t=require(`./template-dom.cjs`),n=require(`./template-bindings.cjs`);let r=require(`@vielzeug/stateit`);var i=t=>{e.runAll(t.cleanups);for(let e of t.nodes)e.remove()},a=(e,r,i=t.indexBindingsInNodes(e))=>{let a=[];return n.applyBindingsWithTargets(r,e=>a.push(e),i),a},o=(n,s,c,l,u)=>{let d=t.findCommentMarker(n,s.uid);if(!d)return;let f=document.createComment(`html-binding`);d.replaceWith(f);let p=[],m=e=>p.push(e),h=()=>{e.runAll(p),p=[]},g=null,_=[];c((0,r.effect)(()=>{(0,r.batch)(()=>{let c=s.signal.value;if(!s.keyed&&c.html===g)return;g=c.html,h();let{bindings:d,html:p,keys:v}=c;s.keyed&&!l.has(s.uid)&&l.set(s.uid,new Map);let y=s.keyed?l.get(s.uid):null,b=f.parentElement||n,x=!1;(0,r.untrack)(()=>{(0,r.batch)(()=>{if(y&&v?.length&&c.items?.length===v.length){if(x=!0,y.size===0&&_.length>0){for(let e of _)e.remove();_=[]}let n=new Map;for(let r=0;r<v.length;r++){let i=v[r],o=c.items[r],s=y.get(i),l=r>0?n.get(v[r-1])?.nodes:null,u=l?.length?l[l.length-1].nextSibling:f.nextSibling;if(s?.html===o.html){s.nodes[0]&&t.insertNodes(f,s.nodes,u),e.runAll(s.cleanups);let r=t.indexBindingsInNodes(s.nodes),c=a(s.nodes,o.bindings,r);n.set(i,{...s,bindings:o.bindings,cleanups:c,targets:r})}else if(s){e.runAll(s.cleanups);let r=t.createNodes(o.html),c=t.indexBindingsInNodes(r);t.insertNodes(f,r,u);let l=a(r,o.bindings,c);n.set(i,{bindings:o.bindings,cleanups:l,html:o.html,nodes:r,targets:c});for(let e of s.nodes)e.remove()}else{let e=t.createNodes(o.html),r=t.indexBindingsInNodes(e);t.insertNodes(f,e,u);let s=a(e,o.bindings,r);n.set(i,{bindings:o.bindings,cleanups:s,html:o.html,nodes:e,targets:r})}}for(let[e,t]of y)n.has(e)||i(t);l.set(s.uid,n)}else{if(s.keyed&&y&&y.size>0)for(let[,e]of y)i(e);else for(let e of _)e.remove();let e=t.parseHTML(p);_=Array.from(e.childNodes),f.after(e),s.keyed&&l.set(s.uid,new Map)}}),x||u(b,d,m,{onHtml:e=>o(b,e,m,l,u)})})})})),c(h),s.keyed&&c(()=>l.delete(s.uid))};exports.applyHtmlBinding=o;
|
|
2
|
+
//# sourceMappingURL=template-html.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-html.cjs","names":[],"sources":["../../src/core/template-html.ts"],"sourcesContent":["import { batch, untrack, effect as _effect, type CleanupFn } from '@vielzeug/stateit';\n\nimport { type Binding, type HtmlBinding } from './internal';\nimport { applyBindingsWithTargets } from './template-bindings';\nimport { type RegisterCleanup } from './template-bindings';\nimport {\n createNodes,\n findCommentMarker,\n indexBindingsInNodes,\n insertNodes,\n parseHTML,\n type BindingTargets,\n} from './template-dom';\nimport { runAll } from './utilities';\n\n/** Keyed reconciliation node — holds DOM nodes + lifecycle for one `each()` item. */\nexport type KeyedNode = {\n bindings: Binding[];\n cleanups: CleanupFn[];\n html: string;\n nodes: Node[];\n targets: BindingTargets;\n};\n\nconst removeKeyed = (keyedNode: KeyedNode) => {\n runAll(keyedNode.cleanups);\n for (const n of keyedNode.nodes) (n as ChildNode).remove();\n};\n\n/** Apply bindings to keyed item nodes using pre-indexed targets. */\nconst applyKeyedItemBindings = (\n nodes: Node[],\n itemBindings: Binding[],\n targets = indexBindingsInNodes(nodes),\n): CleanupFn[] => {\n const itemCleanups: CleanupFn[] = [];\n const itemRegisterCleanup: RegisterCleanup = (fn) => itemCleanups.push(fn);\n\n applyBindingsWithTargets(itemBindings, itemRegisterCleanup, targets);\n\n return itemCleanups;\n};\n\n/**\n * Sets up the reactive effect for an html-binding marker. Handles both non-keyed\n * (full replace) and keyed (`each()`) reconciliation.\n *\n * @param root The root node containing the marker comment.\n * @param b The HtmlBinding descriptor.\n * @param registerCleanup Function that registers a cleanup tied to the outer container's lifetime.\n * @param keyedStates Per-element map of `marker → (key → KeyedNode)` — caller owns this state.\n * @param applyBindingsInContainer Function to apply bindings to container.\n */\nexport const applyHtmlBinding = (\n root: Node,\n b: HtmlBinding,\n registerCleanup: RegisterCleanup,\n keyedStates: Map<string, Map<string | number, KeyedNode>>,\n applyBindingsInContainer: (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n ) => void,\n): void => {\n const found = findCommentMarker(root, b.uid);\n\n if (!found) return;\n\n const marker = document.createComment('html-binding');\n\n found.replaceWith(marker);\n\n let currentCleanups: CleanupFn[] = [];\n const registerInnerCleanup: RegisterCleanup = (fn) => currentCleanups.push(fn);\n const runCurrentCleanups = () => {\n runAll(currentCleanups);\n currentCleanups = [];\n };\n let lastHtml: string | null = null;\n let lastInsertedNodes: Node[] = [];\n\n // Use stateit.effect directly so cleanup is managed manually via registerCleanup, not autoCleanup.\n const stop = _effect(() => {\n batch(() => {\n const data = b.signal.value;\n\n if (!b.keyed && data.html === lastHtml) {\n return;\n }\n\n lastHtml = data.html;\n\n runCurrentCleanups();\n\n const { bindings, html, keys } = data;\n\n if (b.keyed && !keyedStates.has(b.uid)) keyedStates.set(b.uid, new Map());\n\n const keyedState = b.keyed ? keyedStates.get(b.uid)! : null;\n const container = (marker.parentElement || root) as ParentNode;\n\n let bindingsAlreadyApplied = false;\n\n untrack(() => {\n batch(() => {\n if (keyedState && keys?.length && data.items?.length === keys.length) {\n bindingsAlreadyApplied = true;\n\n // Transition from empty/fallback insertion back to keyed list items.\n if (keyedState.size === 0 && lastInsertedNodes.length > 0) {\n for (const n of lastInsertedNodes) (n as ChildNode).remove();\n lastInsertedNodes = [];\n }\n\n const newKeyedState = new Map<string | number, KeyedNode>();\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const itemData = data.items[i];\n const existing = keyedState.get(key);\n\n const prevNodes = i > 0 ? newKeyedState.get(keys[i - 1])?.nodes : null;\n const insertPoint = prevNodes?.length ? prevNodes[prevNodes.length - 1].nextSibling : marker.nextSibling;\n\n if (existing?.html === itemData.html) {\n // UPDATE: Same HTML — reuse nodes, reapply bindings\n if (existing.nodes[0]) insertNodes(marker, existing.nodes, insertPoint);\n\n runAll(existing.cleanups);\n\n const itemTargets = indexBindingsInNodes(existing.nodes);\n const itemCleanups = applyKeyedItemBindings(existing.nodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n ...existing,\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n targets: itemTargets,\n });\n } else if (existing) {\n // REPLACE: Different HTML — create new nodes, remove old\n runAll(existing.cleanups);\n\n const newNodes = createNodes(itemData.html);\n const itemTargets = indexBindingsInNodes(newNodes);\n\n insertNodes(marker, newNodes, insertPoint);\n\n const itemCleanups = applyKeyedItemBindings(newNodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n html: itemData.html,\n nodes: newNodes,\n targets: itemTargets,\n });\n for (const n of existing.nodes) (n as ChildNode).remove();\n } else {\n // CREATE: New item\n const newNodes = createNodes(itemData.html);\n const itemTargets = indexBindingsInNodes(newNodes);\n\n insertNodes(marker, newNodes, insertPoint);\n\n const itemCleanups = applyKeyedItemBindings(newNodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n html: itemData.html,\n nodes: newNodes,\n targets: itemTargets,\n });\n }\n }\n\n // DELETE: Remove old items not in new state\n for (const [oldKey, oldNode] of keyedState) {\n if (!newKeyedState.has(oldKey)) removeKeyed(oldNode);\n }\n\n keyedStates.set(b.uid, newKeyedState);\n } else {\n // Non-keyed or empty list: replace previously inserted nodes.\n if (b.keyed && keyedState && keyedState.size > 0) {\n for (const [, kn] of keyedState) removeKeyed(kn);\n } else {\n for (const n of lastInsertedNodes) (n as ChildNode).remove();\n }\n\n const parsed = parseHTML(html);\n\n lastInsertedNodes = Array.from(parsed.childNodes);\n marker.after(parsed);\n\n if (b.keyed) keyedStates.set(b.uid, new Map());\n }\n });\n\n if (!bindingsAlreadyApplied) {\n applyBindingsInContainer(container, bindings, registerInnerCleanup, {\n onHtml: (binding) =>\n applyHtmlBinding(container, binding, registerInnerCleanup, keyedStates, applyBindingsInContainer),\n });\n }\n });\n });\n });\n\n registerCleanup(stop);\n registerCleanup(runCurrentCleanups);\n\n if (b.keyed) registerCleanup(() => keyedStates.delete(b.uid));\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type CleanupFn } from '@vielzeug/stateit';
|
|
2
|
+
import { type Binding, type HtmlBinding } from './internal';
|
|
3
|
+
import { type RegisterCleanup } from './template-bindings';
|
|
4
|
+
import { type BindingTargets } from './template-dom';
|
|
5
|
+
/** Keyed reconciliation node — holds DOM nodes + lifecycle for one `each()` item. */
|
|
6
|
+
export type KeyedNode = {
|
|
7
|
+
bindings: Binding[];
|
|
8
|
+
cleanups: CleanupFn[];
|
|
9
|
+
html: string;
|
|
10
|
+
nodes: Node[];
|
|
11
|
+
targets: BindingTargets;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Sets up the reactive effect for an html-binding marker. Handles both non-keyed
|
|
15
|
+
* (full replace) and keyed (`each()`) reconciliation.
|
|
16
|
+
*
|
|
17
|
+
* @param root The root node containing the marker comment.
|
|
18
|
+
* @param b The HtmlBinding descriptor.
|
|
19
|
+
* @param registerCleanup Function that registers a cleanup tied to the outer container's lifetime.
|
|
20
|
+
* @param keyedStates Per-element map of `marker → (key → KeyedNode)` — caller owns this state.
|
|
21
|
+
* @param applyBindingsInContainer Function to apply bindings to container.
|
|
22
|
+
*/
|
|
23
|
+
export declare const applyHtmlBinding: (root: Node, b: HtmlBinding, registerCleanup: RegisterCleanup, keyedStates: Map<string, Map<string | number, KeyedNode>>, applyBindingsInContainer: (container: ParentNode, bindings: Binding[], registerCleanup: RegisterCleanup, opts?: {
|
|
24
|
+
onHtml?: (b: HtmlBinding) => void;
|
|
25
|
+
}) => void) => void;
|
|
26
|
+
//# sourceMappingURL=template-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-html.d.ts","sourceRoot":"","sources":["../../src/core/template-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAGxB,qFAAqF;AACrF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;CACzB,CAAC;AAqBF;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,IAAI,EACV,GAAG,WAAW,EACd,iBAAiB,eAAe,EAChC,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,CAAC,EACzD,0BAA0B,CACxB,SAAS,EAAE,UAAU,EACrB,QAAQ,EAAE,OAAO,EAAE,EACnB,eAAe,EAAE,eAAe,EAChC,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,KACzC,IAAI,KACR,IAuJF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./internal.js";import{runAll as e}from"./utilities.js";import{createNodes as t,findCommentMarker as n,indexBindingsInNodes as r,insertNodes as i,parseHTML as a}from"./template-dom.js";import{applyBindingsWithTargets as o}from"./template-bindings.js";import{batch as s,effect as c,untrack as l}from"@vielzeug/stateit";var u=t=>{e(t.cleanups);for(let e of t.nodes)e.remove()},d=(e,t,n=r(e))=>{let i=[];return o(t,e=>i.push(e),n),i},f=(o,p,m,h,g)=>{let _=n(o,p.uid);if(!_)return;let v=document.createComment(`html-binding`);_.replaceWith(v);let y=[],b=e=>y.push(e),x=()=>{e(y),y=[]},S=null,C=[];m(c(()=>{s(()=>{let n=p.signal.value;if(!p.keyed&&n.html===S)return;S=n.html,x();let{bindings:c,html:m,keys:_}=n;p.keyed&&!h.has(p.uid)&&h.set(p.uid,new Map);let y=p.keyed?h.get(p.uid):null,w=v.parentElement||o,T=!1;l(()=>{s(()=>{if(y&&_?.length&&n.items?.length===_.length){if(T=!0,y.size===0&&C.length>0){for(let e of C)e.remove();C=[]}let a=new Map;for(let o=0;o<_.length;o++){let s=_[o],c=n.items[o],l=y.get(s),u=o>0?a.get(_[o-1])?.nodes:null,f=u?.length?u[u.length-1].nextSibling:v.nextSibling;if(l?.html===c.html){l.nodes[0]&&i(v,l.nodes,f),e(l.cleanups);let t=r(l.nodes),n=d(l.nodes,c.bindings,t);a.set(s,{...l,bindings:c.bindings,cleanups:n,targets:t})}else if(l){e(l.cleanups);let n=t(c.html),o=r(n);i(v,n,f);let u=d(n,c.bindings,o);a.set(s,{bindings:c.bindings,cleanups:u,html:c.html,nodes:n,targets:o});for(let e of l.nodes)e.remove()}else{let e=t(c.html),n=r(e);i(v,e,f);let o=d(e,c.bindings,n);a.set(s,{bindings:c.bindings,cleanups:o,html:c.html,nodes:e,targets:n})}}for(let[e,t]of y)a.has(e)||u(t);h.set(p.uid,a)}else{if(p.keyed&&y&&y.size>0)for(let[,e]of y)u(e);else for(let e of C)e.remove();let e=a(m);C=Array.from(e.childNodes),v.after(e),p.keyed&&h.set(p.uid,new Map)}}),T||g(w,c,b,{onHtml:e=>f(w,e,b,h,g)})})})})),m(x),p.keyed&&m(()=>h.delete(p.uid))};export{f as applyHtmlBinding};
|
|
2
|
+
//# sourceMappingURL=template-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-html.js","names":[],"sources":["../../src/core/template-html.ts"],"sourcesContent":["import { batch, untrack, effect as _effect, type CleanupFn } from '@vielzeug/stateit';\n\nimport { type Binding, type HtmlBinding } from './internal';\nimport { applyBindingsWithTargets } from './template-bindings';\nimport { type RegisterCleanup } from './template-bindings';\nimport {\n createNodes,\n findCommentMarker,\n indexBindingsInNodes,\n insertNodes,\n parseHTML,\n type BindingTargets,\n} from './template-dom';\nimport { runAll } from './utilities';\n\n/** Keyed reconciliation node — holds DOM nodes + lifecycle for one `each()` item. */\nexport type KeyedNode = {\n bindings: Binding[];\n cleanups: CleanupFn[];\n html: string;\n nodes: Node[];\n targets: BindingTargets;\n};\n\nconst removeKeyed = (keyedNode: KeyedNode) => {\n runAll(keyedNode.cleanups);\n for (const n of keyedNode.nodes) (n as ChildNode).remove();\n};\n\n/** Apply bindings to keyed item nodes using pre-indexed targets. */\nconst applyKeyedItemBindings = (\n nodes: Node[],\n itemBindings: Binding[],\n targets = indexBindingsInNodes(nodes),\n): CleanupFn[] => {\n const itemCleanups: CleanupFn[] = [];\n const itemRegisterCleanup: RegisterCleanup = (fn) => itemCleanups.push(fn);\n\n applyBindingsWithTargets(itemBindings, itemRegisterCleanup, targets);\n\n return itemCleanups;\n};\n\n/**\n * Sets up the reactive effect for an html-binding marker. Handles both non-keyed\n * (full replace) and keyed (`each()`) reconciliation.\n *\n * @param root The root node containing the marker comment.\n * @param b The HtmlBinding descriptor.\n * @param registerCleanup Function that registers a cleanup tied to the outer container's lifetime.\n * @param keyedStates Per-element map of `marker → (key → KeyedNode)` — caller owns this state.\n * @param applyBindingsInContainer Function to apply bindings to container.\n */\nexport const applyHtmlBinding = (\n root: Node,\n b: HtmlBinding,\n registerCleanup: RegisterCleanup,\n keyedStates: Map<string, Map<string | number, KeyedNode>>,\n applyBindingsInContainer: (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n ) => void,\n): void => {\n const found = findCommentMarker(root, b.uid);\n\n if (!found) return;\n\n const marker = document.createComment('html-binding');\n\n found.replaceWith(marker);\n\n let currentCleanups: CleanupFn[] = [];\n const registerInnerCleanup: RegisterCleanup = (fn) => currentCleanups.push(fn);\n const runCurrentCleanups = () => {\n runAll(currentCleanups);\n currentCleanups = [];\n };\n let lastHtml: string | null = null;\n let lastInsertedNodes: Node[] = [];\n\n // Use stateit.effect directly so cleanup is managed manually via registerCleanup, not autoCleanup.\n const stop = _effect(() => {\n batch(() => {\n const data = b.signal.value;\n\n if (!b.keyed && data.html === lastHtml) {\n return;\n }\n\n lastHtml = data.html;\n\n runCurrentCleanups();\n\n const { bindings, html, keys } = data;\n\n if (b.keyed && !keyedStates.has(b.uid)) keyedStates.set(b.uid, new Map());\n\n const keyedState = b.keyed ? keyedStates.get(b.uid)! : null;\n const container = (marker.parentElement || root) as ParentNode;\n\n let bindingsAlreadyApplied = false;\n\n untrack(() => {\n batch(() => {\n if (keyedState && keys?.length && data.items?.length === keys.length) {\n bindingsAlreadyApplied = true;\n\n // Transition from empty/fallback insertion back to keyed list items.\n if (keyedState.size === 0 && lastInsertedNodes.length > 0) {\n for (const n of lastInsertedNodes) (n as ChildNode).remove();\n lastInsertedNodes = [];\n }\n\n const newKeyedState = new Map<string | number, KeyedNode>();\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const itemData = data.items[i];\n const existing = keyedState.get(key);\n\n const prevNodes = i > 0 ? newKeyedState.get(keys[i - 1])?.nodes : null;\n const insertPoint = prevNodes?.length ? prevNodes[prevNodes.length - 1].nextSibling : marker.nextSibling;\n\n if (existing?.html === itemData.html) {\n // UPDATE: Same HTML — reuse nodes, reapply bindings\n if (existing.nodes[0]) insertNodes(marker, existing.nodes, insertPoint);\n\n runAll(existing.cleanups);\n\n const itemTargets = indexBindingsInNodes(existing.nodes);\n const itemCleanups = applyKeyedItemBindings(existing.nodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n ...existing,\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n targets: itemTargets,\n });\n } else if (existing) {\n // REPLACE: Different HTML — create new nodes, remove old\n runAll(existing.cleanups);\n\n const newNodes = createNodes(itemData.html);\n const itemTargets = indexBindingsInNodes(newNodes);\n\n insertNodes(marker, newNodes, insertPoint);\n\n const itemCleanups = applyKeyedItemBindings(newNodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n html: itemData.html,\n nodes: newNodes,\n targets: itemTargets,\n });\n for (const n of existing.nodes) (n as ChildNode).remove();\n } else {\n // CREATE: New item\n const newNodes = createNodes(itemData.html);\n const itemTargets = indexBindingsInNodes(newNodes);\n\n insertNodes(marker, newNodes, insertPoint);\n\n const itemCleanups = applyKeyedItemBindings(newNodes, itemData.bindings, itemTargets);\n\n newKeyedState.set(key, {\n bindings: itemData.bindings,\n cleanups: itemCleanups,\n html: itemData.html,\n nodes: newNodes,\n targets: itemTargets,\n });\n }\n }\n\n // DELETE: Remove old items not in new state\n for (const [oldKey, oldNode] of keyedState) {\n if (!newKeyedState.has(oldKey)) removeKeyed(oldNode);\n }\n\n keyedStates.set(b.uid, newKeyedState);\n } else {\n // Non-keyed or empty list: replace previously inserted nodes.\n if (b.keyed && keyedState && keyedState.size > 0) {\n for (const [, kn] of keyedState) removeKeyed(kn);\n } else {\n for (const n of lastInsertedNodes) (n as ChildNode).remove();\n }\n\n const parsed = parseHTML(html);\n\n lastInsertedNodes = Array.from(parsed.childNodes);\n marker.after(parsed);\n\n if (b.keyed) keyedStates.set(b.uid, new Map());\n }\n });\n\n if (!bindingsAlreadyApplied) {\n applyBindingsInContainer(container, bindings, registerInnerCleanup, {\n onHtml: (binding) =>\n applyHtmlBinding(container, binding, registerInnerCleanup, keyedStates, applyBindingsInContainer),\n });\n }\n });\n });\n });\n\n registerCleanup(stop);\n registerCleanup(runCurrentCleanups);\n\n if (b.keyed) registerCleanup(() => keyedStates.delete(b.uid));\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
require(`./internal.cjs`);const e=require(`./runtime-lifecycle.cjs`),t=require(`./template-dom.cjs`),n=require(`./template-bindings.cjs`),r=require(`./template-compiler.cjs`),i=require(`./template-html.cjs`);var a=(e,r,i,a)=>{n.applyBindingsWithTargets(r,i,t.indexBindings(e),a)},o=()=>{},s=(t,...n)=>r.compileTemplate(t,n,e.effect),c=(e,t,n,r)=>{i.applyHtmlBinding(e,t,n,r,a)};exports._resetMarkerIndex=o,exports.applyBindingsInContainer=a,exports.applyHtmlBinding=c,exports.html=s;
|
|
2
|
+
//# sourceMappingURL=template.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.cjs","names":[],"sources":["../../src/core/template.ts"],"sourcesContent":["import { type Binding, type HtmlBinding, type HTMLResult } from './internal';\nimport { effect } from './runtime-lifecycle';\nimport { applyBindingsWithTargets } from './template-bindings';\nimport { type RegisterCleanup } from './template-bindings';\nimport { compileTemplate, resetTemplateCompilerState } from './template-compiler';\nimport { indexBindings } from './template-dom';\nimport { applyHtmlBinding as applyHtmlBindingImpl, type KeyedNode } from './template-html';\n\n// ─── Re-exports for consumers ─────────────────────────────────────────────────\nexport type { KeyedNode };\n\n// ─── Binding application orchestration ────────────────────────────────────────\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindings(container), opts);\n};\n\n// ─── Reset and compilation ────────────────────────────────────────────────────\n\nexport const _resetMarkerIndex = (): void => {\n resetTemplateCompilerState();\n};\n\nexport const html = (strings: TemplateStringsArray, ...values: unknown[]): HTMLResult =>\n compileTemplate(strings, values, effect);\n\n// ─── HTML binding with keyed reconciliation ────────────────────────────────────\n\nexport const applyHtmlBinding = (\n root: Node,\n b: HtmlBinding,\n registerCleanup: RegisterCleanup,\n keyedStates: Map<string, Map<string | number, KeyedNode>>,\n): void => {\n applyHtmlBindingImpl(root, b, registerCleanup, keyedStates, applyBindingsInContainer);\n};\n"],"mappings":"gNAaA,IAAa,GACX,EACA,EACA,EACA,IACG,CACH,EAAA,yBAAyB,EAAU,EAAiB,EAAA,cAAc,EAAU,CAAE,EAAK,EAKxE,MAAgC,GAIhC,GAAQ,EAA+B,GAAG,IACrD,EAAA,gBAAgB,EAAS,EAAQ,EAAA,OAAO,CAI7B,GACX,EACA,EACA,EACA,IACS,CACT,EAAA,iBAAqB,EAAM,EAAG,EAAiB,EAAa,EAAyB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Binding, type HtmlBinding, type HTMLResult } from './internal';
|
|
2
|
+
import { type RegisterCleanup } from './template-bindings';
|
|
3
|
+
import { type KeyedNode } from './template-html';
|
|
4
|
+
export type { KeyedNode };
|
|
5
|
+
export declare const applyBindingsInContainer: (container: ParentNode, bindings: Binding[], registerCleanup: RegisterCleanup, opts?: {
|
|
6
|
+
onHtml?: (b: HtmlBinding) => void;
|
|
7
|
+
}) => void;
|
|
8
|
+
export declare const _resetMarkerIndex: () => void;
|
|
9
|
+
export declare const html: (strings: TemplateStringsArray, ...values: unknown[]) => HTMLResult;
|
|
10
|
+
export declare const applyHtmlBinding: (root: Node, b: HtmlBinding, registerCleanup: RegisterCleanup, keyedStates: Map<string, Map<string | number, KeyedNode>>) => void;
|
|
11
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/core/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG3D,OAAO,EAA4C,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG3F,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,eAAO,MAAM,wBAAwB,GACnC,WAAW,UAAU,EACrB,UAAU,OAAO,EAAE,EACnB,iBAAiB,eAAe,EAChC,OAAO;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,SAG7C,CAAC;AAIF,eAAO,MAAM,iBAAiB,QAAO,IAEpC,CAAC;AAEF,eAAO,MAAM,IAAI,GAAI,SAAS,oBAAoB,EAAE,GAAG,QAAQ,OAAO,EAAE,KAAG,UACjC,CAAC;AAI3C,eAAO,MAAM,gBAAgB,GAC3B,MAAM,IAAI,EACV,GAAG,WAAW,EACd,iBAAiB,eAAe,EAChC,aAAa,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,CAAC,KACxD,IAEF,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./internal.js";import{effect as e}from"./runtime-lifecycle.js";import{indexBindings as t}from"./template-dom.js";import{applyBindingsWithTargets as n}from"./template-bindings.js";import{compileTemplate as r}from"./template-compiler.js";import{applyHtmlBinding as i}from"./template-html.js";var a=(e,r,i,a)=>{n(r,i,t(e),a)},o=()=>{},s=(t,...n)=>r(t,n,e),c=(e,t,n,r)=>{i(e,t,n,r,a)};export{o as _resetMarkerIndex,a as applyBindingsInContainer,c as applyHtmlBinding,s as html};
|
|
2
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","names":[],"sources":["../../src/core/template.ts"],"sourcesContent":["import { type Binding, type HtmlBinding, type HTMLResult } from './internal';\nimport { effect } from './runtime-lifecycle';\nimport { applyBindingsWithTargets } from './template-bindings';\nimport { type RegisterCleanup } from './template-bindings';\nimport { compileTemplate, resetTemplateCompilerState } from './template-compiler';\nimport { indexBindings } from './template-dom';\nimport { applyHtmlBinding as applyHtmlBindingImpl, type KeyedNode } from './template-html';\n\n// ─── Re-exports for consumers ─────────────────────────────────────────────────\nexport type { KeyedNode };\n\n// ─── Binding application orchestration ────────────────────────────────────────\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindings(container), opts);\n};\n\n// ─── Reset and compilation ────────────────────────────────────────────────────\n\nexport const _resetMarkerIndex = (): void => {\n resetTemplateCompilerState();\n};\n\nexport const html = (strings: TemplateStringsArray, ...values: unknown[]): HTMLResult =>\n compileTemplate(strings, values, effect);\n\n// ─── HTML binding with keyed reconciliation ────────────────────────────────────\n\nexport const applyHtmlBinding = (\n root: Node,\n b: HtmlBinding,\n registerCleanup: RegisterCleanup,\n keyedStates: Map<string, Map<string | number, KeyedNode>>,\n): void => {\n applyHtmlBindingImpl(root, b, registerCleanup, keyedStates, applyBindingsInContainer);\n};\n"],"mappings":"ySAaA,IAAa,GACX,EACA,EACA,EACA,IACG,CACH,EAAyB,EAAU,EAAiB,EAAc,EAAU,CAAE,EAAK,EAKxE,MAAgC,GAIhC,GAAQ,EAA+B,GAAG,IACrD,EAAgB,EAAS,EAAQ,EAAO,CAI7B,GACX,EACA,EACA,EACA,IACS,CACT,EAAqB,EAAM,EAAG,EAAiB,EAAa,EAAyB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./runtime-lifecycle.cjs`);var t=0,n=()=>{t=0},r=e=>{for(let t of e)t()},i=(e,t,n)=>{n==null||n===!1?e.removeAttribute(t):n===!0?e.setAttribute(t,``):e.setAttribute(t,String(n))},a=(e,t,n,r)=>{let i=n;return e.addEventListener(t,i,r),()=>e.removeEventListener(t,i,r)},o=e=>`${e?`${e}-`:`cft-`}${++t}`,s=(e,t)=>{let n=`${e}-${t&&t.trim()?t:o(e)}`;return{errorId:`error-${n}`,fieldId:n,helperId:`helper-${n}`,labelId:`label-${n}`}},c=(e,t)=>n=>{e()&&t(n)},l=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),u={"'":`'`,'"':`"`,"&":`&`,"<":`<`,">":`>`},d=e=>String(e).replace(/[&<>"']/g,e=>u[e]),f=()=>{let t=e.currentRuntime().el;return((n,...r)=>{e.fire.custom(t,String(n),r.length>0?{detail:r[0]}:void 0)})},p=function(){return this.content},m=(e,...t)=>{let n=``;for(let r=0;r<e.length;r++)if(n+=e[r],r<t.length){let e=t[r];n+=e&&typeof e==`object`&&`content`in e?e.content:e??``}return{content:n.trim(),toString:p}},h=new Map,g=e=>{if(e instanceof CSSStyleSheet)return e;let t=typeof e==`string`?e:e.content,n=h.get(t);if(n)return n;let r=new CSSStyleSheet;try{r.replaceSync(t),h.set(t,r)}catch(e){console.error(`[craftit:E2] style replace failed`,e)}return r};exports._resetIdCounter=n,exports.createEmitFn=f,exports.createFormIds=s,exports.createId=o,exports.css=m,exports.escapeHtml=d,exports.guard=c,exports.listen=a,exports.loadStylesheet=g,exports.runAll=r,exports.setAttr=i,exports.toKebab=l;
|
|
2
|
+
//# sourceMappingURL=utilities.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.cjs","names":[],"sources":["../../src/core/utilities.ts"],"sourcesContent":["/**\n * Utilities — DOM helpers, ID generation, event handling, CSS compilation, and emit functions.\n *\n * This module consolidates:\n * - DOM and string utilities (setAttr, listen, createId, createFormIds, guard, escapeHtml, toKebab)\n * - ID generation and form field ID helpers\n * - Emitter for type-safe custom events\n * - CSS template tag and stylesheet caching\n * - Style loader for adoptedStyleSheets\n */\n\nimport { currentRuntime, fire } from './runtime-lifecycle';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// COMMON DOM & STRING UTILITIES\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ─── Counter singletons ───────────────────────────────────────────────────────\nlet _idCounter = 0;\n\n/** @internal — resets the ID counter. Used by _resetCounters in test/test.ts. */\nexport const _resetIdCounter = (): void => {\n _idCounter = 0;\n};\n\n// ─── Shared DOM/string utilities ──────────────────────────────────────────────\n/** Iterate an iterable and call every function in it. */\nexport const runAll = (fns: Iterable<() => void>): void => {\n for (const fn of fns) fn();\n};\n\nexport const setAttr = (el: Element, name: string, val: unknown): void => {\n if (val == null || val === false) {\n el.removeAttribute(name);\n } else if (val === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, String(val));\n }\n};\n\nexport const listen = (\n el: EventTarget,\n name: string,\n handler: (e: any) => void,\n options?: AddEventListenerOptions,\n): (() => void) => {\n const listener: EventListener = handler as EventListener;\n\n el.addEventListener(name, listener, options);\n\n return () => el.removeEventListener(name, listener, options);\n};\n\n/**\n * Creates a unique, stable ID string — suitable for `aria-labelledby`, `aria-describedby`,\n * and similar accessibility linkages. Call once per component instance (at setup time or inside `onMount`).\n */\nexport const createId = (prefix?: string): string => `${prefix ? `${prefix}-` : 'cft-'}${++_idCounter}`;\n\n/**\n * Generates a stable set of ARIA-related IDs for a form control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n * `name` must be a non-empty string — callers that need a generated ID should\n * pass `createId(prefix)` as the name argument.\n *\n * @example\n * const { fieldId, labelId, helperId, errorId } = createFormIds('input', props.name.value);\n */\nexport const createFormIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name : createId(prefix);\n const fieldId = `${prefix}-${normalizedName}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelId: `label-${fieldId}`,\n };\n};\n\n/**\n * Wraps an event handler with a guard condition. The handler is only invoked when `condition()` returns `true`.\n * Use for disabled checks, readonly guards, or any runtime condition.\n *\n * @example\n * const handleClick = guard(() => !props.disabled.value, (e) => toggle(e));\n */\nexport const guard =\n <E extends Event = Event>(condition: () => unknown, handler: (e: E) => void): ((e: E) => void) =>\n (e) => {\n if (condition()) handler(e);\n };\n\nexport const toKebab = (str: string): string => str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\nconst _ESC: Record<string, string> = { \"'\": ''', '\"': '"', '&': '&', '<': '<', '>': '>' };\n\n/**\n * Escapes HTML entity characters (`&`, `<`, `>`, `\"`, `'`) in a value.\n * **Safe only in HTML text/attribute contexts.** Do NOT use for CSS values,\n * `javascript:` URLs, event handler attributes, or inline `<script>` content.\n */\nexport const escapeHtml = (value: unknown): string => String(value).replace(/[&<>\"']/g, (c) => _ESC[c]);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// EMIT FUNCTION (TYPE-SAFE CUSTOM EVENTS)\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\nexport type EmitFn<T extends Record<string, unknown>> = {\n <K extends KeysWithoutDetail<T>>(event: K): void;\n <K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): void;\n};\n\nexport const createEmitFn = <T extends Record<string, unknown>>(): EmitFn<T> => {\n const el = currentRuntime().el;\n\n return ((event: keyof T, ...rest: unknown[]) => {\n fire.custom(el, String(event), rest.length > 0 ? { detail: rest[0] } : undefined);\n }) as EmitFn<T>;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CSS & STYLESHEET UTILITIES\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type CSSResult = {\n content: string;\n toString(): string;\n};\n\nconst cssResultToString = function (this: CSSResult): string {\n return this.content;\n};\n\nexport const css = (strings: TemplateStringsArray, ...values: unknown[]): CSSResult => {\n let content = '';\n\n for (let i = 0; i < strings.length; i++) {\n content += strings[i];\n\n if (i < values.length) {\n const v = values[i];\n\n content += v && typeof v === 'object' && 'content' in v ? (v as CSSResult).content : (v ?? '');\n }\n }\n\n return { content: content.trim(), toString: cssResultToString };\n};\n\nconst stylesheetStringCache = new Map<string, CSSStyleSheet>();\n\nexport const loadStylesheet = (style: string | CSSStyleSheet | CSSResult): CSSStyleSheet => {\n if (style instanceof CSSStyleSheet) return style;\n\n const cssText = typeof style === 'string' ? style : style.content;\n const cached = stylesheetStringCache.get(cssText);\n\n if (cached) return cached;\n\n const sheet = new CSSStyleSheet();\n\n try {\n sheet.replaceSync(cssText);\n stylesheetStringCache.set(cssText, sheet);\n } catch (err) {\n console.error(`[craftit:E2] style replace failed`, err);\n }\n\n return sheet;\n};\n"],"mappings":"2CAkBA,IAAI,EAAa,EAGJ,MAA8B,CACzC,EAAa,GAKF,EAAU,GAAoC,CACzD,IAAK,IAAM,KAAM,EAAK,GAAI,EAGf,GAAW,EAAa,EAAc,IAAuB,CACpE,GAAO,MAAQ,IAAQ,GACzB,EAAG,gBAAgB,EAAK,CACf,IAAQ,GACjB,EAAG,aAAa,EAAM,GAAG,CAEzB,EAAG,aAAa,EAAM,OAAO,EAAI,CAAC,EAIzB,GACX,EACA,EACA,EACA,IACiB,CACjB,IAAM,EAA0B,EAIhC,OAFA,EAAG,iBAAiB,EAAM,EAAU,EAAQ,KAE/B,EAAG,oBAAoB,EAAM,EAAU,EAAQ,EAOjD,EAAY,GAA4B,GAAG,EAAS,GAAG,EAAO,GAAK,SAAS,EAAE,IAW9E,GAAiB,EAAgB,IAAyB,CAErE,IAAM,EAAU,GAAG,EAAO,GADH,GAAQ,EAAK,MAAM,CAAG,EAAO,EAAS,EAAO,GAGpE,MAAO,CACL,QAAS,SAAS,IAClB,UACA,SAAU,UAAU,IACpB,QAAS,SAAS,IACnB,EAUU,GACe,EAA0B,IACnD,GAAM,CACD,GAAW,EAAE,EAAQ,EAAE,EAGlB,EAAW,GAAwB,EAAI,QAAQ,SAAW,GAAM,IAAI,EAAE,aAAa,GAAG,CAE7F,EAA+B,CAAE,IAAK,QAAS,IAAK,SAAU,IAAK,QAAS,IAAK,OAAQ,IAAK,OAAQ,CAO/F,EAAc,GAA2B,OAAO,EAAM,CAAC,QAAQ,WAAa,GAAM,EAAK,GAAG,CAgB1F,MAAmE,CAC9E,IAAM,EAAK,EAAA,gBAAgB,CAAC,GAE5B,QAAS,EAAgB,GAAG,IAAoB,CAC9C,EAAA,KAAK,OAAO,EAAI,OAAO,EAAM,CAAE,EAAK,OAAS,EAAI,CAAE,OAAQ,EAAK,GAAI,CAAG,IAAA,GAAU,IAa/E,EAAoB,UAAmC,CAC3D,OAAO,KAAK,SAGD,GAAO,EAA+B,GAAG,IAAiC,CACrF,IAAI,EAAU,GAEd,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAGlC,GAFA,GAAW,EAAQ,GAEf,EAAI,EAAO,OAAQ,CACrB,IAAM,EAAI,EAAO,GAEjB,GAAW,GAAK,OAAO,GAAM,UAAY,YAAa,EAAK,EAAgB,QAAW,GAAK,GAI/F,MAAO,CAAE,QAAS,EAAQ,MAAM,CAAE,SAAU,EAAmB,EAG3D,EAAwB,IAAI,IAErB,EAAkB,GAA6D,CAC1F,GAAI,aAAiB,cAAe,OAAO,EAE3C,IAAM,EAAU,OAAO,GAAU,SAAW,EAAQ,EAAM,QACpD,EAAS,EAAsB,IAAI,EAAQ,CAEjD,GAAI,EAAQ,OAAO,EAEnB,IAAM,EAAQ,IAAI,cAElB,GAAI,CACF,EAAM,YAAY,EAAQ,CAC1B,EAAsB,IAAI,EAAS,EAAM,OAClC,EAAK,CACZ,QAAQ,MAAM,oCAAqC,EAAI,CAGzD,OAAO"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities — DOM helpers, ID generation, event handling, CSS compilation, and emit functions.
|
|
3
|
+
*
|
|
4
|
+
* This module consolidates:
|
|
5
|
+
* - DOM and string utilities (setAttr, listen, createId, createFormIds, guard, escapeHtml, toKebab)
|
|
6
|
+
* - ID generation and form field ID helpers
|
|
7
|
+
* - Emitter for type-safe custom events
|
|
8
|
+
* - CSS template tag and stylesheet caching
|
|
9
|
+
* - Style loader for adoptedStyleSheets
|
|
10
|
+
*/
|
|
11
|
+
/** @internal — resets the ID counter. Used by _resetCounters in test/test.ts. */
|
|
12
|
+
export declare const _resetIdCounter: () => void;
|
|
13
|
+
/** Iterate an iterable and call every function in it. */
|
|
14
|
+
export declare const runAll: (fns: Iterable<() => void>) => void;
|
|
15
|
+
export declare const setAttr: (el: Element, name: string, val: unknown) => void;
|
|
16
|
+
export declare const listen: (el: EventTarget, name: string, handler: (e: any) => void, options?: AddEventListenerOptions) => (() => void);
|
|
17
|
+
/**
|
|
18
|
+
* Creates a unique, stable ID string — suitable for `aria-labelledby`, `aria-describedby`,
|
|
19
|
+
* and similar accessibility linkages. Call once per component instance (at setup time or inside `onMount`).
|
|
20
|
+
*/
|
|
21
|
+
export declare const createId: (prefix?: string) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Generates a stable set of ARIA-related IDs for a form control.
|
|
24
|
+
* Snapshot `name` at call time — IDs are stable strings, not reactive.
|
|
25
|
+
* `name` must be a non-empty string — callers that need a generated ID should
|
|
26
|
+
* pass `createId(prefix)` as the name argument.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const { fieldId, labelId, helperId, errorId } = createFormIds('input', props.name.value);
|
|
30
|
+
*/
|
|
31
|
+
export declare const createFormIds: (prefix: string, name?: string | null) => {
|
|
32
|
+
errorId: string;
|
|
33
|
+
fieldId: string;
|
|
34
|
+
helperId: string;
|
|
35
|
+
labelId: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Wraps an event handler with a guard condition. The handler is only invoked when `condition()` returns `true`.
|
|
39
|
+
* Use for disabled checks, readonly guards, or any runtime condition.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const handleClick = guard(() => !props.disabled.value, (e) => toggle(e));
|
|
43
|
+
*/
|
|
44
|
+
export declare const guard: <E extends Event = Event>(condition: () => unknown, handler: (e: E) => void) => ((e: E) => void);
|
|
45
|
+
export declare const toKebab: (str: string) => string;
|
|
46
|
+
/**
|
|
47
|
+
* Escapes HTML entity characters (`&`, `<`, `>`, `"`, `'`) in a value.
|
|
48
|
+
* **Safe only in HTML text/attribute contexts.** Do NOT use for CSS values,
|
|
49
|
+
* `javascript:` URLs, event handler attributes, or inline `<script>` content.
|
|
50
|
+
*/
|
|
51
|
+
export declare const escapeHtml: (value: unknown) => string;
|
|
52
|
+
type NoDetail = void | undefined | never;
|
|
53
|
+
type KeysWithoutDetail<T extends Record<string, unknown>> = {
|
|
54
|
+
[P in keyof T]: [T[P]] extends [NoDetail] ? P : never;
|
|
55
|
+
}[keyof T];
|
|
56
|
+
export type EmitFn<T extends Record<string, unknown>> = {
|
|
57
|
+
<K extends KeysWithoutDetail<T>>(event: K): void;
|
|
58
|
+
<K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): void;
|
|
59
|
+
};
|
|
60
|
+
export declare const createEmitFn: <T extends Record<string, unknown>>() => EmitFn<T>;
|
|
61
|
+
export type CSSResult = {
|
|
62
|
+
content: string;
|
|
63
|
+
toString(): string;
|
|
64
|
+
};
|
|
65
|
+
export declare const css: (strings: TemplateStringsArray, ...values: unknown[]) => CSSResult;
|
|
66
|
+
export declare const loadStylesheet: (style: string | CSSStyleSheet | CSSResult) => CSSStyleSheet;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=utilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/core/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,iFAAiF;AACjF,eAAO,MAAM,eAAe,QAAO,IAElC,CAAC;AAGF,yDAAyD;AACzD,eAAO,MAAM,MAAM,GAAI,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAG,IAElD,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,IAAI,OAAO,EAAE,MAAM,MAAM,EAAE,KAAK,OAAO,KAAG,IAQjE,CAAC;AAEF,eAAO,MAAM,MAAM,GACjB,IAAI,WAAW,EACf,MAAM,MAAM,EACZ,SAAS,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,EACzB,UAAU,uBAAuB,KAChC,CAAC,MAAM,IAAI,CAMb,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,MAA4D,CAAC;AAExG;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,EAAE,OAAO,MAAM,GAAG,IAAI;;;;;CAUjE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GACf,CAAC,SAAS,KAAK,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,KAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAG5F,CAAC;AAEJ,eAAO,MAAM,OAAO,GAAI,KAAK,MAAM,KAAG,MAA6D,CAAC;AAIpG;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,MAA2D,CAAC;AAMxG,KAAK,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;AACzC,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KACzD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACtD,CAAC,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACjD,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CAClF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAK,MAAM,CAAC,CAAC,CAM1E,CAAC;AAMF,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,IAAI,MAAM,CAAC;CACpB,CAAC;AAMF,eAAO,MAAM,GAAG,GAAI,SAAS,oBAAoB,EAAE,GAAG,QAAQ,OAAO,EAAE,KAAG,SAczE,CAAC;AAIF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,GAAG,aAAa,GAAG,SAAS,KAAG,aAkB1E,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{currentRuntime as e,fire as t}from"./runtime-lifecycle.js";var n=0,r=()=>{n=0},i=e=>{for(let t of e)t()},a=(e,t,n)=>{n==null||n===!1?e.removeAttribute(t):n===!0?e.setAttribute(t,``):e.setAttribute(t,String(n))},o=(e,t,n,r)=>{let i=n;return e.addEventListener(t,i,r),()=>e.removeEventListener(t,i,r)},s=e=>`${e?`${e}-`:`cft-`}${++n}`,c=(e,t)=>{let n=`${e}-${t&&t.trim()?t:s(e)}`;return{errorId:`error-${n}`,fieldId:n,helperId:`helper-${n}`,labelId:`label-${n}`}},l=(e,t)=>n=>{e()&&t(n)},u=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),d={"'":`'`,'"':`"`,"&":`&`,"<":`<`,">":`>`},f=e=>String(e).replace(/[&<>"']/g,e=>d[e]),p=()=>{let n=e().el;return((e,...r)=>{t.custom(n,String(e),r.length>0?{detail:r[0]}:void 0)})},m=function(){return this.content},h=(e,...t)=>{let n=``;for(let r=0;r<e.length;r++)if(n+=e[r],r<t.length){let e=t[r];n+=e&&typeof e==`object`&&`content`in e?e.content:e??``}return{content:n.trim(),toString:m}},g=new Map,_=e=>{if(e instanceof CSSStyleSheet)return e;let t=typeof e==`string`?e:e.content,n=g.get(t);if(n)return n;let r=new CSSStyleSheet;try{r.replaceSync(t),g.set(t,r)}catch(e){console.error(`[craftit:E2] style replace failed`,e)}return r};export{r as _resetIdCounter,p as createEmitFn,c as createFormIds,s as createId,h as css,f as escapeHtml,l as guard,o as listen,_ as loadStylesheet,i as runAll,a as setAttr,u as toKebab};
|
|
2
|
+
//# sourceMappingURL=utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.js","names":[],"sources":["../../src/core/utilities.ts"],"sourcesContent":["/**\n * Utilities — DOM helpers, ID generation, event handling, CSS compilation, and emit functions.\n *\n * This module consolidates:\n * - DOM and string utilities (setAttr, listen, createId, createFormIds, guard, escapeHtml, toKebab)\n * - ID generation and form field ID helpers\n * - Emitter for type-safe custom events\n * - CSS template tag and stylesheet caching\n * - Style loader for adoptedStyleSheets\n */\n\nimport { currentRuntime, fire } from './runtime-lifecycle';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// COMMON DOM & STRING UTILITIES\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ─── Counter singletons ───────────────────────────────────────────────────────\nlet _idCounter = 0;\n\n/** @internal — resets the ID counter. Used by _resetCounters in test/test.ts. */\nexport const _resetIdCounter = (): void => {\n _idCounter = 0;\n};\n\n// ─── Shared DOM/string utilities ──────────────────────────────────────────────\n/** Iterate an iterable and call every function in it. */\nexport const runAll = (fns: Iterable<() => void>): void => {\n for (const fn of fns) fn();\n};\n\nexport const setAttr = (el: Element, name: string, val: unknown): void => {\n if (val == null || val === false) {\n el.removeAttribute(name);\n } else if (val === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, String(val));\n }\n};\n\nexport const listen = (\n el: EventTarget,\n name: string,\n handler: (e: any) => void,\n options?: AddEventListenerOptions,\n): (() => void) => {\n const listener: EventListener = handler as EventListener;\n\n el.addEventListener(name, listener, options);\n\n return () => el.removeEventListener(name, listener, options);\n};\n\n/**\n * Creates a unique, stable ID string — suitable for `aria-labelledby`, `aria-describedby`,\n * and similar accessibility linkages. Call once per component instance (at setup time or inside `onMount`).\n */\nexport const createId = (prefix?: string): string => `${prefix ? `${prefix}-` : 'cft-'}${++_idCounter}`;\n\n/**\n * Generates a stable set of ARIA-related IDs for a form control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n * `name` must be a non-empty string — callers that need a generated ID should\n * pass `createId(prefix)` as the name argument.\n *\n * @example\n * const { fieldId, labelId, helperId, errorId } = createFormIds('input', props.name.value);\n */\nexport const createFormIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name : createId(prefix);\n const fieldId = `${prefix}-${normalizedName}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelId: `label-${fieldId}`,\n };\n};\n\n/**\n * Wraps an event handler with a guard condition. The handler is only invoked when `condition()` returns `true`.\n * Use for disabled checks, readonly guards, or any runtime condition.\n *\n * @example\n * const handleClick = guard(() => !props.disabled.value, (e) => toggle(e));\n */\nexport const guard =\n <E extends Event = Event>(condition: () => unknown, handler: (e: E) => void): ((e: E) => void) =>\n (e) => {\n if (condition()) handler(e);\n };\n\nexport const toKebab = (str: string): string => str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\nconst _ESC: Record<string, string> = { \"'\": ''', '\"': '"', '&': '&', '<': '<', '>': '>' };\n\n/**\n * Escapes HTML entity characters (`&`, `<`, `>`, `\"`, `'`) in a value.\n * **Safe only in HTML text/attribute contexts.** Do NOT use for CSS values,\n * `javascript:` URLs, event handler attributes, or inline `<script>` content.\n */\nexport const escapeHtml = (value: unknown): string => String(value).replace(/[&<>\"']/g, (c) => _ESC[c]);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// EMIT FUNCTION (TYPE-SAFE CUSTOM EVENTS)\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype NoDetail = void | undefined | never;\ntype KeysWithoutDetail<T extends Record<string, unknown>> = {\n [P in keyof T]: [T[P]] extends [NoDetail] ? P : never;\n}[keyof T];\n\nexport type EmitFn<T extends Record<string, unknown>> = {\n <K extends KeysWithoutDetail<T>>(event: K): void;\n <K extends Exclude<keyof T, KeysWithoutDetail<T>>>(event: K, detail: T[K]): void;\n};\n\nexport const createEmitFn = <T extends Record<string, unknown>>(): EmitFn<T> => {\n const el = currentRuntime().el;\n\n return ((event: keyof T, ...rest: unknown[]) => {\n fire.custom(el, String(event), rest.length > 0 ? { detail: rest[0] } : undefined);\n }) as EmitFn<T>;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CSS & STYLESHEET UTILITIES\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type CSSResult = {\n content: string;\n toString(): string;\n};\n\nconst cssResultToString = function (this: CSSResult): string {\n return this.content;\n};\n\nexport const css = (strings: TemplateStringsArray, ...values: unknown[]): CSSResult => {\n let content = '';\n\n for (let i = 0; i < strings.length; i++) {\n content += strings[i];\n\n if (i < values.length) {\n const v = values[i];\n\n content += v && typeof v === 'object' && 'content' in v ? (v as CSSResult).content : (v ?? '');\n }\n }\n\n return { content: content.trim(), toString: cssResultToString };\n};\n\nconst stylesheetStringCache = new Map<string, CSSStyleSheet>();\n\nexport const loadStylesheet = (style: string | CSSStyleSheet | CSSResult): CSSStyleSheet => {\n if (style instanceof CSSStyleSheet) return style;\n\n const cssText = typeof style === 'string' ? style : style.content;\n const cached = stylesheetStringCache.get(cssText);\n\n if (cached) return cached;\n\n const sheet = new CSSStyleSheet();\n\n try {\n sheet.replaceSync(cssText);\n stylesheetStringCache.set(cssText, sheet);\n } catch (err) {\n console.error(`[craftit:E2] style replace failed`, err);\n }\n\n return sheet;\n};\n"],"mappings":"kEAkBA,IAAI,EAAa,EAGJ,MAA8B,CACzC,EAAa,GAKF,EAAU,GAAoC,CACzD,IAAK,IAAM,KAAM,EAAK,GAAI,EAGf,GAAW,EAAa,EAAc,IAAuB,CACpE,GAAO,MAAQ,IAAQ,GACzB,EAAG,gBAAgB,EAAK,CACf,IAAQ,GACjB,EAAG,aAAa,EAAM,GAAG,CAEzB,EAAG,aAAa,EAAM,OAAO,EAAI,CAAC,EAIzB,GACX,EACA,EACA,EACA,IACiB,CACjB,IAAM,EAA0B,EAIhC,OAFA,EAAG,iBAAiB,EAAM,EAAU,EAAQ,KAE/B,EAAG,oBAAoB,EAAM,EAAU,EAAQ,EAOjD,EAAY,GAA4B,GAAG,EAAS,GAAG,EAAO,GAAK,SAAS,EAAE,IAW9E,GAAiB,EAAgB,IAAyB,CAErE,IAAM,EAAU,GAAG,EAAO,GADH,GAAQ,EAAK,MAAM,CAAG,EAAO,EAAS,EAAO,GAGpE,MAAO,CACL,QAAS,SAAS,IAClB,UACA,SAAU,UAAU,IACpB,QAAS,SAAS,IACnB,EAUU,GACe,EAA0B,IACnD,GAAM,CACD,GAAW,EAAE,EAAQ,EAAE,EAGlB,EAAW,GAAwB,EAAI,QAAQ,SAAW,GAAM,IAAI,EAAE,aAAa,GAAG,CAE7F,EAA+B,CAAE,IAAK,QAAS,IAAK,SAAU,IAAK,QAAS,IAAK,OAAQ,IAAK,OAAQ,CAO/F,EAAc,GAA2B,OAAO,EAAM,CAAC,QAAQ,WAAa,GAAM,EAAK,GAAG,CAgB1F,MAAmE,CAC9E,IAAM,EAAK,GAAgB,CAAC,GAE5B,QAAS,EAAgB,GAAG,IAAoB,CAC9C,EAAK,OAAO,EAAI,OAAO,EAAM,CAAE,EAAK,OAAS,EAAI,CAAE,OAAQ,EAAK,GAAI,CAAG,IAAA,GAAU,IAa/E,EAAoB,UAAmC,CAC3D,OAAO,KAAK,SAGD,GAAO,EAA+B,GAAG,IAAiC,CACrF,IAAI,EAAU,GAEd,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAGlC,GAFA,GAAW,EAAQ,GAEf,EAAI,EAAO,OAAQ,CACrB,IAAM,EAAI,EAAO,GAEjB,GAAW,GAAK,OAAO,GAAM,UAAY,YAAa,EAAK,EAAgB,QAAW,GAAK,GAI/F,MAAO,CAAE,QAAS,EAAQ,MAAM,CAAE,SAAU,EAAmB,EAG3D,EAAwB,IAAI,IAErB,EAAkB,GAA6D,CAC1F,GAAI,aAAiB,cAAe,OAAO,EAE3C,IAAM,EAAU,OAAO,GAAU,SAAW,EAAQ,EAAM,QACpD,EAAS,EAAsB,IAAI,EAAQ,CAEjD,GAAI,EAAQ,OAAO,EAEnB,IAAM,EAAQ,IAAI,cAElB,GAAI,CACF,EAAM,YAAY,EAAQ,CAC1B,EAAsB,IAAI,EAAS,EAAM,OAClC,EAAK,CACZ,QAAQ,MAAM,oCAAqC,EAAI,CAGzD,OAAO"}
|
package/dist/craftit.cjs
CHANGED
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=new Map,g=r=>{if(d.has(r))return d.get(r);const t=r.replace(/-([a-z])/g,(e,s)=>s.toUpperCase());return d.set(r,t),t},f=new Map,l=r=>{if(f.has(r))return f.get(r);const t=r.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`);return f.set(r,t),t},p=r=>{const t=document.createElement("template");return t.innerHTML=r.trim(),t.content},A=async r=>{if(r instanceof CSSStyleSheet)return r;const t=new CSSStyleSheet;return await t.replace(r),t},v=(r,t)=>{const e={...r},s=new WeakMap,i=n=>{if(n==null||typeof n!="object"||n instanceof Node)return n;const o=s.get(n);if(o)return o;const a=new Proxy(n,{get(c,h){const u=Reflect.get(c,h);return i(u)},set(c,h,u){if(Reflect.get(c,h)===u)return!0;const y=Reflect.set(c,h,u);return typeof h=="string"&&!h.startsWith("_")&&t(),y}});return s.set(n,a),a};return new Proxy(e,{get(n,o){const a=Reflect.get(n,o);return i(a)},set(n,o,a){if(Reflect.get(n,o)===a)return!0;const h=Reflect.set(n,o,a);return typeof o=="string"&&!o.startsWith("_")&&t(),h}})};class C extends HTMLElement{shadow;state;value;#r=new AbortController;#i=new Set;#a=!1;#e=!1;#t;#s;#o;#n;#c=new Map;#h=0;constructor(t){super(),this.#t=t,this.shadow=this.attachShadow({mode:"open"}),this.state=v(t.state||{},()=>{this.render(),this.notifyWatchers()}),t.formAssociated&&"attachInternals"in this&&(this.#s=this.attachInternals()),this.initStyles(),this.initAttributes()}get root(){return this.shadow.firstElementChild}get internals(){return this.#s}get form(){if(this.#s)return{valid:(t,e,s)=>{!t||Object.keys(t).length===0?this.#s.setValidity({}):this.#s.setValidity(t,e,s)},value:(t,e)=>{typeof t=="string"&&(this.value=t),this.#s.setFormValue(t,e)}}}async initStyles(){if(!this.#t.styles?.length)return;const t=await Promise.all(this.#t.styles.map(A));this.shadow.adoptedStyleSheets=t}initAttributes(){const t=this.#t.observedAttributes;if(t?.length)for(const e of t){const s=g(e);s in this||Object.defineProperty(this,s,{configurable:!0,enumerable:!0,get:()=>{const i=this.getAttribute(e);return i===""?!0:i},set:i=>{i==null||i===!1?this.removeAttribute(e):this.setAttribute(e,i===!0?"":String(i))}})}}notifyWatchers(){for(const[,t]of this.#c)try{const e=t.selector(this.state);e!==t.lastValue&&(t.callback(e,t.lastValue),t.lastValue=e)}catch{}}connectedCallback(){this.#r.signal.aborted&&(this.#r=new AbortController),this.shadow.hasChildNodes()||this.performRender(),this.#t.onConnected?.(this)}disconnectedCallback(){this.#t.onDisconnected?.(this),this.#r.abort();for(const t of this.#i)clearTimeout(t);this.#i.clear()}attributeChangedCallback(t,e,s){e!==s&&(this.#t.onAttributeChanged?.(t,e,s,this),this.render())}formDisabledCallback(t){this.#t.onFormDisabled?.(t,this)}formResetCallback(){this.#t.onFormReset?.(this)}formStateRestoreCallback(t,e){this.#t.onFormStateRestore?.(t,e,this)}render(){this.#a||this.#e||(this.#a=!0,this.#n||(this.#n=new Promise(t=>{this.#o=t})),requestAnimationFrame(()=>{this.#a=!1,this.performRender(),this.#o?.(),this.#n=void 0,this.#o=void 0}))}async flush(){this.#n&&await this.#n}async set(t,e){if(typeof t=="function"){const i=await Promise.resolve(t(this.state));this.#e=!0;for(const n of Object.keys(this.state))delete this.state[n];Object.assign(this.state,i),this.#e=!1,e?.silent||(this.render(),await this.flush());return}const s=t;if(e?.replace){this.#e=!0;for(const i of Object.keys(this.state))delete this.state[i];Object.assign(this.state,s),this.#e=!1,e.silent||this.render()}else e?.silent?(this.#e=!0,Object.assign(this.state,s),this.#e=!1):Object.assign(this.state,s)}watch(t,e){const s=++this.#h,i=t(this.state);this.#c.set(s,{callback:e,lastValue:i,selector:t});try{e(i,i)}catch{}return()=>this.#c.delete(s)}find(t){return this.shadow.querySelector(t)}findAll(t){return Array.from(this.shadow.querySelectorAll(t))}on(t,e,s,i){if(typeof t=="string"){const n=t,o=a=>{const c=a.target;if(!c?.matches)return;const h=c.matches(n)?c:c.closest(n);h&&this.shadow.contains(h)&&(Object.defineProperty(a,"currentTarget",{configurable:!0,value:h}),s.call(h,a))};this.shadow.addEventListener(e,o,{...i,signal:this.#r.signal})}else t.addEventListener(e,s,{...i,signal:this.#r.signal})}emit(t,e,s){this.dispatchEvent(new CustomEvent(t,{bubbles:!0,composed:!0,detail:e,...s}))}delay(t,e){const s=setTimeout(()=>{this.#i.delete(s),t()},e);return this.#i.add(s),s}clear(t){clearTimeout(t),this.#i.delete(t)}performRender(){const{template:t}=this.#t;try{let e;typeof t=="function"?e=t(this):e=t;let s;if(typeof e=="string")s=Array.from(p(e).childNodes);else if(e instanceof DocumentFragment){const i=e.cloneNode(!0);s=Array.from(i.childNodes)}else s=[e.cloneNode(!0)];this.reconcile(this.shadow,s),this.#t.onUpdated?.(this)}catch(e){const s=e instanceof Error?e.message:String(e),i=e instanceof Error?e.stack:"";console.error("[craftit] Render error:",e),this.shadow.innerHTML=`
|
|
2
|
-
|
|
3
|
-
<strong>Render Error</strong>
|
|
4
|
-
<p style="margin: 0.5rem 0;">${s}</p>
|
|
5
|
-
${i?`<details style="margin: 0.5rem 0;"><summary>Stack Trace</summary><pre style="overflow: auto; font-size: 0.8em;">${i}</pre></details>`:""}
|
|
6
|
-
<button onclick="this.getRootNode().host.render()" style="margin-top: 0.5rem; padding: 0.25rem 0.5rem; cursor: pointer;">
|
|
7
|
-
Retry Render
|
|
8
|
-
</button>
|
|
9
|
-
</div>
|
|
10
|
-
`}}reconcile(t,e){const s=Array.from(t.childNodes),i=Math.max(s.length,e.length);for(let n=0;n<i;n++){const o=s[n],a=e[n];if(!o&&a){t.appendChild(a);continue}if(o&&!a){t.removeChild(o);continue}if(o&&a){if(o.nodeType!==a.nodeType){t.replaceChild(a,o);continue}if(o.nodeType===Node.TEXT_NODE){o.textContent!==a.textContent&&(o.textContent=a.textContent);continue}if(o instanceof Element&&a instanceof Element){if(o.tagName!==a.tagName){t.replaceChild(a,o);continue}this.updateElement(o,a)}}}}updateElement(t,e){const s=Array.from(t.attributes),i=Array.from(e.attributes);for(const{name:n}of s)e.hasAttribute(n)||t.removeAttribute(n);for(const{name:n,value:o}of i)t.getAttribute(n)!==o&&t.setAttribute(n,o);t instanceof HTMLInputElement?this.updateInputElement(t,e):t instanceof HTMLTextAreaElement?this.updateTextAreaElement(t,e):t instanceof HTMLSelectElement&&this.updateSelectElement(t,e),this.reconcile(t,Array.from(e.childNodes))}updateInputElement(t,e){if(t.type==="checkbox"||t.type==="radio"){const n=e.hasAttribute("checked");t.checked!==n&&(t.checked=n)}else{if(t.type==="file")return;if(e.hasAttribute("value")){const n=e.getAttribute("value")||"";t.value!==n&&(t.value=n)}else t.value!==""&&(t.value="")}const s=e.hasAttribute("disabled");t.disabled!==s&&(t.disabled=s);const i=e.hasAttribute("readonly");t.readOnly!==i&&(t.readOnly=i)}updateTextAreaElement(t,e){const s=e.textContent||"";t.value!==s&&(t.value=s);const i=e.hasAttribute("disabled");t.disabled!==i&&(t.disabled=i);const n=e.hasAttribute("readonly");t.readOnly!==n&&(t.readOnly=n)}updateSelectElement(t,e){const s=e.hasAttribute("disabled");if(t.disabled!==s&&(t.disabled=s),e.hasAttribute("value")){const i=e.getAttribute("value")||"";t.value!==i&&(t.value=i)}}}const m=r=>{class t extends C{static formAssociated=r.formAssociated;static get observedAttributes(){return r.observedAttributes||[]}constructor(){super(r)}}return t},b=(r,t)=>{if(customElements.get(r)){console.warn(`[craftit] Element "${r}" already defined`);return}customElements.define(r,m(t))},S=(r,t)=>(b(r,t),customElements.get(r)),w=(r,...t)=>r.reduce((e,s,i)=>{const n=t[i]??"";return e+s+n},""),$=Object.assign((r,...t)=>r.reduce((e,s,i)=>{const n=t[i]??"";return e+s+n},""),{theme:((r,t,e)=>{const s=e?.selector??":host",i=o=>Object.entries(o).map(([a,c])=>`${a.startsWith("--")?a:`--${l(a)}`}: ${c};`).join(" ");let n;if(!t)n=`${s} { ${i(r)} }`;else{const o=e?.attribute??"data-theme",a=i(r),c=i(t);n=`
|
|
11
|
-
${s} { ${a} }
|
|
12
|
-
@media (prefers-color-scheme: dark) {
|
|
13
|
-
${s}:not([${o}="light"]) { ${c} }
|
|
14
|
-
}
|
|
15
|
-
${s}[${o}="dark"] { ${c} }
|
|
16
|
-
${s}[${o}="light"] { ${a} }
|
|
17
|
-
`.trim()}return new Proxy({},{get(o,a){if(a==="toString"||a===Symbol.toPrimitive)return()=>n;if(typeof a=="string"&&a in r)return`var(${a.startsWith("--")?a:`--${l(a)}`})`}})}),var:(r,t)=>{const e=r.startsWith("--")?r:`--${l(r)}`;return t!==void 0?`var(${e}, ${t})`:`var(${e})`}}),k=r=>Object.entries(r).filter(([,t])=>t).map(([t])=>t).join(" "),x=r=>Object.entries(r).filter(([,t])=>t!=null).map(([t,e])=>`${l(t)}: ${e}`).join("; ");async function R(r,t=document.body){return t.appendChild(r),"flush"in r&&typeof r.flush=="function"?await r.flush():await new Promise(e=>requestAnimationFrame(e)),r}function T(r){r.remove()}exports.attach=R;exports.classMap=k;exports.createComponent=m;exports.css=$;exports.defineElement=b;exports.destroy=T;exports.element=S;exports.html=w;exports.styleMap=x;
|
|
18
|
-
//# sourceMappingURL=craftit.cjs.map
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@vielzeug/stateit`);var t=0,n=e=>{for(let t of e)t()},r=(e,t,n)=>{n==null||!1===n?e.removeAttribute(t):!0===n?e.setAttribute(t,``):e.setAttribute(t,String(n))},i=(e,t,n,r)=>{let i=n;return e.addEventListener(t,i,r),()=>e.removeEventListener(t,i,r)},a=e=>`${e?`${e}-`:`cft-`}${++t}`,o=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),s={"'":`'`,'"':`"`,"&":`&`,"<":`<`,">":`>`},c=e=>String(e).replace(/[&<>"']/g,e=>s[e]),l=function(){return this.content},u=new Map,d=e=>{if(e instanceof CSSStyleSheet)return e;let t=typeof e==`string`?e:e.content,n=u.get(t);if(n)return n;let r=new CSSStyleSheet;try{r.replaceSync(t),u.set(t,r)}catch(e){console.error(`[craftit:E2] style replace failed`,e)}return r},f=[],p=()=>{let e=f[f.length-1];if(!e)throw Error(`[craftit:E1] lifecycle outside setup`);return e},m=e=>{p().onMount.push(e)},h=t=>{f.length>0?p().cleanups.push(t):(0,e.onCleanup)(t)},g=e=>{f.length>0&&h(e)},_=(t,n)=>{let r=(0,e.effect)(t,n);return g(r),r};function v(e,t,n,r){e&&(e.addEventListener(t,n,r),h(()=>e.removeEventListener(t,n,r)))}var y={bubbles:!0,cancelable:!0,composed:!0},b={basic:(e,t,n={})=>e.dispatchEvent(new Event(t,{...y,...n})),custom:(e,t,n={})=>e.dispatchEvent(new CustomEvent(t,{...y,...n})),event:(e,t)=>e.dispatchEvent(t),focus:(e,t,n={})=>e.dispatchEvent(new FocusEvent(t,{...y,...n})),keyboard:(e,t,n={})=>e.dispatchEvent(new KeyboardEvent(t,{...y,...n})),mouse:(e,t,n={})=>e.dispatchEvent(new MouseEvent(t,{...y,...n})),touch:(e,t,n={})=>typeof TouchEvent<`u`?e.dispatchEvent(new TouchEvent(t,{...y,...n})):e.dispatchEvent(new CustomEvent(t,{...y,...n}))},x=new WeakMap,S=new Set,C=(e,t,n)=>{let r=`${n}:${e.localName}:${t||`default`}`;S.has(r)||(S.add(r),console.warn(`[craftit:E10] ${n} could not find a matching <slot${t?` name="${t}"`:``}> in <${e.localName}>. Render the slot before using ${n}.`))};function w(e,t){for(let[n,r]of Object.entries(t))if(n===`classMap`)T(e,r);else if(n.startsWith(`on`)&&n.length>2&&typeof r==`function`){let t=n.slice(2);v(e,t[0].toLowerCase()+t.slice(1),r)}else ee(e,n,r)}function ee(e,t,n){typeof n==`function`?_(()=>r(e,t,n())):r(e,t,n)}function T(e,t){let n=new Set;_(()=>{let r=new Set(Object.entries(t()).filter(([,e])=>e).map(([e])=>e));for(let t of n)r.has(t)||e.classList.remove(t);for(let t of r)n.has(t)||e.classList.add(t);n=r})}function E(e,t=[]){return{__bindings:t,__html:e,toString:()=>e}}var D=Symbol(`craftit.eachSignal`),O=t=>(0,e.isSignal)(t)?t:typeof t==`function`?(0,e.computed)(t):void 0,te=t=>{if(!(0,e.isSignal)(t))return!1;let n=Object.getPrototypeOf(t);for(;n;){let e=Object.getOwnPropertyDescriptor(n,`value`);if(e)return typeof e.set==`function`;n=Object.getPrototypeOf(n)}return!1},k=(e,t)=>{if(!Object.is(e.value,t))try{e.value=t}catch{}},A=new Map,j=e=>(e=>{let t=A.get(e);if(!t){if(t=document.createElement(`template`),t.innerHTML=e,A.size>=1e3){let e=A.keys().next().value;e!==void 0&&A.delete(e)}A.set(e,t)}return t})(e).content.cloneNode(!0),M=(e,t)=>{if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue;n&&t.comments.set(n,e);return}if(e.nodeType!==Node.ELEMENT_NODE)return;let n=e.getAttribute(`u`);n&&t.elements.set(n,e)},N=e=>{let t={comments:new Map,elements:new Map};for(let n of e){let e=document.createTreeWalker(n,NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_ELEMENT);for(M(n,t);e.nextNode();)M(e.currentNode,t)}return t},P=e=>Array.from(j(e).childNodes),F=(e,t,n)=>{if(e.parentNode)for(let r of t)e.parentNode.insertBefore(r,n)},I=e=>Array.isArray(e)||typeof e==`object`&&!!e,L=(e,t,n)=>{n(_(()=>t(e.value)))},ne=(e,t,n)=>{let i=n=>{let i=Q.get(e)?.get(t.name);if(!i&&I(n))return void(e[t.name]=n);if(i&&!i.reflect||(t.mode===`bool`?e.toggleAttribute(t.name,!!n):r(e,t.name,n)),!i)return;let a=I(n)?n:i.parse(t.mode===`bool`?n?``:null:n==null||!1===n?null:String(n));Object.is(i.signal.peek(),a)||(i.signal.value=a)};t.signal?L(t.signal,i,n):i(t.value)},re=(e,t,n)=>{let r=n=>{e[t.name]=n};t.signal?L(t.signal,r,n):r(t.value),((e,t,n,r)=>{n&&(t===`value`?(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)&&r(i(e,e instanceof HTMLSelectElement?`change`:`input`,()=>{k(n,e.value)})):t===`checked`&&e instanceof HTMLInputElement&&r(i(e,`change`,()=>{k(n,e.checked)})))})(e,t.name,t.model,n)},ie=(e,t,n)=>{let{modifiers:r}=t,a=r?{capture:!!r.capture,once:!!r.once,passive:!!r.passive}:void 0;n(i(e,t.name,e=>{r?.self&&e.target!==e.currentTarget||(r?.stop&&e.stopPropagation(),r?.prevent&&!r?.passive&&e.preventDefault(),t.handler(e))},a))},ae=(e,t,n)=>{let{ref:r}=t;typeof r==`function`?(r(e),n(()=>r(null))):Array.isArray(r)?(r.push(e),n(()=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)})):(r.value=e,n(()=>{r.value=null}))},R=(e,t,n,r)=>{let i=new Map;for(let a of e){let e=a.uid;if(a.type===`text`){let r=n.comments.get(e);if(r){let i=document.createTextNode(``);r.replaceWith(i),n.comments.delete(e),L(a.signal,e=>{i.textContent=String(e)},t)}}else a.type===`html`?r?.onHtml?.(a):(i.has(e)||i.set(e,[]),i.get(e).push(a))}for(let[e,r]of i){let i=n.elements.get(e);if(i){i.removeAttribute(`u`),n.elements.delete(e);for(let e of r)switch(e.type){case`attr`:ne(i,e,t);break;case`callback`:e.apply(i,t);break;case`event`:ie(i,e,t);break;case`prop`:re(i,e,t);break;case`ref`:ae(i,e,t)}}}},z=(e,t,n,r)=>{let i=O(r);return i?{mode:e,name:t,signal:i,type:`attr`,uid:n}:{mode:e,name:t,type:`attr`,uid:n,value:r}},B=(e,t,n)=>{let r=O(n);return r?{model:te(n)?n:void 0,name:e,signal:r,type:`prop`,uid:t}:{name:e,type:`prop`,uid:t,value:n}},oe=RegExp(`u="([^"]+)"`,`g`),V=e=>typeof e==`object`&&!!e&&`__html`in e,se=[{kind:`event`,regex:/\s+@([a-zA-Z_][-a-zA-Z0-9_.]*)\s*=\s*["']?$/},{kind:`ref`,regex:/\s+ref\s*=\s*["']?$/},{kind:`specialAttr`,regex:/\s+([:?])([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/},{kind:`prop`,regex:/\.([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/},{kind:`plainAttr`,regex:/\s+([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/}],H=new WeakMap,ce=e=>{let[t,...n]=e.split(`.`),r={};for(let e of n)e===`capture`?r.capture=!0:e===`once`?r.once=!0:e===`passive`?r.passive=!0:e===`prevent`?r.prevent=!0:e===`self`?r.self=!0:e===`stop`&&(r.stop=!0);return{modifiers:Object.keys(r).length?r:void 0,name:t}},U=()=>{let e=0;return()=>String(e++)},W=(e,t)=>{let n=new Map,r=e=>{let r=n.get(e);if(r)return r;let i=t();return n.set(e,i),i};return{bindings:e.__bindings.map(e=>({...e,uid:r(e.uid)})),html:e.__html.replace(oe,(e,t)=>`u="${r(t)}"`).replace(/<!--(\d+)-->/g,(e,t)=>`\x3c!--${r(t)}--\x3e`)}},G=e=>typeof e==`string`?c(e):e==null?``:V(e)?e.__html:c(String(e)),le=(t,n)=>{let r=(e=>typeof e==`object`&&e&&D in e?e[D]:null)(t);if(r)return{keyed:!0,signal:r};if(typeof t==`function`&&!(0,e.isSignal)(t)){let{signal:r}=((t,n)=>{let r={bindings:[],html:``},i=(0,e.signal)(r);return n(()=>{let e=t(),n=Array.isArray(e)?e:[e],a=U(),o=``,s=[];for(let e of n)if(V(e)){let t=W(e,a);o+=t.html,s.push(...t.bindings)}else o+=G(e);let c=s.length!==r.bindings.length||s.some((e,t)=>e!==r.bindings[t]);(o!==r.html||c)&&(r={bindings:s,html:o},i.value=r)}),{bindings:[],signal:i}})(t,n);return{keyed:!1,signal:r}}return(0,e.isSignal)(t)&&V(t.value)?{keyed:!1,signal:(0,e.computed)(()=>{let e=t.value;if(!V(e))return{bindings:[],html:String(e)};let n=W(e,U());return{bindings:n.bindings,html:n.html}})}:null},K=e=>{n(e.cleanups);for(let t of e.nodes)t.remove()},q=(e,t,n=N(e))=>{let r=[];return R(t,e=>r.push(e),n),r},J=(t,r,i,a,o)=>{let s=((e,t)=>{let n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(;n.nextNode();){let e=n.currentNode;if(e.nodeValue===t)return e}return null})(t,r.uid);if(!s)return;let c=document.createComment(`html-binding`);s.replaceWith(c);let l=[],u=e=>l.push(e),d=()=>{n(l),l=[]},f=null,p=[];i((0,e.effect)(()=>{(0,e.batch)(()=>{let i=r.signal.value;if(!r.keyed&&i.html===f)return;f=i.html,d();let{bindings:s,html:l,keys:m}=i;r.keyed&&!a.has(r.uid)&&a.set(r.uid,new Map);let h=r.keyed?a.get(r.uid):null,g=c.parentElement||t,_=!1;(0,e.untrack)(()=>{(0,e.batch)(()=>{if(h&&m?.length&&i.items?.length===m.length){if(_=!0,h.size===0&&p.length>0){for(let e of p)e.remove();p=[]}let e=new Map;for(let t=0;t<m.length;t++){let r=m[t],a=i.items[t],o=h.get(r),s=t>0?e.get(m[t-1])?.nodes:null,l=s?.length?s[s.length-1].nextSibling:c.nextSibling;if(o?.html===a.html){o.nodes[0]&&F(c,o.nodes,l),n(o.cleanups);let t=N(o.nodes),i=q(o.nodes,a.bindings,t);e.set(r,{...o,bindings:a.bindings,cleanups:i,targets:t})}else if(o){n(o.cleanups);let t=P(a.html),i=N(t);F(c,t,l);let s=q(t,a.bindings,i);e.set(r,{bindings:a.bindings,cleanups:s,html:a.html,nodes:t,targets:i});for(let e of o.nodes)e.remove()}else{let t=P(a.html),n=N(t);F(c,t,l);let i=q(t,a.bindings,n);e.set(r,{bindings:a.bindings,cleanups:i,html:a.html,nodes:t,targets:n})}}for(let[t,n]of h)e.has(t)||K(n);a.set(r.uid,e)}else{if(r.keyed&&h&&h.size>0)for(let[,e]of h)K(e);else for(let e of p)e.remove();let e=j(l);p=Array.from(e.childNodes),c.after(e),r.keyed&&a.set(r.uid,new Map)}}),_||o(g,s,u,{onHtml:e=>J(g,e,u,a,o)})})})})),i(d),r.keyed&&i(()=>a.delete(r.uid))},Y=(e,t,n,r)=>{R(t,n,(e=>{let t={comments:new Map,elements:new Map},n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_ELEMENT);for(M(e,t);n.nextNode();)M(n.currentNode,t);return t})(e),r)},X=new WeakMap,Z=new WeakMap,ue=new Set([`default`,`omit`,`parse`,`reflect`,`type`]),de=e=>typeof e==`object`&&!!e&&`default`in e&&Object.keys(e).every(e=>ue.has(e)),Q=new WeakMap,$=(t,n,i)=>{let a=p(),o=a.el;Q.has(o)||Q.set(o,new Map);let s=i?.parse??(e=>i?.type===Boolean?e===``||e===`true`:typeof n==`boolean`?e!==null&&e!==`false`:e==null?n:i?.type===Number||typeof n==`number`?Number(e):e),c=(0,e.signal)(n),l=Object.prototype.hasOwnProperty.call(o,t),u=l?o[t]:void 0,d={parse:s,reflect:i?.reflect??!0,signal:c};if(l?(delete o[t],c.value=u):o.hasAttribute(t)&&(c.value=s(o.getAttribute(t))),Q.get(o).set(t,d),Object.defineProperty(o,t,{configurable:!0,enumerable:!0,get:()=>c.value,set:e=>{c.value=e}}),i?.reflect??1){let n=i?.omit??!1;a.onMount.push(()=>{a.cleanups.push((0,e.effect)(()=>{let e=c.value;e==null||!1===e||n&&e===``?o.removeAttribute(t):r(o,t,e)}))})}return c},fe=class extends HTMLElement{static _setup;static _options;static formAssociated=!1;static observedAttributes=[];shadow;_keyedStates=new Map;_mountFns=[];_template=null;_appliedHtmlBindings=new Set;_setupDone=!1;_runtime;constructor(){super();let e=this.constructor._options;this.shadow=this.attachShadow({mode:`open`,...e?.shadow}),this._runtime={cleanups:[],el:this,errorHandlers:[],onMount:[],styles:e?.styles}}connectedCallback(){this._setupDone||this._runSetup(),this._init()}attributeChangedCallback(e,t,n){if(t===n)return;let r=Q.get(this)?.get(e);if(!r)return;let i=r.parse(n);Object.is(r.signal.peek(),i)||(r.signal.value=i)}disconnectedCallback(){n(this._runtime.cleanups),this._runtime.cleanups=[],this._runtime.onMount=this._mountFns.slice(),this._appliedHtmlBindings.clear(),this._keyedStates.clear()}formAssociatedCallback(e){X.get(this)?.onAssociated?.(e)}formDisabledCallback(e){X.get(this)?.onDisabled?.(e)}formResetCallback(){X.get(this)?.onReset?.()}formStateRestoreCallback(e,t){X.get(this)?.onStateRestore?.(e,t)}_handleError(e){if(this._runtime.errorHandlers.length>0)for(let t of this._runtime.errorHandlers)t(e);else console.error(`[craftit:E3] <${this.localName}>`,e)}_runSetup(){this._setupDone=!0,f.push(this._runtime);try{let{host:e}=this.constructor._options??{};if(e)for(let[t,n]of Object.entries(e))typeof n==`boolean`?n?this.setAttribute(t,``):this.removeAttribute(t):this.setAttribute(t,String(n));let t=this.constructor._setup({host:this,shadow:this.shadow});(typeof t==`string`||typeof t==`object`&&t&&`__html`in t)&&(this._template=t)}catch(e){this._handleError(e)}finally{f.pop()}}_init(){let{styles:e}=this._runtime;if(e?.length&&(this.shadow.adoptedStyleSheets=e.map(d)),this._template){let e=typeof this._template==`string`?E(this._template):this._template;if(this.shadow.replaceChildren(j(e.__html)),e.__bindings.length){let t=e=>this._runtime.cleanups.push(e);Y(this.shadow,e.__bindings,t,{onHtml:e=>{this._appliedHtmlBindings.has(e.uid)||(this._appliedHtmlBindings.add(e.uid),((e,t,n,r)=>{J(e,t,n,r,Y)})(this.shadow,e,t,this._keyedStates))}})}}queueMicrotask(()=>{f.push(this._runtime);try{let e=this._runtime.onMount;this._mountFns=e.slice();for(let t of e){let e=t();typeof e==`function`&&this._runtime.cleanups.push(e)}}catch(e){this._handleError(e)}finally{f.pop(),this._runtime.onMount=[]}})}};exports.aria=function(e,t){let n=t===void 0?p().el:e,r=Object.entries(t===void 0?e:t).map(([e,t])=>_(()=>((e,t)=>{let r=`aria-${e}`,i=typeof t==`function`?t():t;i==null||!1===i?n.removeAttribute(r):n.setAttribute(r,String(i))})(e,t)));if(t!==void 0)return()=>{for(let e of r)e()}},exports.createContext=function(e){return Symbol(e)},exports.createFormIds=(e,t)=>{let n=`${e}-${t&&t.trim()?t:a(e)}`;return{errorId:`error-${n}`,fieldId:n,helperId:`helper-${n}`,labelId:`label-${n}`}},exports.createId=a,exports.css=(e,...t)=>{let n=``;for(let r=0;r<e.length;r++)if(n+=e[r],r<t.length){let e=t[r];n+=e&&typeof e==`object`&&`content`in e?e.content:e??``}return{content:n.trim(),toString:l}},exports.defineComponent=function(t){let{formAssociated:n,host:r,props:i,setup:a,shadow:s,styles:c,tag:l}=t;return function(e,t,n={}){if(!e)throw Error(`[craftit:E4] registerComponent(tag, ...) requires a tag name`);if(customElements.get(e))throw Error(`[craftit:E9] custom element already defined: ${e}`);class r extends fe{static _setup=t;static _options=n;static formAssociated=n.formAssociated??!1;static observedAttributes=n.observedAttrs??[]}return customElements.define(e,r),e}(l,t=>{let n=i?function(e){let t={};for(let[n,r]of Object.entries(e)){let e=de(r)?r:{default:r},i={reflect:!(typeof e.default==`object`&&e.default!==null||Array.isArray(e.default)),...e};t[n]=$(o(n),e.default,i)}return t}(i):{},r=(()=>{let e=p().el;return(t,...n)=>{b.custom(e,String(t),n.length>0?{detail:n[0]}:void 0)}})(),s=(()=>{let t=p().el,n=new Map;return{has:r=>(r=>{if(n.has(r))return n.get(r);let i=(0,e.signal)(!1);return n.set(r,i),m(()=>{let e=r?`slot[name="${r}"]`:`slot:not([name])`,n=t.shadowRoot?.querySelector(e);if(!n)return void C(t,r,`slots.has()`);let a=()=>{i.value=n.assignedNodes().length>0};return a(),n.addEventListener(`slotchange`,a),()=>n.removeEventListener(`slotchange`,a)}),i})(r===`default`?``:String(r))}})();return a({emit:r,host:t.host,props:n,reflect:e=>w(t.host,e),shadow:t.shadow,slots:s})},{formAssociated:n,host:r,observedAttrs:i?Object.keys(i).map(o):[],shadow:s,styles:c})},exports.defineField=(t,n)=>{let r=p().el;if(!r.constructor.formAssociated)throw Error(`[craftit:E8] defineField() requires defineComponent({ formAssociated: true })`);let i=Z.get(r)??r.attachInternals();Z.set(r,i);let a=t.toFormValue??(e=>e==null?``:String(e));return(0,e.effect)(()=>{i.setFormValue(a(t.value.value))}),t.disabled&&(0,e.effect)(()=>{t.disabled.value?i.states.add(`disabled`):i.states.delete(`disabled`)}),n&&X.set(r,{...X.get(r),...n}),{checkValidity:()=>i.checkValidity(),internals:i,reportValidity:()=>i.reportValidity(),setCustomValidity:e=>e?i.setValidity({customError:!0},e):i.setValidity({}),setValidity:i.setValidity.bind(i)}},exports.effect=_,exports.escapeHtml=c,exports.fire=b,exports.guard=(e,t)=>n=>{e()&&t(n)},exports.handle=v,exports.html=(t,...n)=>((t,n,r)=>{let i=(e=>{let t=H.get(e);return t||(t=(e=>{let t=[];for(let n=0;n<e.length-1;n++){let r=e[n],i=!1;for(let e of se){let n=e.regex.exec(r);if(!n)continue;let a=r.slice(0,-n[0].length);if(i=!0,e.kind===`event`){let e=ce(n[1]);t.push({kind:`event`,modifiers:e.modifiers,name:e.name,prefix:a,raw:r})}else e.kind===`ref`?t.push({kind:`ref`,prefix:a,raw:r}):e.kind===`specialAttr`?t.push({kind:`specialAttr`,mode:n[1]===`?`?`bool`:`attr`,name:n[2],prefix:a,raw:r}):e.kind===`prop`?t.push({kind:`prop`,name:n[1],prefix:a,raw:r}):e.kind===`plainAttr`&&t.push({kind:`plainAttr`,name:n[1],prefix:a,raw:r});break}i||t.push({kind:`node`,prefix:r,raw:r})}return{slots:t,tail:e[e.length-1]??``}})(e),H.set(e,t)),t})(t),a=``,o=[],s=null,c=U(),l=e=>(s&&!(e=>e.lastIndexOf(`<`)>e.lastIndexOf(`>`))(e)||(s=c()),s),u=()=>{s=null};for(let t=0;t<i.slots.length;t++){let s=i.slots[t],d=n[t];if(s.kind===`event`){if(typeof d==`function`){let e=l(s.prefix);a+=`${s.prefix} u="${e}"`,o.push({handler:d,modifiers:s.modifiers,name:s.name,type:`event`,uid:e})}else a+=s.raw;continue}if(s.kind===`ref`){if(d){let e=l(s.prefix);a+=`${s.prefix} u="${e}"`,o.push({ref:d,type:`ref`,uid:e})}else a+=s.raw;continue}if(s.kind===`specialAttr`){let e=l(s.prefix);a+=`${s.prefix} u="${e}"`,o.push(z(s.mode,s.name,e,d));continue}if(s.kind===`prop`){let e=l(s.prefix);a+=`${s.prefix} u="${e}"`,o.push(B(s.name,e,d));continue}if(s.kind===`plainAttr`){let e=l(s.prefix);a+=`${s.prefix} u="${e}"`,o.push(z(`attr`,s.name,e,d));continue}if(typeof d==`object`&&d&&(`mount`in d||`render`in d)){let t=`render`in d,n=t?c():l(s.raw);a+=t?`${s.raw}\x3c!--${n}--\x3e`:`${s.raw} u="${n}"`;let i=d.mount?.bind(d);if(i&&o.push({apply:(e,t)=>{i(e,{registerCleanup:t})},type:`callback`,uid:n}),t){let t=d.render.bind(d),i={bindings:[],html:``},a=(0,e.signal)(i);r(()=>{let e=t(),n=Array.isArray(e)?e:[e],r=U(),o=``,s=[];for(let e of n)if(V(e)){let t=W(e,r);o+=t.html,s.push(...t.bindings)}else o+=G(e);let c=s.length!==i.bindings.length||s.some((e,t)=>e!==i.bindings[t]);(o!==i.html||c)&&(i={bindings:s,html:o},a.value=i)}),o.push({keyed:!1,signal:a,type:`html`,uid:n})}continue}u();let f=le(d,r);if(f){let e=c();a+=`${s.raw}\x3c!--${e}--\x3e`,o.push({keyed:f.keyed,signal:f.signal,type:`html`,uid:e});continue}if(Array.isArray(d)){let e=``;for(let t of d)if(V(t)){let n=W(t,c);e+=n.html,o.push(...n.bindings)}else e+=G(t);a+=s.raw+e;continue}if((0,e.isSignal)(d)){let e=c();a+=`${s.raw}\x3c!--${e}--\x3e`,o.push({signal:d,type:`text`,uid:e})}else if(V(d)){let e=W(d,c);a+=s.raw+e.html,o.push(...e.bindings)}else a+=s.raw+G(d)}return a+=i.tail,E(a.replace(/>\s+</g,`><`).trim(),o)})(t,n,_),exports.inject=function(e,...t){let n=p().el;for(;n;){if(n instanceof HTMLElement){let t=x.get(n)?.get(e);if(t!==void 0)return t}let t=n.getRootNode();n=n.parentElement??(t instanceof ShadowRoot?t.host:null)}return t.length>0?t[0]:void 0},exports.observeResize=t=>{let n=(0,e.signal)({height:0,width:0}),r=new ResizeObserver(([e])=>{if(!e)return;let t=e.contentBoxSize[0];t&&(n.value={height:t.blockSize,width:t.inlineSize})});return r.observe(t),h(()=>r.disconnect()),n},exports.onCleanup=h,exports.onError=e=>{p().errorHandlers.push(e)},exports.onMount=m,exports.onSlotChange=(e,t)=>{let n=p().el,r=e===`default`?``:e,i=r?`slot[name="${r}"]`:`slot:not([name])`,a=n.shadowRoot?.querySelector(i);if(!a)return void C(n,r,`onSlotChange()`);let o=()=>t(a.assignedElements({flatten:!0}));o(),a.addEventListener(`slotchange`,o),h(()=>a.removeEventListener(`slotchange`,o))},exports.prop=$,exports.provide=(e,t)=>{let n=p().el;x.has(n)||x.set(n,new Map),x.get(n).set(e,t)},exports.ref=function(){return{value:null}},exports.reflect=w,exports.refs=function(){return[]},exports.syncContextProps=(e,t,n)=>{e&&m(()=>{_(()=>{for(let r of n){let n=e[r]?.value;n!==void 0&&(t[r].value=n)}})})},exports.toKebab=o,exports.typed=(e,t)=>({...t,default:e}),exports.watch=function(t,n,r){if(Array.isArray(t)){let i=r,a=!1,o=!1,s=(0,e.effect)(()=>{for(let e of t)e.value;if(a)(0,e.untrack)(n),i?.once&&s();else if(a=!0,i?.immediate&&((0,e.untrack)(n),i.once))return void(o=!0)});return g(s),o&&s(),s}let i=(0,e.watch)(t,n,r);return g(i),i},Object.keys(e).forEach(function(t){t===`default`||Object.prototype.hasOwnProperty.call(exports,t)||Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
|
|
2
|
+
//# sourceMappingURL=craftit.cjs.map
|