UNPKG

yyf_aka-web-components

Version:

A collection of modern Web Components including counter, data table and custom button components

10 lines (9 loc) 32.6 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class t extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._value=0,this._initialValue=0,this._step=1,this._min=null,this._max=null}static get observedAttributes(){return["initial","step","min","max"]}connectedCallback(){this._initialValue=parseInt(this.getAttribute("initial"))||0,this._step=parseInt(this.getAttribute("step"))||1,this._min=this.hasAttribute("min")?parseInt(this.getAttribute("min")):null,this._max=this.hasAttribute("max")?parseInt(this.getAttribute("max")):null,this._value=this._initialValue,this.render(),this.addEventListeners()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"initial":this._initialValue=parseInt(e)||0;break;case"step":this._step=parseInt(e)||1;break;case"min":this._min=this.hasAttribute("min")?parseInt(e):null;break;case"max":this._max=this.hasAttribute("max")?parseInt(e):null}this.render()}}addEventListeners(){const t=this.shadowRoot,n=t.querySelector(".increment-btn");n&&n.addEventListener("click",()=>{this.increment()});const e=t.querySelector(".decrement-btn");e&&e.addEventListener("click",()=>{this.decrement()});const a=t.querySelector(".reset-btn");a&&a.addEventListener("click",()=>{this.reset()})}render(){this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: inline-block;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n }\n\n .counter-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 15px;\n padding: 20px;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n border-radius: 16px;\n color: white;\n box-shadow: 0 8px 32px rgba(0,0,0,0.1);\n min-width: 200px;\n }\n\n .counter-display {\n font-size: 3rem;\n font-weight: 300;\n text-align: center;\n margin: 0;\n text-shadow: 0 2px 4px rgba(0,0,0,0.2);\n }\n\n .counter-info {\n font-size: 0.9rem;\n opacity: 0.8;\n text-align: center;\n margin: 0;\n }\n\n .counter-controls {\n display: flex;\n gap: 10px;\n align-items: center;\n }\n\n .counter-btn {\n background: rgba(255,255,255,0.2);\n border: 2px solid rgba(255,255,255,0.3);\n color: white;\n padding: 8px 16px;\n border-radius: 8px;\n cursor: pointer;\n font-size: 1.2rem;\n font-weight: 600;\n transition: all 0.3s ease;\n min-width: 50px;\n }\n\n .counter-btn:hover {\n background: rgba(255,255,255,0.3);\n border-color: rgba(255,255,255,0.5);\n transform: translateY(-2px);\n }\n\n .counter-btn:active {\n transform: translateY(0);\n }\n\n .counter-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: none;\n }\n\n .increment-btn {\n background: rgba(76, 175, 80, 0.8);\n border-color: rgba(76, 175, 80, 0.9);\n }\n\n .decrement-btn {\n background: rgba(244, 67, 54, 0.8);\n border-color: rgba(244, 67, 54, 0.9);\n }\n\n .reset-btn {\n background: rgba(255, 193, 7, 0.8);\n border-color: rgba(255, 193, 7, 0.9);\n font-size: 1rem;\n }\n\n @media (max-width: 480px) {\n .counter-container {\n padding: 15px;\n min-width: 180px;\n }\n\n .counter-display {\n font-size: 2.5rem;\n }\n\n .counter-controls {\n flex-direction: column;\n gap: 8px;\n }\n\n .counter-btn {\n width: 100%;\n min-width: auto;\n }\n }\n </style>\n\n <div class="counter-container">\n <h2 class="counter-display">${this._value}</h2>\n <p class="counter-info">\n 步长: ${this._step}\n ${null!==this._min?`<br>最小值: ${this._min}`:""}\n ${null!==this._max?`<br>最大值: ${this._max}`:""}\n </p>\n <div class="counter-controls">\n <button class="counter-btn decrement-btn" \n ${null!==this._min&&this._value<=this._min?"disabled":""}>\n -\n </button>\n <button class="counter-btn reset-btn">重置</button>\n <button class="counter-btn increment-btn" \n ${null!==this._max&&this._value>=this._max?"disabled":""}>\n +\n </button>\n </div>\n </div>\n\n <slot name="footer"></slot>\n `,this.addEventListeners()}getValue(){return this._value}setValue(t){const n=this._value,e=parseInt(t);null!==this._min&&e<this._min?this._value=this._min:null!==this._max&&e>this._max?this._value=this._max:this._value=e,this.dispatchEvent(new CustomEvent("counter-change",{detail:{action:"set",value:this._value,oldValue:n},bubbles:!0,composed:!0})),this.render()}reset(){const t=this._value;this._value=this._initialValue,this.dispatchEvent(new CustomEvent("counter-change",{detail:{action:"reset",value:this._value,oldValue:t},bubbles:!0,composed:!0})),this.render()}increment(){const t=this._value,n=this._value+this._step;null!==this._max&&n>this._max?this._value=this._max:this._value=n,this.dispatchEvent(new CustomEvent("counter-change",{detail:{action:"increment",value:this._value,oldValue:t},bubbles:!0,composed:!0})),this.render()}decrement(){const t=this._value,n=this._value-this._step;null!==this._min&&n<this._min?this._value=this._min:this._value=n,this.dispatchEvent(new CustomEvent("counter-change",{detail:{action:"decrement",value:this._value,oldValue:t},bubbles:!0,composed:!0})),this.render()}}class n extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._data=[],this._columns=[],this._filteredData=[],this._currentPage=1,this._pageSize=10,this._sortColumn=null,this._sortDirection="asc",this._searchTerm="",this._searchable=!0,this._sortable=!0,this._pagination=!0,this._eventListeners=new Map}static get observedAttributes(){return["page-size","searchable","sortable","pagination"]}connectedCallback(){this._pageSize=parseInt(this.getAttribute("page-size"))||10,this._searchable="false"!==this.getAttribute("searchable"),this._sortable="false"!==this.getAttribute("sortable"),this._pagination="false"!==this.getAttribute("pagination"),this.loadData(),this.render(),this.addEventListeners()}disconnectedCallback(){this.removeEventListeners()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"page-size":this._pageSize=parseInt(e)||10,this._currentPage=1;break;case"searchable":this._searchable="false"!==e;break;case"sortable":this._sortable="false"!==e;break;case"pagination":this._pagination="false"!==e}this.render()}}addEventListeners(){const t=this.shadowRoot;if(this._searchable){const n=t.querySelector(".search-input");if(n){const t=t=>{this._searchTerm=t.target.value,this._currentPage=1,this.filterData(),this.render()};this._eventListeners.set("search",{element:n,handler:t,event:"input"}),n.addEventListener("input",t)}}if(this._sortable){t.querySelectorAll(".sort-btn").forEach((t,n)=>{const e=()=>{const n=t.dataset.column;this.sortData(n)};this._eventListeners.set(`sort-${n}`,{element:t,handler:e,event:"click"}),t.addEventListener("click",e)})}if(this._pagination){const n=t.querySelector(".pagination");if(n){const t=t=>{if(t.target.classList.contains("page-btn")){const n=parseInt(t.target.dataset.page);n&&n!==this._currentPage&&!t.target.disabled&&(this._currentPage=n,this.render())}};this._eventListeners.set("pagination",{element:n,handler:t,event:"click"}),n.addEventListener("click",t)}}const n=t.querySelector(".data-table tbody");if(n){const t=t=>{if(t.target.classList.contains("action-btn")){const n=t.target.dataset.action,e=parseInt(t.target.dataset.rowIndex);if(n&&void 0!==e)switch(n){case"view":this.viewRow(e);break;case"edit":this.editRow(e);break;case"delete":this.deleteRow(e)}}};this._eventListeners.set("actions",{element:n,handler:t,event:"click"}),n.addEventListener("click",t)}}removeEventListeners(){this._eventListeners.forEach(({element:t,handler:n,event:e})=>{t&&t.removeEventListener&&t.removeEventListener(e,n)}),this._eventListeners.clear()}loadData(){const t=this.getAttribute("data");if(t)try{this._data=JSON.parse(t)}catch(t){this._data=[]}const n=this.getAttribute("columns");if(n)try{this._columns=JSON.parse(n)}catch(t){this._columns=[]}0===this._columns.length&&this._data.length>0&&(this._columns=Object.keys(this._data[0]).map(t=>({key:t,label:t.charAt(0).toUpperCase()+t.slice(1),type:"text"}))),this._filteredData=[...this._data]}filterData(){if(!this._searchTerm||""===this._searchTerm.trim())return void(this._filteredData=[...this._data]);const t=this._searchTerm.toLowerCase().trim();this._filteredData=this._data.filter(n=>Object.values(n).some(n=>null!=n&&String(n).toLowerCase().includes(t)))}sortData(t){this._sortColumn===t?this._sortDirection="asc"===this._sortDirection?"desc":"asc":(this._sortColumn=t,this._sortDirection="asc"),this._filteredData.sort((n,e)=>{let a=n[t],s=e[t];return null==a&&(a=""),null==s&&(s=""),isNaN(a)||isNaN(s)||""===a||""===s?(a=String(a).toLowerCase(),s=String(s).toLowerCase()):(a=parseFloat(a),s=parseFloat(s)),a<s?"asc"===this._sortDirection?-1:1:a>s?"asc"===this._sortDirection?1:-1:0}),this._currentPage=1,this.render()}getPaginatedData(){if(!this._pagination)return this._filteredData;const t=(this._currentPage-1)*this._pageSize,n=t+this._pageSize;return this._filteredData.slice(t,n)}getTotalPages(){return 0===this._filteredData.length?0:Math.ceil(this._filteredData.length/this._pageSize)}render(){this.removeEventListeners();const t=this.getPaginatedData(),n=this.getTotalPages(),e=this._filteredData.length;this._currentPage>n&&n>0&&(this._currentPage=n),this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n }\n\n .data-table-container {\n background: white;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\n overflow: hidden;\n }\n\n .table-header {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n padding: 20px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .table-title {\n margin: 0;\n font-size: 20px;\n font-weight: 300;\n }\n\n .table-controls {\n display: flex;\n gap: 15px;\n align-items: center;\n }\n\n .search-container {\n position: relative;\n }\n\n .search-input {\n padding: 8px 12px 8px 35px;\n border: none;\n border-radius: 6px;\n background: rgba(255,255,255,0.9);\n color: #333;\n font-size: 14px;\n width: 200px;\n }\n\n .search-input:focus {\n outline: none;\n background: white;\n }\n\n .search-icon {\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n color: #666;\n font-size: 14px;\n }\n\n .table-wrapper {\n overflow-x: auto;\n }\n\n .data-table {\n width: 100%;\n border-collapse: collapse;\n background: white;\n }\n\n .data-table th {\n background: #f8f9fa;\n padding: 15px 12px;\n text-align: left;\n font-weight: 600;\n color: #333;\n border-bottom: 2px solid #e9ecef;\n position: relative;\n }\n\n .data-table th.sortable {\n cursor: pointer;\n user-select: none;\n }\n\n .data-table th.sortable:hover {\n background: #e9ecef;\n }\n\n .sort-btn {\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n width: 100%;\n text-align: left;\n font-weight: inherit;\n color: inherit;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .sort-icon {\n font-size: 12px;\n margin-left: 5px;\n opacity: 0.5;\n }\n\n .sort-icon.active {\n opacity: 1;\n }\n\n .data-table td {\n padding: 12px;\n border-bottom: 1px solid #f0f0f0;\n color: #333;\n }\n\n .data-table tbody tr:hover {\n background: #f8f9fa;\n }\n\n .data-table tbody tr:nth-child(even) {\n background: #fafbfc;\n }\n\n .data-table tbody tr:nth-child(even):hover {\n background: #f0f1f2;\n }\n\n .empty-state {\n text-align: center;\n padding: 40px 20px;\n color: #999;\n }\n\n .empty-state h3 {\n margin: 0 0 10px 0;\n font-weight: 300;\n }\n\n .table-footer {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 15px 20px;\n background: #f8f9fa;\n border-top: 1px solid #e9ecef;\n }\n\n .table-info {\n font-size: 14px;\n color: #666;\n }\n\n .pagination {\n display: flex;\n gap: 5px;\n align-items: center;\n }\n\n .page-btn {\n padding: 6px 12px;\n border: 1px solid #ddd;\n background: white;\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.3s ease;\n }\n\n .page-btn:hover {\n background: #f0f1f2;\n }\n\n .page-btn.active {\n background: #667eea;\n color: white;\n border-color: #667eea;\n }\n\n .page-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .status-badge {\n padding: 4px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n }\n\n .status-active {\n background: #d4edda;\n color: #155724;\n }\n\n .status-inactive {\n background: #f8d7da;\n color: #721c24;\n }\n\n .status-pending {\n background: #fff3cd;\n color: #856404;\n }\n\n .action-btn {\n padding: 4px 8px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 12px;\n margin-right: 5px;\n transition: all 0.3s ease;\n }\n\n .edit-btn {\n background: #ffc107;\n color: #333;\n }\n\n .delete-btn {\n background: #dc3545;\n color: white;\n }\n\n .view-btn {\n background: #17a2b8;\n color: white;\n }\n\n @media (max-width: 768px) {\n .table-header {\n flex-direction: column;\n gap: 15px;\n align-items: stretch;\n }\n\n .table-controls {\n justify-content: center;\n }\n\n .search-input {\n width: 100%;\n }\n\n .table-footer {\n flex-direction: column;\n gap: 15px;\n }\n\n .pagination {\n justify-content: center;\n }\n }\n </style>\n\n <div class="data-table-container">\n <div class="table-header">\n <h2 class="table-title">数据表格</h2>\n ${this._searchable?`\n <div class="table-controls">\n <div class="search-container">\n <span class="search-icon">🔍</span>\n <input type="text" class="search-input" placeholder="搜索..." value="${this._searchTerm}">\n </div>\n </div>\n `:""}\n </div>\n\n <div class="table-wrapper">\n <table class="data-table">\n <thead>\n <tr>\n ${this._columns.length>0?this._columns.map(t=>`\n <th class="${this._sortable?"sortable":""}">\n ${this._sortable?`\n <button class="sort-btn" data-column="${t.key}">\n ${t.label}\n <span class="sort-icon ${this._sortColumn===t.key?"active":""}">\n ${this._sortColumn===t.key?"asc"===this._sortDirection?"↑":"↓":"↕"}\n </span>\n </button>\n `:t.label}\n </th>\n `).join(""):"<th>暂无列定义</th>"}\n </tr>\n </thead>\n <tbody>\n ${t.length>0?t.map((t,n)=>`\n <tr>\n ${this._columns.length>0?this._columns.map(e=>`\n <td>\n ${this.renderCell(t,e,n)}\n </td>\n `).join(""):"<td>暂无数据</td>"}\n </tr>\n `).join(""):`\n <tr>\n <td colspan="${Math.max(this._columns.length,1)}" class="empty-state">\n <h3>暂无数据</h3>\n <p>${this._searchTerm?"没有找到匹配的数据":"请添加数据"}</p>\n </td>\n </tr>\n `}\n </tbody>\n </table>\n </div>\n\n ${this._pagination&&n>1?`\n <div class="table-footer">\n <div class="table-info">\n 显示 ${e>0?(this._currentPage-1)*this._pageSize+1:0} - \n ${Math.min(this._currentPage*this._pageSize,e)} \n 条,共 ${e} 条数据\n </div>\n <div class="pagination">\n <button class="page-btn" data-page="${this._currentPage-1}" \n ${this._currentPage<=1?"disabled":""}>\n 上一页\n </button>\n \n ${this.getPageNumbers().map(t=>`\n <button class="page-btn ${t===this._currentPage?"active":""}" \n data-page="${t}">\n ${t}\n </button>\n `).join("")}\n \n <button class="page-btn" data-page="${this._currentPage+1}" \n ${this._currentPage>=n?"disabled":""}>\n 下一页\n </button>\n </div>\n </div>\n `:""}\n </div>\n\n <slot name="footer"></slot>\n `,this.addEventListeners()}renderCell(t,n,e){const a=t[n.key];if(n.render)return n.render(a,t,e);if("status"===n.type){return`<span class="status-badge ${{active:"status-active",inactive:"status-inactive",pending:"status-pending"}[a]||"status-inactive"}">${a||"unknown"}</span>`}return"actions"===n.type?`\n <button class="action-btn view-btn" data-action="view" data-row-index="${e}">查看</button>\n <button class="action-btn edit-btn" data-action="edit" data-row-index="${e}">编辑</button>\n <button class="action-btn delete-btn" data-action="delete" data-row-index="${e}">删除</button>\n `:null!=a?String(a):""}getPageNumbers(){const t=this.getTotalPages(),n=this._currentPage,e=[];if(t<=7)for(let n=1;n<=t;n++)e.push(n);else if(n<=4){for(let t=1;t<=5;t++)e.push(t);t>5&&(e.push("..."),e.push(t))}else if(n>=t-3){e.push(1),e.push("...");for(let n=t-4;n<=t;n++)e.push(n)}else{e.push(1),e.push("...");for(let t=n-1;t<=n+1;t++)e.push(t);e.push("..."),e.push(t)}return e}setData(t){this._data=Array.isArray(t)?t:[],this._filteredData=[...this._data],this._currentPage=1,this.render()}setColumns(t){this._columns=Array.isArray(t)?t:[],this.render()}addRow(t){t&&"object"==typeof t&&(this._data.push(t),this._filteredData=[...this._data],this.render(),this.dispatchEvent(new CustomEvent("row-added",{detail:{row:t},bubbles:!0,composed:!0})))}updateRow(t,n){t>=0&&t<this._data.length&&n&&"object"==typeof n&&(this._data[t]={...this._data[t],...n},this._filteredData=[...this._data],this.render(),this.dispatchEvent(new CustomEvent("row-updated",{detail:{index:t,row:this._data[t]},bubbles:!0,composed:!0})))}deleteRow(t){if(t>=0&&t<this._data.length){const n=this._data.splice(t,1)[0];this._filteredData=[...this._data],0===this.getPaginatedData().length&&this._currentPage>1&&this._currentPage--,this.render(),this.dispatchEvent(new CustomEvent("row-deleted",{detail:{index:t,row:n},bubbles:!0,composed:!0}))}}viewRow(t){const n=this.getPaginatedData()[t];if(n){const t=this._data.findIndex(t=>void 0!==t.id&&void 0!==n.id?t.id===n.id:t===n);this.dispatchEvent(new CustomEvent("row-view",{detail:{index:t,row:n},bubbles:!0,composed:!0}))}}editRow(t){const n=this.getPaginatedData()[t];if(n){const t=this._data.findIndex(t=>void 0!==t.id&&void 0!==n.id?t.id===n.id:t===n);this.dispatchEvent(new CustomEvent("row-edit",{detail:{index:t,row:n},bubbles:!0,composed:!0}))}}getData(){return[...this._data]}getFilteredData(){return[...this._filteredData]}getCurrentPage(){return this._currentPage}setCurrentPage(t){const n=this.getTotalPages();t>=1&&t<=n&&(this._currentPage=t,this.render())}}class e extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._label="",this._variant="primary",this._size="md",this._disabled=!1,this._loading=!1}static get observedAttributes(){return["label","variant","size","disabled","loading"]}connectedCallback(){this._label=this.getAttribute("label")||"",this._variant=this.getAttribute("variant")||"primary",this._size=this.getAttribute("size")||"md",this._disabled=this.hasAttribute("disabled"),this._loading=this.hasAttribute("loading"),this.render(),this.addEventListeners()}attributeChangedCallback(t,n,e){if(n!==e){switch(t){case"label":this._label=e||"";break;case"variant":this._variant=e||"primary";break;case"size":this._size=e||"md";break;case"disabled":this._disabled=this.hasAttribute("disabled");break;case"loading":this._loading=this.hasAttribute("loading")}this.render()}}addEventListeners(){const t=this.shadowRoot&&this.shadowRoot.querySelector("button");t&&t.addEventListener("click",t=>{if(this._disabled||this._loading)return t.preventDefault(),void t.stopPropagation();this.dispatchEvent(new CustomEvent("button-click",{detail:{label:this._label,variant:this._variant,size:this._size},bubbles:!0,composed:!0}))})}setLoading(t){this._loading=Boolean(t),this._loading?this.setAttribute("loading",""):this.removeAttribute("loading"),this.render()}setDisabled(t){this._disabled=Boolean(t),this._disabled?this.setAttribute("disabled",""):this.removeAttribute("disabled"),this.render()}focus(){const t=this.shadowRoot&&this.shadowRoot.querySelector("button");t&&t.focus()}render(){const t=this._label&&!this.hasChildNodes()?`<span class="btn__label">${this._label}</span>`:"<slot></slot>";this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: inline-block;\n --btn-font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica Neue, Arial, "Apple Color Emoji", "Segoe UI Emoji";\n --btn-radius: 10px;\n --btn-gap: 8px;\n --btn-primary-bg: #4f46e5;\n --btn-primary-bg-hover: #4338ca;\n --btn-secondary-bg: #0ea5e9;\n --btn-secondary-bg-hover: #0284c7;\n --btn-danger-bg: #ef4444;\n --btn-danger-bg-hover: #dc2626;\n --btn-outline-color: #6b7280;\n --btn-outline-hover-bg: rgba(107,114,128,0.08);\n --btn-text-color: #ffffff;\n --btn-disabled-opacity: 0.6;\n --btn-shadow: 0 8px 20px rgba(0,0,0,0.12);\n --btn-shadow-hover: 0 10px 24px rgba(0,0,0,0.16);\n }\n\n .btn {\n position: relative;\n appearance: none;\n border: 0;\n border-radius: var(--btn-radius);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--btn-gap);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n font-family: var(--btn-font-family);\n font-weight: 700;\n letter-spacing: .3px;\n transition: background-color .2s ease, box-shadow .2s ease, transform .06s ease;\n box-shadow: var(--btn-shadow);\n color: var(--btn-text-color);\n }\n\n .btn:active { transform: translateY(1px); }\n\n /* 尺寸 */\n .btn--sm { font-size: 12px; padding: 6px 12px; }\n .btn--md { font-size: 14px; padding: 10px 16px; }\n .btn--lg { font-size: 16px; padding: 14px 22px; }\n\n /* 变体 */\n .btn--primary { background: var(--btn-primary-bg); }\n .btn--primary:hover { background: var(--btn-primary-bg-hover); box-shadow: var(--btn-shadow-hover); }\n\n .btn--secondary { background: var(--btn-secondary-bg); }\n .btn--secondary:hover { background: var(--btn-secondary-bg-hover); box-shadow: var(--btn-shadow-hover); }\n\n .btn--danger { background: var(--btn-danger-bg); }\n .btn--danger:hover { background: var(--btn-danger-bg-hover); box-shadow: var(--btn-shadow-hover); }\n\n .btn--outline {\n background: transparent;\n border: 2px solid var(--btn-outline-color);\n color: var(--btn-outline-color);\n box-shadow: none;\n }\n .btn--outline:hover {\n background: var(--btn-outline-hover-bg);\n }\n\n /* 状态 */\n .btn[disabled] {\n cursor: not-allowed;\n opacity: var(--btn-disabled-opacity);\n box-shadow: none;\n transform: none;\n }\n\n .btn__spinner {\n width: 16px;\n height: 16px;\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,0.6);\n border-top-color: rgba(255,255,255,1);\n animation: spin .8s linear infinite;\n }\n\n @keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n </style>\n\n <button part="button" class="btn btn--${this._variant} btn--${this._size}" ${this._disabled?"disabled":""} aria-busy="${this._loading}">\n ${this._loading?'<span class="btn__spinner" aria-hidden="true"></span>':""}\n ${t}\n </button>\n `,this.addEventListeners()}} /** * Web Components Demo Package * A collection of modern Web Components including counter and data table components * * @version 1.0.0 * @license MIT */var a={CounterComponent:t,DataTable:n,CustomButton:e};"undefined"!=typeof window&&window.customElements&&(window.customElements.get("counter-component")||window.customElements.define("counter-component",t),window.customElements.get("data-table")||window.customElements.define("data-table",n),window.customElements.get("custom-button")||window.customElements.define("custom-button",e)),"undefined"!=typeof globalThis&&(globalThis.CounterComponent=t,globalThis.DataTable=n,globalThis.CustomButton=e),exports.CounterComponent=t,exports.CustomButton=e,exports.DataTable=n,exports.default=a; //# sourceMappingURL=index.js.map