Created
July 14, 2025 14:59
-
-
Save nsaunders/bb58df1282333ce0bf704bcc8b69745d to your computer and use it in GitHub Desktop.
funel prototype
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { ComponentProps, ElementType, ReactNode } from "react"; | |
| import { createElement } from "react"; | |
| export const el = <E extends ElementType>(elementType: E) => { | |
| const ctor = < | |
| P extends | |
| | Record<never, never> | |
| | (unknown extends ComponentProps<E> | |
| ? ReactNode | |
| : ComponentProps<E> | ReactNode) | |
| >( | |
| propsOrChild?: P, | |
| ...children: P extends { children: unknown } ? never[] : ReactNode[] | |
| ) => { | |
| return createElement( | |
| elementType, | |
| ...(propsOrChild && | |
| typeof propsOrChild === "object" && | |
| !("$$typeof" in propsOrChild) | |
| ? [propsOrChild] | |
| : [null, propsOrChild]), | |
| ...children | |
| ); | |
| }; | |
| return new Proxy(ctor, { | |
| get(_target, property) { | |
| return elementType[property as keyof typeof elementType]; | |
| }, | |
| set(_target, property, value) { | |
| elementType[property as keyof typeof elementType] = value; | |
| return true; | |
| }, | |
| }) as E extends string | |
| ? typeof ctor | |
| : typeof ctor & { | |
| displayName?: string | undefined; | |
| }; | |
| }; | |
| export const { | |
| a, | |
| abbr, | |
| address, | |
| area, | |
| article, | |
| aside, | |
| audio, | |
| b, | |
| base, | |
| bdi, | |
| bdo, | |
| blockquote, | |
| body, | |
| br, | |
| button, | |
| canvas, | |
| caption, | |
| cite, | |
| code, | |
| col, | |
| colgroup, | |
| data, | |
| datalist, | |
| dd, | |
| del, | |
| details, | |
| dfn, | |
| dialog, | |
| div, | |
| dl, | |
| dt, | |
| em, | |
| embed, | |
| fieldset, | |
| figcaption, | |
| figure, | |
| footer, | |
| form, | |
| h1, | |
| h2, | |
| h3, | |
| h4, | |
| h5, | |
| h6, | |
| head, | |
| header, | |
| hgroup, | |
| hr, | |
| html, | |
| i, | |
| iframe, | |
| img, | |
| input, | |
| ins, | |
| kbd, | |
| label, | |
| legend, | |
| li, | |
| link, | |
| main, | |
| map, | |
| mark, | |
| menu, | |
| meta, | |
| meter, | |
| nav, | |
| noscript, | |
| object, | |
| ol, | |
| optgroup, | |
| option, | |
| output, | |
| p, | |
| picture, | |
| pre, | |
| progress, | |
| q, | |
| rp, | |
| rt, | |
| ruby, | |
| s, | |
| samp, | |
| script, | |
| search, | |
| section, | |
| select, | |
| slot, | |
| small, | |
| source, | |
| span, | |
| strong, | |
| style, | |
| sub, | |
| summary, | |
| sup, | |
| table, | |
| tbody, | |
| td, | |
| template, | |
| textarea, | |
| tfoot, | |
| th, | |
| thead, | |
| time, | |
| title, | |
| tr, | |
| track, | |
| u, | |
| ul, | |
| var: var_, | |
| video, | |
| wbr, | |
| ...missingTags | |
| } = new Proxy( | |
| {} as { | |
| [Tag in keyof HTMLElementTagNameMap]: ReturnType<typeof el<Tag>>; | |
| }, | |
| { | |
| get: (_target, tag) => { | |
| if (typeof tag !== "string") { | |
| throw new Error("Tag must be a string"); | |
| } | |
| return el(tag as keyof HTMLElementTagNameMap); | |
| }, | |
| } | |
| ); | |
| ({}) satisfies { [P in keyof typeof missingTags]: never }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment