UNPKG

rynex

Version:

A minimalist TypeScript framework for building reactive web applications with no virtual DOM

177 lines 4.45 kB
/** * Rynex Basic Elements * Basic HTML elements and components */ import { createElement } from '../dom.js'; import { effect } from '../state.js'; /** * Div element (generic container) */ export function div(props, ...children) { return createElement('div', props, ...children); } /** * Span element (inline container) */ export function span(props, ...children) { return createElement('span', props, ...children); } /** * Text element with reactive getter support * Usage: text('static') or text(() => `Count: ${state.count}`) or text({ class: 'foo' }, 'static') or text({ class: 'foo' }, () => `Count: ${state.count}`) */ export function text(props, content) { // Case 1: text('static string') if (typeof props === 'string') { return createElement('span', {}, props); } // Case 2: text(() => reactive) if (typeof props === 'function') { const el = createElement('span', {}); effect(() => { el.textContent = props(); }); return el; } // Case 3: text({ props }, 'static') or text({ props }, () => reactive) const el = createElement('span', props); if (typeof content === 'function') { // Reactive content effect(() => { el.textContent = content(); }); } else if (content) { // Static content el.textContent = content; } return el; } /** * Button element with reactive text support * Usage: button({ onClick: ... }, 'Click') or button({ onClick: ... }, () => state.show ? 'Hide' : 'Show') */ export function button(props, content) { const el = createElement('button', props); if (typeof content === 'function') { // Reactive text content effect(() => { el.textContent = content(); }); } else if (typeof content === 'string') { // Static text content el.textContent = content; } else if (content) { // Children elements const children = Array.isArray(content) ? content : [content]; children.forEach(child => { if (typeof child === 'string') { el.appendChild(document.createTextNode(child)); } else if (child instanceof HTMLElement) { el.appendChild(child); } }); } return el; } /** * Input element */ export function input(props) { return createElement('input', props); } /** * Image element */ export function image(props) { const imgProps = { ...props }; if (props.lazy) { imgProps.loading = 'lazy'; delete imgProps.lazy; } return createElement('img', imgProps); } /** * Link/anchor element */ export function link(props, ...children) { return createElement('a', props, ...children); } /** * Label element */ export function label(props, ...content) { return createElement('label', props, ...content); } /** * Paragraph element */ export function p(props, ...content) { return createElement('p', props, ...content); } /** * List element with optimized rendering */ export function list(props) { const { items, renderItem, keyExtractor, ...restProps } = props; const children = items.map((item, index) => { const child = renderItem(item, index); if (keyExtractor) { child.dataset.key = String(keyExtractor(item, index)); } return child; }); return createElement('div', restProps, ...children); } /** * Unordered list */ export function ul(props, ...children) { return createElement('ul', props, ...children); } /** * Ordered list */ export function ol(props, ...children) { return createElement('ol', props, ...children); } /** * List item */ export function li(props, ...content) { return createElement('li', props, ...content); } /** * Horizontal rule */ export function hr(props = {}) { return createElement('hr', props); } /** * Line break */ export function br(props = {}) { return createElement('br', props); } /** * Description list */ export function dl(props, ...children) { return createElement('dl', props, ...children); } /** * Description term */ export function dt(props, ...content) { return createElement('dt', props, ...content); } /** * Description definition */ export function dd(props, ...content) { return createElement('dd', props, ...content); } //# sourceMappingURL=basic_elements.js.map