@spectrum-web-components/tabs 1.12.0-next.20260218162159 → 1.12.0-testing.20260223092154
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/package.json +7 -7
- package/sp-tab-panel.d.ts +1 -1
- package/sp-tab-panel.dev.js.map +1 -1
- package/sp-tab-panel.js.map +1 -1
- package/sp-tab.d.ts +1 -1
- package/sp-tab.dev.js.map +1 -1
- package/sp-tab.js.map +1 -1
- package/sp-tabs-overflow.dev.js.map +1 -1
- package/sp-tabs-overflow.js.map +1 -1
- package/sp-tabs.d.ts +1 -1
- package/sp-tabs.dev.js.map +1 -1
- package/sp-tabs.js.map +1 -1
- package/src/Tab.d.ts +1 -1
- package/src/Tab.dev.js.map +1 -1
- package/src/Tab.js.map +1 -1
- package/src/TabPanel.d.ts +1 -1
- package/src/TabPanel.dev.js.map +1 -1
- package/src/TabPanel.js.map +1 -1
- package/src/Tabs.d.ts +2 -1
- package/src/Tabs.dev.js +1 -0
- package/src/Tabs.dev.js.map +2 -2
- package/src/Tabs.js.map +2 -2
- package/src/TabsOverflow.d.ts +1 -1
- package/src/TabsOverflow.dev.js.map +2 -2
- package/src/TabsOverflow.js.map +2 -2
- package/src/index.d.ts +1 -1
- package/src/index.dev.js.map +1 -1
- package/src/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/tabs",
|
|
3
|
-
"version": "1.12.0-
|
|
3
|
+
"version": "1.12.0-testing.20260223092154",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Adobe",
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
"types": "./src/index.d.ts",
|
|
85
85
|
"dependencies": {
|
|
86
86
|
"@lit-labs/observers": "2.0.2",
|
|
87
|
-
"@spectrum-web-components/action-button": "1.12.0-
|
|
88
|
-
"@spectrum-web-components/base": "1.12.0-
|
|
89
|
-
"@spectrum-web-components/icon": "1.12.0-
|
|
90
|
-
"@spectrum-web-components/icons-ui": "1.12.0-
|
|
91
|
-
"@spectrum-web-components/reactive-controllers": "1.12.0-
|
|
92
|
-
"@spectrum-web-components/shared": "1.12.0-
|
|
87
|
+
"@spectrum-web-components/action-button": "1.12.0-testing.20260223092154",
|
|
88
|
+
"@spectrum-web-components/base": "1.12.0-testing.20260223092154",
|
|
89
|
+
"@spectrum-web-components/icon": "1.12.0-testing.20260223092154",
|
|
90
|
+
"@spectrum-web-components/icons-ui": "1.12.0-testing.20260223092154",
|
|
91
|
+
"@spectrum-web-components/reactive-controllers": "1.12.0-testing.20260223092154",
|
|
92
|
+
"@spectrum-web-components/shared": "1.12.0-testing.20260223092154"
|
|
93
93
|
},
|
|
94
94
|
"keywords": [
|
|
95
95
|
"design-system",
|
package/sp-tab-panel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/sp-tab-panel.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tab-panel.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { TabPanel } from './src/TabPanel.dev.js'\n\ndefineElement('sp-tab-panel', TabPanel);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tab-panel': TabPanel;\n }\n}\n"],
|
|
5
5
|
"mappings": ";AAYA,SAAS,qBAAqB;AAE9B,SAAS,gBAAgB;AAEzB,cAAc,gBAAgB,QAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/sp-tab-panel.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tab-panel.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { TabPanel } from './src/TabPanel.js';\n\ndefineElement('sp-tab-panel', TabPanel);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tab-panel': TabPanel;\n }\n}\n"],
|
|
5
5
|
"mappings": "aAYA,OAAS,iBAAAA,MAAqB,sDAE9B,OAAS,YAAAC,MAAgB,oBAEzBD,EAAc,eAAgBC,CAAQ",
|
|
6
6
|
"names": ["defineElement", "TabPanel"]
|
|
7
7
|
}
|
package/sp-tab.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/sp-tab.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tab.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Tab } from './src/Tab.dev.js'\n\ndefineElement('sp-tab', Tab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tab': Tab;\n }\n}\n"],
|
|
5
5
|
"mappings": ";AAYA,SAAS,qBAAqB;AAE9B,SAAS,WAAW;AAEpB,cAAc,UAAU,GAAG;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/sp-tab.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tab.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Tab } from './src/Tab.js';\n\ndefineElement('sp-tab', Tab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tab': Tab;\n }\n}\n"],
|
|
5
5
|
"mappings": "aAYA,OAAS,iBAAAA,MAAqB,sDAE9B,OAAS,OAAAC,MAAW,eAEpBD,EAAc,SAAUC,CAAG",
|
|
6
6
|
"names": ["defineElement", "Tab"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tabs-overflow.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { TabsOverflow } from './src/TabsOverflow.dev.js'\n\ndefineElement('sp-tabs-overflow', TabsOverflow);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tabs-overflow': TabsOverflow;\n }\n}\n"],
|
|
5
5
|
"mappings": ";AAWA,SAAS,qBAAqB;AAE9B,SAAS,oBAAoB;AAE7B,cAAc,oBAAoB,YAAY;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/sp-tabs-overflow.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tabs-overflow.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { TabsOverflow } from './src/TabsOverflow.js';\n\ndefineElement('sp-tabs-overflow', TabsOverflow);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tabs-overflow': TabsOverflow;\n }\n}\n"],
|
|
5
5
|
"mappings": "aAWA,OAAS,iBAAAA,MAAqB,sDAE9B,OAAS,gBAAAC,MAAoB,wBAE7BD,EAAc,mBAAoBC,CAAY",
|
|
6
6
|
"names": ["defineElement", "TabsOverflow"]
|
|
7
7
|
}
|
package/sp-tabs.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/sp-tabs.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Tabs } from './src/Tabs.dev.js'\n\ndefineElement('sp-tabs', Tabs);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tabs': Tabs;\n }\n}\n"],
|
|
5
5
|
"mappings": ";AAYA,SAAS,qBAAqB;AAE9B,SAAS,YAAY;AAErB,cAAc,WAAW,IAAI;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/sp-tabs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["sp-tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { defineElement } from '@spectrum-web-components/base/src/define-element.js';\n\nimport { Tabs } from './src/Tabs.js';\n\ndefineElement('sp-tabs', Tabs);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sp-tabs': Tabs;\n }\n}\n"],
|
|
5
5
|
"mappings": "aAYA,OAAS,iBAAAA,MAAqB,sDAE9B,OAAS,QAAAC,MAAY,gBAErBD,EAAc,UAAWC,CAAI",
|
|
6
6
|
"names": ["defineElement", "Tabs"]
|
|
7
7
|
}
|
package/src/Tab.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/src/Tab.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tab.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n nothing,\n PropertyValues,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport { property } from '@spectrum-web-components/base/src/decorators.js';\nimport { FocusVisiblePolyfillMixin } from '@spectrum-web-components/shared/src/focus-visible.js';\nimport { ObserveSlotPresence } from '@spectrum-web-components/shared/src/observe-slot-presence.js';\nimport { ObserveSlotText } from '@spectrum-web-components/shared/src/observe-slot-text.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport tabItemStyles from './tab.css.js';\n\n/**\n * @element sp-tab\n *\n * @slot - text label of the Tab\n * @slot icon - The icon that appears on the left of the label\n */\nexport class Tab extends FocusVisiblePolyfillMixin(\n ObserveSlotText(ObserveSlotPresence(SpectrumElement, '[slot=\"icon\"]'), '')\n) {\n public static override get styles(): CSSResultArray {\n return [tabItemStyles];\n }\n\n protected get hasIcon(): boolean {\n return this.slotContentIsPresent;\n }\n\n protected get hasLabel(): boolean {\n return !!this.label || this.slotHasContent;\n }\n\n @property({ type: Boolean, reflect: true })\n public disabled = false;\n\n @property({ reflect: true })\n public label = '';\n\n @property({ type: Boolean, reflect: true })\n public selected = false;\n\n @property({ type: Boolean, reflect: true })\n public vertical = false;\n\n @property({ type: String, reflect: true })\n public value = '';\n\n protected override render(): TemplateResult {\n return html`\n ${this.hasIcon\n ? html`\n <slot name=\"icon\"></slot>\n `\n : nothing}\n <label id=\"item-label\" ?hidden=${!this.hasLabel}>\n ${this.slotHasContent ? nothing : this.label}\n <slot>${this.label}</slot>\n </label>\n `;\n }\n\n protected override firstUpdated(changes: PropertyValues): void {\n super.firstUpdated(changes);\n this.setAttribute('role', 'tab');\n if (!this.hasAttribute('id')) {\n this.id = `sp-tab-${randomID()}`;\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('selected')) {\n this.setAttribute('aria-selected', this.selected ? 'true' : 'false');\n this.setAttribute('tabindex', this.selected ? '0' : '-1');\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 }\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;AAYA;AAAA,EAEE;AAAA,EACA;AAAA,EAEA;AAAA,OAEK;AACP,SAAS,gBAAgB;AACzB,SAAS,iCAAiC;AAC1C,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AAEzB,OAAO,mBAAmB;AAQnB,aAAM,YAAY;AAAA,EACvB,gBAAgB,oBAAoB,iBAAiB,eAAe,GAAG,EAAE;AAC3E,EAAE;AAAA,EAFK;AAAA;AAgBL,SAAO,WAAW;AAGlB,SAAO,QAAQ;AAGf,SAAO,WAAW;AAGlB,SAAO,WAAW;AAGlB,SAAO,QAAQ;AAAA;AAAA,EAzBf,WAA2B,SAAyB;AAClD,WAAO,CAAC,aAAa;AAAA,EACvB;AAAA,EAEA,IAAc,UAAmB;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAc,WAAoB;AAChC,WAAO,CAAC,CAAC,KAAK,SAAS,KAAK;AAAA,EAC9B;AAAA,EAiBmB,SAAyB;AAC1C,WAAO;AAAA,QACH,KAAK,UACH;AAAA;AAAA,cAGA,OAAO;AAAA,uCACsB,CAAC,KAAK,QAAQ;AAAA,UAC3C,KAAK,iBAAiB,UAAU,KAAK,KAAK;AAAA,gBACpC,KAAK,KAAK;AAAA;AAAA;AAAA,EAGxB;AAAA,EAEmB,aAAa,SAA+B;AAC7D,UAAM,aAAa,OAAO;AAC1B,SAAK,aAAa,QAAQ,KAAK;AAC/B,QAAI,CAAC,KAAK,aAAa,IAAI,GAAG;AAC5B,WAAK,KAAK,UAAU,SAAS,CAAC;AAAA,IAChC;AAAA,EACF;AAAA,EAEmB,QAAQ,SAA+B;AACxD,UAAM,QAAQ,OAAO;AACrB,QAAI,QAAQ,IAAI,UAAU,GAAG;AAC3B,WAAK,aAAa,iBAAiB,KAAK,WAAW,SAAS,OAAO;AACnE,WAAK,aAAa,YAAY,KAAK,WAAW,MAAM,IAAI;AAAA,IAC1D;AACA,QAAI,QAAQ,IAAI,UAAU,GAAG;AAC3B,UAAI,KAAK,UAAU;AACjB,aAAK,aAAa,iBAAiB,MAAM;AAAA,MAC3C,OAAO;AACL,aAAK,gBAAgB,eAAe;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;AAlDS;AAAA,EADN,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAf/B,IAgBJ;AAGA;AAAA,EADN,SAAS,EAAE,SAAS,KAAK,CAAC;AAAA,GAlBhB,IAmBJ;AAGA;AAAA,EADN,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GArB/B,IAsBJ;AAGA;AAAA,EADN,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAxB/B,IAyBJ;AAGA;AAAA,EADN,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA3B9B,IA4BJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/Tab.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tab.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n nothing,\n PropertyValues,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport { property } from '@spectrum-web-components/base/src/decorators.js';\nimport { FocusVisiblePolyfillMixin } from '@spectrum-web-components/shared/src/focus-visible.js';\nimport { ObserveSlotPresence } from '@spectrum-web-components/shared/src/observe-slot-presence.js';\nimport { ObserveSlotText } from '@spectrum-web-components/shared/src/observe-slot-text.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport tabItemStyles from './tab.css.js';\n\n/**\n * @element sp-tab\n *\n * @slot - text label of the Tab\n * @slot icon - The icon that appears on the left of the label\n */\nexport class Tab extends FocusVisiblePolyfillMixin(\n ObserveSlotText(ObserveSlotPresence(SpectrumElement, '[slot=\"icon\"]'), '')\n) {\n public static override get styles(): CSSResultArray {\n return [tabItemStyles];\n }\n\n protected get hasIcon(): boolean {\n return this.slotContentIsPresent;\n }\n\n protected get hasLabel(): boolean {\n return !!this.label || this.slotHasContent;\n }\n\n @property({ type: Boolean, reflect: true })\n public disabled = false;\n\n @property({ reflect: true })\n public label = '';\n\n @property({ type: Boolean, reflect: true })\n public selected = false;\n\n @property({ type: Boolean, reflect: true })\n public vertical = false;\n\n @property({ type: String, reflect: true })\n public value = '';\n\n protected override render(): TemplateResult {\n return html`\n ${this.hasIcon\n ? html`\n <slot name=\"icon\"></slot>\n `\n : nothing}\n <label id=\"item-label\" ?hidden=${!this.hasLabel}>\n ${this.slotHasContent ? nothing : this.label}\n <slot>${this.label}</slot>\n </label>\n `;\n }\n\n protected override firstUpdated(changes: PropertyValues): void {\n super.firstUpdated(changes);\n this.setAttribute('role', 'tab');\n if (!this.hasAttribute('id')) {\n this.id = `sp-tab-${randomID()}`;\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('selected')) {\n this.setAttribute('aria-selected', this.selected ? 'true' : 'false');\n this.setAttribute('tabindex', this.selected ? '0' : '-1');\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 }\n}\n"],
|
|
5
5
|
"mappings": "qNAYA,OAEE,QAAAA,EACA,WAAAC,EAEA,mBAAAC,MAEK,gCACP,OAAS,YAAAC,MAAgB,kDACzB,OAAS,6BAAAC,MAAiC,uDAC1C,OAAS,uBAAAC,MAA2B,+DACpC,OAAS,mBAAAC,MAAuB,2DAChC,OAAS,YAAAC,MAAgB,mDAEzB,OAAOC,MAAmB,eAQnB,aAAM,YAAYJ,EACvBE,EAAgBD,EAAoBH,EAAiB,eAAe,EAAG,EAAE,CAC3E,CAAE,CAFK,kCAgBL,KAAO,SAAW,GAGlB,KAAO,MAAQ,GAGf,KAAO,SAAW,GAGlB,KAAO,SAAW,GAGlB,KAAO,MAAQ,GAzBf,WAA2B,QAAyB,CAClD,MAAO,CAACM,CAAa,CACvB,CAEA,IAAc,SAAmB,CAC/B,OAAO,KAAK,oBACd,CAEA,IAAc,UAAoB,CAChC,MAAO,CAAC,CAAC,KAAK,OAAS,KAAK,cAC9B,CAiBmB,QAAyB,CAC1C,OAAOR;AAAA,QACH,KAAK,QACHA;AAAA;AAAA,YAGAC,CAAO;AAAA,uCACsB,CAAC,KAAK,QAAQ;AAAA,UAC3C,KAAK,eAAiBA,EAAU,KAAK,KAAK;AAAA,gBACpC,KAAK,KAAK;AAAA;AAAA,KAGxB,CAEmB,aAAaQ,EAA+B,CAC7D,MAAM,aAAaA,CAAO,EAC1B,KAAK,aAAa,OAAQ,KAAK,EAC1B,KAAK,aAAa,IAAI,IACzB,KAAK,GAAK,UAAUF,EAAS,CAAC,GAElC,CAEmB,QAAQE,EAA+B,CACxD,MAAM,QAAQA,CAAO,EACjBA,EAAQ,IAAI,UAAU,IACxB,KAAK,aAAa,gBAAiB,KAAK,SAAW,OAAS,OAAO,EACnE,KAAK,aAAa,WAAY,KAAK,SAAW,IAAM,IAAI,GAEtDA,EAAQ,IAAI,UAAU,IACpB,KAAK,SACP,KAAK,aAAa,gBAAiB,MAAM,EAEzC,KAAK,gBAAgB,eAAe,EAG1C,CACF,CAlDSC,EAAA,CADNP,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,GAf/B,IAgBJ,wBAGAO,EAAA,CADNP,EAAS,CAAE,QAAS,EAAK,CAAC,GAlBhB,IAmBJ,qBAGAO,EAAA,CADNP,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,GArB/B,IAsBJ,wBAGAO,EAAA,CADNP,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,GAxB/B,IAyBJ,wBAGAO,EAAA,CADNP,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,GA3B9B,IA4BJ",
|
|
6
6
|
"names": ["html", "nothing", "SpectrumElement", "property", "FocusVisiblePolyfillMixin", "ObserveSlotPresence", "ObserveSlotText", "randomID", "tabItemStyles", "changes", "__decorateClass"]
|
|
7
7
|
}
|
package/src/TabPanel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/src/TabPanel.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["TabPanel.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n html,\n PropertyValues,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport { property } from '@spectrum-web-components/base/src/decorators.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport panelStyles from './tab-panel.css.js';\n\n/**\n * @element sp-tab-panel\n *\n * @slot - content of the Tab Panel\n */\nexport class TabPanel extends SpectrumElement {\n static override styles = [panelStyles];\n\n @property({ type: Boolean, reflect: true })\n public selected = false;\n\n @property({ type: String, reflect: true })\n public value = '';\n\n protected handleFocusin(): void {\n this.removeAttribute('tabindex');\n }\n\n protected handleFocusout(): void {\n this.tabIndex = this.selected ? 0 : -1;\n }\n\n protected override render(): TemplateResult {\n return html`\n <slot\n @focusin=${this.handleFocusin}\n @focusout=${this.handleFocusout}\n ></slot>\n `;\n }\n\n protected override firstUpdated(): void {\n this.slot = 'tab-panel';\n this.setAttribute('role', 'tabpanel');\n this.tabIndex = 0;\n if (!this.hasAttribute('id')) {\n this.id = `sp-tab-panel-${randomID()}`;\n }\n }\n\n protected override updated(changes: PropertyValues<this>): void {\n if (changes.has('selected')) {\n if (this.selected) {\n this.removeAttribute('aria-hidden');\n this.tabIndex = 0;\n } else {\n this.setAttribute('aria-hidden', 'true');\n this.tabIndex = -1;\n }\n }\n }\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;AAYA;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;AACP,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AAEzB,OAAO,iBAAiB;AAOjB,aAAM,iBAAiB,gBAAgB;AAAA,EAAvC;AAAA;AAIL,SAAO,WAAW;AAGlB,SAAO,QAAQ;AAAA;AAAA,EAEL,gBAAsB;AAC9B,SAAK,gBAAgB,UAAU;AAAA,EACjC;AAAA,EAEU,iBAAuB;AAC/B,SAAK,WAAW,KAAK,WAAW,IAAI;AAAA,EACtC;AAAA,EAEmB,SAAyB;AAC1C,WAAO;AAAA;AAAA,mBAEQ,KAAK,aAAa;AAAA,oBACjB,KAAK,cAAc;AAAA;AAAA;AAAA,EAGrC;AAAA,EAEmB,eAAqB;AACtC,SAAK,OAAO;AACZ,SAAK,aAAa,QAAQ,UAAU;AACpC,SAAK,WAAW;AAChB,QAAI,CAAC,KAAK,aAAa,IAAI,GAAG;AAC5B,WAAK,KAAK,gBAAgB,SAAS,CAAC;AAAA,IACtC;AAAA,EACF;AAAA,EAEmB,QAAQ,SAAqC;AAC9D,QAAI,QAAQ,IAAI,UAAU,GAAG;AAC3B,UAAI,KAAK,UAAU;AACjB,aAAK,gBAAgB,aAAa;AAClC,aAAK,WAAW;AAAA,MAClB,OAAO;AACL,aAAK,aAAa,eAAe,MAAM;AACvC,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACF;AA9Ca,SACK,SAAS,CAAC,WAAW;AAG9B;AAAA,EADN,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAH/B,SAIJ;AAGA;AAAA,EADN,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAN9B,SAOJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/TabPanel.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["TabPanel.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n html,\n PropertyValues,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport { property } from '@spectrum-web-components/base/src/decorators.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport panelStyles from './tab-panel.css.js';\n\n/**\n * @element sp-tab-panel\n *\n * @slot - content of the Tab Panel\n */\nexport class TabPanel extends SpectrumElement {\n static override styles = [panelStyles];\n\n @property({ type: Boolean, reflect: true })\n public selected = false;\n\n @property({ type: String, reflect: true })\n public value = '';\n\n protected handleFocusin(): void {\n this.removeAttribute('tabindex');\n }\n\n protected handleFocusout(): void {\n this.tabIndex = this.selected ? 0 : -1;\n }\n\n protected override render(): TemplateResult {\n return html`\n <slot\n @focusin=${this.handleFocusin}\n @focusout=${this.handleFocusout}\n ></slot>\n `;\n }\n\n protected override firstUpdated(): void {\n this.slot = 'tab-panel';\n this.setAttribute('role', 'tabpanel');\n this.tabIndex = 0;\n if (!this.hasAttribute('id')) {\n this.id = `sp-tab-panel-${randomID()}`;\n }\n }\n\n protected override updated(changes: PropertyValues<this>): void {\n if (changes.has('selected')) {\n if (this.selected) {\n this.removeAttribute('aria-hidden');\n this.tabIndex = 0;\n } else {\n this.setAttribute('aria-hidden', 'true');\n this.tabIndex = -1;\n }\n }\n }\n}\n"],
|
|
5
5
|
"mappings": "qNAYA,OACE,QAAAA,EAEA,mBAAAC,MAEK,gCACP,OAAS,YAAAC,MAAgB,kDACzB,OAAS,YAAAC,MAAgB,mDAEzB,OAAOC,MAAiB,qBAOjB,aAAM,iBAAiBH,CAAgB,CAAvC,kCAIL,KAAO,SAAW,GAGlB,KAAO,MAAQ,GAEL,eAAsB,CAC9B,KAAK,gBAAgB,UAAU,CACjC,CAEU,gBAAuB,CAC/B,KAAK,SAAW,KAAK,SAAW,EAAI,EACtC,CAEmB,QAAyB,CAC1C,OAAOD;AAAA;AAAA,mBAEQ,KAAK,aAAa;AAAA,oBACjB,KAAK,cAAc;AAAA;AAAA,KAGrC,CAEmB,cAAqB,CACtC,KAAK,KAAO,YACZ,KAAK,aAAa,OAAQ,UAAU,EACpC,KAAK,SAAW,EACX,KAAK,aAAa,IAAI,IACzB,KAAK,GAAK,gBAAgBG,EAAS,CAAC,GAExC,CAEmB,QAAQE,EAAqC,CAC1DA,EAAQ,IAAI,UAAU,IACpB,KAAK,UACP,KAAK,gBAAgB,aAAa,EAClC,KAAK,SAAW,IAEhB,KAAK,aAAa,cAAe,MAAM,EACvC,KAAK,SAAW,IAGtB,CACF,CA9Ca,SACK,OAAS,CAACD,CAAW,EAG9BE,EAAA,CADNJ,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,GAH/B,SAIJ,wBAGAI,EAAA,CADNJ,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,GAN9B,SAOJ",
|
|
6
6
|
"names": ["html", "SpectrumElement", "property", "randomID", "panelStyles", "changes", "__decorateClass"]
|
|
7
7
|
}
|
package/src/Tabs.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -85,6 +85,7 @@ export declare class Tabs extends Tabs_base {
|
|
|
85
85
|
private limitDeltaToInterval;
|
|
86
86
|
/**
|
|
87
87
|
* Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.
|
|
88
|
+
*
|
|
88
89
|
* @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.
|
|
89
90
|
* @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.
|
|
90
91
|
*/
|
package/src/Tabs.dev.js
CHANGED
|
@@ -213,6 +213,7 @@ export class Tabs extends SizedMixin(Focusable, { noDefaultSize: true }) {
|
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
215
|
* Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.
|
|
216
|
+
*
|
|
216
217
|
* @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.
|
|
217
218
|
* @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.
|
|
218
219
|
*/
|
package/src/Tabs.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright 2025 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\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 { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\nimport { Focusable } from '@spectrum-web-components/shared';\n\nimport { Tab } from './Tab.dev.js'\nimport { TabPanel } from './TabPanel.dev.js'\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.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([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: CSSStyleDeclaration['direction'],\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: CSSStyleDeclaration['direction'],\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 direction: 'vertical' | 'vertical-right' | 'horizontal' = '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) {\n return;\n }\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.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) {\n return;\n }\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !this.disabled && !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 private limitDeltaToInterval(min: number, max: number) {\n return (delta: number): number => {\n if (delta < min) {\n return min;\n }\n if (delta > max) {\n return max;\n }\n return delta;\n };\n }\n\n /**\n * Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.\n * @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.\n * @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.\n */\n public scrollTabs(delta: number, behavior: ScrollBehavior = 'smooth'): void {\n if (delta === 0) {\n return;\n }\n\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const dirLimit = scrollWidth - clientWidth - Math.abs(scrollLeft);\n\n const limitDelta =\n this.dir === 'ltr'\n ? this.limitDeltaToInterval(-scrollLeft, dirLimit)\n : this.limitDeltaToInterval(-dirLimit, Math.abs(scrollLeft));\n\n this.tabList?.scrollBy({\n left: limitDelta(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: this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight: 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(changedProperties: PropertyValueMap<this>): 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(this.shouldAnimate ? undefined : 'first-position')}\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(':scope > [selected]') 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) {\n previous.selected = false;\n }\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) {\n next.selected = true;\n }\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('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((el) => el.value === this.selected);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.addEventListener('loadingdone', this.updateSelectionIndicator);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.removeEventListener('loadingdone', this.updateSelectionIndicator);\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAYA,SAAS,8BAA8B;AACvC,SAAS,wBAAwB;AAEjC;AAAA,EACE;AAAA,EAGA;AAAA,EAGA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,gCAAgC;AACzC,SAAS,iBAAiB;AAI1B,OAAO,eAAe;AACtB,OAAO,cAAc;AAGd,aAAM,kBAAkB;AAAA,EAC7B,UAAU;AAAA,EACV,kBAAkB;AAAA,EAElB,WAAW,MAAc,OAAuB;AAC9C,UAAM,QAAQ,QAAQ,KAAK;AAC3B,WAAO,yBAAyB,IAAI,cAAc,KAAK;AAAA,EACzD;AAAA,EAEA,WAAW,KAAa,QAAwB;AAC9C,UAAM,QAAQ,SAAS,KAAK;AAC5B,WAAO,yBAAyB,GAAG,cAAc,KAAK;AAAA,EACxD;AAAA,EAEA,aAAwB;AACtB,WAAO;AAAA;AAAA;AAAA,kBAGO,KAAK,QAAQ;AAAA;AAAA;AAAA,iBAGd,KAAK,QAAQ;AAAA;AAAA;AAAA,EAG5B;AACF;AAMO,gBAAS,kCACd,OACA,WACA,MACA,WACQ;AACR,QAAM,YAAY,SAAS,cAAc,QAAQ,KAAK;AACtD,QAAM,UAAU,KAAK,SAAS;AAC9B,QAAM,cAAc,UAAU,aAAa,UAAU;AACrD,SAAO,UAAU,QAAQ,aAAa,UAAU,cAAc;AAChE;AAMO,gBAAS,iCACd,OACA,WACA,MACA,WACQ;AACR,QAAM,YAAY,SAAS,cAAc,QAAQ,IAAI;AACrD,QAAM,UAAU,KAAK,SAAS;AAC9B,QAAM,kBAAkB,cAAc,QAAQ,CAAC,UAAU,cAAc;AACvE,SAAO,UAAU,QAAQ,aAAa,QAAQ,cAAc;AAC9D;AAWO,aAAM,aAAa,WAAW,WAAW,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,EA2EvE,cAAc;AACZ,UAAM;AA9DR,SAAO,OAAO;AAMd,SAAO,UAAU;AAGjB,SAAO,YAA0D;AAGjE,SAAO,aAAa;AAGpB,SAAO,QAAQ;AAGf,SAAO,mBAAmB;AAM1B,SAAO,QAAQ;AAGf,SAAO,0BAA0B,gBAAgB;AAGjD,SAAO,gBAAgB;AASvB,oBAAW;AAoBX,SAAQ,QAAe,CAAC;AAgBxB,SAAU,mBAAmB,IAAI,iBAAiB,MAAM;AAAA,MACtD,UAAU,MAAM;AACd,aAAK,yBAAyB;AAAA,MAChC;AAAA,IACF,CAAC;AAED,oCAA2B,IAAI,yBAA8B,MAAM;AAAA,MACjE,cAAc,CAAC,aAAa;AAC1B,YAAI,eAAe;AACnB,cAAM,wBAAwB,SAAS,KAAK,CAAC,IAAI,UAAU;AACzD,gBAAM,iBAAiB,KAAK,WACxB,GAAG,UAAU,KAAK,WAClB,CAAC,GAAG;AACR,yBAAe;AACf,iBAAO;AAAA,QACT,CAAC;AACD,eAAO,wBAAwB,eAAe;AAAA,MAChD;AAAA,MACA,WAAW,MAAM;AAAA,MACjB,oBAAoB,CAAC,OAAO;AAC1B,YAAI,CAAC,KAAK,MAAM;AACd;AAAA,QACF;AAEA,aAAK,gBAAgB;AACrB,aAAK,aAAa,EAAE;AAAA,MACtB;AAAA,MACA,UAAU,MAAM,KAAK;AAAA,MACrB,oBAAoB,CAAC,OAAO,CAAC,KAAK,YAAY,CAAC,GAAG;AAAA,MAClD,eAAe,MAAM,KAAK;AAAA,IAC5B,CAAC;
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\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 { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\nimport { Focusable } from '@spectrum-web-components/shared';\n\nimport { Tab } from './Tab.dev.js'\nimport { TabPanel } from './TabPanel.dev.js'\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.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([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: CSSStyleDeclaration['direction'],\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: CSSStyleDeclaration['direction'],\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 direction: 'vertical' | 'vertical-right' | 'horizontal' = '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) {\n return;\n }\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.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) {\n return;\n }\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !this.disabled && !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 private limitDeltaToInterval(min: number, max: number) {\n return (delta: number): number => {\n if (delta < min) {\n return min;\n }\n if (delta > max) {\n return max;\n }\n return delta;\n };\n }\n\n /**\n * Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.\n *\n * @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.\n * @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.\n */\n public scrollTabs(delta: number, behavior: ScrollBehavior = 'smooth'): void {\n if (delta === 0) {\n return;\n }\n\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const dirLimit = scrollWidth - clientWidth - Math.abs(scrollLeft);\n\n const limitDelta =\n this.dir === 'ltr'\n ? this.limitDeltaToInterval(-scrollLeft, dirLimit)\n : this.limitDeltaToInterval(-dirLimit, Math.abs(scrollLeft));\n\n this.tabList?.scrollBy({\n left: limitDelta(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: this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight: 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(changedProperties: PropertyValueMap<this>): 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(this.shouldAnimate ? undefined : 'first-position')}\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(':scope > [selected]') 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) {\n previous.selected = false;\n }\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) {\n next.selected = true;\n }\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('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((el) => el.value === this.selected);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.addEventListener('loadingdone', this.updateSelectionIndicator);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.removeEventListener('loadingdone', this.updateSelectionIndicator);\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/Tabs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tabs.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright 2025 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\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 { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\nimport { Focusable } from '@spectrum-web-components/shared';\n\nimport { Tab } from './Tab.js';\nimport { TabPanel } from './TabPanel.js';\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.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([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: CSSStyleDeclaration['direction'],\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: CSSStyleDeclaration['direction'],\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 direction: 'vertical' | 'vertical-right' | 'horizontal' = '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) {\n return;\n }\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.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) {\n return;\n }\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !this.disabled && !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 private limitDeltaToInterval(min: number, max: number) {\n return (delta: number): number => {\n if (delta < min) {\n return min;\n }\n if (delta > max) {\n return max;\n }\n return delta;\n };\n }\n\n /**\n * Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.\n * @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.\n * @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.\n */\n public scrollTabs(delta: number, behavior: ScrollBehavior = 'smooth'): void {\n if (delta === 0) {\n return;\n }\n\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const dirLimit = scrollWidth - clientWidth - Math.abs(scrollLeft);\n\n const limitDelta =\n this.dir === 'ltr'\n ? this.limitDeltaToInterval(-scrollLeft, dirLimit)\n : this.limitDeltaToInterval(-dirLimit, Math.abs(scrollLeft));\n\n this.tabList?.scrollBy({\n left: limitDelta(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: this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight: 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(changedProperties: PropertyValueMap<this>): 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(this.shouldAnimate ? undefined : 'first-position')}\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(':scope > [selected]') 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) {\n previous.selected = false;\n }\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) {\n next.selected = true;\n }\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('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((el) => el.value === this.selected);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.addEventListener('loadingdone', this.updateSelectionIndicator);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.removeEventListener('loadingdone', this.updateSelectionIndicator);\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": "qNAYA,OAAS,0BAAAA,MAA8B,iDACvC,OAAS,oBAAAC,MAAwB,2CAEjC,OACE,OAAAC,EAGA,QAAAC,EAGA,cAAAC,MAEK,gCACP,OACE,YAAAC,EACA,SAAAC,MACK,kDACP,OACE,YAAAC,EACA,aAAAC,MACK,kDACP,OAAS,4BAAAC,MAAgC,sEACzC,OAAS,aAAAC,MAAiB,kCAI1B,OAAOC,MAAe,gBACtB,OAAOC,MAAc,sBAGd,aAAM,gBAAkB,CAC7B,SAAU,IACV,iBAAkB,iDAElB,WAAWC,EAAcC,EAAuB,CAC9C,MAAMC,EAAQD,EAAQ,KAAK,SAC3B,MAAO,yBAAyBD,CAAI,cAAcE,CAAK,IACzD,EAEA,WAAWC,EAAaC,EAAwB,CAC9C,MAAMF,EAAQE,EAAS,KAAK,SAC5B,MAAO,yBAAyBD,CAAG,cAAcD,CAAK,IACxD,EAEA,YAAwB,CACtB,OAAOb;AAAA;AAAA;AAAA,kBAGO,KAAK,QAAQ;AAAA;AAAA;AAAA,iBAGd,KAAK,QAAQ;AAAA;AAAA,KAG5B,CACF,EAMO,gBAAS,kCACdgB,EACAC,EACAC,EACAC,EACQ,CACR,MAAMC,EAAYJ,GAASC,IAAc,MAAQ,GAAK,GAChDI,EAAUH,EAAKE,CAAS,EACxBE,EAAcH,EAAU,WAAaA,EAAU,YACrD,OAAOE,EAAUA,EAAQ,WAAaF,EAAU,YAAcG,CAChE,CAMO,gBAAS,iCACdN,EACAC,EACAC,EACAC,EACQ,CACR,MAAMI,EAAYP,GAASC,IAAc,MAAQ,EAAI,IAC/CO,EAAUN,EAAKK,CAAS,EACxBE,EAAkBR,IAAc,MAAQ,CAACE,EAAU,YAAc,EACvE,OAAOK,EAAUA,EAAQ,WAAaA,EAAQ,YAAcC,CAC9D,CAWO,aAAM,aAAavB,EAAWM,EAAW,CAAE,cAAe,EAAK,CAAC,CAAE,CA2EvE,aAAc,CACZ,MAAM,EA9DR,KAAO,KAAO,GAMd,KAAO,QAAU,GAGjB,KAAO,UAA0D,aAGjE,KAAO,WAAa,GAGpB,KAAO,MAAQ,GAGf,KAAO,iBAAmB,GAM1B,KAAO,MAAQ,GAGf,KAAO,wBAA0B,gBAAgB,iBAGjD,KAAO,cAAgB,GASvB,cAAW,GAoBX,KAAQ,MAAe,CAAC,EAgBxB,KAAU,iBAAmB,IAAIT,EAAiB,KAAM,CACtD,SAAU,IAAM,CACd,KAAK,yBAAyB,CAChC,CACF,CAAC,EAED,8BAA2B,IAAIQ,EAA8B,KAAM,CACjE,aAAemB,GAAa,CAC1B,IAAIC,EAAe,EAQnB,OAP8BD,EAAS,KAAK,CAACE,EAAIZ,IAAU,CACzD,MAAMa,EAAiB,KAAK,SACxBD,EAAG,QAAU,KAAK,SAClB,CAACA,EAAG,SACR,OAAAD,EAAeX,EACRa,CACT,CAAC,EAC8BF,EAAe,EAChD,EACA,UAAW,IAAM,OACjB,mBAAqBC,GAAO,CACrB,KAAK,OAIV,KAAK,cAAgB,GACrB,KAAK,aAAaA,CAAE,EACtB,EACA,SAAU,IAAM,KAAK,KACrB,mBAAqBA,GAAO,CAAC,KAAK,UAAY,CAACA,EAAG,SAClD,cAAe,IAAM,KAAK,OAC5B,CAAC,
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { IntersectionController } from '@lit-labs/observers/intersection-controller.js';\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\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 { RovingTabindexController } from '@spectrum-web-components/reactive-controllers/src/RovingTabindex.js';\nimport { Focusable } from '@spectrum-web-components/shared';\n\nimport { Tab } from './Tab.js';\nimport { TabPanel } from './TabPanel.js';\nimport tabStyles from './tabs.css.js';\nimport tabSizes from './tabs-sizes.css.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([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: CSSStyleDeclaration['direction'],\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: CSSStyleDeclaration['direction'],\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 direction: 'vertical' | 'vertical-right' | 'horizontal' = '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) {\n return;\n }\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.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) {\n return;\n }\n\n this.shouldAnimate = true;\n this.selectTarget(el);\n },\n elements: () => this.tabs,\n isFocusableElement: (el) => !this.disabled && !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 private limitDeltaToInterval(min: number, max: number) {\n return (delta: number): number => {\n if (delta < min) {\n return min;\n }\n if (delta > max) {\n return max;\n }\n return delta;\n };\n }\n\n /**\n * Scrolls through the tabs component, on the X-axis, by a given ammount of pixels/ delta. The given delta is limited to the scrollable area of the tabs component.\n *\n * @param {number} delta - The ammount of pixels to scroll by. If the value is positive, the tabs will scroll to the right. If the value is negative, the tabs will scroll to the left.\n * @param {ScrollBehavior} behavior - The scroll behavior to use. Defaults to 'smooth'.\n */\n public scrollTabs(delta: number, behavior: ScrollBehavior = 'smooth'): void {\n if (delta === 0) {\n return;\n }\n\n const { scrollLeft, clientWidth, scrollWidth } = this.tabList;\n const dirLimit = scrollWidth - clientWidth - Math.abs(scrollLeft);\n\n const limitDelta =\n this.dir === 'ltr'\n ? this.limitDeltaToInterval(-scrollLeft, dirLimit)\n : this.limitDeltaToInterval(-dirLimit, Math.abs(scrollLeft));\n\n this.tabList?.scrollBy({\n left: limitDelta(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: this.dir === 'ltr' ? canScrollLeft : canScrollRight,\n canScrollRight: 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(changedProperties: PropertyValueMap<this>): 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(this.shouldAnimate ? undefined : 'first-position')}\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(':scope > [selected]') 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) {\n previous.selected = false;\n }\n }\n const next = this.querySelector(\n `[role=\"tabpanel\"][value=\"${this.selected}\"]`\n ) as TabPanel;\n if (next) {\n next.selected = true;\n }\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('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((el) => el.value === this.selected);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.addEventListener('loadingdone', this.updateSelectionIndicator);\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: (name: string, callback: () => void) => void;\n };\n }\n ).fonts.removeEventListener('loadingdone', this.updateSelectionIndicator);\n }\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["IntersectionController", "ResizeController", "css", "html", "SizedMixin", "property", "query", "classMap", "ifDefined", "RovingTabindexController", "Focusable", "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", "min", "max", "delta", "behavior", "_a", "scrollLeft", "clientWidth", "scrollWidth", "dirLimit", "limitDelta", "canScrollLeft", "canScrollRight", "complete", "tabUpdateCompletes", "selectedTab", "selectionEnd", "selectionStart", "viewportStart", "selectedIndex", "scrollTarget", "changedProperties", "panel", "value", "id", "changes", "selectedChild", "previous", "next", "selected", "__decorateClass"]
|
|
7
7
|
}
|
package/src/TabsOverflow.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["TabsOverflow.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAWA,SAAS,wBAAwB;AAEjC;AAAA,EAEE;AAAA,EAEA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,OAAO,uBAAuB;AAE9B,OAAO;AACP,OAAO;AAGP,OAAO,YAAY;AACnB,OAAO,cAAc;
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\n\nimport {\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { classMap } from '@spectrum-web-components/base/src/directives.js';\nimport chevronIconStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';\n\nimport '@spectrum-web-components/action-button/sp-action-button.js';\nimport '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';\n\nimport { Tabs } from './Tabs.dev.js'\nimport styles from './tabs-overflow.css.js';\nimport tabSizes from './tabs-sizes.css.js';\n\ninterface TabsOverflowState {\n canScrollLeft: boolean;\n canScrollRight: boolean;\n}\n\n/**\n * @element sp-tabs-overflow\n */\nexport class TabsOverflow extends SizedMixin(SpectrumElement) {\n public static override get styles(): CSSResultArray {\n return [styles, tabSizes, chevronIconStyles];\n }\n\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ type: String, attribute: 'label-previous' })\n public labelPrevious = 'Scroll to previous tabs';\n\n @property({ type: String, attribute: 'label-next' })\n public labelNext = 'Scroll to next tabs';\n\n @state()\n private overflowState: TabsOverflowState = {\n canScrollLeft: false,\n canScrollRight: false,\n };\n\n @queryAssignedElements({ selector: 'sp-tabs', flatten: true })\n private tabs!: Tabs[];\n\n @query('.tabs-overflow-container')\n private overflowContainer!: HTMLDivElement;\n\n resizeController!: ResizeController;\n\n protected get scrollContent(): Tabs[] {\n return this.tabs;\n }\n\n public constructor() {\n super();\n this.resizeController = new ResizeController(this, {\n target: this,\n callback: (): void => {\n this._updateScrollState();\n },\n });\n }\n\n protected override firstUpdated(changes: PropertyValues): void {\n super.firstUpdated(changes);\n // enable scroll event\n const [tabs] = this.scrollContent;\n if (tabs) {\n tabs.enableTabsScroll = true;\n }\n this.resizeController.observe(this.overflowContainer);\n }\n\n private async _handleSlotChange(): Promise<void> {\n const [tabsElement] = this.scrollContent;\n await tabsElement?.updateComplete;\n this._updateScrollState();\n }\n\n private _updateScrollState(): void {\n const { scrollContent, overflowState } = this;\n\n if (scrollContent) {\n const [tabsElement] = this.scrollContent;\n const { canScrollLeft, canScrollRight } = tabsElement?.scrollState || {\n canScrollLeft: false,\n canScrollRight: false,\n };\n\n this.overflowState = {\n ...overflowState,\n canScrollLeft,\n canScrollRight,\n };\n }\n }\n\n private scrollFactor = 0.5;\n private _handleScrollClick(event: MouseEvent): void {\n const currentTarget = event.currentTarget as HTMLElement;\n const [tabsElement] = this.scrollContent;\n\n const dist = tabsElement.clientWidth * this.scrollFactor;\n const left = currentTarget.classList.contains('left-scroll') ? -dist : dist;\n tabsElement.scrollTabs(left, 'smooth');\n this._updateScrollState();\n }\n\n protected override render(): TemplateResult {\n const { canScrollRight, canScrollLeft } = this.overflowState;\n const ariaLabelPrevious = this.labelPrevious;\n const ariaLabelNext = this.labelNext;\n return html`\n <div\n class=${classMap({\n 'tabs-overflow-container': true,\n 'left-shadow': canScrollLeft,\n 'right-shadow': canScrollRight,\n })}\n >\n <sp-action-button\n class=${classMap({\n 'left-scroll': true,\n show: canScrollLeft,\n })}\n aria-label=${ariaLabelPrevious}\n quiet\n tabindex=\"-1\"\n @click=${this._handleScrollClick}\n >\n <sp-icon-chevron100\n slot=\"icon\"\n class=\"spectrum-UIIcon-ChevronLeft300\"\n ></sp-icon-chevron100>\n </sp-action-button>\n <sp-action-button\n class=${classMap({\n 'right-scroll': true,\n show: canScrollRight,\n })}\n aria-label=${ariaLabelNext}\n quiet\n tabindex=\"-1\"\n @click=${this._handleScrollClick}\n >\n <sp-icon-chevron100\n slot=\"icon\"\n class=\"spectrum-UIIcon-ChevronRight300\"\n ></sp-icon-chevron100>\n </sp-action-button>\n <slot\n @slotchange=${this._handleSlotChange}\n @sp-tabs-scroll=${this._updateScrollState}\n ></slot>\n </div>\n `;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/TabsOverflow.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["TabsOverflow.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
5
|
-
"mappings": "qNAWA,OAAS,oBAAAA,MAAwB,2CAEjC,OAEE,QAAAC,EAEA,cAAAC,EACA,mBAAAC,MAEK,gCACP,OACE,YAAAC,EACA,SAAAC,EACA,yBAAAC,EACA,SAAAC,MACK,kDACP,OAAS,YAAAC,MAAgB,kDACzB,OAAOC,MAAuB,iEAE9B,MAAO,6DACP,MAAO,gEAGP,OAAOC,MAAY,yBACnB,OAAOC,MAAc,
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nimport { ResizeController } from '@lit-labs/observers/resize-controller.js';\n\nimport {\n CSSResultArray,\n html,\n PropertyValues,\n SizedMixin,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { classMap } from '@spectrum-web-components/base/src/directives.js';\nimport chevronIconStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';\n\nimport '@spectrum-web-components/action-button/sp-action-button.js';\nimport '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';\n\nimport { Tabs } from './Tabs.js';\nimport styles from './tabs-overflow.css.js';\nimport tabSizes from './tabs-sizes.css.js';\n\ninterface TabsOverflowState {\n canScrollLeft: boolean;\n canScrollRight: boolean;\n}\n\n/**\n * @element sp-tabs-overflow\n */\nexport class TabsOverflow extends SizedMixin(SpectrumElement) {\n public static override get styles(): CSSResultArray {\n return [styles, tabSizes, chevronIconStyles];\n }\n\n @property({ type: Boolean, reflect: true })\n public compact = false;\n\n @property({ type: String, attribute: 'label-previous' })\n public labelPrevious = 'Scroll to previous tabs';\n\n @property({ type: String, attribute: 'label-next' })\n public labelNext = 'Scroll to next tabs';\n\n @state()\n private overflowState: TabsOverflowState = {\n canScrollLeft: false,\n canScrollRight: false,\n };\n\n @queryAssignedElements({ selector: 'sp-tabs', flatten: true })\n private tabs!: Tabs[];\n\n @query('.tabs-overflow-container')\n private overflowContainer!: HTMLDivElement;\n\n resizeController!: ResizeController;\n\n protected get scrollContent(): Tabs[] {\n return this.tabs;\n }\n\n public constructor() {\n super();\n this.resizeController = new ResizeController(this, {\n target: this,\n callback: (): void => {\n this._updateScrollState();\n },\n });\n }\n\n protected override firstUpdated(changes: PropertyValues): void {\n super.firstUpdated(changes);\n // enable scroll event\n const [tabs] = this.scrollContent;\n if (tabs) {\n tabs.enableTabsScroll = true;\n }\n this.resizeController.observe(this.overflowContainer);\n }\n\n private async _handleSlotChange(): Promise<void> {\n const [tabsElement] = this.scrollContent;\n await tabsElement?.updateComplete;\n this._updateScrollState();\n }\n\n private _updateScrollState(): void {\n const { scrollContent, overflowState } = this;\n\n if (scrollContent) {\n const [tabsElement] = this.scrollContent;\n const { canScrollLeft, canScrollRight } = tabsElement?.scrollState || {\n canScrollLeft: false,\n canScrollRight: false,\n };\n\n this.overflowState = {\n ...overflowState,\n canScrollLeft,\n canScrollRight,\n };\n }\n }\n\n private scrollFactor = 0.5;\n private _handleScrollClick(event: MouseEvent): void {\n const currentTarget = event.currentTarget as HTMLElement;\n const [tabsElement] = this.scrollContent;\n\n const dist = tabsElement.clientWidth * this.scrollFactor;\n const left = currentTarget.classList.contains('left-scroll') ? -dist : dist;\n tabsElement.scrollTabs(left, 'smooth');\n this._updateScrollState();\n }\n\n protected override render(): TemplateResult {\n const { canScrollRight, canScrollLeft } = this.overflowState;\n const ariaLabelPrevious = this.labelPrevious;\n const ariaLabelNext = this.labelNext;\n return html`\n <div\n class=${classMap({\n 'tabs-overflow-container': true,\n 'left-shadow': canScrollLeft,\n 'right-shadow': canScrollRight,\n })}\n >\n <sp-action-button\n class=${classMap({\n 'left-scroll': true,\n show: canScrollLeft,\n })}\n aria-label=${ariaLabelPrevious}\n quiet\n tabindex=\"-1\"\n @click=${this._handleScrollClick}\n >\n <sp-icon-chevron100\n slot=\"icon\"\n class=\"spectrum-UIIcon-ChevronLeft300\"\n ></sp-icon-chevron100>\n </sp-action-button>\n <sp-action-button\n class=${classMap({\n 'right-scroll': true,\n show: canScrollRight,\n })}\n aria-label=${ariaLabelNext}\n quiet\n tabindex=\"-1\"\n @click=${this._handleScrollClick}\n >\n <sp-icon-chevron100\n slot=\"icon\"\n class=\"spectrum-UIIcon-ChevronRight300\"\n ></sp-icon-chevron100>\n </sp-action-button>\n <slot\n @slotchange=${this._handleSlotChange}\n @sp-tabs-scroll=${this._updateScrollState}\n ></slot>\n </div>\n `;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["ResizeController", "html", "SizedMixin", "SpectrumElement", "property", "query", "queryAssignedElements", "state", "classMap", "chevronIconStyles", "styles", "tabSizes", "changes", "tabs", "tabsElement", "scrollContent", "overflowState", "canScrollLeft", "canScrollRight", "event", "currentTarget", "dist", "left", "ariaLabelPrevious", "ariaLabelNext", "__decorateClass"]
|
|
7
7
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
package/src/index.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport * from './Tabs.dev.js'\nexport * from './Tab.dev.js'\nexport * from './TabPanel.dev.js'\nexport * from './TabsOverflow.dev.js'\n"],
|
|
5
5
|
"mappings": ";AAYA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport * from './Tabs.js';\nexport * from './Tab.js';\nexport * from './TabPanel.js';\nexport * from './TabsOverflow.js';\n"],
|
|
5
5
|
"mappings": "aAYA,WAAc,YACd,WAAc,WACd,WAAc,gBACd,WAAc",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|