@arcmantle/lit-jsx 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +768 -0
  2. package/dist/compiler/attribute-processor.d.ts +128 -0
  3. package/dist/compiler/attribute-processor.d.ts.map +1 -0
  4. package/dist/compiler/attribute-processor.js +380 -0
  5. package/dist/compiler/attribute-processor.js.map +1 -0
  6. package/dist/compiler/babel-preset.d.ts +6 -0
  7. package/dist/compiler/babel-preset.d.ts.map +1 -0
  8. package/dist/compiler/babel-preset.js +27 -0
  9. package/dist/compiler/babel-preset.js.map +1 -0
  10. package/dist/compiler/builder.d.ts +22 -0
  11. package/dist/compiler/builder.d.ts.map +1 -0
  12. package/dist/compiler/builder.js +62 -0
  13. package/dist/compiler/builder.js.map +1 -0
  14. package/dist/compiler/compiler-utils.d.ts +81 -0
  15. package/dist/compiler/compiler-utils.d.ts.map +1 -0
  16. package/dist/compiler/compiler-utils.js +410 -0
  17. package/dist/compiler/compiler-utils.js.map +1 -0
  18. package/dist/compiler/config.d.ts +77 -0
  19. package/dist/compiler/config.d.ts.map +1 -0
  20. package/dist/compiler/config.js +78 -0
  21. package/dist/compiler/config.js.map +1 -0
  22. package/dist/compiler/postprocess.d.ts +5 -0
  23. package/dist/compiler/postprocess.d.ts.map +1 -0
  24. package/dist/compiler/postprocess.js +3 -0
  25. package/dist/compiler/postprocess.js.map +1 -0
  26. package/dist/compiler/preprocess.d.ts +5 -0
  27. package/dist/compiler/preprocess.d.ts.map +1 -0
  28. package/dist/compiler/preprocess.js +28 -0
  29. package/dist/compiler/preprocess.js.map +1 -0
  30. package/dist/compiler/transform-jsx.d.ts +5 -0
  31. package/dist/compiler/transform-jsx.d.ts.map +1 -0
  32. package/dist/compiler/transform-jsx.js +25 -0
  33. package/dist/compiler/transform-jsx.js.map +1 -0
  34. package/dist/compiler/transpiler.d.ts +48 -0
  35. package/dist/compiler/transpiler.d.ts.map +1 -0
  36. package/dist/compiler/transpiler.js +463 -0
  37. package/dist/compiler/transpiler.js.map +1 -0
  38. package/dist/compiler/vite-plugin.d.ts +38 -0
  39. package/dist/compiler/vite-plugin.d.ts.map +1 -0
  40. package/dist/compiler/vite-plugin.js +96 -0
  41. package/dist/compiler/vite-plugin.js.map +1 -0
  42. package/dist/runtime/choose-component.d.ts +39 -0
  43. package/dist/runtime/choose-component.d.ts.map +1 -0
  44. package/dist/runtime/choose-component.js +40 -0
  45. package/dist/runtime/choose-component.js.map +1 -0
  46. package/dist/runtime/compiler-ctors.d.ts +21 -0
  47. package/dist/runtime/compiler-ctors.d.ts.map +1 -0
  48. package/dist/runtime/compiler-ctors.js +21 -0
  49. package/dist/runtime/compiler-ctors.js.map +1 -0
  50. package/dist/runtime/for-component.d.ts +25 -0
  51. package/dist/runtime/for-component.d.ts.map +1 -0
  52. package/dist/runtime/for-component.js +35 -0
  53. package/dist/runtime/for-component.js.map +1 -0
  54. package/dist/runtime/literal-map.d.ts +22 -0
  55. package/dist/runtime/literal-map.d.ts.map +1 -0
  56. package/dist/runtime/literal-map.js +29 -0
  57. package/dist/runtime/literal-map.js.map +1 -0
  58. package/dist/runtime/rest-directive.d.ts +28 -0
  59. package/dist/runtime/rest-directive.d.ts.map +1 -0
  60. package/dist/runtime/rest-directive.js +49 -0
  61. package/dist/runtime/rest-directive.js.map +1 -0
  62. package/dist/runtime/show-component.d.ts +33 -0
  63. package/dist/runtime/show-component.d.ts.map +1 -0
  64. package/dist/runtime/show-component.js +30 -0
  65. package/dist/runtime/show-component.js.map +1 -0
  66. package/dist/runtime/tagged-template.d.ts +12 -0
  67. package/dist/runtime/tagged-template.d.ts.map +1 -0
  68. package/dist/runtime/tagged-template.js +12 -0
  69. package/dist/runtime/tagged-template.js.map +1 -0
  70. package/dist/runtime/type-helpers.d.ts +80 -0
  71. package/dist/runtime/type-helpers.d.ts.map +1 -0
  72. package/dist/runtime/type-helpers.js +85 -0
  73. package/dist/runtime/type-helpers.js.map +1 -0
  74. package/dist/shared/jsx-types.d.ts +2139 -0
  75. package/dist/shared/jsx-types.d.ts.map +1 -0
  76. package/dist/shared/jsx-types.js +2 -0
  77. package/dist/shared/jsx-types.js.map +1 -0
  78. package/dist/shared/jsx-utils.d.ts +30 -0
  79. package/dist/shared/jsx-utils.d.ts.map +1 -0
  80. package/dist/shared/jsx-utils.js +58 -0
  81. package/dist/shared/jsx-utils.js.map +1 -0
  82. package/dist/shared/mathml-tags.d.ts +12 -0
  83. package/dist/shared/mathml-tags.d.ts.map +1 -0
  84. package/dist/shared/mathml-tags.js +215 -0
  85. package/dist/shared/mathml-tags.js.map +1 -0
  86. package/dist/shared/svg-tags.d.ts +13 -0
  87. package/dist/shared/svg-tags.d.ts.map +1 -0
  88. package/dist/shared/svg-tags.js +95 -0
  89. package/dist/shared/svg-tags.js.map +1 -0
  90. package/dist/utils.d.ts +30 -0
  91. package/dist/utils.d.ts.map +1 -0
  92. package/dist/utils.js +30 -0
  93. package/dist/utils.js.map +1 -0
  94. package/package.json +52 -0
  95. package/src/compiler/attribute-processor.ts +579 -0
  96. package/src/compiler/babel-preset.ts +34 -0
  97. package/src/compiler/builder.ts +86 -0
  98. package/src/compiler/compiler-utils.ts +789 -0
  99. package/src/compiler/config.ts +77 -0
  100. package/src/compiler/postprocess.ts +7 -0
  101. package/src/compiler/preprocess.ts +40 -0
  102. package/src/compiler/transform-jsx.ts +36 -0
  103. package/src/compiler/transpiler.ts +644 -0
  104. package/src/compiler/vite-plugin.ts +114 -0
  105. package/src/external.d.ts +9 -0
  106. package/src/runtime/choose-component.ts +53 -0
  107. package/src/runtime/compiler-ctors.ts +28 -0
  108. package/src/runtime/for-component.ts +54 -0
  109. package/src/runtime/literal-map.ts +37 -0
  110. package/src/runtime/rest-directive.ts +66 -0
  111. package/src/runtime/show-component.ts +48 -0
  112. package/src/runtime/tagged-template.ts +11 -0
  113. package/src/runtime/type-helpers.ts +91 -0
  114. package/src/shared/jsx-types.ts +2556 -0
  115. package/src/shared/jsx-utils.ts +85 -0
  116. package/src/shared/mathml-tags.ts +235 -0
  117. package/src/shared/svg-tags.ts +103 -0
  118. package/src/tsconfig.json +4 -0
  119. package/src/utils.ts +30 -0
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @fileoverview Vite plugin for lit-jsx preserve-JSX compilation mode.
3
+ *
4
+ * This plugin provides compile-time JSX transformation using Babel to convert
5
+ * JSX syntax directly into optimized Lit templates. Unlike the React compatibility
6
+ * mode, this preserves JSX through the entire build pipeline for maximum performance.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // vite.config.ts
11
+ * import { litJsx } from "@arcmantle/lit-jsx/vite-jsx-preserve";
12
+ *
13
+ * export default {
14
+ * plugins: [litJsx({
15
+ * babel: {
16
+ * // Custom Babel options
17
+ * }
18
+ * })]
19
+ * };
20
+ * ```
21
+ */
22
+
23
+ import * as babel from '@babel/core';
24
+ import { mergeAndConcat } from 'merge-anything';
25
+ import type { PluginOption } from 'vite';
26
+
27
+ import { litJsxBabelPreset } from './babel-preset.js';
28
+
29
+
30
+ type BabelPlugins = NonNullable<NonNullable<babel.TransformOptions['parserOpts']>['plugins']>;
31
+
32
+
33
+ /**
34
+ * Vite plugin for jsx-lit with preserve-JSX compilation.
35
+ *
36
+ * This plugin uses Babel to transform JSX directly into Lit templates at build time,
37
+ * providing optimal performance by eliminating runtime JSX processing entirely.
38
+ *
39
+ * @param options - Configuration options for the plugin
40
+ * @param options.babel - Babel transform options or function returning options
41
+ * @returns Vite plugin configuration
42
+ */
43
+ export const litJsx = (options: {
44
+ /** Options for the Babel transform */
45
+ babel?:
46
+ | babel.TransformOptions
47
+ | ((code: string, id: string) => babel.TransformOptions | Promise<babel.TransformOptions>);
48
+ } = {}): PluginOption => {
49
+ let projectRoot: string;
50
+
51
+ return {
52
+ name: 'lit-jsx-preserve',
53
+ config: {
54
+ order: 'pre',
55
+ handler(userConfig, env) {
56
+ projectRoot = userConfig.root ?? process.cwd();
57
+ },
58
+ },
59
+ transform: {
60
+ filter: {
61
+ id: [ '**/*.jsx', '**/*.tsx' ],
62
+ code: [ '/>', '</' ],
63
+ },
64
+ order: 'pre',
65
+ async handler(source, id) {
66
+ const plugins: BabelPlugins = [ 'jsx', 'decorators', 'decoratorAutoAccessors' ];
67
+ if (id.endsWith('.tsx'))
68
+ plugins.push('typescript');
69
+
70
+ // Default value for babel user options
71
+ let babelUserOptions: babel.TransformOptions = {};
72
+
73
+ if (options.babel) {
74
+ if (typeof options.babel === 'function') {
75
+ const babelOptions = options.babel(source, id);
76
+ babelUserOptions = babelOptions instanceof Promise
77
+ ? await babelOptions
78
+ : babelOptions;
79
+ }
80
+ else {
81
+ babelUserOptions = options.babel;
82
+ }
83
+ }
84
+
85
+ const babelOptions: babel.TransformOptions = {
86
+ root: projectRoot,
87
+ filename: id,
88
+ sourceFileName: id,
89
+ presets: [
90
+ [
91
+ litJsxBabelPreset,
92
+ /* merged into the metadata obj through state.opts */
93
+ {},
94
+ ],
95
+ ],
96
+ plugins: [],
97
+ ast: false,
98
+ sourceMaps: true,
99
+ configFile: false,
100
+ babelrc: false,
101
+ parserOpts: {
102
+ plugins,
103
+ },
104
+ };
105
+
106
+ const opts = mergeAndConcat(babelUserOptions, babelOptions);
107
+ const result = await babel.transformAsync(source, opts);
108
+
109
+ if (result?.code)
110
+ return { code: result.code, map: result.map };
111
+ },
112
+ },
113
+ };
114
+ };
@@ -0,0 +1,9 @@
1
+ declare module '@babel/plugin-syntax-jsx' {
2
+ const module: {
3
+ default: {
4
+ (): any;
5
+ manipulateOptions(opts: any, parserOpts: { plugins: string[]; }): void;
6
+ };
7
+ };
8
+ export default module;
9
+ }
@@ -0,0 +1,53 @@
1
+ import { nothing } from 'lit-html';
2
+
3
+
4
+ type ChooseValue<T> = T extends undefined ? never : T;
5
+ type ChooseChild<T> = [
6
+ condition: (value: ChooseValue<T>) => boolean,
7
+ output: (value: ChooseValue<T>) => JSX.JSXElement,
8
+ ];
9
+
10
+
11
+ /**
12
+ * Conditionally renders content based on evaluating multiple condition-output pairs against a value.
13
+ * Similar to lit-html's choose directive, evaluates each condition in order and renders the first match.
14
+ *
15
+ * @template T - The type of the value to evaluate against (defaults to undefined for no value)
16
+ * @param props.value - The value to pass to each condition and output function
17
+ * @param props.children - Single [condition, output] tuple or multiple tuple children to evaluate
18
+ * @returns The rendered JSX element from the first matching condition, or nothing if no match
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * // Multiple condition-output tuples as separate children
23
+ * <Choose value={status}>
24
+ * {[
25
+ * (status) => status === 'loading',
26
+ * () => <div>Loading...</div>
27
+ * ]}
28
+ * {[
29
+ * (status) => status === 'error',
30
+ * (status) => <div>Error: {status}</div>
31
+ * ]}
32
+ * {[
33
+ * () => true, // default case
34
+ * (status) => <div>Status: {status}</div>
35
+ * ]}
36
+ * </Choose>
37
+ * ```
38
+ */
39
+ export function Choose<T = undefined>(props: {
40
+ value?: T;
41
+ children: ChooseChild<T> | ChooseChild<T>[];
42
+ }): JSX.JSXElement {
43
+ const children = Array.isArray(props.children.at(-1))
44
+ ? props.children as ChooseChild<T>[]
45
+ : [ props.children as ChooseChild<T> ];
46
+
47
+ for (const [ condition, output ] of children) {
48
+ if (condition(props.value as ChooseValue<T>))
49
+ return output(props.value as ChooseValue<T>);
50
+ }
51
+
52
+ return nothing;
53
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview Internal lit-html part constructors for jsx-lit compiler.
3
+ *
4
+ * This module exports the internal part constructors from lit-html that are used
5
+ * by the lit-jsx compiler to create optimized template parts. These are low-level
6
+ * utilities used internally by the compilation process.
7
+ */
8
+
9
+ import * as internals from 'lit-html/private-ssr-support.js';
10
+
11
+
12
+ /** Boolean attribute part constructor from lit-html internals */
13
+ export const BooleanPart: typeof internals._$LH.BooleanAttributePart = internals._$LH.BooleanAttributePart;
14
+
15
+ /** Attribute part constructor from lit-html internals */
16
+ export const AttributePart: typeof internals._$LH.AttributePart = internals._$LH.AttributePart;
17
+
18
+ /** Property part constructor from lit-html internals */
19
+ export const PropertyPart: typeof internals._$LH.PropertyPart = internals._$LH.PropertyPart;
20
+
21
+ /** Element part constructor from lit-html internals */
22
+ export const ElementPart: typeof internals._$LH.ElementPart = internals._$LH.ElementPart;
23
+
24
+ /** Event part constructor from lit-html internals */
25
+ export const EventPart: typeof internals._$LH.EventPart = internals._$LH.EventPart;
26
+
27
+ /** Child part constructor from lit-html internals */
28
+ export const ChildPart: typeof internals._$LH.ChildPart = internals._$LH.ChildPart;
@@ -0,0 +1,54 @@
1
+ import { join } from 'lit-html/directives/join.js';
2
+ import { map } from 'lit-html/directives/map.js';
3
+ import { repeat } from 'lit-html/directives/repeat.js';
4
+
5
+
6
+ /**
7
+ * Renders a list of items with optional keys and separators.
8
+ *
9
+ * @template T - The type of items in the array
10
+ * @template U - The JSX element type returned by the render function
11
+ * @param props.each - Array of items to render
12
+ * @param props.key - Optional key function for efficient updates (uses lit-html's repeat directive)
13
+ * @param props.separator - Optional JSX element to insert between items
14
+ * @param props.children - Render function that receives each item and its index
15
+ * @returns An iterator from either the map or repeat directive, depending on whether a key function is provided.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * <For each={users} key={(user) => user.id}>
20
+ * {(user, index) => <div key={user.id}>{user.name}</div>}
21
+ * </For>
22
+ * ```
23
+ */
24
+ export function For<T, U extends JSX.JSXElement>(props: {
25
+ each: readonly T[];
26
+ key?: (item: T, index: number) => any;
27
+ separator?: JSX.JSXElement;
28
+ children: (item: T, index: number) => U;
29
+ }): JSX.JSXElement {
30
+ if (props.key) {
31
+ return repeat(
32
+ props.each,
33
+ (item, index) => props.key!(item, index),
34
+ (item, index) => {
35
+ if (props.separator && index > 0)
36
+ return [ props.separator, props.children(item, index) ];
37
+
38
+ return props.children(item, index);
39
+ },
40
+ );
41
+ }
42
+
43
+ if (props.separator) {
44
+ return join(map(
45
+ props.each,
46
+ (item, index) => props.children(item, index),
47
+ ), props.separator);
48
+ }
49
+
50
+ return map(
51
+ props.each,
52
+ (item, index) => props.children(item, index),
53
+ );
54
+ }
@@ -0,0 +1,37 @@
1
+ import type { StaticValue } from 'lit-html/static.js';
2
+ import { unsafeStatic } from 'lit-html/static.js';
3
+
4
+
5
+ /**
6
+ * Cache for static literal values used in lit-html templates.
7
+ * Extends Map to automatically create and cache StaticValue instances for string keys.
8
+ */
9
+ class LiteralMap extends Map<string, StaticValue> {
10
+
11
+ /**
12
+ * Gets a cached StaticValue for the given key, creating one if it doesn't exist.
13
+ *
14
+ * @param key - The string key to get or create a StaticValue for
15
+ * @returns The cached or newly created StaticValue
16
+ */
17
+ override get(key: string): StaticValue {
18
+ const value = super.get(key);
19
+ if (value === undefined) {
20
+ const literal = unsafeStatic(key);
21
+ this.set(key, literal);
22
+
23
+ return literal;
24
+ }
25
+
26
+ return value;
27
+ }
28
+
29
+ }
30
+
31
+
32
+ /**
33
+ * Global cache instance for static literal values used throughout jsx-lit templates.
34
+ * This is used internally by the jsx-lit compiler to cache StaticValue instances
35
+ * for efficient template reuse.
36
+ */
37
+ export const __$literalMap: LiteralMap = new LiteralMap();
@@ -0,0 +1,66 @@
1
+ import type { ElementPart } from 'lit-html';
2
+ import { noChange } from 'lit-html';
3
+ import type { DirectiveParameters, DirectiveResult, PartInfo } from 'lit-html/directive.js';
4
+ import { Directive, directive, PartType } from 'lit-html/directive.js';
5
+
6
+
7
+ /**
8
+ * Lit directive for applying rest/spread props to an element.
9
+ * Efficiently sets properties and attributes from an object of key-value pairs.
10
+ */
11
+ class RestDirective extends Directive {
12
+
13
+ constructor(part: PartInfo) {
14
+ super(part);
15
+
16
+ if (part.type !== PartType.ELEMENT)
17
+ throw new Error('RestDirective can only be used on ElementParts');
18
+ }
19
+
20
+ override update(part: ElementPart, [ rest ]: DirectiveParameters<this>): unknown {
21
+ const element = part.element as HTMLElement & Record<string, any>;
22
+
23
+ for (const key in rest) {
24
+ if (!Object.prototype.hasOwnProperty.call(rest, key))
25
+ continue;
26
+
27
+ const value = rest[key]!;
28
+
29
+ if (element[key] === value)
30
+ continue;
31
+
32
+ if (typeof value === 'object')
33
+ element[key] = value;
34
+ else if (value === null || value === undefined)
35
+ element.removeAttribute(key);
36
+ else
37
+ element.setAttribute(key, String(value));
38
+ }
39
+
40
+ return noChange;
41
+ }
42
+
43
+ override render(rest: Record<keyof any, any>): unknown {
44
+ console.log('rest parameter stuff', rest);
45
+
46
+ return noChange;
47
+ }
48
+
49
+ }
50
+
51
+
52
+ /**
53
+ * Lit directive for applying rest/spread props to DOM elements.
54
+ *
55
+ * This directive efficiently applies an object of properties and attributes
56
+ * to a DOM element, handling the differences between properties and attributes
57
+ * automatically.
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * const props = { className: 'my-class', disabled: true };
62
+ * <div {...__$rest(props)}>Content</div>
63
+ * ```
64
+ */
65
+ export const __$rest: DirectiveResult<typeof RestDirective> =
66
+ directive(RestDirective);
@@ -0,0 +1,48 @@
1
+ import { when as litWhen } from 'lit-html/directives/when.js';
2
+
3
+
4
+ type Falsy = null | undefined | false | 0 | -0 | 0n | '';
5
+ export const when = litWhen as <C, T, F>(
6
+ condition: C,
7
+ trueCase: (c: NoInfer<Exclude<C, Falsy>>) => T,
8
+ falseCase?: (c: NoInfer<Exclude<C, Falsy>>) => F,
9
+ ) => C extends Falsy ? F : T;
10
+
11
+ type ShowTrueCase<C, T> = (value: NoInfer<Exclude<C, Falsy>>) => T;
12
+ type ShowFalseCase<C, F> = (value: NoInfer<Exclude<C, Falsy>>) => F;
13
+ type ShowChildren<C, T, F> =
14
+ | ShowTrueCase<C, T>
15
+ | [ true: ShowTrueCase<C, T>, false: ShowFalseCase<C, F> ];
16
+
17
+
18
+ /**
19
+ * Conditionally renders content based on a truthy value.
20
+ *
21
+ * @template T - The type of the condition value
22
+ * @template U - The JSX element type returned by the render functions
23
+ * @param props.when - The condition value to evaluate for truthiness
24
+ * @param props.children - A single render or tuple containing render functions for true and optionally false cases
25
+ * @returns The rendered JSX element based on the condition's truthiness
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <Show when={user}>
30
+ * {(user) => <div>Welcome, {user.name}!</div>}
31
+ * {() => <div>Please log in</div>}
32
+ * </Show>
33
+ *
34
+ * // Or without fallback
35
+ * <Show when={isVisible}>
36
+ * {() => <div>This content is visible</div>}
37
+ * </Show>
38
+ * ```
39
+ */
40
+ export function Show<C, T, F>(props: {
41
+ when: C;
42
+ children: ShowChildren<C, T, F>;
43
+ }): C extends Falsy ? F : T {
44
+ if (Array.isArray(props.children))
45
+ return when(props.when, props.children[0], props.children[1]);
46
+
47
+ return when(props.when, props.children);
48
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Identity function for template string arrays used by jsx-lit compiler.
3
+ *
4
+ * This function is used as a marker by the jsx-lit compiler to identify
5
+ * template literals that should be processed for JSX compilation. It simply
6
+ * returns the input unchanged but signals to the compiler where JSX templates are located.
7
+ *
8
+ * @param strings - The template strings array from a template literal
9
+ * @returns The same template strings array unchanged
10
+ */
11
+ export const __$t: (strings: TemplateStringsArray) => TemplateStringsArray = s => s;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Creates a variable which can be used using the Component syntax in JSX.
3
+ * Also registers the custom element if it hasn't been registered yet.
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * import { toJSX } from 'jsx-lit';
8
+ *
9
+ * export class MyButton extends LitElement {
10
+ * static tagName = 'my-button';
11
+ * static tag = toJSX(MyButton);
12
+ *
13
+ * render() {
14
+ * return html`<button><slot></slot></button>`;
15
+ * }
16
+ * }
17
+ *
18
+ * // Usage in JSX
19
+ * const jsx = (
20
+ * <MyButton.tag
21
+ * class="my-button"
22
+ * on-click={() => { console.log('Clicked!'); }}
23
+ * />
24
+ * );
25
+ * ```
26
+ */
27
+ export const toJSX = <T extends { new(...args: any): any; tagName: string; }>(
28
+ element: T,
29
+ ): (props: JSX.JSXProps<InstanceType<T>>) => string => {
30
+ queueMicrotask(() => {
31
+ if ('register' in element && typeof element.register === 'function')
32
+ element.register();
33
+ else if (!customElements.get(element.tagName))
34
+ customElements.define(element.tagName, element);
35
+ });
36
+
37
+ return element.tagName as any;
38
+ };
39
+
40
+
41
+ /**
42
+ * Creates a dynamic tag name object that can be used with jsx-lit's Component syntax.
43
+ * This function is required for dynamic tag names to compile to static literals.
44
+ *
45
+ * **IMPORTANT**: Dynamic tag names must use the `.tag` property pattern to be properly
46
+ * compiled to lit-html static templates. Without this pattern, jsx-lit cannot detect
47
+ * and transform the dynamic tag name into efficient static template literals.
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * import { toTag } from 'jsx-lit';
52
+ *
53
+ * // ✅ Correct usage - creates { tag: 'div' } object
54
+ * const DynamicDiv = toTag('div');
55
+ * const DynamicCustomElement = toTag('my-custom-element');
56
+ *
57
+ * // Usage in JSX with .tag property (required for compilation)
58
+ * function renderConditional({ useDiv }) {
59
+ * const Tag = toTag(useDiv ? 'div' : 'span');
60
+ * return <Tag.tag class="dynamic">Content</Tag.tag>;
61
+ * }
62
+ *
63
+ * // Compiles to efficient static templates:
64
+ * // const Tag = toTag(useDiv ? 'div' : 'span');
65
+ * // const __$Tag = __$literalMap.get(Tag.tag);
66
+ * // htmlStatic`<${__$Tag} class="dynamic">Content</${__$Tag}>`
67
+ * ```
68
+ *
69
+ * @example
70
+ * ```tsx
71
+ * // ❌ Incorrect usage - won't compile to static templates
72
+ * const badTag = 'div';
73
+ * return <badTag>Content</badTag>; // This won't work with jsx-lit
74
+ *
75
+ * // ❌ Incorrect usage - missing .tag property
76
+ * const BadTag = toTag('div');
77
+ * return <BadTag>Content</BadTag>; // Won't compile correctly
78
+ *
79
+ * // ✅ Correct usage - with .tag property
80
+ * const GoodTag = toTag('div');
81
+ * return <GoodTag.tag>Content</GoodTag.tag>; // Compiles to static templates
82
+ * ```
83
+ *
84
+ * @param tag - The HTML tag name (standard HTML elements or custom element names)
85
+ * @returns An object with a `tag` property containing the tag name, designed for use with jsx-lit's Component syntax
86
+ */
87
+ export const toTag = <T extends keyof HTMLElementTagNameMap | (string & {})>(
88
+ tag: T,
89
+ ): { tag: T; } => {
90
+ return { tag } as any;
91
+ };