-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefault-value.ts
49 lines (42 loc) · 1.59 KB
/
default-value.ts
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
// @defaultValue decorator
//
// Runs when the corresponding attribute of the observed property changes, e.g. after calling Element.setAttribute or after updating
// the observed property.
//
// The decorator checks whether the value of the attribute is different from the value of the property and in that case
// it saves the new value.
//
//
// Usage:
//
// @property({ type: Boolean, reflect: true }) checked = false;
//
// @defaultValue('checked') defaultChecked = false;
//
import { defaultConverter } from 'lit';
import type { ReactiveElement } from 'lit';
export const defaultValue =
(propertyName = 'value') =>
(proto: ReactiveElement, key: string) => {
const ctor = proto.constructor as typeof ReactiveElement;
const attributeChangedCallback = ctor.prototype.attributeChangedCallback;
ctor.prototype.attributeChangedCallback = function (
this: ReactiveElement & { [name: string]: unknown },
name,
old,
value
) {
const options = ctor.getPropertyOptions(propertyName);
const attributeName = typeof options.attribute === 'string' ? options.attribute : propertyName;
if (name === attributeName) {
const converter = options.converter || defaultConverter;
const fromAttribute =
typeof converter === 'function' ? converter : converter?.fromAttribute ?? defaultConverter.fromAttribute;
const newValue: unknown = fromAttribute!(value, options.type);
if (this[propertyName] !== newValue) {
this[key] = newValue;
}
}
attributeChangedCallback.call(this, name, old, value);
};
};