Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 8x 8x 6x 3x 3x 3x 3x 3x 6x 6x 6x 4x 6x 6x 6x 6x 6x 6x 6x | import { Mutable, TypeOf } from '@sgrud/core';
import { Component } from './component';
/**
* {@link Component} prototype property decorator factory. Applying the
* **Attribute** decorator to a property of a {@link Component} binds the
* decorated property to the corresponding **Attribute** of the respective
* {@link Component}. This implies that the **Attribute** `name` is appended to
* the {@link Component.observedAttributes} array of the {@link Component} and
* the decorated property is replaced with a getter and setter deferring those
* operations to the **Attribute**. If no `name` supplied, the name of the
* decorated property will be used instead. Further, if both, a parameter
* initializer and an initial **Attribute** value are supplied, the
* **Attribute** value takes precedence.
*
* @param name - The {@link Component} **Attribute** `name`.
* @returns A {@link Component} prototype property decorator.
*
* @example
* Bind a property to an **Attribute**:
* ```tsx
* import { Attribute, Component } from '@sgrud/shell';
*
* declare global {
* interface HTMLElementTagNameMap {
* 'example-component': ExampleComponent;
* }
* }
*
* @Component('example-component')
* export class ExampleComponent extends HTMLElement implements Component {
*
* @Attribute()
* public field?: string;
*
* public get template(): JSX.Element {
* return <span>Attribute value: {this.field}</span>;
* }
*
* }
* ```
*
* @see {@link Component}
*/
export function Attribute(name?: string) {
/**
* @param prototype - The {@link Component} `prototype` to be decorated.
* @param propertyKey - The {@link Component} property to be decorated.
*/
return function(prototype: Component, propertyKey: PropertyKey): void {
// eslint-disable-next-line @typescript-eslint/unbound-method
const connectedCallback = prototype.connectedCallback;
const key = name || propertyKey as string;
prototype.connectedCallback = function(this: Component): void {
Object.defineProperty(this, propertyKey, {
enumerable: true,
get(this: Component): string | undefined {
return this.getAttribute(key) ?? undefined;
},
set(this: Component, value: string): void {
if (TypeOf.null(value) || TypeOf.undefined(value)) {
this.removeAttribute(key);
} else {
this.setAttribute(key, value);
}
}
});
return connectedCallback
? connectedCallback.call(this)
: this.renderComponent?.();
};
((prototype as Mutable<Component>).observedAttributes ||= []).push(key);
};
}
|