What is a subset of HTML's reflection rules which we should make easy for web components?
HTML's reflection algorithms include:
- URL strings
- Enumeration strings ("limited to only known values")
- Missing value default
- Invalid value default
- Note: case-insensitive
- Other strings
- Booleans
- A bunch of numbers:
- long
- long limited to only non-negative numbers
- unsigned long
- unsigned long limited to only non-negative numbers greater than zero
- unsigned long limited to only non-negative numbers greater than zero with fallback
- double/unrestricted double
- double/unrestricted double limited to numbers greater than zero
- DOMTokenList
- HTMLElement
- URL strings
- Enumeration strings:
- Case-insensitive to match the platform
- Make missing and invalid value default always the same
- Maybe make missing and invalid value default always
""
?
- Other strings
- Booleans
- Numbers, parametrized:
- Lower bound (+ upper bound?)
- Integral or floating point
- Integer default upper bound is 2147483647 to match the platform.
- Setting out-of-bound values causes an exception
- Getting when the attribute has out of bound values returns the lower bound? Returns null? Returns a configurable fallback?
This omits:
- No DOMTokenList for now since it's not constructible
- No HTMLElement since id-based references kind of suck
- Various existing number behavior such as wrapping at 2147483647 or clamping to >=0.
customElements.addReflectingProperties(MyCustomElement, {
href: 'url',
selected: 'boolean',
label: 'string',
preload: {
type: 'enum',
values: ['none', 'metadata', 'auto'],
default: 'auto'
},
// Alternative to preload syntax
preload2: {
type: 'enum',
values: ['none', 'metadata'] // implicit '' value is interpreted
// by the component as auto behavior
// default is always ''
},
colSpan: {
type: 'int',
lowerBound: 1
},
width: {
type: 'float',
lowerBound: 0
},
// Alternative to colSpan/width syntax
colSpan2: {
type: 'number',
integral: true,
lowerBound: 1
},
width2: {
type: 'number',
lowerBound: 0
}
});
const { url, boolean, string, enum, enum2, enum3, int, float } = customElements.decorators;
class MyCustomElement extends HTMLElement {
@url href;
@boolean selected;
@string label;
@enum({ values: ['none', 'metadata', 'auto'], default: 'auto' }) preload;
// Alternative: assume the first is the default
@enum2('auto', 'metadata', 'none') preload2;
// Alternative: implicit '' default
@enum3('metadata', 'none') preload3;
@int({ lowerBound: 1 }) colSpan;
@float({ lowerBound: 0 }) width;
}