blob: 32d9923ce180ef1685d10af2ccd166639717ccd6 [file] [log] [blame]
Alex Rudenkoe4465d12021-08-09 11:37:371// Copyright 2021 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import * as LitHtml from '../../lit-html/lit-html.js';
Benedikt Meurerc7c3c1a2023-11-16 15:13:056import * as VisualLogging from '../../visual_logging/visual_logging.js';
Alex Rudenkoe4465d12021-08-09 11:37:377import * as ComponentHelpers from '../helpers/helpers.js';
8import * as IconButton from '../icon_button/icon_button.js';
9
10import buttonStyles from './button.css.js';
11
12declare global {
13 interface HTMLElementTagNameMap {
14 'devtools-button': Button;
15 }
16}
17
18export const enum Variant {
19 PRIMARY = 'primary',
Alex Rudenkof8fd48e2023-11-21 13:20:3520 TONAL = 'tonal',
Kateryna Prokopenko0895c172024-04-17 09:49:1321 OUTLINED = 'outlined',
22 TEXT = 'text',
Alex Rudenkoe6ba3522021-10-15 06:09:4823 TOOLBAR = 'toolbar',
Alex Rudenkofea82db2023-04-25 11:31:4524 // Just like toolbar but has a style similar to a primary button.
25 PRIMARY_TOOLBAR = 'primary_toolbar',
Kateryna Prokopenko0895c172024-04-17 09:49:1326 ICON = 'icon',
Kateryna Prokopenkocc830042024-05-03 16:30:4627 ICON_TOGGLE = 'icon_toggle',
Kateryna Prokopenko17cba892024-07-26 13:33:5628 ADORNER_ICON = 'adorner_icon',
Alex Rudenkoe4465d12021-08-09 11:37:3729}
30
Alex Rudenko1a41fb42021-09-30 09:12:1431export const enum Size {
Kateryna Prokopenko0895c172024-04-17 09:49:1332 MICRO = 'MICRO',
Alex Rudenko1a41fb42021-09-30 09:12:1433 SMALL = 'SMALL',
Kateryna Prokopenko0895c172024-04-17 09:49:1334 REGULAR = 'REGULAR',
Alex Rudenko1a41fb42021-09-30 09:12:1435}
36
Kateryna Prokopenkocc830042024-05-03 16:30:4637export const enum ToggleType {
38 PRIMARY = 'primary-toggle',
39 RED = 'red-toggle',
40}
41
Alex Rudenko351e6f22021-11-25 09:20:0442type ButtonType = 'button'|'submit'|'reset';
43
Alex Rudenkoe6ba3522021-10-15 06:09:4844interface ButtonState {
Alex Rudenko0f8c2b52023-12-29 05:08:5845 iconUrl?: string;
Alex Rudenkoe4465d12021-08-09 11:37:3746 variant?: Variant;
Alex Rudenko1a41fb42021-09-30 09:12:1447 size?: Size;
Alex Rudenko1bef13a2021-10-19 10:20:5548 disabled: boolean;
Kateryna Prokopenkocc830042024-05-03 16:30:4649 toggled?: boolean;
Kateryna Prokopenko17cba892024-07-26 13:33:5650 toggleOnClick?: boolean;
51 checked?: boolean;
52 pressed?: boolean;
Alex Rudenkofce2db02021-11-09 09:25:5753 active: boolean;
Riho Isawabb8f3982021-11-26 11:58:1654 spinner?: boolean;
Alex Rudenko351e6f22021-11-25 09:20:0455 type: ButtonType;
56 value?: string;
Johan Bay5f9228d2022-01-07 08:02:4057 title?: string;
Alex Rudenko770e4c62023-04-26 07:58:2458 iconName?: string;
Kateryna Prokopenkocc830042024-05-03 16:30:4659 toggledIconName?: string;
60 toggleType?: ToggleType;
Benedikt Meurerc7c3c1a2023-11-16 15:13:0561 jslogContext?: string;
Kateryna Prokopenko17cba892024-07-26 13:33:5662 longClickable?: boolean;
Alex Rudenkoe4465d12021-08-09 11:37:3763}
64
Alex Rudenko770e4c62023-04-26 07:58:2465interface CommonButtonData {
66 variant: Variant;
Alex Rudenko0f8c2b52023-12-29 05:08:5867 iconUrl?: string;
Alex Rudenko770e4c62023-04-26 07:58:2468 iconName?: string;
Kateryna Prokopenkocc830042024-05-03 16:30:4669 toggledIconName?: string;
70 toggleType?: ToggleType;
Kateryna Prokopenko17cba892024-07-26 13:33:5671 toggleOnClick?: boolean;
Alex Rudenko770e4c62023-04-26 07:58:2472 size?: Size;
73 disabled?: boolean;
Kateryna Prokopenkocc830042024-05-03 16:30:4674 toggled?: boolean;
Kateryna Prokopenko17cba892024-07-26 13:33:5675 checked?: boolean;
Alex Rudenko770e4c62023-04-26 07:58:2476 active?: boolean;
77 spinner?: boolean;
78 type?: ButtonType;
79 value?: string;
80 title?: string;
Benedikt Meurerc7c3c1a2023-11-16 15:13:0581 jslogContext?: string;
Kateryna Prokopenko17cba892024-07-26 13:33:5682 longClickable?: boolean;
Alex Rudenko770e4c62023-04-26 07:58:2483}
84
85export type ButtonData = CommonButtonData&(|{
Kateryna Prokopenko0895c172024-04-17 09:49:1386 variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,
Alex Rudenko0f8c2b52023-12-29 05:08:5887 iconUrl: string,
88}|{
Kateryna Prokopenko0895c172024-04-17 09:49:1389 variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,
Alex Rudenko770e4c62023-04-26 07:58:2490 iconName: string,
Alex Rudenkoe6ba3522021-10-15 06:09:4891}|{
Kateryna Prokopenko17cba892024-07-26 13:33:5692 variant: Variant.PRIMARY | Variant.OUTLINED | Variant.TONAL | Variant.TEXT | Variant.ADORNER_ICON,
Kateryna Prokopenkocc830042024-05-03 16:30:4693}|{
94 variant: Variant.ICON_TOGGLE,
95 iconName: string,
96 toggledIconName: string,
97 toggleType: ToggleType,
98 toggled: boolean,
Alex Rudenko770e4c62023-04-26 07:58:2499});
Alex Rudenkoe4465d12021-08-09 11:37:37100
101export class Button extends HTMLElement {
Alex Rudenko351e6f22021-11-25 09:20:04102 static formAssociated = true;
Alex Rudenkoe4465d12021-08-09 11:37:37103 static readonly litTagName = LitHtml.literal`devtools-button`;
Tim van der Lippe055956b2021-11-25 16:10:56104 readonly #shadow = this.attachShadow({mode: 'open', delegatesFocus: true});
Tim van der Lippe0ea22df2021-12-15 11:27:37105 readonly #boundRender = this.#render.bind(this);
106 readonly #boundOnClick = this.#onClick.bind(this);
Tim van der Lippe055956b2021-11-25 16:10:56107 readonly #props: ButtonState = {
Kateryna Prokopenko0895c172024-04-17 09:49:13108 size: Size.REGULAR,
Kateryna Prokopenko17cba892024-07-26 13:33:56109 toggleOnClick: true,
Alex Rudenko1bef13a2021-10-19 10:20:55110 disabled: false,
Alex Rudenkofce2db02021-11-09 09:25:57111 active: false,
Riho Isawabb8f3982021-11-26 11:58:16112 spinner: false,
Alex Rudenko351e6f22021-11-25 09:20:04113 type: 'button',
Kateryna Prokopenko17cba892024-07-26 13:33:56114 longClickable: false,
Alex Rudenko1a41fb42021-09-30 09:12:14115 };
Tim van der Lippe055956b2021-11-25 16:10:56116 #isEmpty = true;
Jack Franklin2204d752022-11-21 14:10:10117 #internals = this.attachInternals();
Alex Rudenkoe4465d12021-08-09 11:37:37118
119 constructor() {
120 super();
Alex Rudenko1bef13a2021-10-19 10:20:55121 this.setAttribute('role', 'presentation');
Tim van der Lippe055956b2021-11-25 16:10:56122 this.addEventListener('click', this.#boundOnClick, true);
Alex Rudenkoe4465d12021-08-09 11:37:37123 }
124
125 /**
126 * Perfer using the .data= setter instead of setting the individual properties
127 * for increased type-safety.
128 */
Alex Rudenkoe6ba3522021-10-15 06:09:48129 set data(data: ButtonData) {
Tim van der Lippe055956b2021-11-25 16:10:56130 this.#props.variant = data.variant;
Alex Rudenko0f8c2b52023-12-29 05:08:58131 this.#props.iconUrl = data.iconUrl;
Alex Rudenko770e4c62023-04-26 07:58:24132 this.#props.iconName = data.iconName;
Kateryna Prokopenkocc830042024-05-03 16:30:46133 this.#props.toggledIconName = data.toggledIconName;
Kateryna Prokopenko17cba892024-07-26 13:33:56134 this.#props.toggleOnClick = data.toggleOnClick !== undefined ? data.toggleOnClick : true;
Kateryna Prokopenko0895c172024-04-17 09:49:13135 this.#props.size = Size.REGULAR;
Jack Franklin98adbb52022-07-13 10:23:21136
137 if ('size' in data && data.size) {
138 this.#props.size = data.size;
139 }
Jack Franklin98adbb52022-07-13 10:23:21140
Tim van der Lippe055956b2021-11-25 16:10:56141 this.#props.active = Boolean(data.active);
Jack Franklin98adbb52022-07-13 10:23:21142 this.#props.spinner = Boolean('spinner' in data ? data.spinner : false);
143
144 this.#props.type = 'button';
145 if ('type' in data && data.type) {
146 this.#props.type = data.type;
147 }
Kateryna Prokopenkocc830042024-05-03 16:30:46148 this.#props.toggled = data.toggled;
149 this.#props.toggleType = data.toggleType;
Kateryna Prokopenko17cba892024-07-26 13:33:56150 this.#props.checked = data.checked;
Tim van der Lippe0ea22df2021-12-15 11:27:37151 this.#setDisabledProperty(data.disabled || false);
Johan Bay5f9228d2022-01-07 08:02:40152 this.#props.title = data.title;
Benedikt Meurerc7c3c1a2023-11-16 15:13:05153 this.#props.jslogContext = data.jslogContext;
Kateryna Prokopenko17cba892024-07-26 13:33:56154 this.#props.longClickable = data.longClickable;
Tim van der Lippe2d9a95c2022-01-04 15:18:03155 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenkoe4465d12021-08-09 11:37:37156 }
157
Alex Rudenko0f8c2b52023-12-29 05:08:58158 set iconUrl(iconUrl: string|undefined) {
159 this.#props.iconUrl = iconUrl;
160 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
161 }
162
Alex Rudenko9d873e52023-05-09 14:26:17163 set iconName(iconName: string|undefined) {
164 this.#props.iconName = iconName;
165 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
166 }
167
Kateryna Prokopenkocc830042024-05-03 16:30:46168 set toggledIconName(toggledIconName: string) {
169 this.#props.toggledIconName = toggledIconName;
170 }
171
172 set toggleType(toggleType: ToggleType) {
173 this.#props.toggleType = toggleType;
174 }
175
Alex Rudenkoe4465d12021-08-09 11:37:37176 set variant(variant: Variant) {
Tim van der Lippe055956b2021-11-25 16:10:56177 this.#props.variant = variant;
Tim van der Lippe2d9a95c2022-01-04 15:18:03178 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenkoe4465d12021-08-09 11:37:37179 }
180
Alex Rudenko1a41fb42021-09-30 09:12:14181 set size(size: Size) {
Tim van der Lippe055956b2021-11-25 16:10:56182 this.#props.size = size;
Tim van der Lippe2d9a95c2022-01-04 15:18:03183 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenko1a41fb42021-09-30 09:12:14184 }
185
Alex Rudenko351e6f22021-11-25 09:20:04186 set type(type: ButtonType) {
Tim van der Lippe055956b2021-11-25 16:10:56187 this.#props.type = type;
Tim van der Lippe2d9a95c2022-01-04 15:18:03188 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenko351e6f22021-11-25 09:20:04189 }
190
Randolf Jungffd14242023-04-19 00:32:25191 override set title(title: string) {
Alex Rudenko47efbe12022-01-19 11:48:50192 this.#props.title = title;
193 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
194 }
195
Alex Rudenko1bef13a2021-10-19 10:20:55196 set disabled(disabled: boolean) {
Tim van der Lippe0ea22df2021-12-15 11:27:37197 this.#setDisabledProperty(disabled);
Tim van der Lippe2d9a95c2022-01-04 15:18:03198 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenko1bef13a2021-10-19 10:20:55199 }
200
Kateryna Prokopenko17cba892024-07-26 13:33:56201 set toggleOnClick(toggleOnClick: boolean) {
202 this.#props.toggleOnClick = toggleOnClick;
203 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
204 }
205
Kateryna Prokopenkocc830042024-05-03 16:30:46206 set toggled(toggled: boolean) {
207 this.#props.toggled = toggled;
208 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
209 }
210
Kim-Anh Tranf2e8fca2024-05-14 08:28:22211 get toggled(): boolean {
212 return Boolean(this.#props.toggled);
213 }
214
Kateryna Prokopenko17cba892024-07-26 13:33:56215 set checked(checked: boolean) {
216 this.#props.checked = checked;
217 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
218 }
219
220 set pressed(pressed: boolean) {
221 this.#props.pressed = pressed;
222 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
223 }
224
Alex Rudenkofce2db02021-11-09 09:25:57225 set active(active: boolean) {
Tim van der Lippe055956b2021-11-25 16:10:56226 this.#props.active = active;
Tim van der Lippe2d9a95c2022-01-04 15:18:03227 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenkofce2db02021-11-09 09:25:57228 }
229
Alex Rudenko409fe742023-10-26 11:56:23230 get active(): boolean {
231 return this.#props.active;
232 }
233
Riho Isawabb8f3982021-11-26 11:58:16234 set spinner(spinner: boolean) {
235 this.#props.spinner = spinner;
Tim van der Lippe2d9a95c2022-01-04 15:18:03236 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Riho Isawabb8f3982021-11-26 11:58:16237 }
238
Benedikt Meurerc7c3c1a2023-11-16 15:13:05239 get jslogContext(): string|undefined {
240 return this.#props.jslogContext;
241 }
242
243 set jslogContext(jslogContext: string|undefined) {
244 this.#props.jslogContext = jslogContext;
245 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
246 }
247
Kateryna Prokopenko17cba892024-07-26 13:33:56248 set longClickable(longClickable: boolean) {
249 this.#props.longClickable = longClickable;
250 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
251 }
252
Tim van der Lippe0ea22df2021-12-15 11:27:37253 #setDisabledProperty(disabled: boolean): void {
Tim van der Lippe055956b2021-11-25 16:10:56254 this.#props.disabled = disabled;
Kateryna Prokopenko17cba892024-07-26 13:33:56255 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenko1bef13a2021-10-19 10:20:55256 }
257
Randolf Jungffd14242023-04-19 00:32:25258 override focus(): void {
Tim van der Lippe055956b2021-11-25 16:10:56259 this.#shadow.querySelector('button')?.focus();
Alex Rudenko48711102021-09-29 08:24:10260 }
261
Alex Rudenkoe4465d12021-08-09 11:37:37262 connectedCallback(): void {
Tim van der Lippe055956b2021-11-25 16:10:56263 this.#shadow.adoptedStyleSheets = [buttonStyles];
Tim van der Lippe2d9a95c2022-01-04 15:18:03264 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenkoe4465d12021-08-09 11:37:37265 }
266
Tim van der Lippe0ea22df2021-12-15 11:27:37267 #onClick(event: Event): void {
Tim van der Lippe055956b2021-11-25 16:10:56268 if (this.#props.disabled) {
Alex Rudenko1bef13a2021-10-19 10:20:55269 event.stopPropagation();
270 event.preventDefault();
Alex Rudenko351e6f22021-11-25 09:20:04271 return;
272 }
Tim van der Lippe055956b2021-11-25 16:10:56273 if (this.form && this.#props.type === 'submit') {
Alex Rudenko351e6f22021-11-25 09:20:04274 event.preventDefault();
275 this.form.dispatchEvent(new SubmitEvent('submit', {
276 submitter: this,
277 }));
278 }
Tim van der Lippe055956b2021-11-25 16:10:56279 if (this.form && this.#props.type === 'reset') {
Alex Rudenko351e6f22021-11-25 09:20:04280 event.preventDefault();
281 this.form.reset();
Alex Rudenko1bef13a2021-10-19 10:20:55282 }
Kateryna Prokopenko17cba892024-07-26 13:33:56283 if (this.#props.toggleOnClick && this.#props.variant === Variant.ICON_TOGGLE && this.#props.iconName) {
Kateryna Prokopenkocc830042024-05-03 16:30:46284 this.toggled = !this.#props.toggled;
285 }
Alex Rudenko1bef13a2021-10-19 10:20:55286 }
287
Tim van der Lippe0ea22df2021-12-15 11:27:37288 #onSlotChange(event: Event): void {
Alex Rudenko50b3a3e2021-09-29 11:01:46289 const slot = event.target as HTMLSlotElement | undefined;
290 const nodes = slot?.assignedNodes();
Tim van der Lippe055956b2021-11-25 16:10:56291 this.#isEmpty = !nodes || !Boolean(nodes.length);
Tim van der Lippe2d9a95c2022-01-04 15:18:03292 void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);
Alex Rudenko50b3a3e2021-09-29 11:01:46293 }
294
Alex Rudenkofea82db2023-04-25 11:31:45295 #isToolbarVariant(): boolean {
296 return this.#props.variant === Variant.TOOLBAR || this.#props.variant === Variant.PRIMARY_TOOLBAR;
297 }
298
Tim van der Lippe0ea22df2021-12-15 11:27:37299 #render(): void {
Tim van der Lippe055956b2021-11-25 16:10:56300 if (!this.#props.variant) {
Alex Rudenkoe4465d12021-08-09 11:37:37301 throw new Error('Button requires a variant to be defined');
302 }
Alex Rudenkofea82db2023-04-25 11:31:45303 if (this.#isToolbarVariant()) {
Alex Rudenko0f8c2b52023-12-29 05:08:58304 if (!this.#props.iconUrl && !this.#props.iconName) {
Alex Rudenkoe6ba3522021-10-15 06:09:48305 throw new Error('Toolbar button requires an icon');
306 }
Tim van der Lippe055956b2021-11-25 16:10:56307 if (!this.#isEmpty) {
Jack Franklin7e5333c2023-02-07 17:13:19308 throw new Error('Toolbar button does not accept children');
Alex Rudenkoe6ba3522021-10-15 06:09:48309 }
310 }
Kateryna Prokopenko0895c172024-04-17 09:49:13311 if (this.#props.variant === Variant.ICON) {
Alex Rudenko0f8c2b52023-12-29 05:08:58312 if (!this.#props.iconUrl && !this.#props.iconName) {
Kateryna Prokopenko0895c172024-04-17 09:49:13313 throw new Error('Icon button requires an icon');
Wolfgang Beyerbabb2202022-03-10 16:32:37314 }
315 if (!this.#isEmpty) {
Kateryna Prokopenko0895c172024-04-17 09:49:13316 throw new Error('Icon button does not accept children');
Wolfgang Beyerbabb2202022-03-10 16:32:37317 }
318 }
Alex Rudenko0f8c2b52023-12-29 05:08:58319 if (this.#props.iconName && this.#props.iconUrl) {
320 throw new Error('Both iconName and iconUrl are provided.');
321 }
322 const hasIcon = Boolean(this.#props.iconUrl) || Boolean(this.#props.iconName);
Alex Rudenkoe4465d12021-08-09 11:37:37323 const classes = {
Tim van der Lippe055956b2021-11-25 16:10:56324 primary: this.#props.variant === Variant.PRIMARY,
Alex Rudenkof8fd48e2023-11-21 13:20:35325 tonal: this.#props.variant === Variant.TONAL,
Kateryna Prokopenko0895c172024-04-17 09:49:13326 outlined: this.#props.variant === Variant.OUTLINED,
327 text: this.#props.variant === Variant.TEXT,
Alex Rudenkofea82db2023-04-25 11:31:45328 toolbar: this.#isToolbarVariant(),
329 'primary-toolbar': this.#props.variant === Variant.PRIMARY_TOOLBAR,
Kateryna Prokopenkocc830042024-05-03 16:30:46330 icon: this.#props.variant === Variant.ICON || this.#props.variant === Variant.ICON_TOGGLE,
331 'primary-toggle': this.#props.toggleType === ToggleType.PRIMARY,
332 'red-toggle': this.#props.toggleType === ToggleType.RED,
333 toggled: Boolean(this.#props.toggled),
Kateryna Prokopenko17cba892024-07-26 13:33:56334 checked: Boolean(this.#props.checked),
Alex Rudenko770e4c62023-04-26 07:58:24335 'text-with-icon': hasIcon && !this.#isEmpty,
336 'only-icon': hasIcon && this.#isEmpty,
Alex Rudenko0bd7a1b2024-01-04 06:58:33337 'only-text': !hasIcon && !this.#isEmpty,
Kateryna Prokopenko0895c172024-04-17 09:49:13338 micro: this.#props.size === Size.MICRO,
Alex Rudenkoc122e162024-01-31 18:56:05339 small: Boolean(this.#props.size === Size.SMALL),
Tim van der Lippe055956b2021-11-25 16:10:56340 active: this.#props.active,
Alex Rudenkoe4465d12021-08-09 11:37:37341 };
Riho Isawabb8f3982021-11-26 11:58:16342 const spinnerClasses = {
343 primary: this.#props.variant === Variant.PRIMARY,
Kateryna Prokopenko0895c172024-04-17 09:49:13344 outlined: this.#props.variant === Variant.OUTLINED,
Riho Isawabb8f3982021-11-26 11:58:16345 disabled: Boolean(this.#props.disabled),
Alex Rudenko3aa078e2024-01-03 13:52:47346 spinner: true,
Riho Isawabb8f3982021-11-26 11:58:16347 };
Benedikt Meurerc7c3c1a2023-11-16 15:13:05348 const jslog =
349 this.#props.jslogContext && VisualLogging.action().track({click: true}).context(this.#props.jslogContext);
Alex Rudenkoe4465d12021-08-09 11:37:37350 // clang-format off
351 LitHtml.render(
352 LitHtml.html`
Kateryna Prokopenko17cba892024-07-26 13:33:56353 <button title=${LitHtml.Directives.ifDefined(this.#props.title)} .disabled=${this.#props.disabled} class=${LitHtml.Directives.classMap(classes)} aria-pressed=${LitHtml.Directives.ifDefined(this.#props.pressed)} jslog=${LitHtml.Directives.ifDefined(jslog)}>
Benedikt Meurerea0cf6f2024-01-02 11:52:28354 ${hasIcon
355 ? LitHtml.html`
Kateryna Prokopenkocc830042024-05-03 16:30:46356 <${IconButton.Icon.Icon.litTagName} name=${this.#props.toggled ? this.#props.toggledIconName : this.#props.iconName || this.#props.iconUrl}>
Benedikt Meurerea0cf6f2024-01-02 11:52:28357 </${IconButton.Icon.Icon.litTagName}>`
358 : ''}
Kateryna Prokopenko17cba892024-07-26 13:33:56359 ${this.#props.longClickable ? LitHtml.html`<${IconButton.Icon.Icon.litTagName} name=${'triangle-bottom-right'} class="long-click">
360 </${IconButton.Icon.Icon.litTagName}>`
361 : ''}
Riho Isawabb8f3982021-11-26 11:58:16362 ${this.#props.spinner ? LitHtml.html`<span class=${LitHtml.Directives.classMap(spinnerClasses)}></span>` : ''}
Tim van der Lippe0ea22df2021-12-15 11:27:37363 <slot @slotchange=${this.#onSlotChange}></slot>
Alex Rudenkoe4465d12021-08-09 11:37:37364 </button>
Tim van der Lippe055956b2021-11-25 16:10:56365 `, this.#shadow, {host: this});
Alex Rudenkoe4465d12021-08-09 11:37:37366 // clang-format on
367 }
Alex Rudenko351e6f22021-11-25 09:20:04368
369 // Based on https://web.dev/more-capable-form-controls/ to make custom elements form-friendly.
370 // Form controls usually expose a "value" property.
371 get value(): string {
Tim van der Lippe055956b2021-11-25 16:10:56372 return this.#props.value || '';
Alex Rudenko351e6f22021-11-25 09:20:04373 }
374 set value(value: string) {
Tim van der Lippe055956b2021-11-25 16:10:56375 this.#props.value = value;
Alex Rudenko351e6f22021-11-25 09:20:04376 }
377
378 // The following properties and methods aren't strictly required,
379 // but browser-level form controls provide them. Providing them helps
380 // ensure consistency with browser-provided controls.
Jack Franklin061f09c2022-07-12 14:31:09381 get form(): HTMLFormElement|null {
Tim van der Lippe055956b2021-11-25 16:10:56382 return this.#internals.form;
Alex Rudenko351e6f22021-11-25 09:20:04383 }
384 get name(): string|null {
385 return this.getAttribute('name');
386 }
387 get type(): ButtonType {
Tim van der Lippe055956b2021-11-25 16:10:56388 return this.#props.type;
Alex Rudenko351e6f22021-11-25 09:20:04389 }
390 get validity(): ValidityState {
Tim van der Lippe055956b2021-11-25 16:10:56391 return this.#internals.validity;
Alex Rudenko351e6f22021-11-25 09:20:04392 }
393 get validationMessage(): string {
Tim van der Lippe055956b2021-11-25 16:10:56394 return this.#internals.validationMessage;
Alex Rudenko351e6f22021-11-25 09:20:04395 }
396 get willValidate(): boolean {
Tim van der Lippe055956b2021-11-25 16:10:56397 return this.#internals.willValidate;
Alex Rudenko351e6f22021-11-25 09:20:04398 }
Jack Franklin2204d752022-11-21 14:10:10399 checkValidity(): boolean {
Tim van der Lippe055956b2021-11-25 16:10:56400 return this.#internals.checkValidity();
Alex Rudenko351e6f22021-11-25 09:20:04401 }
Jack Franklin2204d752022-11-21 14:10:10402 reportValidity(): boolean {
Tim van der Lippe055956b2021-11-25 16:10:56403 return this.#internals.reportValidity();
Alex Rudenko351e6f22021-11-25 09:20:04404 }
Alex Rudenkoe4465d12021-08-09 11:37:37405}
406
Benedikt Meurerd87daa62024-02-20 11:00:38407customElements.define('devtools-button', Button);