@spectrum-web-components/tabs 0.34.1-rc.0 → 0.35.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.
- package/custom-elements.json +14 -14
- package/package.json +8 -8
- package/src/Tabs.dev.js +1 -1
- package/src/Tabs.dev.js.map +2 -2
- package/src/Tabs.js +1 -1
- package/src/Tabs.js.map +2 -2
- package/test/tabs.test.js +11 -3
- package/test/tabs.test.js.map +2 -2
package/custom-elements.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"modules": [
|
|
5
5
|
{
|
|
6
6
|
"kind": "javascript-module",
|
|
7
|
-
"path": "sp-tab-panel.
|
|
7
|
+
"path": "sp-tab-panel.js",
|
|
8
8
|
"declarations": [],
|
|
9
9
|
"exports": [
|
|
10
10
|
{
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"kind": "javascript-module",
|
|
22
|
-
"path": "sp-tab.
|
|
22
|
+
"path": "sp-tab.js",
|
|
23
23
|
"declarations": [],
|
|
24
24
|
"exports": [
|
|
25
25
|
{
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"kind": "javascript-module",
|
|
37
|
-
"path": "sp-tabs-overflow.
|
|
37
|
+
"path": "sp-tabs-overflow.js",
|
|
38
38
|
"declarations": [],
|
|
39
39
|
"exports": [
|
|
40
40
|
{
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"kind": "javascript-module",
|
|
52
|
-
"path": "sp-tabs.
|
|
52
|
+
"path": "sp-tabs.js",
|
|
53
53
|
"declarations": [],
|
|
54
54
|
"exports": [
|
|
55
55
|
{
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
"kind": "javascript-module",
|
|
67
|
-
"path": "src/Tab.
|
|
67
|
+
"path": "src/Tab.js",
|
|
68
68
|
"declarations": [
|
|
69
69
|
{
|
|
70
70
|
"kind": "class",
|
|
@@ -235,14 +235,14 @@
|
|
|
235
235
|
"name": "Tab",
|
|
236
236
|
"declaration": {
|
|
237
237
|
"name": "Tab",
|
|
238
|
-
"module": "src/Tab.
|
|
238
|
+
"module": "src/Tab.js"
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
]
|
|
242
242
|
},
|
|
243
243
|
{
|
|
244
244
|
"kind": "javascript-module",
|
|
245
|
-
"path": "src/TabPanel.
|
|
245
|
+
"path": "src/TabPanel.js",
|
|
246
246
|
"declarations": [
|
|
247
247
|
{
|
|
248
248
|
"kind": "class",
|
|
@@ -320,14 +320,14 @@
|
|
|
320
320
|
"name": "TabPanel",
|
|
321
321
|
"declaration": {
|
|
322
322
|
"name": "TabPanel",
|
|
323
|
-
"module": "src/TabPanel.
|
|
323
|
+
"module": "src/TabPanel.js"
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
]
|
|
327
327
|
},
|
|
328
328
|
{
|
|
329
329
|
"kind": "javascript-module",
|
|
330
|
-
"path": "src/Tabs.
|
|
330
|
+
"path": "src/Tabs.js",
|
|
331
331
|
"declarations": [
|
|
332
332
|
{
|
|
333
333
|
"kind": "variable",
|
|
@@ -511,7 +511,7 @@
|
|
|
511
511
|
{
|
|
512
512
|
"kind": "field",
|
|
513
513
|
"name": "rovingTabindexController",
|
|
514
|
-
"default": "new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: ()
|
|
514
|
+
"default": "new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: () => 'both',\n elementEnterAction: (el) => {\n if (!this.auto) return;\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !el.disabled,\n listenerScope: () => this.tabList,\n })"
|
|
515
515
|
},
|
|
516
516
|
{
|
|
517
517
|
"kind": "field",
|
|
@@ -743,7 +743,7 @@
|
|
|
743
743
|
"name": "ScaledIndicator",
|
|
744
744
|
"declaration": {
|
|
745
745
|
"name": "ScaledIndicator",
|
|
746
|
-
"module": "src/Tabs.
|
|
746
|
+
"module": "src/Tabs.js"
|
|
747
747
|
}
|
|
748
748
|
},
|
|
749
749
|
{
|
|
@@ -751,14 +751,14 @@
|
|
|
751
751
|
"name": "Tabs",
|
|
752
752
|
"declaration": {
|
|
753
753
|
"name": "Tabs",
|
|
754
|
-
"module": "src/Tabs.
|
|
754
|
+
"module": "src/Tabs.js"
|
|
755
755
|
}
|
|
756
756
|
}
|
|
757
757
|
]
|
|
758
758
|
},
|
|
759
759
|
{
|
|
760
760
|
"kind": "javascript-module",
|
|
761
|
-
"path": "src/TabsOverflow.
|
|
761
|
+
"path": "src/TabsOverflow.js",
|
|
762
762
|
"declarations": [
|
|
763
763
|
{
|
|
764
764
|
"kind": "class",
|
|
@@ -894,7 +894,7 @@
|
|
|
894
894
|
"name": "TabsOverflow",
|
|
895
895
|
"declaration": {
|
|
896
896
|
"name": "TabsOverflow",
|
|
897
|
-
"module": "src/TabsOverflow.
|
|
897
|
+
"module": "src/TabsOverflow.js"
|
|
898
898
|
}
|
|
899
899
|
}
|
|
900
900
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/tabs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -86,14 +86,14 @@
|
|
|
86
86
|
],
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"@lit-labs/observers": "^2.0.0",
|
|
89
|
-
"@spectrum-web-components/base": "^0.
|
|
90
|
-
"@spectrum-web-components/icon": "^0.
|
|
91
|
-
"@spectrum-web-components/icons-ui": "^0.
|
|
92
|
-
"@spectrum-web-components/reactive-controllers": "^0.
|
|
93
|
-
"@spectrum-web-components/shared": "^0.
|
|
89
|
+
"@spectrum-web-components/base": "^0.35.0",
|
|
90
|
+
"@spectrum-web-components/icon": "^0.35.0",
|
|
91
|
+
"@spectrum-web-components/icons-ui": "^0.35.0",
|
|
92
|
+
"@spectrum-web-components/reactive-controllers": "^0.35.0",
|
|
93
|
+
"@spectrum-web-components/shared": "^0.35.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
|
-
"@spectrum-css/tabs": "^4.0.
|
|
96
|
+
"@spectrum-css/tabs": "^4.0.2"
|
|
97
97
|
},
|
|
98
98
|
"types": "./src/index.d.ts",
|
|
99
99
|
"customElements": "custom-elements.json",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"./sp-*.js",
|
|
102
102
|
"./**/*.dev.js"
|
|
103
103
|
],
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "1ee5a6c92838cdf48321276d97f61c20f8476ac1"
|
|
105
105
|
}
|
package/src/Tabs.dev.js
CHANGED
|
@@ -81,7 +81,7 @@ export class Tabs extends SizedMixin(Focusable) {
|
|
|
81
81
|
});
|
|
82
82
|
return firstFocusableElement ? focusInIndex : -1;
|
|
83
83
|
},
|
|
84
|
-
direction: () =>
|
|
84
|
+
direction: () => "both",
|
|
85
85
|
elementEnterAction: (el) => {
|
|
86
86
|
if (!this.auto)
|
|
87
87
|
return;
|
package/src/Tabs.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n css,\n CSSResult,\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n classMap,\n ifDefined,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\nimport { Tab } from './Tab.dev.js'\nimport { Focusable } from '@spectrum-web-components/shared';\nimport { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\n\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.js';\nimport { TabPanel } from './TabPanel.dev.js'\n\n// Encapsulated for use both here and in TopNav\nexport const ScaledIndicator = {\n baseSize: 100 as const,\n noSelectionStyle: 'transform: translateX(0px) scaleX(0) scaleY(0)',\n\n transformX(left: number, width: number): string {\n const scale = width / this.baseSize;\n return `transform: translateX(${left}px) scaleX(${scale});`;\n },\n\n transformY(top: number, height: number): string {\n const scale = height / this.baseSize;\n return `transform: translateY(${top}px) scaleY(${scale});`;\n },\n\n baseStyles(): CSSResult {\n return css`\n :host([direction='vertical-right']) #selection-indicator,\n :host([direction='vertical']) #selection-indicator {\n height: ${this.baseSize}px;\n }\n :host([dir][direction='horizontal']) #selection-indicator {\n width: ${this.baseSize}px;\n }\n `;\n },\n};\n\n/**\n * @element sp-tabs\n *\n * @slot - Tab elements to manage as a group\n * @slot tab-panel - Tab Panel elements related to the listed Tab elements\n * @csspart tablist - Container element for the slotted sp-tab elements\n *\n * @fires change - The selected Tab child has changed.\n */\nexport class Tabs extends SizedMixin(Focusable) {\n public static override get styles(): CSSResultArray {\n return [tabSizes, tabStyles, ScaledIndicator.baseStyles()];\n }\n\n /**\n * Whether to activate a tab on keyboard focus or not.\n *\n * By default a tab is activated via a \"click\" interaction. This is specifically intended for when\n * tab content cannot be displayed instantly, e.g. not all of the DOM content is available, etc.\n * To learn more about \"Deciding When to Make Selection Automatically Follow Focus\", visit:\n * https://w3c.github.io/aria-practices/#kbd_selection_follows_focus\n */\n @property({ type: Boolean })\n public auto = false;\n\n /**\n * The tab items are displayed closer together.\n */\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ reflect: true })\n public override dir!: 'ltr' | 'rtl';\n\n @property({ reflect: true })\n public direction: 'vertical' | 'vertical-right' | 'horizontal' =\n 'horizontal';\n\n @property({ type: Boolean, reflect: true })\n public emphasized = false;\n\n @property()\n public label = '';\n\n @property({ type: Boolean })\n public enableTabsScroll = false;\n\n /**\n * The tab list is displayed without a border.\n */\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ attribute: false })\n public selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n\n @property({ attribute: false })\n public shouldAnimate = false;\n\n @query('slot')\n private slotEl!: HTMLSlotElement;\n\n @query('#list')\n private tabList!: HTMLDivElement;\n\n @property({ reflect: true })\n selected = '';\n\n private set tabs(tabs: Tab[]) {\n if (tabs === this.tabs) return;\n this._tabs.forEach((tab) => {\n this.resizeController.unobserve(tab);\n });\n tabs.forEach((tab) => {\n this.resizeController.observe(tab);\n });\n this._tabs = tabs;\n this.rovingTabindexController.clearElementCache();\n }\n\n private get tabs(): Tab[] {\n return this._tabs;\n }\n\n private _tabs: Tab[] = [];\n\n constructor() {\n super();\n new IntersectionController(this, {\n config: {\n root: null,\n rootMargin: '0px',\n threshold: [0, 1],\n },\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n }\n\n protected resizeController = new ResizeController(this, {\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n\n rovingTabindexController = new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: () =>\n this.direction === 'horizontal' ? 'horizontal' : 'vertical',\n elementEnterAction: (el) => {\n if (!this.auto) return;\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !el.disabled,\n listenerScope: () => this.tabList,\n });\n\n /**\n * @private\n */\n public override get focusElement(): Tab | this {\n return this.rovingTabindexController.focusInElement || this;\n }\n\n public scrollTabs(\n delta: number,\n behavior: ScrollBehavior = 'smooth'\n ): void {\n this.tabList?.scrollBy({\n left: delta,\n top: 0,\n behavior,\n });\n }\n\n public get scrollState(): Record<string, boolean> {\n if (this.tabList) {\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const canScrollLeft = Math.abs(scrollLeft) > 0;\n const canScrollRight =\n Math.ceil(Math.abs(scrollLeft)) < scrollWidth - clientWidth;\n return {\n canScrollLeft:\n this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight:\n this.dir === 'ltr' ? canScrollRight : canScrollLeft,\n };\n }\n return {};\n }\n\n protected override manageAutoFocus(): void {\n const tabs = [...this.children] as Tab[];\n const tabUpdateCompletes = tabs.map((tab) => {\n if (typeof tab.updateComplete !== 'undefined') {\n return tab.updateComplete;\n }\n return Promise.resolve(true);\n });\n Promise.all(tabUpdateCompletes).then(() => super.manageAutoFocus());\n }\n\n protected managePanels({\n target,\n }: Event & { target: HTMLSlotElement }): void {\n const panels = target.assignedElements() as TabPanel[];\n panels.map((panel) => {\n const { value, id } = panel;\n const tab = this.querySelector(`[role=\"tab\"][value=\"${value}\"]`);\n if (tab) {\n tab.setAttribute('aria-controls', id);\n panel.setAttribute('aria-labelledby', tab.id);\n }\n panel.selected = value === this.selected;\n });\n }\n\n protected override render(): TemplateResult {\n return html`\n <div\n class=${classMap({ scroll: this.enableTabsScroll })}\n aria-label=${ifDefined(this.label ? this.label : undefined)}\n @click=${this.onClick}\n @keydown=${this.onKeyDown}\n @scroll=${this.onTabsScroll}\n id=\"list\"\n role=\"tablist\"\n part=\"tablist\"\n >\n <slot @slotchange=${this.onSlotChange}></slot>\n <div\n id=\"selection-indicator\"\n class=${ifDefined(\n this.shouldAnimate ? undefined : 'first-position'\n )}\n style=${this.selectionIndicatorStyle}\n role=\"presentation\"\n ></div>\n </div>\n <slot name=\"tab-panel\" @slotchange=${this.managePanels}></slot>\n `;\n }\n\n protected override willUpdate(changes: PropertyValues): void {\n if (!this.hasUpdated) {\n const selectedChild = this.querySelector(\n ':scope > [selected]'\n ) as Tab;\n if (selectedChild) {\n this.selectTarget(selectedChild);\n }\n }\n\n super.willUpdate(changes);\n if (changes.has('selected')) {\n if (this.tabs.length) {\n this.updateCheckedState();\n }\n if (changes.get('selected')) {\n const previous = this.querySelector(\n `[role=\"tabpanel\"][value=\"${changes.get('selected')}\"]`\n ) as TabPanel;\n if (previous) previous.selected = false;\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) next.selected = true;\n }\n if (changes.has('direction')) {\n if (this.direction === 'horizontal') {\n this.removeAttribute('aria-orientation');\n } else {\n this.setAttribute('aria-orientation', 'vertical');\n }\n }\n if (changes.has('dir')) {\n this.updateSelectionIndicator();\n }\n if (changes.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n if (\n !this.shouldAnimate &&\n typeof changes.get('shouldAnimate') !== 'undefined'\n ) {\n this.shouldAnimate = true;\n }\n }\n\n private onTabsScroll = (): void => {\n this.dispatchEvent(\n new Event('sp-tabs-scroll', {\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private onClick = (event: Event): void => {\n if (this.disabled) {\n return;\n }\n const target = event\n .composedPath()\n .find((el) => (el as Tab).parentElement === this) as Tab;\n if (!target || target.disabled) {\n return;\n }\n this.shouldAnimate = true;\n this.selectTarget(target);\n };\n\n private onKeyDown = (event: KeyboardEvent): void => {\n if (event.code === 'Enter' || event.code === 'Space') {\n event.preventDefault();\n const target = event.target as HTMLElement;\n if (target) {\n this.selectTarget(target);\n }\n }\n };\n\n private selectTarget(target: HTMLElement): void {\n const value = target.getAttribute('value');\n if (value) {\n const selected = this.selected;\n this.selected = value;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n cancelable: true,\n })\n );\n if (!applyDefault) {\n this.selected = selected;\n }\n }\n }\n\n private onSlotChange(): void {\n this.tabs = this.slotEl\n .assignedElements()\n .filter((el) => el.getAttribute('role') === 'tab') as Tab[];\n this.updateCheckedState();\n }\n\n private updateCheckedState = (): void => {\n this.tabs.forEach((element) => {\n element.removeAttribute('selected');\n });\n\n if (this.selected) {\n const currentChecked = this.tabs.find(\n (el) => el.value === this.selected\n );\n\n if (currentChecked) {\n currentChecked.selected = true;\n } else {\n this.selected = '';\n }\n } else {\n const firstTab = this.tabs[0];\n if (firstTab) {\n firstTab.setAttribute('tabindex', '0');\n }\n }\n\n this.updateSelectionIndicator();\n };\n\n private updateSelectionIndicator = async (): Promise<void> => {\n const selectedElement = this.tabs.find((el) => el.selected);\n if (!selectedElement) {\n this.selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n return;\n }\n await Promise.all([\n selectedElement.updateComplete,\n document.fonts ? document.fonts.ready : Promise.resolve(),\n ]);\n const { width, height } = selectedElement.getBoundingClientRect();\n\n this.selectionIndicatorStyle =\n this.direction === 'horizontal'\n ? ScaledIndicator.transformX(selectedElement.offsetLeft, width)\n : ScaledIndicator.transformY(selectedElement.offsetTop, height);\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n window.addEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n addEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.addEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n }\n\n public override disconnectedCallback(): void {\n window.removeEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n removeEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.removeEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAYA;AAAA,EACI;AAAA,EAGA;AAAA,EAEA;AAAA,OAEG;AACP;AAAA,EACI;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,EACA;AAAA,OACG;AACP,SAAS,8BAA8B;AACvC,SAAS,wBAAwB;AAEjC,SAAS,iBAAiB;AAC1B,SAAS,gCAAgC;AAEzC,OAAO,eAAe;AACtB,OAAO,cAAc;AAId,aAAM,kBAAkB;AAAA,EAC3B,UAAU;AAAA,EACV,kBAAkB;AAAA,EAElB,WAAW,MAAc,OAAuB;AAC5C,UAAM,QAAQ,QAAQ,KAAK;AAC3B,WAAO,yBAAyB,kBAAkB;AAAA,EACtD;AAAA,EAEA,WAAW,KAAa,QAAwB;AAC5C,UAAM,QAAQ,SAAS,KAAK;AAC5B,WAAO,yBAAyB,iBAAiB;AAAA,EACrD;AAAA,EAEA,aAAwB;AACpB,WAAO;AAAA;AAAA;AAAA,0BAGW,KAAK;AAAA;AAAA;AAAA,yBAGN,KAAK;AAAA;AAAA;AAAA,EAG1B;AACJ;AAWO,aAAM,aAAa,WAAW,SAAS,EAAE;AAAA,EA6E5C,cAAc;AACV,UAAM;AAhEV,SAAO,OAAO;AAMd,SAAO,UAAU;AAMjB,SAAO,YACH;AAGJ,SAAO,aAAa;AAGpB,SAAO,QAAQ;AAGf,SAAO,mBAAmB;AAM1B,SAAO,QAAQ;AAGf,SAAO,0BAA0B,gBAAgB;AAGjD,SAAO,gBAAgB;AASvB,oBAAW;AAkBX,SAAQ,QAAe,CAAC;AAgBxB,SAAU,mBAAmB,IAAI,iBAAiB,MAAM;AAAA,MACpD,UAAU,MAAM;AACZ,aAAK,yBAAyB;AAAA,MAClC;AAAA,IACJ,CAAC;AAED,oCAA2B,IAAI,yBAA8B,MAAM;AAAA,MAC/D,cAAc,CAAC,aAAa;AACxB,YAAI,eAAe;AACnB,cAAM,wBAAwB,SAAS,KAAK,CAAC,IAAI,UAAU;AACvD,gBAAM,iBAAiB,KAAK,WACtB,CAAC,GAAG,YAAY,GAAG,UAAU,KAAK,WAClC,CAAC,GAAG;AACV,yBAAe;AACf,iBAAO;AAAA,QACX,CAAC;AACD,eAAO,wBAAwB,eAAe;AAAA,MAClD;AAAA,MACA,WAAW,
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n css,\n CSSResult,\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n classMap,\n ifDefined,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\nimport { Tab } from './Tab.dev.js'\nimport { Focusable } from '@spectrum-web-components/shared';\nimport { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\n\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.js';\nimport { TabPanel } from './TabPanel.dev.js'\n\n// Encapsulated for use both here and in TopNav\nexport const ScaledIndicator = {\n baseSize: 100 as const,\n noSelectionStyle: 'transform: translateX(0px) scaleX(0) scaleY(0)',\n\n transformX(left: number, width: number): string {\n const scale = width / this.baseSize;\n return `transform: translateX(${left}px) scaleX(${scale});`;\n },\n\n transformY(top: number, height: number): string {\n const scale = height / this.baseSize;\n return `transform: translateY(${top}px) scaleY(${scale});`;\n },\n\n baseStyles(): CSSResult {\n return css`\n :host([direction='vertical-right']) #selection-indicator,\n :host([direction='vertical']) #selection-indicator {\n height: ${this.baseSize}px;\n }\n :host([dir][direction='horizontal']) #selection-indicator {\n width: ${this.baseSize}px;\n }\n `;\n },\n};\n\n/**\n * @element sp-tabs\n *\n * @slot - Tab elements to manage as a group\n * @slot tab-panel - Tab Panel elements related to the listed Tab elements\n * @csspart tablist - Container element for the slotted sp-tab elements\n *\n * @fires change - The selected Tab child has changed.\n */\nexport class Tabs extends SizedMixin(Focusable) {\n public static override get styles(): CSSResultArray {\n return [tabSizes, tabStyles, ScaledIndicator.baseStyles()];\n }\n\n /**\n * Whether to activate a tab on keyboard focus or not.\n *\n * By default a tab is activated via a \"click\" interaction. This is specifically intended for when\n * tab content cannot be displayed instantly, e.g. not all of the DOM content is available, etc.\n * To learn more about \"Deciding When to Make Selection Automatically Follow Focus\", visit:\n * https://w3c.github.io/aria-practices/#kbd_selection_follows_focus\n */\n @property({ type: Boolean })\n public auto = false;\n\n /**\n * The tab items are displayed closer together.\n */\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ reflect: true })\n public override dir!: 'ltr' | 'rtl';\n\n @property({ reflect: true })\n public direction: 'vertical' | 'vertical-right' | 'horizontal' =\n 'horizontal';\n\n @property({ type: Boolean, reflect: true })\n public emphasized = false;\n\n @property()\n public label = '';\n\n @property({ type: Boolean })\n public enableTabsScroll = false;\n\n /**\n * The tab list is displayed without a border.\n */\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ attribute: false })\n public selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n\n @property({ attribute: false })\n public shouldAnimate = false;\n\n @query('slot')\n private slotEl!: HTMLSlotElement;\n\n @query('#list')\n private tabList!: HTMLDivElement;\n\n @property({ reflect: true })\n selected = '';\n\n private set tabs(tabs: Tab[]) {\n if (tabs === this.tabs) return;\n this._tabs.forEach((tab) => {\n this.resizeController.unobserve(tab);\n });\n tabs.forEach((tab) => {\n this.resizeController.observe(tab);\n });\n this._tabs = tabs;\n this.rovingTabindexController.clearElementCache();\n }\n\n private get tabs(): Tab[] {\n return this._tabs;\n }\n\n private _tabs: Tab[] = [];\n\n constructor() {\n super();\n new IntersectionController(this, {\n config: {\n root: null,\n rootMargin: '0px',\n threshold: [0, 1],\n },\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n }\n\n protected resizeController = new ResizeController(this, {\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n\n rovingTabindexController = new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: () => 'both',\n elementEnterAction: (el) => {\n if (!this.auto) return;\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !el.disabled,\n listenerScope: () => this.tabList,\n });\n\n /**\n * @private\n */\n public override get focusElement(): Tab | this {\n return this.rovingTabindexController.focusInElement || this;\n }\n\n public scrollTabs(\n delta: number,\n behavior: ScrollBehavior = 'smooth'\n ): void {\n this.tabList?.scrollBy({\n left: delta,\n top: 0,\n behavior,\n });\n }\n\n public get scrollState(): Record<string, boolean> {\n if (this.tabList) {\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const canScrollLeft = Math.abs(scrollLeft) > 0;\n const canScrollRight =\n Math.ceil(Math.abs(scrollLeft)) < scrollWidth - clientWidth;\n return {\n canScrollLeft:\n this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight:\n this.dir === 'ltr' ? canScrollRight : canScrollLeft,\n };\n }\n return {};\n }\n\n protected override manageAutoFocus(): void {\n const tabs = [...this.children] as Tab[];\n const tabUpdateCompletes = tabs.map((tab) => {\n if (typeof tab.updateComplete !== 'undefined') {\n return tab.updateComplete;\n }\n return Promise.resolve(true);\n });\n Promise.all(tabUpdateCompletes).then(() => super.manageAutoFocus());\n }\n\n protected managePanels({\n target,\n }: Event & { target: HTMLSlotElement }): void {\n const panels = target.assignedElements() as TabPanel[];\n panels.map((panel) => {\n const { value, id } = panel;\n const tab = this.querySelector(`[role=\"tab\"][value=\"${value}\"]`);\n if (tab) {\n tab.setAttribute('aria-controls', id);\n panel.setAttribute('aria-labelledby', tab.id);\n }\n panel.selected = value === this.selected;\n });\n }\n\n protected override render(): TemplateResult {\n return html`\n <div\n class=${classMap({ scroll: this.enableTabsScroll })}\n aria-label=${ifDefined(this.label ? this.label : undefined)}\n @click=${this.onClick}\n @keydown=${this.onKeyDown}\n @scroll=${this.onTabsScroll}\n id=\"list\"\n role=\"tablist\"\n part=\"tablist\"\n >\n <slot @slotchange=${this.onSlotChange}></slot>\n <div\n id=\"selection-indicator\"\n class=${ifDefined(\n this.shouldAnimate ? undefined : 'first-position'\n )}\n style=${this.selectionIndicatorStyle}\n role=\"presentation\"\n ></div>\n </div>\n <slot name=\"tab-panel\" @slotchange=${this.managePanels}></slot>\n `;\n }\n\n protected override willUpdate(changes: PropertyValues): void {\n if (!this.hasUpdated) {\n const selectedChild = this.querySelector(\n ':scope > [selected]'\n ) as Tab;\n if (selectedChild) {\n this.selectTarget(selectedChild);\n }\n }\n\n super.willUpdate(changes);\n if (changes.has('selected')) {\n if (this.tabs.length) {\n this.updateCheckedState();\n }\n if (changes.get('selected')) {\n const previous = this.querySelector(\n `[role=\"tabpanel\"][value=\"${changes.get('selected')}\"]`\n ) as TabPanel;\n if (previous) previous.selected = false;\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) next.selected = true;\n }\n if (changes.has('direction')) {\n if (this.direction === 'horizontal') {\n this.removeAttribute('aria-orientation');\n } else {\n this.setAttribute('aria-orientation', 'vertical');\n }\n }\n if (changes.has('dir')) {\n this.updateSelectionIndicator();\n }\n if (changes.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n if (\n !this.shouldAnimate &&\n typeof changes.get('shouldAnimate') !== 'undefined'\n ) {\n this.shouldAnimate = true;\n }\n }\n\n private onTabsScroll = (): void => {\n this.dispatchEvent(\n new Event('sp-tabs-scroll', {\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private onClick = (event: Event): void => {\n if (this.disabled) {\n return;\n }\n const target = event\n .composedPath()\n .find((el) => (el as Tab).parentElement === this) as Tab;\n if (!target || target.disabled) {\n return;\n }\n this.shouldAnimate = true;\n this.selectTarget(target);\n };\n\n private onKeyDown = (event: KeyboardEvent): void => {\n if (event.code === 'Enter' || event.code === 'Space') {\n event.preventDefault();\n const target = event.target as HTMLElement;\n if (target) {\n this.selectTarget(target);\n }\n }\n };\n\n private selectTarget(target: HTMLElement): void {\n const value = target.getAttribute('value');\n if (value) {\n const selected = this.selected;\n this.selected = value;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n cancelable: true,\n })\n );\n if (!applyDefault) {\n this.selected = selected;\n }\n }\n }\n\n private onSlotChange(): void {\n this.tabs = this.slotEl\n .assignedElements()\n .filter((el) => el.getAttribute('role') === 'tab') as Tab[];\n this.updateCheckedState();\n }\n\n private updateCheckedState = (): void => {\n this.tabs.forEach((element) => {\n element.removeAttribute('selected');\n });\n\n if (this.selected) {\n const currentChecked = this.tabs.find(\n (el) => el.value === this.selected\n );\n\n if (currentChecked) {\n currentChecked.selected = true;\n } else {\n this.selected = '';\n }\n } else {\n const firstTab = this.tabs[0];\n if (firstTab) {\n firstTab.setAttribute('tabindex', '0');\n }\n }\n\n this.updateSelectionIndicator();\n };\n\n private updateSelectionIndicator = async (): Promise<void> => {\n const selectedElement = this.tabs.find((el) => el.selected);\n if (!selectedElement) {\n this.selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n return;\n }\n await Promise.all([\n selectedElement.updateComplete,\n document.fonts ? document.fonts.ready : Promise.resolve(),\n ]);\n const { width, height } = selectedElement.getBoundingClientRect();\n\n this.selectionIndicatorStyle =\n this.direction === 'horizontal'\n ? ScaledIndicator.transformX(selectedElement.offsetLeft, width)\n : ScaledIndicator.transformY(selectedElement.offsetTop, height);\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n window.addEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n addEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.addEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n }\n\n public override disconnectedCallback(): void {\n window.removeEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n removeEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.removeEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/Tabs.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
:host([dir][direction='horizontal']) #selection-indicator {
|
|
7
7
|
width: ${this.baseSize}px;
|
|
8
8
|
}
|
|
9
|
-
`}};export class Tabs extends m(y){constructor(){super();this.auto=!1;this.compact=!1;this.direction="horizontal";this.emphasized=!1;this.label="";this.enableTabsScroll=!1;this.quiet=!1;this.selectionIndicatorStyle=ScaledIndicator.noSelectionStyle;this.shouldAnimate=!1;this.selected="";this._tabs=[];this.resizeController=new g(this,{callback:()=>{this.updateSelectionIndicator()}});this.rovingTabindexController=new E(this,{focusInIndex:e=>{let t=0;return e.find((s,l)=>{const c=this.selected?!s.disabled&&s.value===this.selected:!s.disabled;return t=l,c})?t:-1},direction:()=>
|
|
9
|
+
`}};export class Tabs extends m(y){constructor(){super();this.auto=!1;this.compact=!1;this.direction="horizontal";this.emphasized=!1;this.label="";this.enableTabsScroll=!1;this.quiet=!1;this.selectionIndicatorStyle=ScaledIndicator.noSelectionStyle;this.shouldAnimate=!1;this.selected="";this._tabs=[];this.resizeController=new g(this,{callback:()=>{this.updateSelectionIndicator()}});this.rovingTabindexController=new E(this,{focusInIndex:e=>{let t=0;return e.find((s,l)=>{const c=this.selected?!s.disabled&&s.value===this.selected:!s.disabled;return t=l,c})?t:-1},direction:()=>"both",elementEnterAction:e=>{this.auto&&(this.shouldAnimate=!0,this.selectTarget(e))},elements:()=>this.tabs,isFocusableElement:e=>!e.disabled,listenerScope:()=>this.tabList});this.onTabsScroll=()=>{this.dispatchEvent(new Event("sp-tabs-scroll",{bubbles:!0,composed:!0}))};this.onClick=e=>{if(this.disabled)return;const t=e.composedPath().find(i=>i.parentElement===this);!t||t.disabled||(this.shouldAnimate=!0,this.selectTarget(t))};this.onKeyDown=e=>{if(e.code==="Enter"||e.code==="Space"){e.preventDefault();const t=e.target;t&&this.selectTarget(t)}};this.updateCheckedState=()=>{if(this.tabs.forEach(e=>{e.removeAttribute("selected")}),this.selected){const e=this.tabs.find(t=>t.value===this.selected);e?e.selected=!0:this.selected=""}else{const e=this.tabs[0];e&&e.setAttribute("tabindex","0")}this.updateSelectionIndicator()};this.updateSelectionIndicator=async()=>{const e=this.tabs.find(s=>s.selected);if(!e){this.selectionIndicatorStyle=ScaledIndicator.noSelectionStyle;return}await Promise.all([e.updateComplete,document.fonts?document.fonts.ready:Promise.resolve()]);const{width:t,height:i}=e.getBoundingClientRect();this.selectionIndicatorStyle=this.direction==="horizontal"?ScaledIndicator.transformX(e.offsetLeft,t):ScaledIndicator.transformY(e.offsetTop,i)};new S(this,{config:{root:null,rootMargin:"0px",threshold:[0,1]},callback:()=>{this.updateSelectionIndicator()}})}static get styles(){return[T,C,ScaledIndicator.baseStyles()]}set tabs(e){e!==this.tabs&&(this._tabs.forEach(t=>{this.resizeController.unobserve(t)}),e.forEach(t=>{this.resizeController.observe(t)}),this._tabs=e,this.rovingTabindexController.clearElementCache())}get tabs(){return this._tabs}get focusElement(){return this.rovingTabindexController.focusInElement||this}scrollTabs(e,t="smooth"){var i;(i=this.tabList)==null||i.scrollBy({left:e,top:0,behavior:t})}get scrollState(){if(this.tabList){const{scrollLeft:e,clientWidth:t,scrollWidth:i}=this.tabList,s=Math.abs(e)>0,l=Math.ceil(Math.abs(e))<i-t;return{canScrollLeft:this.dir==="ltr"?s:l,canScrollRight:this.dir==="ltr"?l:s}}return{}}manageAutoFocus(){const t=[...this.children].map(i=>typeof i.updateComplete!="undefined"?i.updateComplete:Promise.resolve(!0));Promise.all(t).then(()=>super.manageAutoFocus())}managePanels({target:e}){e.assignedElements().map(i=>{const{value:s,id:l}=i,c=this.querySelector(`[role="tab"][value="${s}"]`);c&&(c.setAttribute("aria-controls",l),i.setAttribute("aria-labelledby",c.id)),i.selected=s===this.selected})}render(){return f`
|
|
10
10
|
<div
|
|
11
11
|
class=${v({scroll:this.enableTabsScroll})}
|
|
12
12
|
aria-label=${u(this.label?this.label:void 0)}
|
package/src/Tabs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n css,\n CSSResult,\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n classMap,\n ifDefined,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\nimport { Tab } from './Tab.js';\nimport { Focusable } from '@spectrum-web-components/shared';\nimport { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\n\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.js';\nimport { TabPanel } from './TabPanel.js';\n\n// Encapsulated for use both here and in TopNav\nexport const ScaledIndicator = {\n baseSize: 100 as const,\n noSelectionStyle: 'transform: translateX(0px) scaleX(0) scaleY(0)',\n\n transformX(left: number, width: number): string {\n const scale = width / this.baseSize;\n return `transform: translateX(${left}px) scaleX(${scale});`;\n },\n\n transformY(top: number, height: number): string {\n const scale = height / this.baseSize;\n return `transform: translateY(${top}px) scaleY(${scale});`;\n },\n\n baseStyles(): CSSResult {\n return css`\n :host([direction='vertical-right']) #selection-indicator,\n :host([direction='vertical']) #selection-indicator {\n height: ${this.baseSize}px;\n }\n :host([dir][direction='horizontal']) #selection-indicator {\n width: ${this.baseSize}px;\n }\n `;\n },\n};\n\n/**\n * @element sp-tabs\n *\n * @slot - Tab elements to manage as a group\n * @slot tab-panel - Tab Panel elements related to the listed Tab elements\n * @csspart tablist - Container element for the slotted sp-tab elements\n *\n * @fires change - The selected Tab child has changed.\n */\nexport class Tabs extends SizedMixin(Focusable) {\n public static override get styles(): CSSResultArray {\n return [tabSizes, tabStyles, ScaledIndicator.baseStyles()];\n }\n\n /**\n * Whether to activate a tab on keyboard focus or not.\n *\n * By default a tab is activated via a \"click\" interaction. This is specifically intended for when\n * tab content cannot be displayed instantly, e.g. not all of the DOM content is available, etc.\n * To learn more about \"Deciding When to Make Selection Automatically Follow Focus\", visit:\n * https://w3c.github.io/aria-practices/#kbd_selection_follows_focus\n */\n @property({ type: Boolean })\n public auto = false;\n\n /**\n * The tab items are displayed closer together.\n */\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ reflect: true })\n public override dir!: 'ltr' | 'rtl';\n\n @property({ reflect: true })\n public direction: 'vertical' | 'vertical-right' | 'horizontal' =\n 'horizontal';\n\n @property({ type: Boolean, reflect: true })\n public emphasized = false;\n\n @property()\n public label = '';\n\n @property({ type: Boolean })\n public enableTabsScroll = false;\n\n /**\n * The tab list is displayed without a border.\n */\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ attribute: false })\n public selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n\n @property({ attribute: false })\n public shouldAnimate = false;\n\n @query('slot')\n private slotEl!: HTMLSlotElement;\n\n @query('#list')\n private tabList!: HTMLDivElement;\n\n @property({ reflect: true })\n selected = '';\n\n private set tabs(tabs: Tab[]) {\n if (tabs === this.tabs) return;\n this._tabs.forEach((tab) => {\n this.resizeController.unobserve(tab);\n });\n tabs.forEach((tab) => {\n this.resizeController.observe(tab);\n });\n this._tabs = tabs;\n this.rovingTabindexController.clearElementCache();\n }\n\n private get tabs(): Tab[] {\n return this._tabs;\n }\n\n private _tabs: Tab[] = [];\n\n constructor() {\n super();\n new IntersectionController(this, {\n config: {\n root: null,\n rootMargin: '0px',\n threshold: [0, 1],\n },\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n }\n\n protected resizeController = new ResizeController(this, {\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n\n rovingTabindexController = new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: () =>\n this.direction === 'horizontal' ? 'horizontal' : 'vertical',\n elementEnterAction: (el) => {\n if (!this.auto) return;\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !el.disabled,\n listenerScope: () => this.tabList,\n });\n\n /**\n * @private\n */\n public override get focusElement(): Tab | this {\n return this.rovingTabindexController.focusInElement || this;\n }\n\n public scrollTabs(\n delta: number,\n behavior: ScrollBehavior = 'smooth'\n ): void {\n this.tabList?.scrollBy({\n left: delta,\n top: 0,\n behavior,\n });\n }\n\n public get scrollState(): Record<string, boolean> {\n if (this.tabList) {\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const canScrollLeft = Math.abs(scrollLeft) > 0;\n const canScrollRight =\n Math.ceil(Math.abs(scrollLeft)) < scrollWidth - clientWidth;\n return {\n canScrollLeft:\n this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight:\n this.dir === 'ltr' ? canScrollRight : canScrollLeft,\n };\n }\n return {};\n }\n\n protected override manageAutoFocus(): void {\n const tabs = [...this.children] as Tab[];\n const tabUpdateCompletes = tabs.map((tab) => {\n if (typeof tab.updateComplete !== 'undefined') {\n return tab.updateComplete;\n }\n return Promise.resolve(true);\n });\n Promise.all(tabUpdateCompletes).then(() => super.manageAutoFocus());\n }\n\n protected managePanels({\n target,\n }: Event & { target: HTMLSlotElement }): void {\n const panels = target.assignedElements() as TabPanel[];\n panels.map((panel) => {\n const { value, id } = panel;\n const tab = this.querySelector(`[role=\"tab\"][value=\"${value}\"]`);\n if (tab) {\n tab.setAttribute('aria-controls', id);\n panel.setAttribute('aria-labelledby', tab.id);\n }\n panel.selected = value === this.selected;\n });\n }\n\n protected override render(): TemplateResult {\n return html`\n <div\n class=${classMap({ scroll: this.enableTabsScroll })}\n aria-label=${ifDefined(this.label ? this.label : undefined)}\n @click=${this.onClick}\n @keydown=${this.onKeyDown}\n @scroll=${this.onTabsScroll}\n id=\"list\"\n role=\"tablist\"\n part=\"tablist\"\n >\n <slot @slotchange=${this.onSlotChange}></slot>\n <div\n id=\"selection-indicator\"\n class=${ifDefined(\n this.shouldAnimate ? undefined : 'first-position'\n )}\n style=${this.selectionIndicatorStyle}\n role=\"presentation\"\n ></div>\n </div>\n <slot name=\"tab-panel\" @slotchange=${this.managePanels}></slot>\n `;\n }\n\n protected override willUpdate(changes: PropertyValues): void {\n if (!this.hasUpdated) {\n const selectedChild = this.querySelector(\n ':scope > [selected]'\n ) as Tab;\n if (selectedChild) {\n this.selectTarget(selectedChild);\n }\n }\n\n super.willUpdate(changes);\n if (changes.has('selected')) {\n if (this.tabs.length) {\n this.updateCheckedState();\n }\n if (changes.get('selected')) {\n const previous = this.querySelector(\n `[role=\"tabpanel\"][value=\"${changes.get('selected')}\"]`\n ) as TabPanel;\n if (previous) previous.selected = false;\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) next.selected = true;\n }\n if (changes.has('direction')) {\n if (this.direction === 'horizontal') {\n this.removeAttribute('aria-orientation');\n } else {\n this.setAttribute('aria-orientation', 'vertical');\n }\n }\n if (changes.has('dir')) {\n this.updateSelectionIndicator();\n }\n if (changes.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n if (\n !this.shouldAnimate &&\n typeof changes.get('shouldAnimate') !== 'undefined'\n ) {\n this.shouldAnimate = true;\n }\n }\n\n private onTabsScroll = (): void => {\n this.dispatchEvent(\n new Event('sp-tabs-scroll', {\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private onClick = (event: Event): void => {\n if (this.disabled) {\n return;\n }\n const target = event\n .composedPath()\n .find((el) => (el as Tab).parentElement === this) as Tab;\n if (!target || target.disabled) {\n return;\n }\n this.shouldAnimate = true;\n this.selectTarget(target);\n };\n\n private onKeyDown = (event: KeyboardEvent): void => {\n if (event.code === 'Enter' || event.code === 'Space') {\n event.preventDefault();\n const target = event.target as HTMLElement;\n if (target) {\n this.selectTarget(target);\n }\n }\n };\n\n private selectTarget(target: HTMLElement): void {\n const value = target.getAttribute('value');\n if (value) {\n const selected = this.selected;\n this.selected = value;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n cancelable: true,\n })\n );\n if (!applyDefault) {\n this.selected = selected;\n }\n }\n }\n\n private onSlotChange(): void {\n this.tabs = this.slotEl\n .assignedElements()\n .filter((el) => el.getAttribute('role') === 'tab') as Tab[];\n this.updateCheckedState();\n }\n\n private updateCheckedState = (): void => {\n this.tabs.forEach((element) => {\n element.removeAttribute('selected');\n });\n\n if (this.selected) {\n const currentChecked = this.tabs.find(\n (el) => el.value === this.selected\n );\n\n if (currentChecked) {\n currentChecked.selected = true;\n } else {\n this.selected = '';\n }\n } else {\n const firstTab = this.tabs[0];\n if (firstTab) {\n firstTab.setAttribute('tabindex', '0');\n }\n }\n\n this.updateSelectionIndicator();\n };\n\n private updateSelectionIndicator = async (): Promise<void> => {\n const selectedElement = this.tabs.find((el) => el.selected);\n if (!selectedElement) {\n this.selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n return;\n }\n await Promise.all([\n selectedElement.updateComplete,\n document.fonts ? document.fonts.ready : Promise.resolve(),\n ]);\n const { width, height } = selectedElement.getBoundingClientRect();\n\n this.selectionIndicatorStyle =\n this.direction === 'horizontal'\n ? ScaledIndicator.transformX(selectedElement.offsetLeft, width)\n : ScaledIndicator.transformY(selectedElement.offsetTop, height);\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n window.addEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n addEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.addEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n }\n\n public override disconnectedCallback(): void {\n window.removeEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n removeEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.removeEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": "qNAYA,OACI,OAAAA,EAGA,QAAAC,EAEA,cAAAC,MAEG,gCACP,OACI,YAAAC,EACA,SAAAC,MACG,kDACP,OACI,YAAAC,EACA,aAAAC,MACG,kDACP,OAAS,0BAAAC,MAA8B,iDACvC,OAAS,oBAAAC,MAAwB,2CAEjC,OAAS,aAAAC,MAAiB,kCAC1B,OAAS,4BAAAC,MAAgC,sEAEzC,OAAOC,MAAe,gBACtB,OAAOC,MAAc,sBAId,aAAM,gBAAkB,CAC3B,SAAU,IACV,iBAAkB,iDAElB,WAAWC,EAAcC,EAAuB,CAC5C,MAAMC,EAAQD,EAAQ,KAAK,SAC3B,MAAO,yBAAyBD,eAAkBE,KACtD,EAEA,WAAWC,EAAaC,EAAwB,CAC5C,MAAMF,EAAQE,EAAS,KAAK,SAC5B,MAAO,yBAAyBD,eAAiBD,KACrD,EAEA,YAAwB,CACpB,OAAOf;AAAA;AAAA;AAAA,0BAGW,KAAK;AAAA;AAAA;AAAA,yBAGN,KAAK;AAAA;AAAA,SAG1B,CACJ,EAWO,aAAM,aAAaE,EAAWO,CAAS,CAAE,CA6E5C,aAAc,CACV,MAAM,EAhEV,KAAO,KAAO,GAMd,KAAO,QAAU,GAMjB,KAAO,UACH,aAGJ,KAAO,WAAa,GAGpB,KAAO,MAAQ,GAGf,KAAO,iBAAmB,GAM1B,KAAO,MAAQ,GAGf,KAAO,wBAA0B,gBAAgB,iBAGjD,KAAO,cAAgB,GASvB,cAAW,GAkBX,KAAQ,MAAe,CAAC,EAgBxB,KAAU,iBAAmB,IAAID,EAAiB,KAAM,CACpD,SAAU,IAAM,CACZ,KAAK,yBAAyB,CAClC,CACJ,CAAC,EAED,8BAA2B,IAAIE,EAA8B,KAAM,CAC/D,aAAeQ,GAAa,CACxB,IAAIC,EAAe,EAQnB,OAP8BD,EAAS,KAAK,CAACE,EAAIC,IAAU,CACvD,MAAMC,EAAiB,KAAK,SACtB,CAACF,EAAG,UAAYA,EAAG,QAAU,KAAK,SAClC,CAACA,EAAG,SACV,OAAAD,EAAeE,EACRC,CACX,CAAC,EAC8BH,EAAe,EAClD,EACA,UAAW,
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport {\n css,\n CSSResult,\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n classMap,\n ifDefined,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\nimport { Tab } from './Tab.js';\nimport { Focusable } from '@spectrum-web-components/shared';\nimport { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\n\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.js';\nimport { TabPanel } from './TabPanel.js';\n\n// Encapsulated for use both here and in TopNav\nexport const ScaledIndicator = {\n baseSize: 100 as const,\n noSelectionStyle: 'transform: translateX(0px) scaleX(0) scaleY(0)',\n\n transformX(left: number, width: number): string {\n const scale = width / this.baseSize;\n return `transform: translateX(${left}px) scaleX(${scale});`;\n },\n\n transformY(top: number, height: number): string {\n const scale = height / this.baseSize;\n return `transform: translateY(${top}px) scaleY(${scale});`;\n },\n\n baseStyles(): CSSResult {\n return css`\n :host([direction='vertical-right']) #selection-indicator,\n :host([direction='vertical']) #selection-indicator {\n height: ${this.baseSize}px;\n }\n :host([dir][direction='horizontal']) #selection-indicator {\n width: ${this.baseSize}px;\n }\n `;\n },\n};\n\n/**\n * @element sp-tabs\n *\n * @slot - Tab elements to manage as a group\n * @slot tab-panel - Tab Panel elements related to the listed Tab elements\n * @csspart tablist - Container element for the slotted sp-tab elements\n *\n * @fires change - The selected Tab child has changed.\n */\nexport class Tabs extends SizedMixin(Focusable) {\n public static override get styles(): CSSResultArray {\n return [tabSizes, tabStyles, ScaledIndicator.baseStyles()];\n }\n\n /**\n * Whether to activate a tab on keyboard focus or not.\n *\n * By default a tab is activated via a \"click\" interaction. This is specifically intended for when\n * tab content cannot be displayed instantly, e.g. not all of the DOM content is available, etc.\n * To learn more about \"Deciding When to Make Selection Automatically Follow Focus\", visit:\n * https://w3c.github.io/aria-practices/#kbd_selection_follows_focus\n */\n @property({ type: Boolean })\n public auto = false;\n\n /**\n * The tab items are displayed closer together.\n */\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ reflect: true })\n public override dir!: 'ltr' | 'rtl';\n\n @property({ reflect: true })\n public direction: 'vertical' | 'vertical-right' | 'horizontal' =\n 'horizontal';\n\n @property({ type: Boolean, reflect: true })\n public emphasized = false;\n\n @property()\n public label = '';\n\n @property({ type: Boolean })\n public enableTabsScroll = false;\n\n /**\n * The tab list is displayed without a border.\n */\n @property({ type: Boolean, reflect: true })\n public quiet = false;\n\n @property({ attribute: false })\n public selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n\n @property({ attribute: false })\n public shouldAnimate = false;\n\n @query('slot')\n private slotEl!: HTMLSlotElement;\n\n @query('#list')\n private tabList!: HTMLDivElement;\n\n @property({ reflect: true })\n selected = '';\n\n private set tabs(tabs: Tab[]) {\n if (tabs === this.tabs) return;\n this._tabs.forEach((tab) => {\n this.resizeController.unobserve(tab);\n });\n tabs.forEach((tab) => {\n this.resizeController.observe(tab);\n });\n this._tabs = tabs;\n this.rovingTabindexController.clearElementCache();\n }\n\n private get tabs(): Tab[] {\n return this._tabs;\n }\n\n private _tabs: Tab[] = [];\n\n constructor() {\n super();\n new IntersectionController(this, {\n config: {\n root: null,\n rootMargin: '0px',\n threshold: [0, 1],\n },\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n }\n\n protected resizeController = new ResizeController(this, {\n callback: () => {\n this.updateSelectionIndicator();\n },\n });\n\n rovingTabindexController = new RovingTabindexController<Tab>(this, {\n focusInIndex: (elements) => {\n let focusInIndex = 0;\n const firstFocusableElement = elements.find((el, index) => {\n const focusInElement = this.selected\n ? !el.disabled && el.value === this.selected\n : !el.disabled;\n focusInIndex = index;\n return focusInElement;\n });\n return firstFocusableElement ? focusInIndex : -1;\n },\n direction: () => 'both',\n elementEnterAction: (el) => {\n if (!this.auto) return;\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !el.disabled,\n listenerScope: () => this.tabList,\n });\n\n /**\n * @private\n */\n public override get focusElement(): Tab | this {\n return this.rovingTabindexController.focusInElement || this;\n }\n\n public scrollTabs(\n delta: number,\n behavior: ScrollBehavior = 'smooth'\n ): void {\n this.tabList?.scrollBy({\n left: delta,\n top: 0,\n behavior,\n });\n }\n\n public get scrollState(): Record<string, boolean> {\n if (this.tabList) {\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const canScrollLeft = Math.abs(scrollLeft) > 0;\n const canScrollRight =\n Math.ceil(Math.abs(scrollLeft)) < scrollWidth - clientWidth;\n return {\n canScrollLeft:\n this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight:\n this.dir === 'ltr' ? canScrollRight : canScrollLeft,\n };\n }\n return {};\n }\n\n protected override manageAutoFocus(): void {\n const tabs = [...this.children] as Tab[];\n const tabUpdateCompletes = tabs.map((tab) => {\n if (typeof tab.updateComplete !== 'undefined') {\n return tab.updateComplete;\n }\n return Promise.resolve(true);\n });\n Promise.all(tabUpdateCompletes).then(() => super.manageAutoFocus());\n }\n\n protected managePanels({\n target,\n }: Event & { target: HTMLSlotElement }): void {\n const panels = target.assignedElements() as TabPanel[];\n panels.map((panel) => {\n const { value, id } = panel;\n const tab = this.querySelector(`[role=\"tab\"][value=\"${value}\"]`);\n if (tab) {\n tab.setAttribute('aria-controls', id);\n panel.setAttribute('aria-labelledby', tab.id);\n }\n panel.selected = value === this.selected;\n });\n }\n\n protected override render(): TemplateResult {\n return html`\n <div\n class=${classMap({ scroll: this.enableTabsScroll })}\n aria-label=${ifDefined(this.label ? this.label : undefined)}\n @click=${this.onClick}\n @keydown=${this.onKeyDown}\n @scroll=${this.onTabsScroll}\n id=\"list\"\n role=\"tablist\"\n part=\"tablist\"\n >\n <slot @slotchange=${this.onSlotChange}></slot>\n <div\n id=\"selection-indicator\"\n class=${ifDefined(\n this.shouldAnimate ? undefined : 'first-position'\n )}\n style=${this.selectionIndicatorStyle}\n role=\"presentation\"\n ></div>\n </div>\n <slot name=\"tab-panel\" @slotchange=${this.managePanels}></slot>\n `;\n }\n\n protected override willUpdate(changes: PropertyValues): void {\n if (!this.hasUpdated) {\n const selectedChild = this.querySelector(\n ':scope > [selected]'\n ) as Tab;\n if (selectedChild) {\n this.selectTarget(selectedChild);\n }\n }\n\n super.willUpdate(changes);\n if (changes.has('selected')) {\n if (this.tabs.length) {\n this.updateCheckedState();\n }\n if (changes.get('selected')) {\n const previous = this.querySelector(\n `[role=\"tabpanel\"][value=\"${changes.get('selected')}\"]`\n ) as TabPanel;\n if (previous) previous.selected = false;\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) next.selected = true;\n }\n if (changes.has('direction')) {\n if (this.direction === 'horizontal') {\n this.removeAttribute('aria-orientation');\n } else {\n this.setAttribute('aria-orientation', 'vertical');\n }\n }\n if (changes.has('dir')) {\n this.updateSelectionIndicator();\n }\n if (changes.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n if (\n !this.shouldAnimate &&\n typeof changes.get('shouldAnimate') !== 'undefined'\n ) {\n this.shouldAnimate = true;\n }\n }\n\n private onTabsScroll = (): void => {\n this.dispatchEvent(\n new Event('sp-tabs-scroll', {\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private onClick = (event: Event): void => {\n if (this.disabled) {\n return;\n }\n const target = event\n .composedPath()\n .find((el) => (el as Tab).parentElement === this) as Tab;\n if (!target || target.disabled) {\n return;\n }\n this.shouldAnimate = true;\n this.selectTarget(target);\n };\n\n private onKeyDown = (event: KeyboardEvent): void => {\n if (event.code === 'Enter' || event.code === 'Space') {\n event.preventDefault();\n const target = event.target as HTMLElement;\n if (target) {\n this.selectTarget(target);\n }\n }\n };\n\n private selectTarget(target: HTMLElement): void {\n const value = target.getAttribute('value');\n if (value) {\n const selected = this.selected;\n this.selected = value;\n const applyDefault = this.dispatchEvent(\n new Event('change', {\n cancelable: true,\n })\n );\n if (!applyDefault) {\n this.selected = selected;\n }\n }\n }\n\n private onSlotChange(): void {\n this.tabs = this.slotEl\n .assignedElements()\n .filter((el) => el.getAttribute('role') === 'tab') as Tab[];\n this.updateCheckedState();\n }\n\n private updateCheckedState = (): void => {\n this.tabs.forEach((element) => {\n element.removeAttribute('selected');\n });\n\n if (this.selected) {\n const currentChecked = this.tabs.find(\n (el) => el.value === this.selected\n );\n\n if (currentChecked) {\n currentChecked.selected = true;\n } else {\n this.selected = '';\n }\n } else {\n const firstTab = this.tabs[0];\n if (firstTab) {\n firstTab.setAttribute('tabindex', '0');\n }\n }\n\n this.updateSelectionIndicator();\n };\n\n private updateSelectionIndicator = async (): Promise<void> => {\n const selectedElement = this.tabs.find((el) => el.selected);\n if (!selectedElement) {\n this.selectionIndicatorStyle = ScaledIndicator.noSelectionStyle;\n return;\n }\n await Promise.all([\n selectedElement.updateComplete,\n document.fonts ? document.fonts.ready : Promise.resolve(),\n ]);\n const { width, height } = selectedElement.getBoundingClientRect();\n\n this.selectionIndicatorStyle =\n this.direction === 'horizontal'\n ? ScaledIndicator.transformX(selectedElement.offsetLeft, width)\n : ScaledIndicator.transformY(selectedElement.offsetTop, height);\n };\n\n public override connectedCallback(): void {\n super.connectedCallback();\n window.addEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n addEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.addEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n }\n\n public override disconnectedCallback(): void {\n window.removeEventListener('resize', this.updateSelectionIndicator);\n if ('fonts' in document) {\n (\n document as unknown as {\n fonts: {\n removeEventListener: (\n name: string,\n callback: () => void\n ) => void;\n };\n }\n ).fonts.removeEventListener(\n 'loadingdone',\n this.updateSelectionIndicator\n );\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["css", "html", "SizedMixin", "property", "query", "classMap", "ifDefined", "IntersectionController", "ResizeController", "Focusable", "RovingTabindexController", "tabStyles", "tabSizes", "left", "width", "scale", "top", "height", "elements", "focusInIndex", "el", "index", "focusInElement", "event", "target", "element", "currentChecked", "firstTab", "selectedElement", "tabs", "tab", "delta", "behavior", "_a", "scrollLeft", "clientWidth", "scrollWidth", "canScrollLeft", "canScrollRight", "tabUpdateCompletes", "panel", "value", "id", "changes", "selectedChild", "previous", "next", "selected", "__decorateClass"]
|
|
7
7
|
}
|
package/test/tabs.test.js
CHANGED
|
@@ -345,7 +345,6 @@ describe("Tabs", () => {
|
|
|
345
345
|
await elementUpdated(el);
|
|
346
346
|
expect(document.activeElement === firstTab, "Focus first tab").to.be.true;
|
|
347
347
|
firstTab.dispatchEvent(arrowLeftEvent());
|
|
348
|
-
firstTab.dispatchEvent(arrowUpEvent());
|
|
349
348
|
await elementUpdated(el);
|
|
350
349
|
expect(document.activeElement === secondTab, "Focus second tab").to.be.true;
|
|
351
350
|
secondTab.dispatchEvent(enterEvent());
|
|
@@ -357,6 +356,12 @@ describe("Tabs", () => {
|
|
|
357
356
|
firstTab.dispatchEvent(spaceEvent());
|
|
358
357
|
await elementUpdated(el);
|
|
359
358
|
expect(el.selected).to.be.equal("first");
|
|
359
|
+
firstTab.dispatchEvent(arrowUpEvent());
|
|
360
|
+
await elementUpdated(el);
|
|
361
|
+
expect(document.activeElement === secondTab, "Focus second tab").to.be.true;
|
|
362
|
+
secondTab.dispatchEvent(arrowDownEvent());
|
|
363
|
+
await elementUpdated(el);
|
|
364
|
+
expect(document.activeElement === firstTab, "Focus first tab").to.be.true;
|
|
360
365
|
});
|
|
361
366
|
it("accepts keyboard based selection through shadow DOM", async () => {
|
|
362
367
|
class TabTestEl extends LitElement {
|
|
@@ -392,7 +397,6 @@ describe("Tabs", () => {
|
|
|
392
397
|
let activeElement = rootNode.activeElement;
|
|
393
398
|
expect(activeElement === firstTab, "Focus first tab").to.be.true;
|
|
394
399
|
firstTab.dispatchEvent(arrowLeftEvent());
|
|
395
|
-
firstTab.dispatchEvent(arrowUpEvent());
|
|
396
400
|
await elementUpdated(el);
|
|
397
401
|
activeElement = rootNode.activeElement;
|
|
398
402
|
expect(activeElement === secondTab, "Focus second tab").to.be.true;
|
|
@@ -427,7 +431,6 @@ describe("Tabs", () => {
|
|
|
427
431
|
await elementUpdated(el);
|
|
428
432
|
expect(document.activeElement === firstTab, "Focus first tab").to.be.true;
|
|
429
433
|
firstTab.dispatchEvent(arrowLeftEvent());
|
|
430
|
-
firstTab.dispatchEvent(arrowUpEvent());
|
|
431
434
|
await elementUpdated(el);
|
|
432
435
|
expect(document.activeElement === secondTab, "Focus second tab").to.be.true;
|
|
433
436
|
secondTab.dispatchEvent(enterEvent());
|
|
@@ -439,6 +442,11 @@ describe("Tabs", () => {
|
|
|
439
442
|
firstTab.dispatchEvent(spaceEvent());
|
|
440
443
|
await elementUpdated(el);
|
|
441
444
|
expect(el.selected).to.be.equal("first");
|
|
445
|
+
firstTab.dispatchEvent(arrowRightEvent());
|
|
446
|
+
await elementUpdated(el);
|
|
447
|
+
expect(document.activeElement === secondTab, "Focus second tab").to.be.true;
|
|
448
|
+
secondTab.dispatchEvent(arrowLeftEvent());
|
|
449
|
+
expect(document.activeElement === firstTab, "Focus first tab").to.be.true;
|
|
442
450
|
});
|
|
443
451
|
it("selects through slotted DOM", async () => {
|
|
444
452
|
const el = await fixture(
|
package/test/tabs.test.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tabs.test.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport '@spectrum-web-components/tabs/sp-tabs.js';\nimport '@spectrum-web-components/tabs/sp-tab.js';\nimport '@spectrum-web-components/tabs/sp-tab-panel.js';\nimport { Tab, TabPanel, Tabs } from '@spectrum-web-components/tabs';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-checkmark.js';\nimport {\n elementUpdated,\n expect,\n fixture,\n nextFrame,\n waitUntil,\n} from '@open-wc/testing';\nimport { html } from 'lit/static-html.js';\nimport { LitElement, TemplateResult } from '@spectrum-web-components/base';\nimport {\n arrowDownEvent,\n arrowLeftEvent,\n arrowRightEvent,\n arrowUpEvent,\n enterEvent,\n spaceEvent,\n} from '../../../test/testing-helpers.js';\nimport { sendKeys } from '@web/test-runner-commands';\n\nconst createTabs = async (): Promise<Tabs> => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n <sp-tab-panel value=\"first\">First tab content</sp-tab-panel>\n <sp-tab-panel value=\"second\">Second tab content</sp-tab-panel>\n <sp-tab-panel value=\"third\">Third tab content</sp-tab-panel>\n </sp-tabs>\n `\n );\n await elementUpdated(tabs);\n return tabs;\n};\n\ndescribe('Tabs', () => {\n it('loads accessibly', async () => {\n const tabs = await createTabs();\n\n const tabList = tabs.querySelectorAll('sp-tab');\n\n expect(tabList).to.exist;\n expect(tabList.length).to.equal(3);\n\n await expect(tabs).to.be.accessible();\n });\n\n it('loads accessibly w/o panels', async () => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\">Tab 2</sp-tab>\n <sp-tab value=\"third\">Tab 3</sp-tab>\n </sp-tabs>\n `\n );\n\n const tabList = tabs.querySelectorAll('sp-tab');\n\n expect(tabList).to.exist;\n expect(tabList.length).to.equal(3);\n\n await expect(tabs).to.be.accessible();\n });\n\n it('can be disabled', async () => {\n const tabs = await createTabs();\n const tab = tabs.querySelector('[label=\"Tab 3\"]') as Tab;\n tabs.disabled = true;\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n tab.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n });\n\n it('can have disabled sp-tab children', async () => {\n const tabs = await createTabs();\n const tab2 = tabs.querySelector('[label=\"Tab 2\"]') as Tab;\n const tab3 = tabs.querySelector('[label=\"Tab 3\"]') as Tab;\n tab3.disabled = true;\n await elementUpdated(tab3);\n expect(tabs.selected).to.equal('first');\n tab3.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n tab2.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('second');\n });\n\n it('reflects selected tab with selected property', async () => {\n const tabs = await createTabs();\n\n const firstTab = tabs.querySelector('sp-tab[value=first]') as Tab;\n const secondTab = tabs.querySelector('sp-tab[value=second]') as Tab;\n const thirdTab = tabs.querySelector('sp-tab[value=third]') as Tab;\n const firstPanel = tabs.querySelector(\n 'sp-tab-panel[value=first]'\n ) as TabPanel;\n const secondPanel = tabs.querySelector(\n 'sp-tab-panel[value=second]'\n ) as TabPanel;\n const thirdPanel = tabs.querySelector(\n 'sp-tab-panel[value=third]'\n ) as TabPanel;\n\n expect(firstTab.selected, 'first: 1, selected').to.be.true;\n expect(firstPanel.selected, 'first panel: 1, selected').to.be.true;\n expect(secondTab.selected, 'second: 1, not selected').to.be.false;\n expect(secondPanel.selected, 'second panel: 1, not selected').to.be\n .false;\n expect(thirdTab.selected, 'third: 1, not selected').to.be.false;\n expect(thirdPanel.selected, 'third panel: 1, not selected').to.be.false;\n expect(tabs.selected).to.equal(firstTab.value);\n\n secondTab.click();\n await elementUpdated(tabs);\n\n expect(firstTab.selected, 'first: 2, not selected').to.be.false;\n expect(firstPanel.selected, 'first panel: 2, not selected').to.be.false;\n expect(secondTab.selected, 'second: 2, selected').to.be.true;\n expect(secondTab.selected, 'first panel: 2, selected').to.be.true;\n expect(thirdTab.selected, 'third: 2, not selected').to.be.false;\n expect(thirdTab.selected, 'first panel: 2, not selected').to.be.false;\n expect(tabs.selected).to.equal(secondTab.value);\n\n thirdTab.click();\n await elementUpdated(tabs);\n\n expect(firstTab.selected, 'first: 3, not selected').to.be.false;\n expect(firstPanel.selected, 'first panel: 3, not selected').to.be.false;\n expect(secondTab.selected, 'second: 3, not selected').to.be.false;\n expect(secondPanel.selected, 'second panel: 3, not selected').to.be\n .false;\n expect(thirdTab.selected, 'third: 3, selected').to.be.true;\n expect(thirdTab.selected, 'first panel: 3, selected').to.be.true;\n expect(tabs.selected).to.equal(thirdTab.value);\n });\n\n it('autofocuses', async () => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"second\" autofocus>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `\n );\n\n await elementUpdated(tabs);\n\n const autoElement = tabs.querySelector('[label=\"Tab 2\"]') as Tab;\n\n await waitUntil(\n () => document.activeElement === autoElement,\n 'Autofocused'\n );\n });\n\n it('auto', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"second\" auto>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `\n );\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n el.focus();\n await sendKeys({\n press: 'ArrowLeft',\n });\n expect(el.selected).to.equal('first');\n await sendKeys({\n press: 'ArrowLeft',\n });\n expect(el.selected).to.equal('third');\n await sendKeys({\n press: 'ArrowRight',\n });\n expect(el.selected).to.equal('first');\n });\n\n it('forces only one tab to be selected', async () => {\n const tabs = await createTabs();\n\n const selectedTabs = tabs.querySelectorAll('sp-tab[selected]');\n\n expect(tabs.selected).to.equal('first');\n expect(selectedTabs.length).to.equal(1);\n });\n\n it('de-selects all but first selected tab if multiple selected', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected).to.be.true;\n expect(tab2.selected).to.be.false;\n });\n\n it('ensures setting selection updates selected tab', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n const tab3 = tabs.querySelector('sp-tab[value=third]') as Tab;\n\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n if (!(tab3 instanceof Tab)) throw new Error('tab3 not of type Tab');\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected, 'first: 1, selected').to.be.true;\n expect(tab2.selected, 'second: 1, not selected').to.be.false;\n expect(tab3.selected, 'thurd: 1, not selected').to.be.false;\n\n tabs.selected = 'second';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('second');\n expect(tab1.selected, 'first: 2, not selected').to.be.false;\n expect(tab2.selected, 'second: 2, selected').to.be.true;\n expect(tab3.selected, 'third: 2, not selected').to.be.false;\n\n tabs.selected = 'third';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('third');\n expect(tab1.selected, 'first: 3, not selected').to.be.false;\n expect(tab2.selected, 'second: 3, not selected').to.be.false;\n expect(tab3.selected, 'third: 3, selected').to.be.true;\n });\n\n it('ensures setting selected and clicking on tab both work together', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n const tab3 = tabs.querySelector('sp-tab[value=third]') as Tab;\n\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n if (!(tab3 instanceof Tab)) throw new Error('tab3 not of type Tab');\n\n tab2.click();\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('second');\n expect(tab1.selected).to.be.false;\n expect(tab2.selected).to.be.true;\n expect(tab3.selected).to.be.false;\n\n tabs.selected = 'first';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected).to.be.true;\n expect(tab2.selected).to.be.false;\n expect(tab3.selected).to.be.false;\n });\n it('displays `vertical`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\" direction=\"vertical\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n el.selected = 'first';\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('displays with nothing `selected`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n el.selected = 'first';\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('ignores children with no `value`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <div id=\"other\">Other thing</div>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n const otherThing = el.querySelector('#other') as HTMLDivElement;\n otherThing.click();\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('allows selection to be cancellable', async () => {\n const cancelSelection = (event: Event): void => event.preventDefault();\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\" @change=${cancelSelection}>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n secondTab.click();\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('prevents [tabindex=0] while `focusin`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs>\n <sp-tab label=\"Tab 1\" value=\"first\" selected>\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n\n const selected = el.querySelector('[value=\"first\"]') as Tab;\n const toBeSelected = el.querySelector('[value=\"second\"]') as Tab;\n\n await elementUpdated(el);\n await waitUntil(() => el.selected === 'first', 'wait for selection');\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(0);\n\n toBeSelected.dispatchEvent(new Event('focusin', { bubbles: true }));\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(-1);\n\n toBeSelected.dispatchEvent(new Event('focusout', { bubbles: true }));\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(0);\n\n toBeSelected.click();\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n expect(toBeSelected.tabIndex).to.equal(0);\n });\n it('accepts keyboard based selection', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"Unknown\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n const firstTab = el.querySelector('[value=\"first\"]') as Tab;\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n firstTab.dispatchEvent(arrowUpEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowRightEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n\n it('accepts keyboard based selection through shadow DOM', async () => {\n class TabTestEl extends LitElement {\n protected override render(): TemplateResult {\n return html`\n <sp-tabs selected=\"Unknown\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `;\n }\n }\n customElements.define('tab-test-el', TabTestEl);\n const el = await fixture<TabTestEl>(\n html`\n <tab-test-el></tab-test-el>\n `\n );\n\n await elementUpdated(el);\n const rootNode = el.shadowRoot as ShadowRoot;\n const tabsEl = rootNode.querySelector('sp-tabs') as Tabs;\n\n await elementUpdated(tabsEl);\n expect(tabsEl.selected).to.be.equal('');\n\n const firstTab = tabsEl.querySelector('[value=\"first\"]') as Tab;\n const secondTab = tabsEl.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n let activeElement = rootNode.activeElement as Tab;\n expect(activeElement === firstTab, 'Focus first tab').to.be.true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n firstTab.dispatchEvent(arrowUpEvent());\n\n await elementUpdated(el);\n activeElement = rootNode.activeElement as Tab;\n expect(activeElement === secondTab, 'Focus second tab').to.be.true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(tabsEl.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowRightEvent());\n\n await elementUpdated(el);\n activeElement = rootNode.activeElement as Tab;\n expect(activeElement === firstTab, 'Focus first tab').to.be.true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(tabsEl.selected).to.be.equal('first');\n });\n it('accepts keyboard based selection - [direction=\"vertical\"]', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"Unknown\" direction=\"vertical\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n const firstTab = el.querySelector('[value=\"first\"]') as Tab;\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n firstTab.dispatchEvent(arrowUpEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowDownEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('selects through slotted DOM', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\"><span>Tab 2</span></sp-tab>\n </sp-tabs>\n `\n );\n const span = el.querySelector('span') as HTMLSpanElement;\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n\n span.click();\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n });\n it('updates selection indicator in response to tab updates', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\">Tab 2</sp-tab>\n </sp-tabs>\n `\n );\n const selected = el.querySelector('[value=\"first\"]') as Tab;\n await elementUpdated(el);\n\n const extractScaleX = /scaleX\\((.+)\\)/;\n const initialExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const initialWidth = parseFloat(initialExec[1]);\n selected.textContent = 'WWWWWWWWWWWWWWWWWWWWWWWWW';\n await nextFrame();\n await nextFrame();\n\n const longerExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const longerWidth = parseFloat(longerExec[1]);\n expect(initialWidth).to.be.lessThan(longerWidth);\n selected.textContent = 'W';\n await nextFrame();\n\n const shorterExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const shorterWidth = parseFloat(shorterExec[1]);\n expect(initialWidth).to.be.greaterThan(shorterWidth);\n expect(longerWidth).to.be.greaterThan(shorterWidth);\n });\n it('clicks on #list do not throw', async () => {\n const tabs = await createTabs();\n const tabList = (tabs.shadowRoot as ShadowRoot).querySelector(\n '#list'\n ) as HTMLDivElement;\n // exceptions thrown in event listeners do not propagate to caller\n // we must catch them with window.onerror\n let hasError = false;\n const oldOnerror = window.onerror;\n window.onerror = () => {\n hasError = true;\n };\n tabList.dispatchEvent(new MouseEvent('click'));\n expect(hasError, 'it should not error').to.be.false;\n window.onerror = oldOnerror;\n });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport '@spectrum-web-components/tabs/sp-tabs.js';\nimport '@spectrum-web-components/tabs/sp-tab.js';\nimport '@spectrum-web-components/tabs/sp-tab-panel.js';\nimport { Tab, TabPanel, Tabs } from '@spectrum-web-components/tabs';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-checkmark.js';\nimport {\n elementUpdated,\n expect,\n fixture,\n nextFrame,\n waitUntil,\n} from '@open-wc/testing';\nimport { html } from 'lit/static-html.js';\nimport { LitElement, TemplateResult } from '@spectrum-web-components/base';\nimport {\n arrowDownEvent,\n arrowLeftEvent,\n arrowRightEvent,\n arrowUpEvent,\n enterEvent,\n spaceEvent,\n} from '../../../test/testing-helpers.js';\nimport { sendKeys } from '@web/test-runner-commands';\n\nconst createTabs = async (): Promise<Tabs> => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n <sp-tab-panel value=\"first\">First tab content</sp-tab-panel>\n <sp-tab-panel value=\"second\">Second tab content</sp-tab-panel>\n <sp-tab-panel value=\"third\">Third tab content</sp-tab-panel>\n </sp-tabs>\n `\n );\n await elementUpdated(tabs);\n return tabs;\n};\n\ndescribe('Tabs', () => {\n it('loads accessibly', async () => {\n const tabs = await createTabs();\n\n const tabList = tabs.querySelectorAll('sp-tab');\n\n expect(tabList).to.exist;\n expect(tabList.length).to.equal(3);\n\n await expect(tabs).to.be.accessible();\n });\n\n it('loads accessibly w/o panels', async () => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\">Tab 2</sp-tab>\n <sp-tab value=\"third\">Tab 3</sp-tab>\n </sp-tabs>\n `\n );\n\n const tabList = tabs.querySelectorAll('sp-tab');\n\n expect(tabList).to.exist;\n expect(tabList.length).to.equal(3);\n\n await expect(tabs).to.be.accessible();\n });\n\n it('can be disabled', async () => {\n const tabs = await createTabs();\n const tab = tabs.querySelector('[label=\"Tab 3\"]') as Tab;\n tabs.disabled = true;\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n tab.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n });\n\n it('can have disabled sp-tab children', async () => {\n const tabs = await createTabs();\n const tab2 = tabs.querySelector('[label=\"Tab 2\"]') as Tab;\n const tab3 = tabs.querySelector('[label=\"Tab 3\"]') as Tab;\n tab3.disabled = true;\n await elementUpdated(tab3);\n expect(tabs.selected).to.equal('first');\n tab3.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('first');\n tab2.click();\n await elementUpdated(tabs);\n expect(tabs.selected).to.equal('second');\n });\n\n it('reflects selected tab with selected property', async () => {\n const tabs = await createTabs();\n\n const firstTab = tabs.querySelector('sp-tab[value=first]') as Tab;\n const secondTab = tabs.querySelector('sp-tab[value=second]') as Tab;\n const thirdTab = tabs.querySelector('sp-tab[value=third]') as Tab;\n const firstPanel = tabs.querySelector(\n 'sp-tab-panel[value=first]'\n ) as TabPanel;\n const secondPanel = tabs.querySelector(\n 'sp-tab-panel[value=second]'\n ) as TabPanel;\n const thirdPanel = tabs.querySelector(\n 'sp-tab-panel[value=third]'\n ) as TabPanel;\n\n expect(firstTab.selected, 'first: 1, selected').to.be.true;\n expect(firstPanel.selected, 'first panel: 1, selected').to.be.true;\n expect(secondTab.selected, 'second: 1, not selected').to.be.false;\n expect(secondPanel.selected, 'second panel: 1, not selected').to.be\n .false;\n expect(thirdTab.selected, 'third: 1, not selected').to.be.false;\n expect(thirdPanel.selected, 'third panel: 1, not selected').to.be.false;\n expect(tabs.selected).to.equal(firstTab.value);\n\n secondTab.click();\n await elementUpdated(tabs);\n\n expect(firstTab.selected, 'first: 2, not selected').to.be.false;\n expect(firstPanel.selected, 'first panel: 2, not selected').to.be.false;\n expect(secondTab.selected, 'second: 2, selected').to.be.true;\n expect(secondTab.selected, 'first panel: 2, selected').to.be.true;\n expect(thirdTab.selected, 'third: 2, not selected').to.be.false;\n expect(thirdTab.selected, 'first panel: 2, not selected').to.be.false;\n expect(tabs.selected).to.equal(secondTab.value);\n\n thirdTab.click();\n await elementUpdated(tabs);\n\n expect(firstTab.selected, 'first: 3, not selected').to.be.false;\n expect(firstPanel.selected, 'first panel: 3, not selected').to.be.false;\n expect(secondTab.selected, 'second: 3, not selected').to.be.false;\n expect(secondPanel.selected, 'second panel: 3, not selected').to.be\n .false;\n expect(thirdTab.selected, 'third: 3, selected').to.be.true;\n expect(thirdTab.selected, 'first panel: 3, selected').to.be.true;\n expect(tabs.selected).to.equal(thirdTab.value);\n });\n\n it('autofocuses', async () => {\n const tabs = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"second\" autofocus>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `\n );\n\n await elementUpdated(tabs);\n\n const autoElement = tabs.querySelector('[label=\"Tab 2\"]') as Tab;\n\n await waitUntil(\n () => document.activeElement === autoElement,\n 'Autofocused'\n );\n });\n\n it('auto', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"second\" auto>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `\n );\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n el.focus();\n await sendKeys({\n press: 'ArrowLeft',\n });\n expect(el.selected).to.equal('first');\n await sendKeys({\n press: 'ArrowLeft',\n });\n expect(el.selected).to.equal('third');\n await sendKeys({\n press: 'ArrowRight',\n });\n expect(el.selected).to.equal('first');\n });\n\n it('forces only one tab to be selected', async () => {\n const tabs = await createTabs();\n\n const selectedTabs = tabs.querySelectorAll('sp-tab[selected]');\n\n expect(tabs.selected).to.equal('first');\n expect(selectedTabs.length).to.equal(1);\n });\n\n it('de-selects all but first selected tab if multiple selected', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected).to.be.true;\n expect(tab2.selected).to.be.false;\n });\n\n it('ensures setting selection updates selected tab', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n const tab3 = tabs.querySelector('sp-tab[value=third]') as Tab;\n\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n if (!(tab3 instanceof Tab)) throw new Error('tab3 not of type Tab');\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected, 'first: 1, selected').to.be.true;\n expect(tab2.selected, 'second: 1, not selected').to.be.false;\n expect(tab3.selected, 'thurd: 1, not selected').to.be.false;\n\n tabs.selected = 'second';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('second');\n expect(tab1.selected, 'first: 2, not selected').to.be.false;\n expect(tab2.selected, 'second: 2, selected').to.be.true;\n expect(tab3.selected, 'third: 2, not selected').to.be.false;\n\n tabs.selected = 'third';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('third');\n expect(tab1.selected, 'first: 3, not selected').to.be.false;\n expect(tab2.selected, 'second: 3, not selected').to.be.false;\n expect(tab3.selected, 'third: 3, selected').to.be.true;\n });\n\n it('ensures setting selected and clicking on tab both work together', async () => {\n const tabs = await createTabs();\n\n const tab1 = tabs.querySelector('sp-tab[value=first]') as Tab;\n const tab2 = tabs.querySelector('sp-tab[value=second]') as Tab;\n const tab3 = tabs.querySelector('sp-tab[value=third]') as Tab;\n\n if (!(tab1 instanceof Tab)) throw new Error('tab1 not of type Tab');\n if (!(tab2 instanceof Tab)) throw new Error('tab2 not of type Tab');\n if (!(tab3 instanceof Tab)) throw new Error('tab3 not of type Tab');\n\n tab2.click();\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('second');\n expect(tab1.selected).to.be.false;\n expect(tab2.selected).to.be.true;\n expect(tab3.selected).to.be.false;\n\n tabs.selected = 'first';\n await elementUpdated(tabs);\n\n expect(tabs.selected).to.equal('first');\n expect(tab1.selected).to.be.true;\n expect(tab2.selected).to.be.false;\n expect(tab3.selected).to.be.false;\n });\n it('displays `vertical`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\" direction=\"vertical\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n el.selected = 'first';\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('displays with nothing `selected`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n <sp-tab label=\"Tab 3\" value=\"third\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n el.selected = 'first';\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('ignores children with no `value`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\">\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <div id=\"other\">Other thing</div>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n const otherThing = el.querySelector('#other') as HTMLDivElement;\n otherThing.click();\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('allows selection to be cancellable', async () => {\n const cancelSelection = (event: Event): void => event.preventDefault();\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"first\" @change=${cancelSelection}>\n <sp-tab label=\"Tab 1\" value=\"first\"></sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\"></sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n secondTab.click();\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n });\n it('prevents [tabindex=0] while `focusin`', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs>\n <sp-tab label=\"Tab 1\" value=\"first\" selected>\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n\n const selected = el.querySelector('[value=\"first\"]') as Tab;\n const toBeSelected = el.querySelector('[value=\"second\"]') as Tab;\n\n await elementUpdated(el);\n await waitUntil(() => el.selected === 'first', 'wait for selection');\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(0);\n\n toBeSelected.dispatchEvent(new Event('focusin', { bubbles: true }));\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(-1);\n\n toBeSelected.dispatchEvent(new Event('focusout', { bubbles: true }));\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n expect(selected.tabIndex).to.equal(0);\n\n toBeSelected.click();\n\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n expect(toBeSelected.tabIndex).to.equal(0);\n });\n it('accepts keyboard based selection', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"Unknown\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n const firstTab = el.querySelector('[value=\"first\"]') as Tab;\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowRightEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n firstTab.dispatchEvent(arrowUpEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(arrowDownEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n });\n\n it('accepts keyboard based selection through shadow DOM', async () => {\n class TabTestEl extends LitElement {\n protected override render(): TemplateResult {\n return html`\n <sp-tabs selected=\"Unknown\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `;\n }\n }\n customElements.define('tab-test-el', TabTestEl);\n const el = await fixture<TabTestEl>(\n html`\n <tab-test-el></tab-test-el>\n `\n );\n\n await elementUpdated(el);\n const rootNode = el.shadowRoot as ShadowRoot;\n const tabsEl = rootNode.querySelector('sp-tabs') as Tabs;\n\n await elementUpdated(tabsEl);\n expect(tabsEl.selected).to.be.equal('');\n\n const firstTab = tabsEl.querySelector('[value=\"first\"]') as Tab;\n const secondTab = tabsEl.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n let activeElement = rootNode.activeElement as Tab;\n expect(activeElement === firstTab, 'Focus first tab').to.be.true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n\n await elementUpdated(el);\n activeElement = rootNode.activeElement as Tab;\n expect(activeElement === secondTab, 'Focus second tab').to.be.true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(tabsEl.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowRightEvent());\n\n await elementUpdated(el);\n activeElement = rootNode.activeElement as Tab;\n expect(activeElement === firstTab, 'Focus first tab').to.be.true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(tabsEl.selected).to.be.equal('first');\n });\n it('accepts keyboard based selection - [direction=\"vertical\"]', async () => {\n const el = await fixture<Tabs>(html`\n <sp-tabs selected=\"Unknown\" direction=\"vertical\">\n <sp-tab label=\"Tab 1\" value=\"first\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n <sp-tab label=\"Tab 2\" value=\"second\">\n <sp-icon-checkmark slot=\"icon\"></sp-icon-checkmark>\n </sp-tab>\n </sp-tabs>\n `);\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('');\n\n const firstTab = el.querySelector('[value=\"first\"]') as Tab;\n const secondTab = el.querySelector('[value=\"second\"]') as Tab;\n firstTab.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n firstTab.focus();\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(arrowLeftEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(enterEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('second');\n\n secondTab.dispatchEvent(arrowDownEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n\n firstTab.dispatchEvent(spaceEvent());\n\n await elementUpdated(el);\n expect(el.selected).to.be.equal('first');\n\n firstTab.dispatchEvent(arrowRightEvent());\n\n await elementUpdated(el);\n expect(document.activeElement === secondTab, 'Focus second tab').to.be\n .true;\n\n secondTab.dispatchEvent(arrowLeftEvent());\n expect(document.activeElement === firstTab, 'Focus first tab').to.be\n .true;\n });\n it('selects through slotted DOM', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\"><span>Tab 2</span></sp-tab>\n </sp-tabs>\n `\n );\n const span = el.querySelector('span') as HTMLSpanElement;\n await elementUpdated(el);\n\n expect(el.selected).to.equal('first');\n\n span.click();\n await elementUpdated(el);\n\n expect(el.selected).to.equal('second');\n });\n it('updates selection indicator in response to tab updates', async () => {\n const el = await fixture<Tabs>(\n html`\n <sp-tabs selected=\"first\">\n <sp-tab value=\"first\">Tab 1</sp-tab>\n <sp-tab value=\"second\">Tab 2</sp-tab>\n </sp-tabs>\n `\n );\n const selected = el.querySelector('[value=\"first\"]') as Tab;\n await elementUpdated(el);\n\n const extractScaleX = /scaleX\\((.+)\\)/;\n const initialExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const initialWidth = parseFloat(initialExec[1]);\n selected.textContent = 'WWWWWWWWWWWWWWWWWWWWWWWWW';\n await nextFrame();\n await nextFrame();\n\n const longerExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const longerWidth = parseFloat(longerExec[1]);\n expect(initialWidth).to.be.lessThan(longerWidth);\n selected.textContent = 'W';\n await nextFrame();\n\n const shorterExec = extractScaleX.exec(\n el.selectionIndicatorStyle\n ) as unknown as [string, string];\n const shorterWidth = parseFloat(shorterExec[1]);\n expect(initialWidth).to.be.greaterThan(shorterWidth);\n expect(longerWidth).to.be.greaterThan(shorterWidth);\n });\n it('clicks on #list do not throw', async () => {\n const tabs = await createTabs();\n const tabList = (tabs.shadowRoot as ShadowRoot).querySelector(\n '#list'\n ) as HTMLDivElement;\n // exceptions thrown in event listeners do not propagate to caller\n // we must catch them with window.onerror\n let hasError = false;\n const oldOnerror = window.onerror;\n window.onerror = () => {\n hasError = true;\n };\n tabList.dispatchEvent(new MouseEvent('click'));\n expect(hasError, 'it should not error').to.be.false;\n window.onerror = oldOnerror;\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|