-
Notifications
You must be signed in to change notification settings - Fork 9
/
bool-attr.ts
42 lines (36 loc) · 1.44 KB
/
bool-attr.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
import {hasAttr, setAttr} from '../dom/attr';
import {toKebabCase} from '../misc/format';
import type {ESLAttributeDecorator} from '../dom/attr';
import type {ESLDomElementTarget} from '../abstract/dom-target';
/** HTML boolean (marker) attribute mapping configuration */
type BoolAttrDescriptor = {
/** HTML attribute name. Uses kebab-cased variable name by default */
name?: string;
/** Create getter only */
readonly?: boolean;
/** Use data-* attribute */
dataAttr?: boolean;
};
function buildConditionalDescriptor(attrName: string, readOnly: boolean): PropertyDescriptor {
function get(): boolean {
return hasAttr(this, attrName);
}
function set(value: unknown): void {
setAttr(this, attrName, !!value);
}
return readOnly ? {get} : {get, set};
}
const buildAttrName =
(propName: string, dataAttr: boolean): string => dataAttr ? `data-${toKebabCase(propName)}` : toKebabCase(propName);
/**
* Decorator to map current property to element boolean (marker) attribute state.
* Maps boolean type property.
* @param config - mapping configuration. See {@link BoolAttrDescriptor}
*/
export const boolAttr = (config: BoolAttrDescriptor = {}): ESLAttributeDecorator => {
return (target: ESLDomElementTarget, propName: string): any => {
const attrName = buildAttrName(config.name || propName, !!config.dataAttr);
Object.defineProperty(target, propName, buildConditionalDescriptor(attrName, !!config.readonly));
return {};
};
};