element-vir 6.2.1 → 6.3.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 CHANGED
@@ -43,7 +43,7 @@ Use `defineElementNoInputs` to define your element if it's not going to accept a
43
43
  import {defineElementNoInputs, html} from 'element-vir';
44
44
 
45
45
  export const MySimpleElement = defineElementNoInputs({
46
- tagName: 'my-simple-element',
46
+ tagName: 'my-simple',
47
47
  renderCallback: () => html`
48
48
  <span>Hello there!</span>
49
49
  `,
@@ -63,7 +63,7 @@ import {defineElementNoInputs, html} from 'element-vir';
63
63
  import {MySimpleElement} from './my-simple.element';
64
64
 
65
65
  export const MyAppElement = defineElementNoInputs({
66
- tagName: 'my-app-element',
66
+ tagName: 'my-app',
67
67
  renderCallback: () => html`
68
68
  <h1>My App</h1>
69
69
  <${MySimpleElement}></${MySimpleElement}>
@@ -79,13 +79,13 @@ If you wish to bypass this interpolation, make sure to [import the `html` tagged
79
79
 
80
80
  Styles are added through the `styles` property when defining a declarative element (similar to [how they are defined in `lit`](https://lit.dev/docs/components/styles/)):
81
81
 
82
- <!-- example-link: src/readme-examples/my-simple-app-with-styles.element.ts -->
82
+ <!-- example-link: src/readme-examples/my-with-styles.element.ts -->
83
83
 
84
84
  ```TypeScript
85
85
  import {css, defineElementNoInputs, html} from 'element-vir';
86
86
 
87
- export const MySimpleWithStylesElement = defineElementNoInputs({
88
- tagName: 'my-simple-with-styles-element',
87
+ export const MyWithStylesElement = defineElementNoInputs({
88
+ tagName: 'my-with-styles',
89
89
  styles: css`
90
90
  :host {
91
91
  display: flex;
@@ -108,14 +108,14 @@ export const MySimpleWithStylesElement = defineElementNoInputs({
108
108
 
109
109
  Declarative element definitions can be used in the `css` tagged template just like in the `html` tagged template. This will be replaced by the element's tag name:
110
110
 
111
- <!-- example-link: src/readme-examples/my-simple-app-with-styles-and-interpolated-selector.element.ts -->
111
+ <!-- example-link: src/readme-examples/my-with-styles-and-interpolated-selector.element.ts -->
112
112
 
113
113
  ```TypeScript
114
114
  import {css, defineElementNoInputs, html} from 'element-vir';
115
115
  import {MySimpleElement} from './my-simple.element';
116
116
 
117
- export const MySimpleWithStylesAndInterpolatedSelectorElement = defineElementNoInputs({
118
- tagName: 'my-simple-with-styles-and-interpolated-selector-element',
117
+ export const MyWithStylesAndInterpolatedSelectorElement = defineElementNoInputs({
118
+ tagName: 'my-with-styles-and-interpolated-selector',
119
119
  styles: css`
120
120
  ${MySimpleElement} {
121
121
  background-color: blue;
@@ -133,16 +133,16 @@ Define element inputs by using `defineElement` to define a declarative element.
133
133
 
134
134
  To use an element's inputs for use in its template, grab `inputs` from `renderCallback`'s parameters and interpolate it into your HTML template:
135
135
 
136
- <!-- example-link: src/readme-examples/my-simple-with-inputs.element.ts -->
136
+ <!-- example-link: src/readme-examples/my-with-inputs.element.ts -->
137
137
 
138
138
  ```TypeScript
139
139
  import {defineElement, html} from 'element-vir';
140
140
 
141
- export const MySimpleWithInputsElement = defineElement<{
141
+ export const MyWithInputsElement = defineElement<{
142
142
  username: string;
143
143
  email: string;
144
144
  }>()({
145
- tagName: 'my-simple-element-with-inputs',
145
+ tagName: 'my-with-inputs',
146
146
  renderCallback: ({inputs}) => html`
147
147
  <span>Hello there ${inputs.username}!</span>
148
148
  `,
@@ -153,13 +153,13 @@ export const MySimpleWithInputsElement = defineElement<{
153
153
 
154
154
  Define internal state with the `stateInit` property when defining an element. Grab it with `state` in `renderCallback` to use state. Grab `updateState` in `renderCallback` to update state:
155
155
 
156
- <!-- example-link: src/readme-examples/my-simple-with-update-state.element.ts -->
156
+ <!-- example-link: src/readme-examples/my-with-update-state.element.ts -->
157
157
 
158
158
  ```TypeScript
159
159
  import {defineElementNoInputs, html, listen} from 'element-vir';
160
160
 
161
- export const MySimpleWithUpdateStateElement = defineElementNoInputs({
162
- tagName: 'my-simple-element-with-update-state',
161
+ export const MyWithUpdateStateElement = defineElementNoInputs({
162
+ tagName: 'my-with-update-state',
163
163
  stateInit: {
164
164
  username: 'dev',
165
165
  email: undefined as string | undefined,
@@ -180,23 +180,23 @@ export const MySimpleWithUpdateStateElement = defineElementNoInputs({
180
180
 
181
181
  Use the `assign` directive to assign properties to child custom elements:
182
182
 
183
- <!-- example-link: src/readme-examples/my-app-with-assignment.element.ts -->
183
+ <!-- example-link: src/readme-examples/my-with-assignment.element.ts -->
184
184
 
185
185
  ```TypeScript
186
186
  import {assign, defineElementNoInputs, html} from 'element-vir';
187
- import {MySimpleWithInputsElement} from './my-simple-with-inputs.element';
187
+ import {MyWithInputsElement} from './my-with-inputs.element';
188
188
 
189
- export const MyAppWithAssignmentElement = defineElementNoInputs({
190
- tagName: 'my-app-with-assignment-element',
189
+ export const MyWithAssignmentElement = defineElementNoInputs({
190
+ tagName: 'my-with-assignment',
191
191
  renderCallback: () => html`
192
192
  <h1>My App</h1>
193
- <${MySimpleWithInputsElement}
194
- ${assign(MySimpleWithInputsElement, {
193
+ <${MyWithInputsElement}
194
+ ${assign(MyWithInputsElement, {
195
195
  email: 'user@example.com',
196
196
  username: 'user',
197
197
  })}
198
198
  >
199
- </${MySimpleWithInputsElement}>
199
+ </${MyWithInputsElement}>
200
200
  `,
201
201
  });
202
202
  ```
@@ -208,13 +208,13 @@ There are two other callbacks you can define that are sort of similar to lifecyc
208
208
  - `initCallback`: called right before the first render, has all state and inputs setup.
209
209
  - `cleanupCallback`: called when an element is removed from the DOM. (This is the same as the `disconnectedCallback` in standard HTMLElement classes.)
210
210
 
211
- <!-- example-link: src/readme-examples/my-app-with-cleanup-callback.element.ts -->
211
+ <!-- example-link: src/readme-examples/my-with-cleanup-callback.element.ts -->
212
212
 
213
213
  ```TypeScript
214
214
  import {defineElementNoInputs, html} from 'element-vir';
215
215
 
216
- export const MyAppWithAssignmentCleanupCallbackElement = defineElementNoInputs({
217
- tagName: 'my-app-with-cleanup-callback',
216
+ export const MyWithAssignmentCleanupCallbackElement = defineElementNoInputs({
217
+ tagName: 'my-with-cleanup-callback',
218
218
  stateInit: {
219
219
  intervalId: undefined as undefined | number,
220
220
  },
@@ -241,13 +241,13 @@ Define events with `events` when defining a declarative element. Each event must
241
241
 
242
242
  To dispatch an event, grab `dispatch` from `renderCallback`'s parameters.
243
243
 
244
- <!-- example-link: src/readme-examples/my-simple-with-events.element.ts -->
244
+ <!-- example-link: src/readme-examples/my-with-events.element.ts -->
245
245
 
246
246
  ```TypeScript
247
247
  import {defineElementEvent, defineElementNoInputs, html, listen} from 'element-vir';
248
248
 
249
- export const MySimpleWithEventsElement = defineElementNoInputs({
250
- tagName: 'my-simple-element-with-events',
249
+ export const MyWithEventsElement = defineElementNoInputs({
250
+ tagName: 'my-with-events',
251
251
  events: {
252
252
  logoutClick: defineElementEvent<void>(),
253
253
  randomNumber: defineElementEvent<number>(),
@@ -267,29 +267,24 @@ export const MySimpleWithEventsElement = defineElementNoInputs({
267
267
 
268
268
  Use the `listen` directive to listen to typed events emitted by your custom elements:
269
269
 
270
- <!-- example-link: src/readme-examples/my-app-with-events.element.ts -->
270
+ <!-- example-link: src/readme-examples/my-with-events.element.ts -->
271
271
 
272
272
  ```TypeScript
273
- import {defineElementNoInputs, html, listen} from 'element-vir';
274
- import {MySimpleWithEventsElement} from './my-simple-with-events.element';
273
+ import {defineElementEvent, defineElementNoInputs, html, listen} from 'element-vir';
275
274
 
276
- export const MyAppWithEventsElement = defineElementNoInputs({
277
- tagName: 'my-app-with-events-element',
278
- stateInit: {
279
- myNumber: -1,
275
+ export const MyWithEventsElement = defineElementNoInputs({
276
+ tagName: 'my-with-events',
277
+ events: {
278
+ logoutClick: defineElementEvent<void>(),
279
+ randomNumber: defineElementEvent<number>(),
280
280
  },
281
- renderCallback: ({state, updateState}) => html`
282
- <h1>My App</h1>
283
- <${MySimpleWithEventsElement}
284
- ${listen(MySimpleWithEventsElement.events.logoutClick, () => {
285
- console.info('logout triggered');
286
- })}
287
- ${listen(MySimpleWithEventsElement.events.randomNumber, (event) => {
288
- updateState({myNumber: event.detail});
289
- })}
290
- >
291
- </${MySimpleWithEventsElement}>
292
- <span>${state.myNumber}</span>
281
+ renderCallback: ({dispatch, events}) => html`
282
+ <button ${listen('click', () => dispatch(new events.logoutClick(undefined)))}>
283
+ log out
284
+ </button>
285
+ <button ${listen('click', () => dispatch(new events.randomNumber(Math.random())))}>
286
+ generate random number
287
+ </button>
293
288
  `,
294
289
  });
295
290
  ```
@@ -302,35 +297,35 @@ Create a custom event type with `defineTypedEvent`. Make sure to include the typ
302
297
 
303
298
  ### Creating a typed event
304
299
 
305
- <!-- example-link: src/readme-examples/custom-event-no-element.ts -->
300
+ <!-- example-link: src/readme-examples/my-custom-action.event.ts -->
306
301
 
307
302
  ```TypeScript
308
303
  import {defineTypedEvent} from 'element-vir';
309
304
 
310
- export const MyCustomEvent = defineTypedEvent<number>()('myCustomEventName');
305
+ export const MyCustomActionEvent = defineTypedEvent<number>()('my-custom-action');
311
306
  ```
312
307
 
313
308
  ### Using a typed event
314
309
 
315
310
  Both dispatching a custom event and listening to a custom event:
316
311
 
317
- <!-- example-link: src/readme-examples/custom-event-usage.element.ts -->
312
+ <!-- example-link: src/readme-examples/my-with-custom-events.element.ts -->
318
313
 
319
314
  ```TypeScript
320
315
  import {defineElementNoInputs, html, listen} from 'element-vir';
321
- import {MyCustomEvent} from './custom-event-no-element';
316
+ import {MyCustomActionEvent} from './my-custom-action.event';
322
317
 
323
- export const MyElementWithCustomEvents = defineElementNoInputs({
324
- tagName: 'my-app-with-custom-events',
318
+ export const MyWithCustomEventsElement = defineElementNoInputs({
319
+ tagName: 'my-with-custom-events',
325
320
  renderCallback: ({genericDispatch}) => html`
326
321
  <div
327
- ${listen(MyCustomEvent, (event) => {
322
+ ${listen(MyCustomActionEvent, (event) => {
328
323
  console.info(`Got a number! ${event.detail}`);
329
324
  })}
330
325
  >
331
326
  <div
332
327
  ${listen('click', () => {
333
- genericDispatch(new MyCustomEvent(Math.random()));
328
+ genericDispatch(new MyCustomActionEvent(Math.random()));
334
329
  })}
335
330
  ></div>
336
331
  </div>
@@ -340,19 +335,21 @@ export const MyElementWithCustomEvents = defineElementNoInputs({
340
335
 
341
336
  ## Host classes
342
337
 
338
+ ### Defining host classes
339
+
343
340
  Host classes can be defined and used with type safety. Host classes are used to provide alternative styles for components. They are purely driven by CSS and are thus applied via the `class` HTML attribute.
344
341
 
345
342
  Host classes that are defined with a callback will automatically get applied if that callback returns true after a render is executed. These are executed _after_ `renderCallback` is executed. When a definition is set to `false`, it's left to the element's consumer to apply the host class.
346
343
 
347
344
  Apply host classes in the element's stylesheet by using a callback for the styles property.
348
345
 
349
- <!-- example-link: src/readme-examples/host-class-definition.ts -->
346
+ <!-- example-link: src/readme-examples/my-with-host-class-definition.element.ts -->
350
347
 
351
348
  ```TypeScript
352
349
  import {css, defineElementNoInputs, html} from 'element-vir';
353
350
 
354
- export const MyAppWithHostClasses = defineElementNoInputs({
355
- tagName: 'my-app-with-host-classes',
351
+ export const MyWithHostClassDefinitionElement = defineElementNoInputs({
352
+ tagName: 'my-with-host-class-definition',
356
353
  stateInit: {
357
354
  myProp: 'hello there',
358
355
  },
@@ -375,7 +372,7 @@ export const MyAppWithHostClasses = defineElementNoInputs({
375
372
  * Apply styles to the host classes by using a callback for "styles". The callback's argument
376
373
  * contains the host classes defined above in the "hostClasses" property.
377
374
  */
378
- styles: ({hostClass}) => css`
375
+ styles: ({hostClassSelectors: hostClass}) => css`
379
376
  ${hostClass.automaticallyAppliedVariation} {
380
377
  color: blue;
381
378
  }
@@ -390,17 +387,37 @@ export const MyAppWithHostClasses = defineElementNoInputs({
390
387
  });
391
388
  ```
392
389
 
390
+ ### Applying host classes
391
+
392
+ To apply a host class in a parent element, access the child element's `.hostClasses` property:
393
+
394
+ <!-- example-link: src/readme-examples/my-with-host-class-usage.element.ts -->
395
+
396
+ ```TypeScript
397
+ import {defineElementNoInputs, html} from 'element-vir';
398
+ import {MyWithHostClassDefinitionElement} from './my-with-host-class-definition.element';
399
+
400
+ export const MyWithHostClassUsageElement = defineElementNoInputs({
401
+ tagName: 'my-with-host-class-usage',
402
+ renderCallback: () => html`
403
+ <${MyWithHostClassDefinitionElement}
404
+ class=${MyWithHostClassDefinitionElement.hostClasses.styleVariationA}
405
+ ></${MyWithHostClassDefinitionElement}>
406
+ `,
407
+ });
408
+ ```
409
+
393
410
  ## CSS Vars
394
411
 
395
412
  Typed CSS vars are created in a similar way as host classes:
396
413
 
397
- <!-- example-link: src/readme-examples/css-vars-definition.ts -->
414
+ <!-- example-link: src/readme-examples/my-with-css-vars.element.ts -->
398
415
 
399
416
  ```TypeScript
400
417
  import {css, defineElementNoInputs, html} from 'element-vir';
401
418
 
402
- export const MyAppWithCssVars = defineElementNoInputs({
403
- tagName: 'my-app-with-css-vars',
419
+ export const MyWithCssVarsElement = defineElementNoInputs({
420
+ tagName: 'my-with-css-vars',
404
421
  cssVars: {
405
422
  /**
406
423
  * The value assigned here ('blue') becomes the fallback value for this CSS var when used
@@ -408,7 +425,7 @@ export const MyAppWithCssVars = defineElementNoInputs({
408
425
  */
409
426
  myCssVar: 'blue',
410
427
  },
411
- styles: ({cssVarName, cssVarValue}) => css`
428
+ styles: ({cssVarNames: cssVarName, cssVarValues: cssVarValue}) => css`
412
429
  :host {
413
430
  /* Set CSS vars (or reference the name directly) via "cssVarName" */
414
431
  ${cssVarName.myCssVar}: yellow;
@@ -430,13 +447,13 @@ This directive should be used instead of trying to use `querySelector` directly
430
447
 
431
448
  This triggers only once when the element it's attached has actually been created in the DOM. If it's attached element changes, the callback will be triggered again.
432
449
 
433
- <!-- example-link: src/readme-examples/my-simple-with-on-dom-created.element.ts -->
450
+ <!-- example-link: src/readme-examples/my-with-on-dom-created.element.ts -->
434
451
 
435
452
  ```TypeScript
436
453
  import {defineElementNoInputs, html, onDomCreated} from 'element-vir';
437
454
 
438
- export const MySimpleWithOnDomCreatedElement = defineElementNoInputs({
439
- tagName: 'my-simple-with-on-dom-created-element',
455
+ export const MyWithOnDomCreatedElement = defineElementNoInputs({
456
+ tagName: 'my-with-on-dom-created',
440
457
  renderCallback: () => html`
441
458
  <span
442
459
  ${onDomCreated((element) => {
@@ -454,13 +471,13 @@ export const MySimpleWithOnDomCreatedElement = defineElementNoInputs({
454
471
 
455
472
  This directive fulfills a common use case of triggering callbacks when something resizes. Instead of just tracking the _globally_ resizing window though, this allows you to track resizes of an individual element. The callback here is passed an object with a portion of the [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) properties (since not all properties are supported well in browsers).
456
473
 
457
- <!-- example-link: src/readme-examples/my-simple-with-on-resize.element.ts -->
474
+ <!-- example-link: src/readme-examples/my-with-on-resize.element.ts -->
458
475
 
459
476
  ```TypeScript
460
477
  import {defineElementNoInputs, html, onResize} from 'element-vir';
461
478
 
462
- export const MySimpleWithOnResizeElement = defineElementNoInputs({
463
- tagName: 'my-simple-with-on-dom-created-element',
479
+ export const MyWithOnResizeElement = defineElementNoInputs({
480
+ tagName: 'my-with-on-resize',
464
481
  renderCallback: () => html`
465
482
  <span
466
483
  ${onResize((entry) => {
@@ -487,19 +504,19 @@ Listen to a specific event emitted from a custom element. This is explained in t
487
504
 
488
505
  This directive is the same as the `assign` directive but it accepts an additional `cleanupCallback` input. Use this directive to assign values which need some kind of cleanup when they're overwritten. For example, a 3D rendering engine which uses the canvas that should free up memory when it's swapped out.
489
506
 
490
- <!-- example-link: src/readme-examples/my-app-with-cleanup.element.ts -->
507
+ <!-- example-link: src/readme-examples/my-with-cleanup.element.ts -->
491
508
 
492
509
  ```TypeScript
493
510
  import {assignWithCleanup, defineElementNoInputs, html} from 'element-vir';
494
- import {MySimpleWithInputsElement} from './my-simple-with-inputs.element';
511
+ import {MyWithInputsElement} from './my-with-inputs.element';
495
512
 
496
- export const MyAppWithAssignmentCleanupElement = defineElementNoInputs({
497
- tagName: 'my-app-with-cleanup',
513
+ export const MyWithCleanupElement = defineElementNoInputs({
514
+ tagName: 'my-with-cleanup',
498
515
  renderCallback: () => html`
499
516
  <h1>My App</h1>
500
- <${MySimpleWithInputsElement}
517
+ <${MyWithInputsElement}
501
518
  ${assignWithCleanup(
502
- MySimpleWithInputsElement,
519
+ MyWithInputsElement,
503
520
  {
504
521
  email: 'user@example.com',
505
522
  username: 'user',
@@ -512,7 +529,7 @@ export const MyAppWithAssignmentCleanupElement = defineElementNoInputs({
512
529
  },
513
530
  )}
514
531
  >
515
- </${MySimpleWithInputsElement}>
532
+ </${MyWithInputsElement}>
516
533
  `,
517
534
  });
518
535
  ```
@@ -3,9 +3,10 @@ import { CssVarNameOrValueMap } from './css-vars';
3
3
  import { PropertyInitMapBase } from './element-properties';
4
4
  import { HostClassesInitMap, HostClassNamesMap } from './host-classes';
5
5
  export declare type StylesCallbackInput<HostClassKeys extends string, CssVarKeys extends string> = {
6
- hostClass: Record<HostClassKeys, CSSResult>;
7
- cssVarName: Record<CssVarKeys, CSSResult>;
8
- cssVarValue: Record<CssVarKeys, CSSResult>;
6
+ hostClassSelectors: Record<HostClassKeys, CSSResult>;
7
+ hostClassNames: Record<HostClassKeys, CSSResult>;
8
+ cssVarNames: Record<CssVarKeys, CSSResult>;
9
+ cssVarValues: Record<CssVarKeys, CSSResult>;
9
10
  };
10
11
  export declare type StylesCallback<HostClassKeys extends string, CssVarKeys extends string> = (input: StylesCallbackInput<HostClassKeys, CssVarKeys>) => CSSResult;
11
12
  export declare function hostClassNamesToStylesInput<HostClassKeys extends string, CssVarKeys extends string>({ hostClassNames, cssVarNames, cssVarValues, }: {
@@ -2,11 +2,14 @@ import { getObjectTypedKeys, mapObject } from 'augment-vir';
2
2
  import { unsafeCSS } from 'lit';
3
3
  export function hostClassNamesToStylesInput({ hostClassNames, cssVarNames, cssVarValues, }) {
4
4
  return {
5
- hostClass: mapObject(hostClassNames, (key, name) => {
5
+ hostClassSelectors: mapObject(hostClassNames, (key, name) => {
6
6
  return unsafeCSS(`:host(.${name})`);
7
7
  }),
8
- cssVarName: cssVarNames,
9
- cssVarValue: cssVarValues,
8
+ hostClassNames: mapObject(hostClassNames, (key, name) => {
9
+ return unsafeCSS(name);
10
+ }),
11
+ cssVarNames: cssVarNames,
12
+ cssVarValues: cssVarValues,
10
13
  };
11
14
  }
12
15
  export function applyHostClasses({ host, hostClassesInit, hostClassNames, state, inputs, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "element-vir",
3
- "version": "6.2.1",
3
+ "version": "6.3.0",
4
4
  "keywords": [
5
5
  "custom",
6
6
  "web",
@@ -41,7 +41,7 @@
41
41
  "test:web": "virmator test-web"
42
42
  },
43
43
  "dependencies": {
44
- "augment-vir": "^3.0.4",
44
+ "augment-vir": "^3.0.6",
45
45
  "lit": "2.4.0"
46
46
  },
47
47
  "devDependencies": {
@@ -55,7 +55,7 @@
55
55
  "@web/test-runner-playwright": "^0.9.0",
56
56
  "ansi-colors": "^4.1.3",
57
57
  "chai": "^4.3.6",
58
- "cspell": "^6.12.0",
58
+ "cspell": "^6.13.3",
59
59
  "istanbul-smart-text-reporter": "^0.0.1",
60
60
  "markdown-code-example-inserter": "^0.1.11",
61
61
  "mocha": "^10.1.0",
@@ -69,7 +69,7 @@
69
69
  "prettier-plugin-sort-json": "^0.0.3",
70
70
  "prettier-plugin-toml": "^0.3.1",
71
71
  "ts-node": "^10.9.1",
72
- "virmator": "^4.2.13",
73
- "vite": "^3.2.0"
72
+ "virmator": "^4.2.14",
73
+ "vite": "^3.2.2"
74
74
  }
75
75
  }