UNPKG

ziko-wrapper

Version:

integrate zikojs elements within other ui framework like vue react solidjs svelte astro ...

239 lines (210 loc) 6.86 kB
import { createSignal, onCleanup, onMount, createEffect } from 'solid-js'; import { render } from 'solid-js/web'; // Helpers const isDOMElement = (obj) => obj instanceof HTMLElement; const isSolidComponent = (child) => typeof child === 'function' && !isDOMElement(child); // Transform Solid elements to DOM, or return DOM elements as-is const domify = (element, ...args) => { // DOM element → return directly if (isDOMElement(element)) return element; // Solid component (function) if (isSolidComponent(element)) { const [props, ...children] = args; const container = document.createElement('div'); container.style.display = 'contents'; // Render the Solid component into the container const dispose = render(() => element(props, ...children), container); container._solidDispose = dispose; return container; } // ZikoJS-like object (with .element) if (element && typeof element === 'object' && isDOMElement(element.element)) { return element.element; } return null; }; // Recursively process children (DOM, Solid, or ZikoJS) const processChild = (child) => { if (typeof child === 'function') { const result = child(); return processChild(result); } if (Array.isArray(child)) { const frag = document.createDocumentFragment(); child.forEach((c) => { const el = processChild(c); if (el) frag.appendChild(el); }); return frag; } return domify(child); }; // Solid version of DOMWrapper export function DOMWrapper(props) { let container; let disposes = []; const cleanup = () => { disposes.forEach((d) => d?.()); disposes = []; if (container) container.innerHTML = ''; }; onCleanup(cleanup); createEffect(() => { cleanup(); if (!props.children || !container) return; const childArray = Array.isArray(props.children) ? props.children : [props.children]; childArray.forEach((child) => { const el = processChild(child); if (el instanceof HTMLElement || el instanceof DocumentFragment) { container.appendChild(el); if (el._solidDispose) disposes.push(el._solidDispose); } }); }); return <div ref={container} style="display: contents;" />; } // ---------- Pure DOM Element Creators ---------- const createButton = (text, onClick) => { const btn = document.createElement('button'); btn.textContent = text; btn.style.cssText = 'padding: 8px 16px; margin: 5px; background: #4CAF50; color: white; border: none; cursor: pointer; border-radius: 4px;'; if (onClick) btn.onclick = onClick; return btn; }; const createParagraph = (text) => { const p = document.createElement('p'); p.textContent = text; p.style.margin = '10px 0'; return p; }; const createCard = (title, ...children) => { const card = document.createElement('div'); card.style.cssText = 'padding: 15px; border: 2px solid #4CAF50; margin: 10px; border-radius: 8px; background: #f0f0f0;'; const h4 = document.createElement('h4'); h4.textContent = title; h4.style.marginTop = '0'; card.appendChild(h4); children.forEach((child) => { const el = domify(child); if (el) card.appendChild(el); }); return card; }; // ---------- Solid Components ---------- function SolidCard(props) { return ( <div style={{ padding: '15px', border: `2px solid ${props.color || '#2196F3'}`, margin: '10px', 'border-radius': '8px', background: props.color === '#2196F3' ? '#e3f2fd' : '#fff3e0', }} > <h4 style={{ 'margin-top': 0 }}>{props.title}</h4> {props.children} </div> ); } function SolidButton(props) { return ( <button onClick={props.onClick} style={{ padding: '8px 16px', margin: '5px', background: '#2196F3', color: 'white', border: 'none', cursor: 'pointer', 'border-radius': '4px', }} > {props.children} </button> ); } // ---------- Demo ---------- export default function Demo() { return ( <div style="padding: 20px; font-family: sans-serif;"> <h2>DOMWrapper - SolidJS Interleaving Demo</h2> <p style="color: #666"> Mix DOM elements, Solid components, and ZikoJS elements dynamically. </p> <div style="margin-top: 20px;"> <h3>Example 1: Simple DOM Elements</h3> <DOMWrapper> {[ createParagraph('This is a pure DOM paragraph'), createButton('DOM Button', () => alert('DOM button clicked!')), domify( SolidButton, { onClick: () => alert('domified!') }, 'Domified Button' ), ]} </DOMWrapper> </div> <div style="margin-top: 20px;"> <h3>Example 2: DOM → Solid</h3> <DOMWrapper> {createCard( 'DOM Card', createParagraph('DOM content here'), <SolidCard title="Nested Solid Card" color="#FF9800"> <p>This is a Solid component inside a DOM card</p> <SolidButton onClick={() => alert('Solid button clicked!')}> Click Me </SolidButton> </SolidCard> )} </DOMWrapper> </div> <div style="margin-top: 20px;"> <h3>Example 3: Solid → DOM</h3> <DOMWrapper> <SolidCard title="Solid Card"> <p>Solid component wrapping DOM elements</p> <DOMWrapper> {[ createParagraph('DOM inside Solid!'), createButton('DOM Button Inside Solid', () => alert('Works!')), ]} </DOMWrapper> </SolidCard> </DOMWrapper> </div> <div style="margin-top: 20px;"> <h3>Example 4: Deep Nesting</h3> <DOMWrapper> {createCard( 'Level 1: DOM', createParagraph('DOM content'), <SolidCard title="Level 2: Solid"> <p>Solid component</p> <DOMWrapper> {createCard( 'Level 3: DOM', createParagraph('Back to DOM!'), <SolidCard title="Level 4: Solid" color="#FF9800"> <p>🎉 Full interleaving works!</p> <SolidButton onClick={() => alert('Deep nested button!')}> Click Me </SolidButton> </SolidCard> )} </DOMWrapper> </SolidCard> )} </DOMWrapper> </div> </div> ); }