import { expandTemplateStringFromStore, storeSymbol, type Store } from './store.js'; const toHtmlElement = (input: unknown): HTMLElement | Text => { if (input instanceof HTMLElement || input instanceof Text) { return input; } const toHtmlProperty = Object.getOwnPropertyDescriptor(input, 'toHtmlElement'); if (toHtmlProperty && typeof toHtmlProperty.value === 'function') { const elm = toHtmlProperty.value(); return elm; } if (typeof input === 'object') { return document.createTextNode(JSON.stringify(input)); } if (input === undefined) { return document.createTextNode(''); } return document.createTextNode(String(input)); }; const html = (tag: string | (() => HTMLElement)) => { const render = (options: Record) => (strings: TemplateStringsArray, ...params: unknown[]) => { const fn = (elm: HTMLElement) => { for (const [event, listener] of Object.entries(options)) { if (typeof listener === 'function') { elm.addEventListener(event, () => listener()); } } if ('style' in options) { for (const [name, value] of Object.entries(options.style as any)) { (elm.style as any)[name] = value; } } const elements = expandTemplateStringFromStore(strings, ...params); const htmlElements = elements.map(toHtmlElement).filter(Boolean); elm.innerHTML = ''; for (const element of htmlElements) { elm.appendChild(element); } }; return Object.assign(fn, { toHtmlElement: () => { const root = typeof tag === 'function' ? tag() : document.createElement(tag); fn(root); return root; }, }); }; return Object.assign((strings: TemplateStringsArray, ...params: unknown[]) => render({})(strings, ...params), { $: (props: Record) => (strings: TemplateStringsArray, ...params: unknown[]) => render(props)(strings, ...params), }); }; type Html = ReturnType>; const div = html('div'); const h1 = html('h1'); const p = html('p'); const button = html('button'); const scope = (...stores: Store[]) => html(() => { const elm = document.createElement('div'); elm.style.display = 'content'; const storeMap = new Map(); (elm as any)[storeSymbol] = storeMap; for (const store of stores) { storeMap.set(store, store.create()); } return elm; }); export type { Html }; export { html, div, h1, p, button, scope };