chispa 0.9.2 → 0.10.1

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.
@@ -294,7 +294,7 @@ async function findAndCompileHtmlFiles(dir, rootDir) {
294
294
  }
295
295
 
296
296
  // src/html-compiler/vite-plugin.ts
297
- import { transformWithEsbuild } from "vite";
297
+ import { transformWithOxc } from "vite";
298
298
  import * as fs2 from "fs";
299
299
  var toVirtualId = (id) => "\0" + id + ".chispa.ts";
300
300
  var fromVirtualId = (id) => id.replace(/^\0/, "").replace(/\.chispa\.ts$/, "");
@@ -344,9 +344,7 @@ function chispaHtmlPlugin() {
344
344
  const compiler = new HtmlCompiler(content);
345
345
  const { ts } = await compiler.compile();
346
346
  generateTypes(realId, content, rootDir);
347
- const result = await transformWithEsbuild(ts, realId, {
348
- loader: "ts"
349
- });
347
+ const result = await transformWithOxc(ts, realId + ".ts");
350
348
  return result.code;
351
349
  } catch (e) {
352
350
  console.error(`[chispa] Error loading ${id}:`, e);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/html-compiler/html-compiler.ts","../../src/html-compiler/generator.ts","../../src/html-compiler/vite-plugin.ts"],"sourcesContent":["import { JSDOM } from 'jsdom';\nimport { format } from 'prettier';\n\nconst VOID_ELEMENTS = ['area', 'base', 'br', 'hr', 'img', 'input', 'link', 'meta', 'param', 'keygen', 'source'];\n\nconst SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport class HtmlCompiler {\n\tprivate components: Record<string, string> = {};\n\tprivate stack: string[] = ['fragment'];\n\tprivate componentsItems: Record<string, string[]> = {};\n\tprivate componentsTags: Record<string, string> = {};\n\tprivate isSvg: Record<string, boolean> = {};\n\tprivate inSvgContext = 0;\n\tprivate htmlDocument: Document;\n\n\tconstructor(htmlContent: string) {\n\t\tconst dom = new JSDOM(htmlContent);\n\t\tthis.htmlDocument = dom.window.document;\n\t}\n\n\tprivate static camelize(str: string): string {\n\t\tif (str.startsWith('--')) {\n\t\t\treturn str;\n\t\t}\n\t\tconst arr = str.split('-');\n\t\tlet camelized = '';\n\t\tarr.forEach((v, i) => {\n\t\t\tcamelized += i === 0 ? v : v.charAt(0).toUpperCase() + v.slice(1);\n\t\t});\n\t\treturn camelized;\n\t}\n\n\tprivate static parseStyle(cssCode: string): string {\n\t\tlet out = '{';\n\t\tconst styles = cssCode.split(';');\n\t\tstyles.forEach((line) => {\n\t\t\tconst parts = line.split(':');\n\t\t\tif (parts.length !== 2) return;\n\t\t\tconst prop = HtmlCompiler.camelize(parts[0].trim());\n\t\t\tout += ` ${prop}: '${parts[1].trim()}',`;\n\t\t});\n\t\tout += '}';\n\t\treturn out;\n\t}\n\n\tprivate makeClassAttr(classAttr: string | null, isComponent: boolean): string {\n\t\tconst tplClasses = (classAttr || '').split(' ');\n\t\tlet finalClass = '';\n\n\t\ttplClasses.forEach((tplClass) => {\n\t\t\tif (!tplClass.startsWith('-tpl--')) {\n\t\t\t\tfinalClass += tplClass + ' ';\n\t\t\t}\n\t\t});\n\n\t\tfinalClass = finalClass.trim();\n\n\t\treturn ` 'class': \"${finalClass}\", `;\n\t}\n\n\tprivate getHtmlNodeAttrs(domNode: Element, isComponent: boolean): string {\n\t\tlet attrsHtml = '{';\n\t\tattrsHtml += this.makeClassAttr(domNode.getAttribute('class'), isComponent);\n\n\t\tArray.from(domNode.attributes).forEach((attr) => {\n\t\t\tconst attrName = attr.name;\n\t\t\tlet attrValue = attr.value;\n\n\t\t\tif (attrName === 'data-cb') return;\n\t\t\tif (attrName === 'class') return;\n\n\t\t\t// Use JSON.stringify to properly escape newlines, quotes and other characters\n\t\t\tconst valueLiteral = JSON.stringify(attrValue);\n\n\t\t\t// Simplified logic compared to PHP which had cbt.prefixize... calls\n\t\t\t// Assuming we just output the value for now as I don't see cbt implementation here\n\t\t\t// The PHP code imported CoreBuilderTools but here we might not have it.\n\t\t\t// The user's example output imports from 'chispa'.\n\t\t\t// I will stick to simple string values for now unless I see cbt in chispa.\n\n\t\t\tif (attrName === 'style') {\n\t\t\t\t// PHP called cbt.prefixizeStyle, but also had parse_style static method.\n\t\t\t\t// Wait, the PHP code used cbt.prefixizeStyle inside get_html_node_attrs.\n\t\t\t\t// But parse_style was defined but not used in the snippet I read?\n\t\t\t\t// Ah, I should check if I should use parseStyle or just output string.\n\t\t\t\t// The PHP code: $attrs_html .= \" '$attr_name': cbt.prefixizeStyle('$attr_value'), \";\n\t\t\t\t// If cbt is a runtime helper, I should output the call.\n\t\t\t\t// But wait, the generated code imports CoreBuilderTools.\n\t\t\t\t// Does 'chispa' export CoreBuilderTools?\n\t\t\t\t// src/index.ts does NOT export CoreBuilderTools.\n\t\t\t\t// It exports appendChild, getItem, etc.\n\t\t\t\t// Maybe I should just output the string for now.\n\t\t\t\tattrsHtml += ` '${attrName}': ${valueLiteral}, `;\n\t\t\t} else {\n\t\t\t\tattrsHtml += ` '${attrName}': ${valueLiteral}, `;\n\t\t\t}\n\t\t});\n\n\t\tattrsHtml += '}';\n\t\treturn attrsHtml;\n\t}\n\n\tprivate buildTsForNode(domNode: Node, isComponent = false): string {\n\t\tlet htmlNodeCode = '';\n\n\t\tif (domNode.nodeType === 1) {\n\t\t\t// Element\n\t\t\tconst element = domNode as Element;\n\t\t\tlet tagName = element.tagName;\n\n\t\t\tif (tagName === 'svg') {\n\t\t\t\tthis.inSvgContext++;\n\t\t\t}\n\n\t\t\tlet cbid = element.getAttribute('data-cb');\n\n\t\t\tif (cbid) {\n\t\t\t\tconst currComp = this.stack[0];\n\t\t\t\telement.removeAttribute('data-cb');\n\t\t\t\tcbid = HtmlCompiler.camelize(cbid);\n\t\t\t\t// Pushear a todos los padres\n\t\t\t\tfor (const comp of this.stack) {\n\t\t\t\t\tif (!this.componentsItems[comp]) {\n\t\t\t\t\t\tthis.componentsItems[comp] = [];\n\t\t\t\t\t}\n\t\t\t\t\tthis.componentsItems[comp].push(cbid);\n\t\t\t\t}\n\n\t\t\t\tthis.stack.unshift(cbid);\n\t\t\t\tthis.components[cbid] = this.buildTsForNode(element, true);\n\t\t\t\tthis.componentsTags[cbid] = element.tagName;\n\t\t\t\tthis.isSvg[cbid] = this.inSvgContext > 0;\n\t\t\t\tthis.stack.shift();\n\n\t\t\t\tif (currComp === 'fragment') {\n\t\t\t\t\thtmlNodeCode += `getItem(template, props, '${cbid}')`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `getItem(template, props.nodes, '${cbid}')`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst attrs = this.getHtmlNodeAttrs(element, isComponent);\n\n\t\t\t\tif (!this.inSvgContext) {\n\t\t\t\t\ttagName = tagName.toLowerCase();\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElement('${tagName}');\\n`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElementNS('${SVG_NAMESPACE}', '${tagName}');\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `setAttributes(node, ${attrs});\\n`;\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `setProps(node, props);\\n`;\n\t\t\t\t}\n\n\t\t\t\tlet subTs = '';\n\t\t\t\telement.childNodes.forEach((child) => {\n\t\t\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\t\t\tif (chCode) {\n\t\t\t\t\t\tsubTs += `appendChild(node, ${chCode});\\n`;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (!VOID_ELEMENTS.includes(tagName.toLowerCase())) {\n\t\t\t\t\tif (isComponent) {\n\t\t\t\t\t\thtmlNodeCode += `\n if (props.inner === null) {\n node.innerHTML = '';\n } else if (props.inner !== undefined) {\n node.innerHTML = '';\n appendChild(node, props.inner);\n } else {\n ${subTs}\n }\n `;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtmlNodeCode += subTs;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `if (typeof props._ref === 'function') props._ref(node);\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `return node;})()`;\n\n\t\t\t\tif (tagName === 'svg') {\n\t\t\t\t\tthis.inSvgContext--;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (domNode.nodeType === 3) {\n\t\t\t// Text\n\t\t\tconst textNode = domNode as Text;\n\t\t\tconst parent = textNode.parentNode as Element;\n\t\t\tconst parentTag = parent ? parent.tagName.toLowerCase() : '';\n\n\t\t\tconst mustOmit = ['table', 'thead', 'tbody', 'tfoot', 'tr'].includes(parentTag);\n\n\t\t\tif (!mustOmit && textNode.textContent) {\n\t\t\t\tif (textNode.textContent.trim() === '') {\n\t\t\t\t\tif (textNode.textContent.length > 0) {\n\t\t\t\t\t\thtmlNodeCode += `document.createTextNode(' ')`;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode = `document.createTextNode(${JSON.stringify(textNode.textContent)})`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn htmlNodeCode.trim();\n\t}\n\n\tprivate static getPropsTypename(cbid: string): string {\n\t\treturn 'Cb' + cbid.charAt(0).toUpperCase() + cbid.slice(1) + 'Props';\n\t}\n\n\tprivate wrapFnComponent(cbid: string, jsx: string): string {\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\treturn `(props: ${typename}) => { \\n return(${jsx}); \\n }`;\n\t}\n\n\tprivate createAllComponents() {\n\t\tconst body = this.htmlDocument.querySelector('body');\n\t\tif (!body) throw new Error('Not valid HTML');\n\n\t\tlet rendererJsx = '(() => { const fragment = document.createDocumentFragment();\\n';\n\n\t\tbody.childNodes.forEach((child) => {\n\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\tif (chCode) {\n\t\t\t\trendererJsx += `appendChild(fragment, ${chCode});\\n`;\n\t\t\t}\n\t\t});\n\n\t\trendererJsx += 'return fragment;\\n';\n\t\trendererJsx += '})()';\n\n\t\tthis.components['fragment'] = rendererJsx;\n\t}\n\n\tprivate getTypedef(cbid: string): string {\n\t\tconst items = this.componentsItems[cbid] || [];\n\t\tlet itemsType = '{\\n';\n\t\titems.forEach((itemCbid) => {\n\t\t\tconst itemTypename = HtmlCompiler.getPropsTypename(itemCbid);\n\t\t\titemsType += `${itemCbid}?: ${itemTypename} | ChispaContentReactive;\\n`;\n\t\t});\n\t\titemsType += '}\\n';\n\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\n\t\tif (cbid === 'fragment') {\n\t\t\treturn `interface ${typename} ${itemsType}`;\n\t\t} else {\n\t\t\tconst tagname = this.componentsTags[cbid];\n\t\t\tif (this.isSvg[cbid]) {\n\t\t\t\treturn `type ${typename} = ChispaNodeBuilderPropsReactive<SVGElementTagNameMap['${tagname}'], ${itemsType}>;`;\n\t\t\t} else {\n\t\t\t\treturn `type ${typename} = ChispaNodeBuilderPropsReactive<HTMLElementTagNameMap['${tagname.toLowerCase()}'], ${itemsType}>;`;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async compile(): Promise<{ ts: string; dts: string }> {\n\t\tthis.createAllComponents();\n\n\t\tlet componentsClasses = '';\n\t\tlet typedefs = '';\n\n\t\tfor (const [cbid, compJsx] of Object.entries(this.components)) {\n\t\t\ttypedefs += this.getTypedef(cbid) + '\\n';\n\t\t\tcomponentsClasses += `${cbid}: ${this.wrapFnComponent(cbid, compJsx)},\\n`;\n\t\t}\n\n\t\tconst jsOutput = `\n import { appendChild, getItem, setAttributes, setProps } from 'chispa';\n import type { ChispaContentReactive, ChispaNodeBuilderPropsReactive } from 'chispa';\n\t\t\t\n const SVG_NS = 'http://www.w3.org/2000/svg';\n \n const template = {\n ${componentsClasses}\n };\n \n export default template;\n `;\n\n\t\tconst dtsOutput = `\n import type { ChispaContentReactive, ChispaNodeBuilderPropsReactive } from 'chispa';\n \n ${typedefs}\n \n declare const template: {\n ${Object.keys(this.components)\n\t\t\t\t\t.map((cbid) => {\n\t\t\t\t\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\t\t\t\t\treturn `${cbid}: (props: ${typename}) => Node | DocumentFragment;`;\n\t\t\t\t\t})\n\t\t\t\t\t.join('\\n')}\n };\n \n export default template;\n `;\n\n\t\tconst prettierOptions = {\n\t\t\tparser: 'typescript',\n\t\t\tsemi: true,\n\t\t\tsingleQuote: true,\n\t\t\tuseTabs: true,\n\t\t\tprintWidth: 120,\n\t\t};\n\n\t\treturn {\n\t\t\tts: await format(jsOutput, prettierOptions),\n\t\t\tdts: await format(dtsOutput, prettierOptions),\n\t\t};\n\t}\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { HtmlCompiler } from './html-compiler';\n\nexport async function generateTypes(filePath: string, content: string, rootDir: string) {\n\ttry {\n\t\tconst compiler = new HtmlCompiler(content);\n\t\tconst { dts } = await compiler.compile();\n\n\t\tconst outDir = path.join(rootDir, '.chispa/types');\n\t\tconst relativePath = path.relative(rootDir, filePath);\n\t\tconst targetPath = path.join(outDir, relativePath + '.d.ts');\n\t\tconst targetDir = path.dirname(targetPath);\n\n\t\tif (!fs.existsSync(targetDir)) {\n\t\t\tfs.mkdirSync(targetDir, { recursive: true });\n\t\t}\n\t\tfs.writeFileSync(targetPath, dts);\n\t} catch (e) {\n\t\tconsole.error(`[chispa] Error generating types for ${filePath}`, e);\n\t}\n}\n\nexport async function findAndCompileHtmlFiles(dir: string, rootDir: string) {\n\tif (!fs.existsSync(dir)) return;\n\tconst files = fs.readdirSync(dir);\n\tfor (const file of files) {\n\t\tconst fullPath = path.join(dir, file);\n\t\tif (fullPath === path.join(rootDir, 'index.html')) continue;\n\t\tif (fs.statSync(fullPath).isDirectory()) {\n\t\t\tif (file !== 'node_modules' && file !== '.git' && file !== 'dist' && file !== '.chispa') {\n\t\t\t\tawait findAndCompileHtmlFiles(fullPath, rootDir);\n\t\t\t}\n\t\t} else if (file.endsWith('.html')) {\n\t\t\tconsole.log('Generating types for', fullPath);\n\t\t\tconst content = fs.readFileSync(fullPath, 'utf-8');\n\t\t\tawait generateTypes(fullPath, content, rootDir);\n\t\t}\n\t}\n}\n","import { HtmlCompiler } from './html-compiler';\nimport { generateTypes, findAndCompileHtmlFiles } from './generator';\nimport { type Plugin, transformWithEsbuild } from 'vite';\nimport * as fs from 'fs';\n\n/**\n * Convierte una ruta real de archivo en el ID de módulo virtual que usa Vite/Rollup.\n * Añade el prefijo `\\0` para marcar el módulo como virtual y el sufijo\n * `.chispa.ts` para que sea tratado como módulo TypeScript.\n */\nconst toVirtualId = (id: string) => '\\0' + id + '.chispa.ts';\n\n/**\n * Convierte un ID de módulo virtual de vuelta a la ruta real del archivo.\n * Elimina el prefijo `\\0` (si existe) y el sufijo `.chispa.ts`.\n */\nconst fromVirtualId = (id: string) => id.replace(/^\\0/, '').replace(/\\.chispa\\.ts$/, '');\n\nconst CHISPA_VIRTUAL_MODULE_SUFFIX = '.html.chispa.ts';\n\nexport function chispaHtmlPlugin(): Plugin {\n\tlet rootDir = process.cwd();\n\n\treturn {\n\t\tname: 'chispa-html',\n\t\tenforce: 'pre',\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t},\n\t\tasync buildStart() {\n\t\t\tawait findAndCompileHtmlFiles(rootDir, rootDir);\n\t\t},\n\t\tasync handleHotUpdate(ctx) {\n\t\t\tif (ctx.file.endsWith('.html')) {\n\t\t\t\tconst content = await ctx.read();\n\t\t\t\tawait generateTypes(ctx.file, content, rootDir);\n\n\t\t\t\t// Buscamos el módulo virtual asociado al archivo HTML modificado.\n\t\t\t\tconst module = ctx.server.moduleGraph.getModuleById(toVirtualId(ctx.file));\n\t\t\t\tif (module) {\n\t\t\t\t\treturn [module];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync resolveId(source, importer, options) {\n\t\t\tif (source.endsWith(CHISPA_VIRTUAL_MODULE_SUFFIX)) {\n\t\t\t\treturn source;\n\t\t\t}\n\t\t\tif (source.endsWith('.html') && importer) {\n\t\t\t\tconst resolution = await this.resolve(source, importer, { skipSelf: true, ...options });\n\t\t\t\tif (resolution && !resolution.external) {\n\t\t\t\t\treturn toVirtualId(resolution.id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tasync load(id) {\n\t\t\tif (!id.endsWith(CHISPA_VIRTUAL_MODULE_SUFFIX)) return null;\n\n\t\t\tconst realId = fromVirtualId(id);\n\t\t\tthis.addWatchFile(realId); // To ensure changes in the HTML file trigger a rebuild in watch mode.\n\t\t\ttry {\n\t\t\t\tconst content = fs.readFileSync(realId, 'utf-8');\n\t\t\t\tif (content.includes('<!DOCTYPE html>') || content.includes('<html')) {\n\t\t\t\t\treturn 'export default {};';\n\t\t\t\t}\n\n\t\t\t\tconst compiler = new HtmlCompiler(content);\n\t\t\t\tconst { ts } = await compiler.compile();\n\t\t\t\tgenerateTypes(realId, content, rootDir);\n\n\t\t\t\tconst result = await transformWithEsbuild(ts, realId, {\n\t\t\t\t\tloader: 'ts',\n\t\t\t\t});\n\t\t\t\treturn result.code;\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(`[chispa] Error loading ${id}:`, e);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["fs"]}
1
+ {"version":3,"sources":["../../src/html-compiler/html-compiler.ts","../../src/html-compiler/generator.ts","../../src/html-compiler/vite-plugin.ts"],"sourcesContent":["import { JSDOM } from 'jsdom';\nimport { format } from 'prettier';\n\nconst VOID_ELEMENTS = ['area', 'base', 'br', 'hr', 'img', 'input', 'link', 'meta', 'param', 'keygen', 'source'];\n\nconst SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport class HtmlCompiler {\n\tprivate components: Record<string, string> = {};\n\tprivate stack: string[] = ['fragment'];\n\tprivate componentsItems: Record<string, string[]> = {};\n\tprivate componentsTags: Record<string, string> = {};\n\tprivate isSvg: Record<string, boolean> = {};\n\tprivate inSvgContext = 0;\n\tprivate htmlDocument: Document;\n\n\tconstructor(htmlContent: string) {\n\t\tconst dom = new JSDOM(htmlContent);\n\t\tthis.htmlDocument = dom.window.document;\n\t}\n\n\tprivate static camelize(str: string): string {\n\t\tif (str.startsWith('--')) {\n\t\t\treturn str;\n\t\t}\n\t\tconst arr = str.split('-');\n\t\tlet camelized = '';\n\t\tarr.forEach((v, i) => {\n\t\t\tcamelized += i === 0 ? v : v.charAt(0).toUpperCase() + v.slice(1);\n\t\t});\n\t\treturn camelized;\n\t}\n\n\tprivate static parseStyle(cssCode: string): string {\n\t\tlet out = '{';\n\t\tconst styles = cssCode.split(';');\n\t\tstyles.forEach((line) => {\n\t\t\tconst parts = line.split(':');\n\t\t\tif (parts.length !== 2) return;\n\t\t\tconst prop = HtmlCompiler.camelize(parts[0].trim());\n\t\t\tout += ` ${prop}: '${parts[1].trim()}',`;\n\t\t});\n\t\tout += '}';\n\t\treturn out;\n\t}\n\n\tprivate makeClassAttr(classAttr: string | null, isComponent: boolean): string {\n\t\tconst tplClasses = (classAttr || '').split(' ');\n\t\tlet finalClass = '';\n\n\t\ttplClasses.forEach((tplClass) => {\n\t\t\tif (!tplClass.startsWith('-tpl--')) {\n\t\t\t\tfinalClass += tplClass + ' ';\n\t\t\t}\n\t\t});\n\n\t\tfinalClass = finalClass.trim();\n\n\t\treturn ` 'class': \"${finalClass}\", `;\n\t}\n\n\tprivate getHtmlNodeAttrs(domNode: Element, isComponent: boolean): string {\n\t\tlet attrsHtml = '{';\n\t\tattrsHtml += this.makeClassAttr(domNode.getAttribute('class'), isComponent);\n\n\t\tArray.from(domNode.attributes).forEach((attr) => {\n\t\t\tconst attrName = attr.name;\n\t\t\tlet attrValue = attr.value;\n\n\t\t\tif (attrName === 'data-cb') return;\n\t\t\tif (attrName === 'class') return;\n\n\t\t\t// Use JSON.stringify to properly escape newlines, quotes and other characters\n\t\t\tconst valueLiteral = JSON.stringify(attrValue);\n\n\t\t\t// Simplified logic compared to PHP which had cbt.prefixize... calls\n\t\t\t// Assuming we just output the value for now as I don't see cbt implementation here\n\t\t\t// The PHP code imported CoreBuilderTools but here we might not have it.\n\t\t\t// The user's example output imports from 'chispa'.\n\t\t\t// I will stick to simple string values for now unless I see cbt in chispa.\n\n\t\t\tif (attrName === 'style') {\n\t\t\t\t// PHP called cbt.prefixizeStyle, but also had parse_style static method.\n\t\t\t\t// Wait, the PHP code used cbt.prefixizeStyle inside get_html_node_attrs.\n\t\t\t\t// But parse_style was defined but not used in the snippet I read?\n\t\t\t\t// Ah, I should check if I should use parseStyle or just output string.\n\t\t\t\t// The PHP code: $attrs_html .= \" '$attr_name': cbt.prefixizeStyle('$attr_value'), \";\n\t\t\t\t// If cbt is a runtime helper, I should output the call.\n\t\t\t\t// But wait, the generated code imports CoreBuilderTools.\n\t\t\t\t// Does 'chispa' export CoreBuilderTools?\n\t\t\t\t// src/index.ts does NOT export CoreBuilderTools.\n\t\t\t\t// It exports appendChild, getItem, etc.\n\t\t\t\t// Maybe I should just output the string for now.\n\t\t\t\tattrsHtml += ` '${attrName}': ${valueLiteral}, `;\n\t\t\t} else {\n\t\t\t\tattrsHtml += ` '${attrName}': ${valueLiteral}, `;\n\t\t\t}\n\t\t});\n\n\t\tattrsHtml += '}';\n\t\treturn attrsHtml;\n\t}\n\n\tprivate buildTsForNode(domNode: Node, isComponent = false): string {\n\t\tlet htmlNodeCode = '';\n\n\t\tif (domNode.nodeType === 1) {\n\t\t\t// Element\n\t\t\tconst element = domNode as Element;\n\t\t\tlet tagName = element.tagName;\n\n\t\t\tif (tagName === 'svg') {\n\t\t\t\tthis.inSvgContext++;\n\t\t\t}\n\n\t\t\tlet cbid = element.getAttribute('data-cb');\n\n\t\t\tif (cbid) {\n\t\t\t\tconst currComp = this.stack[0];\n\t\t\t\telement.removeAttribute('data-cb');\n\t\t\t\tcbid = HtmlCompiler.camelize(cbid);\n\t\t\t\t// Pushear a todos los padres\n\t\t\t\tfor (const comp of this.stack) {\n\t\t\t\t\tif (!this.componentsItems[comp]) {\n\t\t\t\t\t\tthis.componentsItems[comp] = [];\n\t\t\t\t\t}\n\t\t\t\t\tthis.componentsItems[comp].push(cbid);\n\t\t\t\t}\n\n\t\t\t\tthis.stack.unshift(cbid);\n\t\t\t\tthis.components[cbid] = this.buildTsForNode(element, true);\n\t\t\t\tthis.componentsTags[cbid] = element.tagName;\n\t\t\t\tthis.isSvg[cbid] = this.inSvgContext > 0;\n\t\t\t\tthis.stack.shift();\n\n\t\t\t\tif (currComp === 'fragment') {\n\t\t\t\t\thtmlNodeCode += `getItem(template, props, '${cbid}')`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `getItem(template, props.nodes, '${cbid}')`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst attrs = this.getHtmlNodeAttrs(element, isComponent);\n\n\t\t\t\tif (!this.inSvgContext) {\n\t\t\t\t\ttagName = tagName.toLowerCase();\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElement('${tagName}');\\n`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElementNS('${SVG_NAMESPACE}', '${tagName}');\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `setAttributes(node, ${attrs});\\n`;\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `setProps(node, props);\\n`;\n\t\t\t\t}\n\n\t\t\t\tlet subTs = '';\n\t\t\t\telement.childNodes.forEach((child) => {\n\t\t\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\t\t\tif (chCode) {\n\t\t\t\t\t\tsubTs += `appendChild(node, ${chCode});\\n`;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (!VOID_ELEMENTS.includes(tagName.toLowerCase())) {\n\t\t\t\t\tif (isComponent) {\n\t\t\t\t\t\thtmlNodeCode += `\n if (props.inner === null) {\n node.innerHTML = '';\n } else if (props.inner !== undefined) {\n node.innerHTML = '';\n appendChild(node, props.inner);\n } else {\n ${subTs}\n }\n `;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtmlNodeCode += subTs;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `if (typeof props._ref === 'function') props._ref(node);\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `return node;})()`;\n\n\t\t\t\tif (tagName === 'svg') {\n\t\t\t\t\tthis.inSvgContext--;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (domNode.nodeType === 3) {\n\t\t\t// Text\n\t\t\tconst textNode = domNode as Text;\n\t\t\tconst parent = textNode.parentNode as Element;\n\t\t\tconst parentTag = parent ? parent.tagName.toLowerCase() : '';\n\n\t\t\tconst mustOmit = ['table', 'thead', 'tbody', 'tfoot', 'tr'].includes(parentTag);\n\n\t\t\tif (!mustOmit && textNode.textContent) {\n\t\t\t\tif (textNode.textContent.trim() === '') {\n\t\t\t\t\tif (textNode.textContent.length > 0) {\n\t\t\t\t\t\thtmlNodeCode += `document.createTextNode(' ')`;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode = `document.createTextNode(${JSON.stringify(textNode.textContent)})`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn htmlNodeCode.trim();\n\t}\n\n\tprivate static getPropsTypename(cbid: string): string {\n\t\treturn 'Cb' + cbid.charAt(0).toUpperCase() + cbid.slice(1) + 'Props';\n\t}\n\n\tprivate wrapFnComponent(cbid: string, jsx: string): string {\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\treturn `(props: ${typename}) => { \\n return(${jsx}); \\n }`;\n\t}\n\n\tprivate createAllComponents() {\n\t\tconst body = this.htmlDocument.querySelector('body');\n\t\tif (!body) throw new Error('Not valid HTML');\n\n\t\tlet rendererJsx = '(() => { const fragment = document.createDocumentFragment();\\n';\n\n\t\tbody.childNodes.forEach((child) => {\n\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\tif (chCode) {\n\t\t\t\trendererJsx += `appendChild(fragment, ${chCode});\\n`;\n\t\t\t}\n\t\t});\n\n\t\trendererJsx += 'return fragment;\\n';\n\t\trendererJsx += '})()';\n\n\t\tthis.components['fragment'] = rendererJsx;\n\t}\n\n\tprivate getTypedef(cbid: string): string {\n\t\tconst items = this.componentsItems[cbid] || [];\n\t\tlet itemsType = '{\\n';\n\t\titems.forEach((itemCbid) => {\n\t\t\tconst itemTypename = HtmlCompiler.getPropsTypename(itemCbid);\n\t\t\titemsType += `${itemCbid}?: ${itemTypename} | ChispaContentReactive;\\n`;\n\t\t});\n\t\titemsType += '}\\n';\n\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\n\t\tif (cbid === 'fragment') {\n\t\t\treturn `interface ${typename} ${itemsType}`;\n\t\t} else {\n\t\t\tconst tagname = this.componentsTags[cbid];\n\t\t\tif (this.isSvg[cbid]) {\n\t\t\t\treturn `type ${typename} = ChispaNodeBuilderPropsReactive<SVGElementTagNameMap['${tagname}'], ${itemsType}>;`;\n\t\t\t} else {\n\t\t\t\treturn `type ${typename} = ChispaNodeBuilderPropsReactive<HTMLElementTagNameMap['${tagname.toLowerCase()}'], ${itemsType}>;`;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async compile(): Promise<{ ts: string; dts: string }> {\n\t\tthis.createAllComponents();\n\n\t\tlet componentsClasses = '';\n\t\tlet typedefs = '';\n\n\t\tfor (const [cbid, compJsx] of Object.entries(this.components)) {\n\t\t\ttypedefs += this.getTypedef(cbid) + '\\n';\n\t\t\tcomponentsClasses += `${cbid}: ${this.wrapFnComponent(cbid, compJsx)},\\n`;\n\t\t}\n\n\t\tconst jsOutput = `\n import { appendChild, getItem, setAttributes, setProps } from 'chispa';\n import type { ChispaContentReactive, ChispaNodeBuilderPropsReactive } from 'chispa';\n\t\t\t\n const SVG_NS = 'http://www.w3.org/2000/svg';\n \n const template = {\n ${componentsClasses}\n };\n \n export default template;\n `;\n\n\t\tconst dtsOutput = `\n import type { ChispaContentReactive, ChispaNodeBuilderPropsReactive } from 'chispa';\n \n ${typedefs}\n \n declare const template: {\n ${Object.keys(this.components)\n\t\t\t\t\t.map((cbid) => {\n\t\t\t\t\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\t\t\t\t\treturn `${cbid}: (props: ${typename}) => Node | DocumentFragment;`;\n\t\t\t\t\t})\n\t\t\t\t\t.join('\\n')}\n };\n \n export default template;\n `;\n\n\t\tconst prettierOptions = {\n\t\t\tparser: 'typescript',\n\t\t\tsemi: true,\n\t\t\tsingleQuote: true,\n\t\t\tuseTabs: true,\n\t\t\tprintWidth: 120,\n\t\t};\n\n\t\treturn {\n\t\t\tts: await format(jsOutput, prettierOptions),\n\t\t\tdts: await format(dtsOutput, prettierOptions),\n\t\t};\n\t}\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { HtmlCompiler } from './html-compiler';\n\nexport async function generateTypes(filePath: string, content: string, rootDir: string) {\n\ttry {\n\t\tconst compiler = new HtmlCompiler(content);\n\t\tconst { dts } = await compiler.compile();\n\n\t\tconst outDir = path.join(rootDir, '.chispa/types');\n\t\tconst relativePath = path.relative(rootDir, filePath);\n\t\tconst targetPath = path.join(outDir, relativePath + '.d.ts');\n\t\tconst targetDir = path.dirname(targetPath);\n\n\t\tif (!fs.existsSync(targetDir)) {\n\t\t\tfs.mkdirSync(targetDir, { recursive: true });\n\t\t}\n\t\tfs.writeFileSync(targetPath, dts);\n\t} catch (e) {\n\t\tconsole.error(`[chispa] Error generating types for ${filePath}`, e);\n\t}\n}\n\nexport async function findAndCompileHtmlFiles(dir: string, rootDir: string) {\n\tif (!fs.existsSync(dir)) return;\n\tconst files = fs.readdirSync(dir);\n\tfor (const file of files) {\n\t\tconst fullPath = path.join(dir, file);\n\t\tif (fullPath === path.join(rootDir, 'index.html')) continue;\n\t\tif (fs.statSync(fullPath).isDirectory()) {\n\t\t\tif (file !== 'node_modules' && file !== '.git' && file !== 'dist' && file !== '.chispa') {\n\t\t\t\tawait findAndCompileHtmlFiles(fullPath, rootDir);\n\t\t\t}\n\t\t} else if (file.endsWith('.html')) {\n\t\t\tconsole.log('Generating types for', fullPath);\n\t\t\tconst content = fs.readFileSync(fullPath, 'utf-8');\n\t\t\tawait generateTypes(fullPath, content, rootDir);\n\t\t}\n\t}\n}\n","import { HtmlCompiler } from './html-compiler';\nimport { generateTypes, findAndCompileHtmlFiles } from './generator';\nimport { type Plugin, transformWithOxc } from 'vite';\nimport * as fs from 'fs';\n\n/**\n * Convierte una ruta real de archivo en el ID de módulo virtual que usa Vite/Rollup.\n * Añade el prefijo `\\0` para marcar el módulo como virtual y el sufijo\n * `.chispa.ts` para que sea tratado como módulo TypeScript.\n */\nconst toVirtualId = (id: string) => '\\0' + id + '.chispa.ts';\n\n/**\n * Convierte un ID de módulo virtual de vuelta a la ruta real del archivo.\n * Elimina el prefijo `\\0` (si existe) y el sufijo `.chispa.ts`.\n */\nconst fromVirtualId = (id: string) => id.replace(/^\\0/, '').replace(/\\.chispa\\.ts$/, '');\n\nconst CHISPA_VIRTUAL_MODULE_SUFFIX = '.html.chispa.ts';\n\nexport function chispaHtmlPlugin(): Plugin {\n\tlet rootDir = process.cwd();\n\n\treturn {\n\t\tname: 'chispa-html',\n\t\tenforce: 'pre',\n\t\tconfigResolved(config) {\n\t\t\trootDir = config.root;\n\t\t},\n\t\tasync buildStart() {\n\t\t\tawait findAndCompileHtmlFiles(rootDir, rootDir);\n\t\t},\n\t\tasync handleHotUpdate(ctx) {\n\t\t\tif (ctx.file.endsWith('.html')) {\n\t\t\t\tconst content = await ctx.read();\n\t\t\t\tawait generateTypes(ctx.file, content, rootDir);\n\n\t\t\t\t// Buscamos el módulo virtual asociado al archivo HTML modificado.\n\t\t\t\tconst module = ctx.server.moduleGraph.getModuleById(toVirtualId(ctx.file));\n\t\t\t\tif (module) {\n\t\t\t\t\treturn [module];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync resolveId(source, importer, options) {\n\t\t\tif (source.endsWith(CHISPA_VIRTUAL_MODULE_SUFFIX)) {\n\t\t\t\treturn source;\n\t\t\t}\n\t\t\tif (source.endsWith('.html') && importer) {\n\t\t\t\tconst resolution = await this.resolve(source, importer, { skipSelf: true, ...options });\n\t\t\t\tif (resolution && !resolution.external) {\n\t\t\t\t\treturn toVirtualId(resolution.id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tasync load(id) {\n\t\t\tif (!id.endsWith(CHISPA_VIRTUAL_MODULE_SUFFIX)) return null;\n\n\t\t\tconst realId = fromVirtualId(id);\n\t\t\tthis.addWatchFile(realId); // To ensure changes in the HTML file trigger a rebuild in watch mode.\n\t\t\ttry {\n\t\t\t\tconst content = fs.readFileSync(realId, 'utf-8');\n\t\t\t\tif (content.includes('<!DOCTYPE html>') || content.includes('<html')) {\n\t\t\t\t\treturn 'export default {};';\n\t\t\t\t}\n\n\t\t\t\tconst compiler = new HtmlCompiler(content);\n\t\t\t\tconst { ts } = await compiler.compile();\n\t\t\t\tgenerateTypes(realId, content, rootDir);\n\n\t\t\t\tconst result = await transformWithOxc(ts, realId + '.ts');\n\t\t\t\treturn result.code;\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(`[chispa] Error loading ${id}:`, e);\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["fs"]}
package/dist/index.d.ts CHANGED
@@ -94,7 +94,7 @@ declare class ComponentList<TItem = any, TProps extends Dict = any> {
94
94
  declare function componentList<TItem>(itemFactoryFn: ItemFactoryFn<TItem, any>, keyFn: KeyFn<TItem>): (listSignal: Signal<TItem[]>, props?: any) => ComponentList<TItem>;
95
95
  declare function componentList<TItem, TProps extends Dict>(itemFactoryFn: ItemFactoryFn<TItem, TProps>, keyFn: KeyFn<TItem>): (listSignal: Signal<TItem[]>, props: TProps) => ComponentList<TItem, TProps>;
96
96
 
97
- type ExecutionKind = 'createComponent' | 'computed' | 'addReactivity';
97
+ type ExecutionKind = 'createComponent' | 'computed' | 'addReactivity' | 'injectSingleton';
98
98
  interface IDisposable {
99
99
  dispose: () => void;
100
100
  }
@@ -202,4 +202,48 @@ declare const ChispaDebugConfig: {
202
202
  enableReactivityWarnings: boolean;
203
203
  };
204
204
 
205
- export { type ChispaContent, type ChispaContentReactive, ChispaDebugConfig, type ChispaNodeBuilderProps, type ChispaNodeBuilderPropsReactive, type ChispaReactive, Component, type ComponentFactory, ComponentList, Link, type LinkProps, type Route, Router, type SelectOption, Signal, WritableSignal, appendChild, bindControlledCheckbox, bindControlledInput, bindControlledSelect, component, componentList, computed, effect, getItem, getValidProps, globalContext, isSignal, isWriteableSignal, navigate, onUnmount, pathMatches, setAttributes, setProps, signal };
205
+ type Constructor<T> = new (...args: any[]) => T;
206
+ /**
207
+ * A typed token that can be used to inject values or interfaces that are not
208
+ * tied to a concrete class constructor.
209
+ *
210
+ * @example
211
+ * const API_URL = new InjectionToken<string>('API_URL');
212
+ * provide(API_URL, () => 'https://api.example.com');
213
+ * const url = inject(API_URL); // string
214
+ */
215
+ declare class InjectionToken<T> {
216
+ readonly description: string;
217
+ constructor(description: string);
218
+ }
219
+ type Token<T> = Constructor<T> | InjectionToken<T>;
220
+ /**
221
+ * Registers a factory function for the given token. The factory is called
222
+ * at most once (the result is cached as a singleton). Must be called before
223
+ * the first `inject(token)` call for that token.
224
+ */
225
+ declare function provide<T>(token: Token<T>, factory: () => T): void;
226
+ interface InjectOptions {
227
+ /**
228
+ * When `true`, a new instance is created every time and is NOT added to the
229
+ * singleton cache. Any reactive effects created in the service constructor
230
+ * will be registered to the currently mounting component and disposed when
231
+ * it unmounts.
232
+ */
233
+ local?: boolean;
234
+ }
235
+ /**
236
+ * Injects (or lazily creates) the singleton service associated with `token`.
237
+ * Any reactive effects declared inside the service constructor will NOT be
238
+ * disposed when the component that first triggers the injection is unmounted.
239
+ *
240
+ * Pass `{ local: true }` to get a fresh, component-scoped instance instead:
241
+ * effects will be disposed together with the component.
242
+ */
243
+ declare function inject<T>(token: Token<T>, options?: InjectOptions): T;
244
+ /**
245
+ * Resets the entire service container. Useful for test isolation.
246
+ */
247
+ declare function resetServices(): void;
248
+
249
+ export { type ChispaContent, type ChispaContentReactive, ChispaDebugConfig, type ChispaNodeBuilderProps, type ChispaNodeBuilderPropsReactive, type ChispaReactive, Component, type ComponentFactory, ComponentList, InjectionToken, Link, type LinkProps, type Route, Router, type SelectOption, Signal, WritableSignal, appendChild, bindControlledCheckbox, bindControlledInput, bindControlledSelect, component, componentList, computed, effect, getItem, getValidProps, globalContext, inject, isSignal, isWriteableSignal, navigate, onUnmount, pathMatches, provide, resetServices, setAttributes, setProps, signal };
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ var AppContext = class {
18
18
  this.componentStack.pop();
19
19
  }
20
20
  getCurrentComponent() {
21
+ if (this.executionStack.includes("injectSingleton")) return null;
21
22
  if (this.componentStack.length === 0) {
22
23
  return null;
23
24
  }
@@ -909,8 +910,76 @@ var Link = component((props) => {
909
910
  setProps(a, rest);
910
911
  return a;
911
912
  });
913
+
914
+ // src/injection.ts
915
+ var InjectionToken = class {
916
+ constructor(description) {
917
+ this.description = description;
918
+ }
919
+ };
920
+ var ServiceContainer = class {
921
+ services = /* @__PURE__ */ new Map();
922
+ factories = /* @__PURE__ */ new Map();
923
+ provide(token, factory) {
924
+ if (this.services.has(token)) {
925
+ const name = token instanceof InjectionToken ? `"${token.description}"` : token.name;
926
+ throw new Error(`Cannot call provide() for ${name} after it has already been injected.`);
927
+ }
928
+ this.factories.set(token, factory);
929
+ }
930
+ get(token) {
931
+ if (this.services.has(token)) {
932
+ return this.services.get(token);
933
+ }
934
+ let service;
935
+ globalContext.pushExecutionStack("injectSingleton");
936
+ try {
937
+ service = this.createInstance(token);
938
+ } finally {
939
+ globalContext.popExecutionStack();
940
+ }
941
+ this.services.set(token, service);
942
+ return service;
943
+ }
944
+ /**
945
+ * Creates a fresh, non-cached instance of the token's service.
946
+ * Runs inside the current component context so that any effects created
947
+ * in the constructor are bound to (and disposed with) that component.
948
+ */
949
+ getLocal(token) {
950
+ return this.createInstance(token);
951
+ }
952
+ createInstance(token) {
953
+ const factory = this.factories.get(token);
954
+ if (factory) {
955
+ return factory();
956
+ } else if (token instanceof InjectionToken) {
957
+ throw new Error(`No provider registered for InjectionToken "${token.description}"`);
958
+ } else {
959
+ return new token();
960
+ }
961
+ }
962
+ reset() {
963
+ this.services.clear();
964
+ this.factories.clear();
965
+ }
966
+ };
967
+ var services = new ServiceContainer();
968
+ function provide(token, factory) {
969
+ services.provide(token, factory);
970
+ }
971
+ function inject(token, options) {
972
+ if (options?.local) {
973
+ return services.getLocal(token);
974
+ }
975
+ return services.get(token);
976
+ }
977
+ function resetServices() {
978
+ services.reset();
979
+ }
912
980
  export {
913
981
  ChispaDebugConfig,
982
+ InjectionToken,
914
983
  Link,
915
984
  Router,
916
985
  appendChild,
@@ -924,11 +993,14 @@ export {
924
993
  getItem,
925
994
  getValidProps,
926
995
  globalContext,
996
+ inject,
927
997
  isSignal,
928
998
  isWriteableSignal,
929
999
  navigate,
930
1000
  onUnmount,
931
1001
  pathMatches,
1002
+ provide,
1003
+ resetServices,
932
1004
  setAttributes,
933
1005
  setProps,
934
1006
  signal
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/context.ts","../src/signals.ts","../src/components.ts","../src/builder.ts","../src/controlled-input.ts","../src/router.ts"],"sourcesContent":["export const ChispaDebugConfig = {\n\tenableReactivityWarnings: false,\n};\n","import { Component, ComponentList } from './components';\nimport { ChispaDebugConfig } from './config';\nimport { Signal } from './signals';\n\ntype ExecutionKind = 'createComponent' | 'computed' | 'addReactivity';\n\nexport interface IDisposable {\n\tdispose: () => void;\n}\n\nclass AppContext {\n\tprivate reactivityContextStack: Reactivity[] = [];\n\n\tprivate refreshTimeout: any = 0;\n\n\t//private contexts = new Set<RenderContext>();\n\n\tprivate dirtyReactivities = new Set<Reactivity>();\n\n\tprivate executionStack: ExecutionKind[] = [];\n\n\tprivate componentStack: (Component | ComponentList)[] = [];\n\n\tpushComponentStack(cmp: Component | ComponentList) {\n\t\tthis.componentStack.push(cmp);\n\t}\n\n\tpopComponentStack() {\n\t\tthis.componentStack.pop();\n\t}\n\n\tgetCurrentComponent() {\n\t\tif (this.componentStack.length === 0) {\n\t\t\t//console.warn('No current component');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.componentStack[this.componentStack.length - 1];\n\t}\n\n\tsetCurrentReactivityContext(context: Reactivity) {\n\t\tthis.reactivityContextStack.push(context);\n\t\t//this.contexts.add(context);\n\t}\n\n\trestorePreviousReactivityContext() {\n\t\tthis.reactivityContextStack.pop();\n\t}\n\n\tgetCurrentRenderContext() {\n\t\tif (this.reactivityContextStack.length === 0) {\n\t\t\t//console.warn('No current render context');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.reactivityContextStack[this.reactivityContextStack.length - 1];\n\t}\n\n\t// Maximum number of iterations to process during a scheduled refresh. Prevents\n\t// unbounded loops in case of uncontrolled reactivity cascades. Use the\n\t// `globalContext.maxScheduleIterations` field to override in tests or\n\t// special cases.\n\tpublic maxScheduleIterations = 100;\n\n\tscheduleRefresh() {\n\t\tif (this.refreshTimeout) {\n\t\t\tclearTimeout(this.refreshTimeout);\n\t\t}\n\t\tthis.refreshTimeout = setTimeout(() => {\n\t\t\tlet iteration = 0;\n\t\t\t// Process dirty contexts until none remain, or until the iteration limit\n\t\t\t// is reached (this avoids infinite loops when reactivities keep\n\t\t\t// re-adding themselves or each other).\n\t\t\twhile (this.dirtyReactivities.size > 0 && iteration < this.maxScheduleIterations) {\n\t\t\t\titeration++;\n\t\t\t\tconst dirtyContexts = Array.from(this.dirtyReactivities);\n\t\t\t\tdirtyContexts.forEach((ctx) => ctx.process());\n\t\t\t}\n\n\t\t\tif (this.dirtyReactivities.size > 0) {\n\t\t\t\t// Warn once if we stopped early due to the iteration limit. We also\n\t\t\t\t// clear the set to avoid repeated warnings and to avoid leaving the\n\t\t\t\t// system in a permanently spinning state.\n\t\t\t\tconsole.warn(`[AppContext.scheduleRefresh] possible uncontrolled reactivity cascade: processed ${iteration} iterations — aborting.`);\n\t\t\t\tthis.dirtyReactivities.clear();\n\t\t\t}\n\t\t}, 0);\n\t}\n\n\taddReactivity(executor: () => void) {\n\t\tconst ctx = new Reactivity(executor);\n\t\tglobalContext.pushExecutionStack('addReactivity');\n\t\tctx.exec();\n\t\tglobalContext.popExecutionStack();\n\t\treturn ctx;\n\t}\n\n\tcreateRoot(component: () => Component, mountPoint: HTMLElement) {\n\t\tthis.dirtyReactivities.clear();\n\t\tmountPoint.innerHTML = '';\n\t\tconst cmp = component();\n\t\tcmp.mount(mountPoint, null);\n\t}\n\n\tcanReadSignal() {\n\t\tconst length = this.executionStack.length;\n\t\tif (length === 0) return true;\n\t\tconst current = this.executionStack[length - 1];\n\t\treturn current !== 'createComponent';\n\t}\n\n\tpushExecutionStack(type: ExecutionKind) {\n\t\tthis.executionStack.push(type);\n\t}\n\n\tpopExecutionStack() {\n\t\tthis.executionStack.pop();\n\t}\n\n\taddDirtyContext(ctx: Reactivity) {\n\t\tthis.dirtyReactivities.add(ctx);\n\t}\n\n\tremoveDirtyContext(ctx: Reactivity) {\n\t\tthis.dirtyReactivities.delete(ctx);\n\t}\n}\n\nexport class Reactivity implements IDisposable {\n\tprivate dirty: boolean = false;\n\n\tprivate signals = new Set<Signal<any>>();\n\n\tconstructor(private readonly action: () => void) {\n\t\tconst currentComponent = globalContext.getCurrentComponent();\n\t\tif (currentComponent) {\n\t\t\tcurrentComponent.addDisposable(this);\n\t\t} else {\n\t\t\tif (ChispaDebugConfig.enableReactivityWarnings) {\n\t\t\t\tconsole.warn('Creating a Reactivity outside of a component');\n\t\t\t}\n\t\t}\n\t}\n\n\tmarkDirty() {\n\t\tthis.dirty = true;\n\t\tglobalContext.addDirtyContext(this);\n\t\tglobalContext.scheduleRefresh();\n\t}\n\n\taddSignal(signal: Signal<any>) {\n\t\tthis.signals.add(signal);\n\t}\n\n\tremoveSignal(signal: Signal<any>) {\n\t\tthis.signals.delete(signal);\n\t}\n\n\tprocess() {\n\t\tif (!this.dirty) return;\n\t\tthis.exec();\n\t\t//console.log('re-render cycle completed');\n\t\tthis.dirty = false;\n\t\tglobalContext.removeDirtyContext(this);\n\t}\n\n\texec() {\n\t\tthis.signals.forEach((s) => s.removeContext(this));\n\t\tthis.signals.clear();\n\t\tglobalContext.setCurrentReactivityContext(this);\n\t\tthis.action();\n\t\tglobalContext.restorePreviousReactivityContext();\n\t}\n\n\tdispose() {\n\t\tthis.signals.forEach((s) => s.removeContext(this));\n\t\tthis.signals.clear();\n\t\tthis.dirty = false;\n\t\tglobalContext.removeDirtyContext(this);\n\t}\n}\n\nexport const globalContext = new AppContext();\n","import { globalContext, Reactivity } from './context';\n\ntype WithSignals<T> = { [K in keyof T]: Signal<T[K]> };\n\nabstract class Signal<T> {\n\tprotected abstract value: T;\n\n\tpublic abstract readonly initialValue: T;\n\n\tprotected contexts: Set<Reactivity> = new Set();\n\n\tconstructor() {}\n\n\tget() {\n\t\tif (!globalContext.canReadSignal()) {\n\t\t\tthrow new Error('Cannot read a signal value during component creation. Consider using a computed signal or an effect instead.');\n\t\t}\n\t\t//context.current.register(this);\n\t\tconst ctx = globalContext.getCurrentRenderContext();\n\t\tif (ctx) {\n\t\t\tthis.contexts.add(ctx);\n\t\t\tctx.addSignal(this);\n\t\t}\n\t\treturn this.value;\n\t}\n\n\tpublic readonly computed = new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget: (_, prop) => {\n\t\t\t\treturn computed(() => this.get()[prop as keyof T]);\n\t\t\t},\n\t\t}\n\t) as WithSignals<T>;\n\n\tremoveContext(ctx: Reactivity) {\n\t\tthis.contexts.delete(ctx);\n\t}\n\n\tdispose() {\n\t\t//console.log('disposing signal', this);\n\t\tthis.contexts.forEach((ctx) => {\n\t\t\tctx.removeSignal(this);\n\t\t});\n\t\tthis.contexts.clear();\n\t}\n}\n\nclass WritableSignal<T> extends Signal<T> {\n\tprotected override value: T;\n\n\tpublic override readonly initialValue: T;\n\n\tconstructor(initialValue: T) {\n\t\tsuper();\n\t\tthis.initialValue = initialValue;\n\t\tthis.value = initialValue;\n\t}\n\n\tset(newValue: T) {\n\t\tthis.value = newValue;\n\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t}\n\n\tupdate(updater: (value: T) => T) {\n\t\tthis.value = updater(this.value);\n\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t}\n}\n\nclass ComputedSignal<T> extends Signal<T> {\n\tprotected override value: T;\n\n\tpublic override readonly initialValue: T;\n\n\tprivate computeFn: () => T;\n\n\tconstructor(computeFn: () => T) {\n\t\tsuper();\n\t\tglobalContext.pushExecutionStack('computed');\n\t\tthis.value = computeFn();\n\t\tthis.initialValue = this.value;\n\t\tglobalContext.popExecutionStack();\n\t\tthis.computeFn = computeFn;\n\t}\n\n\trecompute() {\n\t\tconst newValue = this.computeFn();\n\t\tif (newValue !== this.value) {\n\t\t\tthis.value = newValue;\n\t\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t\t}\n\t}\n}\n\nexport function isSignal(value: any): value is Signal<any> {\n\treturn value instanceof Signal;\n}\n\nexport function isWriteableSignal<T>(value: Signal<T>): value is WritableSignal<T> {\n\treturn value instanceof WritableSignal;\n}\n\nexport function signal<T>(initialValue: T) {\n\tconst sig = new WritableSignal(initialValue);\n\n\t// // Creamos una función que se usará como callable\n\t// const fn = (() => sig.get()) as any;\n\n\t// // Copiamos todas las propiedades y métodos de la instancia a la función\n\t// Object.setPrototypeOf(fn, sig.constructor.prototype);\n\n\t// // Copiamos las propiedades de instancia\n\t// Object.assign(fn, this);\n\n\t// // Retornamos la función como si fuera la instancia\n\t// return fn as WritableSignal<T> & (() => T);\n\n\treturn sig;\n}\n\nexport function computed<T>(fn: () => T) {\n\tlet sig: ComputedSignal<T>;\n\tconst ctx = new Reactivity(() => {\n\t\tsig.recompute();\n\t});\n\tglobalContext.setCurrentReactivityContext(ctx);\n\tsig = new ComputedSignal(fn);\n\tglobalContext.restorePreviousReactivityContext();\n\n\treturn sig as Signal<T>;\n}\n\nexport function effect(fn: () => void) {\n\tglobalContext.addReactivity(fn);\n}\n\nexport type { Signal, WritableSignal };\n","import { ChispaContent } from './builder';\nimport { globalContext, IDisposable } from './context';\nimport { computed, Signal, WritableSignal } from './signals';\n\nexport type Dict = Record<string, any>;\nexport type ComponentFactory<TProps extends Dict> = (props: TProps) => ChispaContent;\n\nexport class Component<TProps extends Dict = any> {\n\tpublic nodes: Node[] | null = null;\n\n\tprivate container: Node | null = null;\n\n\tprivate anchor: Node | null = null;\n\n\tprivate disposables: IDisposable[] = [];\n\n\tpublic silent = true;\n\n\tconstructor(\n\t\tprivate readonly factoryFn: ComponentFactory<TProps>,\n\t\tpublic readonly key: any = null,\n\t\tpublic readonly props: TProps | null = null\n\t) {}\n\n\tmount(container: Node, anchor: Node | null = null) {\n\t\tif (!this.silent) console.log('Mounting Component', this);\n\n\t\tthis.container = container;\n\t\tthis.anchor = anchor;\n\n\t\t// If mounting within another component, register for automatic unmounting\n\t\tconst parentComponent = globalContext.getCurrentComponent();\n\t\tif (parentComponent && parentComponent !== this) {\n\t\t\tparentComponent.addDisposable({\n\t\t\t\tdispose: () => this.unmount(),\n\t\t\t});\n\t\t}\n\n\t\tglobalContext.pushExecutionStack('createComponent');\n\t\tglobalContext.pushComponentStack(this);\n\t\tconst node = this.factoryFn ? (this.factoryFn as any)(this.props) : null;\n\t\tglobalContext.popComponentStack();\n\t\tglobalContext.popExecutionStack();\n\t\t// if node is fragment, convert to array of nodes\n\t\tif (node) {\n\t\t\tif (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n\t\t\t\tthis.nodes = Array.from(node.childNodes);\n\t\t\t} else {\n\t\t\t\tthis.nodes = [node];\n\t\t\t}\n\t\t} else {\n\t\t\tthis.nodes = null;\n\t\t}\n\t\tthis.insertNodes();\n\t}\n\n\treanchor(anchor: Node | null) {\n\t\tthis.anchor = anchor;\n\n\t\t//console.log('reanchoring', this.nodes, ' before anchor', this.anchor);\n\t\tthis.insertNodes();\n\t}\n\n\tprivate insertNodes() {\n\t\tif (!this.container || !this.nodes) return;\n\t\t// Insertar en la nueva posición\n\t\tfor (const node of this.nodes) {\n\t\t\tif (this.anchor) {\n\t\t\t\tthis.container.insertBefore(node, this.anchor);\n\t\t\t} else {\n\t\t\t\tthis.container.appendChild(node);\n\t\t\t}\n\t\t}\n\t}\n\n\taddDisposable(disposable: IDisposable) {\n\t\tthis.disposables.push(disposable);\n\t}\n\n\tunmount() {\n\t\tif (!this.silent) console.log('Unmounting Component', this);\n\n\t\tif (this.nodes) {\n\t\t\tthis.nodes.forEach((node) => {\n\t\t\t\tif (node && node.parentNode) {\n\t\t\t\t\tnode.parentNode.removeChild(node);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.disposables.forEach((d) => {\n\t\t\td.dispose();\n\t\t});\n\t\tthis.disposables = [];\n\t\tthis.nodes = null;\n\t\tthis.container = null;\n\t\tthis.anchor = null;\n\t}\n}\n\n// Definimos overloads para component\nexport function component(factory: ComponentFactory<any>): (props?: any) => Component;\nexport function component<TProps extends Dict>(factory: ComponentFactory<TProps>): (props: TProps) => Component<TProps>;\n\nexport function component<TProps extends Dict = any>(factory: ComponentFactory<TProps>) {\n\treturn (props?: TProps) => {\n\t\treturn new Component(factory, null, props);\n\t};\n}\n\nexport function onUnmount(unmountFn: () => void) {\n\tconst currentComponent = globalContext.getCurrentComponent();\n\tif (currentComponent) {\n\t\tcurrentComponent.addDisposable({\n\t\t\tdispose: unmountFn,\n\t\t});\n\t} else {\n\t\tthrow new Error('onUnmount must be called within a component context');\n\t}\n}\n\ntype ItemFactoryFn<T, TProps = any> = (item: Signal<T>, index: Signal<number>, list: Signal<T[]>, props: TProps, key: any) => ChispaContent;\ntype KeyFn<T> = (item: T, index: number) => any;\n\nexport class ComponentList<TItem = any, TProps extends Dict = any> {\n\tprivate readonly components: Map<string, Component<TProps>>;\n\tprivate container: Node | null = null; // Contenedor donde se montan los nodos\n\tprivate anchor: Node | null = null; // Nodes must be inserted before this node\n\tprivate currentKeys: any[] = [];\n\tpublic disposables: any[] = [];\n\n\tconstructor(\n\t\tprivate readonly itemFactoryFn: ItemFactoryFn<TItem, TProps>,\n\t\tprivate readonly keyFn: KeyFn<TItem>,\n\t\tprivate readonly itemsSignal: Signal<TItem[]>,\n\t\tprivate readonly props: TProps | null = null\n\t) {\n\t\tthis.components = new Map();\n\t}\n\n\t/**\n\t * Obtiene todos los componentes\n\t */\n\tprivate getAllComponents(): Component[] {\n\t\treturn Array.from(this.components.values());\n\t}\n\n\t/**\n\t * Limpia todos los componentes\n\t */\n\tprivate clear(): void {\n\t\tArray.from(this.components.values()).forEach((component) => {\n\t\t\tthis.removeComponent(component);\n\t\t});\n\t}\n\n\t/**\n\t * Elimina un componente completo\n\t */\n\tprivate removeComponent(component: Component) {\n\t\tcomponent.unmount();\n\t\tif (component.key) {\n\t\t\tthis.components.delete(component.key);\n\t\t}\n\t}\n\n\t/**\n\t * Crea un nuevo componente\n\t */\n\tprivate createNewComponent(key: any): Component {\n\t\tconst factory = (props: TProps) => {\n\t\t\tconst item = computed(() => this.itemsSignal.get().find((v, index) => this.keyFn(v, index) === key)!);\n\t\t\tconst index = computed(() => this.itemsSignal.get().findIndex((v, index) => this.keyFn(v, index) === key));\n\t\t\treturn this.itemFactoryFn ? this.itemFactoryFn(item, index, this.itemsSignal, props, key) : null;\n\t\t};\n\n\t\tconst component = new Component(factory, key, this.props);\n\t\tthis.components.set(key, component);\n\n\t\treturn component;\n\t}\n\n\tprivate getTargetAnchor(items: TItem[], index: number): Node | null {\n\t\tconst nextItem = index + 1 < items.length ? items[index + 1] : null;\n\t\tconst nextComp = nextItem ? this.components.get(this.keyFn(nextItem, index + 1)) : null;\n\t\tif (nextComp && nextComp.nodes) {\n\t\t\treturn nextComp.nodes[0];\n\t\t} else {\n\t\t\t// Es el último componente, debería insertarse antes del anchor original\n\t\t\treturn this.anchor;\n\t\t}\n\t}\n\n\t/**\n\t * Función principal que sincroniza los componentes DOM con un array de keys\n\t */\n\tprivate synchronizeComponents(): void {\n\t\tconst existingComponents = this.getAllComponents();\n\n\t\t// Identificar qué componentes eliminar (los que no están en keys)\n\t\tconst items = this.itemsSignal.get();\n\t\tconst keys = items.map((item, index) => this.keyFn(item, index));\n\t\tconst componentsToRemove = existingComponents.filter((component) => component.key && !keys.includes(component.key));\n\t\tcomponentsToRemove.forEach((component) => this.removeComponent(component));\n\n\t\tthis.currentKeys = this.currentKeys.filter((key) => keys.includes(key));\n\t\t//console.log('Current keys:', this.currentKeys, 'Target keys:', keys);\n\n\t\tif (!this.container) {\n\t\t\tconsole.warn('Container is null in synchronizeComponents');\n\t\t\treturn;\n\t\t}\n\t\t// Procesar cada key en el orden deseado\n\t\tconst container = this.container;\n\n\t\titems.forEach((item, index) => {\n\t\t\tconst targetKey = this.keyFn(item, index);\n\t\t\tconst currentKey = this.currentKeys[index];\n\t\t\tif (targetKey === currentKey) {\n\t\t\t\t// La key no ha cambiado de posición, no hacer nada\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst existingComponent = this.components.get(targetKey);\n\n\t\t\tif (existingComponent) {\n\t\t\t\tconst prevComp = this.components.get(currentKey);\n\t\t\t\tif (!prevComp || !prevComp.nodes) {\n\t\t\t\t\tconsole.warn('Previous component or its nodes not found for key', currentKey);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\texistingComponent.reanchor(prevComp.nodes[0]);\n\t\t\t\t// Reordenar el array de keys actuales\n\t\t\t\tthis.currentKeys = this.currentKeys.filter((k) => k !== targetKey);\n\t\t\t\tthis.currentKeys.splice(index, 0, targetKey);\n\t\t\t} else {\n\t\t\t\t// El componente no existe, crearlo\n\t\t\t\tconst targetAnchor = this.getTargetAnchor(items, index);\n\t\t\t\tconst newComponent = this.createNewComponent(targetKey);\n\t\t\t\tnewComponent.mount(container, targetAnchor);\n\t\t\t\tthis.currentKeys.splice(index, 0, targetKey);\n\t\t\t}\n\t\t});\n\t}\n\n\tmount(container: Node, anchor: Node | null = null) {\n\t\t//console.log('Mounting ComponentList');\n\t\tthis.container = container;\n\t\tthis.anchor = anchor;\n\n\t\t// If mounting within another component, register for automatic unmounting\n\t\tconst parentComponent = globalContext.getCurrentComponent();\n\t\tif (parentComponent && parentComponent !== this) {\n\t\t\tparentComponent.addDisposable({\n\t\t\t\tdispose: () => this.unmount(),\n\t\t\t});\n\t\t}\n\n\t\tglobalContext.pushComponentStack(this);\n\t\tglobalContext.addReactivity(() => {\n\t\t\tthis.synchronizeComponents();\n\t\t});\n\t\tglobalContext.popComponentStack();\n\t}\n\n\taddDisposable(disposable: IDisposable) {\n\t\tthis.disposables.push(disposable);\n\t}\n\n\tunmount() {\n\t\t//console.log('Unmounting ComponentList');\n\t\tthis.clear();\n\t\tthis.container = null!;\n\t\tthis.anchor = null!;\n\t\tthis.disposables.forEach((d) => {\n\t\t\td.dispose();\n\t\t});\n\t}\n}\n\n// Definimos overloads para componentList\nexport function componentList<TItem>(\n\titemFactoryFn: ItemFactoryFn<TItem, any>,\n\tkeyFn: KeyFn<TItem>\n): (listSignal: Signal<TItem[]>, props?: any) => ComponentList<TItem>;\nexport function componentList<TItem, TProps extends Dict>(\n\titemFactoryFn: ItemFactoryFn<TItem, TProps>,\n\tkeyFn: KeyFn<TItem>\n): (listSignal: Signal<TItem[]>, props: TProps) => ComponentList<TItem, TProps>;\n\nexport function componentList<TItem, TProps extends Dict = any>(itemFactoryFn: ItemFactoryFn<TItem, TProps>, keyFn: KeyFn<TItem>) {\n\treturn (listSignal: Signal<TItem[]>, props?: TProps) => {\n\t\tconst list = new ComponentList(itemFactoryFn, keyFn, listSignal, props);\n\t\treturn list;\n\t};\n}\n","import { Component, ComponentList } from './components';\nimport { globalContext } from './context';\nimport { computed, isSignal, type Signal } from './signals';\n\nexport type ChispaReactive<T> = T | Signal<T> | (() => T);\nexport type ChispaNode = string | number | Node | null;\nexport type ChispaContent = ChispaNode | Component | (ChispaNode | Component)[] | ComponentList;\nexport type ChispaContentReactive = ChispaReactive<ChispaContent>;\nexport type ChispaClasses = Record<string, ChispaReactive<boolean>>;\nexport type ChispaCSSPropertiesStrings = {\n\t[K in keyof CSSStyleDeclaration]?: ChispaReactive<string>;\n};\n\ntype EventPropKeys<T> = Extract<keyof T, `on${string}`>;\ntype AllowSignals<T> = { [K in keyof T]: ChispaReactive<T[K]> };\n\ntype ChispaNodeBuilderBaseProps<T> = AllowSignals<Omit<T, 'style' | 'dataset' | EventPropKeys<T>>> & Pick<T, EventPropKeys<T>>;\ninterface INodeBuilderSpecialProps {\n\taddClass?: ChispaReactive<string | string[]>;\n\tclasses?: ChispaClasses;\n\tstyle?: ChispaCSSPropertiesStrings;\n\tdataset?: Record<string, ChispaReactive<string>>;\n}\ninterface INodeBuilderAdditionalProps<T, TNodes> {\n\tnodes?: TNodes;\n\tinner?: ChispaContentReactive;\n\t_ref?: (node: T) => void | { current: T | null };\n}\nexport type ChispaNodeBuilderProps<T, TNodes> = Partial<ChispaNodeBuilderBaseProps<T>> & INodeBuilderAdditionalProps<T, TNodes> & INodeBuilderSpecialProps;\nexport type ChispaNodeBuilderPropsReactive<T, TNodes> = ChispaReactive<ChispaNodeBuilderProps<T, TNodes>>;\n\nconst forbiddenProps = ['nodes', 'inner', '_ref'];\n\nexport function getValidProps<T>(props: ChispaNodeBuilderProps<T, any>) {\n\tconst finalProps: any = {};\n\n\tfor (const propName in props) {\n\t\tif (!forbiddenProps.includes(propName)) {\n\t\t\tfinalProps[propName] = props[propName as keyof typeof props];\n\t\t}\n\t}\n\n\treturn finalProps as ChispaNodeBuilderProps<T, any>;\n}\n\nconst itemsStack: any[] = [];\nfunction findItemInStack(itemName: string): any {\n\tfor (const itemsDefs of itemsStack) {\n\t\tif (itemsDefs && itemsDefs[itemName]) {\n\t\t\treturn itemsDefs[itemName];\n\t\t}\n\t}\n\treturn null;\n}\n\nexport function getItem<T>(template: T, items: any, itemName: keyof T) {\n\titemsStack.unshift(items);\n\tconst item: any = findItemInStack(itemName as string);\n\n\tif (!item) {\n\t\titemsStack.shift();\n\t\treturn null;\n\t}\n\n\tlet res;\n\tif (item.constructor && item.constructor.name === 'Object' && !(item instanceof Element)) {\n\t\tconst Comp = template[itemName] as (props: any) => Element;\n\t\tconst itemProps = item;\n\n\t\tres = Comp(itemProps);\n\t} else {\n\t\tres = item;\n\t}\n\titemsStack.shift();\n\treturn res;\n}\n\nexport function setAttributes(node: Element, attributes: Record<string, string>) {\n\tfor (const attr in attributes) {\n\t\tconst attrValue = attributes[attr];\n\t\tif (attrValue === undefined || attrValue === null) {\n\t\t\tnode.removeAttribute(attr);\n\t\t\tcontinue;\n\t\t}\n\t\tnode.setAttribute(attr, attrValue);\n\t}\n}\n\nfunction isEventProp(prop: string) {\n\treturn prop.startsWith('on');\n}\n\nfunction getPropValue(props: any, prop: string) {\n\tconst propValue = props[prop];\n\tif (typeof propValue === 'function' && !isEventProp(prop)) {\n\t\treturn computed(propValue);\n\t}\n\treturn propValue;\n}\n\nexport function setProps<T extends Element>(node: T, props: ChispaNodeBuilderPropsReactive<T, any>) {\n\tlet _props = props;\n\tif (typeof _props === 'function') {\n\t\t_props = computed(_props);\n\t}\n\tif (isSignal(_props)) {\n\t\tglobalContext.addReactivity(() => {\n\t\t\tsetProps(node, _props.get());\n\t\t});\n\t\treturn;\n\t}\n\n\tprops = getValidProps(_props);\n\n\tif (node instanceof HTMLElement) {\n\t\tsetSpecialProps(node, props);\n\t}\n\n\tfor (const prop in props) {\n\t\tconst propValue = getPropValue(props, prop);\n\t\t//console.log('setting prop', prop, propValue )\n\t\tif (isSignal(propValue)) {\n\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t(node as any)[prop] = propValue.get();\n\t\t\t});\n\t\t} else if (propValue === undefined) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\t(node as any)[prop] = propValue;\n\t\t}\n\t}\n}\n\nfunction parseAddClassProp(value: string | string[]): string[] {\n\tconst arr = typeof value === 'string' ? value.split(' ') : value;\n\treturn arr.filter((c) => c.trim() !== '');\n}\n\nfunction setSpecialProps<T extends HTMLElement>(node: T, props: INodeBuilderSpecialProps) {\n\tif (props.style !== undefined) {\n\t\tconst style = props.style;\n\t\tfor (const styleKey in style) {\n\t\t\tlet styleValue = style[styleKey]!;\n\t\t\tif (typeof styleValue === 'function') {\n\t\t\t\tstyleValue = computed(styleValue);\n\t\t\t}\n\t\t\tif (isSignal(styleValue)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tnode.style[styleKey] = styleValue.get();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnode.style[styleKey] = styleValue;\n\t\t\t}\n\t\t}\n\t\tdelete props.style;\n\t}\n\n\tif (props.addClass !== undefined) {\n\t\tlet addClass = props.addClass;\n\t\tlet prevClass: string[] | null = null;\n\n\t\tif (typeof addClass === 'function') {\n\t\t\taddClass = computed(addClass);\n\t\t}\n\n\t\tif (isSignal(addClass)) {\n\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\tconst classes = parseAddClassProp(addClass.get());\n\t\t\t\tconst classesToRemove = prevClass ? prevClass.filter((c) => !classes.includes(c)) : [];\n\t\t\t\tnode.classList.remove(...classesToRemove);\n\t\t\t\tnode.classList.add(...classes);\n\t\t\t\tprevClass = classes;\n\t\t\t});\n\t\t} else {\n\t\t\tconst toAdd = parseAddClassProp(addClass);\n\t\t\tnode.classList.add(...toAdd);\n\t\t}\n\t\tdelete props.addClass;\n\t}\n\n\tif (props.classes !== undefined) {\n\t\tconst classes = props.classes;\n\t\tfor (const className in classes) {\n\t\t\tlet apply = classes[className];\n\t\t\tif (typeof apply === 'function') {\n\t\t\t\tapply = computed(apply);\n\t\t\t}\n\t\t\tif (isSignal(apply)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tif (apply.get()) {\n\t\t\t\t\t\tnode.classList.add(className);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.classList.remove(className);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (classes[className]) {\n\t\t\t\t\tnode.classList.add(className);\n\t\t\t\t} else {\n\t\t\t\t\tnode.classList.remove(className);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdelete props.classes;\n\t}\n\n\tif (props.dataset !== undefined) {\n\t\tconst dataset = props.dataset;\n\t\tfor (const datasetKey in dataset) {\n\t\t\tlet ds = dataset[datasetKey];\n\t\t\tif (typeof ds === 'function') {\n\t\t\t\tds = computed(ds);\n\t\t\t}\n\t\t\tif (isSignal(ds)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tnode.dataset[datasetKey] = ds.get();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnode.dataset[datasetKey] = ds;\n\t\t\t}\n\t\t}\n\t\tdelete props.dataset;\n\t}\n}\n\nexport function appendChild(node: Element | DocumentFragment, child: ChispaContentReactive) {\n\tif (child === null) return;\n\tif (typeof child === 'function') {\n\t\tprocessSignalChild(node, computed(child));\n\t\treturn;\n\t}\n\tif (isSignal(child)) {\n\t\tprocessSignalChild(node, child);\n\t\treturn;\n\t}\n\tif (child instanceof Component || child instanceof ComponentList) {\n\t\tchild.mount(node, null);\n\t\treturn;\n\t}\n\tif (Array.isArray(child)) {\n\t\tchild.forEach((ch) => {\n\t\t\tappendChild(node, ch);\n\t\t});\n\t\treturn;\n\t}\n\tnode.appendChild(child instanceof Node ? child : document.createTextNode(child.toString()));\n}\n\nfunction isStaticArrayWithComponents(arr: ChispaContent): arr is (Component | ChispaNode)[] {\n\tif (!Array.isArray(arr)) return false;\n\tfor (const item of arr) {\n\t\tif (item instanceof Component) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction processSignalChild(node: Element | DocumentFragment, child: Signal<ChispaContent>) {\n\tconst anchor = document.createTextNode('');\n\tnode.appendChild(anchor);\n\tlet prevValue: Component | ComponentList | null = null;\n\n\tglobalContext.addReactivity(() => {\n\t\t//console.log('Signal child changed', child);\n\t\tconst ch = child.get();\n\t\tif (prevValue) {\n\t\t\tprevValue.unmount();\n\t\t}\n\t\tif (ch === null) {\n\t\t\tprevValue = null;\n\t\t\treturn;\n\t\t}\n\n\t\tlet component: Component | ComponentList;\n\t\tif (isStaticArrayWithComponents(ch)) {\n\t\t\tcomponent = new Component(() => {\n\t\t\t\tconst frag = document.createDocumentFragment();\n\t\t\t\tfor (const c of ch) {\n\t\t\t\t\tappendChild(frag, c);\n\t\t\t\t}\n\t\t\t\treturn frag;\n\t\t\t});\n\t\t\tcomponent.mount(node, anchor);\n\t\t} else if (ch instanceof Component || ch instanceof ComponentList) {\n\t\t\tch.mount(node, anchor);\n\t\t\tcomponent = ch;\n\t\t} else {\n\t\t\tconst wrCmp = new Component(() => toNode(ch));\n\t\t\t//wrCmp.silent = true;\n\t\t\twrCmp.mount(node, anchor);\n\t\t\tcomponent = wrCmp;\n\t\t}\n\t\tprevValue = component;\n\t});\n}\n\nfunction toNode(n: ChispaNode | ChispaNode[]): Node | null {\n\tif (Array.isArray(n)) {\n\t\tconst frag = document.createDocumentFragment();\n\t\tconst nodes = n.map((c) => toNode(c)).filter((n) => n !== null);\n\t\tfrag.append(...nodes);\n\t\treturn frag;\n\t} else if (n instanceof Node) {\n\t\treturn n;\n\t} else if (typeof n === 'string' || typeof n === 'number') {\n\t\treturn document.createTextNode(n.toString());\n\t} else {\n\t\treturn null;\n\t\t//throw new Error('Invalid node type');\n\t}\n}\n","import { appendChild, setProps } from './builder';\nimport { componentList } from './components';\nimport { globalContext } from './context';\nimport { computed, isSignal, Signal, WritableSignal } from './signals';\n\nexport interface ControlledInputOptions<T> {\n\t/**\n\t * Optional function to transform the value before setting it to the signal.\n\t * Useful for enforcing uppercase, removing invalid characters, etc.\n\t */\n\ttransform?: (value: T) => T;\n\n\t/**\n\t * Optional function to validate the value.\n\t * If it returns false, the change is rejected and the previous value is restored.\n\t */\n\tvalidate?: (value: T) => boolean;\n}\n\nexport interface SelectOption {\n\tvalue: string;\n\tlabel: string;\n\tdisabled?: boolean;\n}\n\ntype InputValueType = string | number;\n\ninterface TypeConverter<T extends InputValueType> {\n\ttoTargetType: (val: string) => T;\n\tfromTargetType: (val: T) => string;\n}\n\nfunction getTypeConverter<T extends InputValueType>(exampleValue: T): TypeConverter<T> {\n\t// TODO: Extend for other types if needed. Also support partial parsing/formatting with invalid intermediate states (e.g. for dates or decimals)\n\tif (typeof exampleValue === 'number') {\n\t\treturn {\n\t\t\ttoTargetType: (val: string) => Number(val) as T,\n\t\t\tfromTargetType: (val: T) => val.toString(),\n\t\t} as const;\n\t} else {\n\t\treturn {\n\t\t\ttoTargetType: (val: string) => val as T,\n\t\t\tfromTargetType: (val: T) => val as string,\n\t\t} as const;\n\t}\n}\n\nexport function bindControlledInput<T extends InputValueType>(\n\telement: HTMLInputElement | HTMLTextAreaElement,\n\tvalueSignal: WritableSignal<T>,\n\toptions: ControlledInputOptions<T> = {}\n) {\n\tconst { transform, validate } = options;\n\n\t// Get type converters based on the initial value type\n\tconst { toTargetType, fromTargetType } = getTypeConverter(valueSignal.initialValue);\n\n\t// Initialize value\n\telement.value = fromTargetType(valueSignal.initialValue);\n\n\t// Handle input events\n\tconst handleInput = (e: Event) => {\n\t\tconst target = e.target as HTMLInputElement;\n\t\tlet newValue = toTargetType(target.value);\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Save cursor position\n\t\tconst selectionStart = target.selectionStart;\n\t\tconst selectionEnd = target.selectionEnd;\n\n\t\t// Apply transformation if provided\n\t\tif (transform) {\n\t\t\tnewValue = transform(newValue);\n\t\t}\n\n\t\t// Apply validation if provided\n\t\tif (validate && !validate(newValue)) {\n\t\t\t// If invalid, revert to original value\n\t\t\tnewValue = originalValue;\n\t\t}\n\n\t\t// Update signal\n\t\tif (newValue !== originalValue) {\n\t\t\tvalueSignal.set(newValue);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value (e.g. transformed or rejected)\n\t\tconst newValueStr = fromTargetType(newValue);\n\t\tif (target.value !== newValueStr) {\n\t\t\tconst lengthDiff = target.value.length - newValueStr.length;\n\t\t\ttarget.value = newValueStr;\n\n\t\t\t// Restore cursor\n\t\t\tif (selectionStart !== null && selectionEnd !== null) {\n\t\t\t\t// Restore to the saved position.\n\t\t\t\t// Adjust for length difference to keep cursor relative to the content\n\t\t\t\tconst newStart = Math.max(0, selectionStart - lengthDiff);\n\t\t\t\tconst newEnd = Math.max(0, selectionEnd - lengthDiff);\n\t\t\t\ttarget.setSelectionRange(newStart, newEnd);\n\t\t\t}\n\t\t}\n\t};\n\n\telement.addEventListener('input', handleInput);\n\n\t// Subscribe to signal changes to update the input if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValueStr = fromTargetType(valueSignal.get());\n\t\t// Only update if the value is actually different to avoid cursor jumping\n\t\tif (element.value !== newValueStr) {\n\t\t\telement.value = newValueStr;\n\t\t}\n\t});\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('input', handleInput);\n\t};\n}\n\nexport function bindControlledCheckbox(element: HTMLInputElement, valueSignal: WritableSignal<boolean>, indeterminate?: Signal<boolean>) {\n\t// Initialize checked state\n\telement.checked = valueSignal.initialValue;\n\n\t// Handle change events\n\tconst handleChange = (e: Event) => {\n\t\tconst target = e.target as HTMLInputElement;\n\t\tlet newChecked = target.checked;\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Update signal\n\t\tif (newChecked !== originalValue) {\n\t\t\tvalueSignal.set(newChecked);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value\n\t\tif (target.checked !== newChecked) {\n\t\t\ttarget.checked = newChecked;\n\t\t}\n\t};\n\n\telement.addEventListener('change', handleChange);\n\n\t// Subscribe to signal changes to update the checkbox if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValue = valueSignal.get();\n\t\tif (element.checked !== newValue) {\n\t\t\telement.checked = newValue;\n\t\t}\n\t});\n\n\t// Subscribe to indeterminate signal if provided as a Signal\n\tif (indeterminate) {\n\t\tglobalContext.addReactivity(() => {\n\t\t\telement.indeterminate = indeterminate.get();\n\t\t});\n\t}\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('change', handleChange);\n\t};\n}\n\nexport function bindControlledSelect(element: HTMLSelectElement, valueSignal: WritableSignal<string>, optionList?: Signal<SelectOption[]> | SelectOption[]) {\n\tconst Options = componentList<SelectOption>(\n\t\t(option) => {\n\t\t\tconst optElement = document.createElement('option');\n\t\t\tsetProps(optElement, {\n\t\t\t\tvalue: () => option.get().value ?? '',\n\t\t\t\ttextContent: () => option.get().label ?? '',\n\t\t\t\tdisabled: () => option.get().disabled ?? false,\n\t\t\t});\n\t\t\treturn optElement;\n\t\t},\n\t\t(o) => o.value\n\t);\n\n\t// Handle change events\n\tconst handleChange = (e: Event) => {\n\t\tconst target = e.target as HTMLSelectElement;\n\t\tlet newValue = target.value;\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Update signal\n\t\tif (newValue !== originalValue) {\n\t\t\tvalueSignal.set(newValue);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value (e.g. transformed or rejected)\n\t\tif (target.value !== newValue) {\n\t\t\ttarget.value = newValue;\n\t\t}\n\t};\n\n\t// Subscribe to options signal changes if provided\n\tif (optionList) {\n\t\tconst optionsSignal = isSignal(optionList) ? optionList : computed(() => optionList || []);\n\n\t\telement.innerHTML = '';\n\t\tappendChild(element, Options(optionsSignal));\n\t\tglobalContext.addReactivity(() => {\n\t\t\tconst currValue = valueSignal.get();\n\t\t\t// If the current value is not in the new options, reset it\n\t\t\tif (!optionsSignal.get().some((opt) => opt.value === currValue)) {\n\t\t\t\telement.value = '';\n\t\t\t} else if (element.value !== currValue) {\n\t\t\t\telement.value = currValue;\n\t\t\t}\n\t\t});\n\t}\n\n\t// Subscribe to signal changes to update the select if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValue = valueSignal.get();\n\t\t// Only update if the value is actually different\n\t\tif (element.value !== newValue) {\n\t\t\telement.value = newValue;\n\t\t}\n\t});\n\n\telement.addEventListener('change', handleChange);\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('change', handleChange);\n\t};\n}\n","import { signal, computed, Signal } from './signals';\nimport { component, Component, Dict } from './components';\nimport { appendChild, ChispaNodeBuilderProps, setProps } from './builder';\n\nexport interface Route {\n\tpath: string;\n\tcomponent: (props?: any) => Component<any>;\n}\n\nconst currentPath = signal(typeof window !== 'undefined' ? window.location.pathname : '/');\n\nif (typeof window !== 'undefined') {\n\twindow.addEventListener('popstate', () => {\n\t\tcurrentPath.set(window.location.pathname);\n\t});\n}\n\nexport function navigate(to: string, replace = false) {\n\tif (typeof window === 'undefined') {\n\t\tcurrentPath.set(to);\n\t\treturn;\n\t}\n\tif (replace) {\n\t\twindow.history.replaceState({}, '', to);\n\t} else {\n\t\twindow.history.pushState({}, '', to);\n\t}\n\tcurrentPath.set(to);\n}\n\nexport function pathMatches(path: string): Signal<boolean> {\n\treturn computed(() => {\n\t\tconst current = currentPath.get();\n\t\treturn match(path, current) !== null;\n\t});\n}\n\nfunction match(routePath: string, currentPath: string): Dict | null {\n\tif (routePath === '*') return {};\n\tconst routeParts = routePath.split('/').filter(Boolean);\n\tconst currentParts = currentPath.split('/').filter(Boolean);\n\tif (routeParts.length !== currentParts.length) return null;\n\tconst params: Dict = {};\n\tfor (let i = 0; i < routeParts.length; i++) {\n\t\tif (routeParts[i].startsWith(':')) {\n\t\t\tparams[routeParts[i].substring(1)] = currentParts[i];\n\t\t} else if (routeParts[i] !== currentParts[i]) {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn params;\n}\n\nexport const Router = component<{ routes: Route[] }>((props) => {\n\tconst container = document.createElement('div');\n\tcontainer.style.display = 'contents';\n\tconst activeRoute = computed(() => {\n\t\tconst path = currentPath.get();\n\t\tfor (const route of props.routes) {\n\t\t\tconst params = match(route.path, path);\n\t\t\tif (params) {\n\t\t\t\treturn route.component(params);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t});\n\tappendChild(container, activeRoute);\n\treturn container;\n});\n\nexport interface LinkProps extends ChispaNodeBuilderProps<HTMLAnchorElement, {}> {\n\tto: string;\n}\n\nexport const Link = component<LinkProps>((props) => {\n\tconst { to, inner, ...rest } = props;\n\tconst a = document.createElement('a');\n\ta.href = to;\n\n\ta.addEventListener('click', (e) => {\n\t\tif (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.defaultPrevented || e.button !== 0) {\n\t\t\treturn;\n\t\t}\n\t\te.preventDefault();\n\t\tnavigate(to);\n\t});\n\n\tif (inner) {\n\t\tappendChild(a, inner);\n\t}\n\n\tsetProps(a, rest);\n\n\treturn a;\n});\n"],"mappings":"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","names":["component","signal","component","index","component","n","currentPath"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/context.ts","../src/signals.ts","../src/components.ts","../src/builder.ts","../src/controlled-input.ts","../src/router.ts","../src/injection.ts"],"sourcesContent":["export const ChispaDebugConfig = {\n\tenableReactivityWarnings: false,\n};\n","import { Component, ComponentList } from './components';\nimport { ChispaDebugConfig } from './config';\nimport { Signal } from './signals';\n\ntype ExecutionKind = 'createComponent' | 'computed' | 'addReactivity' | 'injectSingleton';\n\nexport interface IDisposable {\n\tdispose: () => void;\n}\n\nclass AppContext {\n\tprivate reactivityContextStack: Reactivity[] = [];\n\n\tprivate refreshTimeout: any = 0;\n\n\t//private contexts = new Set<RenderContext>();\n\n\tprivate dirtyReactivities = new Set<Reactivity>();\n\n\tprivate executionStack: ExecutionKind[] = [];\n\n\tprivate componentStack: (Component | ComponentList)[] = [];\n\n\tpushComponentStack(cmp: Component | ComponentList) {\n\t\tthis.componentStack.push(cmp);\n\t}\n\n\tpopComponentStack() {\n\t\tthis.componentStack.pop();\n\t}\n\n\tgetCurrentComponent() {\n\t\tif (this.executionStack.includes('injectSingleton')) return null;\n\t\tif (this.componentStack.length === 0) {\n\t\t\t//console.warn('No current component');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.componentStack[this.componentStack.length - 1];\n\t}\n\n\tsetCurrentReactivityContext(context: Reactivity) {\n\t\tthis.reactivityContextStack.push(context);\n\t\t//this.contexts.add(context);\n\t}\n\n\trestorePreviousReactivityContext() {\n\t\tthis.reactivityContextStack.pop();\n\t}\n\n\tgetCurrentRenderContext() {\n\t\tif (this.reactivityContextStack.length === 0) {\n\t\t\t//console.warn('No current render context');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.reactivityContextStack[this.reactivityContextStack.length - 1];\n\t}\n\n\t// Maximum number of iterations to process during a scheduled refresh. Prevents\n\t// unbounded loops in case of uncontrolled reactivity cascades. Use the\n\t// `globalContext.maxScheduleIterations` field to override in tests or\n\t// special cases.\n\tpublic maxScheduleIterations = 100;\n\n\tscheduleRefresh() {\n\t\tif (this.refreshTimeout) {\n\t\t\tclearTimeout(this.refreshTimeout);\n\t\t}\n\t\tthis.refreshTimeout = setTimeout(() => {\n\t\t\tlet iteration = 0;\n\t\t\t// Process dirty contexts until none remain, or until the iteration limit\n\t\t\t// is reached (this avoids infinite loops when reactivities keep\n\t\t\t// re-adding themselves or each other).\n\t\t\twhile (this.dirtyReactivities.size > 0 && iteration < this.maxScheduleIterations) {\n\t\t\t\titeration++;\n\t\t\t\tconst dirtyContexts = Array.from(this.dirtyReactivities);\n\t\t\t\tdirtyContexts.forEach((ctx) => ctx.process());\n\t\t\t}\n\n\t\t\tif (this.dirtyReactivities.size > 0) {\n\t\t\t\t// Warn once if we stopped early due to the iteration limit. We also\n\t\t\t\t// clear the set to avoid repeated warnings and to avoid leaving the\n\t\t\t\t// system in a permanently spinning state.\n\t\t\t\tconsole.warn(`[AppContext.scheduleRefresh] possible uncontrolled reactivity cascade: processed ${iteration} iterations — aborting.`);\n\t\t\t\tthis.dirtyReactivities.clear();\n\t\t\t}\n\t\t}, 0);\n\t}\n\n\taddReactivity(executor: () => void) {\n\t\tconst ctx = new Reactivity(executor);\n\t\tglobalContext.pushExecutionStack('addReactivity');\n\t\tctx.exec();\n\t\tglobalContext.popExecutionStack();\n\t\treturn ctx;\n\t}\n\n\tcreateRoot(component: () => Component, mountPoint: HTMLElement) {\n\t\tthis.dirtyReactivities.clear();\n\t\tmountPoint.innerHTML = '';\n\t\tconst cmp = component();\n\t\tcmp.mount(mountPoint, null);\n\t}\n\n\tcanReadSignal() {\n\t\tconst length = this.executionStack.length;\n\t\tif (length === 0) return true;\n\t\tconst current = this.executionStack[length - 1];\n\t\treturn current !== 'createComponent';\n\t}\n\n\tpushExecutionStack(type: ExecutionKind) {\n\t\tthis.executionStack.push(type);\n\t}\n\n\tpopExecutionStack() {\n\t\tthis.executionStack.pop();\n\t}\n\n\taddDirtyContext(ctx: Reactivity) {\n\t\tthis.dirtyReactivities.add(ctx);\n\t}\n\n\tremoveDirtyContext(ctx: Reactivity) {\n\t\tthis.dirtyReactivities.delete(ctx);\n\t}\n}\n\nexport class Reactivity implements IDisposable {\n\tprivate dirty: boolean = false;\n\n\tprivate signals = new Set<Signal<any>>();\n\n\tconstructor(private readonly action: () => void) {\n\t\tconst currentComponent = globalContext.getCurrentComponent();\n\t\tif (currentComponent) {\n\t\t\tcurrentComponent.addDisposable(this);\n\t\t} else {\n\t\t\tif (ChispaDebugConfig.enableReactivityWarnings) {\n\t\t\t\tconsole.warn('Creating a Reactivity outside of a component');\n\t\t\t}\n\t\t}\n\t}\n\n\tmarkDirty() {\n\t\tthis.dirty = true;\n\t\tglobalContext.addDirtyContext(this);\n\t\tglobalContext.scheduleRefresh();\n\t}\n\n\taddSignal(signal: Signal<any>) {\n\t\tthis.signals.add(signal);\n\t}\n\n\tremoveSignal(signal: Signal<any>) {\n\t\tthis.signals.delete(signal);\n\t}\n\n\tprocess() {\n\t\tif (!this.dirty) return;\n\t\tthis.exec();\n\t\t//console.log('re-render cycle completed');\n\t\tthis.dirty = false;\n\t\tglobalContext.removeDirtyContext(this);\n\t}\n\n\texec() {\n\t\tthis.signals.forEach((s) => s.removeContext(this));\n\t\tthis.signals.clear();\n\t\tglobalContext.setCurrentReactivityContext(this);\n\t\tthis.action();\n\t\tglobalContext.restorePreviousReactivityContext();\n\t}\n\n\tdispose() {\n\t\tthis.signals.forEach((s) => s.removeContext(this));\n\t\tthis.signals.clear();\n\t\tthis.dirty = false;\n\t\tglobalContext.removeDirtyContext(this);\n\t}\n}\n\nexport const globalContext = new AppContext();\n","import { globalContext, Reactivity } from './context';\n\ntype WithSignals<T> = { [K in keyof T]: Signal<T[K]> };\n\nabstract class Signal<T> {\n\tprotected abstract value: T;\n\n\tpublic abstract readonly initialValue: T;\n\n\tprotected contexts: Set<Reactivity> = new Set();\n\n\tconstructor() {}\n\n\tget() {\n\t\tif (!globalContext.canReadSignal()) {\n\t\t\tthrow new Error('Cannot read a signal value during component creation. Consider using a computed signal or an effect instead.');\n\t\t}\n\t\t//context.current.register(this);\n\t\tconst ctx = globalContext.getCurrentRenderContext();\n\t\tif (ctx) {\n\t\t\tthis.contexts.add(ctx);\n\t\t\tctx.addSignal(this);\n\t\t}\n\t\treturn this.value;\n\t}\n\n\tpublic readonly computed = new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget: (_, prop) => {\n\t\t\t\treturn computed(() => this.get()[prop as keyof T]);\n\t\t\t},\n\t\t}\n\t) as WithSignals<T>;\n\n\tremoveContext(ctx: Reactivity) {\n\t\tthis.contexts.delete(ctx);\n\t}\n\n\tdispose() {\n\t\t//console.log('disposing signal', this);\n\t\tthis.contexts.forEach((ctx) => {\n\t\t\tctx.removeSignal(this);\n\t\t});\n\t\tthis.contexts.clear();\n\t}\n}\n\nclass WritableSignal<T> extends Signal<T> {\n\tprotected override value: T;\n\n\tpublic override readonly initialValue: T;\n\n\tconstructor(initialValue: T) {\n\t\tsuper();\n\t\tthis.initialValue = initialValue;\n\t\tthis.value = initialValue;\n\t}\n\n\tset(newValue: T) {\n\t\tthis.value = newValue;\n\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t}\n\n\tupdate(updater: (value: T) => T) {\n\t\tthis.value = updater(this.value);\n\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t}\n}\n\nclass ComputedSignal<T> extends Signal<T> {\n\tprotected override value: T;\n\n\tpublic override readonly initialValue: T;\n\n\tprivate computeFn: () => T;\n\n\tconstructor(computeFn: () => T) {\n\t\tsuper();\n\t\tglobalContext.pushExecutionStack('computed');\n\t\tthis.value = computeFn();\n\t\tthis.initialValue = this.value;\n\t\tglobalContext.popExecutionStack();\n\t\tthis.computeFn = computeFn;\n\t}\n\n\trecompute() {\n\t\tconst newValue = this.computeFn();\n\t\tif (newValue !== this.value) {\n\t\t\tthis.value = newValue;\n\t\t\tthis.contexts.forEach((ctx) => ctx.markDirty());\n\t\t}\n\t}\n}\n\nexport function isSignal(value: any): value is Signal<any> {\n\treturn value instanceof Signal;\n}\n\nexport function isWriteableSignal<T>(value: Signal<T>): value is WritableSignal<T> {\n\treturn value instanceof WritableSignal;\n}\n\nexport function signal<T>(initialValue: T) {\n\tconst sig = new WritableSignal(initialValue);\n\n\t// // Creamos una función que se usará como callable\n\t// const fn = (() => sig.get()) as any;\n\n\t// // Copiamos todas las propiedades y métodos de la instancia a la función\n\t// Object.setPrototypeOf(fn, sig.constructor.prototype);\n\n\t// // Copiamos las propiedades de instancia\n\t// Object.assign(fn, this);\n\n\t// // Retornamos la función como si fuera la instancia\n\t// return fn as WritableSignal<T> & (() => T);\n\n\treturn sig;\n}\n\nexport function computed<T>(fn: () => T) {\n\tlet sig: ComputedSignal<T>;\n\tconst ctx = new Reactivity(() => {\n\t\tsig.recompute();\n\t});\n\tglobalContext.setCurrentReactivityContext(ctx);\n\tsig = new ComputedSignal(fn);\n\tglobalContext.restorePreviousReactivityContext();\n\n\treturn sig as Signal<T>;\n}\n\nexport function effect(fn: () => void) {\n\tglobalContext.addReactivity(fn);\n}\n\nexport type { Signal, WritableSignal };\n","import { ChispaContent } from './builder';\nimport { globalContext, IDisposable } from './context';\nimport { computed, Signal, WritableSignal } from './signals';\n\nexport type Dict = Record<string, any>;\nexport type ComponentFactory<TProps extends Dict> = (props: TProps) => ChispaContent;\n\nexport class Component<TProps extends Dict = any> {\n\tpublic nodes: Node[] | null = null;\n\n\tprivate container: Node | null = null;\n\n\tprivate anchor: Node | null = null;\n\n\tprivate disposables: IDisposable[] = [];\n\n\tpublic silent = true;\n\n\tconstructor(\n\t\tprivate readonly factoryFn: ComponentFactory<TProps>,\n\t\tpublic readonly key: any = null,\n\t\tpublic readonly props: TProps | null = null\n\t) {}\n\n\tmount(container: Node, anchor: Node | null = null) {\n\t\tif (!this.silent) console.log('Mounting Component', this);\n\n\t\tthis.container = container;\n\t\tthis.anchor = anchor;\n\n\t\t// If mounting within another component, register for automatic unmounting\n\t\tconst parentComponent = globalContext.getCurrentComponent();\n\t\tif (parentComponent && parentComponent !== this) {\n\t\t\tparentComponent.addDisposable({\n\t\t\t\tdispose: () => this.unmount(),\n\t\t\t});\n\t\t}\n\n\t\tglobalContext.pushExecutionStack('createComponent');\n\t\tglobalContext.pushComponentStack(this);\n\t\tconst node = this.factoryFn ? (this.factoryFn as any)(this.props) : null;\n\t\tglobalContext.popComponentStack();\n\t\tglobalContext.popExecutionStack();\n\t\t// if node is fragment, convert to array of nodes\n\t\tif (node) {\n\t\t\tif (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n\t\t\t\tthis.nodes = Array.from(node.childNodes);\n\t\t\t} else {\n\t\t\t\tthis.nodes = [node];\n\t\t\t}\n\t\t} else {\n\t\t\tthis.nodes = null;\n\t\t}\n\t\tthis.insertNodes();\n\t}\n\n\treanchor(anchor: Node | null) {\n\t\tthis.anchor = anchor;\n\n\t\t//console.log('reanchoring', this.nodes, ' before anchor', this.anchor);\n\t\tthis.insertNodes();\n\t}\n\n\tprivate insertNodes() {\n\t\tif (!this.container || !this.nodes) return;\n\t\t// Insertar en la nueva posición\n\t\tfor (const node of this.nodes) {\n\t\t\tif (this.anchor) {\n\t\t\t\tthis.container.insertBefore(node, this.anchor);\n\t\t\t} else {\n\t\t\t\tthis.container.appendChild(node);\n\t\t\t}\n\t\t}\n\t}\n\n\taddDisposable(disposable: IDisposable) {\n\t\tthis.disposables.push(disposable);\n\t}\n\n\tunmount() {\n\t\tif (!this.silent) console.log('Unmounting Component', this);\n\n\t\tif (this.nodes) {\n\t\t\tthis.nodes.forEach((node) => {\n\t\t\t\tif (node && node.parentNode) {\n\t\t\t\t\tnode.parentNode.removeChild(node);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.disposables.forEach((d) => {\n\t\t\td.dispose();\n\t\t});\n\t\tthis.disposables = [];\n\t\tthis.nodes = null;\n\t\tthis.container = null;\n\t\tthis.anchor = null;\n\t}\n}\n\n// Definimos overloads para component\nexport function component(factory: ComponentFactory<any>): (props?: any) => Component;\nexport function component<TProps extends Dict>(factory: ComponentFactory<TProps>): (props: TProps) => Component<TProps>;\n\nexport function component<TProps extends Dict = any>(factory: ComponentFactory<TProps>) {\n\treturn (props?: TProps) => {\n\t\treturn new Component(factory, null, props);\n\t};\n}\n\nexport function onUnmount(unmountFn: () => void) {\n\tconst currentComponent = globalContext.getCurrentComponent();\n\tif (currentComponent) {\n\t\tcurrentComponent.addDisposable({\n\t\t\tdispose: unmountFn,\n\t\t});\n\t} else {\n\t\tthrow new Error('onUnmount must be called within a component context');\n\t}\n}\n\ntype ItemFactoryFn<T, TProps = any> = (item: Signal<T>, index: Signal<number>, list: Signal<T[]>, props: TProps, key: any) => ChispaContent;\ntype KeyFn<T> = (item: T, index: number) => any;\n\nexport class ComponentList<TItem = any, TProps extends Dict = any> {\n\tprivate readonly components: Map<string, Component<TProps>>;\n\tprivate container: Node | null = null; // Contenedor donde se montan los nodos\n\tprivate anchor: Node | null = null; // Nodes must be inserted before this node\n\tprivate currentKeys: any[] = [];\n\tpublic disposables: any[] = [];\n\n\tconstructor(\n\t\tprivate readonly itemFactoryFn: ItemFactoryFn<TItem, TProps>,\n\t\tprivate readonly keyFn: KeyFn<TItem>,\n\t\tprivate readonly itemsSignal: Signal<TItem[]>,\n\t\tprivate readonly props: TProps | null = null\n\t) {\n\t\tthis.components = new Map();\n\t}\n\n\t/**\n\t * Obtiene todos los componentes\n\t */\n\tprivate getAllComponents(): Component[] {\n\t\treturn Array.from(this.components.values());\n\t}\n\n\t/**\n\t * Limpia todos los componentes\n\t */\n\tprivate clear(): void {\n\t\tArray.from(this.components.values()).forEach((component) => {\n\t\t\tthis.removeComponent(component);\n\t\t});\n\t}\n\n\t/**\n\t * Elimina un componente completo\n\t */\n\tprivate removeComponent(component: Component) {\n\t\tcomponent.unmount();\n\t\tif (component.key) {\n\t\t\tthis.components.delete(component.key);\n\t\t}\n\t}\n\n\t/**\n\t * Crea un nuevo componente\n\t */\n\tprivate createNewComponent(key: any): Component {\n\t\tconst factory = (props: TProps) => {\n\t\t\tconst item = computed(() => this.itemsSignal.get().find((v, index) => this.keyFn(v, index) === key)!);\n\t\t\tconst index = computed(() => this.itemsSignal.get().findIndex((v, index) => this.keyFn(v, index) === key));\n\t\t\treturn this.itemFactoryFn ? this.itemFactoryFn(item, index, this.itemsSignal, props, key) : null;\n\t\t};\n\n\t\tconst component = new Component(factory, key, this.props);\n\t\tthis.components.set(key, component);\n\n\t\treturn component;\n\t}\n\n\tprivate getTargetAnchor(items: TItem[], index: number): Node | null {\n\t\tconst nextItem = index + 1 < items.length ? items[index + 1] : null;\n\t\tconst nextComp = nextItem ? this.components.get(this.keyFn(nextItem, index + 1)) : null;\n\t\tif (nextComp && nextComp.nodes) {\n\t\t\treturn nextComp.nodes[0];\n\t\t} else {\n\t\t\t// Es el último componente, debería insertarse antes del anchor original\n\t\t\treturn this.anchor;\n\t\t}\n\t}\n\n\t/**\n\t * Función principal que sincroniza los componentes DOM con un array de keys\n\t */\n\tprivate synchronizeComponents(): void {\n\t\tconst existingComponents = this.getAllComponents();\n\n\t\t// Identificar qué componentes eliminar (los que no están en keys)\n\t\tconst items = this.itemsSignal.get();\n\t\tconst keys = items.map((item, index) => this.keyFn(item, index));\n\t\tconst componentsToRemove = existingComponents.filter((component) => component.key && !keys.includes(component.key));\n\t\tcomponentsToRemove.forEach((component) => this.removeComponent(component));\n\n\t\tthis.currentKeys = this.currentKeys.filter((key) => keys.includes(key));\n\t\t//console.log('Current keys:', this.currentKeys, 'Target keys:', keys);\n\n\t\tif (!this.container) {\n\t\t\tconsole.warn('Container is null in synchronizeComponents');\n\t\t\treturn;\n\t\t}\n\t\t// Procesar cada key en el orden deseado\n\t\tconst container = this.container;\n\n\t\titems.forEach((item, index) => {\n\t\t\tconst targetKey = this.keyFn(item, index);\n\t\t\tconst currentKey = this.currentKeys[index];\n\t\t\tif (targetKey === currentKey) {\n\t\t\t\t// La key no ha cambiado de posición, no hacer nada\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst existingComponent = this.components.get(targetKey);\n\n\t\t\tif (existingComponent) {\n\t\t\t\tconst prevComp = this.components.get(currentKey);\n\t\t\t\tif (!prevComp || !prevComp.nodes) {\n\t\t\t\t\tconsole.warn('Previous component or its nodes not found for key', currentKey);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\texistingComponent.reanchor(prevComp.nodes[0]);\n\t\t\t\t// Reordenar el array de keys actuales\n\t\t\t\tthis.currentKeys = this.currentKeys.filter((k) => k !== targetKey);\n\t\t\t\tthis.currentKeys.splice(index, 0, targetKey);\n\t\t\t} else {\n\t\t\t\t// El componente no existe, crearlo\n\t\t\t\tconst targetAnchor = this.getTargetAnchor(items, index);\n\t\t\t\tconst newComponent = this.createNewComponent(targetKey);\n\t\t\t\tnewComponent.mount(container, targetAnchor);\n\t\t\t\tthis.currentKeys.splice(index, 0, targetKey);\n\t\t\t}\n\t\t});\n\t}\n\n\tmount(container: Node, anchor: Node | null = null) {\n\t\t//console.log('Mounting ComponentList');\n\t\tthis.container = container;\n\t\tthis.anchor = anchor;\n\n\t\t// If mounting within another component, register for automatic unmounting\n\t\tconst parentComponent = globalContext.getCurrentComponent();\n\t\tif (parentComponent && parentComponent !== this) {\n\t\t\tparentComponent.addDisposable({\n\t\t\t\tdispose: () => this.unmount(),\n\t\t\t});\n\t\t}\n\n\t\tglobalContext.pushComponentStack(this);\n\t\tglobalContext.addReactivity(() => {\n\t\t\tthis.synchronizeComponents();\n\t\t});\n\t\tglobalContext.popComponentStack();\n\t}\n\n\taddDisposable(disposable: IDisposable) {\n\t\tthis.disposables.push(disposable);\n\t}\n\n\tunmount() {\n\t\t//console.log('Unmounting ComponentList');\n\t\tthis.clear();\n\t\tthis.container = null!;\n\t\tthis.anchor = null!;\n\t\tthis.disposables.forEach((d) => {\n\t\t\td.dispose();\n\t\t});\n\t}\n}\n\n// Definimos overloads para componentList\nexport function componentList<TItem>(\n\titemFactoryFn: ItemFactoryFn<TItem, any>,\n\tkeyFn: KeyFn<TItem>\n): (listSignal: Signal<TItem[]>, props?: any) => ComponentList<TItem>;\nexport function componentList<TItem, TProps extends Dict>(\n\titemFactoryFn: ItemFactoryFn<TItem, TProps>,\n\tkeyFn: KeyFn<TItem>\n): (listSignal: Signal<TItem[]>, props: TProps) => ComponentList<TItem, TProps>;\n\nexport function componentList<TItem, TProps extends Dict = any>(itemFactoryFn: ItemFactoryFn<TItem, TProps>, keyFn: KeyFn<TItem>) {\n\treturn (listSignal: Signal<TItem[]>, props?: TProps) => {\n\t\tconst list = new ComponentList(itemFactoryFn, keyFn, listSignal, props);\n\t\treturn list;\n\t};\n}\n","import { Component, ComponentList } from './components';\nimport { globalContext } from './context';\nimport { computed, isSignal, type Signal } from './signals';\n\nexport type ChispaReactive<T> = T | Signal<T> | (() => T);\nexport type ChispaNode = string | number | Node | null;\nexport type ChispaContent = ChispaNode | Component | (ChispaNode | Component)[] | ComponentList;\nexport type ChispaContentReactive = ChispaReactive<ChispaContent>;\nexport type ChispaClasses = Record<string, ChispaReactive<boolean>>;\nexport type ChispaCSSPropertiesStrings = {\n\t[K in keyof CSSStyleDeclaration]?: ChispaReactive<string>;\n};\n\ntype EventPropKeys<T> = Extract<keyof T, `on${string}`>;\ntype AllowSignals<T> = { [K in keyof T]: ChispaReactive<T[K]> };\n\ntype ChispaNodeBuilderBaseProps<T> = AllowSignals<Omit<T, 'style' | 'dataset' | EventPropKeys<T>>> & Pick<T, EventPropKeys<T>>;\ninterface INodeBuilderSpecialProps {\n\taddClass?: ChispaReactive<string | string[]>;\n\tclasses?: ChispaClasses;\n\tstyle?: ChispaCSSPropertiesStrings;\n\tdataset?: Record<string, ChispaReactive<string>>;\n}\ninterface INodeBuilderAdditionalProps<T, TNodes> {\n\tnodes?: TNodes;\n\tinner?: ChispaContentReactive;\n\t_ref?: (node: T) => void | { current: T | null };\n}\nexport type ChispaNodeBuilderProps<T, TNodes> = Partial<ChispaNodeBuilderBaseProps<T>> & INodeBuilderAdditionalProps<T, TNodes> & INodeBuilderSpecialProps;\nexport type ChispaNodeBuilderPropsReactive<T, TNodes> = ChispaReactive<ChispaNodeBuilderProps<T, TNodes>>;\n\nconst forbiddenProps = ['nodes', 'inner', '_ref'];\n\nexport function getValidProps<T>(props: ChispaNodeBuilderProps<T, any>) {\n\tconst finalProps: any = {};\n\n\tfor (const propName in props) {\n\t\tif (!forbiddenProps.includes(propName)) {\n\t\t\tfinalProps[propName] = props[propName as keyof typeof props];\n\t\t}\n\t}\n\n\treturn finalProps as ChispaNodeBuilderProps<T, any>;\n}\n\nconst itemsStack: any[] = [];\nfunction findItemInStack(itemName: string): any {\n\tfor (const itemsDefs of itemsStack) {\n\t\tif (itemsDefs && itemsDefs[itemName]) {\n\t\t\treturn itemsDefs[itemName];\n\t\t}\n\t}\n\treturn null;\n}\n\nexport function getItem<T>(template: T, items: any, itemName: keyof T) {\n\titemsStack.unshift(items);\n\tconst item: any = findItemInStack(itemName as string);\n\n\tif (!item) {\n\t\titemsStack.shift();\n\t\treturn null;\n\t}\n\n\tlet res;\n\tif (item.constructor && item.constructor.name === 'Object' && !(item instanceof Element)) {\n\t\tconst Comp = template[itemName] as (props: any) => Element;\n\t\tconst itemProps = item;\n\n\t\tres = Comp(itemProps);\n\t} else {\n\t\tres = item;\n\t}\n\titemsStack.shift();\n\treturn res;\n}\n\nexport function setAttributes(node: Element, attributes: Record<string, string>) {\n\tfor (const attr in attributes) {\n\t\tconst attrValue = attributes[attr];\n\t\tif (attrValue === undefined || attrValue === null) {\n\t\t\tnode.removeAttribute(attr);\n\t\t\tcontinue;\n\t\t}\n\t\tnode.setAttribute(attr, attrValue);\n\t}\n}\n\nfunction isEventProp(prop: string) {\n\treturn prop.startsWith('on');\n}\n\nfunction getPropValue(props: any, prop: string) {\n\tconst propValue = props[prop];\n\tif (typeof propValue === 'function' && !isEventProp(prop)) {\n\t\treturn computed(propValue);\n\t}\n\treturn propValue;\n}\n\nexport function setProps<T extends Element>(node: T, props: ChispaNodeBuilderPropsReactive<T, any>) {\n\tlet _props = props;\n\tif (typeof _props === 'function') {\n\t\t_props = computed(_props);\n\t}\n\tif (isSignal(_props)) {\n\t\tglobalContext.addReactivity(() => {\n\t\t\tsetProps(node, _props.get());\n\t\t});\n\t\treturn;\n\t}\n\n\tprops = getValidProps(_props);\n\n\tif (node instanceof HTMLElement) {\n\t\tsetSpecialProps(node, props);\n\t}\n\n\tfor (const prop in props) {\n\t\tconst propValue = getPropValue(props, prop);\n\t\t//console.log('setting prop', prop, propValue )\n\t\tif (isSignal(propValue)) {\n\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t(node as any)[prop] = propValue.get();\n\t\t\t});\n\t\t} else if (propValue === undefined) {\n\t\t\tcontinue;\n\t\t} else {\n\t\t\t(node as any)[prop] = propValue;\n\t\t}\n\t}\n}\n\nfunction parseAddClassProp(value: string | string[]): string[] {\n\tconst arr = typeof value === 'string' ? value.split(' ') : value;\n\treturn arr.filter((c) => c.trim() !== '');\n}\n\nfunction setSpecialProps<T extends HTMLElement>(node: T, props: INodeBuilderSpecialProps) {\n\tif (props.style !== undefined) {\n\t\tconst style = props.style;\n\t\tfor (const styleKey in style) {\n\t\t\tlet styleValue = style[styleKey]!;\n\t\t\tif (typeof styleValue === 'function') {\n\t\t\t\tstyleValue = computed(styleValue);\n\t\t\t}\n\t\t\tif (isSignal(styleValue)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tnode.style[styleKey] = styleValue.get();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnode.style[styleKey] = styleValue;\n\t\t\t}\n\t\t}\n\t\tdelete props.style;\n\t}\n\n\tif (props.addClass !== undefined) {\n\t\tlet addClass = props.addClass;\n\t\tlet prevClass: string[] | null = null;\n\n\t\tif (typeof addClass === 'function') {\n\t\t\taddClass = computed(addClass);\n\t\t}\n\n\t\tif (isSignal(addClass)) {\n\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\tconst classes = parseAddClassProp(addClass.get());\n\t\t\t\tconst classesToRemove = prevClass ? prevClass.filter((c) => !classes.includes(c)) : [];\n\t\t\t\tnode.classList.remove(...classesToRemove);\n\t\t\t\tnode.classList.add(...classes);\n\t\t\t\tprevClass = classes;\n\t\t\t});\n\t\t} else {\n\t\t\tconst toAdd = parseAddClassProp(addClass);\n\t\t\tnode.classList.add(...toAdd);\n\t\t}\n\t\tdelete props.addClass;\n\t}\n\n\tif (props.classes !== undefined) {\n\t\tconst classes = props.classes;\n\t\tfor (const className in classes) {\n\t\t\tlet apply = classes[className];\n\t\t\tif (typeof apply === 'function') {\n\t\t\t\tapply = computed(apply);\n\t\t\t}\n\t\t\tif (isSignal(apply)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tif (apply.get()) {\n\t\t\t\t\t\tnode.classList.add(className);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.classList.remove(className);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (classes[className]) {\n\t\t\t\t\tnode.classList.add(className);\n\t\t\t\t} else {\n\t\t\t\t\tnode.classList.remove(className);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdelete props.classes;\n\t}\n\n\tif (props.dataset !== undefined) {\n\t\tconst dataset = props.dataset;\n\t\tfor (const datasetKey in dataset) {\n\t\t\tlet ds = dataset[datasetKey];\n\t\t\tif (typeof ds === 'function') {\n\t\t\t\tds = computed(ds);\n\t\t\t}\n\t\t\tif (isSignal(ds)) {\n\t\t\t\tglobalContext.addReactivity(() => {\n\t\t\t\t\tnode.dataset[datasetKey] = ds.get();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnode.dataset[datasetKey] = ds;\n\t\t\t}\n\t\t}\n\t\tdelete props.dataset;\n\t}\n}\n\nexport function appendChild(node: Element | DocumentFragment, child: ChispaContentReactive) {\n\tif (child === null) return;\n\tif (typeof child === 'function') {\n\t\tprocessSignalChild(node, computed(child));\n\t\treturn;\n\t}\n\tif (isSignal(child)) {\n\t\tprocessSignalChild(node, child);\n\t\treturn;\n\t}\n\tif (child instanceof Component || child instanceof ComponentList) {\n\t\tchild.mount(node, null);\n\t\treturn;\n\t}\n\tif (Array.isArray(child)) {\n\t\tchild.forEach((ch) => {\n\t\t\tappendChild(node, ch);\n\t\t});\n\t\treturn;\n\t}\n\tnode.appendChild(child instanceof Node ? child : document.createTextNode(child.toString()));\n}\n\nfunction isStaticArrayWithComponents(arr: ChispaContent): arr is (Component | ChispaNode)[] {\n\tif (!Array.isArray(arr)) return false;\n\tfor (const item of arr) {\n\t\tif (item instanceof Component) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction processSignalChild(node: Element | DocumentFragment, child: Signal<ChispaContent>) {\n\tconst anchor = document.createTextNode('');\n\tnode.appendChild(anchor);\n\tlet prevValue: Component | ComponentList | null = null;\n\n\tglobalContext.addReactivity(() => {\n\t\t//console.log('Signal child changed', child);\n\t\tconst ch = child.get();\n\t\tif (prevValue) {\n\t\t\tprevValue.unmount();\n\t\t}\n\t\tif (ch === null) {\n\t\t\tprevValue = null;\n\t\t\treturn;\n\t\t}\n\n\t\tlet component: Component | ComponentList;\n\t\tif (isStaticArrayWithComponents(ch)) {\n\t\t\tcomponent = new Component(() => {\n\t\t\t\tconst frag = document.createDocumentFragment();\n\t\t\t\tfor (const c of ch) {\n\t\t\t\t\tappendChild(frag, c);\n\t\t\t\t}\n\t\t\t\treturn frag;\n\t\t\t});\n\t\t\tcomponent.mount(node, anchor);\n\t\t} else if (ch instanceof Component || ch instanceof ComponentList) {\n\t\t\tch.mount(node, anchor);\n\t\t\tcomponent = ch;\n\t\t} else {\n\t\t\tconst wrCmp = new Component(() => toNode(ch));\n\t\t\t//wrCmp.silent = true;\n\t\t\twrCmp.mount(node, anchor);\n\t\t\tcomponent = wrCmp;\n\t\t}\n\t\tprevValue = component;\n\t});\n}\n\nfunction toNode(n: ChispaNode | ChispaNode[]): Node | null {\n\tif (Array.isArray(n)) {\n\t\tconst frag = document.createDocumentFragment();\n\t\tconst nodes = n.map((c) => toNode(c)).filter((n) => n !== null);\n\t\tfrag.append(...nodes);\n\t\treturn frag;\n\t} else if (n instanceof Node) {\n\t\treturn n;\n\t} else if (typeof n === 'string' || typeof n === 'number') {\n\t\treturn document.createTextNode(n.toString());\n\t} else {\n\t\treturn null;\n\t\t//throw new Error('Invalid node type');\n\t}\n}\n","import { appendChild, setProps } from './builder';\nimport { componentList } from './components';\nimport { globalContext } from './context';\nimport { computed, isSignal, Signal, WritableSignal } from './signals';\n\nexport interface ControlledInputOptions<T> {\n\t/**\n\t * Optional function to transform the value before setting it to the signal.\n\t * Useful for enforcing uppercase, removing invalid characters, etc.\n\t */\n\ttransform?: (value: T) => T;\n\n\t/**\n\t * Optional function to validate the value.\n\t * If it returns false, the change is rejected and the previous value is restored.\n\t */\n\tvalidate?: (value: T) => boolean;\n}\n\nexport interface SelectOption {\n\tvalue: string;\n\tlabel: string;\n\tdisabled?: boolean;\n}\n\ntype InputValueType = string | number;\n\ninterface TypeConverter<T extends InputValueType> {\n\ttoTargetType: (val: string) => T;\n\tfromTargetType: (val: T) => string;\n}\n\nfunction getTypeConverter<T extends InputValueType>(exampleValue: T): TypeConverter<T> {\n\t// TODO: Extend for other types if needed. Also support partial parsing/formatting with invalid intermediate states (e.g. for dates or decimals)\n\tif (typeof exampleValue === 'number') {\n\t\treturn {\n\t\t\ttoTargetType: (val: string) => Number(val) as T,\n\t\t\tfromTargetType: (val: T) => val.toString(),\n\t\t} as const;\n\t} else {\n\t\treturn {\n\t\t\ttoTargetType: (val: string) => val as T,\n\t\t\tfromTargetType: (val: T) => val as string,\n\t\t} as const;\n\t}\n}\n\nexport function bindControlledInput<T extends InputValueType>(\n\telement: HTMLInputElement | HTMLTextAreaElement,\n\tvalueSignal: WritableSignal<T>,\n\toptions: ControlledInputOptions<T> = {}\n) {\n\tconst { transform, validate } = options;\n\n\t// Get type converters based on the initial value type\n\tconst { toTargetType, fromTargetType } = getTypeConverter(valueSignal.initialValue);\n\n\t// Initialize value\n\telement.value = fromTargetType(valueSignal.initialValue);\n\n\t// Handle input events\n\tconst handleInput = (e: Event) => {\n\t\tconst target = e.target as HTMLInputElement;\n\t\tlet newValue = toTargetType(target.value);\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Save cursor position\n\t\tconst selectionStart = target.selectionStart;\n\t\tconst selectionEnd = target.selectionEnd;\n\n\t\t// Apply transformation if provided\n\t\tif (transform) {\n\t\t\tnewValue = transform(newValue);\n\t\t}\n\n\t\t// Apply validation if provided\n\t\tif (validate && !validate(newValue)) {\n\t\t\t// If invalid, revert to original value\n\t\t\tnewValue = originalValue;\n\t\t}\n\n\t\t// Update signal\n\t\tif (newValue !== originalValue) {\n\t\t\tvalueSignal.set(newValue);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value (e.g. transformed or rejected)\n\t\tconst newValueStr = fromTargetType(newValue);\n\t\tif (target.value !== newValueStr) {\n\t\t\tconst lengthDiff = target.value.length - newValueStr.length;\n\t\t\ttarget.value = newValueStr;\n\n\t\t\t// Restore cursor\n\t\t\tif (selectionStart !== null && selectionEnd !== null) {\n\t\t\t\t// Restore to the saved position.\n\t\t\t\t// Adjust for length difference to keep cursor relative to the content\n\t\t\t\tconst newStart = Math.max(0, selectionStart - lengthDiff);\n\t\t\t\tconst newEnd = Math.max(0, selectionEnd - lengthDiff);\n\t\t\t\ttarget.setSelectionRange(newStart, newEnd);\n\t\t\t}\n\t\t}\n\t};\n\n\telement.addEventListener('input', handleInput);\n\n\t// Subscribe to signal changes to update the input if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValueStr = fromTargetType(valueSignal.get());\n\t\t// Only update if the value is actually different to avoid cursor jumping\n\t\tif (element.value !== newValueStr) {\n\t\t\telement.value = newValueStr;\n\t\t}\n\t});\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('input', handleInput);\n\t};\n}\n\nexport function bindControlledCheckbox(element: HTMLInputElement, valueSignal: WritableSignal<boolean>, indeterminate?: Signal<boolean>) {\n\t// Initialize checked state\n\telement.checked = valueSignal.initialValue;\n\n\t// Handle change events\n\tconst handleChange = (e: Event) => {\n\t\tconst target = e.target as HTMLInputElement;\n\t\tlet newChecked = target.checked;\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Update signal\n\t\tif (newChecked !== originalValue) {\n\t\t\tvalueSignal.set(newChecked);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value\n\t\tif (target.checked !== newChecked) {\n\t\t\ttarget.checked = newChecked;\n\t\t}\n\t};\n\n\telement.addEventListener('change', handleChange);\n\n\t// Subscribe to signal changes to update the checkbox if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValue = valueSignal.get();\n\t\tif (element.checked !== newValue) {\n\t\t\telement.checked = newValue;\n\t\t}\n\t});\n\n\t// Subscribe to indeterminate signal if provided as a Signal\n\tif (indeterminate) {\n\t\tglobalContext.addReactivity(() => {\n\t\t\telement.indeterminate = indeterminate.get();\n\t\t});\n\t}\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('change', handleChange);\n\t};\n}\n\nexport function bindControlledSelect(element: HTMLSelectElement, valueSignal: WritableSignal<string>, optionList?: Signal<SelectOption[]> | SelectOption[]) {\n\tconst Options = componentList<SelectOption>(\n\t\t(option) => {\n\t\t\tconst optElement = document.createElement('option');\n\t\t\tsetProps(optElement, {\n\t\t\t\tvalue: () => option.get().value ?? '',\n\t\t\t\ttextContent: () => option.get().label ?? '',\n\t\t\t\tdisabled: () => option.get().disabled ?? false,\n\t\t\t});\n\t\t\treturn optElement;\n\t\t},\n\t\t(o) => o.value\n\t);\n\n\t// Handle change events\n\tconst handleChange = (e: Event) => {\n\t\tconst target = e.target as HTMLSelectElement;\n\t\tlet newValue = target.value;\n\t\tconst originalValue = valueSignal.get();\n\n\t\t// Update signal\n\t\tif (newValue !== originalValue) {\n\t\t\tvalueSignal.set(newValue);\n\t\t}\n\n\t\t// Force update DOM if it doesn't match the new value (e.g. transformed or rejected)\n\t\tif (target.value !== newValue) {\n\t\t\ttarget.value = newValue;\n\t\t}\n\t};\n\n\t// Subscribe to options signal changes if provided\n\tif (optionList) {\n\t\tconst optionsSignal = isSignal(optionList) ? optionList : computed(() => optionList || []);\n\n\t\telement.innerHTML = '';\n\t\tappendChild(element, Options(optionsSignal));\n\t\tglobalContext.addReactivity(() => {\n\t\t\tconst currValue = valueSignal.get();\n\t\t\t// If the current value is not in the new options, reset it\n\t\t\tif (!optionsSignal.get().some((opt) => opt.value === currValue)) {\n\t\t\t\telement.value = '';\n\t\t\t} else if (element.value !== currValue) {\n\t\t\t\telement.value = currValue;\n\t\t\t}\n\t\t});\n\t}\n\n\t// Subscribe to signal changes to update the select if it changes externally\n\tglobalContext.addReactivity(() => {\n\t\tconst newValue = valueSignal.get();\n\t\t// Only update if the value is actually different\n\t\tif (element.value !== newValue) {\n\t\t\telement.value = newValue;\n\t\t}\n\t});\n\n\telement.addEventListener('change', handleChange);\n\n\t// Return a cleanup function\n\treturn () => {\n\t\telement.removeEventListener('change', handleChange);\n\t};\n}\n","import { signal, computed, Signal } from './signals';\nimport { component, Component, Dict } from './components';\nimport { appendChild, ChispaNodeBuilderProps, setProps } from './builder';\n\nexport interface Route {\n\tpath: string;\n\tcomponent: (props?: any) => Component<any>;\n}\n\nconst currentPath = signal(typeof window !== 'undefined' ? window.location.pathname : '/');\n\nif (typeof window !== 'undefined') {\n\twindow.addEventListener('popstate', () => {\n\t\tcurrentPath.set(window.location.pathname);\n\t});\n}\n\nexport function navigate(to: string, replace = false) {\n\tif (typeof window === 'undefined') {\n\t\tcurrentPath.set(to);\n\t\treturn;\n\t}\n\tif (replace) {\n\t\twindow.history.replaceState({}, '', to);\n\t} else {\n\t\twindow.history.pushState({}, '', to);\n\t}\n\tcurrentPath.set(to);\n}\n\nexport function pathMatches(path: string): Signal<boolean> {\n\treturn computed(() => {\n\t\tconst current = currentPath.get();\n\t\treturn match(path, current) !== null;\n\t});\n}\n\nfunction match(routePath: string, currentPath: string): Dict | null {\n\tif (routePath === '*') return {};\n\tconst routeParts = routePath.split('/').filter(Boolean);\n\tconst currentParts = currentPath.split('/').filter(Boolean);\n\tif (routeParts.length !== currentParts.length) return null;\n\tconst params: Dict = {};\n\tfor (let i = 0; i < routeParts.length; i++) {\n\t\tif (routeParts[i].startsWith(':')) {\n\t\t\tparams[routeParts[i].substring(1)] = currentParts[i];\n\t\t} else if (routeParts[i] !== currentParts[i]) {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn params;\n}\n\nexport const Router = component<{ routes: Route[] }>((props) => {\n\tconst container = document.createElement('div');\n\tcontainer.style.display = 'contents';\n\tconst activeRoute = computed(() => {\n\t\tconst path = currentPath.get();\n\t\tfor (const route of props.routes) {\n\t\t\tconst params = match(route.path, path);\n\t\t\tif (params) {\n\t\t\t\treturn route.component(params);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t});\n\tappendChild(container, activeRoute);\n\treturn container;\n});\n\nexport interface LinkProps extends ChispaNodeBuilderProps<HTMLAnchorElement, {}> {\n\tto: string;\n}\n\nexport const Link = component<LinkProps>((props) => {\n\tconst { to, inner, ...rest } = props;\n\tconst a = document.createElement('a');\n\ta.href = to;\n\n\ta.addEventListener('click', (e) => {\n\t\tif (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.defaultPrevented || e.button !== 0) {\n\t\t\treturn;\n\t\t}\n\t\te.preventDefault();\n\t\tnavigate(to);\n\t});\n\n\tif (inner) {\n\t\tappendChild(a, inner);\n\t}\n\n\tsetProps(a, rest);\n\n\treturn a;\n});\n","import { globalContext } from './context';\n\ntype Constructor<T> = new (...args: any[]) => T;\n\n/**\n * A typed token that can be used to inject values or interfaces that are not\n * tied to a concrete class constructor.\n *\n * @example\n * const API_URL = new InjectionToken<string>('API_URL');\n * provide(API_URL, () => 'https://api.example.com');\n * const url = inject(API_URL); // string\n */\nexport class InjectionToken<T> {\n\tconstructor(public readonly description: string) {}\n}\n\ntype Token<T> = Constructor<T> | InjectionToken<T>;\n\nclass ServiceContainer {\n\tprivate services = new Map<Token<any>, any>();\n\tprivate factories = new Map<Token<any>, () => any>();\n\n\tpublic provide<T>(token: Token<T>, factory: () => T): void {\n\t\tif (this.services.has(token)) {\n\t\t\tconst name = token instanceof InjectionToken ? `\"${token.description}\"` : (token as Constructor<T>).name;\n\t\t\tthrow new Error(`Cannot call provide() for ${name} after it has already been injected.`);\n\t\t}\n\t\tthis.factories.set(token, factory);\n\t}\n\n\tpublic get<T>(token: Token<T>): T {\n\t\tif (this.services.has(token)) {\n\t\t\treturn this.services.get(token) as T;\n\t\t}\n\n\t\tlet service: T;\n\n\t\tglobalContext.pushExecutionStack('injectSingleton');\n\t\ttry {\n\t\t\tservice = this.createInstance(token);\n\t\t} finally {\n\t\t\tglobalContext.popExecutionStack();\n\t\t}\n\n\t\tthis.services.set(token, service);\n\t\treturn service;\n\t}\n\n\t/**\n\t * Creates a fresh, non-cached instance of the token's service.\n\t * Runs inside the current component context so that any effects created\n\t * in the constructor are bound to (and disposed with) that component.\n\t */\n\tpublic getLocal<T>(token: Token<T>): T {\n\t\t// TODO: this is a bit hacky, we should find a cleaner way to create local instances without affecting the global singleton cache or execution stack\n\t\treturn this.createInstance(token);\n\t}\n\n\tprivate createInstance<T>(token: Token<T>): T {\n\t\tconst factory = this.factories.get(token);\n\t\tif (factory) {\n\t\t\treturn factory();\n\t\t} else if (token instanceof InjectionToken) {\n\t\t\tthrow new Error(`No provider registered for InjectionToken \"${token.description}\"`);\n\t\t} else {\n\t\t\treturn new (token as Constructor<T>)();\n\t\t}\n\t}\n\n\tpublic reset(): void {\n\t\tthis.services.clear();\n\t\tthis.factories.clear();\n\t}\n}\n\nconst services = new ServiceContainer();\n\n/**\n * Registers a factory function for the given token. The factory is called\n * at most once (the result is cached as a singleton). Must be called before\n * the first `inject(token)` call for that token.\n */\nexport function provide<T>(token: Token<T>, factory: () => T): void {\n\tservices.provide(token, factory);\n}\n\nexport interface InjectOptions {\n\t/**\n\t * When `true`, a new instance is created every time and is NOT added to the\n\t * singleton cache. Any reactive effects created in the service constructor\n\t * will be registered to the currently mounting component and disposed when\n\t * it unmounts.\n\t */\n\tlocal?: boolean;\n}\n\n/**\n * Injects (or lazily creates) the singleton service associated with `token`.\n * Any reactive effects declared inside the service constructor will NOT be\n * disposed when the component that first triggers the injection is unmounted.\n *\n * Pass `{ local: true }` to get a fresh, component-scoped instance instead:\n * effects will be disposed together with the component.\n */\nexport function inject<T>(token: Token<T>, options?: InjectOptions): T {\n\tif (options?.local) {\n\t\treturn services.getLocal(token);\n\t}\n\treturn services.get(token);\n}\n\n/**\n * Resets the entire service container. Useful for test isolation.\n */\nexport function resetServices(): void {\n\tservices.reset();\n}\n"],"mappings":"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","names":["component","signal","component","index","component","n","currentPath"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chispa",
3
- "version": "0.9.2",
3
+ "version": "0.10.1",
4
4
  "description": "A fully declarative UI reactive engine for building web applications.",
5
5
  "author": "José Carlos HR <joecarlhr@gmail.com>",
6
6
  "license": "MIT",
@@ -28,15 +28,15 @@
28
28
  "url": "git+https://github.com/joecarl/chispa.git"
29
29
  },
30
30
  "dependencies": {
31
- "jsdom": "^27.4.0",
31
+ "jsdom": "^29.0.2",
32
32
  "prettier": "^3.7.4"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/jsdom": "^27.0.0",
35
+ "@types/jsdom": "^28.0.1",
36
36
  "tsup": "^8.5.1",
37
- "typescript": "^5.9.3",
38
- "vite": "^7.3.0",
39
- "vitest": "^4.0.16"
37
+ "typescript": "^6.0.2",
38
+ "vite": "^8.0.8",
39
+ "vitest": "^4.1.4"
40
40
  },
41
41
  "bugs": {
42
42
  "url": "https://github.com/joecarl/chispa/issues"