Do not reflect default values

- Add `default` descriptor
- Do not reflect attributes when equal to their default value
- Patch getter return value to return default value when empty
- Use it in button `appearance`
This commit is contained in:
Lea Verou
2025-01-21 15:07:13 -05:00
parent f2bb2c84a0
commit e3560dcf98
2 changed files with 49 additions and 3 deletions

View File

@@ -72,7 +72,8 @@ export default class WaButton extends WebAwesomeFormAssociatedElement {
@property({ reflect: true }) variant: 'neutral' | 'brand' | 'success' | 'warning' | 'danger' = 'neutral';
/** The button's visual appearance. */
@property({ reflect: true }) appearance: 'accent' | 'filled' | 'outlined' | 'plain' = 'accent';
@property({ reflect: true, default: 'accent' })
appearance: 'accent' | 'filled' | 'outlined' | 'plain' = 'accent';
/** The button's size. */
@property({ reflect: true }) size: 'small' | 'medium' | 'large' = 'medium';

View File

@@ -1,8 +1,18 @@
import type { CSSResult, CSSResultGroup, PropertyValues } from 'lit';
import { LitElement, isServer, unsafeCSS } from 'lit';
import type { CSSResult, CSSResultGroup, PropertyDeclaration, PropertyValues } from 'lit';
import { LitElement, defaultConverter, isServer, unsafeCSS } from 'lit';
import { property } from 'lit/decorators.js';
import componentStyles from '../styles/shadow/component.css';
// Augment Lit's module
declare module 'lit' {
interface PropertyDeclaration {
/**
* Specifies the propertys default value
*/
default?: any;
}
}
export default class WebAwesomeElement extends LitElement {
constructor() {
super();
@@ -148,4 +158,39 @@ export default class WebAwesomeElement extends LitElement {
hasCustomState(state: string): boolean {
return this.hasStatesSupport() ? this.internals.states.has(state) : false;
}
static createProperty(name: PropertyKey, options?: PropertyDeclaration): void {
if (options && options.default !== undefined && options.converter === undefined) {
// Wrap the default converter to remove the attribute if the value is the default
// This effectively prevents the component sprouting attributes that have not been specified
let converter = {
...defaultConverter,
toAttribute(value: string, type: unknown): unknown {
if (value === options!.default) {
return null;
}
return defaultConverter.toAttribute!(value, type);
},
};
options = { ...options, converter };
}
super.createProperty(name, options);
// Wrap the default accessor with logic to return the default value if the value is null
if (options && options.default !== undefined) {
const descriptor = Object.getOwnPropertyDescriptor(this.prototype, name as string);
if (descriptor?.get) {
const getter = descriptor.get;
Object.defineProperty(this.prototype, name, {
...descriptor,
get() {
return getter.call(this) ?? options.default;
},
});
}
}
}
}