UNPKG

@lume/element

Version:

Create Custom Elements with reactivity and automatic re-rendering.

334 lines 12.7 kB
import './metadata-shim.js'; import type { ElementCtor } from './element.js'; import type { PropKey } from 'classy-solid/dist/decorators/types.js'; export declare const classFinishers__: ((Class: ElementCtor) => void)[]; type AttributeDecoratorContext<This = unknown, Value = unknown> = ClassFieldDecoratorContext<This, Value> | ClassGetterDecoratorContext<This, Value> | ClassSetterDecoratorContext<This, Value> | ClassAccessorDecoratorContext<This, Value>; /** * A decorator that when used on a property or accessor causes an HTML attribute * with the same name (but dash-cased instead of camelCased) to be mapped to the * decorated property. For example, if the `@attribute` decorator is used on a * property called `firstName`, then an attribute called `first-name` will be * mapped to the property. Any time that the attribute value changes (f.e. with * `el.setAttribute`), the attribute value will propgate to the property which * triggers reactivity. * * The decorated property is backed by a Solid.js signal, thus useful in effects * or templates. * * The `@attribute` decorator is only for public fields, getters, setters, and * auto accessors. * * Example: * * ```js * ⁣@element('my-el') * class MyEl extends Element { * ⁣@attribute name = 'Lazayah' * * template = () => <p>Name: {this.name}</p> * } * ``` */ export declare function attribute(value: unknown, context: AttributeDecoratorContext): any; export declare function attribute(handler?: AttributeHandler): (value: unknown, context: AttributeDecoratorContext) => any; export declare namespace attribute { var string: AttributeHandler<string>; var number: AttributeHandler<number>; var boolean: AttributeHandler<boolean>; var event: AttributeHandler<EventListener<Event> | null>; var json: AttributeHandler<JSONValue>; } /** * Place this decorator before `@element` to avoid the property from being * backed by a Solid signal. I.e. the property will not be reactive, but will * still receive values from the HTML attribute. */ export declare const noSignal: (_value: unknown, context: AttributeDecoratorContext) => void; export interface AttributeDecoratorMetadata { attributeCount?: number; noSignal?: Set<PropKey>; } export declare function setUpAttribute__(elementDecoratedClass: ElementCtor, attrName: string, propName: string, attributeHandler: AttributeHandler): any; export declare const hasAttributeChangedCallback__: unique symbol; export declare const attributesToProps__: unique symbol; export type AttributePropSpec = { name: string; default?: unknown; attributeHandler?: AttributeHandler; }; export type AttributePropSpecs = Record<string, AttributePropSpec>; /** * Defines how values are mapped from an attribute to a JS property on a custom * element class. */ export type AttributeHandler<T = any> = { to?: (propValue: T) => string | null; /** * Define how to deserialize an attribute string value on its way to the * respective JS property. * * If not defined, the attribute string value is passed to the JS property * untouched. * * **Default when omitted:** `value => value` */ from?: (AttributeValue: string) => T; /** * A side effect to run when the value is set on the JS property. It also * runs once with the initial value. Avoid this if you can, and instead use * Solid effects. One use case of this is to call addEventListener with * event listener values immediately, just like with native `.on*` * properties. * * **Default when omitted:** `() => {}` (no sideeffect) */ sideEffect?: (instance: Element, prop: string, propValue: T) => void; /** * @deprecated - Define a field with the initial value instead of providing * the initial value here. When decorators land in browsers, this will be * removed. * * The default value that the respective JS property should have when the * attribute is removed. * * If this is not specified, and the respective class field is defined, it * will default to the initial value of the class field. If this is * specified, it will take precedence over the respective field's initial * value. This should generally be avoided, and the class field initial * value should be relied on as the source of the default value. * * When defined, an attribute's respective JS property will be set to this * value when the attribute is removed. If not defined, then the JS property * will always receive the initial value of the respective JS class field or * `undefined` if the field was not defined (that's the "initial value" of * the field), when the attribute is removed. * * **Default when omitted:** the value of the respective class field, or * `undefined` if the field was not defined. */ default?: T; /** * Whether to convert the property name to dash-case for the attribute name. * This option is ignore if the `name` option is set. * * The default is `true`, where the attribute name will be the same as the * property name but dash-cased (and all lower case). For example, `fooBar` * becomes `foo-bar` and `foo-bar` stays `foo-bar`. * * If this is set to `false`, the attribute name will be the same as the * property name, but all lowercased (attributes are case insensitive). For * example `fooBar` becomes `foobar` and `foo-bar` stays `foo-bar`. * * Note! Using this option to make a non-standard prop-attribute mapping * will result in template type definitions (f.e. in JSX) missing the * customized attribute names and will require custom type definition * management. * * **Default when omitted:** `true` */ dashcase?: boolean; /** * The name of the attribute to use. Use of this options bad practice to be * avoided, but it may be useful in rare cases. * * If this is not specified, see `dashcase` for how the attribute name is * derived from the property name. * * Note! Using this option to make a non-standard prop-attribute mapping * will result in template type definitions (f.e. in JSX) missing the * customized attribute names and will require custom type definition * management. * * **Default when omitted:** the attribute name derived from the property * name, converted to dash-case based on the `dashcase` option. */ name?: string; /** * Whether to suppress warnings about the attribute attribute name clashes * when not using default `dashcase` and `name` settings. This is * discouraged, and should only be used when you know what you're doing, * such as overriding a property that has `dashcase` set to `false` or * `name` set to the same name as the attribue of another property. * * **Default when omitted:** `false` */ noWarn?: boolean; }; /** * This is essentially an alias for `@attribute`. You can just use `@attribute` * if you want a more concise definition. * * A decorator for mapping a string-valued attribute to a JS property. All * attribute values get passed as-is, except for `null` (i.e. when an attribute * is removed) which gets converted into an empty string or the default value of * the class field. The handling of `null` (on attribute removed) is the only * difference between this and plain `@attribute`, where `@attribute` will pass * along `null`. * * Example decorator usage: * * ```js * ⁣@element('my-el') * class MyEl extends LumeElement { * ⁣@stringAttribute color = "skyblue" * } * ``` * * Example HTML attribute usage: * * ```html * <!-- el.color === "", because an attribute without a written value has an empty string value. --> * <my-el color></my-el> * * <!-- el.color === "skyblue", based on the default value defined on the class field. --> * <my-el></my-el> * * <!-- el.color === "deeppink" --> * <my-el color="deeppink"></my-el> * * <!-- el.color === "4.5" --> * <my-el color="4.5"></my-el> * * <!-- el.color === "any string in here" --> * <my-el color="any string in here"></my-el> * ``` */ export declare const stringAttribute: (value: unknown, context: AttributeDecoratorContext) => any; /** * A decorator for mapping a number attribute to a JS property. The string value * of the attribute will be parsed into a number. * * Example decorator usage: * * ```js * ⁣@element('my-el') * class MyEl extends LumeElement { * ⁣@numberAttribute money = 123 * } * ``` * * Example HTML attribute usage: * * ```html * <!-- el.money === 0, because an empty string gets coerced into 0. --> * <my-el money></my-el> * * <!-- el.money === 123, based on the default value defined on the class field. --> * <my-el></my-el> * * <!-- el.money === 10 --> * <my-el money="10"></my-el> * * <!-- el.money === 4.5 --> * <my-el money="4.5"></my-el> * * <!-- el.money === Infinity --> * <my-el money="Infinity"></my-el> * * <!-- el.money === NaN --> * <my-el money="NaN"></my-el> * * <!-- el.money === NaN --> * <my-el money="blahblah"></my-el> * ``` */ export declare const numberAttribute: (value: unknown, context: AttributeDecoratorContext) => any; /** * A decorator for mapping a boolean attribute to a JS property. The string * value of the attribute will be converted into a boolean value on the JS * property. A string value of `"false"` and a value of `null` (attribute * removed) will be converted into a `false` value on the JS property. All other * attribute values (strings) will be converted into `true`. * * Example decorator usage: * * ```js * ⁣@element('my-el') * class MyEl extends LumeElement { * ⁣@booleanAttribute hasMoney = true * ⁣@booleanAttribute excited = false * } * ``` * * Example HTML attribute usage: * * ```html * <!-- el.hasMoney === true, el.excited === true --> * <my-el has-money excited></my-el> * * <!-- el.hasMoney === true, el.excited === false, based on the default values defined * on the class fields. Start the a class field with a value of `false` to have * behavior similar to traditional DOM boolean attributes where the presence of * the attribute determines the boolean value of its respective JS property. --> * <my-el></my-el> * * <!-- el.hasMoney === false, el.excited === true --> * <my-el has-money="false"></my-el> * * <!-- el.hasMoney === true, el.excited === true --> * <my-el has-money="true"></my-el> * * <!-- el.hasMoney === true, el.excited === true --> * <my-el has-money=""></my-el> * * <!-- el.hasMoney === true, el.excited === true --> * <my-el has-money="blahblah"></my-el> * ``` */ export declare const booleanAttribute: (value: unknown, context: AttributeDecoratorContext) => any; /** * A decorator for mapping an event attribute to a JS property (similar to * builtin attributes like "onclick"). The string value of the attribute will be * converted into a function for use as an event handler. * * Example decorator usage: * * ```js * ⁣@element('my-el') * class MyEl extends LumeElement { * ⁣@eventAttribute onsomeevent = null * * connectedCallback() { * super.connectedCallback() * this.dispatchEvent(new Event('someevent')) * } * } * * const el = document.createElement('my-el') * el.onsomeevent = e => console.log('someevent', e) * document.body.append(el) // will log "someevent Event {...}" when the element is connected * * const el2 = document.createElement('my-el') * el2.setAttribute("onsomeevent", "console.log('someevent', event)") * document.body.append(el2) // will log "someevent Event {...}" when the element is connected * ``` * * Example HTML attribute usage: * * ```html * <body> * <my-el onsomeevent="console.log('someevent', event)"></my-el> * </body> * ``` * * Example JSX prop usage: * * ```jsx * return <my-el onsomeevent={event => console.log('someevent', event)} /> * ``` */ export declare const eventAttribute: (value: unknown, context: AttributeDecoratorContext) => any; export type EventListener<T extends Event = Event> = (event: T) => void; export type EventHandler<T extends Event = Event> = { handleEvent: EventListener<T>; }; /** * A decorator for mapping a JSON-valued attribute to a JS property. The string * value of the attribute will be parsed into a JS value using `JSON.parse()`. */ export declare const jsonAttribute: (value: unknown, context: AttributeDecoratorContext) => any; export type JSONValue = string | number | boolean | null | { [key: string]: JSONValue; } | Array<JSONValue>; export {}; //# sourceMappingURL=attribute.d.ts.map