@spectrum-web-components/tabs 0.44.0 → 0.46.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 +106 -0
- package/package.json +7 -7
- package/src/Tabs.d.ts +11 -0
- package/src/Tabs.dev.js +42 -2
- package/src/Tabs.dev.js.map +2 -2
- package/src/Tabs.js +3 -3
- package/src/Tabs.js.map +3 -3
- package/src/tab.css.dev.js +1 -1
- package/src/tab.css.dev.js.map +1 -1
- package/src/tab.css.js +1 -1
- package/src/tab.css.js.map +1 -1
- package/src/tabs-overflow.css.dev.js +1 -1
- package/src/tabs-overflow.css.dev.js.map +1 -1
- package/src/tabs-overflow.css.js +1 -1
- package/src/tabs-overflow.css.js.map +1 -1
- package/stories/tabs-overflow.stories.js +18 -0
- package/stories/tabs-overflow.stories.js.map +2 -2
- package/test/tabs-overflow.test.js +136 -88
- package/test/tabs-overflow.test.js.map +2 -2
package/custom-elements.json
CHANGED
|
@@ -337,6 +337,78 @@
|
|
|
337
337
|
},
|
|
338
338
|
"default": "{\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}"
|
|
339
339
|
},
|
|
340
|
+
{
|
|
341
|
+
"kind": "function",
|
|
342
|
+
"name": "calculateScrollTargetForRightSide",
|
|
343
|
+
"return": {
|
|
344
|
+
"type": {
|
|
345
|
+
"text": "number"
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"parameters": [
|
|
349
|
+
{
|
|
350
|
+
"name": "index",
|
|
351
|
+
"type": {
|
|
352
|
+
"text": "number"
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"name": "direction",
|
|
357
|
+
"type": {
|
|
358
|
+
"text": "'rtl' | 'ltr'"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"name": "tabs",
|
|
363
|
+
"type": {
|
|
364
|
+
"text": "Tab[]"
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"name": "container",
|
|
369
|
+
"type": {
|
|
370
|
+
"text": "HTMLDivElement"
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
],
|
|
374
|
+
"description": "Given that the scroll needs to be on the right side of the viewport.\nReturns the coordonate x it needs to scroll so that the tab with given index is visible."
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"kind": "function",
|
|
378
|
+
"name": "calculateScrollTargetForLeftSide",
|
|
379
|
+
"return": {
|
|
380
|
+
"type": {
|
|
381
|
+
"text": "number"
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
"parameters": [
|
|
385
|
+
{
|
|
386
|
+
"name": "index",
|
|
387
|
+
"type": {
|
|
388
|
+
"text": "number"
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"name": "direction",
|
|
393
|
+
"type": {
|
|
394
|
+
"text": "'rtl' | 'ltr'"
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"name": "tabs",
|
|
399
|
+
"type": {
|
|
400
|
+
"text": "Tab[]"
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"name": "container",
|
|
405
|
+
"type": {
|
|
406
|
+
"text": "HTMLDivElement"
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
],
|
|
410
|
+
"description": "Given that the scroll needs to be on the left side of the viewport.\nReturns the coordonate x it needs to scroll so that the tab with given index is visible."
|
|
411
|
+
},
|
|
340
412
|
{
|
|
341
413
|
"kind": "class",
|
|
342
414
|
"description": "",
|
|
@@ -565,6 +637,24 @@
|
|
|
565
637
|
}
|
|
566
638
|
}
|
|
567
639
|
},
|
|
640
|
+
{
|
|
641
|
+
"kind": "method",
|
|
642
|
+
"name": "getNecessaryAutoScroll",
|
|
643
|
+
"privacy": "private",
|
|
644
|
+
"return": {
|
|
645
|
+
"type": {
|
|
646
|
+
"text": "number"
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
"parameters": [
|
|
650
|
+
{
|
|
651
|
+
"name": "index",
|
|
652
|
+
"type": {
|
|
653
|
+
"text": "number"
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
]
|
|
657
|
+
},
|
|
568
658
|
{
|
|
569
659
|
"kind": "method",
|
|
570
660
|
"name": "scrollToSelection",
|
|
@@ -755,6 +845,22 @@
|
|
|
755
845
|
"module": "src/Tabs.js"
|
|
756
846
|
}
|
|
757
847
|
},
|
|
848
|
+
{
|
|
849
|
+
"kind": "js",
|
|
850
|
+
"name": "calculateScrollTargetForRightSide",
|
|
851
|
+
"declaration": {
|
|
852
|
+
"name": "calculateScrollTargetForRightSide",
|
|
853
|
+
"module": "src/Tabs.js"
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
"kind": "js",
|
|
858
|
+
"name": "calculateScrollTargetForLeftSide",
|
|
859
|
+
"declaration": {
|
|
860
|
+
"name": "calculateScrollTargetForLeftSide",
|
|
861
|
+
"module": "src/Tabs.js"
|
|
862
|
+
}
|
|
863
|
+
},
|
|
758
864
|
{
|
|
759
865
|
"kind": "js",
|
|
760
866
|
"name": "Tabs",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/tabs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -86,11 +86,11 @@
|
|
|
86
86
|
],
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"@lit-labs/observers": "^2.0.2",
|
|
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.46.0",
|
|
90
|
+
"@spectrum-web-components/icon": "^0.46.0",
|
|
91
|
+
"@spectrum-web-components/icons-ui": "^0.46.0",
|
|
92
|
+
"@spectrum-web-components/reactive-controllers": "^0.46.0",
|
|
93
|
+
"@spectrum-web-components/shared": "^0.46.0"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@spectrum-css/tabs": "^5.1.0"
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"./sp-*.js",
|
|
102
102
|
"./**/*.dev.js"
|
|
103
103
|
],
|
|
104
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "ab84b447210de593649b086a1605abf1be1d64f2"
|
|
105
105
|
}
|
package/src/Tabs.d.ts
CHANGED
|
@@ -10,6 +10,16 @@ export declare const ScaledIndicator: {
|
|
|
10
10
|
transformY(top: number, height: number): string;
|
|
11
11
|
baseStyles(): CSSResult;
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Given that the scroll needs to be on the right side of the viewport.
|
|
15
|
+
* Returns the coordonate x it needs to scroll so that the tab with given index is visible.
|
|
16
|
+
*/
|
|
17
|
+
export declare function calculateScrollTargetForRightSide(index: number, direction: 'rtl' | 'ltr', tabs: Tab[], container: HTMLDivElement): number;
|
|
18
|
+
/**
|
|
19
|
+
* Given that the scroll needs to be on the left side of the viewport.
|
|
20
|
+
* Returns the coordonate x it needs to scroll so that the tab with given index is visible.
|
|
21
|
+
*/
|
|
22
|
+
export declare function calculateScrollTargetForLeftSide(index: number, direction: 'rtl' | 'ltr', tabs: Tab[], container: HTMLDivElement): number;
|
|
13
23
|
declare const Tabs_base: typeof Focusable & {
|
|
14
24
|
new (...args: any[]): import("@spectrum-web-components/base").SizedElementInterface;
|
|
15
25
|
prototype: import("@spectrum-web-components/base").SizedElementInterface;
|
|
@@ -65,6 +75,7 @@ export declare class Tabs extends Tabs_base {
|
|
|
65
75
|
scrollTabs(delta: number, behavior?: ScrollBehavior): void;
|
|
66
76
|
get scrollState(): Record<string, boolean>;
|
|
67
77
|
getUpdateComplete(): Promise<boolean>;
|
|
78
|
+
private getNecessaryAutoScroll;
|
|
68
79
|
scrollToSelection(): Promise<void>;
|
|
69
80
|
protected updated(changedProperties: PropertyValueMap<this>): void;
|
|
70
81
|
protected managePanels({ target, }: Event & {
|
package/src/Tabs.dev.js
CHANGED
|
@@ -51,6 +51,18 @@ export const ScaledIndicator = {
|
|
|
51
51
|
`;
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
|
+
export function calculateScrollTargetForRightSide(index, direction, tabs, container) {
|
|
55
|
+
const nextIndex = index + (direction === "rtl" ? -1 : 1);
|
|
56
|
+
const nextTab = tabs[nextIndex];
|
|
57
|
+
const viewportEnd = container.scrollLeft + container.offsetWidth;
|
|
58
|
+
return nextTab ? nextTab.offsetLeft - container.offsetWidth : viewportEnd;
|
|
59
|
+
}
|
|
60
|
+
export function calculateScrollTargetForLeftSide(index, direction, tabs, container) {
|
|
61
|
+
const prevIndex = index + (direction === "rtl" ? 1 : -1);
|
|
62
|
+
const prevTab = tabs[prevIndex];
|
|
63
|
+
const leftmostElement = direction === "rtl" ? -container.offsetWidth : 0;
|
|
64
|
+
return prevTab ? prevTab.offsetLeft + prevTab.offsetWidth : leftmostElement;
|
|
65
|
+
}
|
|
54
66
|
export class Tabs extends SizedMixin(Focusable, { noDefaultSize: true }) {
|
|
55
67
|
constructor() {
|
|
56
68
|
super();
|
|
@@ -218,15 +230,43 @@ export class Tabs extends SizedMixin(Focusable, { noDefaultSize: true }) {
|
|
|
218
230
|
await Promise.all(tabUpdateCompletes);
|
|
219
231
|
return complete;
|
|
220
232
|
}
|
|
233
|
+
getNecessaryAutoScroll(index) {
|
|
234
|
+
const selectedTab = this.tabs[index];
|
|
235
|
+
const selectionEnd = selectedTab.offsetLeft + selectedTab.offsetWidth;
|
|
236
|
+
const viewportEnd = this.tabList.scrollLeft + this.tabList.offsetWidth;
|
|
237
|
+
const selectionStart = selectedTab.offsetLeft;
|
|
238
|
+
const viewportStart = this.tabList.scrollLeft;
|
|
239
|
+
if (selectionEnd > viewportEnd) {
|
|
240
|
+
return calculateScrollTargetForRightSide(
|
|
241
|
+
index,
|
|
242
|
+
this.dir,
|
|
243
|
+
this.tabs,
|
|
244
|
+
this.tabList
|
|
245
|
+
);
|
|
246
|
+
} else if (selectionStart < viewportStart) {
|
|
247
|
+
return calculateScrollTargetForLeftSide(
|
|
248
|
+
index,
|
|
249
|
+
this.dir,
|
|
250
|
+
this.tabs,
|
|
251
|
+
this.tabList
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
return -1;
|
|
255
|
+
}
|
|
221
256
|
async scrollToSelection() {
|
|
222
257
|
if (!this.enableTabsScroll || !this.selected) {
|
|
223
258
|
return;
|
|
224
259
|
}
|
|
225
260
|
await this.updateComplete;
|
|
226
|
-
const
|
|
261
|
+
const selectedIndex = this.tabs.findIndex(
|
|
227
262
|
(tab) => tab.value === this.selected
|
|
228
263
|
);
|
|
229
|
-
|
|
264
|
+
if (selectedIndex !== -1 && this.tabList) {
|
|
265
|
+
const scrollTarget = this.getNecessaryAutoScroll(selectedIndex);
|
|
266
|
+
if (scrollTarget !== -1) {
|
|
267
|
+
this.tabList.scrollTo({ left: scrollTarget });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
230
270
|
}
|
|
231
271
|
updated(changedProperties) {
|
|
232
272
|
super.updated(changedProperties);
|
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 PropertyValueMap,\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, { noDefaultSize: true }) {\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 override async getUpdateComplete(): Promise<boolean> {\n const complete = await super.getUpdateComplete();\n\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\n await Promise.all(tabUpdateCompletes);\n return complete;\n }\n\n public async scrollToSelection(): Promise<void> {\n if (!this.enableTabsScroll || !this.selected) {\n return;\n }\n\n await this.updateComplete;\n const selectedTab = this.tabs.find(\n (tab) => tab.value === this.selected\n );\n selectedTab?.scrollIntoView();\n }\n\n protected override updated(\n changedProperties: PropertyValueMap<this>\n ): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('selected')) {\n this.scrollToSelection();\n }\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,EAGA;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,IAAI,cAAc,KAAK;AAAA,EAC3D;AAAA,EAEA,WAAW,KAAa,QAAwB;AAC5C,UAAM,QAAQ,SAAS,KAAK;AAC5B,WAAO,yBAAyB,GAAG,cAAc,KAAK;AAAA,EAC1D;AAAA,EAEA,aAAwB;AACpB,WAAO;AAAA;AAAA;AAAA,0BAGW,KAAK,QAAQ;AAAA;AAAA;AAAA,yBAGd,KAAK,QAAQ;AAAA;AAAA;AAAA,EAGlC;AACJ;AAWO,aAAM,aAAa,WAAW,WAAW,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,EA6ErE,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,MAAM;AAAA,MACjB,oBAAoB,CAAC,OAAO;AACxB,YAAI,CAAC,KAAK,KAAM;AAEhB,aAAK,gBAAgB;AACrB,aAAK,aAAa,EAAE;AAAA,MACxB;AAAA,MACA,UAAU,MAAM,KAAK;AAAA,MACrB,oBAAoB,CAAC,OAAO,CAAC,GAAG;AAAA,MAChC,eAAe,MAAM,KAAK;AAAA,IAC9B,CAAC;
|
|
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 PropertyValueMap,\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 * Given that the scroll needs to be on the right side of the viewport.\n * Returns the coordonate x it needs to scroll so that the tab with given index is visible.\n */\nexport function calculateScrollTargetForRightSide(\n index: number,\n direction: 'rtl' | 'ltr',\n tabs: Tab[],\n container: HTMLDivElement\n): number {\n const nextIndex = index + (direction === 'rtl' ? -1 : 1);\n const nextTab = tabs[nextIndex];\n const viewportEnd = container.scrollLeft + container.offsetWidth;\n return nextTab ? nextTab.offsetLeft - container.offsetWidth : viewportEnd;\n}\n\n/**\n * Given that the scroll needs to be on the left side of the viewport.\n * Returns the coordonate x it needs to scroll so that the tab with given index is visible.\n */\nexport function calculateScrollTargetForLeftSide(\n index: number,\n direction: 'rtl' | 'ltr',\n tabs: Tab[],\n container: HTMLDivElement\n): number {\n const prevIndex = index + (direction === 'rtl' ? 1 : -1);\n const prevTab = tabs[prevIndex];\n const leftmostElement = direction === 'rtl' ? -container.offsetWidth : 0;\n return prevTab ? prevTab.offsetLeft + prevTab.offsetWidth : leftmostElement;\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, { noDefaultSize: true }) {\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 override async getUpdateComplete(): Promise<boolean> {\n const complete = await super.getUpdateComplete();\n\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\n await Promise.all(tabUpdateCompletes);\n return complete;\n }\n\n private getNecessaryAutoScroll(index: number): number {\n const selectedTab = this.tabs[index];\n const selectionEnd = selectedTab.offsetLeft + selectedTab.offsetWidth;\n const viewportEnd = this.tabList.scrollLeft + this.tabList.offsetWidth;\n const selectionStart = selectedTab.offsetLeft;\n const viewportStart = this.tabList.scrollLeft;\n\n if (selectionEnd > viewportEnd) {\n // Selection is on the right side, not visible.\n return calculateScrollTargetForRightSide(\n index,\n this.dir,\n this.tabs,\n this.tabList\n );\n } else if (selectionStart < viewportStart) {\n // Selection is on the left side, not visible.\n return calculateScrollTargetForLeftSide(\n index,\n this.dir,\n this.tabs,\n this.tabList\n );\n }\n\n return -1;\n }\n\n public async scrollToSelection(): Promise<void> {\n if (!this.enableTabsScroll || !this.selected) {\n return;\n }\n\n await this.updateComplete;\n\n const selectedIndex = this.tabs.findIndex(\n (tab) => tab.value === this.selected\n );\n\n if (selectedIndex !== -1 && this.tabList) {\n // We have a selection, calculate the scroll needed to bring it into view\n const scrollTarget = this.getNecessaryAutoScroll(selectedIndex);\n\n // scrollTarget = -1 means it is already into view.\n if (scrollTarget !== -1) {\n this.tabList.scrollTo({ left: scrollTarget });\n }\n }\n }\n\n protected override updated(\n changedProperties: PropertyValueMap<this>\n ): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('selected')) {\n this.scrollToSelection();\n }\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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var h=Object.defineProperty;var
|
|
1
|
+
"use strict";var h=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var l=(a,o,e,t)=>{for(var i=t>1?void 0:t?b(o,e):o,s=a.length-1,r;s>=0;s--)(r=a[s])&&(i=(t?r(o,e,i):r(i))||i);return t&&i&&h(o,e,i),i};import{css as f,html as p,SizedMixin as m}from"@spectrum-web-components/base";import{property as n,query as d}from"@spectrum-web-components/base/src/decorators.js";import{classMap as v,ifDefined as u}from"@spectrum-web-components/base/src/directives.js";import{IntersectionController as S}from"@lit-labs/observers/intersection-controller.js";import{ResizeController as g}from"@lit-labs/observers/resize-controller.js";import{Focusable as y}from"@spectrum-web-components/shared";import{RovingTabindexController as E}from"@spectrum-web-components/reactive-controllers/src/RovingTabindex.js";import T from"./tabs.css.js";import L from"./tabs-sizes.css.js";export const ScaledIndicator={baseSize:100,noSelectionStyle:"transform: translateX(0px) scaleX(0) scaleY(0)",transformX(a,o){const e=o/this.baseSize;return`transform: translateX(${a}px) scaleX(${e});`},transformY(a,o){const e=o/this.baseSize;return`transform: translateY(${a}px) scaleY(${e});`},baseStyles(){return f`
|
|
2
2
|
:host([direction='vertical-right']) #selection-indicator,
|
|
3
3
|
:host([direction='vertical']) #selection-indicator {
|
|
4
4
|
height: ${this.baseSize}px;
|
|
@@ -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,{noDefaultSize:!0}){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,r)=>{const c=this.selected?!s.disabled&&s.value===this.selected:!s.disabled;return t=r,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,
|
|
9
|
+
`}};export function calculateScrollTargetForRightSide(a,o,e,t){const i=a+(o==="rtl"?-1:1),s=e[i],r=t.scrollLeft+t.offsetWidth;return s?s.offsetLeft-t.offsetWidth:r}export function calculateScrollTargetForLeftSide(a,o,e,t){const i=a+(o==="rtl"?1:-1),s=e[i],r=o==="rtl"?-t.offsetWidth:0;return s?s.offsetLeft+s.offsetWidth:r}export class Tabs extends m(y,{noDefaultSize:!0}){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,r)=>{const c=this.selected?!s.disabled&&s.value===this.selected:!s.disabled;return t=r,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[L,T,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,r=Math.ceil(Math.abs(e))<i-t;return{canScrollLeft:this.dir==="ltr"?s:r,canScrollRight:this.dir==="ltr"?r:s}}return{}}async getUpdateComplete(){const e=await super.getUpdateComplete(),i=[...this.children].map(s=>typeof s.updateComplete!="undefined"?s.updateComplete:Promise.resolve(!0));return await Promise.all(i),e}getNecessaryAutoScroll(e){const t=this.tabs[e],i=t.offsetLeft+t.offsetWidth,s=this.tabList.scrollLeft+this.tabList.offsetWidth,r=t.offsetLeft,c=this.tabList.scrollLeft;return i>s?calculateScrollTargetForRightSide(e,this.dir,this.tabs,this.tabList):r<c?calculateScrollTargetForLeftSide(e,this.dir,this.tabs,this.tabList):-1}async scrollToSelection(){if(!this.enableTabsScroll||!this.selected)return;await this.updateComplete;const e=this.tabs.findIndex(t=>t.value===this.selected);if(e!==-1&&this.tabList){const t=this.getNecessaryAutoScroll(e);t!==-1&&this.tabList.scrollTo({left:t})}}updated(e){super.updated(e),e.has("selected")&&this.scrollToSelection()}managePanels({target:e}){e.assignedElements().map(i=>{const{value:s,id:r}=i,c=this.querySelector(`[role="tab"][value="${s}"]`);c&&(c.setAttribute("aria-controls",r),i.setAttribute("aria-labelledby",c.id)),i.selected=s===this.selected})}render(){return p`
|
|
10
10
|
<div
|
|
11
11
|
class=${v({scroll:this.enableTabsScroll})}
|
|
12
12
|
aria-label=${u(this.label?this.label:void 0)}
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
></div>
|
|
27
27
|
</div>
|
|
28
28
|
<slot name="tab-panel" @slotchange=${this.managePanels}></slot>
|
|
29
|
-
`}willUpdate(e){if(!this.hasUpdated){const t=this.querySelector(":scope > [selected]");t&&this.selectTarget(t)}if(super.willUpdate(e),e.has("selected")){if(this.tabs.length&&this.updateCheckedState(),e.get("selected")){const i=this.querySelector(`[role="tabpanel"][value="${e.get("selected")}"]`);i&&(i.selected=!1)}const t=this.querySelector(`[role="tabpanel"][value="${this.selected}"]`);t&&(t.selected=!0)}e.has("direction")&&(this.direction==="horizontal"?this.removeAttribute("aria-orientation"):this.setAttribute("aria-orientation","vertical")),e.has("dir")&&this.updateSelectionIndicator(),e.has("disabled")&&(this.disabled?this.setAttribute("aria-disabled","true"):this.removeAttribute("aria-disabled")),!this.shouldAnimate&&typeof e.get("shouldAnimate")!="undefined"&&(this.shouldAnimate=!0)}selectTarget(e){const t=e.getAttribute("value");if(t){const i=this.selected;this.selected=t,this.dispatchEvent(new Event("change",{cancelable:!0}))||(this.selected=i)}}onSlotChange(){this.tabs=this.slotEl.assignedElements().filter(e=>e.getAttribute("role")==="tab"),this.updateCheckedState()}connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this.updateSelectionIndicator),"fonts"in document&&document.fonts.addEventListener("loadingdone",this.updateSelectionIndicator)}disconnectedCallback(){window.removeEventListener("resize",this.updateSelectionIndicator),"fonts"in document&&document.fonts.removeEventListener("loadingdone",this.updateSelectionIndicator),super.disconnectedCallback()}}l([
|
|
29
|
+
`}willUpdate(e){if(!this.hasUpdated){const t=this.querySelector(":scope > [selected]");t&&this.selectTarget(t)}if(super.willUpdate(e),e.has("selected")){if(this.tabs.length&&this.updateCheckedState(),e.get("selected")){const i=this.querySelector(`[role="tabpanel"][value="${e.get("selected")}"]`);i&&(i.selected=!1)}const t=this.querySelector(`[role="tabpanel"][value="${this.selected}"]`);t&&(t.selected=!0)}e.has("direction")&&(this.direction==="horizontal"?this.removeAttribute("aria-orientation"):this.setAttribute("aria-orientation","vertical")),e.has("dir")&&this.updateSelectionIndicator(),e.has("disabled")&&(this.disabled?this.setAttribute("aria-disabled","true"):this.removeAttribute("aria-disabled")),!this.shouldAnimate&&typeof e.get("shouldAnimate")!="undefined"&&(this.shouldAnimate=!0)}selectTarget(e){const t=e.getAttribute("value");if(t){const i=this.selected;this.selected=t,this.dispatchEvent(new Event("change",{cancelable:!0}))||(this.selected=i)}}onSlotChange(){this.tabs=this.slotEl.assignedElements().filter(e=>e.getAttribute("role")==="tab"),this.updateCheckedState()}connectedCallback(){super.connectedCallback(),window.addEventListener("resize",this.updateSelectionIndicator),"fonts"in document&&document.fonts.addEventListener("loadingdone",this.updateSelectionIndicator)}disconnectedCallback(){window.removeEventListener("resize",this.updateSelectionIndicator),"fonts"in document&&document.fonts.removeEventListener("loadingdone",this.updateSelectionIndicator),super.disconnectedCallback()}}l([n({type:Boolean})],Tabs.prototype,"auto",2),l([n({type:Boolean,reflect:!0})],Tabs.prototype,"compact",2),l([n({reflect:!0})],Tabs.prototype,"dir",2),l([n({reflect:!0})],Tabs.prototype,"direction",2),l([n({type:Boolean,reflect:!0})],Tabs.prototype,"emphasized",2),l([n()],Tabs.prototype,"label",2),l([n({type:Boolean})],Tabs.prototype,"enableTabsScroll",2),l([n({type:Boolean,reflect:!0})],Tabs.prototype,"quiet",2),l([n({attribute:!1})],Tabs.prototype,"selectionIndicatorStyle",2),l([n({attribute:!1})],Tabs.prototype,"shouldAnimate",2),l([d("slot")],Tabs.prototype,"slotEl",2),l([d("#list")],Tabs.prototype,"tabList",2),l([n({reflect:!0})],Tabs.prototype,"selected",2);
|
|
30
30
|
//# sourceMappingURL=Tabs.js.map
|
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 PropertyValueMap,\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, { noDefaultSize: true }) {\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 override async getUpdateComplete(): Promise<boolean> {\n const complete = await super.getUpdateComplete();\n\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\n await Promise.all(tabUpdateCompletes);\n return complete;\n }\n\n public async scrollToSelection(): Promise<void> {\n if (!this.enableTabsScroll || !this.selected) {\n return;\n }\n\n await this.updateComplete;\n const selectedTab = this.tabs.find(\n (tab) => tab.value === this.selected\n );\n selectedTab?.scrollIntoView();\n }\n\n protected override updated(\n changedProperties: PropertyValueMap<this>\n ): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('selected')) {\n this.scrollToSelection();\n }\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,EAGA,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,CAAI,cAAcE,CAAK,IAC3D,EAEA,WAAWC,EAAaC,EAAwB,CAC5C,MAAMF,EAAQE,EAAS,KAAK,SAC5B,MAAO,yBAAyBD,CAAG,cAAcD,CAAK,IAC1D,EAEA,YAAwB,CACpB,OAAOf;AAAA;AAAA;AAAA,0BAGW,KAAK,QAAQ;AAAA;AAAA;AAAA,yBAGd,KAAK,QAAQ;AAAA;AAAA,SAGlC,CACJ,
|
|
6
|
-
"names": ["css", "html", "SizedMixin", "property", "query", "classMap", "ifDefined", "IntersectionController", "ResizeController", "Focusable", "RovingTabindexController", "tabStyles", "tabSizes", "left", "width", "scale", "top", "height", "
|
|
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 PropertyValueMap,\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 * Given that the scroll needs to be on the right side of the viewport.\n * Returns the coordonate x it needs to scroll so that the tab with given index is visible.\n */\nexport function calculateScrollTargetForRightSide(\n index: number,\n direction: 'rtl' | 'ltr',\n tabs: Tab[],\n container: HTMLDivElement\n): number {\n const nextIndex = index + (direction === 'rtl' ? -1 : 1);\n const nextTab = tabs[nextIndex];\n const viewportEnd = container.scrollLeft + container.offsetWidth;\n return nextTab ? nextTab.offsetLeft - container.offsetWidth : viewportEnd;\n}\n\n/**\n * Given that the scroll needs to be on the left side of the viewport.\n * Returns the coordonate x it needs to scroll so that the tab with given index is visible.\n */\nexport function calculateScrollTargetForLeftSide(\n index: number,\n direction: 'rtl' | 'ltr',\n tabs: Tab[],\n container: HTMLDivElement\n): number {\n const prevIndex = index + (direction === 'rtl' ? 1 : -1);\n const prevTab = tabs[prevIndex];\n const leftmostElement = direction === 'rtl' ? -container.offsetWidth : 0;\n return prevTab ? prevTab.offsetLeft + prevTab.offsetWidth : leftmostElement;\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, { noDefaultSize: true }) {\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 override async getUpdateComplete(): Promise<boolean> {\n const complete = await super.getUpdateComplete();\n\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\n await Promise.all(tabUpdateCompletes);\n return complete;\n }\n\n private getNecessaryAutoScroll(index: number): number {\n const selectedTab = this.tabs[index];\n const selectionEnd = selectedTab.offsetLeft + selectedTab.offsetWidth;\n const viewportEnd = this.tabList.scrollLeft + this.tabList.offsetWidth;\n const selectionStart = selectedTab.offsetLeft;\n const viewportStart = this.tabList.scrollLeft;\n\n if (selectionEnd > viewportEnd) {\n // Selection is on the right side, not visible.\n return calculateScrollTargetForRightSide(\n index,\n this.dir,\n this.tabs,\n this.tabList\n );\n } else if (selectionStart < viewportStart) {\n // Selection is on the left side, not visible.\n return calculateScrollTargetForLeftSide(\n index,\n this.dir,\n this.tabs,\n this.tabList\n );\n }\n\n return -1;\n }\n\n public async scrollToSelection(): Promise<void> {\n if (!this.enableTabsScroll || !this.selected) {\n return;\n }\n\n await this.updateComplete;\n\n const selectedIndex = this.tabs.findIndex(\n (tab) => tab.value === this.selected\n );\n\n if (selectedIndex !== -1 && this.tabList) {\n // We have a selection, calculate the scroll needed to bring it into view\n const scrollTarget = this.getNecessaryAutoScroll(selectedIndex);\n\n // scrollTarget = -1 means it is already into view.\n if (scrollTarget !== -1) {\n this.tabList.scrollTo({ left: scrollTarget });\n }\n }\n }\n\n protected override updated(\n changedProperties: PropertyValueMap<this>\n ): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('selected')) {\n this.scrollToSelection();\n }\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
|
+
"names": ["css", "html", "SizedMixin", "property", "query", "classMap", "ifDefined", "IntersectionController", "ResizeController", "Focusable", "RovingTabindexController", "tabStyles", "tabSizes", "left", "width", "scale", "top", "height", "index", "direction", "tabs", "container", "nextIndex", "nextTab", "viewportEnd", "prevIndex", "prevTab", "leftmostElement", "elements", "focusInIndex", "el", "focusInElement", "event", "target", "element", "currentChecked", "firstTab", "selectedElement", "tab", "delta", "behavior", "_a", "scrollLeft", "clientWidth", "scrollWidth", "canScrollLeft", "canScrollRight", "complete", "tabUpdateCompletes", "selectedTab", "selectionEnd", "selectionStart", "viewportStart", "selectedIndex", "scrollTarget", "changedProperties", "panel", "value", "id", "changes", "selectedChild", "previous", "next", "selected", "__decorateClass"]
|
|
7
7
|
}
|
package/src/tab.css.dev.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { css } from "@spectrum-web-components/base";
|
|
3
3
|
const styles = css`
|
|
4
|
-
:host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:"";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:
|
|
4
|
+
:host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:"";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:ButtonFace}:host ::slotted([slot=icon]){z-index:1;color:inherit;position:relative}#item-label{z-index:1;position:relative}:host([selected]){color:HighlightText}:host([selected]) ::slotted([slot=icon]){color:HighlightText}:host([selected]) #item-label{color:HighlightText}}:host([vertical]){height:auto;flex-direction:column;justify-content:center;align-items:center;display:flex}:host([dir][vertical]) slot[name=icon]+#item-label{margin-inline-start:0;margin-block:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2)calc(var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text))/2)}:host([vertical]) ::slotted([slot=icon]){margin-block-start:calc(var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))/2)}
|
|
5
5
|
`;
|
|
6
6
|
export default styles;
|
|
7
7
|
//# sourceMappingURL=tab.css.dev.js.map
|
package/src/tab.css.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tab.css.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:\"\";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:\"\";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:ButtonFace}:host ::slotted([slot=icon]){z-index:1;color:inherit;position:relative}#item-label{z-index:1;position:relative}:host([selected]){color:HighlightText}:host([selected]) ::slotted([slot=icon]){color:HighlightText}:host([selected]) #item-label{color:HighlightText}}:host([vertical]){height:auto;flex-direction:column;justify-content:center;align-items:center;display:flex}:host([dir][vertical]) slot[name=icon]+#item-label{margin-inline-start:0;margin-block:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2)calc(var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text))/2)}:host([vertical]) ::slotted([slot=icon]){margin-block-start:calc(var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))/2)}\n`;\nexport default styles;"],
|
|
5
5
|
"mappings": ";AAWA,SAAS,WAAW;AACpB,MAAM,SAAS;AAAA;AAAA;AAGf,eAAe;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/tab.css.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use strict";import{css as t}from"@spectrum-web-components/base";const o=t`
|
|
2
|
-
:host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:"";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:
|
|
2
|
+
:host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:"";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:ButtonFace}:host ::slotted([slot=icon]){z-index:1;color:inherit;position:relative}#item-label{z-index:1;position:relative}:host([selected]){color:HighlightText}:host([selected]) ::slotted([slot=icon]){color:HighlightText}:host([selected]) #item-label{color:HighlightText}}:host([vertical]){height:auto;flex-direction:column;justify-content:center;align-items:center;display:flex}:host([dir][vertical]) slot[name=icon]+#item-label{margin-inline-start:0;margin-block:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2)calc(var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text))/2)}:host([vertical]) ::slotted([slot=icon]){margin-block-start:calc(var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))/2)}
|
|
3
3
|
`;export default o;
|
|
4
4
|
//# sourceMappingURL=tab.css.js.map
|
package/src/tab.css.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tab.css.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:\"\";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{box-sizing:border-box;block-size:calc(var(--mod-tabs-item-height,var(--spectrum-tabs-item-height)) - var(--mod-tabs-divider-size,var(--spectrum-tabs-divider-size)));z-index:1;white-space:nowrap;color:var(--highcontrast-tabs-color,var(--mod-tabs-color,var(--spectrum-tabs-color)));transition:color var(--mod-tabs-animation-duration,var(--spectrum-tabs-animation-duration))ease-out;cursor:pointer;outline:none;-webkit-text-decoration:none;text-decoration:none;position:relative}::slotted([slot=icon]){block-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));inline-size:var(--mod-tabs-icon-size,var(--spectrum-tabs-icon-size));margin-block-start:var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))}[name=icon]+#item-label{margin-inline-start:var(--mod-tabs-icon-to-text,var(--spectrum-tabs-icon-to-text))}:host:before{content:\"\";box-sizing:border-box;block-size:calc(100% - var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text)));inline-size:calc(100% + var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*2);border:var(--mod-tabs-focus-indicator-width,var(--spectrum-tabs-focus-indicator-width))solid transparent;border-radius:var(--mod-tabs-focus-indicator-border-radius,var(--spectrum-tabs-focus-indicator-border-radius));pointer-events:none;position:absolute;inset-block-start:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2);inset-inline-start:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1);inset-inline-end:calc(var(--mod-tabs-focus-indicator-gap,var(--spectrum-tabs-focus-indicator-gap))*-1)}@media (hover:hover){:host(:hover){color:var(--highcontrast-tabs-color-hover,var(--mod-tabs-color-hover,var(--spectrum-tabs-color-hover)))}}:host([selected]){color:var(--highcontrast-tabs-color-selected,var(--mod-tabs-color-selected,var(--spectrum-tabs-color-selected)))}:host([disabled]){cursor:default;color:var(--highcontrast-tabs-color-disabled,var(--mod-tabs-color-disabled,var(--spectrum-tabs-color-disabled)))}:host([disabled]) #item-label{cursor:default}:host(:focus-visible){color:var(--highcontrast-tabs-color-key-focus,var(--mod-tabs-color-key-focus,var(--spectrum-tabs-color-key-focus)))}:host(:focus-visible):before{border-color:var(--highcontrast-tabs-focus-indicator-color,var(--mod-tabs-focus-indicator-color,var(--spectrum-tabs-focus-indicator-color)))}#item-label{cursor:pointer;vertical-align:top;font-family:var(--mod-tabs-font-family,var(--spectrum-tabs-font-family));font-style:var(--mod-tabs-font-style,var(--spectrum-tabs-font-style));font-size:var(--mod-tabs-font-size,var(--spectrum-tabs-font-size));font-weight:var(--mod-tabs-font-weight,var(--spectrum-tabs-font-weight));line-height:var(--mod-tabs-line-height,var(--spectrum-tabs-line-height));margin-block-start:var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text));margin-block-end:var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text));-webkit-text-decoration:none;text-decoration:none;display:inline-block}#item-label:empty{display:none}:host{scroll-margin-inline:var(--mod-tabs-item-horizontal-spacing,var(--spectrum-tabs-item-horizontal-spacing))}:host([disabled]){pointer-events:none}#item-label[hidden]{display:none}@media (forced-colors:active){:host:before{background-color:ButtonFace}:host ::slotted([slot=icon]){z-index:1;color:inherit;position:relative}#item-label{z-index:1;position:relative}:host([selected]){color:HighlightText}:host([selected]) ::slotted([slot=icon]){color:HighlightText}:host([selected]) #item-label{color:HighlightText}}:host([vertical]){height:auto;flex-direction:column;justify-content:center;align-items:center;display:flex}:host([dir][vertical]) slot[name=icon]+#item-label{margin-inline-start:0;margin-block:calc(var(--mod-tabs-top-to-text,var(--spectrum-tabs-top-to-text))/2)calc(var(--mod-tabs-bottom-to-text,var(--spectrum-tabs-bottom-to-text))/2)}:host([vertical]) ::slotted([slot=icon]){margin-block-start:calc(var(--mod-tabs-top-to-icon,var(--spectrum-tabs-top-to-icon))/2)}\n`;\nexport default styles;"],
|
|
5
5
|
"mappings": "aAWA,OAAS,OAAAA,MAAW,gCACpB,MAAMC,EAASD;AAAA;AAAA,EAGf,eAAeC",
|
|
6
6
|
"names": ["css", "styles"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
import { css } from "@spectrum-web-components/base";
|
|
3
3
|
const styles = css`
|
|
4
|
-
:host{
|
|
4
|
+
:host{width:100%;--sp-tabs-overflow-next-button-right:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-previous-button-left:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-medium) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-medium);--sp-tabs-overflow-icon-color:var(--spectrum-gray-800);--sp-tabs-overflow-shadow-color:var(--spectrum-gray-100);--sp-tabs-overflow-shadow-width:50px;--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-100);inset:0}:host([size=s]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-small) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-small);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-75)}:host([size=l]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-200)}:host([size=xl]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-extra-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-extra-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-300)}:host([compact]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-compact-height-medium) - var(--spectrum-border-width-200));--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-50)}sp-action-button{width:var(--sp-tabs-overflow-button-size);height:var(--sp-tabs-overflow-button-height);z-index:2;text-align:center;box-shadow:none;color:var(--sp-tabs-overflow-icon-color);background:0 0;border:none;position:absolute}sp-action-button.left-scroll{visibility:hidden;left:var(--sp-tabs-overflow-previous-button-left)}sp-action-button.right-scroll{visibility:hidden;right:var(--sp-tabs-overflow-next-button-right)}sp-action-button.left-scroll.show,sp-action-button.right-scroll.show{visibility:visible}.tabs-overflow-container{position:relative}.tabs-overflow-container:before,.tabs-overflow-container:after{content:"";visibility:hidden;z-index:1;height:var(--sp-tabs-overflow-button-height);width:var(--sp-tabs-overflow-shadow-width);pointer-events:none;position:absolute;inset-block-start:0}.tabs-overflow-container:before{background:transparent linear-gradient(270deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;left:0}.tabs-overflow-container:after{background:transparent linear-gradient(90deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;right:0}.tabs-overflow-container.left-shadow:before,.tabs-overflow-container.right-shadow:after{visibility:visible}
|
|
5
5
|
`;
|
|
6
6
|
export default styles;
|
|
7
7
|
//# sourceMappingURL=tabs-overflow.css.dev.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tabs-overflow.css.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{width:100%;--sp-tabs-overflow-next-button-right:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-previous-button-left:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-medium) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-medium);--sp-tabs-overflow-icon-color:var(--spectrum-gray-800);--sp-tabs-overflow-shadow-color:var(--spectrum-gray-100);--sp-tabs-overflow-shadow-width:50px;--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-100);inset:0}:host([size=s]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-small) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-small);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-75)}:host([size=l]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-200)}:host([size=xl]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-extra-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-extra-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-300)}:host([compact]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-compact-height-medium) - var(--spectrum-border-width-200));--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-50)}sp-action-button{width:var(--sp-tabs-overflow-button-size);height:var(--sp-tabs-overflow-button-height);z-index:2;text-align:center;box-shadow:none;color:var(--sp-tabs-overflow-icon-color);background:0 0;border:none;position:absolute}sp-action-button.left-scroll{visibility:hidden;left:var(--sp-tabs-overflow-previous-button-left)}sp-action-button.right-scroll{visibility:hidden;right:var(--sp-tabs-overflow-next-button-right)}sp-action-button.left-scroll.show,sp-action-button.right-scroll.show{visibility:visible}.tabs-overflow-container{position:relative}.tabs-overflow-container:before,.tabs-overflow-container:after{content:\"\";visibility:hidden;z-index:1;height:var(--sp-tabs-overflow-button-height);width:var(--sp-tabs-overflow-shadow-width);pointer-events:none;position:absolute;inset-block-start:0}.tabs-overflow-container:before{background:transparent linear-gradient(270deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;left:0}.tabs-overflow-container:after{background:transparent linear-gradient(90deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;right:0}.tabs-overflow-container.left-shadow:before,.tabs-overflow-container.right-shadow:after{visibility:visible}\n`;\nexport default styles;"],
|
|
5
5
|
"mappings": ";AAWA,SAAS,WAAW;AACpB,MAAM,SAAS;AAAA;AAAA;AAGf,eAAe;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/tabs-overflow.css.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use strict";import{css as t}from"@spectrum-web-components/base";const o=t`
|
|
2
|
-
:host{
|
|
2
|
+
:host{width:100%;--sp-tabs-overflow-next-button-right:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-previous-button-left:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-medium) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-medium);--sp-tabs-overflow-icon-color:var(--spectrum-gray-800);--sp-tabs-overflow-shadow-color:var(--spectrum-gray-100);--sp-tabs-overflow-shadow-width:50px;--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-100);inset:0}:host([size=s]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-small) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-small);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-75)}:host([size=l]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-200)}:host([size=xl]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-extra-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-extra-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-300)}:host([compact]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-compact-height-medium) - var(--spectrum-border-width-200));--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-50)}sp-action-button{width:var(--sp-tabs-overflow-button-size);height:var(--sp-tabs-overflow-button-height);z-index:2;text-align:center;box-shadow:none;color:var(--sp-tabs-overflow-icon-color);background:0 0;border:none;position:absolute}sp-action-button.left-scroll{visibility:hidden;left:var(--sp-tabs-overflow-previous-button-left)}sp-action-button.right-scroll{visibility:hidden;right:var(--sp-tabs-overflow-next-button-right)}sp-action-button.left-scroll.show,sp-action-button.right-scroll.show{visibility:visible}.tabs-overflow-container{position:relative}.tabs-overflow-container:before,.tabs-overflow-container:after{content:"";visibility:hidden;z-index:1;height:var(--sp-tabs-overflow-button-height);width:var(--sp-tabs-overflow-shadow-width);pointer-events:none;position:absolute;inset-block-start:0}.tabs-overflow-container:before{background:transparent linear-gradient(270deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;left:0}.tabs-overflow-container:after{background:transparent linear-gradient(90deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;right:0}.tabs-overflow-container.left-shadow:before,.tabs-overflow-container.right-shadow:after{visibility:visible}
|
|
3
3
|
`;export default o;
|
|
4
4
|
//# sourceMappingURL=tabs-overflow.css.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tabs-overflow.css.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2024 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 { css } from '@spectrum-web-components/base';\nconst styles = css`\n :host{width:100%;--sp-tabs-overflow-next-button-right:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-previous-button-left:calc(-1*var(--spectrum-component-edge-to-text-100));--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-medium) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-medium);--sp-tabs-overflow-icon-color:var(--spectrum-gray-800);--sp-tabs-overflow-shadow-color:var(--spectrum-gray-100);--sp-tabs-overflow-shadow-width:50px;--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-100);inset:0}:host([size=s]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-small) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-small);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-75)}:host([size=l]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-200)}:host([size=xl]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-height-extra-large) - var(--spectrum-border-width-200));--sp-tabs-overflow-button-size:var(--spectrum-tab-item-height-extra-large);--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-300)}:host([compact]){--sp-tabs-overflow-button-height:calc(var(--spectrum-tab-item-compact-height-medium) - var(--spectrum-border-width-200));--mod-actionbutton-icon-size:var(--spectrum-workflow-icon-size-50)}sp-action-button{width:var(--sp-tabs-overflow-button-size);height:var(--sp-tabs-overflow-button-height);z-index:2;text-align:center;box-shadow:none;color:var(--sp-tabs-overflow-icon-color);background:0 0;border:none;position:absolute}sp-action-button.left-scroll{visibility:hidden;left:var(--sp-tabs-overflow-previous-button-left)}sp-action-button.right-scroll{visibility:hidden;right:var(--sp-tabs-overflow-next-button-right)}sp-action-button.left-scroll.show,sp-action-button.right-scroll.show{visibility:visible}.tabs-overflow-container{position:relative}.tabs-overflow-container:before,.tabs-overflow-container:after{content:\"\";visibility:hidden;z-index:1;height:var(--sp-tabs-overflow-button-height);width:var(--sp-tabs-overflow-shadow-width);pointer-events:none;position:absolute;inset-block-start:0}.tabs-overflow-container:before{background:transparent linear-gradient(270deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;left:0}.tabs-overflow-container:after{background:transparent linear-gradient(90deg,transparent,var(--sp-tabs-overflow-shadow-color))0 0 no-repeat padding-box;right:0}.tabs-overflow-container.left-shadow:before,.tabs-overflow-container.right-shadow:after{visibility:visible}\n`;\nexport default styles;"],
|
|
5
5
|
"mappings": "aAWA,OAAS,OAAAA,MAAW,gCACpB,MAAMC,EAASD;AAAA;AAAA,EAGf,eAAeC",
|
|
6
6
|
"names": ["css", "styles"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
import { html } from "@spectrum-web-components/base";
|
|
2
3
|
import { renderTabsOverflowExample } from "./index.js";
|
|
3
4
|
export default {
|
|
4
5
|
title: "Tabs Overflow",
|
|
@@ -16,4 +17,21 @@ export const autoscroll = (args) => {
|
|
|
16
17
|
autoscroll.args = {
|
|
17
18
|
selected: 15
|
|
18
19
|
};
|
|
20
|
+
export const autoscrollOnlyHorizontally = (args) => {
|
|
21
|
+
return html`
|
|
22
|
+
<style>
|
|
23
|
+
.container {
|
|
24
|
+
height: 500px;
|
|
25
|
+
overflow-y: scroll;
|
|
26
|
+
}
|
|
27
|
+
</style>
|
|
28
|
+
<div class="container">
|
|
29
|
+
<div style="height: 500px">There are some tabs down here!</div>
|
|
30
|
+
${renderTabsOverflowExample(args)}
|
|
31
|
+
</div>
|
|
32
|
+
`;
|
|
33
|
+
};
|
|
34
|
+
autoscrollOnlyHorizontally.args = {
|
|
35
|
+
selected: 15
|
|
36
|
+
};
|
|
19
37
|
//# sourceMappingURL=tabs-overflow.stories.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tabs-overflow.stories.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2022 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 { TemplateResult } from '@spectrum-web-components/base';\nimport { OverflowProperties, renderTabsOverflowExample } from './index.js';\n\nexport default {\n title: 'Tabs Overflow',\n component: 'sp-tabs-overflow',\n};\n\nexport const compact = (args: OverflowProperties): TemplateResult => {\n return renderTabsOverflowExample(args);\n};\ncompact.args = {\n compact: true,\n};\n\nexport const autoscroll = (args: OverflowProperties): TemplateResult => {\n return renderTabsOverflowExample(args);\n};\nautoscroll.args = {\n selected: 15,\n};\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2022 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 { html, TemplateResult } from '@spectrum-web-components/base';\nimport { OverflowProperties, renderTabsOverflowExample } from './index.js';\n\nexport default {\n title: 'Tabs Overflow',\n component: 'sp-tabs-overflow',\n};\n\nexport const compact = (args: OverflowProperties): TemplateResult => {\n return renderTabsOverflowExample(args);\n};\ncompact.args = {\n compact: true,\n};\n\nexport const autoscroll = (args: OverflowProperties): TemplateResult => {\n return renderTabsOverflowExample(args);\n};\nautoscroll.args = {\n selected: 15,\n};\n\n// https://github.com/adobe/spectrum-web-components/issues/4590\nexport const autoscrollOnlyHorizontally = (\n args: OverflowProperties\n): TemplateResult => {\n return html`\n <style>\n .container {\n height: 500px;\n overflow-y: scroll;\n }\n </style>\n <div class=\"container\">\n <div style=\"height: 500px\">There are some tabs down here!</div>\n ${renderTabsOverflowExample(args)}\n </div>\n `;\n};\nautoscrollOnlyHorizontally.args = {\n selected: 15,\n};\n"],
|
|
5
|
+
"mappings": ";AAWA,SAAS,YAA4B;AACrC,SAA6B,iCAAiC;AAE9D,eAAe;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AACf;AAEO,aAAM,UAAU,CAAC,SAA6C;AACjE,SAAO,0BAA0B,IAAI;AACzC;AACA,QAAQ,OAAO;AAAA,EACX,SAAS;AACb;AAEO,aAAM,aAAa,CAAC,SAA6C;AACpE,SAAO,0BAA0B,IAAI;AACzC;AACA,WAAW,OAAO;AAAA,EACd,UAAU;AACd;AAGO,aAAM,6BAA6B,CACtC,SACiB;AACjB,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cASG,0BAA0B,IAAI,CAAC;AAAA;AAAA;AAG7C;AACA,2BAA2B,OAAO;AAAA,EAC9B,UAAU;AACd;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,6 +6,10 @@ import "@spectrum-web-components/tabs/sp-tab.js";
|
|
|
6
6
|
import "@spectrum-web-components/tabs/sp-tabs.js";
|
|
7
7
|
import "@spectrum-web-components/tabs/sp-tab-panel.js";
|
|
8
8
|
import "@spectrum-web-components/tabs/sp-tabs-overflow.js";
|
|
9
|
+
import {
|
|
10
|
+
calculateScrollTargetForLeftSide,
|
|
11
|
+
calculateScrollTargetForRightSide
|
|
12
|
+
} from "@spectrum-web-components/tabs";
|
|
9
13
|
import { elementUpdated, expect, fixture } from "@open-wc/testing";
|
|
10
14
|
import {
|
|
11
15
|
ElementSizes,
|
|
@@ -17,58 +21,52 @@ const renderTabsOverflow = async ({
|
|
|
17
21
|
count,
|
|
18
22
|
size,
|
|
19
23
|
includeTabPanel,
|
|
20
|
-
selected = 1
|
|
21
|
-
autoscroll = false
|
|
24
|
+
selected = 1
|
|
22
25
|
}) => {
|
|
23
|
-
const tabsContainer = await fixture(
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
<sp-tabs
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
</div>
|
|
53
|
-
`
|
|
54
|
-
);
|
|
26
|
+
const tabsContainer = await fixture(html`
|
|
27
|
+
<div class="container" style="width: 200px; height: 150px;">
|
|
28
|
+
<sp-tabs-overflow>
|
|
29
|
+
<sp-tabs size=${size} selected=${selected}>
|
|
30
|
+
${repeat(
|
|
31
|
+
new Array(count),
|
|
32
|
+
(item) => item,
|
|
33
|
+
(_item, index) => html`
|
|
34
|
+
<sp-tab
|
|
35
|
+
label=${`Tab Item ${index + 1}`}
|
|
36
|
+
value=${index + 1}
|
|
37
|
+
></sp-tab>
|
|
38
|
+
`
|
|
39
|
+
)}
|
|
40
|
+
${includeTabPanel ? html`
|
|
41
|
+
${repeat(
|
|
42
|
+
new Array(count),
|
|
43
|
+
(item) => item,
|
|
44
|
+
(_item, index) => html`
|
|
45
|
+
<sp-tab-panel value=${index + 1}>
|
|
46
|
+
Content for Tab Item ${index + 1}
|
|
47
|
+
</sp-tab-panel>
|
|
48
|
+
`
|
|
49
|
+
)}
|
|
50
|
+
` : nothing}
|
|
51
|
+
</sp-tabs>
|
|
52
|
+
</sp-tabs-overflow>
|
|
53
|
+
</div>
|
|
54
|
+
`);
|
|
55
55
|
await elementUpdated(tabsContainer);
|
|
56
56
|
return tabsContainer;
|
|
57
57
|
};
|
|
58
58
|
describe("TabsOverflow", () => {
|
|
59
59
|
it("loads default tabs-overflow accessibly", async () => {
|
|
60
|
-
const el = await fixture(
|
|
61
|
-
|
|
62
|
-
<sp-tabs
|
|
63
|
-
<sp-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`
|
|
71
|
-
);
|
|
60
|
+
const el = await fixture(html`
|
|
61
|
+
<sp-tabs-overflow>
|
|
62
|
+
<sp-tabs size="m" selected="1">
|
|
63
|
+
<sp-tab label="Tab Item 1" value="1"></sp-tab>
|
|
64
|
+
<sp-tab label="Tab Item 2" value="2"></sp-tab>
|
|
65
|
+
<sp-tab-panel value="1">Tab Content 1</sp-tab-panel>
|
|
66
|
+
<sp-tab-panel value="2">Tab Content 2</sp-tab-panel>
|
|
67
|
+
</sp-tabs>
|
|
68
|
+
</sp-tabs-overflow>
|
|
69
|
+
`);
|
|
72
70
|
await elementUpdated(el);
|
|
73
71
|
await expect(el).to.be.accessible();
|
|
74
72
|
});
|
|
@@ -130,13 +128,11 @@ describe("TabsOverflow", () => {
|
|
|
130
128
|
expect(finalLeft).to.be.lessThanOrEqual(initialLeft);
|
|
131
129
|
});
|
|
132
130
|
it("should fail properly if slot is not sp-tabs", async () => {
|
|
133
|
-
const el = await fixture(
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`
|
|
139
|
-
);
|
|
131
|
+
const el = await fixture(html`
|
|
132
|
+
<sp-tabs-overflow>
|
|
133
|
+
<div>Some div</div>
|
|
134
|
+
</sp-tabs-overflow>
|
|
135
|
+
`);
|
|
140
136
|
await elementUpdated(el);
|
|
141
137
|
const slot = el.shadowRoot.querySelector("slot");
|
|
142
138
|
const slotContent = (slot == null ? void 0 : slot.assignedElements()) || "";
|
|
@@ -151,16 +147,30 @@ describe("TabsOverflow", () => {
|
|
|
151
147
|
});
|
|
152
148
|
await elementUpdated(el);
|
|
153
149
|
const tabsEl = el.querySelector("sp-tabs");
|
|
154
|
-
|
|
150
|
+
let selectedTab = tabsEl.querySelector(
|
|
155
151
|
`[role="tab"][value="10"]`
|
|
156
152
|
);
|
|
157
153
|
expect(selectedTab).to.exist;
|
|
158
|
-
|
|
154
|
+
let selectedTabPosition = selectedTab.getBoundingClientRect();
|
|
159
155
|
expect(selectedTabPosition.left).to.be.greaterThan(0);
|
|
160
|
-
expect(selectedTabPosition.left).to.be.lessThan(tabsEl.
|
|
156
|
+
expect(selectedTabPosition.left).to.be.lessThan(tabsEl.offsetWidth);
|
|
161
157
|
const firstTab = tabsEl.querySelector(`[role="tab"][value="1"]`);
|
|
162
158
|
const firstTabPosition = firstTab.getBoundingClientRect();
|
|
163
159
|
expect(firstTabPosition.left).to.be.lessThan(0);
|
|
160
|
+
tabsEl.selected = "1";
|
|
161
|
+
await elementUpdated(tabsEl);
|
|
162
|
+
selectedTab = tabsEl.querySelector(`[role="tab"][value="1"]`);
|
|
163
|
+
expect(selectedTab).to.exist;
|
|
164
|
+
selectedTabPosition = selectedTab.getBoundingClientRect();
|
|
165
|
+
expect(selectedTabPosition.left).to.be.greaterThan(0);
|
|
166
|
+
expect(selectedTabPosition.left).to.be.lessThan(tabsEl.offsetWidth);
|
|
167
|
+
const previousSelection = tabsEl.querySelector(
|
|
168
|
+
`[role="tab"][value="10"]`
|
|
169
|
+
);
|
|
170
|
+
const previousSelectionPosition = previousSelection.getBoundingClientRect();
|
|
171
|
+
expect(previousSelectionPosition.left).to.be.greaterThan(
|
|
172
|
+
tabsEl.offsetWidth
|
|
173
|
+
);
|
|
164
174
|
});
|
|
165
175
|
it("prev and next buttons have default labels", async () => {
|
|
166
176
|
const el = await renderTabsOverflow({
|
|
@@ -186,38 +196,36 @@ describe("TabsOverflow", () => {
|
|
|
186
196
|
);
|
|
187
197
|
});
|
|
188
198
|
it("prev and next buttons labels overwritten via attributes", async () => {
|
|
189
|
-
const tabsContainer = await fixture(
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`
|
|
220
|
-
);
|
|
199
|
+
const tabsContainer = await fixture(html`
|
|
200
|
+
<div class="container" style="width: 200px; height: 150px;">
|
|
201
|
+
<sp-tabs-overflow
|
|
202
|
+
label-previous="custom label prev"
|
|
203
|
+
label-next="custom label next"
|
|
204
|
+
>
|
|
205
|
+
<sp-tabs size=${ElementSizes.M} selected=${1}>
|
|
206
|
+
${repeat(
|
|
207
|
+
new Array(20),
|
|
208
|
+
(item) => item,
|
|
209
|
+
(_item, index) => html`
|
|
210
|
+
<sp-tab
|
|
211
|
+
label=${`Tab Item ${index + 1}`}
|
|
212
|
+
value=${index + 1}
|
|
213
|
+
></sp-tab>
|
|
214
|
+
`
|
|
215
|
+
)}
|
|
216
|
+
${repeat(
|
|
217
|
+
new Array(20),
|
|
218
|
+
(item) => item,
|
|
219
|
+
(_item, index) => html`
|
|
220
|
+
<sp-tab-panel value=${index + 1}>
|
|
221
|
+
Content for Tab Item ${index + 1}
|
|
222
|
+
</sp-tab-panel>
|
|
223
|
+
`
|
|
224
|
+
)}
|
|
225
|
+
</sp-tabs>
|
|
226
|
+
</sp-tabs-overflow>
|
|
227
|
+
</div>
|
|
228
|
+
`);
|
|
221
229
|
await elementUpdated(tabsContainer);
|
|
222
230
|
const el = tabsContainer;
|
|
223
231
|
const spTabsOverflows = el.querySelector(
|
|
@@ -237,4 +245,44 @@ describe("TabsOverflow", () => {
|
|
|
237
245
|
);
|
|
238
246
|
});
|
|
239
247
|
});
|
|
248
|
+
describe("calculateScrollTargetForRightSide", () => {
|
|
249
|
+
const container = { offsetWidth: 100, scrollLeft: 0 };
|
|
250
|
+
const tabs = [
|
|
251
|
+
{ offsetLeft: 0, offsetWidth: 100 },
|
|
252
|
+
// currently selected tab
|
|
253
|
+
{ offsetLeft: 100, offsetWidth: 100 },
|
|
254
|
+
{ offsetLeft: 200, offsetWidth: 100 }
|
|
255
|
+
];
|
|
256
|
+
it("correctly aligns tab on the right side of the viewport", () => {
|
|
257
|
+
expect(
|
|
258
|
+
calculateScrollTargetForRightSide(2, "ltr", tabs, container)
|
|
259
|
+
).to.equal(100);
|
|
260
|
+
expect(
|
|
261
|
+
calculateScrollTargetForRightSide(2, "rtl", tabs, container)
|
|
262
|
+
).to.equal(0);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
describe("calculateScrollTargetForLeftSide", () => {
|
|
266
|
+
const container = { offsetWidth: 100, scrollLeft: 200 };
|
|
267
|
+
const tabs = [
|
|
268
|
+
{ offsetLeft: -200, offsetWidth: 100 },
|
|
269
|
+
{ offsetLeft: -100, offsetWidth: 100 },
|
|
270
|
+
{ offsetLeft: 0, offsetWidth: 100 }
|
|
271
|
+
// currently selected tab
|
|
272
|
+
];
|
|
273
|
+
it("correctly aligns tab on the left side of the viewport", () => {
|
|
274
|
+
expect(
|
|
275
|
+
calculateScrollTargetForLeftSide(1, "ltr", tabs, container)
|
|
276
|
+
).to.equal(-100);
|
|
277
|
+
expect(
|
|
278
|
+
calculateScrollTargetForLeftSide(0, "ltr", tabs, container)
|
|
279
|
+
).to.equal(0);
|
|
280
|
+
expect(
|
|
281
|
+
calculateScrollTargetForLeftSide(1, "rtl", tabs, container)
|
|
282
|
+
).to.equal(100);
|
|
283
|
+
expect(
|
|
284
|
+
calculateScrollTargetForLeftSide(0, "rtl", tabs, container)
|
|
285
|
+
).to.equal(0);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
240
288
|
//# sourceMappingURL=tabs-overflow.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["tabs-overflow.test.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2022 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/theme/sp-theme.js';\nimport '@spectrum-web-components/theme/scale-medium.js';\nimport '@spectrum-web-components/theme/theme-light.js';\nimport '@spectrum-web-components/tabs/sp-tab.js';\nimport '@spectrum-web-components/tabs/sp-tabs.js';\nimport '@spectrum-web-components/tabs/sp-tab-panel.js';\nimport '@spectrum-web-components/tabs/sp-tabs-overflow.js';\nimport { Tab, Tabs, TabsOverflow } from '@spectrum-web-components/tabs';\nimport { ActionButton } from '@spectrum-web-components/action-button';\n\nimport { elementUpdated, expect, fixture } from '@open-wc/testing';\nimport {\n ElementSize,\n ElementSizes,\n html,\n nothing,\n} from '@spectrum-web-components/base';\nimport { repeat } from 'lit/directives/repeat.js';\n\ntype OverflowProperties = {\n count: number;\n size: ElementSize;\n includeTabPanel: boolean;\n selected?: number;\n autoscroll?: boolean;\n labelPrev?: string;\n labelNext?: string;\n};\n\nconst renderTabsOverflow = async ({\n count,\n size,\n includeTabPanel,\n selected = 1,\n autoscroll = false,\n}: OverflowProperties): Promise<HTMLDivElement> => {\n const tabsContainer = await fixture<HTMLDivElement>(\n html`\n <div class=\"container\" style=\"width: 200px; height: 150px;\">\n <sp-tabs-overflow ?autoscroll=${autoscroll}>\n <sp-tabs size=${size} selected=${selected}>\n ${repeat(\n new Array(count),\n (item) => item,\n (_item, index) =>\n html`\n <sp-tab\n label=${`Tab Item ${index + 1}`}\n value=${index + 1}\n ></sp-tab>\n `\n )}\n ${includeTabPanel\n ? html`\n ${repeat(\n new Array(count),\n (item) => item,\n (_item, index) =>\n html`\n <sp-tab-panel value=${index + 1}>\n Content for Tab Item\n ${index + 1}\n </sp-tab-panel>\n `\n )}\n `\n : nothing}\n </sp-tabs>\n </sp-tabs-overflow>\n </div>\n `\n );\n await elementUpdated(tabsContainer);\n return tabsContainer;\n};\n\ndescribe('TabsOverflow', () => {\n it('loads default tabs-overflow accessibly', async () => {\n const el = await fixture<TabsOverflow>(\n html`\n <sp-tabs-overflow>\n <sp-tabs size=\"m\" selected=\"1\">\n <sp-tab label=\"Tab Item 1\" value=\"1\"></sp-tab>\n <sp-tab label=\"Tab Item 2\" value=\"2\"></sp-tab>\n <sp-tab-panel value=\"1\">Tab Content 1</sp-tab-panel>\n <sp-tab-panel value=\"2\">Tab Content 2</sp-tab-panel>\n </sp-tabs>\n </sp-tabs-overflow>\n `\n );\n\n await elementUpdated(el);\n\n await expect(el).to.be.accessible();\n });\n\n it('show render left and right buttons in shadowDom', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: true,\n });\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n expect(rightButton).to.exist;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n expect(leftButton).to.exist;\n });\n\n it('reflect proper sp-tab size', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.M,\n includeTabPanel: true,\n });\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n\n expect(spTabsOverflows.getAttribute('size')).to.equal('m');\n });\n\n it('should scroll when the button is clicked', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: true,\n });\n await elementUpdated(el);\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n leftButton.dispatchEvent(new Event('click', {}));\n\n const tabsEl = spTabsOverflows.querySelector('sp-tab') as Tab;\n const initialLeft = tabsEl.getBoundingClientRect().left;\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n const finalLeft = tabsEl.getBoundingClientRect().left;\n expect(finalLeft).to.be.lessThanOrEqual(initialLeft);\n });\n\n it('should fail properly if slot is not sp-tabs', async () => {\n const el = await fixture<TabsOverflow>(\n html`\n <sp-tabs-overflow>\n <div>Some div</div>\n </sp-tabs-overflow>\n `\n );\n\n await elementUpdated(el);\n const slot = el.shadowRoot.querySelector('slot');\n const slotContent = slot?.assignedElements() || '';\n expect(slotContent[0].toString()).to.not.contains('Tabs');\n });\n\n it('should automatically bring the selected tab into view', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: false,\n selected: 10,\n });\n await elementUpdated(el);\n\n // Grab the list of tabs.\n const tabsEl = el.querySelector('sp-tabs') as Tabs;\n\n // Grab the coordonates of the selected tab.\n const selectedTab = tabsEl.querySelector(\n `[role=\"tab\"][value=\"10\"]`\n ) as Tab;\n expect(selectedTab).to.exist;\n const selectedTabPosition = selectedTab.getBoundingClientRect();\n\n // Selected tab is in the viewport, offset left is greater than 0 and less than the width of the tabs.\n expect(selectedTabPosition.left).to.be.greaterThan(0);\n expect(selectedTabPosition.left).to.be.lessThan(tabsEl.clientWidth);\n\n // First tab is not in the viewport anymore, its offset left is less than 0.\n const firstTab = tabsEl.querySelector(`[role=\"tab\"][value=\"1\"]`) as Tab;\n const firstTabPosition = firstTab.getBoundingClientRect();\n expect(firstTabPosition.left).to.be.lessThan(0);\n });\n\n it('prev and next buttons have default labels', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.M,\n includeTabPanel: true,\n });\n await elementUpdated(el);\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n expect(leftButton?.getAttribute('aria-label')).to.equal(\n 'Scroll to previous tabs'\n );\n expect(rightButton?.getAttribute('aria-label')).to.equal(\n 'Scroll to next tabs'\n );\n });\n\n it('prev and next buttons labels overwritten via attributes', async () => {\n const tabsContainer = await fixture<HTMLDivElement>(\n html`\n <div class=\"container\" style=\"width: 200px; height: 150px;\">\n <sp-tabs-overflow\n label-previous=\"custom label prev\"\n label-next=\"custom label next\"\n >\n <sp-tabs size=${ElementSizes.M} selected=${1}>\n ${repeat(\n new Array(20),\n (item) => item,\n (_item, index) =>\n html`\n <sp-tab\n label=${`Tab Item ${index + 1}`}\n value=${index + 1}\n ></sp-tab>\n `\n )}\n ${repeat(\n new Array(20),\n (item) => item,\n (_item, index) =>\n html`\n <sp-tab-panel value=${index + 1}>\n Content for Tab Item ${index + 1}\n </sp-tab-panel>\n `\n )}\n </sp-tabs>\n </sp-tabs-overflow>\n </div>\n `\n );\n await elementUpdated(tabsContainer);\n const el = tabsContainer;\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n expect(leftButton?.getAttribute('aria-label')).to.equal(\n 'custom label prev'\n );\n expect(rightButton?.getAttribute('aria-label')).to.equal(\n 'custom label next'\n );\n });\n});\n"],
|
|
5
|
-
"mappings": ";AAWA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2022 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/theme/sp-theme.js';\nimport '@spectrum-web-components/theme/scale-medium.js';\nimport '@spectrum-web-components/theme/theme-light.js';\nimport '@spectrum-web-components/tabs/sp-tab.js';\nimport '@spectrum-web-components/tabs/sp-tabs.js';\nimport '@spectrum-web-components/tabs/sp-tab-panel.js';\nimport '@spectrum-web-components/tabs/sp-tabs-overflow.js';\nimport {\n calculateScrollTargetForLeftSide,\n calculateScrollTargetForRightSide,\n Tab,\n Tabs,\n TabsOverflow,\n} from '@spectrum-web-components/tabs';\nimport { ActionButton } from '@spectrum-web-components/action-button';\n\nimport { elementUpdated, expect, fixture } from '@open-wc/testing';\nimport {\n ElementSize,\n ElementSizes,\n html,\n nothing,\n} from '@spectrum-web-components/base';\nimport { repeat } from 'lit/directives/repeat.js';\n\ntype OverflowProperties = {\n count: number;\n size: ElementSize;\n includeTabPanel: boolean;\n selected?: number;\n labelPrev?: string;\n labelNext?: string;\n};\n\nconst renderTabsOverflow = async ({\n count,\n size,\n includeTabPanel,\n selected = 1,\n}: OverflowProperties): Promise<HTMLDivElement> => {\n const tabsContainer = await fixture<HTMLDivElement>(html`\n <div class=\"container\" style=\"width: 200px; height: 150px;\">\n <sp-tabs-overflow>\n <sp-tabs size=${size} selected=${selected}>\n ${repeat(\n new Array(count),\n (item) => item,\n (_item, index) => html`\n <sp-tab\n label=${`Tab Item ${index + 1}`}\n value=${index + 1}\n ></sp-tab>\n `\n )}\n ${includeTabPanel\n ? html`\n ${repeat(\n new Array(count),\n (item) => item,\n (_item, index) => html`\n <sp-tab-panel value=${index + 1}>\n Content for Tab Item ${index + 1}\n </sp-tab-panel>\n `\n )}\n `\n : nothing}\n </sp-tabs>\n </sp-tabs-overflow>\n </div>\n `);\n await elementUpdated(tabsContainer);\n return tabsContainer;\n};\n\ndescribe('TabsOverflow', () => {\n it('loads default tabs-overflow accessibly', async () => {\n const el = await fixture<TabsOverflow>(html`\n <sp-tabs-overflow>\n <sp-tabs size=\"m\" selected=\"1\">\n <sp-tab label=\"Tab Item 1\" value=\"1\"></sp-tab>\n <sp-tab label=\"Tab Item 2\" value=\"2\"></sp-tab>\n <sp-tab-panel value=\"1\">Tab Content 1</sp-tab-panel>\n <sp-tab-panel value=\"2\">Tab Content 2</sp-tab-panel>\n </sp-tabs>\n </sp-tabs-overflow>\n `);\n\n await elementUpdated(el);\n\n await expect(el).to.be.accessible();\n });\n\n it('show render left and right buttons in shadowDom', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: true,\n });\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n expect(rightButton).to.exist;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n expect(leftButton).to.exist;\n });\n\n it('reflect proper sp-tab size', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.M,\n includeTabPanel: true,\n });\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n\n expect(spTabsOverflows.getAttribute('size')).to.equal('m');\n });\n\n it('should scroll when the button is clicked', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: true,\n });\n await elementUpdated(el);\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n leftButton.dispatchEvent(new Event('click', {}));\n\n const tabsEl = spTabsOverflows.querySelector('sp-tab') as Tab;\n const initialLeft = tabsEl.getBoundingClientRect().left;\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n rightButton.dispatchEvent(new Event('click', {}));\n await elementUpdated(el);\n const finalLeft = tabsEl.getBoundingClientRect().left;\n expect(finalLeft).to.be.lessThanOrEqual(initialLeft);\n });\n\n it('should fail properly if slot is not sp-tabs', async () => {\n const el = await fixture<TabsOverflow>(html`\n <sp-tabs-overflow>\n <div>Some div</div>\n </sp-tabs-overflow>\n `);\n\n await elementUpdated(el);\n const slot = el.shadowRoot.querySelector('slot');\n const slotContent = slot?.assignedElements() || '';\n expect(slotContent[0].toString()).to.not.contains('Tabs');\n });\n\n it('should automatically bring the selected tab into view', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.L,\n includeTabPanel: false,\n selected: 10,\n });\n await elementUpdated(el);\n\n // Grab the list of tabs.\n const tabsEl = el.querySelector('sp-tabs') as Tabs;\n\n // Grab the coordonates of the selected tab.\n let selectedTab = tabsEl.querySelector(\n `[role=\"tab\"][value=\"10\"]`\n ) as Tab;\n expect(selectedTab).to.exist;\n let selectedTabPosition = selectedTab.getBoundingClientRect();\n\n // Selected tab is in the viewport, offset left is greater than 0 and less than the width of the tabs.\n expect(selectedTabPosition.left).to.be.greaterThan(0);\n expect(selectedTabPosition.left).to.be.lessThan(tabsEl.offsetWidth);\n\n // First tab is not in the viewport anymore, its offset left is less than 0.\n const firstTab = tabsEl.querySelector(`[role=\"tab\"][value=\"1\"]`) as Tab;\n const firstTabPosition = firstTab.getBoundingClientRect();\n expect(firstTabPosition.left).to.be.lessThan(0);\n\n // Make the component automatically scroll left by selecting the first tab.\n tabsEl.selected = '1';\n await elementUpdated(tabsEl);\n\n selectedTab = tabsEl.querySelector(`[role=\"tab\"][value=\"1\"]`) as Tab;\n expect(selectedTab).to.exist;\n selectedTabPosition = selectedTab.getBoundingClientRect();\n\n // First tab is in the viewport, offset left is greater than 0 and less than the width of the tabs.\n expect(selectedTabPosition.left).to.be.greaterThan(0);\n expect(selectedTabPosition.left).to.be.lessThan(tabsEl.offsetWidth);\n\n // Tab nr. 10 is not in the viewport anymore.\n const previousSelection = tabsEl.querySelector(\n `[role=\"tab\"][value=\"10\"]`\n ) as Tab;\n const previousSelectionPosition =\n previousSelection.getBoundingClientRect();\n expect(previousSelectionPosition.left).to.be.greaterThan(\n tabsEl.offsetWidth\n );\n });\n\n it('prev and next buttons have default labels', async () => {\n const el = await renderTabsOverflow({\n count: 20,\n size: ElementSizes.M,\n includeTabPanel: true,\n });\n await elementUpdated(el);\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n expect(leftButton?.getAttribute('aria-label')).to.equal(\n 'Scroll to previous tabs'\n );\n expect(rightButton?.getAttribute('aria-label')).to.equal(\n 'Scroll to next tabs'\n );\n });\n\n it('prev and next buttons labels overwritten via attributes', async () => {\n const tabsContainer = await fixture<HTMLDivElement>(html`\n <div class=\"container\" style=\"width: 200px; height: 150px;\">\n <sp-tabs-overflow\n label-previous=\"custom label prev\"\n label-next=\"custom label next\"\n >\n <sp-tabs size=${ElementSizes.M} selected=${1}>\n ${repeat(\n new Array(20),\n (item) => item,\n (_item, index) => html`\n <sp-tab\n label=${`Tab Item ${index + 1}`}\n value=${index + 1}\n ></sp-tab>\n `\n )}\n ${repeat(\n new Array(20),\n (item) => item,\n (_item, index) => html`\n <sp-tab-panel value=${index + 1}>\n Content for Tab Item ${index + 1}\n </sp-tab-panel>\n `\n )}\n </sp-tabs>\n </sp-tabs-overflow>\n </div>\n `);\n await elementUpdated(tabsContainer);\n const el = tabsContainer;\n\n const spTabsOverflows: TabsOverflow = el.querySelector(\n 'sp-tabs-overflow'\n ) as TabsOverflow;\n const leftButton = spTabsOverflows.shadowRoot.querySelector(\n '.left-scroll'\n ) as ActionButton;\n const rightButton = spTabsOverflows.shadowRoot.querySelector(\n '.right-scroll'\n ) as ActionButton;\n\n expect(leftButton?.getAttribute('aria-label')).to.equal(\n 'custom label prev'\n );\n expect(rightButton?.getAttribute('aria-label')).to.equal(\n 'custom label next'\n );\n });\n});\n\ndescribe('calculateScrollTargetForRightSide', () => {\n const container = { offsetWidth: 100, scrollLeft: 0 } as HTMLDivElement;\n const tabs = [\n { offsetLeft: 0, offsetWidth: 100 }, // currently selected tab\n { offsetLeft: 100, offsetWidth: 100 },\n { offsetLeft: 200, offsetWidth: 100 },\n ] as Tab[];\n\n it('correctly aligns tab on the right side of the viewport', () => {\n // Where do I need to scroll on the x axis to get the tab at index 2 to be visible?\n expect(\n calculateScrollTargetForRightSide(2, 'ltr', tabs, container)\n ).to.equal(100); // You need to scroll 100px more\n\n // Repeat for RTL\n expect(\n calculateScrollTargetForRightSide(2, 'rtl', tabs, container)\n ).to.equal(0); // You need to scroll at the begining of the scrollable area\n });\n});\n\ndescribe('calculateScrollTargetForLeftSide', () => {\n const container = { offsetWidth: 100, scrollLeft: 200 } as HTMLDivElement;\n const tabs = [\n { offsetLeft: -200, offsetWidth: 100 },\n { offsetLeft: -100, offsetWidth: 100 },\n { offsetLeft: 0, offsetWidth: 100 }, // currently selected tab\n ] as Tab[];\n\n it('correctly aligns tab on the left side of the viewport', () => {\n // Where do I need to scroll on the x axis to get the tab at index 1 to be visible?\n expect(\n calculateScrollTargetForLeftSide(1, 'ltr', tabs, container)\n ).to.equal(-100); // you need to scroll back -100px\n\n // Where do I need to scroll on the x axis to get the first tab to be visible?\n expect(\n calculateScrollTargetForLeftSide(0, 'ltr', tabs, container)\n ).to.equal(0); // you need to scroll to the begining of the scrollable area\n\n // Repeat for RTL\n expect(\n calculateScrollTargetForLeftSide(1, 'rtl', tabs, container)\n ).to.equal(100);\n\n expect(\n calculateScrollTargetForLeftSide(0, 'rtl', tabs, container)\n ).to.equal(0);\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|