Skip to content

Commit d1f12fc

Browse files
authored
Update extra.ts
1 parent 5362285 commit d1f12fc

1 file changed

Lines changed: 138 additions & 0 deletions

File tree

src/api/extra.ts

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,3 +451,141 @@ export function render(
451451
};
452452
})();
453453
}
454+
455+
456+
457+
// /**
458+
// * A type representing the possible children for the tag function.
459+
// * Can be a DOM node, a string, a number, null/undefined, or a nested array of other children.
460+
// */
461+
// type TagChild = Node | string | number | null | undefined | TagChild[];
462+
463+
// /**
464+
// * Creates an HTML element programmatically with a flexible and concise syntax.
465+
// *
466+
// * This hyperscript-style function is a powerful utility for building DOM structures
467+
// * in JavaScript without resorting to messy string concatenation. It's an ideal
468+
// * companion for `watch-selector`'s rendering primitives like `For*` and `Show*`.
469+
// *
470+
// * @param name The tag name of the element to create (e.g., 'div', 'button', 'span').
471+
// * @param args A rest parameter that can include:
472+
// * - **An attributes object**: A plain object where keys are attribute names.
473+
// * - **Children**: Strings, numbers, DOM nodes, or other `tag()` calls.
474+
// * - **Arrays of children**: Nested arrays are automatically flattened.
475+
// * @returns The created HTMLElement.
476+
// *
477+
// * @example
478+
// * // Basic usage
479+
// * const myDiv = tag('div', { class: 'container' }, 'Hello World');
480+
// * // <div class="container">Hello World</div>
481+
// *
482+
// * @example
483+
// * // Nested structure with event handlers and styles
484+
// * const app = tag('main', { id: 'app' },
485+
// * tag('h1', { style: { color: 'navy' } }, 'My App'),
486+
// * tag('p', 'This is a list of items:'),
487+
// * tag('ul',
488+
// * ['Item 1', 'Item 2', 'Item 3'].map(item => tag('li', item))
489+
// * ),
490+
// * tag('button',
491+
// * {
492+
// * id: 'action-btn',
493+
// * disabled: false,
494+
// * // Event handlers are automatically attached
495+
// * onclick: (e) => alert('Button clicked!'),
496+
// * },
497+
// * 'Click Me'
498+
// * )
499+
// * );
500+
// * document.body.appendChild(app);
501+
// *
502+
// * @example
503+
// * // Integration with watch-selector's `For*` primitive
504+
// * watch('#user-list', function*() {
505+
// * const users = createState('users', [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]);
506+
// *
507+
// * yield* For(
508+
// * users.get(),
509+
// * user => user.id,
510+
// * user => tag('div', { class: 'user-card' },
511+
// * tag('p', `ID: ${user.id}`),
512+
// * tag('strong', `Name: ${user.name}`)
513+
// * )
514+
// * );
515+
// * });
516+
// */
517+
// export function tag(
518+
// name: string,
519+
// ...args: (Record<string, any> | TagChild)[]
520+
// ): HTMLElement {
521+
// const element = document.createElement(name);
522+
523+
// /**
524+
// * Helper function to recursively append children to the element.
525+
// * It handles strings, numbers, Nodes, and nested arrays.
526+
// */
527+
// function appendChildren(children: TagChild[]) {
528+
// for (const child of children) {
529+
// if (child === null || child === undefined) {
530+
// continue; // Ignore null/undefined children
531+
// }
532+
533+
// if (Array.isArray(child)) {
534+
// // Recursively handle nested arrays
535+
// appendChildren(child);
536+
// } else if (child instanceof Node) {
537+
// // Append DOM nodes directly
538+
// element.appendChild(child);
539+
// } else {
540+
// // Convert strings, numbers, etc., to text nodes
541+
// element.appendChild(document.createTextNode(String(child)));
542+
// }
543+
// }
544+
// }
545+
546+
// // Iterate through the arguments to process attributes and children
547+
// for (const arg of args) {
548+
// if (arg === null || arg === undefined) {
549+
// continue;
550+
// }
551+
552+
// if (Array.isArray(arg)) {
553+
// // Argument is an array of children
554+
// appendChildren(arg);
555+
// } else if (arg instanceof Node) {
556+
// // Argument is a single child node
557+
// element.appendChild(arg);
558+
// } else if (typeof arg === 'object' && arg.constructor === Object) {
559+
// // Argument is a plain object, treat as attributes
560+
// for (const key in arg) {
561+
// const value = arg[key];
562+
// if (value === null || value === undefined) continue;
563+
564+
// // Handle special cases for attributes
565+
// if (key.startsWith('on') && typeof value === 'function') {
566+
// // Event listeners: onclick -> click
567+
// const eventName = key.substring(2).toLowerCase();
568+
// element.addEventListener(eventName, value);
569+
// } else if (key === 'style' && typeof value === 'object') {
570+
// // Style object: { color: 'red', fontSize: '16px' }
571+
// Object.assign(element.style, value);
572+
// } else if (key === 'class' || key === 'className') {
573+
// // Class attribute
574+
// element.className = String(value);
575+
// } else if (typeof value === 'boolean') {
576+
// // Boolean attributes: disabled, checked, etc.
577+
// // The `toggleAttribute` API correctly handles true/false.
578+
// element.toggleAttribute(key, value);
579+
// } else {
580+
// // All other attributes
581+
// element.setAttribute(key, String(value));
582+
// }
583+
// }
584+
// } else {
585+
// // Argument is a primitive (string, number), treat as a child text node
586+
// element.appendChild(document.createTextNode(String(arg)));
587+
// }
588+
// }
589+
590+
// return element;
591+
// }

0 commit comments

Comments
 (0)