kempo 2.15.0 → 2.15.1

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.
@@ -1 +1 @@
1
- import Component from"./Component.js";import{dispatchEvent}from"../utils/element.js";const clickHandler=Symbol();export class Tab extends Component{constructor(){super(),this[clickHandler]=()=>{this.active||(this.tabs.active=this.for)},this.slot="tabs",this.registerAttribute("active",!1)}connectedCallback(){super.connectedCallback(),this.shadowRoot.getElementById("button").addEventListener("click",this[clickHandler])}get for(){const t=this.getAttribute("for");return t||this?.tabs.tabs.indexOf(this)}set for(t){t?this.setAttribute("for",t):this.removeAttribute("for")}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get shadowTemplate(){return`\n <button id="button">\n ${super.shadowTemplate}\n </button>\n `}get shadowStyles(){return"\n :host {\n margin-bottom: -1px;\n }\n #button {\n padding: var(--spacer_h);\n background-color: transparent;\n border: none;\n cursor: inherit;\n box-shadow: none;\n color: inherit;\n }\n :host(:not([active])) #button {\n cursor: pointer;\n }\n :host([active]){\n border-bottom: 2px solid var(--c_primary);\n margin-bottom: -1px;\n }\n :host([active]) #button {\n color: var(--tc_primary);\n }\n "}}window.customElements.define("k-tab",Tab);export class TabContent extends Component{constructor(){super(),this.registerAttribute("active",!1)}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get name(){const t=this.getAttribute("name");return t||this?.tabs.contents.indexOf(this)}set name(t){t?this.setAttribute("name",t):this.removeAttribute("name")}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n height: 100%;\n max-height: 100%;\n flex: 1 1 auto;\n overflow: hidden;\n }\n :host([active]) {\n display: block;\n }\n :host(:not([active])) {\n display: none;\n }\n `}}window.customElements.define("k-tab-content",TabContent);export class Tabs extends Component{constructor(){super(),this.registerAttribute("active","")}async connectedCallback(){await super.connectedCallback(),this.active||(this.active=`${this.querySelectorAll("k-tab-content")[0].name}`)}attributeChangedCallback(t,e,n){if("active"===t){const t=this.getActiveTab();t&&(t.active=!1);const e=this.getActiveContent();e&&(e.active=!1);const s=this.getTab(n);s&&(s.active=!0);const o=this.getContent(n);o&&(o.active=!0),dispatchEvent(this,"tab",{tab:n})}}get contents(){return[...this.querySelectorAll(":scope > k-tab-content")]}get tabs(){return[...this.querySelectorAll(":scope > k-tab")]}getTab(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab[for="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab")[n]}return e}getActiveTab(){return this.querySelector(':scope > k-tab[active="true"]')}getContent(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab-content[name="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab-content")[n]}return e}getActiveContent(){return this.querySelector(':scope > k-tab-content[active="true"]')}get shadowTemplate(){return`\n <div id="wrapper">\n <div id="tabs">\n <slot name="tabs"></slot>\n </div>\n <div id="contents">\n ${super.shadowTemplate}\n </div>\n </div>\n \n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n overflow: hidden;\n }\n #wrapper {\n display: flex;\n flex-direction: column;\n max-height: 100%;\n height: 100%;\n overflow: hidden;\n }\n #tabs {\n display: flex;\n border-bottom: 1px solid var(--c_border);\n padding: 0;\n margin-top: calc(0 - var(--spacer));\n align-items: flex-start;\n }\n #contents {\n display: flex;\n flex-direction: column;\n flex: 1;\n max-height: 100%;\n overflow: hidden\n }\n `}static observedAttributes=[...super.observedAttributes,"active"]}window.customElements.define("k-tabs",Tabs);export class TabSpacer extends Component{constructor(){super(),this.slot="tabs"}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n flex: 1 1 auto;\n height: 1px;\n }\n `}}window.customElements.define("k-tab-spacer",TabSpacer);export default{Tab:Tab,TabContent:TabContent,Tabs:Tabs,TabSpacer:TabSpacer};
1
+ import Component from"./Component.js";import{dispatchEvent}from"../utils/element.js";const clickHandler=Symbol();export class Tab extends Component{constructor(){super(),this[clickHandler]=()=>{this.active||(this.tabs.active=this.for)},this.slot="tabs",this.registerAttribute("active",!1)}connectedCallback(){super.connectedCallback(),this.shadowRoot.getElementById("button").addEventListener("click",this[clickHandler])}get for(){const t=this.getAttribute("for");return t||this?.tabs.tabs.indexOf(this)}set for(t){t?this.setAttribute("for",t):this.removeAttribute("for")}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get shadowTemplate(){return`\n <button id="button">\n ${super.shadowTemplate}\n </button>\n `}get shadowStyles(){return"\n :host {\n margin-bottom: -1px;\n }\n #button {\n padding: var(--spacer_h);\n background-color: transparent;\n border: none;\n cursor: inherit;\n box-shadow: none;\n color: inherit;\n }\n :host(:not([active])) #button {\n cursor: pointer;\n }\n :host([active]){\n border-bottom: 2px solid var(--c_primary);\n margin-bottom: -1px;\n }\n :host([active]) #button {\n color: var(--tc_primary);\n }\n "}}window.customElements.define("k-tab",Tab);export class TabContent extends Component{constructor(){super(),this.registerAttribute("active",!1)}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get name(){const t=this.getAttribute("name");return t||this?.tabs.contents.indexOf(this)}set name(t){t?this.setAttribute("name",t):this.removeAttribute("name")}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n height: 100%;\n max-height: 100%;\n flex: 1 1 auto;\n overflow: hidden;\n }\n :host([active]) {\n display: block;\n }\n :host(:not([active])) {\n display: none;\n }\n `}}window.customElements.define("k-tab-content",TabContent);export class Tabs extends Component{constructor(){super(),this.registerAttribute("active","")}async connectedCallback(){await super.connectedCallback(),this.active||(this.active=`${this.querySelectorAll("k-tab-content")[0].name}`);const t=this.shadowRoot.getElementById("tabs");t.addEventListener("scroll",this.updateScrollIndicators.bind(this)),this.updateScrollIndicators(),new ResizeObserver((()=>this.updateScrollIndicators())).observe(t)}updateScrollIndicators(){const t=this.shadowRoot.getElementById("tabs"),e=this.shadowRoot.getElementById("scroll-left"),n=this.shadowRoot.getElementById("scroll-right"),s=t.scrollLeft>0,o=t.scrollLeft<t.scrollWidth-t.clientWidth;e.classList.toggle("visible",s),n.classList.toggle("visible",o)}attributeChangedCallback(t,e,n){if("active"===t){const t=this.getActiveTab();t&&(t.active=!1);const e=this.getActiveContent();e&&(e.active=!1);const s=this.getTab(n);s&&(s.active=!0);const o=this.getContent(n);o&&(o.active=!0),dispatchEvent(this,"tab",{tab:n})}}get contents(){return[...this.querySelectorAll(":scope > k-tab-content")]}get tabs(){return[...this.querySelectorAll(":scope > k-tab")]}getTab(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab[for="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab")[n]}return e}getActiveTab(){return this.querySelector(':scope > k-tab[active="true"]')}getContent(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab-content[name="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab-content")[n]}return e}getActiveContent(){return this.querySelector(':scope > k-tab-content[active="true"]')}get shadowTemplate(){return`\n <div id="wrapper">\n <div id="tabs-container">\n <div id="scroll-left" class="scroll-indicator"></div>\n <div id="tabs">\n <slot name="tabs"></slot>\n </div>\n <div id="scroll-right" class="scroll-indicator"></div>\n </div>\n <div id="contents">\n ${super.shadowTemplate}\n </div>\n </div>\n \n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n overflow: hidden;\n }\n #wrapper {\n display: flex;\n flex-direction: column;\n max-height: 100%;\n height: 100%;\n overflow: hidden;\n }\n #tabs-container {\n position: relative;\n display: flex;\n border-bottom: 1px solid var(--c_border);\n }\n #tabs {\n display: flex;\n padding: 0;\n margin-top: calc(0 - var(--spacer));\n align-items: stretch;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -ms-overflow-style: none;\n flex: 1;\n }\n #tabs::-webkit-scrollbar {\n display: none;\n }\n #tabs ::slotted(*) {\n display: flex;\n align-items: center;\n }\n .scroll-indicator {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 32px;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.2s;\n z-index: 1;\n }\n .scroll-indicator.visible {\n opacity: 1;\n }\n #scroll-left {\n left: 0;\n background: linear-gradient(to right, var(--c_bg, white) 0%, transparent 100%);\n }\n #scroll-right {\n right: 0;\n background: linear-gradient(to left, var(--c_bg, white) 0%, transparent 100%);\n }\n #contents {\n display: flex;\n flex-direction: column;\n flex: 1;\n max-height: 100%;\n overflow: hidden;\n }\n `}static observedAttributes=[...super.observedAttributes,"active"]}window.customElements.define("k-tabs",Tabs);export class TabSpacer extends Component{constructor(){super(),this.slot="tabs"}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n flex: 1 1 auto;\n height: 1px;\n }\n `}}window.customElements.define("k-tab-spacer",TabSpacer);export default{Tab:Tab,TabContent:TabContent,Tabs:Tabs,TabSpacer:TabSpacer};
@@ -23,6 +23,7 @@
23
23
  <h6>Examples</h6>
24
24
  <a href="#basicUsage">Basic Usage</a><br />
25
25
  <a href="#tabSpacers">Tab Spacers</a><br />
26
+ <a href="#scrollingTabs">Scrolling Tabs</a><br />
26
27
 
27
28
  <h6 class="mt">JavaScript Reference</h6>
28
29
  <a href="#constructor">Constructor</a><br />
@@ -62,36 +63,77 @@
62
63
  </k-tab-content>
63
64
  </k-tabs>
64
65
 
65
- <h2 id="jsRef">JavaScript Reference</h2>
66
+ <h3 id="scrollingTabs"><a href="#scrollingTabs" class="no-link">Scrolling Tabs</a></h3>
67
+ <p>When there are many tabs, they will scroll horizontally with gradient indicators showing when more tabs are available.</p>
68
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-tabs</span>&gt;</span>
69
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab1"</span>&gt;</span>Tab 1<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
70
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab2"</span>&gt;</span>Tab 2<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
71
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab3"</span>&gt;</span>Tab 3<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
72
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab4"</span>&gt;</span>Tab 4<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
73
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab5"</span>&gt;</span>Tab 5<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
74
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab6"</span>&gt;</span>Tab 6<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
75
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab7"</span>&gt;</span>Tab 7<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
76
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab8"</span>&gt;</span>Tab 8<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
77
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab9"</span>&gt;</span>Tab 9<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
78
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"tab10"</span>&gt;</span>Tab 10<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab</span>&gt;</span>
79
+ <span class="hljs-comment">&lt;!-- Tab Contents --&gt;</span>
80
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab1"</span>&gt;</span>Content 1<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
81
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab2"</span>&gt;</span>Content 2<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
82
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab3"</span>&gt;</span>Content 3<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
83
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab4"</span>&gt;</span>Content 4<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
84
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab5"</span>&gt;</span>Content 5<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
85
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab6"</span>&gt;</span>Content 6<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
86
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab7"</span>&gt;</span>Content 7<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
87
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab8"</span>&gt;</span>Content 8<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
88
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab9"</span>&gt;</span>Content 9<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
89
+ <span class="hljs-tag">&lt;<span class="hljs-name">k-tab-content</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"tab10"</span>&gt;</span>Content 10<span class="hljs-tag">&lt;/<span class="hljs-name">k-tab-content</span>&gt;</span>
90
+ <span class="hljs-tag">&lt;/<span class="hljs-name">k-tabs</span>&gt;</span></code></pre>
91
+ <k-tabs>
92
+ <k-tab for="tab1">Long Tab Name 1</k-tab>
93
+ <k-tab for="tab2">Long Tab Name 2</k-tab>
94
+ <k-tab for="tab3">Long Tab Name 3</k-tab>
95
+ <k-tab for="tab4">Long Tab Name 4</k-tab>
96
+ <k-tab for="tab5">Long Tab Name 5</k-tab>
97
+ <k-tab for="tab6">Long Tab Name 6</k-tab>
98
+ <k-tab for="tab7">Long Tab Name 7</k-tab>
99
+ <k-tab for="tab8">Long Tab Name 8</k-tab>
100
+ <k-tab for="tab9">Long Tab Name 9</k-tab>
101
+ <k-tab for="tab10">Long Tab Name 10</k-tab>
102
+ <k-tab-content name="tab1"><p>Content 1</p></k-tab-content>
103
+ <k-tab-content name="tab2"><p>Content 2</p></k-tab-content>
104
+ <k-tab-content name="tab3"><p>Content 3</p></k-tab-content>
105
+ <k-tab-content name="tab4"><p>Content 4</p></k-tab-content>
106
+ <k-tab-content name="tab5"><p>Content 5</p></k-tab-content>
107
+ <k-tab-content name="tab6"><p>Content 6</p></k-tab-content>
108
+ <k-tab-content name="tab7"><p>Content 7</p></k-tab-content>
109
+ <k-tab-content name="tab8"><p>Content 8</p></k-tab-content>
110
+ <k-tab-content name="tab9"><p>Content 9</p></k-tab-content>
111
+ <k-tab-content name="tab10"><p>Content 10</p></k-tab-content>
112
+ </k-tabs>
66
113
 
114
+ <h2 id="jsRef">JavaScript Reference</h2>
67
115
  <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
68
116
  <h6>Extends <a href="./component.html">Component</a></h6>
69
- <h5>
70
- <code>new Tabs()</code>
71
- </h5>
72
-
117
+ <h5><code>new Tabs()</code></h5>
73
118
  <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
74
119
  <ul>
75
120
  <li><a href="./component.html">Component</a></li>
76
121
  </ul>
77
-
78
122
  <h3 id="attributes"><a href="#attributes" class="no-link">Attributes</a></h3>
79
123
  <h5><code>active<i>: string</i></code></h5>
80
124
  <p>The name of the active tab.</p>
81
-
82
125
  <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
83
- <h5><code>getTab(id)<i>: Tab</i></code></h5>
84
- <p>Returns the tab with the specified id.</p>
85
126
  <h5><code>getActiveTab()<i>: Tab</i></code></h5>
86
127
  <p>Returns the currently active tab.</p>
87
- <h5><code>getContent(id)<i>: TabContent</i></code></h5>
88
- <p>Returns the tab content with the specified id.</p>
128
+ <h5><code>getTab(id)<i>: Tab</i></code></h5>
129
+ <p>Returns the tab with the specified id.</p>
89
130
  <h5><code>getActiveContent()<i>: TabContent</i></code></h5>
90
131
  <p>Returns the currently active tab content.</p>
91
-
132
+ <h5><code>getContent(id)<i>: TabContent</i></code></h5>
133
+ <p>Returns the tab content with the specified id.</p>
92
134
  </main>
93
135
  <div style="height:33vh"></div>
94
- <script type="module" src="../kempo/components/Import.js"></script>
95
- <script type="module" src="../kempo/components/Tabs.js"></script>
136
+ <script type="module" src="../kempo/components/Tabs.js"></script>
137
+ <script type="module" src="../kempo/components/Import.js"></script>
96
138
  </body>
97
139
  </html>
@@ -1 +1 @@
1
- import Component from"./Component.js";import{dispatchEvent}from"../utils/element.js";const clickHandler=Symbol();export class Tab extends Component{constructor(){super(),this[clickHandler]=()=>{this.active||(this.tabs.active=this.for)},this.slot="tabs",this.registerAttribute("active",!1)}connectedCallback(){super.connectedCallback(),this.shadowRoot.getElementById("button").addEventListener("click",this[clickHandler])}get for(){const t=this.getAttribute("for");return t||this?.tabs.tabs.indexOf(this)}set for(t){t?this.setAttribute("for",t):this.removeAttribute("for")}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get shadowTemplate(){return`\n <button id="button">\n ${super.shadowTemplate}\n </button>\n `}get shadowStyles(){return"\n :host {\n margin-bottom: -1px;\n }\n #button {\n padding: var(--spacer_h);\n background-color: transparent;\n border: none;\n cursor: inherit;\n box-shadow: none;\n color: inherit;\n }\n :host(:not([active])) #button {\n cursor: pointer;\n }\n :host([active]){\n border-bottom: 2px solid var(--c_primary);\n margin-bottom: -1px;\n }\n :host([active]) #button {\n color: var(--tc_primary);\n }\n "}}window.customElements.define("k-tab",Tab);export class TabContent extends Component{constructor(){super(),this.registerAttribute("active",!1)}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get name(){const t=this.getAttribute("name");return t||this?.tabs.contents.indexOf(this)}set name(t){t?this.setAttribute("name",t):this.removeAttribute("name")}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n height: 100%;\n max-height: 100%;\n flex: 1 1 auto;\n overflow: hidden;\n }\n :host([active]) {\n display: block;\n }\n :host(:not([active])) {\n display: none;\n }\n `}}window.customElements.define("k-tab-content",TabContent);export class Tabs extends Component{constructor(){super(),this.registerAttribute("active","")}async connectedCallback(){await super.connectedCallback(),this.active||(this.active=`${this.querySelectorAll("k-tab-content")[0].name}`)}attributeChangedCallback(t,e,n){if("active"===t){const t=this.getActiveTab();t&&(t.active=!1);const e=this.getActiveContent();e&&(e.active=!1);const s=this.getTab(n);s&&(s.active=!0);const o=this.getContent(n);o&&(o.active=!0),dispatchEvent(this,"tab",{tab:n})}}get contents(){return[...this.querySelectorAll(":scope > k-tab-content")]}get tabs(){return[...this.querySelectorAll(":scope > k-tab")]}getTab(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab[for="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab")[n]}return e}getActiveTab(){return this.querySelector(':scope > k-tab[active="true"]')}getContent(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab-content[name="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab-content")[n]}return e}getActiveContent(){return this.querySelector(':scope > k-tab-content[active="true"]')}get shadowTemplate(){return`\n <div id="wrapper">\n <div id="tabs">\n <slot name="tabs"></slot>\n </div>\n <div id="contents">\n ${super.shadowTemplate}\n </div>\n </div>\n \n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n overflow: hidden;\n }\n #wrapper {\n display: flex;\n flex-direction: column;\n max-height: 100%;\n height: 100%;\n overflow: hidden;\n }\n #tabs {\n display: flex;\n border-bottom: 1px solid var(--c_border);\n padding: 0;\n margin-top: calc(0 - var(--spacer));\n align-items: flex-start;\n }\n #contents {\n display: flex;\n flex-direction: column;\n flex: 1;\n max-height: 100%;\n overflow: hidden\n }\n `}static observedAttributes=[...super.observedAttributes,"active"]}window.customElements.define("k-tabs",Tabs);export class TabSpacer extends Component{constructor(){super(),this.slot="tabs"}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n flex: 1 1 auto;\n height: 1px;\n }\n `}}window.customElements.define("k-tab-spacer",TabSpacer);export default{Tab:Tab,TabContent:TabContent,Tabs:Tabs,TabSpacer:TabSpacer};
1
+ import Component from"./Component.js";import{dispatchEvent}from"../utils/element.js";const clickHandler=Symbol();export class Tab extends Component{constructor(){super(),this[clickHandler]=()=>{this.active||(this.tabs.active=this.for)},this.slot="tabs",this.registerAttribute("active",!1)}connectedCallback(){super.connectedCallback(),this.shadowRoot.getElementById("button").addEventListener("click",this[clickHandler])}get for(){const t=this.getAttribute("for");return t||this?.tabs.tabs.indexOf(this)}set for(t){t?this.setAttribute("for",t):this.removeAttribute("for")}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get shadowTemplate(){return`\n <button id="button">\n ${super.shadowTemplate}\n </button>\n `}get shadowStyles(){return"\n :host {\n margin-bottom: -1px;\n }\n #button {\n padding: var(--spacer_h);\n background-color: transparent;\n border: none;\n cursor: inherit;\n box-shadow: none;\n color: inherit;\n }\n :host(:not([active])) #button {\n cursor: pointer;\n }\n :host([active]){\n border-bottom: 2px solid var(--c_primary);\n margin-bottom: -1px;\n }\n :host([active]) #button {\n color: var(--tc_primary);\n }\n "}}window.customElements.define("k-tab",Tab);export class TabContent extends Component{constructor(){super(),this.registerAttribute("active",!1)}get tabs(){return"K-TABS"===this.parentElement.tagName?this.parentElement:null}get name(){const t=this.getAttribute("name");return t||this?.tabs.contents.indexOf(this)}set name(t){t?this.setAttribute("name",t):this.removeAttribute("name")}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n height: 100%;\n max-height: 100%;\n flex: 1 1 auto;\n overflow: hidden;\n }\n :host([active]) {\n display: block;\n }\n :host(:not([active])) {\n display: none;\n }\n `}}window.customElements.define("k-tab-content",TabContent);export class Tabs extends Component{constructor(){super(),this.registerAttribute("active","")}async connectedCallback(){await super.connectedCallback(),this.active||(this.active=`${this.querySelectorAll("k-tab-content")[0].name}`);const t=this.shadowRoot.getElementById("tabs");t.addEventListener("scroll",this.updateScrollIndicators.bind(this)),this.updateScrollIndicators(),new ResizeObserver((()=>this.updateScrollIndicators())).observe(t)}updateScrollIndicators(){const t=this.shadowRoot.getElementById("tabs"),e=this.shadowRoot.getElementById("scroll-left"),n=this.shadowRoot.getElementById("scroll-right"),s=t.scrollLeft>0,o=t.scrollLeft<t.scrollWidth-t.clientWidth;e.classList.toggle("visible",s),n.classList.toggle("visible",o)}attributeChangedCallback(t,e,n){if("active"===t){const t=this.getActiveTab();t&&(t.active=!1);const e=this.getActiveContent();e&&(e.active=!1);const s=this.getTab(n);s&&(s.active=!0);const o=this.getContent(n);o&&(o.active=!0),dispatchEvent(this,"tab",{tab:n})}}get contents(){return[...this.querySelectorAll(":scope > k-tab-content")]}get tabs(){return[...this.querySelectorAll(":scope > k-tab")]}getTab(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab[for="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab")[n]}return e}getActiveTab(){return this.querySelector(':scope > k-tab[active="true"]')}getContent(t){let e;if("string"==typeof t&&(e=this.querySelector(`k-tab-content[name="${t}"]`)),!e){let n=parseInt(t);n||(n=0),e=this.querySelectorAll("k-tab-content")[n]}return e}getActiveContent(){return this.querySelector(':scope > k-tab-content[active="true"]')}get shadowTemplate(){return`\n <div id="wrapper">\n <div id="tabs-container">\n <div id="scroll-left" class="scroll-indicator"></div>\n <div id="tabs">\n <slot name="tabs"></slot>\n </div>\n <div id="scroll-right" class="scroll-indicator"></div>\n </div>\n <div id="contents">\n ${super.shadowTemplate}\n </div>\n </div>\n \n `}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n display: block;\n overflow: hidden;\n }\n #wrapper {\n display: flex;\n flex-direction: column;\n max-height: 100%;\n height: 100%;\n overflow: hidden;\n }\n #tabs-container {\n position: relative;\n display: flex;\n border-bottom: 1px solid var(--c_border);\n }\n #tabs {\n display: flex;\n padding: 0;\n margin-top: calc(0 - var(--spacer));\n align-items: stretch;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -ms-overflow-style: none;\n flex: 1;\n }\n #tabs::-webkit-scrollbar {\n display: none;\n }\n #tabs ::slotted(*) {\n display: flex;\n align-items: center;\n }\n .scroll-indicator {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 32px;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.2s;\n z-index: 1;\n }\n .scroll-indicator.visible {\n opacity: 1;\n }\n #scroll-left {\n left: 0;\n background: linear-gradient(to right, var(--c_bg, white) 0%, transparent 100%);\n }\n #scroll-right {\n right: 0;\n background: linear-gradient(to left, var(--c_bg, white) 0%, transparent 100%);\n }\n #contents {\n display: flex;\n flex-direction: column;\n flex: 1;\n max-height: 100%;\n overflow: hidden;\n }\n `}static observedAttributes=[...super.observedAttributes,"active"]}window.customElements.define("k-tabs",Tabs);export class TabSpacer extends Component{constructor(){super(),this.slot="tabs"}get shadowStyles(){return`\n ${super.shadowStyles}\n :host {\n flex: 1 1 auto;\n height: 1px;\n }\n `}}window.customElements.define("k-tab-spacer",TabSpacer);export default{Tab:Tab,TabContent:TabContent,Tabs:Tabs,TabSpacer:TabSpacer};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo",
3
- "version": "2.15.0",
3
+ "version": "2.15.1",
4
4
  "type": "module",
5
5
  "description": "A web component library",
6
6
  "exports": {
@@ -53,6 +53,7 @@ export class Tab extends Component {
53
53
  return /*css*/`
54
54
  :host {
55
55
  margin-bottom: -1px;
56
+ flex: 0 0 auto; /* Important: prevent shrinking and growing */
56
57
  }
57
58
  #button {
58
59
  padding: var(--spacer_h);
@@ -61,6 +62,7 @@ export class Tab extends Component {
61
62
  cursor: inherit;
62
63
  box-shadow: none;
63
64
  color: inherit;
65
+ white-space: nowrap; /* Prevent text wrapping */
64
66
  }
65
67
  :host(:not([active])) #button {
66
68
  cursor: pointer;
@@ -133,7 +135,38 @@ export class Tabs extends Component {
133
135
  if(!this.active){
134
136
  this.active = `${this.querySelectorAll('k-tab-content')[0].name}`;
135
137
  }
138
+
139
+ // Add scroll listeners for indicators
140
+ const tabsContainer = this.shadowRoot.getElementById('tabs');
141
+ tabsContainer.addEventListener('scroll', this.updateScrollIndicators.bind(this));
142
+ this.updateScrollIndicators();
143
+
144
+ // Update indicators on resize
145
+ new ResizeObserver(() => this.updateScrollIndicators()).observe(tabsContainer);
146
+
147
+ const leftButton = this.shadowRoot.getElementById('scroll-left');
148
+ const rightButton = this.shadowRoot.getElementById('scroll-right');
149
+
150
+ leftButton.addEventListener('click', () => {
151
+ tabsContainer.scrollBy({ left: -200, behavior: 'smooth' });
152
+ });
153
+ rightButton.addEventListener('click', () => {
154
+ tabsContainer.scrollBy({ left: 200, behavior: 'smooth' });
155
+ });
156
+ }
157
+
158
+ updateScrollIndicators() {
159
+ const tabsContainer = this.shadowRoot.getElementById('tabs');
160
+ const leftIndicator = this.shadowRoot.getElementById('scroll-left');
161
+ const rightIndicator = this.shadowRoot.getElementById('scroll-right');
162
+
163
+ const hasLeftScroll = tabsContainer.scrollLeft > 0;
164
+ const hasRightScroll = tabsContainer.scrollLeft < (tabsContainer.scrollWidth - tabsContainer.clientWidth);
165
+
166
+ leftIndicator.classList.toggle('visible', hasLeftScroll);
167
+ rightIndicator.classList.toggle('visible', hasRightScroll);
136
168
  }
169
+
137
170
  attributeChangedCallback(n, oV, nV){
138
171
  if(n === 'active'){
139
172
  const $activeTab = this.getActiveTab();
@@ -190,14 +223,25 @@ export class Tabs extends Component {
190
223
  get shadowTemplate(){
191
224
  return /*html*/`
192
225
  <div id="wrapper">
193
- <div id="tabs">
194
- <slot name="tabs"></slot>
226
+ <div id="tabs-container">
227
+ <div id="scroll-left" class="scroll-indicator">
228
+ <svg class="arrow" width="20" height="20" viewBox="0 0 20 20" fill="none">
229
+ <path d="M12 15L7 10L12 5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
230
+ </svg>
231
+ </div>
232
+ <div id="tabs">
233
+ <slot name="tabs"></slot>
234
+ </div>
235
+ <div id="scroll-right" class="scroll-indicator">
236
+ <svg class="arrow" width="20" height="20" viewBox="0 0 20 20" fill="none">
237
+ <path d="M8 15L13 10L8 5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
238
+ </svg>
239
+ </div>
195
240
  </div>
196
241
  <div id="contents">
197
242
  ${super.shadowTemplate}
198
243
  </div>
199
244
  </div>
200
-
201
245
  `;
202
246
  }
203
247
  get shadowStyles(){
@@ -205,28 +249,62 @@ export class Tabs extends Component {
205
249
  ${super.shadowStyles}
206
250
  :host {
207
251
  display: block;
208
- overflow: hidden;
252
+ width: 100%;
209
253
  }
210
254
  #wrapper {
211
255
  display: flex;
212
256
  flex-direction: column;
213
- max-height: 100%;
214
- height: 100%;
215
- overflow: hidden;
257
+ width: 100%;
258
+ min-width: 0;
259
+ }
260
+ #tabs-container {
261
+ position: relative;
262
+ border-bottom: 1px solid var(--c_border);
216
263
  }
217
264
  #tabs {
218
265
  display: flex;
219
- border-bottom: 1px solid var(--c_border);
220
- padding: 0;
221
- margin-top: calc(0 - var(--spacer));
222
- align-items: flex-start;
266
+ overflow-x: auto;
267
+ overflow-y: hidden;
223
268
  }
224
- #contents {
269
+ #tabs ::slotted(*) {
270
+ flex: 0 0 auto;
271
+ }
272
+ .scroll-indicator {
273
+ position: absolute;
274
+ top: 0;
275
+ bottom: 0;
276
+ width: 72px;
277
+ pointer-events: none;
278
+ opacity: 0;
279
+ transition: opacity 0.2s;
225
280
  display: flex;
226
- flex-direction: column;
227
- flex: 1;
228
- max-height: 100%;
229
- overflow: hidden
281
+ align-items: center;
282
+ justify-content: flex-start;
283
+ padding-bottom: 2px;
284
+ }
285
+ .scroll-indicator .arrow {
286
+ color: var(--tc_base);
287
+ z-index: 1;
288
+ }
289
+ .scroll-indicator.visible {
290
+ opacity: 1;
291
+ }
292
+ #scroll-left {
293
+ left: 0;
294
+ background: linear-gradient(90deg,
295
+ var(--c_bg) 0%,
296
+ var(--c_bg) 30%,
297
+ transparent 100%
298
+ );
299
+ }
300
+ #scroll-right {
301
+ right: 0;
302
+ justify-content: flex-end;
303
+ background: linear-gradient(-90deg,
304
+ var(--c_bg) 0%,
305
+ var(--c_bg) 30%,
306
+ transparent 100%
307
+ );
230
308
  }
231
309
  `;
232
310
  }