@arcmantle/lit-jsx 1.0.32 → 1.0.34

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 (84) hide show
  1. package/README.md +153 -105
  2. package/dist/compiler/attribute-processor.d.ts +9 -19
  3. package/dist/compiler/attribute-processor.d.ts.map +1 -1
  4. package/dist/compiler/attribute-processor.js +22 -39
  5. package/dist/compiler/attribute-processor.js.map +1 -1
  6. package/dist/compiler/babel-plugin.d.ts +1 -0
  7. package/dist/compiler/babel-plugin.d.ts.map +1 -1
  8. package/dist/compiler/babel-plugin.js +2 -1
  9. package/dist/compiler/babel-plugin.js.map +1 -1
  10. package/dist/compiler/compiler-utils.d.ts +9 -1
  11. package/dist/compiler/compiler-utils.d.ts.map +1 -1
  12. package/dist/compiler/compiler-utils.js +71 -60
  13. package/dist/compiler/compiler-utils.js.map +1 -1
  14. package/dist/compiler/config.d.ts +23 -28
  15. package/dist/compiler/config.d.ts.map +1 -1
  16. package/dist/compiler/config.js +28 -28
  17. package/dist/compiler/config.js.map +1 -1
  18. package/dist/compiler/oxc-walker.d.ts +4 -4
  19. package/dist/compiler/oxc-walker.d.ts.map +1 -1
  20. package/dist/compiler/oxc-walker.js +1 -1
  21. package/dist/compiler/oxc-walker.js.map +1 -1
  22. package/dist/compiler/preprocess.d.ts +1 -0
  23. package/dist/compiler/preprocess.d.ts.map +1 -1
  24. package/dist/compiler/preprocess.js +31 -0
  25. package/dist/compiler/preprocess.js.map +1 -1
  26. package/dist/compiler/transpiler.d.ts.map +1 -1
  27. package/dist/compiler/transpiler.js +31 -13
  28. package/dist/compiler/transpiler.js.map +1 -1
  29. package/dist/compiler/vite-plugin.d.ts +3 -1
  30. package/dist/compiler/vite-plugin.d.ts.map +1 -1
  31. package/dist/compiler/vite-plugin.js +1 -0
  32. package/dist/compiler/vite-plugin.js.map +1 -1
  33. package/dist/runtime/choose-component.d.ts +2 -2
  34. package/dist/runtime/choose-component.d.ts.map +1 -1
  35. package/dist/runtime/for-component.d.ts +3 -3
  36. package/dist/runtime/for-component.d.ts.map +1 -1
  37. package/dist/runtime/for-component.js.map +1 -1
  38. package/dist/runtime/lit-reexports.d.ts +11 -0
  39. package/dist/runtime/lit-reexports.d.ts.map +1 -0
  40. package/dist/runtime/lit-reexports.js +14 -0
  41. package/dist/runtime/lit-reexports.js.map +1 -0
  42. package/dist/runtime/show-component.d.ts +4 -4
  43. package/dist/runtime/show-component.d.ts.map +1 -1
  44. package/dist/runtime/type-helpers.d.ts +1 -1
  45. package/dist/runtime/type-helpers.d.ts.map +1 -1
  46. package/dist/shared/jsx-core.d.ts +83 -0
  47. package/dist/shared/jsx-core.d.ts.map +1 -0
  48. package/dist/shared/jsx-core.js +2 -0
  49. package/dist/shared/jsx-core.js.map +1 -0
  50. package/dist/shared/jsx-dom.d.ts +26 -0
  51. package/dist/shared/jsx-dom.d.ts.map +1 -0
  52. package/dist/shared/jsx-dom.js +2 -0
  53. package/dist/shared/jsx-dom.js.map +1 -0
  54. package/dist/shared/jsx-hooks.d.ts +69 -0
  55. package/dist/shared/jsx-hooks.d.ts.map +1 -0
  56. package/dist/shared/jsx-hooks.js +2 -0
  57. package/dist/shared/jsx-hooks.js.map +1 -0
  58. package/dist/shared/jsx-types.d.ts +3 -2140
  59. package/dist/shared/jsx-types.d.ts.map +1 -1
  60. package/dist/shared/jsx-types.js +3 -1
  61. package/dist/shared/jsx-types.js.map +1 -1
  62. package/dist/utils.d.ts +1 -0
  63. package/dist/utils.d.ts.map +1 -1
  64. package/dist/utils.js +3 -0
  65. package/dist/utils.js.map +1 -1
  66. package/package.json +17 -17
  67. package/src/compiler/attribute-processor.ts +33 -60
  68. package/src/compiler/babel-plugin.ts +3 -1
  69. package/src/compiler/compiler-utils.ts +91 -259
  70. package/src/compiler/config.ts +52 -43
  71. package/src/compiler/oxc-walker.ts +5 -5
  72. package/src/compiler/preprocess.ts +41 -0
  73. package/src/compiler/transpiler.ts +31 -12
  74. package/src/compiler/vite-plugin.ts +4 -1
  75. package/src/runtime/choose-component.ts +2 -2
  76. package/src/runtime/for-component.ts +3 -3
  77. package/src/runtime/lit-reexports.ts +16 -0
  78. package/src/runtime/show-component.ts +4 -4
  79. package/src/runtime/type-helpers.ts +1 -1
  80. package/src/shared/jsx-core.ts +123 -0
  81. package/src/shared/jsx-dom.ts +29 -0
  82. package/src/shared/jsx-hooks.ts +86 -0
  83. package/src/shared/jsx-types.ts +3 -2559
  84. package/src/utils.ts +15 -0
@@ -16,6 +16,7 @@ import {
16
16
  isJSXElementStatic,
17
17
  isJSXFragmentPath,
18
18
  isValidOpeningElement,
19
+ normalizeText,
19
20
  } from './compiler-utils.js';
20
21
  import {
21
22
  Ensure,
@@ -160,10 +161,14 @@ export class TemplateTranspiler extends JSXTranspiler<TemplateContext> {
160
161
  override children(context: TemplateContext): void {
161
162
  for (const [ index, child ] of context.path.node.children.entries()) {
162
163
  if (t.isJSXText(child)) {
163
- if (WHITESPACE_TAGS.includes(context.tagName))
164
+ if (WHITESPACE_TAGS.includes(context.tagName)) {
164
165
  context.builder.addText(child.value);
165
- else
166
- context.builder.addText(child.value.trim());
166
+ }
167
+ else {
168
+ const normalizedValue = normalizeText(child.value);
169
+ if (normalizedValue)
170
+ context.builder.addText(normalizedValue);
171
+ }
167
172
  }
168
173
  else if (t.isJSXExpressionContainer(child)) {
169
174
  if (t.isJSXEmptyExpression(child.expression))
@@ -300,9 +305,14 @@ export class TemplateTranspiler extends JSXTranspiler<TemplateContext> {
300
305
  const child = childPath.node;
301
306
 
302
307
  if (t.isJSXText(child)) {
303
- const trimmedValue = child.value.trim();
304
- if (trimmedValue)
305
- childrenArray.push(t.stringLiteral(trimmedValue));
308
+ if (WHITESPACE_TAGS.includes(context.tagName)) {
309
+ childrenArray.push(t.stringLiteral(child.value));
310
+ }
311
+ else {
312
+ const normalizedValue = normalizeText(child.value);
313
+ if (normalizedValue)
314
+ childrenArray.push(t.stringLiteral(normalizedValue));
315
+ }
306
316
  }
307
317
  else if (t.isJSXExpressionContainer(child)) {
308
318
  if (t.isJSXEmptyExpression(child.expression))
@@ -463,10 +473,14 @@ export class CompiledTranspiler extends JSXTranspiler<CompiledContext> {
463
473
  const child = childPath.node;
464
474
 
465
475
  if (t.isJSXText(child)) {
466
- if (WHITESPACE_TAGS.includes(context.tagName))
476
+ if (WHITESPACE_TAGS.includes(context.tagName)) {
467
477
  context.builder.addText(child.value);
468
- else
469
- context.builder.addText(child.value.trim());
478
+ }
479
+ else {
480
+ const normalizedValue = normalizeText(child.value);
481
+ if (normalizedValue)
482
+ context.builder.addText(normalizedValue);
483
+ }
470
484
  }
471
485
  else if (t.isJSXExpressionContainer(child)) {
472
486
  if (t.isJSXEmptyExpression(child.expression))
@@ -560,9 +574,14 @@ export class CompiledTranspiler extends JSXTranspiler<CompiledContext> {
560
574
  const child = childPath.node;
561
575
 
562
576
  if (t.isJSXText(child)) {
563
- const trimmedValue = child.value.trim();
564
- if (trimmedValue)
565
- childrenArray.push(t.stringLiteral(trimmedValue));
577
+ if (WHITESPACE_TAGS.includes(context.tagName)) {
578
+ childrenArray.push(t.stringLiteral(child.value));
579
+ }
580
+ else {
581
+ const normalizedValue = normalizeText(child.value);
582
+ if (normalizedValue)
583
+ childrenArray.push(t.stringLiteral(normalizedValue));
584
+ }
566
585
  }
567
586
  else if (t.isJSXExpressionContainer(child)) {
568
587
  if (t.isJSXEmptyExpression(child.expression))
@@ -16,8 +16,10 @@ import { ImportDiscovery } from './import-discovery.js';
16
16
  export const litJsx = (options: {
17
17
  /** Enable legacy decorators support */
18
18
  legacyDecorators?: boolean;
19
- /** Enables experimental support for compiled templates */
19
+ /** Enables support for experimental compiled templates @default true */
20
20
  useCompiledTemplates?: boolean;
21
+ /** Opts into the automatic discovery is custom elements instead of using the static attribute */
22
+ useImportDiscovery?: boolean;
21
23
  /** Enable debug mode for additional logging */
22
24
  debug?: boolean;
23
25
  /** Options for the Babel transform */
@@ -65,6 +67,7 @@ export const litJsx = (options: {
65
67
  plugins: [
66
68
  litJsxBabelPlugin({
67
69
  useCompiledTemplates: options.useCompiledTemplates,
70
+ useImportDiscovery: options.useImportDiscovery,
68
71
  }),
69
72
  ],
70
73
  ast: false,
@@ -4,7 +4,7 @@ import { nothing } from 'lit-html';
4
4
  type ChooseValue<T> = T extends undefined ? never : T;
5
5
  type ChooseChild<T> = [
6
6
  condition: (value: ChooseValue<T>) => boolean,
7
- output: (value: ChooseValue<T>) => JSX.JSXElement,
7
+ output: (value: ChooseValue<T>) => LitJSX.Child,
8
8
  ];
9
9
 
10
10
 
@@ -39,7 +39,7 @@ type ChooseChild<T> = [
39
39
  export function Choose<T = undefined>(props: {
40
40
  value?: T;
41
41
  children: ChooseChild<T> | ChooseChild<T>[];
42
- }): JSX.JSXElement {
42
+ }): LitJSX.Child {
43
43
  const children = Array.isArray(props.children.at(-1))
44
44
  ? props.children as ChooseChild<T>[]
45
45
  : [ props.children as ChooseChild<T> ];
@@ -21,12 +21,12 @@ import { repeat } from 'lit-html/directives/repeat.js';
21
21
  * </For>
22
22
  * ```
23
23
  */
24
- export function For<T, U extends JSX.JSXElement>(props: {
24
+ export function For<T, U extends LitJSX.Child>(props: {
25
25
  each: readonly T[];
26
26
  key?: (item: T, index: number) => any;
27
- separator?: JSX.JSXElement;
27
+ separator?: LitJSX.Child;
28
28
  children: (item: T, index: number) => U;
29
- }): JSX.JSXElement {
29
+ }): LitJSX.Child {
30
30
  if (props.key) {
31
31
  return repeat(
32
32
  props.each,
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Re-exports of lit-html functionality used by the transpiler.
3
+ * This allows consumers to use @arcmantle/lit-jsx without having direct lit-html dependencies.
4
+ * Only exports what the transpiler actually generates in its output code.
5
+ */
6
+
7
+ // Core template tags
8
+ export { html, mathml, svg } from 'lit-html';
9
+
10
+ // Static template tags
11
+ export { html as htmlStatic, mathml as mathmlStatic, svg as svgStatic, unsafeStatic } from 'lit-html/static.js';
12
+
13
+ // Directives
14
+ export { classMap } from 'lit-html/directives/class-map.js';
15
+ export { ref } from 'lit-html/directives/ref.js';
16
+ export { styleMap } from 'lit-html/directives/style-map.js';
@@ -26,12 +26,12 @@ import { when } from 'lit-html/directives/when.js';
26
26
  export function Show<C>(props: {
27
27
  when: C;
28
28
  children:
29
- | ((value: NoInfer<C>) => JSX.JSXElement)
29
+ | ((value: NoInfer<C>) => LitJSX.Child)
30
30
  | [
31
- true: ((value: NoInfer<C>) => JSX.JSXElement),
32
- false: ((value: NoInfer<C>) => JSX.JSXElement),
31
+ true: ((value: NoInfer<C>) => LitJSX.Child),
32
+ false: ((value: NoInfer<C>) => LitJSX.Child),
33
33
  ];
34
- }): JSX.JSXElement {
34
+ }): LitJSX.Child {
35
35
  if (Array.isArray(props.children))
36
36
  return when(props.when, props.children[0], props.children[1]);
37
37
 
@@ -36,7 +36,7 @@ export const toComponent = <T extends { new(...args: any): any; tagName: string;
36
36
  };
37
37
 
38
38
  export type ToComponent<T extends object = object> =
39
- (props: JSX.JSXProps<T> & { static: any; }) => string;
39
+ (props: LitJSX.JSXProps<T> & { static: any; }) => string;
40
40
 
41
41
 
42
42
  /**
@@ -0,0 +1,123 @@
1
+ import type { TemplateResult } from 'lit-html';
2
+ import type { DirectiveResult } from 'lit-html/async-directive.js';
3
+ import type { RefOrCallback } from 'lit-html/directives/ref.js';
4
+
5
+
6
+ declare global {
7
+ namespace LitJSX {
8
+ type HTMLElementAssignableProps<T extends object & Record<string, any>> =
9
+ Partial<TrimReadonly<T>>;
10
+
11
+ type HTMLElementProps = HTMLElementAssignableProps<HTMLElement>;
12
+
13
+ type JSXElementProps<T extends object> = HTMLElementAssignableProps<T> & {
14
+ children?: LitJSX.Child;
15
+ ref?: RefOrCallback<HTMLElementAssignableProps<T>>;
16
+ classList?: { [k: string]: boolean | undefined; };
17
+ styleList?: CSSProperties;
18
+
19
+ /**
20
+ * This property takes in one or more element directives.
21
+ * This is akin to applying a directive through `<div ${myDirective()}></div>`.
22
+ */
23
+ directive?: DirectiveResult<any> | DirectiveResult<any>[];
24
+ } & {
25
+ [key: `data-${ string }`]: string | undefined;
26
+ };
27
+
28
+ type ElementMapToJSXElements<T extends object & Record<string, any>> = {
29
+ [K in keyof T]: JSXElementProps<T[K]>;
30
+ };
31
+
32
+ type IfEquals<X, Y, A = X> =
33
+ (<T>() => T extends X ? 1 : 2) extends
34
+ (<T>() => T extends Y ? 1 : 2) ? A : never;
35
+
36
+ type WritableKeys<T> = {
37
+ [P in keyof T]-?: IfEquals<
38
+ { [Q in P]: T[P] },
39
+ { -readonly [Q in P]: T[P] },
40
+ P
41
+ >
42
+ }[keyof T];
43
+
44
+ type TrimReadonly<T> = Pick<T, WritableKeys<T>>;
45
+
46
+ type TrimHTMLElement<T extends object> = TrimReadonly<Omit<T, keyof HTMLElement | 'constructor'>>;
47
+
48
+ type JSXProps<T extends object> =
49
+ & TrimHTMLElement<T>
50
+ & Omit<HTMLElementProps, keyof TrimHTMLElement<T>>;
51
+
52
+ type Child = unknown;
53
+
54
+ type Element = TemplateResult<any>;
55
+
56
+ type AnyTagName = string & Record<never, never>;
57
+
58
+ interface IntrinsicElements extends
59
+ NativeHTMLElements,
60
+ NativeSVGElements,
61
+ NativeMathMLElements,
62
+ SemanticTags {}
63
+
64
+ type TagName = keyof IntrinsicElements | AnyTagName;
65
+
66
+ type DynamicTagProps<Tag extends string> = Tag extends keyof IntrinsicElements
67
+ ? IntrinsicElements[Tag]
68
+ : (Tag extends keyof HTMLElementTagNameMap
69
+ ? JSXElementProps<HTMLElementTagNameMap[Tag]>
70
+ : JSXElementProps<HTMLElement>);
71
+
72
+ type IntrinsicElementProps<Tag extends keyof IntrinsicElements> = IntrinsicElements[Tag];
73
+
74
+ type DynamicTag<Tag extends TagName> = ((props: DynamicTagProps<Tag> & StaticMarker) => Element);
75
+
76
+ interface StaticMarker {
77
+ /**
78
+ * Opt into the lit-jsx custom-element transform. \
79
+ * Example: `<MyElement static />`
80
+ */
81
+ static: true;
82
+ }
83
+
84
+ type Component<P extends object = {}> = (props: P) => Element;
85
+ type ClassComponent<Instance extends object = any> = abstract new (...args: any[]) => Instance;
86
+
87
+ type ComponentLike<P extends object = object> =
88
+ | Component<P>
89
+ | ClassComponent<any>;
90
+
91
+ type ComponentProps<T> =
92
+ T extends Component<infer P> ? P :
93
+ T extends ClassComponent<infer I> ? JSXProps<Extract<I, object>> :
94
+ T extends abstract new (...args: any[]) => infer I ? JSXProps<Extract<I, object>> :
95
+ {};
96
+ }
97
+
98
+ // eslint-disable-next-line no-var
99
+ var as: {
100
+ /**
101
+ * Informs the compiler that the value should be bound as a property value.\
102
+ * This binds the expression value as a property, using the `.` syntax e.g `.key=${value}`\
103
+ * This function call is removed during compilation, therefore it has no runtime effect.
104
+ */
105
+ prop: <T>(value: T) => T;
106
+ /**
107
+ * Informs the compiler that the value should be bound as a boolean attribute.\
108
+ * This allows the template to bind the value using the `?` syntax, e.g. `?disabled=${true}`\
109
+ * This function call is removed during compilation, therefore it has no runtime effect.
110
+ */
111
+ bool: (value: boolean) => boolean;
112
+ /**
113
+ * Creates a component-like value for an intrinsic tag, so it can be used in
114
+ * JSX as a dynamic tag identifier.
115
+ *
116
+ * The returned component requires `static`.
117
+ * Example:
118
+ * const Tag = as.tag('a');
119
+ * <Tag static href="..." />
120
+ */
121
+ tag: <Tag extends LitJSX.TagName>(tag: Tag) => LitJSX.DynamicTag<Tag>;
122
+ };
123
+ }
@@ -0,0 +1,29 @@
1
+ import type * as csstype from 'csstype';
2
+
3
+
4
+ declare global {
5
+ namespace LitJSX {
6
+
7
+ interface CSSProperties extends csstype.Properties { }
8
+
9
+ /**
10
+ * Interface for native HTML elements
11
+ */
12
+ type NativeHTMLElements = ElementMapToJSXElements<HTMLElementTagNameMap>;
13
+
14
+ /**
15
+ * Interface for native SVG elements
16
+ */
17
+ type NativeSVGElements = ElementMapToJSXElements<Omit<SVGElementTagNameMap, keyof HTMLElementTagNameMap>>;
18
+
19
+ /**
20
+ * Interface for native MathML elements
21
+ */
22
+ type NativeMathMLElements = ElementMapToJSXElements<Omit<MathMLElementTagNameMap, keyof HTMLElementTagNameMap>>;
23
+
24
+ /**
25
+ * Interface for semantic tags that start with "s-".
26
+ */
27
+ interface SemanticTags { [key: `s-${ string }`]: JSXElementProps<HTMLElement>; }
28
+ }
29
+ }
@@ -0,0 +1,86 @@
1
+ export {};
2
+
3
+
4
+ /**
5
+ * TSX hook declarations for lit-jsx.
6
+ */
7
+
8
+ declare global {
9
+ //#region JSX hooks (TypeScript special names)
10
+ // These names are *looked up by TypeScript* when type-checking TSX.
11
+ namespace JSX {
12
+ /**
13
+ * TSX hook: the type produced by any JSX expression.
14
+ *
15
+ * In lit-jsx we return a lit `TemplateResult`, so `<div />` has this type.
16
+ */
17
+ type Element = LitJSX.Element;
18
+
19
+ /**
20
+ * TSX hook: what values are allowed as JSX tags.
21
+ *
22
+ * Note: this intentionally references tag/component helper types declared in
23
+ * `jsx-core.ts`.
24
+ */
25
+ type ElementType
26
+ = keyof LitJSX.IntrinsicElements
27
+ | (string & {})
28
+ | LitJSX.ComponentLike<any>;
29
+
30
+ /**
31
+ * TSX hook: computes the attribute (props) type for a JSX tag.
32
+ *
33
+ * lit-jsx uses this to:
34
+ * - require `static: true` for class-based component tags
35
+ * - preserve TSX generic arguments on class instances (avoid `unknown` props)
36
+ */
37
+ type LibraryManagedAttributes<C, P>
38
+ = C extends abstract new (...args: any[]) => infer I
39
+ ? (P extends I
40
+ ? LitJSX.JSXProps<Extract<P, object>> & LitJSX.StaticMarker
41
+ : LitJSX.ComponentProps<C> & LitJSX.StaticMarker)
42
+ : (C extends keyof LitJSX.IntrinsicElements
43
+ ? LitJSX.IntrinsicElementProps<C>
44
+ : LitJSX.ComponentProps<C>);
45
+
46
+ /**
47
+ * TSX hook: controls the instance type used for class components.
48
+ *
49
+ * We keep this empty because we don’t require any particular base class.
50
+ */
51
+ interface ElementClass {}
52
+
53
+ /**
54
+ * TSX hook: which property name TypeScript should read for “props”.
55
+ *
56
+ * Leaving it empty means TS uses its default behavior.
57
+ */
58
+ interface ElementAttributesProperty {}
59
+
60
+ /**
61
+ * TSX hook: which property name represents “children”.
62
+ */
63
+ interface ElementChildrenAttribute { children: {}; }
64
+
65
+ /** TSX hook: attributes allowed on *all* JSX elements (e.g. React's `key`). */
66
+ interface IntrinsicAttributes {}
67
+
68
+ /** TSX hook: attributes allowed on class components specifically (often `ref`-like). */
69
+ interface IntrinsicClassAttributes<_T> {}
70
+
71
+ /** TSX hook: base attribute bag TypeScript may intersect into component props. */
72
+ interface Attributes {}
73
+
74
+ /** TSX hook: fragment typing for `<>...</>` */
75
+ type Fragment = Element;
76
+
77
+ /**
78
+ * TSX hook: mapping of intrinsic tag names to their attribute types.
79
+ *
80
+ * Note: this intentionally depends on DOM typings declared in `jsx-dom.ts`
81
+ * (e.g. `HTMLElementTags`, `SVGElementTags`, ...).
82
+ */
83
+ interface IntrinsicElements extends LitJSX.IntrinsicElements {}
84
+ }
85
+ //#endregion
86
+ }