@material/web 2.5.1-nightly.b4de401.0 → 2.5.1-nightly.bd360db.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/button/internal/button.d.ts +10 -0
  2. package/button/internal/button.js +23 -2
  3. package/button/internal/button.js.map +1 -1
  4. package/chips/internal/assist-chip.d.ts +10 -0
  5. package/chips/internal/assist-chip.js +20 -1
  6. package/chips/internal/assist-chip.js.map +1 -1
  7. package/chips/internal/chip.js +3 -1
  8. package/chips/internal/chip.js.map +1 -1
  9. package/chips/internal/input-chip.d.ts +10 -0
  10. package/chips/internal/input-chip.js +20 -1
  11. package/chips/internal/input-chip.js.map +1 -1
  12. package/custom-elements.json +25295 -20106
  13. package/iconbutton/internal/icon-button.d.ts +10 -0
  14. package/iconbutton/internal/icon-button.js +21 -2
  15. package/iconbutton/internal/icon-button.js.map +1 -1
  16. package/internal/directives/safe-href.d.ts +23 -0
  17. package/internal/directives/safe-href.js +44 -0
  18. package/internal/directives/safe-href.js.map +1 -0
  19. package/labs/aria/buttons/keyboard_click_handler.d.ts +25 -0
  20. package/labs/aria/buttons/keyboard_click_handler.js +74 -0
  21. package/labs/aria/buttons/keyboard_click_handler.js.map +1 -0
  22. package/labs/aria/buttons/md-aria-toggle.d.ts +29 -0
  23. package/labs/aria/buttons/md-aria-toggle.js +67 -0
  24. package/labs/aria/buttons/md-aria-toggle.js.map +1 -0
  25. package/labs/aria/buttons/toggle.d.ts +40 -0
  26. package/labs/aria/buttons/toggle.js +100 -0
  27. package/labs/aria/buttons/toggle.js.map +1 -0
  28. package/labs/aria/command.d.ts +18 -0
  29. package/labs/aria/command.js +204 -0
  30. package/labs/aria/command.js.map +1 -0
  31. package/labs/aria/menu/fieldset.d.ts +36 -0
  32. package/labs/aria/menu/fieldset.js +103 -0
  33. package/labs/aria/menu/fieldset.js.map +1 -0
  34. package/labs/aria/menu/internal.d.ts +15 -0
  35. package/labs/aria/menu/internal.js +16 -0
  36. package/labs/aria/menu/internal.js.map +1 -0
  37. package/labs/aria/menu/md-aria-fieldset.d.ts +11 -0
  38. package/labs/aria/menu/md-aria-fieldset.js +8 -0
  39. package/labs/aria/menu/md-aria-fieldset.js.map +1 -0
  40. package/labs/aria/menu/md-aria-menuitem.d.ts +11 -0
  41. package/labs/aria/menu/md-aria-menuitem.js +8 -0
  42. package/labs/aria/menu/md-aria-menuitem.js.map +1 -0
  43. package/labs/aria/menu/md-aria-menulist.d.ts +11 -0
  44. package/labs/aria/menu/md-aria-menulist.js +8 -0
  45. package/labs/aria/menu/md-aria-menulist.js.map +1 -0
  46. package/labs/aria/menu/menuitem.d.ts +59 -0
  47. package/labs/aria/menu/menuitem.js +237 -0
  48. package/labs/aria/menu/menuitem.js.map +1 -0
  49. package/labs/aria/menu/menulist.d.ts +21 -0
  50. package/labs/aria/menu/menulist.js +102 -0
  51. package/labs/aria/menu/menulist.js.map +1 -0
  52. package/labs/aria/menu/shared-slotted-content.d.ts +10 -0
  53. package/labs/aria/menu/shared-slotted-content.js +51 -0
  54. package/labs/aria/menu/shared-slotted-content.js.map +1 -0
  55. package/labs/aria/pseudo-classes.d.ts +19 -0
  56. package/labs/aria/pseudo-classes.js +22 -0
  57. package/labs/aria/pseudo-classes.js.map +1 -0
  58. package/labs/aria/query-associated.d.ts +23 -0
  59. package/labs/aria/query-associated.js +36 -0
  60. package/labs/aria/query-associated.js.map +1 -0
  61. package/labs/aria/tabs/md-aria-tab.d.ts +11 -0
  62. package/labs/aria/tabs/md-aria-tab.js +8 -0
  63. package/labs/aria/tabs/md-aria-tab.js.map +1 -0
  64. package/labs/aria/tabs/md-aria-tablist.d.ts +11 -0
  65. package/labs/aria/tabs/md-aria-tablist.js +8 -0
  66. package/labs/aria/tabs/md-aria-tablist.js.map +1 -0
  67. package/labs/aria/tabs/md-aria-tabpanel.d.ts +11 -0
  68. package/labs/aria/tabs/md-aria-tabpanel.js +8 -0
  69. package/labs/aria/tabs/md-aria-tabpanel.js.map +1 -0
  70. package/labs/aria/tabs/tab.d.ts +33 -0
  71. package/labs/aria/tabs/tab.js +93 -0
  72. package/labs/aria/tabs/tab.js.map +1 -0
  73. package/labs/aria/tabs/tablist.d.ts +65 -0
  74. package/labs/aria/tabs/tablist.js +206 -0
  75. package/labs/aria/tabs/tablist.js.map +1 -0
  76. package/labs/aria/tabs/tabpanel.d.ts +26 -0
  77. package/labs/aria/tabs/tabpanel.js +53 -0
  78. package/labs/aria/tabs/tabpanel.js.map +1 -0
  79. package/labs/gb/components/appbar/_app-bar-tokens.scss +136 -0
  80. package/labs/gb/components/appbar/app-bar-element.d.ts +54 -0
  81. package/labs/gb/components/appbar/app-bar-element.js +145 -0
  82. package/labs/gb/components/appbar/app-bar-element.js.map +1 -0
  83. package/labs/gb/components/appbar/app-bar.css +4 -0
  84. package/labs/gb/components/appbar/app-bar.css.map +1 -0
  85. package/labs/gb/components/appbar/app-bar.cssresult.d.ts +3 -0
  86. package/labs/gb/components/appbar/app-bar.cssresult.js +14 -0
  87. package/labs/gb/components/appbar/app-bar.cssresult.js.map +1 -0
  88. package/labs/gb/components/appbar/app-bar.d.ts +71 -0
  89. package/labs/gb/components/appbar/app-bar.js +96 -0
  90. package/labs/gb/components/appbar/app-bar.js.map +1 -0
  91. package/labs/gb/components/appbar/app-bar.scss +168 -0
  92. package/labs/gb/components/appbar/md-gb-app-bar.d.ts +12 -0
  93. package/labs/gb/components/appbar/md-gb-app-bar.js +8 -0
  94. package/labs/gb/components/appbar/md-gb-app-bar.js.map +1 -0
  95. package/labs/gb/components/badge/badge-element.d.ts +1 -0
  96. package/labs/gb/components/badge/badge-element.js +1 -0
  97. package/labs/gb/components/badge/badge-element.js.map +1 -1
  98. package/labs/gb/components/badge/badge.css +1 -1
  99. package/labs/gb/components/badge/badge.css.map +1 -1
  100. package/labs/gb/components/badge/badge.cssresult.js +1 -1
  101. package/labs/gb/components/badge/badge.cssresult.js.map +1 -1
  102. package/labs/gb/components/badge/badge.scss +1 -0
  103. package/labs/gb/components/button/_button-tokens.scss +28 -22
  104. package/labs/gb/components/button/button-element.d.ts +20 -5
  105. package/labs/gb/components/button/button-element.js +43 -8
  106. package/labs/gb/components/button/button-element.js.map +1 -1
  107. package/labs/gb/components/button/button.css +1 -1
  108. package/labs/gb/components/button/button.css.map +1 -1
  109. package/labs/gb/components/button/button.cssresult.js +1 -1
  110. package/labs/gb/components/button/button.cssresult.js.map +1 -1
  111. package/labs/gb/components/button/button.js +1 -1
  112. package/labs/gb/components/button/button.js.map +1 -1
  113. package/labs/gb/components/button/button.scss +5 -6
  114. package/labs/gb/components/card/card-element.d.ts +1 -0
  115. package/labs/gb/components/card/card-element.js +1 -0
  116. package/labs/gb/components/card/card-element.js.map +1 -1
  117. package/labs/gb/components/checkbox/checkbox-element.d.ts +1 -0
  118. package/labs/gb/components/checkbox/checkbox-element.js +1 -0
  119. package/labs/gb/components/checkbox/checkbox-element.js.map +1 -1
  120. package/labs/gb/components/chip/_chip-tokens.scss +167 -0
  121. package/labs/gb/components/chip/chip-element.d.ts +84 -0
  122. package/labs/gb/components/chip/chip-element.js +255 -0
  123. package/labs/gb/components/chip/chip-element.js.map +1 -0
  124. package/labs/gb/components/chip/chip.css +4 -0
  125. package/labs/gb/components/chip/chip.css.map +1 -0
  126. package/labs/gb/components/chip/chip.cssresult.d.ts +3 -0
  127. package/labs/gb/components/chip/chip.cssresult.js +14 -0
  128. package/labs/gb/components/chip/chip.cssresult.js.map +1 -0
  129. package/labs/gb/components/chip/chip.d.ts +77 -0
  130. package/labs/gb/components/chip/chip.js +99 -0
  131. package/labs/gb/components/chip/chip.js.map +1 -0
  132. package/labs/gb/components/chip/chip.scss +100 -0
  133. package/labs/gb/components/chip/md-gb-chip.d.ts +13 -0
  134. package/labs/gb/components/chip/md-gb-chip.js +9 -0
  135. package/labs/gb/components/chip/md-gb-chip.js.map +1 -0
  136. package/labs/gb/components/divider/divider-element.d.ts +1 -0
  137. package/labs/gb/components/divider/divider-element.js +1 -0
  138. package/labs/gb/components/divider/divider-element.js.map +1 -1
  139. package/labs/gb/components/fab/_fab-tokens.scss +4 -1
  140. package/labs/gb/components/fab/fab-element.d.ts +2 -0
  141. package/labs/gb/components/fab/fab-element.js +2 -0
  142. package/labs/gb/components/fab/fab-element.js.map +1 -1
  143. package/labs/gb/components/fab/fab.css +1 -1
  144. package/labs/gb/components/fab/fab.css.map +1 -1
  145. package/labs/gb/components/fab/fab.cssresult.js +1 -1
  146. package/labs/gb/components/fab/fab.cssresult.js.map +1 -1
  147. package/labs/gb/components/fab/fab.scss +2 -0
  148. package/labs/gb/components/iconbutton/_icon-button-tokens.scss +13 -4
  149. package/labs/gb/components/iconbutton/icon-button-element.d.ts +15 -1
  150. package/labs/gb/components/iconbutton/icon-button-element.js +38 -4
  151. package/labs/gb/components/iconbutton/icon-button-element.js.map +1 -1
  152. package/labs/gb/components/iconbutton/icon-button.css +1 -1
  153. package/labs/gb/components/iconbutton/icon-button.css.map +1 -1
  154. package/labs/gb/components/iconbutton/icon-button.cssresult.js +1 -1
  155. package/labs/gb/components/iconbutton/icon-button.cssresult.js.map +1 -1
  156. package/labs/gb/components/iconbutton/icon-button.js +1 -1
  157. package/labs/gb/components/iconbutton/icon-button.js.map +1 -1
  158. package/labs/gb/components/iconbutton/icon-button.scss +8 -0
  159. package/labs/gb/components/list/_list-tokens.scss +11 -14
  160. package/labs/gb/components/list/list-element.d.ts +1 -0
  161. package/labs/gb/components/list/list-element.js +1 -0
  162. package/labs/gb/components/list/list-element.js.map +1 -1
  163. package/labs/gb/components/list/list-item-element.d.ts +5 -0
  164. package/labs/gb/components/list/list-item-element.js +5 -0
  165. package/labs/gb/components/list/list-item-element.js.map +1 -1
  166. package/labs/gb/components/list/list.css +1 -1
  167. package/labs/gb/components/list/list.css.map +1 -1
  168. package/labs/gb/components/list/list.cssresult.js +1 -1
  169. package/labs/gb/components/list/list.cssresult.js.map +1 -1
  170. package/labs/gb/components/list/list.scss +6 -0
  171. package/labs/gb/components/menu/_menu-tokens.scss +45 -16
  172. package/labs/gb/components/menu/menu-element.d.ts +1 -0
  173. package/labs/gb/components/menu/menu-element.js +1 -0
  174. package/labs/gb/components/menu/menu-element.js.map +1 -1
  175. package/labs/gb/components/menu/menu-group-element.d.ts +1 -0
  176. package/labs/gb/components/menu/menu-group-element.js +1 -0
  177. package/labs/gb/components/menu/menu-group-element.js.map +1 -1
  178. package/labs/gb/components/menu/menu-item-element.d.ts +5 -1
  179. package/labs/gb/components/menu/menu-item-element.js +5 -1
  180. package/labs/gb/components/menu/menu-item-element.js.map +1 -1
  181. package/labs/gb/components/menu/menu.css +1 -1
  182. package/labs/gb/components/menu/menu.css.map +1 -1
  183. package/labs/gb/components/menu/menu.cssresult.js +1 -1
  184. package/labs/gb/components/menu/menu.cssresult.js.map +1 -1
  185. package/labs/gb/components/menu/menu.scss +4 -0
  186. package/labs/gb/components/radio/radio-element.d.ts +1 -0
  187. package/labs/gb/components/radio/radio-element.js +1 -0
  188. package/labs/gb/components/radio/radio-element.js.map +1 -1
  189. package/labs/gb/components/shared/pseudo-classes.d.ts +1 -7
  190. package/labs/gb/components/shared/pseudo-classes.js +1 -9
  191. package/labs/gb/components/shared/pseudo-classes.js.map +1 -1
  192. package/labs/gb/components/shared/update-class-list.d.ts +22 -0
  193. package/labs/gb/components/shared/update-class-list.js +26 -0
  194. package/labs/gb/components/shared/update-class-list.js.map +1 -0
  195. package/labs/gb/components/splitbutton/split-button-element.d.ts +1 -0
  196. package/labs/gb/components/splitbutton/split-button-element.js +1 -0
  197. package/labs/gb/components/splitbutton/split-button-element.js.map +1 -1
  198. package/labs/gb/components/switch/switch-element.d.ts +1 -0
  199. package/labs/gb/components/switch/switch-element.js +1 -0
  200. package/labs/gb/components/switch/switch-element.js.map +1 -1
  201. package/labs/gb/components/switch/switch.js +5 -2
  202. package/labs/gb/components/switch/switch.js.map +1 -1
  203. package/labs/gb/components/tabs/_tabs-tokens.scss +177 -0
  204. package/labs/gb/components/tabs/md-gb-tab.d.ts +12 -0
  205. package/labs/gb/components/tabs/md-gb-tab.js +8 -0
  206. package/labs/gb/components/tabs/md-gb-tab.js.map +1 -0
  207. package/labs/gb/components/tabs/md-gb-tabs.d.ts +12 -0
  208. package/labs/gb/components/tabs/md-gb-tabs.js +8 -0
  209. package/labs/gb/components/tabs/md-gb-tabs.js.map +1 -0
  210. package/labs/gb/components/tabs/tab-element.d.ts +42 -0
  211. package/labs/gb/components/tabs/tab-element.js +75 -0
  212. package/labs/gb/components/tabs/tab-element.js.map +1 -0
  213. package/labs/gb/components/tabs/tabs-element.d.ts +37 -0
  214. package/labs/gb/components/tabs/tabs-element.js +67 -0
  215. package/labs/gb/components/tabs/tabs-element.js.map +1 -0
  216. package/labs/gb/components/tabs/tabs.css +4 -0
  217. package/labs/gb/components/tabs/tabs.css.map +1 -0
  218. package/labs/gb/components/tabs/tabs.cssresult.d.ts +3 -0
  219. package/labs/gb/components/tabs/tabs.cssresult.js +14 -0
  220. package/labs/gb/components/tabs/tabs.cssresult.js.map +1 -0
  221. package/labs/gb/components/tabs/tabs.d.ts +98 -0
  222. package/labs/gb/components/tabs/tabs.js +112 -0
  223. package/labs/gb/components/tabs/tabs.js.map +1 -0
  224. package/labs/gb/components/tabs/tabs.scss +301 -0
  225. package/labs/gb/components/toolbar/_toolbar-tokens.scss +70 -0
  226. package/labs/gb/components/toolbar/md-gb-toolbar.d.ts +12 -0
  227. package/labs/gb/components/toolbar/md-gb-toolbar.js +8 -0
  228. package/labs/gb/components/toolbar/md-gb-toolbar.js.map +1 -0
  229. package/labs/gb/components/toolbar/toolbar-element.d.ts +56 -0
  230. package/labs/gb/components/toolbar/toolbar-element.js +120 -0
  231. package/labs/gb/components/toolbar/toolbar-element.js.map +1 -0
  232. package/labs/gb/components/toolbar/toolbar.css +4 -0
  233. package/labs/gb/components/toolbar/toolbar.css.map +1 -0
  234. package/labs/gb/components/toolbar/toolbar.cssresult.d.ts +3 -0
  235. package/labs/gb/components/toolbar/toolbar.cssresult.js +14 -0
  236. package/labs/gb/components/toolbar/toolbar.cssresult.js.map +1 -0
  237. package/labs/gb/components/toolbar/toolbar.d.ts +56 -0
  238. package/labs/gb/components/toolbar/toolbar.js +60 -0
  239. package/labs/gb/components/toolbar/toolbar.js.map +1 -0
  240. package/labs/gb/components/toolbar/toolbar.scss +240 -0
  241. package/labs/gb/styles/icon/icon-element.d.ts +1 -0
  242. package/labs/gb/styles/icon/icon-element.js +1 -0
  243. package/labs/gb/styles/icon/icon-element.js.map +1 -1
  244. package/labs/gb/styles/tailwind.css +1 -1
  245. package/labs/gb/styles/tailwind.css.map +1 -1
  246. package/labs/gb/styles/tailwind.cssresult.js +1 -1
  247. package/labs/gb/styles/tailwind.cssresult.js.map +1 -1
  248. package/labs/gb/styles/tailwind.scss +2 -0
  249. package/list/internal/listitem/list-item.d.ts +10 -0
  250. package/list/internal/listitem/list-item.js +20 -1
  251. package/list/internal/listitem/list-item.js.map +1 -1
  252. package/menu/internal/menuitem/menu-item.d.ts +10 -0
  253. package/menu/internal/menuitem/menu-item.js +20 -1
  254. package/menu/internal/menuitem/menu-item.js.map +1 -1
  255. package/package.json +2 -1
  256. package/radio/internal/single-selection-controller.js +4 -1
  257. package/radio/internal/single-selection-controller.js.map +1 -1
  258. package/testing/harness.js +3 -0
  259. package/testing/harness.js.map +1 -1
  260. package/types/command-event.d.ts +34 -0
  261. package/types/popover.d.ts +25 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { AriaTabpanelElement } from './tabpanel.js';
7
+ customElements.define('md-aria-tabpanel', AriaTabpanelElement);
8
+ //# sourceMappingURL=md-aria-tabpanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"md-aria-tabpanel.js","sourceRoot":"","sources":["md-aria-tabpanel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,eAAe,CAAC;AAQlD,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {AriaTabpanelElement} from './tabpanel.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'md-aria-tabpanel': AriaTabpanelElement;\n }\n}\n\ncustomElements.define('md-aria-tabpanel', AriaTabpanelElement);\n"]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { CSSResultGroup, LitElement } from 'lit';
7
+ declare const baseClass: import("../../behaviors/mixin.js").MixinReturn<import("../../behaviors/mixin.js").MixinReturn<import("../../behaviors/mixin.js").MixinReturn<typeof LitElement, import("../../behaviors/element-internals.js").WithElementInternals>, import("../../behaviors/custom-state-set.js").WithCustomStateSet>, import("../../behaviors/focusable.js").Focusable>;
8
+ /**
9
+ * An ARIA tab element.
10
+ *
11
+ * @cssstate selected - Whether the tab is selected.
12
+ */
13
+ export declare class AriaTabElement extends baseClass {
14
+ static styles: CSSResultGroup;
15
+ /**
16
+ * ID of the associated `md-aria-tabpanel` element.
17
+ */
18
+ get tabpanel(): string;
19
+ set tabpanel(value: string);
20
+ /**
21
+ * The tabpanel element that is controlled by this tab.
22
+ */
23
+ get tabpanelElement(): Element | null;
24
+ set tabpanelElement(value: Element | null);
25
+ /**
26
+ * Whether the tab is selected.
27
+ */
28
+ get selected(): boolean;
29
+ set selected(value: boolean);
30
+ constructor();
31
+ protected render(): import("lit-html").TemplateResult<1>;
32
+ }
33
+ export {};
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { __decorate } from "tslib";
7
+ import { css, html, isServer, LitElement } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { afterDispatch, setupDispatchHooks, } from '../../../internal/events/dispatch-hooks.js';
10
+ import { queryAssociatedById } from '../../aria/query-associated.js';
11
+ import { mixinCustomStateSet, toggleState, } from '../../behaviors/custom-state-set.js';
12
+ import { internals, mixinElementInternals, } from '../../behaviors/element-internals.js';
13
+ import { mixinFocusable } from '../../behaviors/focusable.js';
14
+ const baseClass = mixinFocusable(mixinCustomStateSet(mixinElementInternals(LitElement)));
15
+ /**
16
+ * An ARIA tab element.
17
+ *
18
+ * @cssstate selected - Whether the tab is selected.
19
+ */
20
+ export class AriaTabElement extends baseClass {
21
+ /**
22
+ * ID of the associated `md-aria-tabpanel` element.
23
+ */
24
+ get tabpanel() {
25
+ return this.tabpanelElement?.id || '';
26
+ }
27
+ set tabpanel(value) {
28
+ this.tabpanelElement = queryAssociatedById(this, value);
29
+ }
30
+ /**
31
+ * The tabpanel element that is controlled by this tab.
32
+ */
33
+ get tabpanelElement() {
34
+ return this[internals].ariaControlsElements?.[0] || null;
35
+ }
36
+ set tabpanelElement(value) {
37
+ const previousValue = this.tabpanelElement;
38
+ if (value === previousValue)
39
+ return;
40
+ this[internals].ariaControlsElements = value ? [value] : [];
41
+ }
42
+ /**
43
+ * Whether the tab is selected.
44
+ */
45
+ get selected() {
46
+ return this[internals].ariaSelected === 'true';
47
+ }
48
+ set selected(value) {
49
+ const oldValue = this.selected;
50
+ value = Boolean(value); // coerce for safety
51
+ this[internals].ariaSelected = String(value);
52
+ this[toggleState]('selected', value);
53
+ // Request update manually for Lit 2 compatibility, where user-defined
54
+ // accessors are not automatically wrapped by createProperty().
55
+ // May be removed once Lit 2 is no longer supported.
56
+ this.requestUpdate('selected', oldValue);
57
+ }
58
+ constructor() {
59
+ super();
60
+ if (isServer)
61
+ return;
62
+ this[internals].role = 'tab';
63
+ setupDispatchHooks(this, 'keydown');
64
+ this.addEventListener('keydown', (event) => {
65
+ afterDispatch(event, () => {
66
+ if (event.defaultPrevented) {
67
+ return;
68
+ }
69
+ if (event.key === 'Enter' || event.key === ' ') {
70
+ // Prevent default behavior such as scrolling when pressing spacebar.
71
+ event.preventDefault();
72
+ this.click();
73
+ }
74
+ });
75
+ });
76
+ }
77
+ render() {
78
+ return html `<slot></slot>`;
79
+ }
80
+ }
81
+ AriaTabElement.styles = css `
82
+ :host {
83
+ display: inline-block;
84
+ cursor: pointer;
85
+ }
86
+ `;
87
+ __decorate([
88
+ property({ type: String, reflect: true, noAccessor: true })
89
+ ], AriaTabElement.prototype, "tabpanel", null);
90
+ __decorate([
91
+ property({ type: Boolean, reflect: true })
92
+ ], AriaTabElement.prototype, "selected", null);
93
+ //# sourceMappingURL=tab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab.js","sourceRoot":"","sources":["tab.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {css, CSSResultGroup, html, isServer, LitElement} from 'lit';\nimport {property} from 'lit/decorators.js';\n\nimport {\n afterDispatch,\n setupDispatchHooks,\n} from '../../../internal/events/dispatch-hooks.js';\nimport {queryAssociatedById} from '../../aria/query-associated.js';\nimport {\n mixinCustomStateSet,\n toggleState,\n} from '../../behaviors/custom-state-set.js';\nimport {\n internals,\n mixinElementInternals,\n} from '../../behaviors/element-internals.js';\nimport {mixinFocusable} from '../../behaviors/focusable.js';\n\nconst baseClass = mixinFocusable(\n mixinCustomStateSet(mixinElementInternals(LitElement)),\n);\n\n/**\n * An ARIA tab element.\n *\n * @cssstate selected - Whether the tab is selected.\n */\nexport class AriaTabElement extends baseClass {\n static override styles: CSSResultGroup = css`\n :host {\n display: inline-block;\n cursor: pointer;\n }\n `;\n\n /**\n * ID of the associated `md-aria-tabpanel` element.\n */\n @property({type: String, reflect: true, noAccessor: true})\n get tabpanel(): string {\n return this.tabpanelElement?.id || '';\n }\n set tabpanel(value: string) {\n this.tabpanelElement = queryAssociatedById(this, value);\n }\n\n /**\n * The tabpanel element that is controlled by this tab.\n */\n get tabpanelElement(): Element | null {\n return this[internals].ariaControlsElements?.[0] || null;\n }\n set tabpanelElement(value: Element | null) {\n const previousValue = this.tabpanelElement;\n if (value === previousValue) return;\n this[internals].ariaControlsElements = value ? [value] : [];\n }\n\n /**\n * Whether the tab is selected.\n */\n @property({type: Boolean, reflect: true})\n get selected(): boolean {\n return this[internals].ariaSelected === 'true';\n }\n set selected(value: boolean) {\n const oldValue = this.selected;\n value = Boolean(value); // coerce for safety\n this[internals].ariaSelected = String(value);\n this[toggleState]('selected', value);\n // Request update manually for Lit 2 compatibility, where user-defined\n // accessors are not automatically wrapped by createProperty().\n // May be removed once Lit 2 is no longer supported.\n this.requestUpdate('selected', oldValue);\n }\n\n constructor() {\n super();\n if (isServer) return;\n this[internals].role = 'tab';\n setupDispatchHooks(this, 'keydown');\n this.addEventListener('keydown', (event: KeyboardEvent) => {\n afterDispatch(event, () => {\n if (event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n // Prevent default behavior such as scrolling when pressing spacebar.\n event.preventDefault();\n this.click();\n }\n });\n });\n }\n\n protected override render() {\n return html`<slot></slot>`;\n }\n}\n"]}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { CSSResultGroup, LitElement, PropertyValues } from 'lit';
7
+ declare const baseClass: import("../../behaviors/mixin.js").MixinReturn<typeof LitElement, import("../../behaviors/element-internals.js").WithElementInternals>;
8
+ /**
9
+ * An ARIA tablist element.
10
+ */
11
+ export declare class AriaTablistElement extends baseClass {
12
+ static styles: CSSResultGroup;
13
+ /**
14
+ * The tabs of this tablist.
15
+ */
16
+ get tabs(): HTMLElement[];
17
+ /**
18
+ * The currently selected tab, `null` only when there are no tab children.
19
+ *
20
+ * @export
21
+ */
22
+ get selectedTab(): HTMLElement | null;
23
+ set selectedTab(tab: HTMLElement | null);
24
+ /**
25
+ * The index of the currently selected tab.
26
+ *
27
+ * @export
28
+ */
29
+ get selectedTabIndex(): number;
30
+ set selectedTabIndex(index: number);
31
+ /**
32
+ * Whether or not to automatically select a tab when it is focused.
33
+ */
34
+ autoSelect: boolean;
35
+ /**
36
+ * Orientation of the tablist ('horizontal' or 'vertical').
37
+ */
38
+ orientation: 'horizontal' | 'vertical';
39
+ private readonly slotElement;
40
+ constructor();
41
+ protected updated(changedProperties: PropertyValues<this>): void;
42
+ protected render(): import("lit-html").TemplateResult<1>;
43
+ /**
44
+ * Returns true if the element is a valid tab component or role. Subclasses
45
+ * may override this method to determine if an element is a supported tab.
46
+ */
47
+ protected isTab(element: HTMLElement): boolean;
48
+ /**
49
+ * Returns true if the tab is currently selected. Subclasses may override this
50
+ * method to support custom tab selection implementations.
51
+ */
52
+ protected isTabSelected(tab: HTMLElement): boolean;
53
+ /**
54
+ * Updates the selection state of the tab element and visibility of its
55
+ * tabpanel. Subclasses may override this method to support custom tab
56
+ * selection implementations.
57
+ */
58
+ protected setTabSelected(tab: HTMLElement, isSelected: boolean): void;
59
+ protected onTabChange(previousTab: HTMLElement | null): void;
60
+ protected updateSelectedTab(tabToSelect: HTMLElement): void;
61
+ private handleClick;
62
+ private handleFocusin;
63
+ protected handleSlotChange(): void;
64
+ }
65
+ export {};
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { __decorate } from "tslib";
7
+ import { css, html, isServer, LitElement, } from 'lit';
8
+ import { property, query } from 'lit/decorators.js';
9
+ import { afterDispatch, setupDispatchHooks, } from '../../../internal/events/dispatch-hooks.js';
10
+ import { internals, mixinElementInternals, } from '../../behaviors/element-internals.js';
11
+ const baseClass = mixinElementInternals(LitElement);
12
+ /**
13
+ * An ARIA tablist element.
14
+ */
15
+ export class AriaTablistElement extends baseClass {
16
+ /**
17
+ * The tabs of this tablist.
18
+ */
19
+ get tabs() {
20
+ return (this.slotElement
21
+ ?.assignedElements({ flatten: true })
22
+ .filter((el) => this.isTab(el)) ?? []);
23
+ }
24
+ /**
25
+ * The currently selected tab, `null` only when there are no tab children.
26
+ *
27
+ * @export
28
+ */
29
+ get selectedTab() {
30
+ return this.tabs.find((tab) => this.isTabSelected(tab)) ?? null;
31
+ }
32
+ set selectedTab(tab) {
33
+ // Ignore setting selectedTab to null. As long as there are children, one
34
+ // tab must be selected.
35
+ if (tab) {
36
+ this.updateSelectedTab(tab);
37
+ }
38
+ }
39
+ /**
40
+ * The index of the currently selected tab.
41
+ *
42
+ * @export
43
+ */
44
+ get selectedTabIndex() {
45
+ return this.tabs.findIndex((tab) => this.isTabSelected(tab));
46
+ }
47
+ set selectedTabIndex(index) {
48
+ const selectTabAtIndex = () => {
49
+ const tab = this.tabs[index];
50
+ // Ignore out-of-bound indices.
51
+ if (tab) {
52
+ this.updateSelectedTab(tab);
53
+ }
54
+ };
55
+ if (!this.slotElement) {
56
+ // This is needed to support setting the selectedTabIndex via a lit
57
+ // property binding.
58
+ //
59
+ // ```ts
60
+ // html`
61
+ // <md-aria-tablist .selectedTabIndex=${1}>
62
+ // <md-aria-tab>First</md-aria-tab>
63
+ // <md-aria-tab>Second</md-aria-tab>
64
+ // </md-aria-tablist>
65
+ // `;
66
+ // ```
67
+ //
68
+ // It's needed since lit's rendering lifecycle is asynchronous, and the
69
+ // `<slot>` element hasn't rendered, so `tabs` is empty.
70
+ this.updateComplete.then(selectTabAtIndex);
71
+ return;
72
+ }
73
+ selectTabAtIndex();
74
+ }
75
+ constructor() {
76
+ super();
77
+ /**
78
+ * Whether or not to automatically select a tab when it is focused.
79
+ */
80
+ this.autoSelect = false;
81
+ /**
82
+ * Orientation of the tablist ('horizontal' or 'vertical').
83
+ */
84
+ this.orientation = 'horizontal';
85
+ if (isServer)
86
+ return;
87
+ this[internals].role = 'tablist';
88
+ setupDispatchHooks(this, 'click', 'focusin');
89
+ this.addEventListener('click', this.handleClick.bind(this));
90
+ this.addEventListener('focusin', this.handleFocusin.bind(this));
91
+ }
92
+ updated(changedProperties) {
93
+ super.updated(changedProperties);
94
+ if (changedProperties.has('orientation') ||
95
+ !this.hasAttribute('focusgroup')) {
96
+ const isVertical = this.orientation === 'vertical';
97
+ this[internals].ariaOrientation = isVertical ? 'vertical' : 'horizontal';
98
+ this.setAttribute('focusgroup', `tablist ${isVertical ? 'block' : 'inline'}`);
99
+ }
100
+ }
101
+ render() {
102
+ return html `<slot @slotchange=${this.handleSlotChange}></slot>`;
103
+ }
104
+ /**
105
+ * Returns true if the element is a valid tab component or role. Subclasses
106
+ * may override this method to determine if an element is a supported tab.
107
+ */
108
+ isTab(element) {
109
+ return isAriaTabLike(element);
110
+ }
111
+ /**
112
+ * Returns true if the tab is currently selected. Subclasses may override this
113
+ * method to support custom tab selection implementations.
114
+ */
115
+ isTabSelected(tab) {
116
+ if (!isAriaTabLike(tab))
117
+ return false;
118
+ return tab.selected;
119
+ }
120
+ /**
121
+ * Updates the selection state of the tab element and visibility of its
122
+ * tabpanel. Subclasses may override this method to support custom tab
123
+ * selection implementations.
124
+ */
125
+ setTabSelected(tab, isSelected) {
126
+ if (!isAriaTabLike(tab))
127
+ return;
128
+ tab.selected = isSelected;
129
+ const panel = tab.tabpanelElement;
130
+ if (panel) {
131
+ panel.hidden = !isSelected;
132
+ }
133
+ }
134
+ onTabChange(previousTab) {
135
+ this.dispatchEvent(new Event('change', { bubbles: true }));
136
+ }
137
+ updateSelectedTab(tabToSelect) {
138
+ const { tabs } = this;
139
+ const tabToSelectIndex = tabs.indexOf(tabToSelect);
140
+ if (tabToSelectIndex === -1) {
141
+ // Ignore setting selectedTab to a tab element that is not a child.
142
+ return;
143
+ }
144
+ for (const tab of tabs) {
145
+ this.setTabSelected(tab, tab === tabToSelect);
146
+ }
147
+ }
148
+ handleClick(event) {
149
+ // event.composedPath() needs to be called before dispatch completes.
150
+ const tab = event
151
+ .composedPath()
152
+ .find((el) => this.isTab(el));
153
+ // Allow event to bubble
154
+ afterDispatch(event, () => {
155
+ if (event.defaultPrevented) {
156
+ return;
157
+ }
158
+ if (tab && !this.isTabSelected(tab)) {
159
+ const previousTab = this.selectedTab;
160
+ this.updateSelectedTab(tab);
161
+ this.onTabChange(previousTab);
162
+ }
163
+ });
164
+ }
165
+ handleFocusin(event) {
166
+ if (this.autoSelect) {
167
+ this.handleClick(event);
168
+ }
169
+ }
170
+ handleSlotChange() {
171
+ const tabToSelect = this.selectedTab ?? this.tabs[0];
172
+ if (tabToSelect) {
173
+ // Sync tab selection state when slotted content changes. If the active
174
+ // tab was removed or none selected, auto-select the first tab. There
175
+ // should always be a single selected tab while the tablist has children.
176
+ this.updateSelectedTab(tabToSelect);
177
+ }
178
+ }
179
+ }
180
+ AriaTablistElement.styles = css `
181
+ :host {
182
+ display: flex;
183
+ }
184
+ :host([orientation='vertical']) {
185
+ flex-direction: column;
186
+ }
187
+ `;
188
+ __decorate([
189
+ property({ type: Number })
190
+ ], AriaTablistElement.prototype, "selectedTabIndex", null);
191
+ __decorate([
192
+ property({ type: Boolean })
193
+ ], AriaTablistElement.prototype, "autoSelect", void 0);
194
+ __decorate([
195
+ property({ reflect: true })
196
+ ], AriaTablistElement.prototype, "orientation", void 0);
197
+ __decorate([
198
+ query('slot:not([name])')
199
+ ], AriaTablistElement.prototype, "slotElement", void 0);
200
+ function isAriaTabLike(element) {
201
+ return Boolean(element &&
202
+ typeof element === 'object' &&
203
+ 'selected' in element &&
204
+ 'tabpanelElement' in element);
205
+ }
206
+ //# sourceMappingURL=tablist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tablist.js","sourceRoot":"","sources":["tablist.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAEH,OAAO,EACL,GAAG,EAEH,IAAI,EACJ,QAAQ,EACR,UAAU,GAEX,MAAM,KAAK,CAAC;AACb,OAAO,EAAC,QAAQ,EAAE,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAElD,OAAO,EACL,aAAa,EACb,kBAAkB,GACnB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACL,SAAS,EACT,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAE9C,MAAM,SAAS,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,SAAS;IAU/C;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,CACL,IAAI,CAAC,WAAW;YACd,EAAE,gBAAgB,CAAC,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC;aAClC,MAAM,CAAC,CAAC,EAAE,EAAqB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAiB,CAAC,CAAC,IAAI,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IAClE,CAAC;IACD,IAAI,WAAW,CAAC,GAAuB;QACrC,yEAAyE;QACzE,wBAAwB;QACxB,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;;OAIG;IAEH,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,gBAAgB,CAAC,KAAa;QAChC,MAAM,gBAAgB,GAAG,GAAG,EAAE;YAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,+BAA+B;YAC/B,IAAI,GAAG,EAAE,CAAC;gBACR,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,mEAAmE;YACnE,oBAAoB;YACpB,EAAE;YACF,QAAQ;YACR,QAAQ;YACR,6CAA6C;YAC7C,uCAAuC;YACvC,wCAAwC;YACxC,uBAAuB;YACvB,KAAK;YACL,MAAM;YACN,EAAE;YACF,uEAAuE;YACvE,wDAAwD;YACxD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,gBAAgB,EAAE,CAAC;IACrB,CAAC;IAgBD;QACE,KAAK,EAAE,CAAC;QAfV;;WAEG;QACwB,eAAU,GAAG,KAAK,CAAC;QAE9C;;WAEG;QACwB,gBAAW,GACpC,YAAY,CAAC;QAOb,IAAI,QAAQ;YAAE,OAAO;QACrB,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC;QACjC,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,CAAC;IAEkB,OAAO,CAAC,iBAAuC;QAChE,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACjC,IACE,iBAAiB,CAAC,GAAG,CAAC,aAAa,CAAC;YACpC,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAChC,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,KAAK,UAAU,CAAC;YACnD,IAAI,CAAC,SAAS,CAAC,CAAC,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;YACzE,IAAI,CAAC,YAAY,CACf,YAAY,EACZ,WAAW,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAC7C,CAAC;QACJ,CAAC;IACH,CAAC;IAEkB,MAAM;QACvB,OAAO,IAAI,CAAA,qBAAqB,IAAI,CAAC,gBAAgB,UAAU,CAAC;IAClE,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,OAAoB;QAClC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED;;;OAGG;IACO,aAAa,CAAC,GAAgB;QACtC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,GAAG,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACO,cAAc,CAAC,GAAgB,EAAE,UAAmB;QAC5D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;YAAE,OAAO;QAChC,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC;QAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,eAAqC,CAAC;QACxD,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC;QAC7B,CAAC;IACH,CAAC;IAES,WAAW,CAAC,WAA+B;QACnD,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAES,iBAAiB,CAAC,WAAwB;QAClD,MAAM,EAAC,IAAI,EAAC,GAAG,IAAI,CAAC;QACpB,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACnD,IAAI,gBAAgB,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5B,mEAAmE;YACnE,OAAO;QACT,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,KAAK,WAAW,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,KAAY;QAC9B,qEAAqE;QACrE,MAAM,GAAG,GAAG,KAAK;aACd,YAAY,EAAE;aACd,IAAI,CAAC,CAAC,EAAE,EAAqB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAiB,CAAC,CAAC,CAAC;QAElE,wBAAwB;QACxB,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE;YACxB,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;gBACrC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAC5B,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,aAAa,CAAC,KAAiB;QACrC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAES,gBAAgB;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,WAAW,EAAE,CAAC;YAChB,uEAAuE;YACvE,qEAAqE;YACrE,yEAAyE;YACzE,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;;AAxMe,yBAAM,GAAmB,GAAG,CAAA;;;;;;;GAO3C,AAPqB,CAOpB;AAmCF;IADC,QAAQ,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC;0DAGxB;AAmC0B;IAA1B,QAAQ,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC;sDAAoB;AAKnB;IAA1B,QAAQ,CAAC,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC;uDACX;AAGE;IADhB,KAAK,CAAC,kBAAkB,CAAC;uDAC4B;AAwHxD,SAAS,aAAa,CAAC,OAAgB;IACrC,OAAO,OAAO,CACZ,OAAO;QACL,OAAO,OAAO,KAAK,QAAQ;QAC3B,UAAU,IAAI,OAAO;QACrB,iBAAiB,IAAI,OAAO,CAC/B,CAAC;AACJ,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n css,\n CSSResultGroup,\n html,\n isServer,\n LitElement,\n PropertyValues,\n} from 'lit';\nimport {property, query} from 'lit/decorators.js';\n\nimport {\n afterDispatch,\n setupDispatchHooks,\n} from '../../../internal/events/dispatch-hooks.js';\nimport {\n internals,\n mixinElementInternals,\n} from '../../behaviors/element-internals.js';\n\nconst baseClass = mixinElementInternals(LitElement);\n\n/**\n * An ARIA tablist element.\n */\nexport class AriaTablistElement extends baseClass {\n static override styles: CSSResultGroup = css`\n :host {\n display: flex;\n }\n :host([orientation='vertical']) {\n flex-direction: column;\n }\n `;\n\n /**\n * The tabs of this tablist.\n */\n get tabs(): HTMLElement[] {\n return (\n this.slotElement\n ?.assignedElements({flatten: true})\n .filter((el): el is HTMLElement => this.isTab(el as HTMLElement)) ?? []\n );\n }\n\n /**\n * The currently selected tab, `null` only when there are no tab children.\n *\n * @export\n */\n get selectedTab() {\n return this.tabs.find((tab) => this.isTabSelected(tab)) ?? null;\n }\n set selectedTab(tab: HTMLElement | null) {\n // Ignore setting selectedTab to null. As long as there are children, one\n // tab must be selected.\n if (tab) {\n this.updateSelectedTab(tab);\n }\n }\n\n /**\n * The index of the currently selected tab.\n *\n * @export\n */\n @property({type: Number})\n get selectedTabIndex() {\n return this.tabs.findIndex((tab) => this.isTabSelected(tab));\n }\n set selectedTabIndex(index: number) {\n const selectTabAtIndex = () => {\n const tab = this.tabs[index];\n // Ignore out-of-bound indices.\n if (tab) {\n this.updateSelectedTab(tab);\n }\n };\n\n if (!this.slotElement) {\n // This is needed to support setting the selectedTabIndex via a lit\n // property binding.\n //\n // ```ts\n // html`\n // <md-aria-tablist .selectedTabIndex=${1}>\n // <md-aria-tab>First</md-aria-tab>\n // <md-aria-tab>Second</md-aria-tab>\n // </md-aria-tablist>\n // `;\n // ```\n //\n // It's needed since lit's rendering lifecycle is asynchronous, and the\n // `<slot>` element hasn't rendered, so `tabs` is empty.\n this.updateComplete.then(selectTabAtIndex);\n return;\n }\n\n selectTabAtIndex();\n }\n\n /**\n * Whether or not to automatically select a tab when it is focused.\n */\n @property({type: Boolean}) autoSelect = false;\n\n /**\n * Orientation of the tablist ('horizontal' or 'vertical').\n */\n @property({reflect: true}) orientation: 'horizontal' | 'vertical' =\n 'horizontal';\n\n @query('slot:not([name])')\n private readonly slotElement!: HTMLSlotElement | null;\n\n constructor() {\n super();\n if (isServer) return;\n this[internals].role = 'tablist';\n setupDispatchHooks(this, 'click', 'focusin');\n this.addEventListener('click', this.handleClick.bind(this));\n this.addEventListener('focusin', this.handleFocusin.bind(this));\n }\n\n protected override updated(changedProperties: PropertyValues<this>) {\n super.updated(changedProperties);\n if (\n changedProperties.has('orientation') ||\n !this.hasAttribute('focusgroup')\n ) {\n const isVertical = this.orientation === 'vertical';\n this[internals].ariaOrientation = isVertical ? 'vertical' : 'horizontal';\n this.setAttribute(\n 'focusgroup',\n `tablist ${isVertical ? 'block' : 'inline'}`,\n );\n }\n }\n\n protected override render() {\n return html`<slot @slotchange=${this.handleSlotChange}></slot>`;\n }\n\n /**\n * Returns true if the element is a valid tab component or role. Subclasses\n * may override this method to determine if an element is a supported tab.\n */\n protected isTab(element: HTMLElement): boolean {\n return isAriaTabLike(element);\n }\n\n /**\n * Returns true if the tab is currently selected. Subclasses may override this\n * method to support custom tab selection implementations.\n */\n protected isTabSelected(tab: HTMLElement): boolean {\n if (!isAriaTabLike(tab)) return false;\n return tab.selected;\n }\n\n /**\n * Updates the selection state of the tab element and visibility of its\n * tabpanel. Subclasses may override this method to support custom tab\n * selection implementations.\n */\n protected setTabSelected(tab: HTMLElement, isSelected: boolean): void {\n if (!isAriaTabLike(tab)) return;\n tab.selected = isSelected;\n const panel = tab.tabpanelElement as HTMLElement | null;\n if (panel) {\n panel.hidden = !isSelected;\n }\n }\n\n protected onTabChange(previousTab: HTMLElement | null): void {\n this.dispatchEvent(new Event('change', {bubbles: true}));\n }\n\n protected updateSelectedTab(tabToSelect: HTMLElement) {\n const {tabs} = this;\n const tabToSelectIndex = tabs.indexOf(tabToSelect);\n if (tabToSelectIndex === -1) {\n // Ignore setting selectedTab to a tab element that is not a child.\n return;\n }\n\n for (const tab of tabs) {\n this.setTabSelected(tab, tab === tabToSelect);\n }\n }\n\n private handleClick(event: Event) {\n // event.composedPath() needs to be called before dispatch completes.\n const tab = event\n .composedPath()\n .find((el): el is HTMLElement => this.isTab(el as HTMLElement));\n\n // Allow event to bubble\n afterDispatch(event, () => {\n if (event.defaultPrevented) {\n return;\n }\n\n if (tab && !this.isTabSelected(tab)) {\n const previousTab = this.selectedTab;\n this.updateSelectedTab(tab);\n this.onTabChange(previousTab);\n }\n });\n }\n\n private handleFocusin(event: FocusEvent) {\n if (this.autoSelect) {\n this.handleClick(event);\n }\n }\n\n protected handleSlotChange() {\n const tabToSelect = this.selectedTab ?? this.tabs[0];\n if (tabToSelect) {\n // Sync tab selection state when slotted content changes. If the active\n // tab was removed or none selected, auto-select the first tab. There\n // should always be a single selected tab while the tablist has children.\n this.updateSelectedTab(tabToSelect);\n }\n }\n}\n\ninterface AriaTabLike extends HTMLElement {\n selected: boolean;\n tabpanelElement: Element | null;\n}\n\nfunction isAriaTabLike(element: unknown): element is AriaTabLike {\n return Boolean(\n element &&\n typeof element === 'object' &&\n 'selected' in element &&\n 'tabpanelElement' in element,\n );\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { LitElement } from 'lit';
7
+ declare const baseClass: import("../../behaviors/mixin.js").MixinReturn<import("../../behaviors/mixin.js").MixinReturn<typeof LitElement, import("../../behaviors/element-internals.js").WithElementInternals>, import("../../behaviors/focusable.js").Focusable>;
8
+ /**
9
+ * An ARIA tabpanel element.
10
+ */
11
+ export declare class AriaTabpanelElement extends baseClass {
12
+ static styles: import("lit").CSSResult;
13
+ /**
14
+ * ID of the tab element that controls this tabpanel.
15
+ */
16
+ get tab(): string;
17
+ set tab(value: string);
18
+ /**
19
+ * The tab element that controls this tabpanel.
20
+ */
21
+ get tabElement(): Element | null;
22
+ set tabElement(value: Element | null);
23
+ constructor();
24
+ protected render(): import("lit-html").TemplateResult<1>;
25
+ }
26
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { __decorate } from "tslib";
7
+ import { css, html, isServer, LitElement } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { queryAssociatedById } from '../../aria/query-associated.js';
10
+ import { internals, mixinElementInternals, } from '../../behaviors/element-internals.js';
11
+ import { mixinFocusable } from '../../behaviors/focusable.js';
12
+ const baseClass = mixinFocusable(mixinElementInternals(LitElement));
13
+ /**
14
+ * An ARIA tabpanel element.
15
+ */
16
+ export class AriaTabpanelElement extends baseClass {
17
+ /**
18
+ * ID of the tab element that controls this tabpanel.
19
+ */
20
+ get tab() {
21
+ return this.tabElement?.id || '';
22
+ }
23
+ set tab(value) {
24
+ this.tabElement = queryAssociatedById(this, value);
25
+ }
26
+ /**
27
+ * The tab element that controls this tabpanel.
28
+ */
29
+ get tabElement() {
30
+ return this[internals].ariaLabelledByElements?.[0] || null;
31
+ }
32
+ set tabElement(value) {
33
+ this[internals].ariaLabelledByElements = value ? [value] : [];
34
+ }
35
+ constructor() {
36
+ super();
37
+ if (isServer)
38
+ return;
39
+ this[internals].role = 'tabpanel';
40
+ }
41
+ render() {
42
+ return html `<slot></slot>`;
43
+ }
44
+ }
45
+ AriaTabpanelElement.styles = css `
46
+ :host(:not([hidden])) {
47
+ display: block;
48
+ }
49
+ `;
50
+ __decorate([
51
+ property({ type: String, reflect: true, noAccessor: true })
52
+ ], AriaTabpanelElement.prototype, "tab", null);
53
+ //# sourceMappingURL=tabpanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabpanel.js","sourceRoot":"","sources":["tabpanel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;AAEH,OAAO,EAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAC,MAAM,KAAK,CAAC;AACpD,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,SAAS,EACT,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAE5D,MAAM,SAAS,GAAG,cAAc,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAOhD;;OAEG;IAEH,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IACD,IAAI,GAAG,CAAC,KAAa;QACnB,IAAI,CAAC,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC7D,CAAC;IACD,IAAI,UAAU,CAAC,KAAqB;QAClC,IAAI,CAAC,SAAS,CAAC,CAAC,sBAAsB,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QACR,IAAI,QAAQ;YAAE,OAAO;QACrB,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,GAAG,UAAU,CAAC;IACpC,CAAC;IAEkB,MAAM;QACvB,OAAO,IAAI,CAAA,eAAe,CAAC;IAC7B,CAAC;;AAnCe,0BAAM,GAAG,GAAG,CAAA;;;;GAI3B,CAAC;AAMF;IADC,QAAQ,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAC,CAAC;8CAGzD","sourcesContent":["/**\n * @license\n * Copyright 2026 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {css, html, isServer, LitElement} from 'lit';\nimport {property} from 'lit/decorators.js';\n\nimport {queryAssociatedById} from '../../aria/query-associated.js';\nimport {\n internals,\n mixinElementInternals,\n} from '../../behaviors/element-internals.js';\nimport {mixinFocusable} from '../../behaviors/focusable.js';\n\nconst baseClass = mixinFocusable(mixinElementInternals(LitElement));\n\n/**\n * An ARIA tabpanel element.\n */\nexport class AriaTabpanelElement extends baseClass {\n static override styles = css`\n :host(:not([hidden])) {\n display: block;\n }\n `;\n\n /**\n * ID of the tab element that controls this tabpanel.\n */\n @property({type: String, reflect: true, noAccessor: true})\n get tab(): string {\n return this.tabElement?.id || '';\n }\n set tab(value: string) {\n this.tabElement = queryAssociatedById(this, value);\n }\n\n /**\n * The tab element that controls this tabpanel.\n */\n get tabElement(): Element | null {\n return this[internals].ariaLabelledByElements?.[0] || null;\n }\n set tabElement(value: Element | null) {\n this[internals].ariaLabelledByElements = value ? [value] : [];\n }\n\n constructor() {\n super();\n if (isServer) return;\n this[internals].role = 'tabpanel';\n }\n\n protected override render() {\n return html`<slot></slot>`;\n }\n}\n"]}