@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.
- package/README.md +768 -0
- package/dist/compiler/attribute-processor.d.ts +128 -0
- package/dist/compiler/attribute-processor.d.ts.map +1 -0
- package/dist/compiler/attribute-processor.js +380 -0
- package/dist/compiler/attribute-processor.js.map +1 -0
- package/dist/compiler/babel-preset.d.ts +6 -0
- package/dist/compiler/babel-preset.d.ts.map +1 -0
- package/dist/compiler/babel-preset.js +27 -0
- package/dist/compiler/babel-preset.js.map +1 -0
- package/dist/compiler/builder.d.ts +22 -0
- package/dist/compiler/builder.d.ts.map +1 -0
- package/dist/compiler/builder.js +62 -0
- package/dist/compiler/builder.js.map +1 -0
- package/dist/compiler/compiler-utils.d.ts +81 -0
- package/dist/compiler/compiler-utils.d.ts.map +1 -0
- package/dist/compiler/compiler-utils.js +410 -0
- package/dist/compiler/compiler-utils.js.map +1 -0
- package/dist/compiler/config.d.ts +77 -0
- package/dist/compiler/config.d.ts.map +1 -0
- package/dist/compiler/config.js +78 -0
- package/dist/compiler/config.js.map +1 -0
- package/dist/compiler/postprocess.d.ts +5 -0
- package/dist/compiler/postprocess.d.ts.map +1 -0
- package/dist/compiler/postprocess.js +3 -0
- package/dist/compiler/postprocess.js.map +1 -0
- package/dist/compiler/preprocess.d.ts +5 -0
- package/dist/compiler/preprocess.d.ts.map +1 -0
- package/dist/compiler/preprocess.js +28 -0
- package/dist/compiler/preprocess.js.map +1 -0
- package/dist/compiler/transform-jsx.d.ts +5 -0
- package/dist/compiler/transform-jsx.d.ts.map +1 -0
- package/dist/compiler/transform-jsx.js +25 -0
- package/dist/compiler/transform-jsx.js.map +1 -0
- package/dist/compiler/transpiler.d.ts +48 -0
- package/dist/compiler/transpiler.d.ts.map +1 -0
- package/dist/compiler/transpiler.js +463 -0
- package/dist/compiler/transpiler.js.map +1 -0
- package/dist/compiler/vite-plugin.d.ts +38 -0
- package/dist/compiler/vite-plugin.d.ts.map +1 -0
- package/dist/compiler/vite-plugin.js +96 -0
- package/dist/compiler/vite-plugin.js.map +1 -0
- package/dist/runtime/choose-component.d.ts +39 -0
- package/dist/runtime/choose-component.d.ts.map +1 -0
- package/dist/runtime/choose-component.js +40 -0
- package/dist/runtime/choose-component.js.map +1 -0
- package/dist/runtime/compiler-ctors.d.ts +21 -0
- package/dist/runtime/compiler-ctors.d.ts.map +1 -0
- package/dist/runtime/compiler-ctors.js +21 -0
- package/dist/runtime/compiler-ctors.js.map +1 -0
- package/dist/runtime/for-component.d.ts +25 -0
- package/dist/runtime/for-component.d.ts.map +1 -0
- package/dist/runtime/for-component.js +35 -0
- package/dist/runtime/for-component.js.map +1 -0
- package/dist/runtime/literal-map.d.ts +22 -0
- package/dist/runtime/literal-map.d.ts.map +1 -0
- package/dist/runtime/literal-map.js +29 -0
- package/dist/runtime/literal-map.js.map +1 -0
- package/dist/runtime/rest-directive.d.ts +28 -0
- package/dist/runtime/rest-directive.d.ts.map +1 -0
- package/dist/runtime/rest-directive.js +49 -0
- package/dist/runtime/rest-directive.js.map +1 -0
- package/dist/runtime/show-component.d.ts +33 -0
- package/dist/runtime/show-component.d.ts.map +1 -0
- package/dist/runtime/show-component.js +30 -0
- package/dist/runtime/show-component.js.map +1 -0
- package/dist/runtime/tagged-template.d.ts +12 -0
- package/dist/runtime/tagged-template.d.ts.map +1 -0
- package/dist/runtime/tagged-template.js +12 -0
- package/dist/runtime/tagged-template.js.map +1 -0
- package/dist/runtime/type-helpers.d.ts +80 -0
- package/dist/runtime/type-helpers.d.ts.map +1 -0
- package/dist/runtime/type-helpers.js +85 -0
- package/dist/runtime/type-helpers.js.map +1 -0
- package/dist/shared/jsx-types.d.ts +2139 -0
- package/dist/shared/jsx-types.d.ts.map +1 -0
- package/dist/shared/jsx-types.js +2 -0
- package/dist/shared/jsx-types.js.map +1 -0
- package/dist/shared/jsx-utils.d.ts +30 -0
- package/dist/shared/jsx-utils.d.ts.map +1 -0
- package/dist/shared/jsx-utils.js +58 -0
- package/dist/shared/jsx-utils.js.map +1 -0
- package/dist/shared/mathml-tags.d.ts +12 -0
- package/dist/shared/mathml-tags.d.ts.map +1 -0
- package/dist/shared/mathml-tags.js +215 -0
- package/dist/shared/mathml-tags.js.map +1 -0
- package/dist/shared/svg-tags.d.ts +13 -0
- package/dist/shared/svg-tags.d.ts.map +1 -0
- package/dist/shared/svg-tags.js +95 -0
- package/dist/shared/svg-tags.js.map +1 -0
- package/dist/utils.d.ts +30 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +30 -0
- package/dist/utils.js.map +1 -0
- package/package.json +52 -0
- package/src/compiler/attribute-processor.ts +579 -0
- package/src/compiler/babel-preset.ts +34 -0
- package/src/compiler/builder.ts +86 -0
- package/src/compiler/compiler-utils.ts +789 -0
- package/src/compiler/config.ts +77 -0
- package/src/compiler/postprocess.ts +7 -0
- package/src/compiler/preprocess.ts +40 -0
- package/src/compiler/transform-jsx.ts +36 -0
- package/src/compiler/transpiler.ts +644 -0
- package/src/compiler/vite-plugin.ts +114 -0
- package/src/external.d.ts +9 -0
- package/src/runtime/choose-component.ts +53 -0
- package/src/runtime/compiler-ctors.ts +28 -0
- package/src/runtime/for-component.ts +54 -0
- package/src/runtime/literal-map.ts +37 -0
- package/src/runtime/rest-directive.ts +66 -0
- package/src/runtime/show-component.ts +48 -0
- package/src/runtime/tagged-template.ts +11 -0
- package/src/runtime/type-helpers.ts +91 -0
- package/src/shared/jsx-types.ts +2556 -0
- package/src/shared/jsx-utils.ts +85 -0
- package/src/shared/mathml-tags.ts +235 -0
- package/src/shared/svg-tags.ts +103 -0
- package/src/tsconfig.json +4 -0
- 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,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
|
+
};
|