I ran codemod, then addressed TypeScript errors in the most naive way.

Moving decorators from getters -> setters.
Wrapping inherited properties with the same decorators as base class.
This commit is contained in:
Andrew Jakubowicz 2023-09-06 10:25:56 -07:00
parent 5ca098c313
commit a22dd4908c
56 changed files with 370 additions and 335 deletions

View File

@ -37,18 +37,18 @@ export abstract class Button extends LitElement implements FormSubmitter {
/**
* Whether or not the button is disabled.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* The URL that the link button points to.
*/
@property() href = '';
@property() accessor href = '';
/**
* Where to display the linked `href` URL for a link button. Common options
* include `_blank` to open in a new tab.
*/
@property() target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property() accessor target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
/**
* Whether to render the icon at the inline end of the label rather than the
@ -56,16 +56,16 @@ export abstract class Button extends LitElement implements FormSubmitter {
*
* _Note:_ Link buttons cannot have trailing icons.
*/
@property({type: Boolean, attribute: 'trailing-icon'}) trailingIcon = false;
@property({type: Boolean, attribute: 'trailing-icon'}) accessor trailingIcon = false;
/**
* Whether to display the icon or not.
*/
@property({type: Boolean, attribute: 'has-icon'}) hasIcon = false;
@property({type: Boolean, attribute: 'has-icon'}) accessor hasIcon = false;
@property() type: FormSubmitterType = 'submit';
@property() accessor type: FormSubmitterType = 'submit';
@property() value = '';
@property() accessor value = '';
get name() {
return this.getAttribute('name') ?? '';
@ -81,14 +81,15 @@ export abstract class Button extends LitElement implements FormSubmitter {
return this[internals].form;
}
@query('.button') private readonly buttonElement!: HTMLElement|null;
@query('.button')
private accessor buttonElement!: HTMLElement|null;
@queryAssignedElements({slot: 'icon', flatten: true})
private readonly assignedIcons!: HTMLElement[];
private accessor assignedIcons!: HTMLElement[];
/** @private */
[internals] =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -34,26 +34,26 @@ export class CopyCodeButton extends LitElement {
private timeoutId: number|undefined;
@state() private showCheckmark = false;
@state() private accessor showCheckmark = false;
/**
* The aria label for the copy button when it has not been clicked.
*/
@property() label = 'Copy code';
@property() accessor label = 'Copy code';
/**
* The aria label for the copy button when it has been clicked and the copy is
* successul.
*/
@property({attribute: 'success-label'}) successLabel = 'Copy successful';
@property({attribute: 'success-label'}) accessor successLabel = 'Copy successful';
/**
* The title to be set on the copy button.
*/
@property({attribute: 'button-title'}) buttonTitle = 'Copy code';
@property({attribute: 'button-title'}) accessor buttonTitle = 'Copy code';
@queryAssignedElements({flatten: true, selector: '*'})
private slottedEls!: NodeListOf<HTMLElement>;
private accessor slottedEls!: NodeListOf<HTMLElement>;
render() {
const label = this.showCheckmark ? this.successLabel : this.label;

View File

@ -32,23 +32,23 @@ export class HCTSlider extends LitElement {
/**
* The visiable and accessible label for the control.
*/
@property({type: String}) label = '';
@property({type: String}) accessor label = '';
/**
* The value of the slider.
*/
@property({type: Number}) value = 0;
@property({type: Number}) accessor value = 0;
/**
* The color from which to base the preview gradient (really only useful for
* chroma).
*/
@property({type: String}) color = '';
@property({type: String}) accessor color = '';
/**
* The type of HCT slider to display
*/
@property({type: String}) type: 'hue'|'chroma'|'tone' = 'hue';
@property({type: String}) accessor type: 'hue'|'chroma'|'tone' = 'hue';
override render() {
let range = HUE_RANGE;

View File

@ -26,14 +26,14 @@ import {SignalElement} from '../signals/signal-element.js';
/**
* Whether or not the side drawer is collapsible or inline.
*/
@state() private isCollapsible = false;
@state() private accessor isCollapsible = false;
/**
* Whether or not the TOC should be rendered.
*/
@property({type: Boolean, attribute: 'has-toc'}) hasToc = false;
@property({type: Boolean, attribute: 'has-toc'}) accessor hasToc = false;
@property({attribute: 'page-title'}) pageTitle = '';
@property({attribute: 'page-title'}) accessor pageTitle = '';
render() {
const showModal = this.isCollapsible && drawerOpenSignal.value;

View File

@ -32,7 +32,7 @@ export class ThemeChanger extends LitElement {
/**
* The currently selected color mode.
*/
@state() selectedColorMode: ColorMode|null = null;
@state() accessor selectedColorMode: ColorMode|null = null;
/**
* The currently selected hex color.
@ -40,25 +40,25 @@ export class ThemeChanger extends LitElement {
* NOTE: Hex colors are in the srgb color space and HCT has a much larger, so
* this value is a clipped value of HCT.
*/
@state() hexColor = '';
@state() accessor hexColor = '';
/**
* The current hue value of the hue slider.
*/
@state() hue = 0;
@state() accessor hue = 0;
/**
* The crrent value of the chroma slider.
*/
@state() chroma = 0;
@state() accessor chroma = 0;
/**
* The current value of the tone slider.
*/
@state() tone = 0;
@state() accessor tone = 0;
@query('input') private inputEl!: HTMLInputElement;
@queryAll('hct-slider') private sliders!: NodeListOf<HCTSlider>;
@query('input') private accessor inputEl!: HTMLInputElement;
@queryAll('hct-slider') private accessor sliders!: NodeListOf<HCTSlider>;
render() {
return html`

View File

@ -26,7 +26,7 @@ import {materialDesign} from '../svg/material-design-logo.js';
/**
* Whether or not the color picker menu is open.
*/
@state() private menuOpen = false;
@state() private accessor menuOpen = false;
render() {
return html`

View File

@ -106,7 +106,7 @@ export class KnobColorSelector extends LitElement {
private internalValue = '';
@property({type: Boolean}) hasAlpha = false;
@property({type: Boolean}) accessor hasAlpha = false;
set value(val: string) {
const oldVal = this.internalValue;

View File

@ -59,14 +59,14 @@ export class StoriesRenderer extends LitElement {
];
/** If true, will not show the UI for any knobs on this collection. */
@property({type: Boolean}) hideKnobs: boolean = false;
@property({type: Boolean}) accessor hideKnobs: boolean = false;
@property({attribute: false})
focusStories?: readonly Story[];
@property({attribute: false}) collection?: Collection;
@property({type: Boolean}) hideLabels = false;
@property({type: Boolean, reflect: true}) hasKnobs = false;
@state() knobsOpen = true;
@state() knobsPanelType: 'modal'|'inline' = 'inline';
accessor focusStories?: readonly Story[];
@property({attribute: false}) accessor collection?: Collection;
@property({type: Boolean}) accessor hideLabels = false;
@property({type: Boolean, reflect: true}) accessor hasKnobs = false;
@state() accessor knobsOpen = true;
@state() accessor knobsPanelType: 'modal'|'inline' = 'inline';
private observedKnobs: undefined|KnobValues<PolymorphicArrayOfKnobs> =
undefined;

View File

@ -29,13 +29,13 @@ export const DEFAULT_DIMENSIONS = {
*/
@customElement('story-knob-panel')
export class StoryKnobPanel extends LitElement {
@query('.dragBar') dragBar!: HTMLElement|null;
@query('.dragBar') accessor dragBar!: HTMLElement|null;
@property({type: Boolean}) showCloseIcon = true;
@property({type: Boolean, reflect: true}) open = false;
@property({type: Boolean, reflect: true}) override draggable = false;
@property({type: Boolean}) hideDragIcon = false;
@property({type: String, reflect: true}) type: 'modal'|'inline' = 'inline';
@property({type: Boolean}) accessor showCloseIcon = true;
@property({type: Boolean, reflect: true}) accessor open = false;
@property({type: Boolean, reflect: true}) override accessor draggable = false;
@property({type: Boolean}) accessor hideDragIcon = false;
@property({type: String, reflect: true}) accessor type: 'modal'|'inline' = 'inline';
private isDragging = false;
private previousX = 0;
private currentX = 0;

View File

@ -23,7 +23,7 @@ export class StoryRenderer extends LitElement {
}
`,
];
@property({attribute: false}) story?: Story = undefined;
@property({attribute: false}) accessor story?: Story = undefined;
private storyRenderComplete: Promise<void>|undefined = undefined;
override updated(propertiesChanged: PropertyValues) {

View File

@ -35,19 +35,19 @@ export class Checkbox extends LitElement {
/**
* Whether or not the checkbox is selected.
*/
@property({type: Boolean}) checked = false;
@property({type: Boolean}) accessor checked = false;
/**
* Whether or not the checkbox is disabled.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* Whether or not the checkbox is indeterminate.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate_state_checkboxes
*/
@property({type: Boolean}) indeterminate = false;
@property({type: Boolean}) accessor indeterminate = false;
/**
* When true, require the checkbox to be selected when participating in
@ -55,14 +55,14 @@ export class Checkbox extends LitElement {
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation
*/
@property({type: Boolean}) required = false;
@property({type: Boolean}) accessor required = false;
/**
* The value of the checkbox that is submitted with a form when selected.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value
*/
@property() value = 'on';
@property() accessor value = 'on';
/**
* The HTML name to use in form submission.
@ -123,12 +123,13 @@ export class Checkbox extends LitElement {
return this.internals.willValidate;
}
@state() private prevChecked = false;
@state() private prevDisabled = false;
@state() private prevIndeterminate = false;
@query('input') private readonly input!: HTMLInputElement|null;
@state() private accessor prevChecked = false;
@state() private accessor prevDisabled = false;
@state() private accessor prevIndeterminate = false;
@query('input')
private accessor input!: HTMLInputElement|null;
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -17,9 +17,9 @@ import {Chip, renderGridAction, renderGridContainer} from './chip.js';
* An assist chip component.
*/
export class AssistChip extends Chip {
@property({type: Boolean}) elevated = false;
@property() href = '';
@property() target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property({type: Boolean}) accessor elevated = false;
@property() accessor href = '';
@property() accessor target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
protected get primaryId() {
return this.href ? 'link' : 'button';

View File

@ -30,10 +30,11 @@ export class ChipSet extends LitElement {
(child): child is Chip => child instanceof Chip);
}
@property() type: ChipSetType = '';
@property({type: Boolean, attribute: 'single-select'}) singleSelect = false;
@property() accessor type: ChipSetType = '';
@property({type: Boolean, attribute: 'single-select'}) accessor singleSelect = false;
@queryAssignedElements() private readonly childElements!: HTMLElement[];
@queryAssignedElements()
private accessor childElements!: HTMLElement[];
constructor() {
super();

View File

@ -27,8 +27,8 @@ export abstract class Chip extends LitElement {
delegatesFocus: true
};
@property({type: Boolean}) disabled = false;
@property() label = '';
@property({type: Boolean}) accessor disabled = false;
@property() accessor label = '';
/**
* The `id` of the action the primary focus ring and ripple are for.

View File

@ -20,17 +20,18 @@ import {renderRemoveButton} from './trailing-icons.js';
* A filter chip component.
*/
export class FilterChip extends MultiActionChip {
@property({type: Boolean}) elevated = false;
@property({type: Boolean}) removable = false;
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean}) accessor elevated = false;
@property({type: Boolean}) accessor removable = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
protected get primaryId() {
return 'option';
}
@query('.primary.action') protected readonly primaryAction!: HTMLElement|null;
@query('.primary.action')
protected accessor primaryAction!: HTMLElement|null;
@query('.trailing.action')
protected readonly trailingAction!: HTMLElement|null;
protected accessor trailingAction!: HTMLElement|null;
protected override updated(changed: PropertyValues<this>) {
if (changed.has('selected') && changed.get('selected') !== undefined) {

View File

@ -16,7 +16,6 @@ import {FilterChip} from './filter-chip.js';
@customElement('test-filter-chip')
class TestFilterChip extends FilterChip {
declare primaryAction: HTMLElement;
}
describe('Filter chip', () => {

View File

@ -17,11 +17,11 @@ import {renderRemoveButton} from './trailing-icons.js';
* An input chip component.
*/
export class InputChip extends MultiActionChip {
@property({type: Boolean}) avatar = false;
@property() href = '';
@property() target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property({type: Boolean, attribute: 'remove-only'}) removeOnly = false;
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean}) accessor avatar = false;
@property() accessor href = '';
@property() accessor target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property({type: Boolean, attribute: 'remove-only'}) accessor removeOnly = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
protected get primaryId() {
if (this.href) {
@ -51,7 +51,7 @@ export class InputChip extends MultiActionChip {
}
@query('.trailing.action')
protected readonly trailingAction!: HTMLElement|null;
protected accessor trailingAction!: HTMLElement|null;
protected override renderContainer(content: unknown) {
return renderGridContainer(content, this.getContainerClasses());

View File

@ -19,9 +19,9 @@ import {renderRemoveButton} from './trailing-icons.js';
class TestMultiActionChip extends MultiActionChip {
static override styles = css`:host { position: relative; }`;
@query('#primary') primaryAction!: HTMLElement;
@query('.trailing.action') trailingAction!: HTMLElement;
@property() noTrailingAction = false;
@query('#primary') accessor primaryAction!: HTMLElement;
@query('.trailing.action') accessor trailingAction!: HTMLElement;
@property() accessor noTrailingAction = false;
protected primaryId = 'primary';

View File

@ -1,12 +1,15 @@
// File name: add-accessor-keyword.mjs
// Run with `jscodeshift -t=add-accessor-keyword.mjs button/internal/button.ts`
/**
* Note this transform is not idempotent and will explode if you
* run it a second time. Sorry :(
*/
export default function transformer(file, api) {
const j = api.jscodeshift;
const root = j(file.source);
root.find(j.ClassProperty).forEach((path) => {
if (path.node.decorators && path.node.decorators.length > 0) {
path.node.key.name = "accessor " + path.node.key.name;
@ -19,4 +22,4 @@ export default function transformer(file, api) {
return root.toSource();
}
export const parser = 'ts'
export const parser = "ts";

View File

@ -39,11 +39,11 @@ export class Dialog extends LitElement {
/**
* Opens the dialog when set to `true` and closes it when set to `false`.
*/
@property({type: Boolean})
get open() {
return this.isOpen;
}
@property({type: Boolean})
set open(open: boolean) {
if (open === this.isOpen) {
return;
@ -65,13 +65,13 @@ export class Dialog extends LitElement {
*
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/returnValue
*/
@property({attribute: false}) returnValue = '';
@property({attribute: false}) accessor returnValue = '';
/**
* The type of dialog for accessibility. Set this to `alert` to announce a
* dialog as an alert dialog.
*/
@property() type?: 'alert';
@property() accessor type: 'alert' | undefined;
/**
* Gets the opening animation for a dialog. Set to a new function to customize
@ -90,23 +90,32 @@ export class Dialog extends LitElement {
// getIsConnectedPromise() immediately sets the resolve property.
private isConnectedPromiseResolve!: () => void;
private isConnectedPromise = this.getIsConnectedPromise();
@query('dialog') private readonly dialog!: HTMLDialogElement|null;
@query('.scrim') private readonly scrim!: HTMLDialogElement|null;
@query('.container') private readonly container!: HTMLDialogElement|null;
@query('.headline') private readonly headline!: HTMLDialogElement|null;
@query('.content') private readonly content!: HTMLDialogElement|null;
@query('.actions') private readonly actions!: HTMLDialogElement|null;
@state() private isAtScrollTop = false;
@state() private isAtScrollBottom = false;
@query('.scroller') private readonly scroller!: HTMLElement|null;
@query('.top.anchor') private readonly topAnchor!: HTMLElement|null;
@query('.bottom.anchor') private readonly bottomAnchor!: HTMLElement|null;
@query('dialog')
private accessor dialog!: HTMLDialogElement|null;
@query('.scrim')
private accessor scrim!: HTMLDialogElement|null;
@query('.container')
private accessor container!: HTMLDialogElement|null;
@query('.headline')
private accessor headline!: HTMLDialogElement|null;
@query('.content')
private accessor content!: HTMLDialogElement|null;
@query('.actions')
private accessor actions!: HTMLDialogElement|null;
@state() private accessor isAtScrollTop = false;
@state() private accessor isAtScrollBottom = false;
@query('.scroller')
private accessor scroller!: HTMLElement|null;
@query('.top.anchor')
private accessor topAnchor!: HTMLElement|null;
@query('.bottom.anchor')
private accessor bottomAnchor!: HTMLElement|null;
private nextClickIsFromContent = false;
private intersectionObserver?: IntersectionObserver;
// Dialogs should not be SSR'd while open, so we can just use runtime checks.
@state() private hasHeadline = false;
@state() private hasActions = false;
@state() private hasIcon = false;
@state() private accessor hasHeadline = false;
@state() private accessor hasActions = false;
@state() private accessor hasIcon = false;
constructor() {
super();

View File

@ -14,17 +14,17 @@ export class Divider extends LitElement {
/**
* Indents the divider with equal padding on both sides.
*/
@property({type: Boolean, reflect: true}) inset = false;
@property({type: Boolean, reflect: true}) accessor inset = false;
/**
* Indents the divider with padding on the leading side.
*/
@property({type: Boolean, reflect: true, attribute: 'inset-start'})
insetStart = false;
accessor insetStart = false;
/**
* Indents the divider with padding on the trailing side.
*/
@property({type: Boolean, reflect: true, attribute: 'inset-end'})
insetEnd = false;
accessor insetEnd = false;
}

View File

@ -6,7 +6,7 @@
import {customElement} from 'lit/decorators.js';
import {Fab, FabVariant} from './internal/fab.js';
import {Fab} from './internal/fab.js';
import {styles} from './internal/fab-branded-styles.css.js';
import {styles as forcedColors} from './internal/forced-colors-styles.css.js';
import {styles as sharedStyles} from './internal/shared-styles.css.js';
@ -52,7 +52,6 @@ export class MdBrandedFab extends Fab {
/**
* Branded FABs have no variants
*/
override variant!: FabVariant;
override getRenderClasses() {
return {

View File

@ -18,7 +18,7 @@ export class Fab extends SharedFab {
/**
* The FAB color variant to render.
*/
@property() variant: FabVariant = 'surface';
@property() accessor variant: FabVariant = 'surface';
override getRenderClasses() {
return {

View File

@ -38,18 +38,18 @@ export abstract class SharedFab extends LitElement {
* NOTE: Branded FABs cannot be sized to `small`, and Extended FABs do not
* have different sizes.
*/
@property({reflect: true}) size: FabSize = 'medium';
@property({reflect: true}) accessor size: FabSize = 'medium';
/**
* The text to display on the FAB.
*/
@property() label = '';
@property() accessor label = '';
/**
* Lowers the FAB's elevation.
*/
@property({type: Boolean}) lowered = false;
@property({type: Boolean}) accessor lowered = false;
protected override render() {
// Needed for closure conformance

View File

@ -15,29 +15,29 @@ import {SurfacePositionTarget} from '../../menu/internal/surfacePositionControll
* A field component.
*/
export class Field extends LitElement implements SurfacePositionTarget {
@property({type: Boolean}) disabled = false;
@property({type: Boolean}) error = false;
@property({type: Boolean}) focused = false;
@property() label = '';
@property({type: Boolean}) populated = false;
@property({type: Boolean}) required = false;
@property({attribute: 'supporting-text'}) supportingText = '';
@property({attribute: 'error-text'}) errorText = '';
@property({type: Number}) count = -1;
@property({type: Number}) max = -1;
@property({type: Boolean}) accessor disabled = false;
@property({type: Boolean}) accessor error = false;
@property({type: Boolean}) accessor focused = false;
@property() accessor label = '';
@property({type: Boolean}) accessor populated = false;
@property({type: Boolean}) accessor required = false;
@property({attribute: 'supporting-text'}) accessor supportingText = '';
@property({attribute: 'error-text'}) accessor errorText = '';
@property({type: Number}) accessor count = -1;
@property({type: Number}) accessor max = -1;
/**
* Whether or not the field has leading content.
*/
@property({type: Boolean, attribute: 'has-start'}) hasStart = false;
@property({type: Boolean, attribute: 'has-start'}) accessor hasStart = false;
/**
* Whether or not the field has trailing content.
*/
@property({type: Boolean, attribute: 'has-end'}) hasEnd = false;
@property({type: Boolean, attribute: 'has-end'}) accessor hasEnd = false;
@queryAssignedElements({slot: 'aria-describedby'})
private readonly slottedAriaDescribedBy!: HTMLElement[];
private accessor slottedAriaDescribedBy!: HTMLElement[];
private get counterText() {
if (this.count < 0 || this.max < 0) {
@ -51,17 +51,20 @@ export class Field extends LitElement implements SurfacePositionTarget {
return this.error && this.errorText ? this.errorText : this.supportingText;
}
@state() private isAnimating = false;
@state() private accessor isAnimating = false;
private labelAnimation?: Animation;
/**
* When set to true, the error text's `role="alert"` will be removed, then
* re-added after an animation frame. This will re-announce an error message
* to screen readers.
*/
@state() private refreshErrorAlert = false;
@query('.label.floating') private readonly floatingLabelEl!: HTMLElement|null;
@query('.label.resting') private readonly restingLabelEl!: HTMLElement|null;
@query('.container') private readonly containerEl!: HTMLElement|null;
@state() private accessor refreshErrorAlert = false;
@query('.label.floating')
private accessor floatingLabelEl!: HTMLElement|null;
@query('.label.resting')
private accessor restingLabelEl!: HTMLElement|null;
@query('.container')
private accessor containerEl!: HTMLElement|null;
/**
* Re-announces the field's error supporting text to screen readers.

View File

@ -23,12 +23,12 @@ export class FocusRing extends LitElement implements Attachable {
/**
* Makes the focus ring visible.
*/
@property({type: Boolean, reflect: true}) visible = false;
@property({type: Boolean, reflect: true}) accessor visible = false;
/**
* Makes the focus ring animate inwards instead of outwards.
*/
@property({type: Boolean, reflect: true}) inward = false;
@property({type: Boolean, reflect: true}) accessor inward = false;
get htmlFor() {
return this.attachableController.htmlFor;

View File

@ -37,45 +37,45 @@ export class IconButton extends LitElement implements FormSubmitter {
/**
* Disables the icon button and makes it non-interactive.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* Flips the icon if it is in an RTL context at startup.
*/
@property({type: Boolean, attribute: 'flip-icon-in-rtl'})
flipIconInRtl = false;
accessor flipIconInRtl = false;
/**
* Sets the underlying `HTMLAnchorElement`'s `href` resource attribute.
*/
@property() href = '';
@property() accessor href = '';
/**
* Sets the underlying `HTMLAnchorElement`'s `target` attribute.
*/
@property() target: LinkTarget|'' = '';
@property() accessor target: LinkTarget|'' = '';
/**
* The `aria-label` of the button when the button is toggleable and selected.
*/
@property({attribute: 'aria-label-selected'}) ariaLabelSelected = '';
@property({attribute: 'aria-label-selected'}) accessor ariaLabelSelected = '';
/**
* When true, the button will toggle between selected and unselected
* states
*/
@property({type: Boolean}) toggle = false;
@property({type: Boolean}) accessor toggle = false;
/**
* Sets the selected state. When false, displays the default icon. When true,
* displays the `selectedIcon`, or the default icon If no `selectedIcon` is
* provided.
*/
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
@property() type: FormSubmitterType = 'submit';
@property() accessor type: FormSubmitterType = 'submit';
@property() value = '';
@property() accessor value = '';
get name() {
return this.getAttribute('name') ?? '';
@ -98,11 +98,11 @@ export class IconButton extends LitElement implements FormSubmitter {
return this[internals].labels;
}
@state() private flipIcon = isRtl(this, this.flipIconInRtl);
@state() private accessor flipIcon = isRtl(this, this.flipIconInRtl);
/** @private */
[internals] =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
/**
* Link buttons cannot be disabled.

View File

@ -25,7 +25,8 @@ class AriaDelegateElement extends LitElement {
requestUpdateOnAriaChange(AriaDelegateElement);
}
@queryAsync('button') readonly button!: Promise<HTMLButtonElement|null>;
@queryAsync('button')
accessor button!: Promise<HTMLButtonElement|null>;
protected override render() {
return html`<button aria-label=${this.ariaLabel || nothing}>Label</button>`;

View File

@ -30,7 +30,7 @@ class FormSubmitterButton extends LitElement {
static formAssociated = true;
type: FormSubmitterType = 'submit';
@property({reflect: true}) name = '';
@property({reflect: true}) accessor name = '';
value = '';
[internals] = this.attachInternals();

View File

@ -12,7 +12,7 @@ import {classMap} from 'lit/directives/class-map.js';
* TODO(b/265340196): add docs
*/
export class Badge extends LitElement {
@property() value = '';
@property() accessor value = '';
protected override render() {
const classes = {'md3-badge--large': this.value};

View File

@ -25,15 +25,15 @@ export class NavigationBar extends LitElement implements NavigationBarState {
requestUpdateOnAriaChange(NavigationBar);
}
@property({type: Number, attribute: 'active-index'}) activeIndex = 0;
@property({type: Number, attribute: 'active-index'}) accessor activeIndex = 0;
@property({type: Boolean, attribute: 'hide-inactive-labels'})
hideInactiveLabels = false;
accessor hideInactiveLabels = false;
tabs: NavigationTab[] = [];
@queryAssignedElements({flatten: true})
private readonly tabsElement!: NavigationTab[];
private accessor tabsElement!: NavigationTab[];
protected override render() {
// Needed for closure conformance

View File

@ -19,8 +19,8 @@ export class NavigationDrawerModal extends LitElement {
requestUpdateOnAriaChange(NavigationDrawerModal);
}
@property({type: Boolean}) opened = false;
@property() pivot: 'start'|'end' = 'end';
@property({type: Boolean}) accessor opened = false;
@property() accessor pivot: 'start'|'end' = 'end';
protected override render() {
const ariaExpanded = this.opened ? 'true' : 'false';

View File

@ -21,8 +21,8 @@ export class NavigationDrawer extends LitElement {
requestUpdateOnAriaChange(NavigationDrawer);
}
@property({type: Boolean}) opened = false;
@property() pivot: 'start'|'end' = 'end';
@property({type: Boolean}) accessor opened = false;
@property() accessor pivot: 'start'|'end' = 'end';
protected override render() {
const ariaExpanded = this.opened ? 'true' : 'false';

View File

@ -25,15 +25,15 @@ export class NavigationTab extends LitElement implements NavigationTabState {
requestUpdateOnAriaChange(NavigationTab);
}
@property({type: Boolean}) disabled = false;
@property({type: Boolean, reflect: true}) active = false;
@property({type: Boolean}) accessor disabled = false;
@property({type: Boolean, reflect: true}) accessor active = false;
@property({type: Boolean, attribute: 'hide-inactive-label'})
hideInactiveLabel = false;
@property() label?: string;
@property({attribute: 'badge-value'}) badgeValue = '';
@property({type: Boolean, attribute: 'show-badge'}) showBadge = false;
accessor hideInactiveLabel = false;
@property() accessor label: string | undefined;
@property({attribute: 'badge-value'}) accessor badgeValue = '';
@property({type: Boolean, attribute: 'show-badge'}) accessor showBadge = false;
@query('button') buttonElement!: HTMLElement|null;
@query('button') accessor buttonElement!: HTMLElement|null;
protected override render() {
// Needed for closure conformance

View File

@ -25,15 +25,15 @@ export class SegmentedButton extends LitElement {
requestUpdateOnAriaChange(SegmentedButton);
}
@property({type: Boolean}) disabled = false;
@property({type: Boolean}) selected = false;
@property() label = '';
@property({type: Boolean, attribute: 'no-checkmark'}) noCheckmark = false;
@property({type: Boolean, attribute: 'has-icon'}) hasIcon = false;
@property({type: Boolean}) accessor disabled = false;
@property({type: Boolean}) accessor selected = false;
@property() accessor label = '';
@property({type: Boolean, attribute: 'no-checkmark'}) accessor noCheckmark = false;
@property({type: Boolean, attribute: 'has-icon'}) accessor hasIcon = false;
@state() private animState = '';
@state() private accessor animState = '';
@queryAssignedElements({slot: 'icon', flatten: true})
private readonly iconElement!: HTMLElement[];
private accessor iconElement!: HTMLElement[];
protected override update(props: PropertyValues<SegmentedButton>) {
this.animState = this.nextAnimationState(props);

View File

@ -21,9 +21,9 @@ export class SegmentedButtonSet extends LitElement {
requestUpdateOnAriaChange(SegmentedButtonSet);
}
@property({type: Boolean}) multiselect = false;
@property({type: Boolean}) accessor multiselect = false;
@queryAssignedElements({flatten: true}) buttons!: SegmentedButton[];
@queryAssignedElements({flatten: true}) accessor buttons!: SegmentedButton[];
getButtonDisabled(index: number): boolean {
if (this.indexOutOfBounds(index)) return false;

View File

@ -46,14 +46,14 @@ export class List extends LitElement {
static override shadowRootOptions:
ShadowRootInit = {mode: 'open', delegatesFocus: true};
@property() type: 'menu'|'menubar'|'listbox'|'list'|'' = 'list';
@property() accessor type: 'menu'|'menubar'|'listbox'|'list'|'' = 'list';
/**
* The tabindex of the underlying list.
*/
@property({type: Number, attribute: 'list-tabindex'}) listTabIndex = 0;
@property({type: Number, attribute: 'list-tabindex'}) accessor listTabIndex = 0;
@query('.list') private listRoot!: HTMLElement|null;
@query('.list') private accessor listRoot!: HTMLElement|null;
/**
* An array of activatable and disableable list items. Queries every assigned
@ -64,7 +64,7 @@ export class List extends LitElement {
* children / directly slotted elements.
*/
@queryAssignedElements({flatten: true, selector: '[md-list-item]'})
items!: ListItem[];
accessor items!: ListItem[];
protected override render() {
return this.renderList();

View File

@ -14,7 +14,7 @@ export class ListItemOnly extends ListItemEl {
/**
* Removes the hover and click ripples from the item when true.
*/
@property({type: Boolean}) noninteractive = false;
@property({type: Boolean}) accessor noninteractive = false;
override getRenderClasses() {
return {

View File

@ -40,32 +40,32 @@ export class ListItemEl extends LitElement implements ListItem {
/**
* The primary, headline text of the list item.
*/
@property() headline = '';
@property() accessor headline = '';
/**
* The one-line supporting text below the headline. Set
* `multiLineSupportingText` to `true` to support multiple lines in the
* supporting text.
*/
@property({attribute: 'supporting-text'}) supportingText = '';
@property({attribute: 'supporting-text'}) accessor supportingText = '';
/**
* Modifies `supportingText` to support multiple lines.
*/
@property({type: Boolean, attribute: 'multi-line-supporting-text'})
multiLineSupportingText = false;
accessor multiLineSupportingText = false;
/**
* The supporting text placed at the end of the item. Overridden by elements
* slotted into the `end` slot.
*/
@property({attribute: 'trailing-supporting-text'})
trailingSupportingText = '';
accessor trailingSupportingText = '';
/**
* Disables the item and makes it non-selectable and non-interactive.
*/
@property({type: Boolean}) disabled = false;
@property({type: Boolean}) accessor disabled = false;
/**
* The tabindex of the underlying item.
@ -73,40 +73,41 @@ export class ListItemEl extends LitElement implements ListItem {
* __NOTE:__ this is overridden by the keyboard behavior of `md-list` and by
* setting `selected`.
*/
@property({type: Number, attribute: 'item-tabindex'}) itemTabIndex = -1;
@property({type: Number, attribute: 'item-tabindex'}) accessor itemTabIndex = -1;
/**
* Whether or not the element is actively being interacted with by md-list.
* When active, tabindex is set to 0, and in some list item variants (like
* md-list-item), focuses the underlying item.
*/
@property({type: Boolean, reflect: true}) active = false;
@property({type: Boolean, reflect: true}) accessor active = false;
/**
* Sets the role of the list item. Set to 'nothing' to clear the role. This
* property will be ignored if `href` is set since the underlying element will
* be a native anchor tag.
*/
@property() type: ListItemRole = 'listitem';
@property() accessor type: ListItemRole = 'listitem';
/**
* READONLY. Sets the `md-list-item` attribute on the element.
*/
@property({type: Boolean, attribute: 'md-list-item', reflect: true})
isListItem = true;
accessor isListItem = true;
/**
* Sets the underlying `HTMLAnchorElement`'s `href` resource attribute.
*/
@property() href = '';
@property() accessor href = '';
/**
* Sets the underlying `HTMLAnchorElement`'s `target` attribute when `href` is
* set.
*/
@property() target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@property() accessor target: '_blank'|'_parent'|'_self'|'_top'|'' = '';
@query('.list-item') protected readonly listItemRoot!: HTMLElement|null;
@query('.list-item')
protected accessor listItemRoot!: HTMLElement|null;
/**
* Only meant to be overridden by subclassing and not by the user. This is

View File

@ -67,9 +67,12 @@ export abstract class Menu extends LitElement {
requestUpdateOnAriaChange(Menu);
}
@query('md-list') private readonly listElement!: List|null;
@query('.menu') private readonly surfaceEl!: HTMLElement|null;
@query('slot') private readonly slotEl!: HTMLSlotElement|null;
@query('md-list')
private accessor listElement!: List|null;
@query('.menu')
private accessor surfaceEl!: HTMLElement|null;
@query('slot')
private accessor slotEl!: HTMLSlotElement|null;
/**
* The ID of the element in the same root node in which the menu should align
@ -78,7 +81,7 @@ export abstract class Menu extends LitElement {
* __NOTE__: anchor or anchorElement must either be an HTMLElement or resolve
* to an HTMLElement in order for menu to open.
*/
@property() anchor = '';
@property() accessor anchor = '';
/**
* Makes the element use `position:fixed` instead of `position:absolute`. In
* most cases, the menu should position itself above most other
@ -88,11 +91,11 @@ export abstract class Menu extends LitElement {
* __NOTE__: Fixed menus will not scroll with the page and will be fixed to
* the window instead.
*/
@property({type: Boolean}) fixed = false;
@property({type: Boolean}) accessor fixed = false;
/**
* Skips the opening and closing animations.
*/
@property({type: Boolean}) quick = false;
@property({type: Boolean}) accessor quick = false;
/**
* Displays overflow content like a submenu.
*
@ -100,12 +103,12 @@ export abstract class Menu extends LitElement {
* `md-menu {max-height:...}`
* and have items overflowing items in the "y" direction.
*/
@property({type: Boolean, attribute: 'has-overflow'}) hasOverflow = false;
@property({type: Boolean, attribute: 'has-overflow'}) accessor hasOverflow = false;
/**
* Opens the menu and makes it visible. Alternative to the `.show()` and
* `.close()` methods
*/
@property({type: Boolean, reflect: true}) open = false;
@property({type: Boolean, reflect: true}) accessor open = false;
/**
* Offsets the menu's inline alignment from the anchor by the given number in
* pixels. This value is direction aware and will follow the LTR / RTL
@ -114,38 +117,38 @@ export abstract class Menu extends LitElement {
* e.g. LTR: positive -> right, negative -> left
* RTL: positive -> left, negative -> right
*/
@property({type: Number, attribute: 'x-offset'}) xOffset = 0;
@property({type: Number, attribute: 'x-offset'}) accessor xOffset = 0;
/**
* Offsets the menu's block alignment from the anchor by the given number in
* pixels.
*
* e.g. positive -> down, negative -> up
*/
@property({type: Number, attribute: 'y-offset'}) yOffset = 0;
@property({type: Number, attribute: 'y-offset'}) accessor yOffset = 0;
/**
* The tabindex of the underlying list element.
*/
@property({type: Number, attribute: 'list-tabindex'}) listTabIndex = 0;
@property({type: Number, attribute: 'list-tabindex'}) accessor listTabIndex = 0;
/**
* The role of the underlying list element.
*/
@property() type: 'menu'|'menubar'|'listbox'|'list' = 'menu';
@property() accessor type: 'menu'|'menubar'|'listbox'|'list' = 'menu';
/**
* The max time between the keystrokes of the typeahead menu behavior before
* it clears the typeahead buffer.
*/
@property({type: Number, attribute: 'typeahead-delay'})
typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
accessor typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
/**
* The corner of the anchor which to align the menu in the standard logical
* property style of <block>_<inline>.
*/
@property({attribute: 'anchor-corner'}) anchorCorner: Corner = 'END_START';
@property({attribute: 'anchor-corner'}) accessor anchorCorner: Corner = 'END_START';
/**
* The corner of the menu which to align the anchor in the standard logical
* property style of <block>_<inline>.
*/
@property({attribute: 'menu-corner'}) menuCorner: Corner = 'START_START';
@property({attribute: 'menu-corner'}) accessor menuCorner: Corner = 'START_START';
/**
* Keeps the user clicks outside the menu.
*
@ -153,7 +156,7 @@ export abstract class Menu extends LitElement {
* `stayOpenOnFocusout`.
*/
@property({type: Boolean, attribute: 'stay-open-on-outside-click'})
stayOpenOnOutsideClick = false;
accessor stayOpenOnOutsideClick = false;
/**
* Keeps the menu open when focus leaves the menu's composed subtree.
*
@ -161,20 +164,20 @@ export abstract class Menu extends LitElement {
* this property to true to opt-out of menu's focuout handling altogether.
*/
@property({type: Boolean, attribute: 'stay-open-on-focusout'})
stayOpenOnFocusout = false;
accessor stayOpenOnFocusout = false;
/**
* After closing, does not restore focus to the last focused element before
* the menu was opened.
*/
@property({type: Boolean, attribute: 'skip-restore-focus'})
skipRestoreFocus = false;
accessor skipRestoreFocus = false;
/**
* The element that should be focused by default once opened.
*/
@property({attribute: 'default-focus'})
defaultFocus: DefaultFocusState = 'LIST_ROOT';
accessor defaultFocus: DefaultFocusState = 'LIST_ROOT';
@state() private typeaheadActive = true;
@state() private accessor typeaheadActive = true;
private readonly openCloseAnimationSignal = createAnimationSignal();

View File

@ -20,21 +20,22 @@ export class MenuItemEl extends ListItemEl implements MenuItem {
* READONLY: self-identifies as a menu item and sets its identifying attribute
*/
@property({type: Boolean, attribute: 'md-menu-item', reflect: true})
isMenuItem = true;
accessor isMenuItem = true;
/**
* Keeps the menu open if clicked or keyboard selected.
*/
@property({type: Boolean, attribute: 'keep-open'}) keepOpen = false;
@property({type: Boolean, attribute: 'keep-open'}) accessor keepOpen = false;
@state() protected hasFocusRing = false;
@state() protected accessor hasFocusRing = false;
/**
* Used for overriding e.g. sub-menu-item.
*/
protected keepOpenOnClick = false;
override readonly type: ListItemRole = 'menuitem';
@property()
override accessor type: ListItemRole = 'menuitem';
protected override onClick() {
if (this.keepOpen || this.keepOpenOnClick) return;

View File

@ -33,29 +33,29 @@ export class SubMenuItem extends MenuItemEl {
/**
* The anchorCorner to set on the submenu.
*/
@property({attribute: 'anchor-corner'}) anchorCorner: Corner = 'START_END';
@property({attribute: 'anchor-corner'}) accessor anchorCorner: Corner = 'START_END';
/**
* The menuCorner to set on the submenu.
*/
@property({attribute: 'menu-corner'}) menuCorner: Corner = 'START_START';
@property({attribute: 'menu-corner'}) accessor menuCorner: Corner = 'START_START';
/**
* The delay between pointerenter and submenu opening.
*/
@property({type: Number, attribute: 'hover-open-delay'}) hoverOpenDelay = 400;
@property({type: Number, attribute: 'hover-open-delay'}) accessor hoverOpenDelay = 400;
/**
* The delay between ponterleave and the submenu closing.
*/
@property({type: Number, attribute: 'hover-close-delay'})
hoverCloseDelay = 400;
accessor hoverCloseDelay = 400;
/**
* Sets the item in the selected visual state when a submenu is opened.
*/
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
@state() protected submenuHover = false;
@state() protected accessor submenuHover = false;
@queryAssignedElements({slot: 'submenu', flatten: true})
private readonly menus!: Menu[];
private accessor menus!: Menu[];
protected override keepOpenOnClick = true;
private previousOpenTimeout = 0;

View File

@ -17,7 +17,7 @@ export class LinearProgress extends Progress {
/**
* Buffer amount to display, a fraction between 0 and 1.
*/
@property({type: Number}) buffer = 1;
@property({type: Number}) accessor buffer = 1;
// Note, the indeterminate animation is rendered with transform %'s
// Previously, this was optimized to use px calculated with the resizeObserver

View File

@ -22,23 +22,23 @@ export abstract class Progress extends LitElement {
/**
* Progress to display, a fraction between 0 and `max`.
*/
@property({type: Number}) value = 0;
@property({type: Number}) accessor value = 0;
/**
* Maximum progress to display, defaults to 1.
*/
@property({type: Number}) max = 1;
@property({type: Number}) accessor max = 1;
/**
* Whether or not to display indeterminate progress, which gives no indication
* to how long an activity will take.
*/
@property({type: Boolean}) indeterminate = false;
@property({type: Boolean}) accessor indeterminate = false;
/**
* Whether or not to render indeterminate mode using 4 colors instead of one.
*/
@property({type: Boolean, attribute: 'four-color'}) fourColor = false;
@property({type: Boolean, attribute: 'four-color'}) accessor fourColor = false;
protected override render() {
// Needed for closure conformance

View File

@ -32,10 +32,10 @@ export class Radio extends LitElement {
/**
* Whether or not the radio is selected.
*/
@property({type: Boolean})
get checked() {
return this[CHECKED];
}
@property({type: Boolean})
set checked(checked: boolean) {
const wasChecked = this.checked;
if (wasChecked === checked) {
@ -54,12 +54,12 @@ export class Radio extends LitElement {
/**
* Whether or not the radio is disabled.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* The element value to use in form submission when checked.
*/
@property() value = 'on';
@property() accessor value = 'on';
/**
* The HTML name to use in form submission.
@ -87,7 +87,7 @@ export class Radio extends LitElement {
private readonly selectionController = new SingleSelectionController(this);
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -86,7 +86,7 @@ export class Ripple extends LitElement implements Attachable {
/**
* Disables the ripple.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
get htmlFor() {
return this.attachableController.htmlFor;
@ -104,10 +104,11 @@ export class Ripple extends LitElement implements Attachable {
}
@state() private hovered = false;
@state() private pressed = false;
@state() private accessor hovered = false;
@state() private accessor pressed = false;
@query('.surface') private readonly mdRoot!: HTMLElement|null;
@query('.surface')
private accessor mdRoot!: HTMLElement|null;
private rippleSize = '';
private rippleScale = '';
private initialSize = 0;

View File

@ -37,15 +37,15 @@ export abstract class Select extends LitElement {
/**
* Opens the menu synchronously with no animation.
*/
@property({type: Boolean}) quick = false;
@property({type: Boolean}) accessor quick = false;
/**
* Whether or not the select is required.
*/
@property({type: Boolean}) required = false;
@property({type: Boolean}) accessor required = false;
/**
* Disables the select.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* The error message that replaces supporting text when `error` is true. If
* `errorText` is an empty string, then the supporting text will continue to
@ -54,49 +54,51 @@ export abstract class Select extends LitElement {
* Calling `reportValidity()` will automatically update `errorText` to the
* native `validationMessage`.
*/
@property({type: String, attribute: 'error-text'}) errorText = '';
@property({type: String, attribute: 'error-text'}) accessor errorText = '';
/**
* The floating label for the field.
*/
@property() label = '';
@property() accessor label = '';
/**
* Conveys additional information below the text field, such as how it should
* be used.
*/
@property({type: String, attribute: 'supporting-text'}) supportingText = '';
@property({type: String, attribute: 'supporting-text'}) accessor supportingText = '';
/**
* Gets or sets whether or not the text field is in a visually invalid state.
*
* Calling `reportValidity()` will automatically update `error`.
*/
@property({type: Boolean, reflect: true}) error = false;
@property({type: Boolean, reflect: true}) accessor error = false;
/**
* Whether or not the underlying md-menu should be position: fixed to display
* in a top-level manner.
*/
@property({type: Boolean, attribute: 'menu-fixed'}) menuFixed = false;
@property({type: Boolean, attribute: 'menu-fixed'}) accessor menuFixed = false;
/**
* The max time between the keystrokes of the typeahead select / menu behavior
* before it clears the typeahead buffer.
*/
@property({type: Number, attribute: 'typeahead-delay'})
typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
accessor typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
/**
* Whether or not the text field has a leading icon. Used for SSR.
*/
@property({type: Boolean, attribute: 'has-leading-icon'})
hasLeadingIcon = false;
accessor hasLeadingIcon = false;
/**
* Text to display in the field. Only set for SSR.
*/
@property({attribute: 'display-text'}) displayText = '';
@property({attribute: 'display-text'}) accessor displayText = '';
@state() private focused = false;
@state() private open = false;
@query('md-menu') private readonly menu!: Menu|null;
@query('#label') private readonly labelEl!: HTMLElement;
@state() private accessor focused = false;
@state() private accessor open = false;
@query('md-menu')
private accessor menu!: Menu|null;
@query('#label')
private accessor labelEl!: HTMLElement;
@queryAssignedElements({slot: 'leadingicon', flatten: true})
private readonly leadingIcons!: Element[];
private accessor leadingIcons!: Element[];
/**
* The value of the currently selected option.
@ -104,11 +106,11 @@ export abstract class Select extends LitElement {
* Note: For SSR, set `[selected]` on the requested option and `displayText`
* rather than setting `value` setting `value` will incur a DOM query.
*/
@property()
get value(): string {
return this[VALUE];
}
@property()
set value(value: string) {
this.lastUserSetValue = value;
this.select(value);
@ -128,13 +130,13 @@ export abstract class Select extends LitElement {
* rather than setting `selectedIndex` setting `selectedIndex` will incur a
* DOM query.
*/
@property({type: Number, attribute: 'selected-index'})
get selectedIndex(): number {
// tslint:disable-next-line:enforce-name-casing
const [_option, index] = (this.getSelectedOptions() ?? [])[0] ?? [];
return index ?? -1;
}
@property({type: Number, attribute: 'selected-index'})
set selectedIndex(index: number) {
this.lastUserSetSelectedIndex = index;
this.selectIndex(index);

View File

@ -21,14 +21,15 @@ export class SelectOptionEl extends MenuItemEl implements SelectOption {
/**
* Form value of the option.
*/
@property() value = '';
@property() accessor value = '';
/**
* Whether or not this option is selected.
*/
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
override readonly type: ListItemRole = 'option';
@property()
override accessor type: ListItemRole = 'option';
override willUpdate(changed: PropertyValues<this>) {
if (changed.has('selected')) {

View File

@ -40,96 +40,96 @@ export class Slider extends LitElement {
/**
* Whether or not the slider is disabled.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* The slider minimum value
*/
@property({type: Number}) min = 0;
@property({type: Number}) accessor min = 0;
/**
* The slider maximum value
*/
@property({type: Number}) max = 100;
@property({type: Number}) accessor max = 100;
/**
* The slider value displayed when range is false.
*/
@property({type: Number}) value?: number;
@property({type: Number}) accessor value: number|undefined;
/**
* The slider start value displayed when range is true.
*/
@property({type: Number, attribute: 'value-start'}) valueStart?: number;
@property({type: Number, attribute: 'value-start'}) accessor valueStart: number|undefined;
/**
* The slider end value displayed when range is true.
*/
@property({type: Number, attribute: 'value-end'}) valueEnd?: number;
@property({type: Number, attribute: 'value-end'}) accessor valueEnd: number|undefined;
/**
* An optional label for the slider's value displayed when range is
* false; if not set, the label is the value itself.
*/
@property({attribute: 'value-label'}) valueLabel = '';
@property({attribute: 'value-label'}) accessor valueLabel = '';
/**
* An optional label for the slider's start value displayed when
* range is true; if not set, the label is the valueStart itself.
*/
@property({attribute: 'value-label-start'}) valueLabelStart = '';
@property({attribute: 'value-label-start'}) accessor valueLabelStart = '';
/**
* An optional label for the slider's end value displayed when
* range is true; if not set, the label is the valueEnd itself.
*/
@property({attribute: 'value-label-end'}) valueLabelEnd = '';
@property({attribute: 'value-label-end'}) accessor valueLabelEnd = '';
/**
* Aria label for the slider's start handle displayed when
* range is true.
*/
@property({attribute: 'aria-label-start'}) ariaLabelStart = '';
@property({attribute: 'aria-label-start'}) accessor ariaLabelStart = '';
/**
* Aria value text for the slider's start value displayed when
* range is true.
*/
@property({attribute: 'aria-valuetext-start'}) ariaValueTextStart = '';
@property({attribute: 'aria-valuetext-start'}) accessor ariaValueTextStart = '';
/**
* Aria label for the slider's end handle displayed when
* range is true.
*/
@property({attribute: 'aria-label-end'}) ariaLabelEnd = '';
@property({attribute: 'aria-label-end'}) accessor ariaLabelEnd = '';
/**
* Aria value text for the slider's end value displayed when
* range is true.
*/
@property({attribute: 'aria-valuetext-end'}) ariaValueTextEnd = '';
@property({attribute: 'aria-valuetext-end'}) accessor ariaValueTextEnd = '';
/**
* The step between values.
*/
@property({type: Number}) step = 1;
@property({type: Number}) accessor step = 1;
/**
* Whether or not to show tick marks.
*/
@property({type: Boolean}) ticks = false;
@property({type: Boolean}) accessor ticks = false;
/**
* Whether or not to show a value label when activated.
*/
@property({type: Boolean}) labeled = false;
@property({type: Boolean}) accessor labeled = false;
/**
* Whether or not to show a value range. When false, the slider displays
* a slideable handle for the value property; when true, it displays
* slideable handles for the valueStart and valueEnd properties.
*/
@property({type: Boolean}) range = false;
@property({type: Boolean}) accessor range = false;
/**
* The HTML name to use in form submission.
@ -179,28 +179,32 @@ export class Slider extends LitElement {
return this.internals.labels;
}
@query('input.start') private readonly inputStart!: HTMLInputElement|null;
@query('.handle.start') private readonly handleStart!: HTMLDivElement|null;
@query('input.start')
private accessor inputStart!: HTMLInputElement|null;
@query('.handle.start')
private accessor handleStart!: HTMLDivElement|null;
@queryAsync('md-ripple.start')
private readonly rippleStart!: Promise<MdRipple|null>;
private accessor rippleStart!: Promise<MdRipple|null>;
@query('input.end') private readonly inputEnd!: HTMLInputElement|null;
@query('.handle.end') private readonly handleEnd!: HTMLDivElement|null;
@query('input.end')
private accessor inputEnd!: HTMLInputElement|null;
@query('.handle.end')
private accessor handleEnd!: HTMLDivElement|null;
@queryAsync('md-ripple.end')
private readonly rippleEnd!: Promise<MdRipple|null>;
private accessor rippleEnd!: Promise<MdRipple|null>;
// handle hover/pressed states are set manually since the handle
// does not receive pointer events so that the native inputs are
// interaction targets.
@state() private handleStartHover = false;
@state() private handleEndHover = false;
@state() private accessor handleStartHover = false;
@state() private accessor handleEndHover = false;
@state() private startOnTop = false;
@state() private handlesOverlapping = false;
@state() private accessor startOnTop = false;
@state() private accessor handlesOverlapping = false;
@state() private renderValueStart?: number;
@state() private renderValueEnd?: number;
@state() private accessor renderValueStart: number|undefined;
@state() private accessor renderValueEnd: number|undefined;
// Note: start aria-* properties are only applied when range=true, which is
// why they do not need to handle both cases.
@ -250,7 +254,7 @@ export class Slider extends LitElement {
private action?: Action;
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -35,25 +35,25 @@ export class Switch extends LitElement {
/**
* Disables the switch and makes it non-interactive.
*/
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* Puts the switch in the selected state and sets the form submission value to
* the `value` property.
*/
@property({type: Boolean}) selected = false;
@property({type: Boolean}) accessor selected = false;
/**
* Shows both the selected and deselected icons.
*/
@property({type: Boolean}) icons = false;
@property({type: Boolean}) accessor icons = false;
/**
* Shows only the selected icon, and not the deselected icon. If `true`,
* overrides the behavior of the `icons` property.
*/
@property({type: Boolean, attribute: 'show-only-selected-icon'})
showOnlySelectedIcon = false;
accessor showOnlySelectedIcon = false;
/**
* When true, require the switch to be selected when participating in
@ -61,13 +61,13 @@ export class Switch extends LitElement {
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#validation
*/
@property({type: Boolean}) required = false;
@property({type: Boolean}) accessor required = false;
/**
* The value associated with this switch on form submission. `null` is
* submitted when `selected` is `false`.
*/
@property() value = 'on';
@property() accessor value = 'on';
/**
* The HTML name to use in form submission.
@ -128,9 +128,10 @@ export class Switch extends LitElement {
return this.internals.willValidate;
}
@query('input') private readonly input!: HTMLInputElement|null;
@query('input')
private accessor input!: HTMLInputElement|null;
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -15,7 +15,7 @@ export class PrimaryTab extends Tab {
/**
* Whether or not the icon renders inline with label or stacked vertically.
*/
@property({type: Boolean, attribute: 'inline-icon'}) inlineIcon = false;
@property({type: Boolean, attribute: 'inline-icon'}) accessor inlineIcon = false;
protected override getContentClasses() {
return {

View File

@ -10,5 +10,5 @@ import {Tab} from './tab.js';
* A secondary tab component.
*/
export class SecondaryTab extends Tab {
protected override fullWidthIndicator = true;
protected override accessor fullWidthIndicator = true;
}

View File

@ -44,33 +44,35 @@ export class Tab extends LitElement {
/**
* Whether or not the tab is `selected`.
**/
@property({type: Boolean, reflect: true}) selected = false;
@property({type: Boolean, reflect: true}) accessor selected = false;
/**
* Whether or not the tab is `focusable`.
*/
@property({type: Boolean}) focusable = false;
@property({type: Boolean}) accessor focusable = false;
/**
* In SSR, set this to true when an icon is present.
*/
@property({type: Boolean, attribute: 'has-icon'}) hasIcon = false;
@property({type: Boolean, attribute: 'has-icon'}) accessor hasIcon = false;
/**
* In SSR, set this to true when there is no label and only an icon.
*/
@property({type: Boolean, attribute: 'icon-only'}) iconOnly = false;
@property({type: Boolean, attribute: 'icon-only'}) accessor iconOnly = false;
@query('.button') private readonly button!: HTMLElement|null;
@query('.button')
private accessor button!: HTMLElement|null;
// note, this is public so it can participate in selection animation.
/** @private */
@query('.indicator') readonly indicator!: HTMLElement;
@state() protected fullWidthIndicator = false;
@query('.indicator')
accessor indicator!: HTMLElement;
@state() protected accessor fullWidthIndicator = false;
@queryAssignedNodes({flatten: true})
private readonly assignedDefaultNodes!: Node[];
private accessor assignedDefaultNodes!: Node[];
@queryAssignedElements({slot: 'icon', flatten: true})
private readonly assignedIcons!: HTMLElement[];
private accessor assignedIcons!: HTMLElement[];
constructor() {
super();

View File

@ -44,26 +44,26 @@ export class Tabs extends LitElement {
/**
* Index of the selected item.
*/
@property({type: Number}) selected = 0;
@property({type: Number}) accessor selected = 0;
/**
* Whether or not to select an item when focused.
*/
@property({type: Boolean, attribute: 'select-on-focus'})
selectOnFocus = false;
accessor selectOnFocus = false;
private previousSelected = -1;
private readonly scrollMargin = 48;
@queryAssignedElements({flatten: true})
private readonly maybeTabItems!: HTMLElement[];
private accessor maybeTabItems!: HTMLElement[];
private get items(): Tab[] {
return this.maybeTabItems.filter(isTab);
}
// this tracks if items have changed, which triggers rendering so they can
// be kept in sync
@state() private itemsDirty = false;
@state() private accessor itemsDirty = false;
/**
* The item currently selected.
@ -87,7 +87,7 @@ export class Tabs extends LitElement {
}
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();

View File

@ -30,10 +30,10 @@ export class TestTable<S extends string = string> extends LitElement {
/** @nocollapse */
static override shadowRootOptions: ShadowRootInit = {mode: 'open'};
@property() override title = 'Title';
@property({type: Array}) states: S[] = [];
@property({type: Array}) templates: Array<TestTableTemplate<S>> = [];
@property({type: Boolean, reflect: true}) dark = false;
@property() override accessor title = 'Title';
@property({type: Array}) accessor states: S[] = [];
@property({type: Array}) accessor templates: Array<TestTableTemplate<S>> = [];
@property({type: Boolean, reflect: true}) accessor dark = false;
protected override render() {
return html`

View File

@ -50,13 +50,13 @@ export abstract class TextField extends LitElement {
/** @nocollapse */
static readonly formAssociated = true;
@property({type: Boolean, reflect: true}) disabled = false;
@property({type: Boolean, reflect: true}) accessor disabled = false;
/**
* Gets or sets whether or not the text field is in a visually invalid state.
*
* Calling `reportValidity()` will automatically update `error`.
*/
@property({type: Boolean, reflect: true}) error = false;
@property({type: Boolean, reflect: true}) accessor error = false;
/**
* The error message that replaces supporting text when `error` is true. If
* `errorText` is an empty string, then the supporting text will continue to
@ -65,47 +65,47 @@ export abstract class TextField extends LitElement {
* Calling `reportValidity()` will automatically update `errorText` to the
* native `validationMessage`.
*/
@property({attribute: 'error-text'}) errorText = '';
@property() label = '';
@property({type: Boolean, reflect: true}) required = false;
@property({attribute: 'error-text'}) accessor errorText = '';
@property() accessor label = '';
@property({type: Boolean, reflect: true}) accessor required = false;
/**
* The current value of the text field. It is always a string.
*/
@property() value = '';
@property() accessor value = '';
/**
* An optional prefix to display before the input value.
*/
@property({attribute: 'prefix-text'}) prefixText = '';
@property({attribute: 'prefix-text'}) accessor prefixText = '';
/**
* An optional suffix to display after the input value.
*/
@property({attribute: 'suffix-text'}) suffixText = '';
@property({attribute: 'suffix-text'}) accessor suffixText = '';
/**
* Whether or not the text field has a leading icon. Used for SSR.
*/
@property({type: Boolean, attribute: 'has-leading-icon'})
hasLeadingIcon = false;
accessor hasLeadingIcon = false;
/**
* Whether or not the text field has a trailing icon. Used for SSR.
*/
@property({type: Boolean, attribute: 'has-trailing-icon'})
hasTrailingIcon = false;
accessor hasTrailingIcon = false;
/**
* Conveys additional information below the text field, such as how it should
* be used.
*/
@property({attribute: 'supporting-text'}) supportingText = '';
@property({attribute: 'supporting-text'}) accessor supportingText = '';
/**
* Override the input text CSS `direction`. Useful for RTL languages that use
* LTR notation for fractions.
*/
@property({attribute: 'text-direction'}) textDirection = '';
@property({attribute: 'text-direction'}) accessor textDirection = '';
/**
* The number of rows to display for a `type="textarea"` text field.
* Defaults to 2.
*/
@property({type: Number}) rows = 2;
@property({type: Number}) accessor rows = 2;
/**
* The associated form element with which this element's value will submit.
@ -132,41 +132,41 @@ export abstract class TextField extends LitElement {
}
// <input> properties
@property({reflect: true}) override inputMode = '';
@property({reflect: true}) override accessor inputMode = '';
/**
* Defines the greatest value in the range of permitted values.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max
*/
@property() max = '';
@property() accessor max = '';
/**
* The maximum number of characters a user can enter into the text field. Set
* to -1 for none.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength
*/
@property({type: Number}) maxLength = -1;
@property({type: Number}) accessor maxLength = -1;
/**
* Defines the most negative value in the range of permitted values.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min
*/
@property() min = '';
@property() accessor min = '';
/**
* The minimum number of characters a user can enter into the text field. Set
* to -1 for none.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength
*/
@property({type: Number}) minLength = -1;
@property({type: Number}) accessor minLength = -1;
/**
* A regular expression that the text field's value must match to pass
* constraint validation.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern
*/
@property() pattern = '';
@property({reflect: true, converter: stringConverter}) placeholder = '';
@property() accessor pattern = '';
@property({reflect: true, converter: stringConverter}) accessor placeholder = '';
/**
* Indicates whether or not a user should be able to edit the text field's
@ -174,7 +174,7 @@ export abstract class TextField extends LitElement {
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly
*/
@property({type: Boolean, reflect: true}) readOnly = false;
@property({type: Boolean, reflect: true}) accessor readOnly = false;
/**
* Gets or sets the direction in which selection occurred.
@ -212,10 +212,10 @@ export abstract class TextField extends LitElement {
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step
*/
@property() step = '';
@property() accessor step = '';
@property({reflect: true})
type: TextFieldType|UnsupportedTextFieldType = 'text';
accessor type: TextFieldType|UnsupportedTextFieldType = 'text';
/**
* Returns the text field's validation error message.
@ -297,31 +297,32 @@ export abstract class TextField extends LitElement {
* Returns true when the text field has been interacted with. Native
* validation errors only display in response to user interactions.
*/
@state() private dirty = false;
@state() private focused = false;
@state() private accessor dirty = false;
@state() private accessor focused = false;
/**
* Whether or not a native error has been reported via `reportValidity()`.
*/
@state() private nativeError = false;
@state() private accessor nativeError = false;
/**
* The validation message displayed from a native error via
* `reportValidity()`.
*/
@state() private nativeErrorText = '';
@state() private accessor nativeErrorText = '';
private get hasError() {
return this.error || this.nativeError;
}
@query('.input')
private readonly inputOrTextarea?: HTMLInputElement|HTMLTextAreaElement|null;
@query('.field') private readonly field?: Field|null;
private accessor inputOrTextarea: HTMLInputElement|HTMLTextAreaElement|null|undefined;
@query('.field')
private accessor field: Field|null|undefined;
@queryAssignedElements({slot: 'leadingicon'})
private readonly leadingIcons!: Element[];
private accessor leadingIcons!: Element[];
@queryAssignedElements({slot: 'trailingicon'})
private readonly trailingIcons!: Element[];
private accessor trailingIcons!: Element[];
private readonly internals =
(this as HTMLElement /* needed for closure */).attachInternals();
((this as HTMLElement) /* needed for closure */).attachInternals();
constructor() {
super();