diff --git a/src/dev/pages/label/label.ejs b/src/dev/pages/label/label.ejs index 01f9e2f31..2176b22dd 100644 --- a/src/dev/pages/label/label.ejs +++ b/src/dev/pages/label/label.ejs @@ -14,6 +14,14 @@ + +
+

Frozen

+ + Label + + +
\ No newline at end of file diff --git a/src/lib/label/label-constants.ts b/src/lib/label/label-constants.ts index 31e5d8f9e..15e588de0 100644 --- a/src/lib/label/label-constants.ts +++ b/src/lib/label/label-constants.ts @@ -5,7 +5,8 @@ import { SWITCH_CONSTANTS } from '../switch'; const elementName: keyof HTMLElementTagNameMap = `${COMPONENT_NAME_PREFIX}label`; const attributes = { - FOR: 'for' + FOR: 'for', + FREEZE: 'freeze' }; const selectors = { diff --git a/src/lib/label/label-foundation.ts b/src/lib/label/label-foundation.ts index 3590fbbd2..1ba25d753 100644 --- a/src/lib/label/label-foundation.ts +++ b/src/lib/label/label-foundation.ts @@ -5,13 +5,16 @@ import { LABEL_CONSTANTS } from './label-constants'; export interface ILabelFoundation extends ICustomElementFoundation { for: string | null | undefined; forElement: HTMLElement | null | undefined; + freeze: boolean; disconnect(): void; + update(): void; } export class LabelFoundation implements ILabelFoundation { // State private _for: string | null | undefined; private _forElement: HTMLElement | null | undefined; + private _freeze = false; private _isConnected = false; // Listeners @@ -35,6 +38,10 @@ export class LabelFoundation implements ILabelFoundation { this._adapter.destroy(); } + public update(): void { + this._adapter.updateTargetLabel(); + } + private _handleClick(evt: PointerEvent): void { // Prevent duplicate clicks from a nested target element if (evt.target === this._adapter.getTargetElement()) { @@ -49,7 +56,9 @@ export class LabelFoundation implements ILabelFoundation { private _connect(): void { this._adapter.addHostListener('click', this._clickListener); - this._adapter.addMutationObserver(this._mutationCallback); + if (!this._freeze) { + this._adapter.addMutationObserver(this._mutationCallback); + } this._isConnected = true; } @@ -89,4 +98,20 @@ export class LabelFoundation implements ILabelFoundation { this._tryConnect(); } } + + public get freeze(): boolean { + return this._freeze; + } + public set freeze(value: boolean) { + if (this._freeze !== value) { + this._freeze = value; + this._adapter.toggleHostAttribute(LABEL_CONSTANTS.attributes.FREEZE, this._freeze); + if (this._freeze) { + this._adapter.removeMutationObserver(); + this._adapter.updateTargetLabel(); + } else if (this._adapter.hasTargetElement()) { + this._adapter.addMutationObserver(this._mutationCallback); + } + } + } } diff --git a/src/lib/label/label.ts b/src/lib/label/label.ts index 56fcda3d1..7cbf88286 100644 --- a/src/lib/label/label.ts +++ b/src/lib/label/label.ts @@ -1,4 +1,4 @@ -import { CustomElement, FoundationProperty, attachShadowTemplate } from '@tylertech/forge-core'; +import { CustomElement, FoundationProperty, attachShadowTemplate, coerceBoolean } from '@tylertech/forge-core'; import { BaseComponent, IBaseComponent } from '../core'; import { LabelAdapter } from './label-adapter'; import { LABEL_CONSTANTS } from './label-constants'; @@ -10,6 +10,8 @@ import style from './label.scss'; export interface ILabelComponent extends IBaseComponent { for: string | null | undefined; forElement: HTMLElement | null | undefined; + freeze: boolean; + update(): void; } declare global { @@ -21,13 +23,17 @@ declare global { /** * @tag forge-label * - * @summary The Forge Label component is used to associate a text label with a Forge form + * @summary The Forge Label component is used to associate a text label with a compatible Forge * component. * - * @property {string | null | undefined} for - The id of the associated form component. - * @property {HTMLElement | null | undefined} forElement - The associated form component. + * @property {string | null | undefined} for - The id of the associated element. + * @property {HTMLElement | null | undefined} forElement - The associated element. + * @property {boolean} freeze - Prevents the label from monitoring changes to its content. Set this if the label's content will never change. * * @attribute {string} for - The id of the associated form component. + * @attribute {boolean} freeze - Prevents the label from monitoring changes to its content. + * + * @method update - Updates the targetted element with the label's current text content. * * @csspart label - Styles the label's root element. */ @@ -37,7 +43,8 @@ declare global { export class LabelComponent extends BaseComponent implements ILabelComponent { public static get observedAttributes(): string[] { return [ - LABEL_CONSTANTS.attributes.FOR + LABEL_CONSTANTS.attributes.FOR, + LABEL_CONSTANTS.attributes.FREEZE ]; } @@ -62,6 +69,9 @@ export class LabelComponent extends BaseComponent implements ILabelComponent { case LABEL_CONSTANTS.attributes.FOR: this.for = newValue; break; + case LABEL_CONSTANTS.attributes.FREEZE: + this.freeze = coerceBoolean(newValue); + break; } } @@ -70,4 +80,14 @@ export class LabelComponent extends BaseComponent implements ILabelComponent { @FoundationProperty() public forElement: HTMLElement | null | undefined; + + @FoundationProperty() + public freeze: boolean; + + /** + * Updates the targetted element with the label's current text content. + */ + public update(): void { + this._foundation.update(); + } }