From c4e39746651fbf796ee730c20d3e743080c8bb60 Mon Sep 17 00:00:00 2001 From: waldronmatt Date: Sun, 1 Sep 2024 11:51:21 -0400 Subject: [PATCH] fix(query-template-by-id.ts): fix setter to uncache oldValue, enroll in requestUpdate, improve types --- packages/lit-override/README.md | 25 ++++- packages/lit-override/custom-elements.json | 98 +++++++++---------- packages/lit-override/custom-elements.md | 48 ++++----- .../src/components/lit-override-component.ts | 4 +- .../src/decorators/query-template-by-id.ts | 21 ++-- 5 files changed, 111 insertions(+), 85 deletions(-) diff --git a/packages/lit-override/README.md b/packages/lit-override/README.md index 40dcd407..7ea34da8 100644 --- a/packages/lit-override/README.md +++ b/packages/lit-override/README.md @@ -80,14 +80,13 @@ Add the following to the component you want to override styles and markup on: ```ts import { LitElement, html } from 'lit'; -import { property } from 'lit/decorators.js'; import { templateContentWithFallback } from '@waldronmatt/lit-override/directives/template-content-with-fallback.js'; import { AdoptedStyleSheetsConverter } from '@waldronmatt/lit-override/controllers/adopted-stylesheets-converter.js'; -import { queryTemplateById } from '@waldronmatt/lit-override/decorators/query-template-by-id.js'; +import { queryTemplateById, TemplateIdProperty } from '@waldronmatt/lit-override/decorators/query-template-by-id.js'; export class ChildComponent extends LitElement { @queryTemplateById({ fallback: true }) - templateId!: HTMLTemplateElement | null; + templateId!: TemplateIdProperty['templateIdGetter']; connectedCallback() { super.connectedCallback(); @@ -130,6 +129,26 @@ Set `templateId` on `child-component` to point to the template from which to add ``` +**Note**: You can assign `templateId` an id that references a different template programtically using type assertion: + +`child-component.ts` + +```ts +import { LitElement } from 'lit'; +import { queryTemplateById, TemplateIdProperty } from '@waldronmatt/lit-override/decorators/query-template-by-id.js'; + +export class ChildComponent extends LitElement { + @queryTemplateById({ fallback: true }) + templateId!: TemplateIdProperty['templateIdGetter']; + + connectedCallback() { + super.connectedCallback(); + + (this.templateId as TemplateIdProperty['templateIdSetter']) = 'otherChildTemplate'; + } +} +``` + ### Lit Override Component The `` component provides an all-in-one approach to override markup and styles in the light DOM and shadow DOM: diff --git a/packages/lit-override/custom-elements.json b/packages/lit-override/custom-elements.json index ba7695ab..f6579777 100644 --- a/packages/lit-override/custom-elements.json +++ b/packages/lit-override/custom-elements.json @@ -226,6 +226,55 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/decorators/index.ts", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "*", + "declaration": { + "name": "*", + "package": "./query-template-by-id.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "src/decorators/query-template-by-id.ts", + "declarations": [ + { + "kind": "function", + "name": "queryTemplateById", + "parameters": [ + { + "name": "{ fallback = false }", + "default": "{}", + "type": { + "text": "QueryTemplateByIdParams" + } + }, + { + "description": "gets a template element if an id is not provided (not cached). Defaults to `false`.", + "name": "fallback" + } + ], + "description": "queryTemplateById\n\nGets a template element by id that is provided to the `templateId` property.\nWill cache the template element on successful query." + } + ], + "exports": [ + { + "kind": "js", + "name": "queryTemplateById", + "declaration": { + "name": "queryTemplateById", + "module": "src/decorators/query-template-by-id.ts" + } + } + ] + }, { "kind": "javascript-module", "path": "src/controllers/adopted-stylesheets-converter.ts", @@ -391,55 +440,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/decorators/index.ts", - "declarations": [], - "exports": [ - { - "kind": "js", - "name": "*", - "declaration": { - "name": "*", - "package": "./query-template-by-id.js" - } - } - ] - }, - { - "kind": "javascript-module", - "path": "src/decorators/query-template-by-id.ts", - "declarations": [ - { - "kind": "function", - "name": "queryTemplateById", - "parameters": [ - { - "name": "{ fallback = false }", - "default": "{}", - "type": { - "text": "QueryTemplateByIdParams" - } - }, - { - "description": "gets a template element if an id is not provided (not cached). Defaults to `false`.", - "name": "fallback" - } - ], - "description": "queryTemplateById\n\nGets a template element by id that is provided to the `templateId` property.\nWill cache the template element on successful query." - } - ], - "exports": [ - { - "kind": "js", - "name": "queryTemplateById", - "declaration": { - "name": "queryTemplateById", - "module": "src/decorators/query-template-by-id.ts" - } - } - ] - }, { "kind": "javascript-module", "path": "src/mixins/emit-connected-callback.ts", diff --git a/packages/lit-override/custom-elements.md b/packages/lit-override/custom-elements.md index 7582b7cb..f3c73e06 100644 --- a/packages/lit-override/custom-elements.md +++ b/packages/lit-override/custom-elements.md @@ -74,6 +74,30 @@ | `js` | `default` | LitOverride | src/components/lit-override.ts | | | `custom-element-definition` | `lit-override` | LitOverride | /src/components/lit-override-component.js | | +## `src/decorators/index.ts`: + +### Exports + +| Kind | Name | Declaration | Module | Package | +| ---- | ---- | ----------- | ------ | ------------------------- | +| `js` | `*` | \* | | ./query-template-by-id.js | + +## `src/decorators/query-template-by-id.ts`: + +### Functions + +| Name | Description | Parameters | Return | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------ | +| `queryTemplateById` | queryTemplateById Gets a template element by id that is provided to the \`templateId\` property. Will cache the template element on successful query. | `{ fallback = false }: QueryTemplateByIdParams, fallback` | | + +
+ +### Exports + +| Kind | Name | Declaration | Module | Package | +| ---- | ------------------- | ----------------- | -------------------------------------- | ------- | +| `js` | `queryTemplateById` | queryTemplateById | src/decorators/query-template-by-id.ts | | + ## `src/controllers/adopted-stylesheets-converter.ts`: ### class: `AdoptedStyleSheetsConverter` @@ -134,30 +158,6 @@ | `js` | `templateContentWithFallback` | templateContentWithFallback | src/directives/template-content-with-fallback.ts | | | `js` | `TemplateContentWithFallbackDirective` | TemplateContentWithFallbackDirective | src/directives/template-content-with-fallback.ts | | -## `src/decorators/index.ts`: - -### Exports - -| Kind | Name | Declaration | Module | Package | -| ---- | ---- | ----------- | ------ | ------------------------- | -| `js` | `*` | \* | | ./query-template-by-id.js | - -## `src/decorators/query-template-by-id.ts`: - -### Functions - -| Name | Description | Parameters | Return | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------- | ------ | -| `queryTemplateById` | queryTemplateById Gets a template element by id that is provided to the \`templateId\` property. Will cache the template element on successful query. | `{ fallback = false }: QueryTemplateByIdParams, fallback` | | - -
- -### Exports - -| Kind | Name | Declaration | Module | Package | -| ---- | ------------------- | ----------------- | -------------------------------------- | ------- | -| `js` | `queryTemplateById` | queryTemplateById | src/decorators/query-template-by-id.ts | | - ## `src/mixins/emit-connected-callback.ts`: ### class: `EmitConnectedCallbackProps` diff --git a/packages/lit-override/src/components/lit-override-component.ts b/packages/lit-override/src/components/lit-override-component.ts index 437949ab..026fda9b 100644 --- a/packages/lit-override/src/components/lit-override-component.ts +++ b/packages/lit-override/src/components/lit-override-component.ts @@ -2,7 +2,7 @@ import { LitElement, html } from 'lit'; import { EmitConnectedCallback } from '../mixins/emit-connected-callback.js'; import { templateContentWithFallback } from '../directives/template-content-with-fallback.js'; import { AdoptedStyleSheetsConverter } from '../controllers/adopted-stylesheets-converter.js'; -import { queryTemplateById } from '../decorators/query-template-by-id.js'; +import { queryTemplateById, TemplateIdProperty } from '../decorators/query-template-by-id.js'; /** * LitOverride - `` @@ -17,7 +17,7 @@ import { queryTemplateById } from '../decorators/query-template-by-id.js'; */ export class LitOverride extends EmitConnectedCallback(LitElement) { @queryTemplateById({ fallback: true }) - templateId!: HTMLTemplateElement | null; + templateId!: TemplateIdProperty['templateIdGetter']; connectedCallback() { super.connectedCallback(); diff --git a/packages/lit-override/src/decorators/query-template-by-id.ts b/packages/lit-override/src/decorators/query-template-by-id.ts index 928c62c0..c7d0425b 100644 --- a/packages/lit-override/src/decorators/query-template-by-id.ts +++ b/packages/lit-override/src/decorators/query-template-by-id.ts @@ -1,9 +1,14 @@ import { property } from 'lit/decorators.js'; import { ReactiveElement } from 'lit'; +export interface TemplateIdProperty { + get templateIdGetter(): HTMLTemplateElement | null; + set templateIdSetter(value: string | null); +} + interface ExtendedElement extends ReactiveElement { - [key: symbol]: string | null; - _templateCache?: Record; + [key: symbol]: TemplateIdProperty['templateIdSetter']; + _templateCache?: Record; } export interface QueryTemplateByIdParams { @@ -25,7 +30,7 @@ export const queryTemplateById = ({ fallback = false }: QueryTemplateByIdParams property({ reflect: true, type: String })(proto, propName); Object.defineProperty(proto, 'templateId', { - get(this: ExtendedElement): HTMLTemplateElement | null { + get(this: ExtendedElement): TemplateIdProperty['templateIdGetter'] { const id = this[internalKey]; if (!this._templateCache) { @@ -38,7 +43,6 @@ export const queryTemplateById = ({ fallback = false }: QueryTemplateByIdParams if (typeof id === 'string' && id) { const templateElement = document.querySelector(`template#${id}`) as HTMLTemplateElement | null; - if (!templateElement) { console.error(`Template id ${id} could not be found`); return null; @@ -50,12 +54,15 @@ export const queryTemplateById = ({ fallback = false }: QueryTemplateByIdParams return fallback ? document.querySelector('template') : null; }, - set(this: ExtendedElement, value: string | null) { + set(this: ExtendedElement, value: TemplateIdProperty['templateIdSetter']) { + const oldValue = this[internalKey]; this[internalKey] = value; - if (this._templateCache && value) { - delete this._templateCache[value]; + if (this._templateCache && oldValue) { + delete this._templateCache[oldValue]; } + + this.requestUpdate('templateId', oldValue); }, enumerable: true, configurable: true,