element-vir 26.11.2 → 26.12.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 (188) hide show
  1. package/package.json +12 -12
  2. package/src/declarative-element/declarative-element-init.ts +115 -0
  3. package/src/declarative-element/declarative-element.ts +372 -0
  4. package/src/declarative-element/define-element.ts +515 -0
  5. package/{dist/declarative-element/definition-options.d.ts → src/declarative-element/definition-options.ts} +7 -2
  6. package/src/declarative-element/directives/assign.directive.ts +89 -0
  7. package/{dist/declarative-element/directives/async-prop.js → src/declarative-element/directives/async-prop.ts} +42 -8
  8. package/src/declarative-element/directives/attributes.directive.ts +63 -0
  9. package/src/declarative-element/directives/create-attribute-directive.ts +47 -0
  10. package/src/declarative-element/directives/directive-helpers.ts +67 -0
  11. package/{dist/declarative-element/directives/listen-to-activate.js → src/declarative-element/directives/listen-to-activate.ts} +8 -3
  12. package/src/declarative-element/directives/listen.directive.ts +206 -0
  13. package/src/declarative-element/directives/mutate.directive.ts +78 -0
  14. package/src/declarative-element/directives/on-dom-created.directive.ts +68 -0
  15. package/src/declarative-element/directives/on-dom-rendered.directive.ts +61 -0
  16. package/src/declarative-element/directives/on-intersect.directive.ts +139 -0
  17. package/src/declarative-element/directives/on-resize.directive.ts +142 -0
  18. package/src/declarative-element/directives/render-async.directive.ts +111 -0
  19. package/{dist/declarative-element/directives/render-if.directive.js → src/declarative-element/directives/render-if.directive.ts} +12 -3
  20. package/{dist/declarative-element/directives/test-id.directive.js → src/declarative-element/directives/test-id.directive.ts} +7 -2
  21. package/{dist/declarative-element/has-declarative-element-parent.js → src/declarative-element/has-declarative-element-parent.ts} +7 -4
  22. package/{dist/declarative-element/is-declarative-element-definition.js → src/declarative-element/is-declarative-element-definition.ts} +28 -11
  23. package/{dist/declarative-element/is-declarative-element.js → src/declarative-element/is-declarative-element.ts} +11 -5
  24. package/src/declarative-element/properties/assign-inputs.ts +30 -0
  25. package/src/declarative-element/properties/css-vars.ts +24 -0
  26. package/src/declarative-element/properties/element-events.ts +161 -0
  27. package/src/declarative-element/properties/host-classes.ts +63 -0
  28. package/{dist/declarative-element/properties/property-proxy.js → src/declarative-element/properties/property-proxy.ts} +58 -21
  29. package/src/declarative-element/properties/string-names.ts +83 -0
  30. package/src/declarative-element/properties/styles.ts +112 -0
  31. package/src/declarative-element/render-callback.ts +196 -0
  32. package/src/declarative-element/wrap-define-element.ts +127 -0
  33. package/{dist/index.d.ts → src/index.ts} +2 -0
  34. package/{dist/lit-exports/base-lit-exports.js → src/lit-exports/base-lit-exports.ts} +10 -1
  35. package/{dist/lit-exports/lit-repeat-fix.d.ts → src/lit-exports/lit-repeat-fix.ts} +45 -16
  36. package/{dist/readme-examples/my-app.element.js → src/readme-examples/my-app.element.ts} +5 -4
  37. package/src/readme-examples/my-custom-action.event.ts +3 -0
  38. package/{dist/readme-examples/my-custom-define.js → src/readme-examples/my-custom-define.ts} +9 -4
  39. package/{dist/readme-examples/my-simple.element.js → src/readme-examples/my-simple.element.ts} +4 -3
  40. package/src/readme-examples/my-with-assignment.element.ts +16 -0
  41. package/{dist/readme-examples/my-with-async-prop.element.js → src/readme-examples/my-with-async-prop.element.ts} +24 -16
  42. package/{dist/readme-examples/my-with-cleanup-callback.element.js → src/readme-examples/my-with-cleanup-callback.element.ts} +5 -4
  43. package/{dist/readme-examples/my-with-css-vars.element.js → src/readme-examples/my-with-css-vars.element.ts} +5 -4
  44. package/src/readme-examples/my-with-custom-events.element.ts +23 -0
  45. package/{dist/readme-examples/my-with-event-listening.element.js → src/readme-examples/my-with-event-listening.element.ts} +10 -9
  46. package/src/readme-examples/my-with-events.element.ts +23 -0
  47. package/{dist/readme-examples/my-with-host-class-definition.element.js → src/readme-examples/my-with-host-class-definition.element.ts} +7 -6
  48. package/{dist/readme-examples/my-with-host-class-usage.element.js → src/readme-examples/my-with-host-class-usage.element.ts} +5 -4
  49. package/src/readme-examples/my-with-inputs.element.ts +13 -0
  50. package/{dist/readme-examples/my-with-on-dom-created.element.js → src/readme-examples/my-with-on-dom-created.element.ts} +7 -6
  51. package/src/readme-examples/my-with-on-resize.element.ts +19 -0
  52. package/src/readme-examples/my-with-render-if.element.ts +15 -0
  53. package/{dist/readme-examples/my-with-styles-and-interpolated-selector.element.js → src/readme-examples/my-with-styles-and-interpolated-selector.element.ts} +6 -5
  54. package/{dist/readme-examples/my-with-styles.element.js → src/readme-examples/my-with-styles.element.ts} +5 -4
  55. package/{dist/readme-examples/my-with-update-state.element.js → src/readme-examples/my-with-update-state.element.ts} +8 -7
  56. package/src/readme-examples/require-declarative-element.ts +3 -0
  57. package/{dist/require-declarative-element.js → src/require-declarative-element.ts} +1 -0
  58. package/{dist/template-transforms/minimal-element-definition.d.ts → src/template-transforms/minimal-element-definition.ts} +19 -7
  59. package/src/template-transforms/nested-mapped-templates.ts +157 -0
  60. package/{dist/template-transforms/template-transform-type.d.ts → src/template-transforms/template-transform-type.ts} +3 -1
  61. package/{dist/template-transforms/transform-template.js → src/template-transforms/transform-template.ts} +70 -22
  62. package/src/template-transforms/vir-css/css-transform.ts +30 -0
  63. package/src/template-transforms/vir-css/vir-css.ts +30 -0
  64. package/src/template-transforms/vir-html/html-interpolation.ts +103 -0
  65. package/src/template-transforms/vir-html/html-transform.ts +149 -0
  66. package/{dist/template-transforms/vir-html/tag-name-keys.js → src/template-transforms/vir-html/tag-name-keys.ts} +1 -1
  67. package/{dist/template-transforms/vir-html/vir-html.js → src/template-transforms/vir-html/vir-html.ts} +13 -5
  68. package/src/typed-event/typed-event.ts +90 -0
  69. package/{dist/util/array.js → src/util/array.ts} +18 -5
  70. package/{dist/util/increment.d.ts → src/util/increment.ts} +24 -5
  71. package/{dist/util/lit-template.js → src/util/lit-template.ts} +30 -10
  72. package/src/util/map-async-value.ts +33 -0
  73. package/dist/declarative-element/custom-tag-name.js +0 -1
  74. package/dist/declarative-element/declarative-element-init.d.ts +0 -56
  75. package/dist/declarative-element/declarative-element-init.js +0 -1
  76. package/dist/declarative-element/declarative-element.d.ts +0 -114
  77. package/dist/declarative-element/declarative-element.js +0 -36
  78. package/dist/declarative-element/define-element.d.ts +0 -41
  79. package/dist/declarative-element/define-element.js +0 -248
  80. package/dist/declarative-element/definition-options.js +0 -9
  81. package/dist/declarative-element/directives/assign.directive.d.ts +0 -24
  82. package/dist/declarative-element/directives/assign.directive.js +0 -34
  83. package/dist/declarative-element/directives/async-prop.d.ts +0 -61
  84. package/dist/declarative-element/directives/attributes.directive.d.ts +0 -30
  85. package/dist/declarative-element/directives/attributes.directive.js +0 -35
  86. package/dist/declarative-element/directives/create-attribute-directive.d.ts +0 -28
  87. package/dist/declarative-element/directives/create-attribute-directive.js +0 -41
  88. package/dist/declarative-element/directives/directive-helpers.d.ts +0 -27
  89. package/dist/declarative-element/directives/directive-helpers.js +0 -37
  90. package/dist/declarative-element/directives/listen-to-activate.d.ts +0 -15
  91. package/dist/declarative-element/directives/listen.directive.d.ts +0 -92
  92. package/dist/declarative-element/directives/listen.directive.js +0 -48
  93. package/dist/declarative-element/directives/mutate.directive.d.ts +0 -38
  94. package/dist/declarative-element/directives/mutate.directive.js +0 -45
  95. package/dist/declarative-element/directives/on-dom-created.directive.d.ts +0 -44
  96. package/dist/declarative-element/directives/on-dom-created.directive.js +0 -51
  97. package/dist/declarative-element/directives/on-dom-rendered.directive.d.ts +0 -41
  98. package/dist/declarative-element/directives/on-dom-rendered.directive.js +0 -45
  99. package/dist/declarative-element/directives/on-intersect.directive.d.ts +0 -64
  100. package/dist/declarative-element/directives/on-intersect.directive.js +0 -89
  101. package/dist/declarative-element/directives/on-resize.directive.d.ts +0 -74
  102. package/dist/declarative-element/directives/on-resize.directive.js +0 -106
  103. package/dist/declarative-element/directives/render-async.directive.d.ts +0 -45
  104. package/dist/declarative-element/directives/render-async.directive.js +0 -33
  105. package/dist/declarative-element/directives/render-if.directive.d.ts +0 -32
  106. package/dist/declarative-element/directives/test-id.directive.d.ts +0 -52
  107. package/dist/declarative-element/has-declarative-element-parent.d.ts +0 -1
  108. package/dist/declarative-element/is-declarative-element-definition.d.ts +0 -17
  109. package/dist/declarative-element/is-declarative-element.d.ts +0 -15
  110. package/dist/declarative-element/properties/assign-inputs.d.ts +0 -1
  111. package/dist/declarative-element/properties/assign-inputs.js +0 -25
  112. package/dist/declarative-element/properties/css-vars.d.ts +0 -16
  113. package/dist/declarative-element/properties/css-vars.js +0 -1
  114. package/dist/declarative-element/properties/element-events.d.ts +0 -65
  115. package/dist/declarative-element/properties/element-events.js +0 -62
  116. package/dist/declarative-element/properties/element-properties.js +0 -1
  117. package/dist/declarative-element/properties/host-classes.d.ts +0 -36
  118. package/dist/declarative-element/properties/host-classes.js +0 -16
  119. package/dist/declarative-element/properties/property-proxy.d.ts +0 -22
  120. package/dist/declarative-element/properties/string-names.d.ts +0 -28
  121. package/dist/declarative-element/properties/string-names.js +0 -40
  122. package/dist/declarative-element/properties/styles.d.ts +0 -51
  123. package/dist/declarative-element/properties/styles.js +0 -41
  124. package/dist/declarative-element/properties/tag-name.js +0 -1
  125. package/dist/declarative-element/render-callback.d.ts +0 -56
  126. package/dist/declarative-element/render-callback.js +0 -27
  127. package/dist/declarative-element/wrap-define-element.d.ts +0 -36
  128. package/dist/declarative-element/wrap-define-element.js +0 -25
  129. package/dist/index.js +0 -42
  130. package/dist/lit-exports/all-lit-exports.js +0 -2
  131. package/dist/lit-exports/base-lit-exports.d.ts +0 -25
  132. package/dist/lit-exports/lit-repeat-fix.js +0 -37
  133. package/dist/readme-examples/my-app.element.d.ts +0 -1
  134. package/dist/readme-examples/my-custom-action.event.d.ts +0 -1
  135. package/dist/readme-examples/my-custom-action.event.js +0 -2
  136. package/dist/readme-examples/my-custom-define.d.ts +0 -4
  137. package/dist/readme-examples/my-simple.element.d.ts +0 -1
  138. package/dist/readme-examples/my-with-assignment.element.d.ts +0 -1
  139. package/dist/readme-examples/my-with-assignment.element.js +0 -15
  140. package/dist/readme-examples/my-with-async-prop.element.d.ts +0 -10
  141. package/dist/readme-examples/my-with-cleanup-callback.element.d.ts +0 -3
  142. package/dist/readme-examples/my-with-css-vars.element.d.ts +0 -1
  143. package/dist/readme-examples/my-with-custom-events.element.d.ts +0 -1
  144. package/dist/readme-examples/my-with-custom-events.element.js +0 -22
  145. package/dist/readme-examples/my-with-event-listening.element.d.ts +0 -3
  146. package/dist/readme-examples/my-with-events.element.d.ts +0 -4
  147. package/dist/readme-examples/my-with-events.element.js +0 -20
  148. package/dist/readme-examples/my-with-host-class-definition.element.d.ts +0 -3
  149. package/dist/readme-examples/my-with-host-class-usage.element.d.ts +0 -1
  150. package/dist/readme-examples/my-with-inputs.element.d.ts +0 -4
  151. package/dist/readme-examples/my-with-inputs.element.js +0 -9
  152. package/dist/readme-examples/my-with-on-dom-created.element.d.ts +0 -1
  153. package/dist/readme-examples/my-with-on-resize.element.d.ts +0 -1
  154. package/dist/readme-examples/my-with-on-resize.element.js +0 -18
  155. package/dist/readme-examples/my-with-render-if.element.d.ts +0 -3
  156. package/dist/readme-examples/my-with-render-if.element.js +0 -11
  157. package/dist/readme-examples/my-with-styles-and-interpolated-selector.element.d.ts +0 -1
  158. package/dist/readme-examples/my-with-styles.element.d.ts +0 -1
  159. package/dist/readme-examples/my-with-update-state.element.d.ts +0 -8
  160. package/dist/readme-examples/require-declarative-element.d.ts +0 -1
  161. package/dist/readme-examples/require-declarative-element.js +0 -2
  162. package/dist/require-declarative-element.d.ts +0 -14
  163. package/dist/template-transforms/minimal-element-definition.js +0 -19
  164. package/dist/template-transforms/nested-mapped-templates.d.ts +0 -6
  165. package/dist/template-transforms/nested-mapped-templates.js +0 -96
  166. package/dist/template-transforms/template-transform-type.js +0 -1
  167. package/dist/template-transforms/transform-template.d.ts +0 -14
  168. package/dist/template-transforms/vir-css/css-transform.d.ts +0 -4
  169. package/dist/template-transforms/vir-css/css-transform.js +0 -15
  170. package/dist/template-transforms/vir-css/vir-css.d.ts +0 -12
  171. package/dist/template-transforms/vir-css/vir-css.js +0 -21
  172. package/dist/template-transforms/vir-html/html-interpolation.d.ts +0 -42
  173. package/dist/template-transforms/vir-html/html-interpolation.js +0 -1
  174. package/dist/template-transforms/vir-html/html-transform.d.ts +0 -5
  175. package/dist/template-transforms/vir-html/html-transform.js +0 -96
  176. package/dist/template-transforms/vir-html/tag-name-keys.d.ts +0 -7
  177. package/dist/template-transforms/vir-html/vir-html.d.ts +0 -11
  178. package/dist/typed-event/typed-event.d.ts +0 -55
  179. package/dist/typed-event/typed-event.js +0 -50
  180. package/dist/util/array.d.ts +0 -5
  181. package/dist/util/increment.js +0 -1
  182. package/dist/util/lit-template.d.ts +0 -9
  183. package/dist/util/type.js +0 -1
  184. /package/{dist/declarative-element/custom-tag-name.d.ts → src/declarative-element/custom-tag-name.ts} +0 -0
  185. /package/{dist/declarative-element/properties/element-properties.d.ts → src/declarative-element/properties/element-properties.ts} +0 -0
  186. /package/{dist/declarative-element/properties/tag-name.d.ts → src/declarative-element/properties/tag-name.ts} +0 -0
  187. /package/{dist/lit-exports/all-lit-exports.d.ts → src/lit-exports/all-lit-exports.ts} +0 -0
  188. /package/{dist/util/type.d.ts → src/util/type.ts} +0 -0
@@ -1,6 +1,7 @@
1
- import { defineElement } from 'element-vir';
2
- import { html, listen } from '../index.js';
3
- import { MyWithEvents } from './my-with-events.element.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {html, listen} from '../index.js';
3
+ import {MyWithEvents} from './my-with-events.element.js';
4
+
4
5
  export const MyWithEventListening = defineElement()({
5
6
  tagName: 'my-with-event-listening',
6
7
  state() {
@@ -8,16 +9,16 @@ export const MyWithEventListening = defineElement()({
8
9
  myNumber: -1,
9
10
  };
10
11
  },
11
- render({ state, updateState }) {
12
- return html `
12
+ render({state, updateState}) {
13
+ return html`
13
14
  <h1>My App</h1>
14
15
  <${MyWithEvents}
15
16
  ${listen(MyWithEvents.events.logoutClick, () => {
16
- console.info('logout triggered');
17
- })}
17
+ console.info('logout triggered');
18
+ })}
18
19
  ${listen(MyWithEvents.events.randomNumber, (event) => {
19
- updateState({ myNumber: event.detail });
20
- })}
20
+ updateState({myNumber: event.detail});
21
+ })}
21
22
  ></${MyWithEvents}>
22
23
  <span>${state.myNumber}</span>
23
24
  `;
@@ -0,0 +1,23 @@
1
+ import {randomInteger} from '@augment-vir/common';
2
+ import {defineElement} from 'element-vir';
3
+ import {defineElementEvent, html, listen} from '../index.js';
4
+
5
+ export const MyWithEvents = defineElement()({
6
+ tagName: 'my-with-events',
7
+ events: {
8
+ logoutClick: defineElementEvent<void>(),
9
+ randomNumber: defineElementEvent<number>(),
10
+ },
11
+ render({dispatch, events}) {
12
+ return html`
13
+ <button ${listen('click', () => dispatch(new events.logoutClick()))}>log out</button>
14
+ <button
15
+ ${listen('click', () =>
16
+ dispatch(new events.randomNumber(randomInteger({min: 0, max: 1_000_000}))),
17
+ )}
18
+ >
19
+ generate random number
20
+ </button>
21
+ `;
22
+ },
23
+ });
@@ -1,5 +1,6 @@
1
- import { defineElement } from 'element-vir';
2
- import { css, html } from '../index.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {css, html} from '../index.js';
3
+
3
4
  export const MyWithHostClassDefinition = defineElement()({
4
5
  tagName: 'my-with-host-class-definition',
5
6
  state() {
@@ -17,7 +18,7 @@ export const MyWithHostClassDefinition = defineElement()({
17
18
  * This host class will be automatically applied if the given callback is evaluated to true
18
19
  * after a call to render.
19
20
  */
20
- 'my-with-host-class-definition-automatic': ({ state }) => {
21
+ 'my-with-host-class-definition-automatic': ({state}) => {
21
22
  return state.myProp === 'foo';
22
23
  },
23
24
  },
@@ -25,7 +26,7 @@ export const MyWithHostClassDefinition = defineElement()({
25
26
  * Apply styles to the host classes by using a callback for "styles". The callback's argument
26
27
  * contains the host classes defined above in the "hostClasses" property.
27
28
  */
28
- styles: ({ hostClasses }) => css `
29
+ styles: ({hostClasses}) => css`
29
30
  ${hostClasses['my-with-host-class-definition-automatic'].selector} {
30
31
  color: blue;
31
32
  }
@@ -34,8 +35,8 @@ export const MyWithHostClassDefinition = defineElement()({
34
35
  color: red;
35
36
  }
36
37
  `,
37
- render({ state }) {
38
- return html `
38
+ render({state}) {
39
+ return html`
39
40
  ${state.myProp}
40
41
  `;
41
42
  },
@@ -1,10 +1,11 @@
1
- import { defineElement } from 'element-vir';
2
- import { html } from '../index.js';
3
- import { MyWithHostClassDefinition } from './my-with-host-class-definition.element.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {html} from '../index.js';
3
+ import {MyWithHostClassDefinition} from './my-with-host-class-definition.element.js';
4
+
4
5
  export const MyWithHostClassUsage = defineElement()({
5
6
  tagName: 'my-with-host-class-usage',
6
7
  render() {
7
- return html `
8
+ return html`
8
9
  <${MyWithHostClassDefinition}
9
10
  class=${MyWithHostClassDefinition.hostClasses['my-with-host-class-definition-a']}
10
11
  ></${MyWithHostClassDefinition}>
@@ -0,0 +1,13 @@
1
+ import {defineElement, html} from '../index.js';
2
+
3
+ export const MyWithInputs = defineElement<{
4
+ username: string;
5
+ email: string;
6
+ }>()({
7
+ tagName: 'my-with-inputs',
8
+ render({inputs}) {
9
+ return html`
10
+ <span>Hello there ${inputs.username}!</span>
11
+ `;
12
+ },
13
+ });
@@ -1,14 +1,15 @@
1
- import { defineElement } from 'element-vir';
2
- import { html, onDomCreated } from '../index.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {html, onDomCreated} from '../index.js';
3
+
3
4
  export const MyWithOnDomCreated = defineElement()({
4
5
  tagName: 'my-with-on-dom-created',
5
6
  render() {
6
- return html `
7
+ return html`
7
8
  <span
8
9
  ${onDomCreated((element) => {
9
- // logs a span element
10
- console.info(element);
11
- })}
10
+ // logs a span element
11
+ console.info(element);
12
+ })}
12
13
  >
13
14
  Hello there!
14
15
  </span>
@@ -0,0 +1,19 @@
1
+ import {defineElement} from 'element-vir';
2
+ import {html, onResize} from '../index.js';
3
+
4
+ export const MyWithOnResize = defineElement()({
5
+ tagName: 'my-with-on-resize',
6
+ render() {
7
+ return html`
8
+ <span
9
+ ${onResize((entry) => {
10
+ // this will track resizing of this span
11
+ // the entry parameter contains target and contentRect properties
12
+ console.info(entry);
13
+ })}
14
+ >
15
+ Hello there!
16
+ </span>
17
+ `;
18
+ },
19
+ });
@@ -0,0 +1,15 @@
1
+ import {defineElement, html, renderIf} from '../index.js';
2
+
3
+ export const MyWithRenderIf = defineElement<{shouldRender: boolean}>()({
4
+ tagName: 'my-with-render-if',
5
+ render({inputs}) {
6
+ return html`
7
+ ${renderIf(
8
+ inputs.shouldRender,
9
+ html`
10
+ I'm conditionally rendered!
11
+ `,
12
+ )}
13
+ `;
14
+ },
15
+ });
@@ -1,15 +1,16 @@
1
- import { defineElement } from 'element-vir';
2
- import { css, html } from '../index.js';
3
- import { MySimple } from './my-simple.element.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {css, html} from '../index.js';
3
+ import {MySimple} from './my-simple.element.js';
4
+
4
5
  export const MyWithStylesAndInterpolatedSelector = defineElement()({
5
6
  tagName: 'my-with-styles-and-interpolated-selector',
6
- styles: css `
7
+ styles: css`
7
8
  ${MySimple} {
8
9
  background-color: blue;
9
10
  }
10
11
  `,
11
12
  render() {
12
- return html `
13
+ return html`
13
14
  <${MySimple}></${MySimple}>
14
15
  `;
15
16
  },
@@ -1,8 +1,9 @@
1
- import { defineElement } from 'element-vir';
2
- import { css, html } from '../index.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {css, html} from '../index.js';
3
+
3
4
  export const MyWithStyles = defineElement()({
4
5
  tagName: 'my-with-styles',
5
- styles: css `
6
+ styles: css`
6
7
  :host {
7
8
  display: flex;
8
9
  flex-direction: column;
@@ -14,7 +15,7 @@ export const MyWithStyles = defineElement()({
14
15
  }
15
16
  `,
16
17
  render() {
17
- return html `
18
+ return html`
18
19
  <span>Hello there!</span>
19
20
  <span>How are you doing?</span>
20
21
  `;
@@ -1,5 +1,6 @@
1
- import { defineElement } from 'element-vir';
2
- import { html, listen } from '../index.js';
1
+ import {defineElement} from 'element-vir';
2
+ import {html, listen} from '../index.js';
3
+
3
4
  export const MyWithUpdateState = defineElement()({
4
5
  tagName: 'my-with-update-state',
5
6
  state() {
@@ -9,15 +10,15 @@ export const MyWithUpdateState = defineElement()({
9
10
  * Use "as" to create state properties that can be types other than the initial value's
10
11
  * type. This is particularly useful when, as below, the initial value is undefined.
11
12
  */
12
- email: undefined,
13
+ email: undefined as string | undefined,
13
14
  };
14
15
  },
15
- render({ state, updateState }) {
16
- return html `
16
+ render({state, updateState}) {
17
+ return html`
17
18
  <span
18
19
  ${listen('click', () => {
19
- updateState({ username: 'new name!' });
20
- })}
20
+ updateState({username: 'new name!'});
21
+ })}
21
22
  >
22
23
  Hello there ${state.username}!
23
24
  </span>
@@ -0,0 +1,3 @@
1
+ import {requireAllCustomElementsToBeDeclarativeElements} from '../index.js';
2
+
3
+ requireAllCustomElementsToBeDeclarativeElements();
@@ -5,6 +5,7 @@
5
5
  * @category Internal
6
6
  */
7
7
  export let declarativeElementRequired = false;
8
+
8
9
  /**
9
10
  * Calling this requires all custom element children to be declarative elements defined by
10
11
  * element-vir.
@@ -1,5 +1,7 @@
1
- import { type DeclarativeElementDefinitionOptions } from '../declarative-element/definition-options.js';
2
- import { type PropertyInitMapBase } from '../declarative-element/properties/element-properties.js';
1
+ import {check} from '@augment-vir/assert';
2
+ import {type DeclarativeElementDefinitionOptions} from '../declarative-element/definition-options.js';
3
+ import {type PropertyInitMapBase} from '../declarative-element/properties/element-properties.js';
4
+
3
5
  /**
4
6
  * A minimal element definition used for interpolating element definitions into HTML templates with
5
7
  * a more generic type (to prevent insane circular dependencies).
@@ -10,10 +12,9 @@ export type MinimalElementDefinition<TagName extends string = string> = {
10
12
  tagName: TagName;
11
13
  elementOptions?: DeclarativeElementDefinitionOptions | undefined;
12
14
  /** This is used when wrapping interpolated raw tag name strings. */
13
- tagInterpolationKey?: {
14
- tagName: string;
15
- } | undefined;
15
+ tagInterpolationKey?: {tagName: string} | undefined;
16
16
  };
17
+
17
18
  /**
18
19
  * A parent definition of {@link MinimalElementDefinition} with inputs also specified with allows the
19
20
  * `.assign()` method to be used inside of HTML templates.
@@ -30,16 +31,27 @@ export type MinimalDefinitionWithInputs<TagName extends string = string> = {
30
31
  definition: MinimalElementDefinition<TagName>;
31
32
  inputs: PropertyInitMapBase;
32
33
  };
34
+
33
35
  /**
34
36
  * Checks if the input is an instance of {@link MinimalDefinitionWithInputs}.
35
37
  *
36
38
  * @category Internal
37
39
  */
38
- export declare function isMinimalDefinitionWithInputs(value: unknown): value is MinimalDefinitionWithInputs;
40
+ export function isMinimalDefinitionWithInputs(
41
+ value: unknown,
42
+ ): value is MinimalDefinitionWithInputs {
43
+ return (
44
+ check.hasKey(value, '_elementVirIsMinimalDefinitionWithInputs') &&
45
+ !!value._elementVirIsMinimalDefinitionWithInputs
46
+ );
47
+ }
48
+
39
49
  /**
40
50
  * Checks if the input is an object that has a `tagName` property. Used inside of the HTML tagged
41
51
  * template functions for checking if interpolated values should be treated as element tags.
42
52
  *
43
53
  * @category Internal
44
54
  */
45
- export declare function hasTagName(value: unknown): value is MinimalElementDefinition;
55
+ export function hasTagName(value: unknown): value is MinimalElementDefinition {
56
+ return check.hasKey(value, 'tagName') && !!value.tagName && typeof value.tagName === 'string';
57
+ }
@@ -0,0 +1,157 @@
1
+ import {check} from '@augment-vir/assert';
2
+ import {filterMap} from '@augment-vir/common';
3
+ import {hasTagName, isMinimalDefinitionWithInputs} from './minimal-element-definition.js';
4
+ import {type TemplateTransform} from './template-transform-type.js';
5
+
6
+ type WeakMapElementKey = {
7
+ tagName: string;
8
+ };
9
+
10
+ type TemplateAndNested = {
11
+ template: TemplateTransform | undefined;
12
+ nested: NestedTemplatesWeakMap | undefined;
13
+ };
14
+ type NestedTemplatesWeakMap = WeakMap<WeakMapElementKey, TemplateAndNested>;
15
+ type TemplatesWeakMap = WeakMap<TemplateStringsArray, TemplateAndNested>;
16
+
17
+ function extractElementKeys(values: unknown[]): WeakMapElementKey[] {
18
+ return filterMap(
19
+ values,
20
+ (value): WeakMapElementKey | undefined => {
21
+ if (isMinimalDefinitionWithInputs(value)) {
22
+ return value.definition;
23
+ }
24
+ if (hasTagName(value)) {
25
+ return value.tagInterpolationKey || value;
26
+ }
27
+
28
+ return undefined;
29
+ },
30
+ check.isTruthy,
31
+ );
32
+ }
33
+
34
+ /**
35
+ * The transformed templates are written to a map so that we can preserve reference equality between
36
+ * calls. Without maintaining reference equality between html`` calls, lit-element reconstructs all
37
+ * of its children on every render.
38
+ *
39
+ * This is a WeakMap because we only care about the transformed array value as long as the original
40
+ * template array key exists.
41
+ */
42
+ const transformedTemplateStrings: TemplatesWeakMap = new WeakMap();
43
+
44
+ export function getAlreadyMappedTemplate<PossibleValues>(
45
+ templateStringsKey: TemplateStringsArray,
46
+ values: PossibleValues[],
47
+ ) {
48
+ const elementKeys = extractElementKeys(values);
49
+ const nestedValue = getNestedValues(transformedTemplateStrings, [
50
+ templateStringsKey,
51
+ ...elementKeys,
52
+ ]);
53
+ return nestedValue.value?.template;
54
+ }
55
+
56
+ export function setMappedTemplate<PossibleValues>(
57
+ templateStringsKey: TemplateStringsArray,
58
+ values: PossibleValues[],
59
+ valueToSet: TemplateTransform,
60
+ ) {
61
+ const elementKeys = extractElementKeys(values);
62
+ return setNestedValues(
63
+ transformedTemplateStrings,
64
+ [
65
+ templateStringsKey,
66
+ ...elementKeys,
67
+ ],
68
+ valueToSet,
69
+ );
70
+ }
71
+
72
+ function getNestedValues(
73
+ map: TemplatesWeakMap | NestedTemplatesWeakMap,
74
+ keys: (TemplateStringsArray | WeakMapElementKey)[],
75
+ index = 0,
76
+ ): {value: undefined | TemplateAndNested; reason: string} {
77
+ const {currentTemplateAndNested, reason} = getCurrentKeyAndValue(map, keys, index);
78
+ if (!currentTemplateAndNested) {
79
+ return {value: currentTemplateAndNested, reason};
80
+ }
81
+
82
+ if (index === keys.length - 1) {
83
+ return {value: currentTemplateAndNested, reason: `reached end of keys array`};
84
+ }
85
+
86
+ if (!currentTemplateAndNested.nested) {
87
+ return {value: undefined, reason: `map at key index ${index} did not have nested maps`};
88
+ }
89
+
90
+ return getNestedValues(currentTemplateAndNested.nested, keys, index + 1);
91
+ }
92
+
93
+ function getCurrentKeyAndValue(
94
+ map: TemplatesWeakMap | NestedTemplatesWeakMap,
95
+ keys: (TemplateStringsArray | WeakMapElementKey)[],
96
+ index: number,
97
+ ): {
98
+ currentKey: TemplateStringsArray | WeakMapElementKey | undefined;
99
+ currentTemplateAndNested: TemplateAndNested | undefined;
100
+ reason: string;
101
+ } {
102
+ const currentKey = keys[index];
103
+ if (currentKey == undefined) {
104
+ return {
105
+ currentKey: undefined,
106
+ currentTemplateAndNested: undefined,
107
+ reason: `key at index ${index} not found`,
108
+ };
109
+ }
110
+ if (!map.has(currentKey as any)) {
111
+ return {
112
+ currentKey,
113
+ currentTemplateAndNested: undefined,
114
+ reason: `key at index ${index} was not in the map`,
115
+ };
116
+ }
117
+ const currentTemplateAndNested = map.get(currentKey as any);
118
+ if (currentTemplateAndNested == undefined) {
119
+ return {
120
+ currentKey,
121
+ currentTemplateAndNested: undefined,
122
+ reason: `value at key at index ${index} was undefined`,
123
+ };
124
+ }
125
+
126
+ return {currentKey, currentTemplateAndNested, reason: `key and value exists`};
127
+ }
128
+
129
+ function setNestedValues(
130
+ map: TemplatesWeakMap | NestedTemplatesWeakMap,
131
+ keys: (TemplateStringsArray | WeakMapElementKey)[],
132
+ valueToSet: TemplateTransform,
133
+ index = 0,
134
+ ): {result: boolean; reason: string} {
135
+ const {currentTemplateAndNested, currentKey, reason} = getCurrentKeyAndValue(map, keys, index);
136
+ if (!currentKey) {
137
+ return {result: false, reason};
138
+ }
139
+
140
+ const nestedAndTemplate = currentTemplateAndNested ?? {nested: undefined, template: undefined};
141
+ if (!currentTemplateAndNested) {
142
+ map.set(currentKey as any, nestedAndTemplate);
143
+ }
144
+
145
+ if (index === keys.length - 1) {
146
+ nestedAndTemplate.template = valueToSet;
147
+ return {result: true, reason: `set value at end of keys array`};
148
+ }
149
+
150
+ const nestedWeakMap = nestedAndTemplate.nested ?? new WeakMap();
151
+
152
+ if (!nestedAndTemplate.nested) {
153
+ nestedAndTemplate.nested = nestedWeakMap;
154
+ }
155
+
156
+ return setNestedValues(nestedWeakMap, keys, valueToSet, index + 1);
157
+ }
@@ -1,8 +1,10 @@
1
- import { type ArrayInsertion } from '../util/array.js';
1
+ import {type ArrayInsertion} from '../util/array.js';
2
+
2
3
  export type AllValueTransforms = {
3
4
  valueIndexDeletions: number[];
4
5
  valueInsertions: ArrayInsertion<unknown>[];
5
6
  };
7
+
6
8
  export type TemplateTransform = {
7
9
  templateStrings: TemplateStringsArray;
8
10
  valuesTransform(values: unknown[]): AllValueTransforms;
@@ -1,36 +1,78 @@
1
- import { insertAndRemoveValues } from '../util/array.js';
2
- import { getAlreadyMappedTemplate, setMappedTemplate } from './nested-mapped-templates.js';
3
- export function getTransformedTemplate(templateStringsKey, values, fallbackTransform) {
1
+ import {type ArrayInsertion, insertAndRemoveValues} from '../util/array.js';
2
+ import {getAlreadyMappedTemplate, setMappedTemplate} from './nested-mapped-templates.js';
3
+ import {type AllValueTransforms, type TemplateTransform} from './template-transform-type.js';
4
+
5
+ export type ValueInsertion = {
6
+ index: number;
7
+ value: unknown;
8
+ };
9
+
10
+ export type ValueTransformCallback = (
11
+ lastNewString: string,
12
+ currentLitString: string,
13
+ currentValue: unknown,
14
+ ) =>
15
+ | {
16
+ replacement: unknown;
17
+ getExtraValues: ((currentValue: unknown) => unknown[]) | undefined;
18
+ }
19
+ | undefined;
20
+
21
+ export function getTransformedTemplate<PossibleValues>(
22
+ templateStringsKey: TemplateStringsArray,
23
+ values: PossibleValues[],
24
+ fallbackTransform: () => TemplateTransform,
25
+ ) {
4
26
  const alreadyTransformedTemplateStrings = getAlreadyMappedTemplate(templateStringsKey, values);
5
- const templateTransform = alreadyTransformedTemplateStrings ?? fallbackTransform();
27
+
28
+ const templateTransform: TemplateTransform =
29
+ alreadyTransformedTemplateStrings ?? fallbackTransform();
30
+
6
31
  if (!alreadyTransformedTemplateStrings) {
7
32
  const result = setMappedTemplate(templateStringsKey, values, templateTransform);
8
33
  if (!result.result) {
9
34
  throw new Error(`Failed to set template transform: ${result.reason}`);
10
35
  }
11
36
  }
37
+
12
38
  const valueTransforms = templateTransform.valuesTransform(values);
13
- const transformedValuesArray = insertAndRemoveValues(values, valueTransforms.valueInsertions, valueTransforms.valueIndexDeletions);
39
+
40
+ const transformedValuesArray: PossibleValues[] = insertAndRemoveValues(
41
+ values,
42
+ valueTransforms.valueInsertions,
43
+ valueTransforms.valueIndexDeletions,
44
+ ) as PossibleValues[];
45
+
14
46
  return {
15
47
  strings: templateTransform.templateStrings,
16
48
  values: transformedValuesArray,
17
49
  };
18
50
  }
19
- export function transformTemplate(inputTemplateStrings, inputValues, transformValue, assertValidString) {
20
- const newStrings = [];
21
- const newRaws = [];
22
- const valueIndexDeletions = [];
23
- const valueTransforms = [];
51
+
52
+ export function transformTemplate<PossibleValues>(
53
+ inputTemplateStrings: TemplateStringsArray,
54
+ inputValues: PossibleValues[],
55
+ transformValue: ValueTransformCallback,
56
+ assertValidString?: (templateStringPart: string) => void,
57
+ ): TemplateTransform {
58
+ const newStrings: string[] = [];
59
+ const newRaws: string[] = [];
60
+ const valueIndexDeletions: AllValueTransforms['valueIndexDeletions'] = [];
61
+ const valueTransforms: ((values: unknown[]) => ArrayInsertion<unknown>)[] = [];
62
+
24
63
  inputTemplateStrings.forEach((currentTemplateString, currentTemplateStringIndex) => {
25
64
  const lastNewStringsIndex = newStrings.length - 1;
26
65
  const lastNewString = newStrings[lastNewStringsIndex];
27
66
  const currentValueIndex = currentTemplateStringIndex - 1;
28
67
  const currentValue = inputValues[currentValueIndex];
68
+
29
69
  if (assertValidString) {
30
70
  assertValidString(currentTemplateString);
31
71
  }
32
- let transformOutput = undefined;
33
- let extraValues = [];
72
+
73
+ let transformOutput: ReturnType<ValueTransformCallback> | undefined = undefined;
74
+ let extraValues: unknown[] = [];
75
+
34
76
  if (typeof lastNewString === 'string') {
35
77
  transformOutput = transformValue(lastNewString, currentTemplateString, currentValue);
36
78
  if (transformOutput) {
@@ -41,6 +83,7 @@ export function transformTemplate(inputTemplateStrings, inputValues, transformVa
41
83
  valueIndexDeletions.push(currentValueIndex);
42
84
  const getExtraValuesCallback = transformOutput.getExtraValues;
43
85
  extraValues = getExtraValuesCallback ? getExtraValuesCallback(currentValue) : [];
86
+
44
87
  if (extraValues.length && getExtraValuesCallback) {
45
88
  newStrings[lastNewStringsIndex] += ' ';
46
89
  extraValues.forEach((value, index) => {
@@ -49,7 +92,7 @@ export function transformTemplate(inputTemplateStrings, inputValues, transformVa
49
92
  newStrings.push(' ');
50
93
  }
51
94
  });
52
- valueTransforms.push((values) => {
95
+ valueTransforms.push((values): ArrayInsertion<unknown> => {
53
96
  const latestCurrentValue = values[currentValueIndex];
54
97
  const insertions = getExtraValuesCallback(latestCurrentValue);
55
98
  return {
@@ -58,21 +101,22 @@ export function transformTemplate(inputTemplateStrings, inputValues, transformVa
58
101
  };
59
102
  });
60
103
  newStrings.push(currentTemplateString);
61
- }
62
- else {
104
+ } else {
63
105
  newStrings[lastNewStringsIndex] += currentTemplateString;
64
106
  }
65
107
  }
66
108
  }
109
+
67
110
  if (!transformOutput) {
68
111
  newStrings.push(currentTemplateString);
69
112
  }
113
+
70
114
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
71
- const currentRawLitString = inputTemplateStrings.raw[currentTemplateStringIndex];
115
+ const currentRawLitString = inputTemplateStrings.raw[currentTemplateStringIndex]!;
72
116
  if (transformOutput) {
73
117
  newRaws[lastNewStringsIndex] = [
74
118
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
75
- newRaws[lastNewStringsIndex],
119
+ newRaws[lastNewStringsIndex]!,
76
120
  transformOutput.replacement,
77
121
  currentRawLitString,
78
122
  ].join('');
@@ -81,18 +125,22 @@ export function transformTemplate(inputTemplateStrings, inputValues, transformVa
81
125
  newRaws.push('');
82
126
  });
83
127
  }
84
- }
85
- else {
128
+ } else {
86
129
  newRaws.push(currentRawLitString);
87
130
  }
88
131
  });
89
- const newTemplateStrings = Object.assign([], newStrings, {
132
+
133
+ const newTemplateStrings: TemplateStringsArray = Object.assign([], newStrings, {
90
134
  raw: newRaws,
91
135
  });
136
+
92
137
  return {
93
138
  templateStrings: newTemplateStrings,
94
- valuesTransform(values) {
95
- const insertions = valueTransforms.flatMap((transformCallback) => transformCallback(values));
139
+ valuesTransform(values): AllValueTransforms {
140
+ const insertions: ArrayInsertion<unknown>[] = valueTransforms.flatMap(
141
+ (transformCallback) => transformCallback(values),
142
+ );
143
+
96
144
  return {
97
145
  valueIndexDeletions,
98
146
  valueInsertions: insertions,