@designbasekorea/ui-wc 0.9.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +2 -0
- package/dist/esm/components/db-accordion.d.ts +22 -10
- package/dist/esm/components/db-accordion.js +1 -1
- package/dist/esm/components/db-avatar.js +1 -1
- package/dist/esm/components/db-button.d.ts +33 -1
- package/dist/esm/components/db-button.js +1 -1
- package/dist/esm/components/db-chat-orb.d.ts +13 -0
- package/dist/esm/components/db-chat-orb.js +1 -1
- package/dist/esm/components/db-chat-room.js +1 -1
- package/dist/esm/components/db-chat-widget.js +1 -1
- package/dist/esm/components/db-checkbox.d.ts +3 -0
- package/dist/esm/components/db-checkbox.js +1 -1
- package/dist/esm/components/db-confetti.d.ts +11 -5
- package/dist/esm/components/db-confetti.js +1 -1
- package/dist/esm/components/db-email-verify.d.ts +36 -7
- package/dist/esm/components/db-email-verify.js +1 -1
- package/dist/esm/components/db-floating-action-button.d.ts +1 -1
- package/dist/esm/components/db-floating-action-button.js +1 -1
- package/dist/esm/components/db-input.d.ts +8 -1
- package/dist/esm/components/db-input.js +1 -1
- package/dist/esm/components/db-navbar.d.ts +3 -0
- package/dist/esm/components/db-navbar.js +1 -1
- package/dist/esm/components/db-otp-input.js +1 -1
- package/dist/esm/components/db-page-header.d.ts +11 -0
- package/dist/esm/components/db-page-header.js +1 -1
- package/dist/esm/components/db-phone-verify.d.ts +33 -11
- package/dist/esm/components/db-phone-verify.js +1 -1
- package/dist/esm/components/db-radio.d.ts +3 -0
- package/dist/esm/components/db-radio.js +1 -1
- package/dist/esm/components/db-range-slider.d.ts +35 -7
- package/dist/esm/components/db-range-slider.js +1 -1
- package/dist/esm/components/db-select.d.ts +35 -6
- package/dist/esm/components/db-select.js +1 -1
- package/dist/esm/components/db-tabs.d.ts +36 -13
- package/dist/esm/components/db-tabs.js +1 -1
- package/dist/esm/components/db-textarea.d.ts +13 -1
- package/dist/esm/components/db-textarea.js +1 -1
- package/dist/esm/components/db-toggle.d.ts +33 -4
- package/dist/esm/components/db-toggle.js +1 -1
- package/dist/esm/components/db-two-factor.d.ts +35 -12
- package/dist/esm/components/db-two-factor.js +1 -1
- package/dist/esm/core/control-label.js +1 -0
- package/dist/esm/core/i18n-copy.js +1 -1
- package/dist/esm/core/range-values.js +1 -0
- package/dist/esm/core/text-field-state.js +1 -0
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +362 -77
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +5431 -634
- package/dist/react/index.esm.js +1 -1
- package/package.json +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setHostClasses as e}from"../core/host-class.js";import{labelFrom as t,t as s,dbFormat as i}from"../core/i18n.js";import{getDbComponentIconSize as r,createDbIcon as a}from"./db-icons.js";import"./db-checkbox.js";import{dbUid as n}from"../core/uid.js";import{SELECT_SIZES as l,SELECT_POSITIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as c}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";class DbSelect extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.built=!1,this.searchTerm="",this.focusedIndex=-1,this.handleTriggerClick=()=>{this.hasAttribute("disabled")||this.hasAttribute("readonly")||(this.open=!this.open,this.open&&this.searchable&&setTimeout(()=>this.searchInput?.focus(),0))},this.handleTriggerFocus=()=>{this.trigger?.classList.add("designbase-wc-select__trigger--focused")},this.handleTriggerBlur=()=>{this.trigger?.classList.remove("designbase-wc-select__trigger--focused")},this.handleClear=e=>{e.stopPropagation();const t=[];this.setSelectedValues(t),this.syncTrigger(),this.syncOptions(),this.dispatchChange(t)},this.handleSearchInput=()=>{this.searchTerm=this.searchInput?.value||"",this.focusedIndex=-1,this.syncOptions()},this.handleDocumentMouseDown=e=>{this.contains(e.target)||(this.open=!1,this.searchTerm="",this.searchInput&&(this.searchInput.value=""),this.focusedIndex=-1,this.syncOptions())},this.handleDocumentKeyDown=e=>{if(!this.contains(document.activeElement))return;if(!this.open)return void("Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.open=!0));const t=this.getFilteredOptions();switch(e.key){case"Escape":e.preventDefault(),this.open=!1,this.searchTerm="",this.searchInput&&(this.searchInput.value=""),this.focusedIndex=-1,this.syncOptions();break;case"ArrowDown":e.preventDefault(),this.focusedIndex=Math.min(this.focusedIndex+1,t.length-1),this.syncOptions();break;case"ArrowUp":e.preventDefault(),this.focusedIndex=Math.max(this.focusedIndex-1,0),this.syncOptions();break;case"Enter":e.preventDefault(),this.focusedIndex>=0&&t[this.focusedIndex]&&this.selectOption(t[this.focusedIndex])}}}static get observedAttributes(){return["options","value","placeholder","label","size","full-width","disabled","readonly","required","error","error-message","helper-text","multiple","searchable","show-clear-button","open","max-height","position","dropdown-width","name"]}get name(){return this.getAttribute("name")??""}set name(e){this.setAttribute("name",e)}get open(){return this.hasAttribute("open")}set open(e){this.toggleAttribute("open",e),this.syncOpenState()}get value(){return this.getAttribute("value")||""}set value(e){e?this.setAttribute("value",e):this.removeAttribute("value"),this.syncTrigger(),this.syncOptions(),this.syncFormValue()}connectedCallback(){this.built||this.build(),this.syncState(),queueMicrotask(()=>{this.isConnected&&this.syncFormValue()}),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}formAssociatedCallback(){this.syncFormValue()}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown)}formResetCallback(){this.removeAttribute("value"),this.internals.setFormValue(null),this.built&&(this.syncTrigger(),this.syncOptions(),this.syncFormValue())}formDisabledCallback(e){this.toggleAttribute("disabled",e)}attributeChangedCallback(e){if(this.built){if("open"!==e)return"value"===e?(this.syncTrigger(),this.syncOptions(),void this.syncFormValue()):void this.syncState();this.syncOpenState()}}get multiple(){return this.hasAttribute("multiple")}set multiple(e){this.toggleAttribute("multiple",Boolean(e))}get searchable(){return this.hasAttribute("searchable")}set searchable(e){this.toggleAttribute("searchable",Boolean(e))}get showClearButton(){return!this.hasAttribute("show-clear-button")||"false"!==this.getAttribute("show-clear-button")}parseOptions(){const e=this.getAttribute("options")||"[]";try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return e.split(",").map(e=>e.trim()).filter(Boolean).map(e=>({value:e,label:e}))}}parseSelectedValues(){const e=this.getAttribute("value")||"";if(!e)return[];if(this.multiple)try{const t=JSON.parse(e);return Array.isArray(t)?t.map(String):[]}catch{return e.split(",").map(e=>e.trim()).filter(Boolean)}return e?[e]:[]}setSelectedValues(e){this.multiple?e.length?this.setAttribute("value",JSON.stringify(e)):this.removeAttribute("value"):e[0]?this.setAttribute("value",e[0]):this.removeAttribute("value")}syncFormValue(){const e=this.parseSelectedValues();if(this.multiple){const t=new FormData;return e.forEach(e=>t.append(this.name||"select",e)),void this.internals.setFormValue(e.length?t:null)}this.internals.setFormValue(e[0]||null)}getIconSize(){const e=this.getAttribute("size")||"m";return r(l.includes(e)?e:"m")}syncIndicatorIcons(){const e=this.getIconSize();this.clearButton?.replaceChildren(a("close",e)),this.chevronEl&&this.chevronEl.replaceChildren(a(this.open?"chevron-up":"chevron-down",e))}build(){const e=this.getAttribute("id")||n("db-select"),s=`${e}-listbox`;this.hasAttribute("id")||this.setAttribute("id",e),this.labelEl=document.createElement("label"),this.labelEl.className="designbase-wc-select__label",this.trigger=document.createElement("div"),this.trigger.className="designbase-wc-select__trigger",this.trigger.tabIndex=0,this.trigger.setAttribute("role","combobox"),this.trigger.setAttribute("aria-haspopup","listbox"),this.trigger.setAttribute("aria-controls",s),this.trigger.addEventListener("click",this.handleTriggerClick),this.trigger.addEventListener("focus",this.handleTriggerFocus),this.trigger.addEventListener("blur",this.handleTriggerBlur),this.valueEl=document.createElement("div"),this.valueEl.className="designbase-wc-select__value",this.indicatorsEl=document.createElement("div"),this.indicatorsEl.className="designbase-wc-select__indicators",this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="designbase-wc-select__clear-button",this.clearButton.setAttribute("aria-label",t(this,"label-clear","clearAll")),this.clearButton.hidden=!0,this.clearButton.appendChild(a("close",this.getIconSize())),this.clearButton.addEventListener("click",this.handleClear),this.chevronEl=document.createElement("div"),this.chevronEl.className="designbase-wc-select__chevron",this.indicatorsEl.append(this.clearButton,this.chevronEl),this.trigger.append(this.valueEl,this.indicatorsEl),this.dropdown=document.createElement("div"),this.dropdown.className="designbase-wc-select__dropdown",this.searchWrap=document.createElement("div"),this.searchWrap.className="designbase-wc-select__search",this.searchWrap.hidden=!0,this.searchInput=document.createElement("input"),this.searchInput.type="text",this.searchInput.className="designbase-wc-select__search-input",this.searchInput.placeholder=t(this,"label-search","search.label"),this.searchInput.addEventListener("input",this.handleSearchInput),this.searchInput.addEventListener("mousedown",e=>e.stopPropagation()),this.searchInput.addEventListener("click",e=>e.stopPropagation()),this.searchWrap.appendChild(this.searchInput),this.optionsEl=document.createElement("div"),this.optionsEl.className="designbase-wc-select__options",this.optionsEl.id=s,this.optionsEl.setAttribute("role","listbox"),this.dropdown.append(this.searchWrap,this.optionsEl),this.helperEl=document.createElement("p"),this.helperEl.className="designbase-wc-select__helper-text",this.errorEl=document.createElement("p"),this.errorEl.className="designbase-wc-select__error-message",this.append(this.labelEl,this.trigger,this.dropdown,this.helperEl,this.errorEl),this.built=!0}getFilteredOptions(){const e=this.parseOptions();if(!this.searchable||!this.searchTerm)return e;const t=this.searchTerm.toLowerCase();return e.filter(e=>e.label.toLowerCase().includes(t))}selectOption(e){if(e.disabled)return;const t=this.parseSelectedValues();let s;this.multiple?s=t.includes(e.value)?t.filter(t=>t!==e.value):[...t,e.value]:(s=[e.value],this.open=!1,this.searchTerm="",this.searchInput&&(this.searchInput.value=""),this.focusedIndex=-1),this.setSelectedValues(s),this.syncTrigger(),this.syncOptions(),this.dispatchChange(s)}dispatchChange(e){const t=this.parseOptions();if(this.multiple)return this.syncFormValue(),this.dispatchEvent(new Event("change",{bubbles:!0})),void this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e,labels:e.map(e=>t.find(t=>t.value===e)?.label||e)},bubbles:!0,composed:!0}));const s=e[0]||"",i=t.find(e=>e.value===s)?.label||"";this.syncFormValue(),this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:s,label:i},bubbles:!0,composed:!0}))}syncAccessibleName(e){if(!this.trigger)return;if(e&&this.labelEl)return this.labelEl.id||(this.labelEl.id=n("db-select-label")),this.trigger.setAttribute("aria-labelledby",this.labelEl.id),void this.trigger.removeAttribute("aria-label");this.trigger.removeAttribute("aria-labelledby");const t=this.getAttribute("aria-label")||this.getAttribute("placeholder")||s("select.placeholder");this.trigger.setAttribute("aria-label",t)}syncState(){if(!this.trigger||!this.dropdown||!this.optionsEl)return;const t=c(this.getAttribute("size"),l,"m"),s=c(this.getAttribute("position"),h,"bottom"),i="full"===this.getAttribute("dropdown-width")?"full":"auto",r=Number(this.getAttribute("max-height")||200),a=this.getAttribute("label")||"",n=this.getAttribute("helper-text")||"",o=this.getAttribute("error-message")||"",d=this.hasAttribute("error"),u=this.getAttribute("id")||"";e(this,["designbase-wc-select",`designbase-wc-select--${t}`,this.open&&"designbase-wc-select--open",d&&"designbase-wc-select--error",this.hasAttribute("disabled")&&"designbase-wc-select--disabled",this.hasAttribute("readonly")&&"designbase-wc-select--readonly",this.hasAttribute("full-width")&&"designbase-wc-select--full-width",this.multiple&&"designbase-wc-select--multiple",this.searchable&&"designbase-wc-select--searchable"]);const p=this.parseSelectedValues();if(this.classList.toggle("designbase-wc-select--has-value",p.length>0),this.labelEl){const e=this.hasAttribute("required")?'<span class="designbase-wc-select__required" aria-hidden="true">*</span>':"";this.labelEl.innerHTML=a?`${this.escape(a)}${e}`:"",this.labelEl.hidden=!a}this.syncAccessibleName(a),this.dropdown.className=["designbase-wc-select__dropdown",`designbase-wc-select__dropdown--${i}`,`designbase-wc-select__dropdown--${s}`,this.open&&"designbase-wc-select__dropdown--open"].filter(Boolean).join(" "),this.optionsEl.style.maxHeight=`${r}px`,this.searchWrap&&(this.searchWrap.hidden=!this.searchable);const b=`${u}-helper`,g=`${u}-error`;d&&o?(this.errorEl.id=g,this.errorEl.textContent=o,this.errorEl.hidden=!1,this.helperEl.hidden=!0,this.trigger.setAttribute("aria-describedby",g),this.trigger.setAttribute("aria-invalid","true")):n?(this.helperEl.id=b,this.helperEl.textContent=n,this.helperEl.hidden=!1,this.errorEl.hidden=!0,this.trigger.setAttribute("aria-describedby",b),this.trigger.removeAttribute("aria-invalid")):(this.helperEl.hidden=!0,this.errorEl.hidden=!0,this.trigger.removeAttribute("aria-describedby"),this.trigger.removeAttribute("aria-invalid")),this.hasAttribute("disabled")||this.hasAttribute("readonly")?this.trigger.tabIndex=-1:this.trigger.tabIndex=0,this.syncOpenState(),this.syncTrigger(),this.syncOptions(),this.syncFormValue(),this.syncIndicatorIcons()}syncOpenState(){this.trigger&&this.dropdown&&this.chevronEl&&(this.trigger.setAttribute("aria-expanded",String(this.open)),this.classList.toggle("designbase-wc-select--open",this.open),this.dropdown.classList.toggle("designbase-wc-select__dropdown--open",this.open),this.syncIndicatorIcons())}syncTrigger(){if(!this.valueEl||!this.clearButton)return;const e=this.parseOptions(),t=this.parseSelectedValues(),r=this.getAttribute("placeholder")||s("select.placeholder"),n=t.length>0,l=n&&this.showClearButton&&!this.hasAttribute("disabled")&&!this.hasAttribute("readonly");if(this.valueEl.replaceChildren(),this.multiple)if(0===t.length){const e=document.createElement("span");e.className="designbase-wc-select__placeholder",e.textContent=r,this.valueEl.appendChild(e)}else{const s=document.createElement("div");s.className="designbase-wc-select__tags",t.forEach(r=>{const n=e.find(e=>e.value===r),l=document.createElement("span");l.className="designbase-wc-select__tag";const h=document.createElement("span");h.className="designbase-wc-select__tag-label",h.textContent=n?.label||r;const c=document.createElement("button");c.type="button",c.className="designbase-wc-select__tag-remove",c.setAttribute("aria-label",i("{0} 제거",[n?.label||r])),c.appendChild(a("close",12)),c.addEventListener("click",e=>{e.stopPropagation();const s=t.filter(e=>e!==r);this.setSelectedValues(s),this.syncTrigger(),this.syncOptions(),this.dispatchChange(s)}),l.append(h,c),s.appendChild(l)}),this.valueEl.appendChild(s)}else{const s=document.createElement("span");s.className="designbase-wc-select__single-value";const i=e.find(e=>e.value===t[0]);s.textContent=n?i?.label||t[0]:r,n||s.classList.add("designbase-wc-select__placeholder"),this.valueEl.appendChild(s)}this.clearButton.hidden=!l,this.clearButton.setAttribute("aria-hidden",l?"false":"true"),this.classList.toggle("designbase-wc-select--has-value",n)}syncOptions(){if(!this.optionsEl)return;const e=this.getFilteredOptions(),s=this.parseSelectedValues(),i=this.getAttribute("id")||"db-select";if(this.optionsEl.replaceChildren(),0===e.length){const e=document.createElement("div");return e.className="designbase-wc-select__no-options",e.textContent=this.searchTerm?t(this,"label-no-results","select.noResults"):t(this,"label-empty","select.noResults"),void this.optionsEl.appendChild(e)}e.forEach((e,t)=>{const r=s.includes(e.value),a=t===this.focusedIndex,n=document.createElement("div");if(n.className=["designbase-wc-select__option",r&&"designbase-wc-select__option--selected",a&&"designbase-wc-select__option--focused",e.disabled&&"designbase-wc-select__option--disabled"].filter(Boolean).join(" "),n.id=`${i}-option-${t}`,n.setAttribute("role","option"),n.setAttribute("aria-selected",String(r)),n.setAttribute("aria-disabled",String(Boolean(e.disabled))),n.addEventListener("click",()=>this.selectOption(e)),this.multiple){const t=document.createElement("div");t.className="designbase-wc-select__checkbox";const s=document.createElement("db-checkbox");s.setAttribute("size","s"),s.setAttribute("has-label","false"),r&&s.setAttribute("checked",""),e.disabled&&s.setAttribute("disabled",""),t.appendChild(s),n.appendChild(t)}const l=document.createElement("span");l.className="designbase-wc-select__option-label",l.textContent=e.label,n.appendChild(l),this.optionsEl.appendChild(n)}),this.focusedIndex>=0?this.trigger?.setAttribute("aria-activedescendant",`${i}-option-${this.focusedIndex}`):this.trigger?.removeAttribute("aria-activedescendant")}escape(e){return e.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[e]||e))}}DbSelect.formAssociated=!0,customElements.get("db-select")||customElements.define("db-select",DbSelect);export{DbSelect};
|
|
1
|
+
import{setHostClasses as e}from"../core/host-class.js";import{t,labelFrom as s,dbFormat as i}from"../core/i18n.js";import{getDbComponentIconSize as a,createDbIcon as r}from"./db-icons.js";import{dbUid as l}from"../core/uid.js";import{SELECT_SIZES as n,SELECT_POSITIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";class DbSelect extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.built=!1,this.searchTerm="",this.focusedIndex=-1,this.awaitingValue=!0,this.userInteracted=!1,this.formDisabled=!1,this.wasOpen=!1,this.typeahead="",this.typeaheadAt=0,this.handleTriggerClick=()=>{this.locked||(this.open=!this.open)},this.handleTriggerFocus=()=>{this.trigger?.classList.add("designbase-wc-select__trigger--focused")},this.handleTriggerBlur=()=>{this.trigger?.classList.remove("designbase-wc-select__trigger--focused")},this.handleClear=e=>{if(e.stopPropagation(),this.locked)return;this.userInteracted=!0,this.awaitingValue=!1;const t=[];this.setSelectedValues(t),this.syncTrigger(),this.syncOptions(),this.dispatchChange(t),this.focus()},this.handleSearchInput=()=>{this.searchTerm=this.searchInput?.value||"",this.focusedIndex=-1,this.syncOptions()},this.handleDocumentMouseDown=e=>{!e.composedPath().includes(this)&&this.open&&(this.open=!1)},this.handleFocusOut=()=>{queueMicrotask(()=>{const e=this.getRootNode();this.isConnected&&!this.contains(e.activeElement)&&(this.open=!1)})},this.handleDocumentKeyDown=e=>{if(!(this.locked||e.target!==this.trigger&&e.target!==this.searchInput))if("Tab"!==e.key){if(!this.open&&["Enter"," ","ArrowDown","ArrowUp"].includes(e.key))return e.preventDefault(),this.open=!0,void("ArrowDown"!==e.key&&"ArrowUp"!==e.key||this.moveFocus("ArrowDown"===e.key?"first":"last"));switch(e.key){case"Escape":if(!this.open)return;e.preventDefault(),e.stopPropagation(),this.open=!1,this.focus();break;case"ArrowDown":case"ArrowUp":if(!this.open)return;e.preventDefault(),this.moveFocus("ArrowDown"===e.key?"next":"previous");break;case"Home":case"End":if(e.target===this.searchInput||!this.open)return;e.preventDefault(),this.moveFocus("Home"===e.key?"first":"last");break;case"Enter":case" ":if(!this.open||" "===e.key&&e.target===this.searchInput)return;e.preventDefault();const t=this.getFilteredOptions()[this.focusedIndex];t&&this.selectOption(t);break;default:if(e.target===this.searchInput||1!==e.key.length||e.ctrlKey||e.metaKey||e.altKey)return;const s=performance.now();this.typeahead=s-this.typeaheadAt>700?e.key:this.typeahead+e.key,this.typeaheadAt=s,this.open=!0,this.focusedIndex=this.getFilteredOptions().findIndex(e=>!e.disabled&&e.label.toLocaleLowerCase().startsWith(this.typeahead.toLocaleLowerCase())),this.syncOptions()}}else this.open=!1}}static get observedAttributes(){return["options","value","placeholder","label","size","full-width","disabled","readonly","required","error","error-message","helper-text","multiple","searchable","show-clear-button","open","max-height","position","dropdown-width","name","default-value","aria-label","aria-labelledby","aria-describedby","label-search","label-clear","label-no-results","label-empty"]}get defaultValue(){return this.getAttribute("default-value")??this.initialValue??this.value}set defaultValue(e){this.setAttribute("default-value",Array.isArray(e)?JSON.stringify(e):e)}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",Boolean(e))}get readOnly(){return this.hasAttribute("readonly")}set readOnly(e){this.toggleAttribute("readonly",Boolean(e))}get required(){return this.hasAttribute("required")}set required(e){this.toggleAttribute("required",Boolean(e))}get form(){return this.internals.form}get validity(){return this.internals.validity}get validationMessage(){return this.internals.validationMessage}get willValidate(){return this.internals.willValidate}checkValidity(){return this.internals.checkValidity()}reportValidity(){return this.internals.reportValidity()}focus(e){this.trigger?.focus(e)}get unavailable(){return this.disabled||this.formDisabled}get locked(){return this.unavailable||this.readOnly}captureDefault(){void 0===this.initialValue&&(this.initialValue=this.getAttribute("default-value")??this.value,this.awaitingValue=!this.hasAttribute("value")&&!this.hasAttribute("default-value"),!this.hasAttribute("value")&&this.initialValue&&this.setAttribute("value",this.initialValue))}get name(){return this.getAttribute("name")??""}set name(e){this.setAttribute("name",e)}get open(){return this.hasAttribute("open")}set open(e){const t=Boolean(e)&&!this.locked;this.open!==t&&this.toggleAttribute("open",t)}get value(){return this.getAttribute("value")||""}set value(e){const t=Array.isArray(e)?JSON.stringify(e):e;t?this.setAttribute("value",t):this.removeAttribute("value"),this.syncTrigger(),this.syncOptions(),this.syncFormValue()}connectedCallback(){for(const e of["name","value","defaultValue","disabled","readOnly","required","multiple","searchable","open"]){if(!Object.prototype.hasOwnProperty.call(this,e))continue;const t=this,s=t[e];delete t[e],t[e]=s}this.captureDefault(),this.built||this.build(),this.syncState(),queueMicrotask(()=>{this.isConnected&&this.syncFormValue()}),document.addEventListener("mousedown",this.handleDocumentMouseDown),this.addEventListener("keydown",this.handleDocumentKeyDown),this.addEventListener("focusout",this.handleFocusOut)}formAssociatedCallback(){this.syncFormValue()}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),this.removeEventListener("keydown",this.handleDocumentKeyDown),this.removeEventListener("focusout",this.handleFocusOut),this.open=!1,this.cancelSearchFocus()}formResetCallback(){this.value=this.defaultValue,this.userInteracted=!1,this.open=!1,this.syncState()}formStateRestoreCallback(e){"string"==typeof e&&(this.value=e)}formDisabledCallback(e){this.formDisabled=e,this.built&&this.syncState()}attributeChangedCallback(e,t){if("value"===e&&void 0!==this.initialValue&&this.awaitingValue&&!this.userInteracted&&(this.initialValue=this.value,this.awaitingValue=!1),this.built){if("multiple"===e){let e=[];if(null!==t)try{const t=JSON.parse(this.value);e=Array.isArray(t)?t.map(String):[this.value]}catch{e=this.value.split(",").filter(Boolean)}else e=this.value?[this.value]:[];this.setSelectedValues(this.multiple?e:e.slice(0,1))}if("default-value"!==e||this.userInteracted||(this.value=this.defaultValue),"open"!==e)return"value"===e?(this.syncTrigger(),this.syncOptions(),void this.syncFormValue()):void this.syncState();this.syncOpenState()}}get multiple(){return this.hasAttribute("multiple")}set multiple(e){this.toggleAttribute("multiple",Boolean(e))}get searchable(){return this.hasAttribute("searchable")}set searchable(e){this.toggleAttribute("searchable",Boolean(e))}get showClearButton(){return!this.hasAttribute("show-clear-button")||"false"!==this.getAttribute("show-clear-button")}parseOptions(){const e=this.getAttribute("options")||"[]";try{const t=JSON.parse(e);if(!Array.isArray(t))return[];const s=new Set;return t.flatMap(e=>{if(!e||"object"!=typeof e)return[];const t=e;if(!["string","number"].includes(typeof t.value)||!["string","number"].includes(typeof t.label))return[];const i=String(t.value);return s.has(i)?[]:(s.add(i),[{value:i,label:String(t.label),disabled:!0===t.disabled}])})}catch{return e.split(",").map(e=>e.trim()).filter(Boolean).map(e=>({value:e,label:e}))}}parseSelectedValues(){const e=this.getAttribute("value")||"";if(!e)return[];if(this.multiple)try{const t=JSON.parse(e);return Array.isArray(t)?[...new Set(t.filter(e=>"string"==typeof e||"number"==typeof e).map(String))]:[]}catch{return e.split(",").map(e=>e.trim()).filter(Boolean)}return e?[e]:[]}setSelectedValues(e){this.multiple?e.length?this.setAttribute("value",JSON.stringify(e)):this.removeAttribute("value"):e[0]?this.setAttribute("value",e[0]):this.removeAttribute("value")}syncFormValue(){const e=this.parseSelectedValues(),s=this.value;if(this.unavailable||!this.name)this.internals.setFormValue(null,s);else if(this.multiple){const t=new FormData;e.forEach(e=>t.append(this.name,e)),this.internals.setFormValue(e.length?t:null,s)}else this.internals.setFormValue(e[0]||null,s);const i=this.required&&!this.locked&&0===e.length;this.internals.setValidity(i?{valueMissing:!0}:{},i?t("required"):"",this.trigger)}getIconSize(){const e=this.getAttribute("size")||"m";return a(n.includes(e)?e:"m")}syncIndicatorIcons(){const e=this.getIconSize(),update=(t,s)=>{if(!t)return;const i=t.querySelector(":scope > svg[data-designbase-icon]");i?.getAttribute("data-designbase-icon")===s&&i.getAttribute("width")===String(e)||t.replaceChildren(r(s,e))};update(this.clearButton,"close"),update(this.chevronEl,this.open?"chevron-up":"chevron-down")}build(){const e=this.getAttribute("id")||l("db-select"),t=`${e}-listbox`;this.hasAttribute("id")||this.setAttribute("id",e),this.labelEl=document.createElement("label"),this.labelEl.className="designbase-wc-select__label",this.labelEl.addEventListener("click",()=>this.focus()),this.trigger=document.createElement("div"),this.trigger.className="designbase-wc-select__trigger",this.trigger.tabIndex=0,this.trigger.setAttribute("role","combobox"),this.trigger.setAttribute("aria-haspopup","listbox"),this.trigger.setAttribute("aria-controls",t),this.trigger.addEventListener("click",this.handleTriggerClick),this.trigger.addEventListener("focus",this.handleTriggerFocus),this.trigger.addEventListener("blur",this.handleTriggerBlur),this.valueEl=document.createElement("div"),this.valueEl.className="designbase-wc-select__value",this.indicatorsEl=document.createElement("div"),this.indicatorsEl.className="designbase-wc-select__indicators",this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="designbase-wc-select__clear-button",this.clearButton.setAttribute("aria-label",s(this,"label-clear","clearAll")),this.clearButton.hidden=!0,this.clearButton.appendChild(r("close",this.getIconSize())),this.clearButton.addEventListener("click",this.handleClear),this.chevronEl=document.createElement("div"),this.chevronEl.className="designbase-wc-select__chevron",this.indicatorsEl.append(this.clearButton,this.chevronEl),this.trigger.append(this.valueEl,this.indicatorsEl),this.dropdown=document.createElement("div"),this.dropdown.className="designbase-wc-select__dropdown",this.searchWrap=document.createElement("div"),this.searchWrap.className="designbase-wc-select__search",this.searchWrap.hidden=!0,this.searchInput=document.createElement("input"),this.searchInput.type="text",this.searchInput.className="designbase-wc-select__search-input",this.searchInput.placeholder=s(this,"label-search","search.label"),this.searchInput.setAttribute("role","combobox"),this.searchInput.setAttribute("aria-autocomplete","list"),this.searchInput.setAttribute("aria-controls",t),this.searchInput.addEventListener("input",this.handleSearchInput),this.searchInput.addEventListener("mousedown",e=>e.stopPropagation()),this.searchInput.addEventListener("click",e=>e.stopPropagation()),this.searchWrap.appendChild(this.searchInput),this.optionsEl=document.createElement("div"),this.optionsEl.className="designbase-wc-select__options",this.optionsEl.id=t,this.optionsEl.setAttribute("role","listbox"),this.dropdown.append(this.searchWrap,this.optionsEl),this.helperEl=document.createElement("p"),this.helperEl.className="designbase-wc-select__helper-text",this.errorEl=document.createElement("p"),this.errorEl.className="designbase-wc-select__error-message",this.append(this.labelEl,this.trigger,this.dropdown,this.helperEl,this.errorEl),this.built=!0}moveFocus(e){const t=this.getFilteredOptions().map((e,t)=>e.disabled?-1:t).filter(e=>e>=0);t.length?this.focusedIndex="first"===e?t[0]:"last"===e?t[t.length-1]:"next"===e?t.find(e=>e>this.focusedIndex)??t[t.length-1]:[...t].reverse().find(e=>e<this.focusedIndex)??t[0]:this.focusedIndex=-1,this.syncOptions()}getFilteredOptions(){const e=this.parseOptions();if(!this.searchable||!this.searchTerm)return e;const t=this.searchTerm.toLowerCase();return e.filter(e=>e.label.toLowerCase().includes(t))}selectOption(e){if(this.locked||e.disabled)return;this.userInteracted=!0,this.awaitingValue=!1;const t=this.parseSelectedValues();let s;this.multiple?s=t.includes(e.value)?t.filter(t=>t!==e.value):[...t,e.value]:(s=[e.value],this.open=!1,this.searchTerm="",this.searchInput&&(this.searchInput.value=""),this.focusedIndex=-1),this.setSelectedValues(s),this.syncTrigger(),this.syncOptions(),this.dispatchChange(s),this.multiple||this.focus()}dispatchChange(e){const t=this.parseOptions();if(this.multiple)return this.syncFormValue(),this.dispatchEvent(new Event("change",{bubbles:!0})),void this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e,labels:e.map(e=>t.find(t=>t.value===e)?.label||e)},bubbles:!0,composed:!0}));const s=e[0]||"",i=t.find(e=>e.value===s)?.label||"";this.syncFormValue(),this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:s,label:i},bubbles:!0,composed:!0}))}syncAccessibleName(e){var s;if(!this.trigger)return;const i=this.getAttribute("aria-label");let a=this.getAttribute("aria-labelledby");!a&&!i&&e&&this.labelEl&&((s=this.labelEl).id||(s.id=l("db-select-label")),a=this.labelEl.id);for(const s of[this.trigger,this.searchInput,this.optionsEl])s&&(a?(s.setAttribute("aria-labelledby",a),s.removeAttribute("aria-label")):(s.removeAttribute("aria-labelledby"),s.setAttribute("aria-label",i||e||this.getAttribute("placeholder")||t("select.placeholder"))))}syncState(){if(!this.trigger||!this.dropdown||!this.optionsEl)return;const t=o(this.getAttribute("size"),n,"m"),i=o(this.getAttribute("position"),h,"bottom"),a="full"===this.getAttribute("dropdown-width")?"full":"auto",r=Number(this.getAttribute("max-height")||200),l=Number.isFinite(r)&&r>0?r:200,c=this.getAttribute("label")||"",d=this.getAttribute("helper-text")||"",u=this.getAttribute("error-message")||"",p=this.hasAttribute("error"),b=this.getAttribute("id")||"";e(this,["designbase-wc-select",`designbase-wc-select--${t}`,this.open&&"designbase-wc-select--open",p&&"designbase-wc-select--error",this.unavailable&&"designbase-wc-select--disabled",this.hasAttribute("readonly")&&"designbase-wc-select--readonly",this.hasAttribute("full-width")&&"designbase-wc-select--full-width",this.multiple&&"designbase-wc-select--multiple",this.searchable&&"designbase-wc-select--searchable"]);const g=this.parseSelectedValues();if(this.classList.toggle("designbase-wc-select--has-value",g.length>0),this.labelEl){const e=this.hasAttribute("required")?'<span class="designbase-wc-select__required" aria-hidden="true">*</span>':"";this.labelEl.innerHTML=c?`${this.escape(c)}${e}`:"",this.labelEl.hidden=!c}this.syncAccessibleName(c),this.dropdown.className=["designbase-wc-select__dropdown",`designbase-wc-select__dropdown--${a}`,`designbase-wc-select__dropdown--${i}`,this.open&&"designbase-wc-select__dropdown--open"].filter(Boolean).join(" "),this.optionsEl.style.maxHeight=`${l}px`,this.searchWrap&&(this.searchWrap.hidden=!this.searchable);const m=`${b}-helper`,v=`${b}-error`;this.trigger.setAttribute("aria-required",String(this.required)),this.trigger.setAttribute("aria-disabled",String(this.unavailable)),this.trigger.setAttribute("aria-readonly",String(this.readOnly)),this.searchInput.disabled=this.locked,this.searchInput.placeholder=s(this,"label-search","search.label"),this.clearButton.setAttribute("aria-label",s(this,"label-clear","clearAll")),this.optionsEl.setAttribute("aria-multiselectable",String(this.multiple)),p&&u?(this.errorEl.id=v,this.errorEl.textContent=u,this.errorEl.hidden=!1,this.helperEl.hidden=!0,this.trigger.setAttribute("aria-describedby",v),this.trigger.setAttribute("aria-invalid","true")):d?(this.helperEl.id=m,this.helperEl.textContent=d,this.helperEl.hidden=!1,this.errorEl.hidden=!0,this.trigger.setAttribute("aria-describedby",m),this.trigger.removeAttribute("aria-invalid")):(this.helperEl.hidden=!0,this.errorEl.hidden=!0,this.trigger.removeAttribute("aria-describedby"),this.trigger.removeAttribute("aria-invalid")),p&&this.trigger.setAttribute("aria-invalid","true");const f=[this.getAttribute("aria-describedby"),this.trigger.getAttribute("aria-describedby")].filter(Boolean).join(" ");f&&this.trigger.setAttribute("aria-describedby",[...new Set(f.split(/\s+/))].join(" "));for(const e of["aria-describedby","aria-required","aria-invalid"]){const t=this.trigger.getAttribute(e);null===t?this.searchInput.removeAttribute(e):this.searchInput.setAttribute(e,t)}this.unavailable?this.trigger.tabIndex=-1:this.trigger.tabIndex=0,this.syncOpenState(),this.syncTrigger(),this.syncOptions(),this.syncFormValue(),this.syncIndicatorIcons()}syncOpenState(){if(!this.trigger||!this.dropdown||!this.chevronEl)return;if(this.locked&&this.open)return void this.removeAttribute("open");const e=this.open&&!this.wasOpen;this.wasOpen=this.open,this.trigger.setAttribute("aria-expanded",String(this.open)),this.searchInput?.setAttribute("aria-expanded",String(this.open)),this.classList.toggle("designbase-wc-select--open",this.open),this.dropdown.classList.toggle("designbase-wc-select__dropdown--open",this.open),this.dropdown.inert=!this.open,this.open?e&&this.searchable&&this.scheduleSearchFocus():(this.cancelSearchFocus(),this.searchTerm="",this.focusedIndex=-1,this.searchInput&&(this.searchInput.value=""),this.syncOptions()),this.syncIndicatorIcons()}cancelSearchFocus(){void 0!==this.searchFocusFrame&&cancelAnimationFrame(this.searchFocusFrame),this.searchFocusFrame=void 0}scheduleSearchFocus(){this.cancelSearchFocus();const attempt=()=>{this.searchFocusFrame=void 0;const e=this.getRootNode();this.isConnected&&this.open&&this.searchable&&!this.locked&&this.searchInput&&this.contains(e.activeElement)&&("visible"===getComputedStyle(this.searchInput).visibility&&this.searchInput.getClientRects().length?this.searchInput.focus():this.dropdown?.getClientRects().length&&(this.searchFocusFrame=requestAnimationFrame(attempt)))};this.searchFocusFrame=requestAnimationFrame(attempt)}syncTrigger(){if(!this.valueEl||!this.clearButton)return;const e=this.parseOptions(),s=this.parseSelectedValues(),a=this.getAttribute("placeholder")||t("select.placeholder"),l=s.length>0,n=l&&this.showClearButton&&!this.locked;if(this.valueEl.replaceChildren(),this.multiple)if(0===s.length){const e=document.createElement("span");e.className="designbase-wc-select__placeholder",e.textContent=a,this.valueEl.appendChild(e)}else{const t=document.createElement("div");t.className="designbase-wc-select__tags",s.forEach(a=>{const l=e.find(e=>e.value===a),n=document.createElement("span");n.className="designbase-wc-select__tag";const h=document.createElement("span");h.className="designbase-wc-select__tag-label",h.textContent=l?.label||a;const o=document.createElement("button");o.type="button",o.disabled=this.locked,o.hidden=this.locked,o.className="designbase-wc-select__tag-remove",o.setAttribute("aria-label",i("{0} 제거",[l?.label||a])),o.appendChild(r("close",12)),o.addEventListener("click",e=>{if(e.stopPropagation(),this.locked)return;this.userInteracted=!0,this.awaitingValue=!1;const t=s.filter(e=>e!==a);this.setSelectedValues(t),this.syncTrigger(),this.syncOptions(),this.dispatchChange(t),this.focus()}),n.append(h,o),t.appendChild(n)}),this.valueEl.appendChild(t)}else{const t=document.createElement("span");t.className="designbase-wc-select__single-value";const i=e.find(e=>e.value===s[0]);t.textContent=l?i?.label||s[0]:a,l||t.classList.add("designbase-wc-select__placeholder"),this.valueEl.appendChild(t)}this.clearButton.hidden=!n,this.clearButton.setAttribute("aria-hidden",n?"false":"true"),this.classList.toggle("designbase-wc-select--has-value",l)}syncOptions(){if(!this.optionsEl)return;const e=this.getFilteredOptions(),t=this.parseSelectedValues(),i=this.getAttribute("id")||"db-select";if(this.optionsEl.replaceChildren(),this.trigger?.removeAttribute("aria-activedescendant"),this.searchInput?.removeAttribute("aria-activedescendant"),0===e.length){const e=document.createElement("div");return e.className="designbase-wc-select__no-options",e.textContent=this.searchTerm?s(this,"label-no-results","select.noResults"):s(this,"label-empty","select.noResults"),void this.optionsEl.appendChild(e)}if(e.forEach((e,s)=>{const a=t.includes(e.value),l=s===this.focusedIndex,n=document.createElement("div");if(n.className=["designbase-wc-select__option",a&&"designbase-wc-select__option--selected",l&&"designbase-wc-select__option--focused",e.disabled&&"designbase-wc-select__option--disabled"].filter(Boolean).join(" "),n.id=`${i}-option-${s}`,n.setAttribute("role","option"),n.setAttribute("aria-selected",String(a)),n.setAttribute("aria-disabled",String(Boolean(e.disabled))),n.addEventListener("mousedown",e=>e.preventDefault()),n.addEventListener("click",()=>this.selectOption(e)),this.multiple){const e=document.createElement("div");e.className="designbase-wc-select__checkbox",e.setAttribute("aria-hidden","true"),e.appendChild(r("done",16)),e.classList.toggle("designbase-wc-select__checkbox--checked",a),n.appendChild(e)}const h=document.createElement("span");h.className="designbase-wc-select__option-label",h.textContent=e.label,n.appendChild(h),this.optionsEl.appendChild(n)}),this.open&&this.focusedIndex>=0&&e[this.focusedIndex]&&!e[this.focusedIndex].disabled){const e=`${i}-option-${this.focusedIndex}`;this.trigger?.setAttribute("aria-activedescendant",e),this.searchInput?.setAttribute("aria-activedescendant",e);const t=this.optionsEl.children[this.focusedIndex];t.offsetTop<this.optionsEl.scrollTop?this.optionsEl.scrollTop=t.offsetTop:t.offsetTop+t.offsetHeight>this.optionsEl.scrollTop+this.optionsEl.clientHeight&&(this.optionsEl.scrollTop=t.offsetTop+t.offsetHeight-this.optionsEl.clientHeight)}else this.trigger?.removeAttribute("aria-activedescendant")}escape(e){return e.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[e]||e))}}DbSelect.formAssociated=!0,customElements.get("db-select")||customElements.define("db-select",DbSelect);export{DbSelect};
|
|
@@ -6,23 +6,32 @@ interface TabItemConfig {
|
|
|
6
6
|
}
|
|
7
7
|
declare class DbTabs extends HTMLElement {
|
|
8
8
|
static get observedAttributes(): string[];
|
|
9
|
+
private readonly uid;
|
|
10
|
+
private readonly records;
|
|
11
|
+
private readonly slotNodes;
|
|
9
12
|
private list?;
|
|
10
13
|
private indicator?;
|
|
11
|
-
private
|
|
12
|
-
private
|
|
13
|
-
private
|
|
14
|
-
private
|
|
14
|
+
private stash?;
|
|
15
|
+
private rendering;
|
|
16
|
+
private reflecting;
|
|
17
|
+
private focusedKey?;
|
|
15
18
|
private childObserver?;
|
|
16
19
|
private resizeObserver?;
|
|
17
20
|
private resizeRaf?;
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
private drag?;
|
|
22
|
+
private suppressClick;
|
|
23
|
+
private clickTimer?;
|
|
20
24
|
get tabItems(): TabItemConfig[];
|
|
21
|
-
get items(): TabItemConfig[];
|
|
22
|
-
set items(value: TabItemConfig[] | string);
|
|
23
25
|
set tabItems(value: TabItemConfig[] | string);
|
|
26
|
+
get items(): TabItemConfig[] | string;
|
|
27
|
+
set items(value: TabItemConfig[] | string);
|
|
28
|
+
get labels(): string[];
|
|
29
|
+
set labels(value: string[] | string);
|
|
30
|
+
private entries;
|
|
24
31
|
get activeIndex(): number;
|
|
25
32
|
set activeIndex(value: number);
|
|
33
|
+
get selectedId(): string;
|
|
34
|
+
set selectedId(value: string);
|
|
26
35
|
get orientation(): string;
|
|
27
36
|
set orientation(value: string);
|
|
28
37
|
get size(): string;
|
|
@@ -33,13 +42,26 @@ declare class DbTabs extends HTMLElement {
|
|
|
33
42
|
set fullWidth(value: boolean);
|
|
34
43
|
connectedCallback(): void;
|
|
35
44
|
disconnectedCallback(): void;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
private
|
|
45
|
+
attributeChangedCallback(name: string, oldValue: string | null, value: string | null): void;
|
|
46
|
+
refresh(): void;
|
|
47
|
+
focus(options?: FocusOptions): void;
|
|
48
|
+
private slotIndex;
|
|
49
|
+
private collectSlots;
|
|
50
|
+
private createRecord;
|
|
51
|
+
private hideUnassigned;
|
|
40
52
|
private render;
|
|
53
|
+
private syncRoving;
|
|
41
54
|
private select;
|
|
42
|
-
private
|
|
55
|
+
private navigate;
|
|
56
|
+
private ensureVisible;
|
|
57
|
+
private beginDrag;
|
|
58
|
+
private moveDrag;
|
|
59
|
+
private finishDrag;
|
|
60
|
+
private cancelDrag;
|
|
61
|
+
private endDrag;
|
|
62
|
+
private captureClick;
|
|
63
|
+
private handleResize;
|
|
64
|
+
private handleListScroll;
|
|
43
65
|
private updateIndicator;
|
|
44
66
|
}
|
|
45
67
|
declare global {
|
|
@@ -49,3 +71,4 @@ declare global {
|
|
|
49
71
|
}
|
|
50
72
|
|
|
51
73
|
export { DbTabs };
|
|
74
|
+
export type { TabItemConfig };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as t}from"./db-icons.js";import{labelFrom as e}from"../core/i18n.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TABS_ORIENTATIONS as i,TABS_SIZES as a,TABS_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTabs extends HTMLElement{constructor(){super(...arguments),this.tabButtons=[],this.inactivePanels=document.createDocumentFragment(),this.isRendering=!1,this.handleResize=()=>{this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=requestAnimationFrame(()=>{this.isRendering||(this.handleListScroll(),this.updateIndicator(!1))})},this.handleListScroll=()=>{if(!this.list)return;const t=this.list.scrollWidth>this.list.clientWidth,e=this.list.scrollLeft+this.list.clientWidth>=this.list.scrollWidth-5;this.list.classList.toggle("designbase-wc-tabs__list--show-gradient",t&&!e&&"horizontal"===this.orientation)}}static get observedAttributes(){return["labels","items","active-index","selected-id","orientation","size","variant","full-width"]}get labels(){const t=this.tabItems.map(t=>t.label);return t.length?t:(this.getAttribute("labels")||"").split(",").map(t=>t.trim()).filter(Boolean)}set labels(t){this.setAttribute("labels",Array.isArray(t)?t.join(","):t)}get tabItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t:[]}catch{return[]}}get items(){return this.tabItems}set items(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}set tabItems(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}get activeIndex(){const t=this.getAttribute("selected-id");if(t){const e=this.tabItems.findIndex((e,s)=>(e.id||String(s))===t);if(e>=0)return e}return Number(this.getAttribute("active-index")||0)}set activeIndex(t){this.setAttribute("active-index",String(t))}get orientation(){return s(this.getAttribute("orientation"),i,"horizontal")}set orientation(t){this.setAttribute("orientation",t)}get size(){return s(this.getAttribute("size"),a,"m")}set size(t){this.setAttribute("size",t)}get variant(){return s(this.getAttribute("variant"),n,"default")}set variant(t){this.setAttribute("variant",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",Boolean(t))}connectedCallback(){this.render(),this.list?.addEventListener("scroll",this.handleListScroll,{passive:!0}),window.addEventListener("resize",this.handleResize),this.resizeObserver=new ResizeObserver(()=>this.handleResize()),this.resizeObserver.observe(this),this.childObserver=new MutationObserver(t=>{if(this.isRendering)return;t.some(t=>Array.from(t.addedNodes).some(t=>t instanceof HTMLElement&&(t.hasAttribute("slot")||void 0!==t.dataset.panelIndex)))&&this.render()}),this.childObserver.observe(this,{childList:!0})}disconnectedCallback(){this.list?.removeEventListener("scroll",this.handleListScroll),window.removeEventListener("resize",this.handleResize),this.resizeObserver?.disconnect(),this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.childObserver?.disconnect()}attributeChangedCallback(){this.isConnected&&this.render()}collectPanelContent(){const t=new Map,register=(e,s)=>{if(!(e instanceof HTMLElement)||"SLOT"===e.tagName)return;t.has(s)||t.set(s,[]);const i=t.get(s);i.includes(e)||i.push(e)};return Array.from(this.children).forEach(t=>{const e=t.getAttribute("slot")?.match(/^panel-(\d+)$/);if(e)return void register(t,Number(e[1]));const s=t.dataset.panelIndex;void 0!==s&®ister(t,Number(s))}),this.panel?.querySelectorAll(":scope > .designbase-wc-tabs__panel-inner > [data-panel-index]").forEach(t=>{t instanceof HTMLElement&®ister(t,Number(t.dataset.panelIndex))}),Array.from(this.inactivePanels.children).forEach(t=>{t instanceof HTMLElement&&void 0!==t.dataset.panelIndex&®ister(t,Number(t.dataset.panelIndex))}),t}render(){this.isRendering=!0;const s=this.collectPanelContent(),i=[...s.values()].some(t=>t.length>0),a=this.labels,n=this.tabItems,r=Math.min(Math.max(this.activeIndex,0),Math.max(a.length-1,0)),l=this.size,o=this.orientation,d=this.variant,h="default"===d;this.className=["designbase-wc-tabs",`designbase-wc-tabs--${o}`,`designbase-wc-tabs--${l}`,`designbase-wc-tabs--${d}`,this.fullWidth&&"designbase-wc-tabs--full-width",!i&&"designbase-wc-tabs--nav-only"].filter(Boolean).join(" "),this.querySelectorAll(":scope > .designbase-wc-tabs__list, :scope > .designbase-wc-tabs__panel").forEach(t=>t.remove()),this.list=document.createElement("div"),this.list.className=["designbase-wc-tabs__list",`designbase-wc-tabs__list--${o}`,this.fullWidth&&"designbase-wc-tabs__list--full-width"].filter(Boolean).join(" "),this.list.setAttribute("role","tablist"),this.list.setAttribute("aria-orientation",o),this.list.setAttribute("aria-label",e(this,"label-tablist","tabs.label")),this.tabButtons=[],a.forEach((e,s)=>{const a=n[s],o=Boolean(a?.disabled),d=s===r,h=document.createElement("button");if(h.type="button",h.className=["designbase-wc-tabs__tab",d&&"designbase-wc-tabs__tab--selected",o&&"designbase-wc-tabs__tab--disabled"].filter(Boolean).join(" "),h.setAttribute("role","tab"),h.setAttribute("aria-selected",String(d)),i&&h.setAttribute("aria-controls",`panel-${s}`),h.id=`tab-${s}`,h.tabIndex=d?0:-1,h.disabled=o,a?.icon){const e=document.createElement("span");e.className="designbase-wc-tabs__tab-icon";const s="s"===l?16:"l"===l?20:18;e.setAttribute("aria-hidden","true"),e.append(t(a.icon,s)),h.append(e)}const c=document.createElement("span");c.className="designbase-wc-tabs__tab-label",c.textContent=e,h.append(c),h.addEventListener("click",()=>this.select(s)),h.addEventListener("keydown",t=>this.handleKeyDown(t,s)),this.list?.append(h),this.tabButtons.push(h)}),h?(this.indicator=document.createElement("span"),this.indicator.className="designbase-wc-tabs__indicator designbase-wc-tabs__indicator--no-transition",this.list.append(this.indicator),requestAnimationFrame(()=>this.updateIndicator(!1))):this.indicator=void 0,this.panel=document.createElement("div"),this.panel.className="designbase-wc-tabs__panel",this.panel.setAttribute("role","tabpanel"),this.panel.id=`panel-${r}`,this.panel.setAttribute("aria-labelledby",`tab-${r}`),this.panel.tabIndex=i?0:-1,this.panel.hidden=!i;const c=document.createElement("div");c.className="designbase-wc-tabs__panel-inner",s.forEach((t,e)=>{t.forEach(t=>{t.removeAttribute("slot"),t.dataset.panelIndex=String(e),e===r?c.append(t):this.inactivePanels.append(t)})}),this.panel.append(c),this.append(this.list,this.panel),requestAnimationFrame(()=>{this.handleListScroll(),h&&this.updateIndicator(!1)}),this.isRendering=!1}select(t){const e=this.labels,s=this.tabItems;if(!e[t]||s[t]?.disabled)return;this.activeIndex=t;const i=s[t]?.id||String(t);this.setAttribute("selected-id",i),this.dispatchEvent(new CustomEvent("db-change",{detail:{index:t,label:e[t],id:i},bubbles:!0,composed:!0})),this.render()}handleKeyDown(t,e){const s=this.labels,i=this.tabItems;let a=e;if("ArrowRight"===t.key||"ArrowDown"===t.key)a=(e+1)%s.length;else if("ArrowLeft"===t.key||"ArrowUp"===t.key)a=(e-1+s.length)%s.length;else if("Home"===t.key)a=0;else{if("End"!==t.key)return"Enter"===t.key||" "===t.key?(t.preventDefault(),void this.select(e)):void 0;a=s.length-1}t.preventDefault();let n=0;for(;i[a]?.disabled&&n<s.length;)a="ArrowLeft"===t.key||"ArrowUp"===t.key?(a-1+s.length)%s.length:(a+1)%s.length,n+=1;this.tabButtons[a]?.focus()}updateIndicator(t=!1){const e=this.list?.querySelector(".designbase-wc-tabs__tab--selected");if(!e||!this.indicator)return;const s="vertical"===this.orientation;this.indicator.classList.toggle("designbase-wc-tabs__indicator--no-transition",!t),this.indicator.classList.add(s?"designbase-wc-tabs__indicator--vertical":"designbase-wc-tabs__indicator--horizontal"),this.indicator.classList.add("designbase-wc-tabs__indicator--ready"),s?(this.indicator.style.width="2px",this.indicator.style.height=`${e.offsetHeight}px`,this.indicator.style.transform=`translate3d(0, ${e.offsetTop}px, 0)`):(this.indicator.style.width=`${e.offsetWidth}px`,this.indicator.style.height="2px",this.indicator.style.transform=`translate3d(${e.offsetLeft}px, 0, 0)`)}}customElements.get("db-tabs")||customElements.define("db-tabs",DbTabs);export{DbTabs};
|
|
1
|
+
import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{labelFrom as i}from"../core/i18n.js";import{dbUid as s}from"../core/uid.js";import{setHostClasses as n}from"../core/host-class.js";import{coerceToContract as r}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TABS_ORIENTATIONS as a,TABS_SIZES as o,TABS_VARIANTS as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTabs extends HTMLElement{constructor(){super(...arguments),this.uid=s("db-tabs"),this.records=new Map,this.slotNodes=new Set,this.rendering=!1,this.reflecting=!1,this.suppressClick=!1,this.beginDrag=t=>{if(!this.list||"touch"===t.pointerType||!t.isPrimary||0!==t.button||this.drag)return;if(!("horizontal"===this.orientation?this.list.scrollWidth>this.list.clientWidth+1:this.list.scrollHeight>this.list.clientHeight+1))return;const e=t.target instanceof Element&&t.target.closest("button")||this.list;this.drag={id:t.pointerId,target:e,x:t.clientX,y:t.clientY,left:this.list.scrollLeft,top:this.list.scrollTop,moved:!1};try{e.setPointerCapture(t.pointerId)}catch{}},this.moveDrag=t=>{const e=this.drag;if(!e||!this.list||e.id!==t.pointerId)return;const i="horizontal"===this.orientation?t.clientX-e.x:t.clientY-e.y;!e.moved&&Math.abs(i)<6||(e.moved=!0,this.list.classList.add("designbase-wc-tabs__list--dragging"),t.cancelable&&t.preventDefault(),"horizontal"===this.orientation?this.list.scrollLeft=e.left-i:this.list.scrollTop=e.top-i)},this.finishDrag=t=>{t.pointerId===this.drag?.id&&(this.moveDrag(t),this.endDrag(!1))},this.cancelDrag=t=>{t.pointerId===this.drag?.id&&this.endDrag(!0)},this.captureClick=t=>{this.suppressClick&&(t.preventDefault(),t.stopImmediatePropagation())},this.handleResize=()=>{this.isConnected&&(void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=requestAnimationFrame(()=>{this.resizeRaf=void 0,this.handleListScroll(),this.updateIndicator()}))},this.handleListScroll=()=>{if(!this.list)return;const t="rtl"===getComputedStyle(this).direction,e=[...this.records.values()],i=e[e.length-1]?.button.getBoundingClientRect(),s=this.list.getBoundingClientRect(),n="horizontal"===this.orientation&&!!i&&(t?i.left<s.left-1:i.right>s.right+1);this.list.classList.toggle("designbase-wc-tabs__list--show-gradient",n)}}static get observedAttributes(){return["labels","items","active-index","selected-id","orientation","size","variant","full-width","aria-label","aria-labelledby","aria-describedby","label-tablist","dir"]}get tabItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t.filter(t=>!!t&&"object"==typeof t&&"string"==typeof t.label&&t.label.trim().length>0):[]}catch{return[]}}set tabItems(t){this.items=t}get items(){return this.tabItems}set items(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}get labels(){const t=this.tabItems;if(t.length)return t.map(t=>t.label);const e=this.getAttribute("labels")||"";try{const t=JSON.parse(e);if(Array.isArray(t))return t.filter(t=>"string"==typeof t&&!!t.trim())}catch{}return e.split(",").map(t=>t.trim()).filter(Boolean)}set labels(t){this.setAttribute("labels",Array.isArray(t)?JSON.stringify(t):t)}entries(){const t=this.tabItems,e=new Set;return this.labels.map((i,s)=>{const n=t[s]||{label:i},r="string"==typeof n.id&&n.id?n.id:String(s);let a=r,o=1;for(;e.has(a);)a=`${r}#${++o}`;return e.add(a),{key:a,item:n,index:s}})}get activeIndex(){const t=this.entries(),e=this.getAttribute("selected-id");let i=e?t.findIndex(t=>t.key===e):-1;if(i<0){const t=Number(this.getAttribute("active-index")||0);i=Number.isFinite(t)?Math.trunc(t):0}if(i=Math.max(0,Math.min(i,t.length-1)),t[i]&&!t[i].item.disabled)return i;const s=t.find(t=>t.index>=i&&!t.item.disabled);return s?.index??t.find(t=>!t.item.disabled)?.index??-1}set activeIndex(t){this.reflecting=!0;try{this.removeAttribute("selected-id"),this.setAttribute("active-index",String(t))}finally{this.reflecting=!1}this.isConnected&&this.render()}get selectedId(){return this.entries()[this.activeIndex]?.key||""}set selectedId(t){this.setAttribute("selected-id",t)}get orientation(){return r(this.getAttribute("orientation"),a,"horizontal")}set orientation(t){this.setAttribute("orientation",t)}get size(){return r(this.getAttribute("size"),o,"m")}set size(t){this.setAttribute("size",t)}get variant(){return r(this.getAttribute("variant"),l,"default")}set variant(t){this.setAttribute("variant",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){for(const t of["items","tabItems","labels","activeIndex","selectedId","orientation","size","variant","fullWidth"])if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}this.resizeObserver??(this.resizeObserver=new ResizeObserver(this.handleResize)),this.resizeObserver.observe(this),this.render(),this.resizeObserver.observe(this.list);for(const t of this.records.values())this.resizeObserver.observe(t.button);window.addEventListener("resize",this.handleResize),document.fonts?.addEventListener("loadingdone",this.handleResize),this.childObserver??(this.childObserver=new MutationObserver(t=>{if(this.rendering)return;t.some(t=>"attributes"===t.type||Array.from(t.addedNodes).some(t=>t instanceof HTMLElement&&t.parentElement===this&&void 0!==this.slotIndex(t))||Array.from(t.removedNodes).some(t=>t instanceof HTMLElement&&(this.slotNodes.has(t)&&!this.contains(t)||[...this.records.values()].some(e=>e.panel===t)&&t.parentElement!==this)))&&this.render()})),this.childObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["slot","data-panel-index"]})}disconnectedCallback(){this.endDrag(!0),void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.suppressClick=!1,this.clickTimer=void 0,window.removeEventListener("resize",this.handleResize),document.fonts?.removeEventListener("loadingdone",this.handleResize),this.resizeObserver?.disconnect(),this.childObserver?.disconnect(),void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=void 0}attributeChangedCallback(t,e,i){if(!this.reflecting&&e!==i){if("active-index"===t&&this.isConnected){this.reflecting=!0;try{this.removeAttribute("selected-id")}finally{this.reflecting=!1}}this.isConnected&&this.render()}}refresh(){this.isConnected&&this.render()}focus(t){this.records.get(this.selectedId)?.button.focus(t)}slotIndex(t){const e=t.getAttribute("slot")?.match(/^panel-(\d+)$/),i=e?.[1]??t.dataset.panelIndex;if(void 0===i||""===i.trim())return;const s=Number(i);return Number.isInteger(s)&&s>=0?s:void 0}collectSlots(){for(const t of Array.from(this.children))t instanceof HTMLElement&&void 0!==this.slotIndex(t)&&this.slotNodes.add(t);const t=new Map;for(const e of this.slotNodes){if(!this.contains(e)){this.slotNodes.delete(e);continue}const i=this.slotIndex(e);if(void 0===i)continue;const s=t.get(i)||[];s.push(e),t.set(i,s)}return t}createRecord(t){const e=document.createElement("button");e.type="button",e.setAttribute("role","tab");const i=s(this.uid);e.id=`${i}-tab`;const n=document.createElement("span");n.className="designbase-wc-tabs__tab-icon",n.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className="designbase-wc-tabs__tab-label",e.append(n,r);const a=document.createElement("div");a.id=`${i}-panel`,a.className="designbase-wc-tabs__panel",a.setAttribute("role","tabpanel"),a.setAttribute("aria-labelledby",e.id),a.tabIndex=0;const o=document.createElement("div");return o.id=`${i}-inner`,o.className="designbase-wc-tabs__panel-inner",a.append(o),e.addEventListener("click",()=>this.select(t)),e.addEventListener("focus",()=>{this.focusedKey=t,this.syncRoving()}),e.addEventListener("keydown",e=>this.navigate(e,t)),this.resizeObserver?.observe(e),{button:e,icon:n,label:r,panel:a,inner:o}}hideUnassigned(t){this.stash??(this.stash=Object.assign(document.createElement("div"),{hidden:!0,inert:!0})),this.stash.parentElement||this.append(this.stash),t.parentElement!==this.stash&&this.stash.append(t)}render(){if(!this.rendering){this.drag&&this.endDrag(!0),this.rendering=!0;try{const s=this.entries(),r=this.activeIndex,a=s[r]?.key||"",o=document.activeElement,l=[...this.records.values()].findIndex(t=>t.button===o||t.panel.contains(o)),d=this.collectSlots(),h=new Set;this.list??(this.list=document.createElement("div")),this.list.parentElement||(this.list.addEventListener("scroll",this.handleListScroll,{passive:!0}),this.list.addEventListener("pointerdown",this.beginDrag),this.list.addEventListener("pointermove",this.moveDrag),this.list.addEventListener("pointerup",this.finishDrag),this.list.addEventListener("pointercancel",this.cancelDrag),this.list.addEventListener("lostpointercapture",this.cancelDrag),this.list.addEventListener("click",this.captureClick,!0),this.prepend(this.list)),this.list.className=`designbase-wc-tabs__list designbase-wc-tabs__list--${this.orientation}${this.fullWidth?" designbase-wc-tabs__list--full-width":""}`,this.list.setAttribute("role","tablist"),this.list.setAttribute("aria-orientation",this.orientation),this.list.setAttribute("aria-label",this.getAttribute("aria-label")||i(this,"label-tablist","tabs.label"));for(const t of["aria-labelledby","aria-describedby"])this.hasAttribute(t)?this.list.setAttribute(t,this.getAttribute(t)):this.list.removeAttribute(t);const c=[];let b=null,u=this.list;for(const{key:i,item:n,index:a}of s){const s=this.records.get(i)||this.createRecord(i);c.push([i,s]),s.button.className=`designbase-wc-tabs__tab${a===r?" designbase-wc-tabs__tab--selected":""}${n.disabled?" designbase-wc-tabs__tab--disabled":""}`,s.button.disabled=Boolean(n.disabled),s.button.setAttribute("aria-selected",String(a===r)),s.label.textContent=n.label;const o=`${n.icon}:${this.size}`;if(s.iconSignature!==o){s.icon.replaceChildren();const i=n.icon,r="string"==typeof i&&t(i);s.icon.hidden=!r,r&&s.icon.append(e(i,"s"===this.size?16:"l"===this.size?20:18)),s.iconSignature=o}if(s.inner.dataset.dbTabsContentIndex=String(a),!s.inner.hasAttribute("data-db-react-content")){const t=d.get(a)||[];for(const e of Array.from(s.inner.children))t.includes(e)||this.hideUnassigned(e);for(const e of t)h.add(e),e.parentElement!==s.inner&&s.inner.append(e)}const l=b?b.nextElementSibling:this.list.firstElementChild;l!==s.button&&this.list.insertBefore(s.button,l),b=s.button;const g=u.nextElementSibling;g!==s.panel&&this.insertBefore(s.panel,g),u=s.panel}const g=new Set(s.map(t=>t.key));for(const[t,e]of this.records)if(!g.has(t)){for(const t of this.slotNodes)e.panel.contains(t)&&!h.has(t)&&this.hideUnassigned(t);this.resizeObserver?.unobserve(e.button),e.button.remove(),e.panel.remove()}for(const t of this.slotNodes)h.has(t)||this.hideUnassigned(t);this.records.clear();for(const[t,e]of c)this.records.set(t,e);const f=c.some(([,t])=>t.inner.childNodes.length>0||t.inner.hasAttribute("data-db-react-content"));n(this,["designbase-wc-tabs",`designbase-wc-tabs--${this.orientation}`,`designbase-wc-tabs--${this.size}`,`designbase-wc-tabs--${this.variant}`,this.fullWidth&&"designbase-wc-tabs--full-width",!f&&"designbase-wc-tabs--nav-only"]);for(const[t,e]of c){const i=f&&t===a;e.panel.hidden=!i,e.panel.inert=!i,e.panel.setAttribute("aria-hidden",String(!i)),f?e.button.setAttribute("aria-controls",e.panel.id):e.button.removeAttribute("aria-controls")}this.focusedKey&&this.records.has(this.focusedKey)&&!this.records.get(this.focusedKey)?.button.disabled||(this.focusedKey=a),this.list.contains(o)||(this.focusedKey=a),this.syncRoving(),this.reflecting=!0;try{this.setAttribute("active-index",String(r)),a?this.setAttribute("selected-id",a):this.removeAttribute("selected-id")}finally{this.reflecting=!1}"default"===this.variant&&a?(this.indicator??(this.indicator=document.createElement("span")),this.indicator.className="designbase-wc-tabs__indicator designbase-wc-tabs__indicator--no-transition",this.indicator.setAttribute("aria-hidden","true"),this.indicator.parentElement!==this.list&&this.list.append(this.indicator)):this.indicator?.remove(),o instanceof HTMLElement&&l>=0&&(document.activeElement!==o||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled)&&(!o.isConnected||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled?this.records.get(a)?.button.focus({preventScroll:!0}):o.focus({preventScroll:!0})),this.handleResize()}finally{this.rendering=!1}this.dispatchEvent(new Event("db-content-targets-change"))}}syncRoving(){for(const[t,e]of this.records)e.button.tabIndex=e.button.disabled||t!==this.focusedKey?-1:0}select(t){if(this.suppressClick)return;const e=this.entries().find(e=>e.key===t);e&&!e.item.disabled&&(this.focusedKey=t,this.syncRoving(),t!==this.selectedId&&(this.selectedId=t,this.dispatchEvent(new CustomEvent("db-change",{detail:{index:e.index,label:e.item.label,id:t},bubbles:!0,composed:!0})),this.ensureVisible(this.records.get(t).button)))}navigate(t,e){if(t.altKey||t.ctrlKey||t.metaKey)return;const i=this.entries().filter(t=>!t.item.disabled),s=i.findIndex(t=>t.key===e);if(s<0)return;let n=s;const r="vertical"===this.orientation,a="rtl"===getComputedStyle(this).direction;if("Home"===t.key)n=0;else if("End"===t.key)n=i.length-1;else if(!r||"ArrowDown"!==t.key&&"ArrowUp"!==t.key){if(r||"ArrowRight"!==t.key&&"ArrowLeft"!==t.key)return;n=(s+("ArrowRight"===t.key!==a?1:-1)+i.length)%i.length}else n=(s+("ArrowDown"===t.key?1:-1)+i.length)%i.length;t.preventDefault();const o=this.records.get(i[n].key).button;o.focus({preventScroll:!0}),this.ensureVisible(o)}ensureVisible(t){if(!this.list)return;const e=t.getBoundingClientRect(),i=this.list.getBoundingClientRect();"horizontal"===this.orientation?this.list.scrollBy({left:e.left<i.left?e.left-i.left:e.right>i.right?e.right-i.right:0,behavior:"auto"}):this.list.scrollBy({top:e.top<i.top?e.top-i.top:e.bottom>i.bottom?e.bottom-i.bottom:0,behavior:"auto"})}endDrag(t){const e=this.drag;if(this.drag=void 0,e){this.list?.classList.remove("designbase-wc-tabs__list--dragging"),e.moved&&(this.suppressClick=!0,void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.clickTimer=window.setTimeout(()=>{this.suppressClick=!1,this.clickTimer=void 0},0));try{e.target.hasPointerCapture(e.id)&&e.target.releasePointerCapture(e.id)}catch{}t&&this.handleListScroll()}}updateIndicator(){const t=this.records.get(this.selectedId)?.button;if(!t||!this.indicator?.isConnected)return;const e="vertical"===this.orientation;this.indicator.classList.toggle("designbase-wc-tabs__indicator--vertical",e),this.indicator.classList.toggle("designbase-wc-tabs__indicator--horizontal",!e),this.indicator.classList.add("designbase-wc-tabs__indicator--ready"),this.indicator.style.width=e?"2px":`${t.offsetWidth}px`,this.indicator.style.height=e?`${t.offsetHeight}px`:"2px",this.indicator.style.transform=e?`translate3d(0, ${t.offsetTop}px, 0)`:`translate3d(${t.offsetLeft}px, 0, 0)`}}customElements.get("db-tabs")||customElements.define("db-tabs",DbTabs);export{DbTabs};
|
|
@@ -8,13 +8,25 @@ declare class DbTextarea extends HTMLElement {
|
|
|
8
8
|
private errorEl?;
|
|
9
9
|
private footerEl?;
|
|
10
10
|
private built;
|
|
11
|
+
private formState;
|
|
11
12
|
get value(): string;
|
|
12
13
|
set value(value: string);
|
|
14
|
+
get defaultValue(): string;
|
|
15
|
+
set defaultValue(value: string);
|
|
16
|
+
get name(): string;
|
|
17
|
+
set name(value: string);
|
|
18
|
+
get required(): boolean;
|
|
19
|
+
set required(value: boolean);
|
|
20
|
+
get disabled(): boolean;
|
|
21
|
+
set disabled(value: boolean);
|
|
22
|
+
get readOnly(): boolean;
|
|
23
|
+
set readOnly(value: boolean);
|
|
13
24
|
get size(): string;
|
|
14
25
|
set size(value: string);
|
|
15
26
|
connectedCallback(): void;
|
|
27
|
+
disconnectedCallback(): void;
|
|
16
28
|
attributeChangedCallback(name: string): void;
|
|
17
|
-
focus(): void;
|
|
29
|
+
focus(options?: FocusOptions): void;
|
|
18
30
|
private get showCharacterCount();
|
|
19
31
|
private get characterCountPosition();
|
|
20
32
|
private build;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{TextFieldState as t,TEXT_FIELD_ATTRIBUTES as e,upgradeTextProperties as i,textFieldDescription as s}from"../core/text-field-state.js";import{setHostClasses as a}from"../core/host-class.js";import{dbUid as r}from"../core/uid.js";import{coerceToContract as h}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TEXTAREA_SIZES as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTextarea extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.formState=new t(this,()=>this.updateCharacterCount()),this.handleInput=t=>{t.stopPropagation(),this.field&&(this.getAttribute("value")!==this.field.value&&this.setAttribute("value",this.field.value),this.updateCharacterCount(),this.dispatchEvent(new InputEvent("input",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value,nativeEvent:t},bubbles:!0,composed:!0})))},this.handleChange=t=>{if(t.stopPropagation(),!this.field)return;const e=this.field.value;this.getAttribute("value")!==e&&this.setAttribute("value",e),this.updateCharacterCount(),this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e,nativeEvent:t},bubbles:!0,composed:!0}))}}static get observedAttributes(){return["label","placeholder","value","default-value","name","size","rows","max-length","show-character-count","character-count-position","disabled","readonly","required","error","error-message","helper-text","full-width","resizable",...e]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.setAttribute("value",t),this.field&&(this.field.value=t,this.updateCharacterCount())}get defaultValue(){return this.formState.defaultValue}set defaultValue(t){this.setAttribute("default-value",t)}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t)}get size(){return h(this.getAttribute("size"),l,"m")}set size(t){this.setAttribute("size",t)}connectedCallback(){i(this,["value","defaultValue","name","required","size","disabled","readOnly"]),this.built||this.build(),this.syncState()}disconnectedCallback(){this.formState.disconnect()}attributeChangedCallback(t){if(this.built){if("value"===t&&this.field){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t),this.formState.syncValue(this.field),void this.updateCharacterCount()}this.syncState()}}focus(t){this.field?.focus(t)}get showCharacterCount(){return this.hasAttribute("show-character-count")}get characterCountPosition(){return this.getAttribute("character-count-position")||"bottom"}build(){const t=this.getAttribute("id")||r("db-textarea");this.hasAttribute("id")||this.setAttribute("id",t),this.labelEl=document.createElement("label"),this.labelEl.className="designbase-wc-textarea__label",this.labelEl.htmlFor=`${t}-field`,this.countTop=document.createElement("div"),this.countTop.className="designbase-wc-textarea__character-count designbase-wc-textarea__character-count--top",this.countTop.hidden=!0;const e=document.createElement("div");e.className="designbase-wc-textarea__wrapper",this.field=document.createElement("textarea"),this.field.id=`${t}-field`,this.field.className="designbase-wc-textarea__field",this.field.addEventListener("input",this.handleInput),this.field.addEventListener("change",this.handleChange),e.appendChild(this.field),this.footerEl=document.createElement("div"),this.footerEl.className="designbase-wc-textarea__footer",this.errorEl=document.createElement("div"),this.errorEl.className="designbase-wc-textarea__error-message",this.errorEl.setAttribute("role","alert"),this.helperEl=document.createElement("div"),this.helperEl.className="designbase-wc-textarea__helper-text",this.countBottom=document.createElement("div"),this.countBottom.className="designbase-wc-textarea__character-count designbase-wc-textarea__character-count--bottom",this.countBottom.hidden=!0,this.footerEl.append(this.errorEl,this.helperEl,this.countBottom),this.append(this.labelEl,this.countTop,e,this.footerEl),this.built=!0}syncState(){if(!this.field)return;const t=l.includes(this.size)?this.size:"m",e=this.getAttribute("label")||"",i=this.getAttribute("helper-text")||"",r=this.getAttribute("error-message")||"",h=this.hasAttribute("error"),d=this.getAttribute("value")??this.getAttribute("default-value")??"";if(a(this,["designbase-wc-textarea",`designbase-wc-textarea--${t}`,h&&"designbase-wc-textarea--error",this.hasAttribute("disabled")&&"designbase-wc-textarea--disabled",this.hasAttribute("readonly")&&"designbase-wc-textarea--readonly",this.hasAttribute("full-width")&&"designbase-wc-textarea--full-width",this.hasAttribute("rows")&&"designbase-wc-textarea--rows",this.hasAttribute("resizable")?"":"designbase-wc-textarea--not-resizable"]),this.labelEl){const t=this.hasAttribute("required")?'<span aria-hidden="true"> *</span>':"";this.labelEl.innerHTML=e?`${this.escape(e)}${t}`:"",this.labelEl.hidden=!e}this.field.placeholder=this.getAttribute("placeholder")||"",this.field.name=this.getAttribute("name")||"",this.field.value!==d&&(this.field.value=d);const n=Number(this.getAttribute("rows")||4);this.field.rows=Number.isInteger(n)&&n>0?n:4,this.field.disabled=this.hasAttribute("disabled"),this.field.readOnly=this.hasAttribute("readonly"),this.field.required=this.hasAttribute("required"),this.field.setAttribute("aria-invalid",String(h));const o=`${this.getAttribute("id")}-helper`,u=`${this.getAttribute("id")}-error`;h&&r?(this.errorEl.id=u,this.errorEl.textContent=r,this.errorEl.hidden=!1,this.helperEl.hidden=!0,this.field.setAttribute("aria-describedby",u)):i?(this.helperEl.id=o,this.helperEl.textContent=i,this.helperEl.hidden=!1,this.errorEl.hidden=!0,this.field.setAttribute("aria-describedby",o)):(this.helperEl.hidden=!0,this.errorEl.hidden=!0,this.field.removeAttribute("aria-describedby"));const c=s(this,this.field.getAttribute("aria-describedby")||"");c&&this.field.setAttribute("aria-describedby",c),this.formState.sync(this.field),this.updateCharacterCount()}updateCharacterCount(){if(!this.field||!this.countTop||!this.countBottom)return;const t=this.field.value.length,e=this.field.maxLength>=0?this.field.maxLength:null,i=null!==e&&t>e,s=`${t}${null!==e?` / ${e}`:""}`,renderCount=t=>{let e=t.querySelector(".designbase-wc-textarea__character-count-text");e||(e=document.createElement("span"),t.replaceChildren(e)),e.className="designbase-wc-textarea__character-count-text",e.classList.toggle("designbase-wc-textarea__character-count-text--error",i),e.textContent=s};this.showCharacterCount&&"top"===this.characterCountPosition?(renderCount(this.countTop),this.countTop.hidden=!1,this.countBottom.hidden=!0):this.showCharacterCount?(renderCount(this.countBottom),this.countBottom.hidden=!1,this.countTop.hidden=!0):(this.countTop.hidden=!0,this.countBottom.hidden=!0),this.footerEl&&(this.footerEl.hidden=Boolean(this.errorEl?.hidden&&this.helperEl?.hidden&&this.countBottom.hidden))}escape(t){return t.replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[t]||t))}}customElements.get("db-textarea")||customElements.define("db-textarea",DbTextarea);export{DbTextarea};
|
|
@@ -4,26 +4,55 @@ declare class DbToggle extends HTMLElement {
|
|
|
4
4
|
private readonly internals;
|
|
5
5
|
private root?;
|
|
6
6
|
private labelEl?;
|
|
7
|
+
private readonly labelContent;
|
|
7
8
|
private built;
|
|
8
|
-
|
|
9
|
-
private
|
|
9
|
+
private dirty;
|
|
10
|
+
private resetChecked?;
|
|
11
|
+
private awaitingInitial;
|
|
12
|
+
private formDisabled;
|
|
10
13
|
get checked(): boolean;
|
|
11
14
|
set checked(value: boolean);
|
|
15
|
+
get selected(): boolean;
|
|
16
|
+
set selected(value: boolean);
|
|
17
|
+
get defaultChecked(): boolean;
|
|
18
|
+
set defaultChecked(value: boolean);
|
|
19
|
+
get defaultSelected(): boolean;
|
|
20
|
+
set defaultSelected(value: boolean);
|
|
12
21
|
get name(): string;
|
|
13
22
|
set name(value: string);
|
|
23
|
+
get label(): string;
|
|
24
|
+
set label(value: string);
|
|
25
|
+
get value(): string;
|
|
26
|
+
set value(value: string);
|
|
14
27
|
get disabled(): boolean;
|
|
15
28
|
set disabled(value: boolean);
|
|
16
29
|
get readOnly(): boolean;
|
|
17
30
|
set readOnly(value: boolean);
|
|
31
|
+
get required(): boolean;
|
|
32
|
+
set required(value: boolean);
|
|
33
|
+
get hasLabel(): boolean;
|
|
34
|
+
set hasLabel(value: boolean);
|
|
18
35
|
get size(): string;
|
|
19
36
|
set size(value: string);
|
|
20
37
|
get variant(): string;
|
|
21
38
|
set variant(value: string);
|
|
39
|
+
get form(): HTMLFormElement | null;
|
|
40
|
+
get validity(): ValidityState;
|
|
41
|
+
get validationMessage(): string;
|
|
42
|
+
get willValidate(): boolean;
|
|
43
|
+
checkValidity(): boolean;
|
|
44
|
+
reportValidity(): boolean;
|
|
45
|
+
focus(options?: FocusOptions): void;
|
|
46
|
+
private get unavailable();
|
|
47
|
+
private captureFirstChecked;
|
|
48
|
+
private setPristineChecked;
|
|
22
49
|
connectedCallback(): void;
|
|
23
|
-
|
|
50
|
+
disconnectedCallback(): void;
|
|
51
|
+
attributeChangedCallback(name: string): void;
|
|
52
|
+
formAssociatedCallback(): void;
|
|
24
53
|
formResetCallback(): void;
|
|
54
|
+
formStateRestoreCallback(state: string | File | FormData | null): void;
|
|
25
55
|
formDisabledCallback(disabled: boolean): void;
|
|
26
|
-
private get hasLabel();
|
|
27
56
|
private syncFormValue;
|
|
28
57
|
private build;
|
|
29
58
|
private handleClick;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ControlLabel as t}from"../core/control-label.js";import{t as e}from"../core/i18n.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TOGGLE_SIZES as s,TOGGLE_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbToggle extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.labelContent=new t(this),this.built=!1,this.dirty=!1,this.awaitingInitial=!1,this.formDisabled=!1,this.handleClick=()=>{if(this.unavailable||this.readOnly)return;const t=!this.checked;this.awaitingInitial=!1,this.checked=t,this.dispatchEvent(new Event("change",{bubbles:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{checked:t,selected:t},bubbles:!0,composed:!0}))}}static get observedAttributes(){return["checked","selected","default-checked","default-selected","size","variant","disabled","readonly","has-label","name","value","label","required","aria-label","aria-labelledby","aria-describedby","aria-description","aria-invalid","tabindex"]}get checked(){return this.hasAttribute("checked")||this.hasAttribute("selected")||!this.dirty&&this.defaultChecked}set checked(t){this.captureFirstChecked(Boolean(t)),this.dirty=!0,this.removeAttribute("selected"),this.toggleAttribute("checked",Boolean(t)),this.syncState()}get selected(){return this.checked}set selected(t){this.checked=t}get defaultChecked(){return this.hasAttribute("default-checked")||this.hasAttribute("default-selected")||(this.resetChecked??!1)}set defaultChecked(t){this.awaitingInitial=!1,this.resetChecked=Boolean(t),this.removeAttribute("default-selected"),this.toggleAttribute("default-checked",Boolean(t)),this.dirty||this.setPristineChecked(Boolean(t)),this.syncState()}get defaultSelected(){return this.defaultChecked}set defaultSelected(t){this.defaultChecked=t}get name(){return this.getAttribute("name")??""}set name(t){this.setAttribute("name",t)}get label(){return this.labelContent.value}set label(t){this.setAttribute("label",t)}get value(){return this.getAttribute("value")??"on"}set value(t){this.setAttribute("value",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",Boolean(t))}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",Boolean(t))}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",Boolean(t))}get hasLabel(){return"false"!==this.getAttribute("has-label")}set hasLabel(t){this.setAttribute("has-label",String(Boolean(t)))}get size(){return i(this.getAttribute("size"),s,"m")}set size(t){this.setAttribute("size",t)}get variant(){return i(this.getAttribute("variant"),a,"default")}set variant(t){this.setAttribute("variant",t)}get form(){return this.internals.form}get validity(){return this.internals.validity}get validationMessage(){return this.internals.validationMessage}get willValidate(){return this.internals.willValidate}checkValidity(){return this.internals.checkValidity()}reportValidity(){return this.internals.reportValidity()}focus(t){this.root?.focus(t)}get unavailable(){return this.disabled||this.formDisabled}captureFirstChecked(t){this.awaitingInitial&&(this.awaitingInitial=!1,this.hasAttribute("default-checked")||this.hasAttribute("default-selected")||(this.resetChecked=t))}setPristineChecked(t){this.removeAttribute("selected"),this.toggleAttribute("checked",t),this.dirty=!1}connectedCallback(){for(const t of["defaultChecked","defaultSelected","checked","selected","name","value","label","disabled","readOnly","required","hasLabel","size","variant"]){if(!Object.prototype.hasOwnProperty.call(this,t))continue;const e=this,i=e[t];delete e[t],e[t]=i}void 0===this.resetChecked&&(this.resetChecked=this.hasAttribute("default-checked")||this.hasAttribute("default-selected")||this.hasAttribute("checked")||this.hasAttribute("selected"),this.awaitingInitial=!["checked","selected","default-checked","default-selected"].some(t=>this.hasAttribute(t))),this.style.display||(this.style.display="contents"),this.built||this.build(),this.labelContent.connect(this.labelEl,()=>this.syncState()),this.syncState()}disconnectedCallback(){this.labelContent.disconnect()}attributeChangedCallback(t){"checked"!==t&&"selected"!==t||(this.captureFirstChecked(this.hasAttribute("checked")||this.hasAttribute("selected")),this.built&&(this.dirty=!0)),"default-checked"!==t&&"default-selected"!==t||(this.resetChecked=this.hasAttribute("default-checked")||this.hasAttribute("default-selected"),this.awaitingInitial=!1,this.built&&!this.dirty&&this.setPristineChecked(this.resetChecked)),this.built&&this.syncState()}formAssociatedCallback(){this.syncFormValue()}formResetCallback(){this.awaitingInitial=!1,this.setPristineChecked(this.defaultChecked),this.syncState()}formStateRestoreCallback(t){"string"==typeof t&&(this.awaitingInitial=!1,this.checked="true"===t)}formDisabledCallback(t){this.formDisabled=t,this.syncState()}syncFormValue(){const t=this.checked;this.internals.setFormValue(t&&!this.unavailable&&this.name?this.value:null,String(t));const i=this.required&&!this.unavailable&&!this.readOnly&&!t;this.internals.setValidity(i?{valueMissing:!0}:{},i?e("required"):"",this.root)}build(){this.root=document.createElement("button"),this.root.type="button",this.root.className="designbase-wc-toggle";const t=document.createElement("span");t.className="designbase-wc-toggle__track",t.setAttribute("aria-hidden","true");const e=document.createElement("span");for(e.className="designbase-wc-toggle__thumb",t.appendChild(e),this.labelEl=document.createElement("span"),this.labelEl.className="designbase-wc-toggle__label";this.firstChild;)this.labelEl.appendChild(this.firstChild);this.root.append(t,this.labelEl),this.appendChild(this.root),this.root.addEventListener("click",this.handleClick),this.built=!0}syncState(){if(!this.root)return;this.labelContent.sync(),this.root.disabled=this.unavailable;const t=this.getAttribute("tabindex");this.root.tabIndex=this.unavailable?-1:null!==t&&/^-?\d+$/.test(t)?Number(t):0,this.root.setAttribute("role","switch"),this.root.setAttribute("aria-checked",String(this.checked)),this.readOnly?this.root.setAttribute("aria-readonly","true"):this.root.removeAttribute("aria-readonly");for(const t of["aria-label","aria-labelledby","aria-describedby","aria-description","aria-invalid"]){const e=this.getAttribute(t);null!==e?this.root.setAttribute(t,e):this.root.removeAttribute(t)}this.hasLabel||this.hasAttribute("aria-label")||this.hasAttribute("aria-labelledby")||!this.label.trim()||this.root.setAttribute("aria-label",this.label.trim()),this.required?this.root.setAttribute("aria-required","true"):this.root.removeAttribute("aria-required"),this.syncFormValue(),this.hasLabel?this.labelEl?.removeAttribute("hidden"):this.labelEl?.setAttribute("hidden",""),this.syncClasses()}syncClasses(){if(!this.root)return;const t=s.includes(this.size)?this.size:"m",e=this.hasLabel&&Boolean(this.label.trim()),i=this.checked;this.root.className=["designbase-wc-toggle",`designbase-wc-toggle--${t}`,`designbase-wc-toggle--${this.variant}`,i&&"designbase-wc-toggle--selected",this.unavailable&&"designbase-wc-toggle--disabled",this.readOnly&&"designbase-wc-toggle--readonly",!e&&"designbase-wc-toggle--no-label"].filter(Boolean).join(" "),this.root.removeAttribute("aria-pressed")}}DbToggle.formAssociated=!0,customElements.get("db-toggle")||customElements.define("db-toggle",DbToggle);export{DbToggle};
|
|
@@ -20,41 +20,64 @@ declare class DbTwoFactor extends HTMLElement {
|
|
|
20
20
|
static get observedAttributes(): string[];
|
|
21
21
|
private built;
|
|
22
22
|
private timerId;
|
|
23
|
+
/** 코드 유효 시간(초) — SMS·이메일에서만 쓴다 */
|
|
23
24
|
private remaining;
|
|
25
|
+
/** 재전송 버튼이 다시 열리기까지 남은 시간(초) */
|
|
26
|
+
private cooldownLeft;
|
|
27
|
+
private expired;
|
|
28
|
+
private backupMode;
|
|
29
|
+
private resendCount;
|
|
30
|
+
private closeBtn;
|
|
31
|
+
private headerEl;
|
|
32
|
+
private eyebrowEl;
|
|
33
|
+
private titleEl;
|
|
34
|
+
private descEl;
|
|
24
35
|
private segment;
|
|
25
|
-
private
|
|
26
|
-
private
|
|
36
|
+
private codeBlock;
|
|
37
|
+
private codeLabelEl;
|
|
27
38
|
private timerEl;
|
|
28
|
-
private
|
|
29
|
-
private
|
|
39
|
+
private otpInput;
|
|
40
|
+
private expiredEl;
|
|
41
|
+
private backupInput;
|
|
30
42
|
private verifyBtn;
|
|
43
|
+
private resendGroup;
|
|
44
|
+
private resendHintEl;
|
|
45
|
+
private resendBtn;
|
|
31
46
|
private backupBtn;
|
|
32
|
-
private errorEl;
|
|
33
|
-
private channelActions;
|
|
34
|
-
private resendStatus;
|
|
35
|
-
private backupBlock;
|
|
36
|
-
private backupInput;
|
|
37
47
|
private backupCancelBtn;
|
|
38
|
-
private
|
|
39
|
-
private
|
|
48
|
+
private verifiedBlock;
|
|
49
|
+
private verifiedTitleEl;
|
|
50
|
+
private verifiedDescEl;
|
|
51
|
+
private doneBtn;
|
|
52
|
+
private errorEl;
|
|
40
53
|
get method(): Method;
|
|
41
54
|
set method(v: Method);
|
|
42
55
|
get size(): Size;
|
|
43
56
|
set size(v: Size);
|
|
44
57
|
get countdown(): number;
|
|
45
58
|
set countdown(v: number);
|
|
59
|
+
/** 재전송을 다시 누를 수 있기까지 기다리는 시간(초). 기본 30초. 0이면 바로 누를 수 있다. */
|
|
60
|
+
get resendCooldown(): number;
|
|
61
|
+
set resendCooldown(v: number);
|
|
46
62
|
get maxResends(): number;
|
|
63
|
+
private get usesTimer();
|
|
47
64
|
connectedCallback(): void;
|
|
48
65
|
disconnectedCallback(): void;
|
|
49
66
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
50
67
|
/** 수동 제어 모드에서 코드 발송 성공 후 카운트다운을 시작합니다. */
|
|
51
68
|
restartCountdown(): void;
|
|
69
|
+
/** 인증 완료 화면으로 전환합니다. */
|
|
70
|
+
markVerified(): void;
|
|
52
71
|
private clearTimer;
|
|
53
|
-
private
|
|
72
|
+
private startTimers;
|
|
54
73
|
private renderTimer;
|
|
74
|
+
private syncVerifyDisabled;
|
|
75
|
+
private emit;
|
|
55
76
|
private build;
|
|
56
77
|
private sync;
|
|
57
78
|
private requestVerify;
|
|
79
|
+
/** 번역 문장 안의 {0} 자리에 값을 굵게 넣는다 — 언어마다 어순이 달라 조각내 번역하지 않는다. */
|
|
80
|
+
private setTextWithValue;
|
|
58
81
|
}
|
|
59
82
|
declare global {
|
|
60
83
|
interface HTMLElementTagNameMap {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-segment-control.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TWO_FACTOR_SIZES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbTwoFactor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0,this.backupMode=!1,this.resendCount=0}static get observedAttributes(){return["method","code","size","disabled","error","error-message","title","description","verify-label","code-length","show-backup","countdown","destination","manual","sending","verifying","auto-submit","resend-label","max-resends"]}get method(){const t=this.getAttribute("method");return"sms"===t||"email"===t||"app"===t?t:"app"}set method(t){this.setAttribute("method",t)}get size(){return s(this.getAttribute("size"),n,"m")}set size(t){this.setAttribute("size",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}set countdown(t){this.setAttribute("countdown",String(t))}get maxResends(){const t=Number(this.getAttribute("max-resends")||3);return Number.isFinite(t)?Math.max(1,Math.min(5,Math.round(t))):3}connectedCallback(){this.build(),this.sync(),"app"===this.method||this.hasAttribute("manual")||this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"method"!==t&&"manual"!==t||e===i||("method"===t&&(this.resendCount=0,this.backupMode=!1),"app"===this.method||this.hasAttribute("manual")?this.clearTimer():this.startTimer(this.countdown)))}restartCountdown(){"app"!==this.method&&this.startTimer(this.countdown)}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0,this.timerEl&&(this.timerEl.textContent="")}startTimer(t){this.clearTimer(),this.remaining=t,this.renderTimer(),this.timerId=setInterval(()=>{this.remaining-=1,this.renderTimer(),this.remaining<=0&&(this.clearTimer(),this.resendBtn.disabled=!1,this.dispatchEvent(new CustomEvent("db-countdown-complete",{bubbles:!0,composed:!0})))},1e3)}renderTimer(){const i=Math.max(0,Math.floor(this.remaining/60)),s=Math.max(0,this.remaining%60);this.timerEl.textContent="app"===this.method?"":`${String(i).padStart(2,"0")}:${String(s).padStart(2,"0")}`,"app"!==this.method?this.timerEl.setAttribute("aria-label",t("남은 시간 {0}분 {1}초",[i,s])):this.timerEl.removeAttribute("aria-label");const n=this.resendCount>=this.maxResends;this.resendBtn.disabled="app"===this.method||this.remaining>0||n||this.hasAttribute("disabled"),"app"===this.method?this.resendStatus.textContent="":n?this.resendStatus.textContent=e("재전송 한도에 도달했습니다. 새 인증을 시작해 주세요."):this.remaining>0?this.resendStatus.textContent=t("{0}:{1} 후 재전송 가능 · 남은 횟수 {2}회",[String(i).padStart(2,"0"),String(s).padStart(2,"0"),this.maxResends-this.resendCount]):this.resendStatus.textContent=t("재전송 가능 · 남은 횟수 {0}회",[this.maxResends-this.resendCount])}build(){if(this.built)return;this.built=!0;const t="designbase-wc-two-factor";this.replaceChildren();const s=el("div",`${t}__header`),n=el("div",`${t}__icon`);n.append(i("lock",22));const r=el("div",`${t}__titles`),o=el("h3",`${t}__title`);o.dataset.role="title";const a=el("p",`${t}__description`);a.dataset.role="description",r.append(o,a),s.append(n,r),this.segment=document.createElement("db-segment-control"),this.segment.setAttribute("options",JSON.stringify([{value:"app",label:e("인증 앱")},{value:"sms",label:"SMS"},{value:"email",label:e("이메일")}].map(t=>({value:t.value,label:t.label})))),this.segment.setAttribute("full-width",""),this.segment.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"app");e!==this.method&&(this.setAttribute("code",""),this.method=e,this.dispatchEvent(new CustomEvent("db-method-change",{detail:{method:e},bubbles:!0,composed:!0})),"app"!==e&&this.dispatchEvent(new CustomEvent("db-send-code",{detail:{method:e,destination:this.getAttribute("destination")||""},bubbles:!0,composed:!0})))}),this.hintEl=el("p",`${t}__hint`),this.hintEl.dataset.role="hint",this.codeHead=el("div",`${t}__code-head`);const h=el("span",`${t}__code-label`);h.textContent=e("인증 코드"),this.timerEl=el("span",`${t}__timer`),this.codeHead.append(h,this.timerEl),this.otpInput=document.createElement("db-otp-input"),this.otpInput.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.setAttribute("code",e),this.dispatchEvent(new CustomEvent("db-code-change",{detail:{code:e},bubbles:!0,composed:!0}))}),this.otpInput.addEventListener("db-complete",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.dispatchEvent(new CustomEvent("db-code-complete",{detail:{code:e,method:this.method},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()}),this.channelActions=el("div",`${t}__channel`),this.resendBtn=el("button",`${t}__resend`),this.resendBtn.type="button",this.resendBtn.textContent=e("코드 재전송"),this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.resendCount+=1,this.dispatchEvent(new CustomEvent("db-resend",{detail:{method:this.method,destination:this.getAttribute("destination")||""},bubbles:!0,composed:!0})),this.hasAttribute("manual")?this.renderTimer():this.startTimer(this.countdown))}),this.resendStatus=el("p",`${t}__resend-status`),this.resendStatus.setAttribute("aria-live","polite"),this.channelActions.append(this.resendBtn,this.resendStatus),this.backupBlock=el("div",`${t}__backup-block`);const d=el("p",`${t}__hint`);d.textContent=e("계정 설정 시 저장한 8자리 백업 코드 중 사용하지 않은 코드를 입력하세요."),this.backupInput=document.createElement("db-input"),this.backupInput.setAttribute("label","백업 코드"),this.backupInput.setAttribute("placeholder","XXXX-XXXX"),this.backupInput.setAttribute("autocomplete","one-time-code"),this.backupInput.setAttribute("full-width",""),this.backupInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value||"").toUpperCase().replace(/[^A-Z0-9]/g,"").slice(0,8),i=e.length>4?`${e.slice(0,4)}-${e.slice(4)}`:e;this.backupInput.value=i,this.sync()}),this.backupCancelBtn=el("button",`${t}__backup`),this.backupCancelBtn.type="button",this.backupCancelBtn.textContent=e("인증 코드로 돌아가기"),this.backupCancelBtn.addEventListener("click",()=>{this.backupMode=!1,this.sync()}),this.backupBlock.append(d,this.backupInput,this.backupCancelBtn),this.verifyBtn=document.createElement("db-button"),this.verifyBtn.setAttribute("variant","primary"),this.verifyBtn.setAttribute("full-width",""),this.verifyBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestVerify()}),this.backupBtn=el("button",`${t}__backup`),this.backupBtn.type="button",this.backupBtn.textContent=e("백업 코드로 인증"),this.backupBtn.addEventListener("click",()=>{this.backupMode=!0,this.sync(),requestAnimationFrame(()=>this.backupInput?.focus?.()),this.dispatchEvent(new CustomEvent("db-backup-request",{bubbles:!0,composed:!0}))}),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0,this.append(s,this.segment,this.hintEl,this.codeHead,this.otpInput,this.channelActions,this.backupBlock,this.verifyBtn,this.backupBtn,this.errorEl)}sync(){const t="designbase-wc-two-factor",i=this.size,s=this.method,n=this.hasAttribute("disabled"),r=this.getAttribute("code-length")||"6",o=this.getAttribute("destination")||"";this.className=[t,`${t}--${i}`,`${t}--${s}`,n&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" ");const a=this.querySelector('[data-role="title"]'),h=this.querySelector('[data-role="description"]');a.textContent=this.getAttribute("title")||"2단계 인증",h.textContent=this.getAttribute("description")||"계속하려면 인증 코드를 입력해 주세요.",this.segment.setAttribute("value",s),this.segment.setAttribute("size",i),this.segment.toggleAttribute("disabled",n),this.segment.toggleAttribute("hidden",this.backupMode);const d=this.querySelector('[data-role="hint"]');d.textContent="app"===s?e("인증 앱(Google Authenticator, 1Password 등)에 표시된 6자리 코드를 입력하세요."):"sms"===s?o?`${o} 으로 보낸 SMS 인증 코드를 입력하세요.`:"등록된 휴대폰으로 보낸 SMS 인증 코드를 입력하세요.":o?`${o} 으로 보낸 이메일 인증 코드를 입력하세요.`:"등록된 이메일로 보낸 인증 코드를 입력하세요.",this.otpInput.setAttribute("length",r),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",n),this.otpInput.toggleAttribute("error",this.hasAttribute("error")),this.getAttribute("error-message")?this.otpInput.setAttribute("error-message",this.getAttribute("error-message")||""):this.otpInput.removeAttribute("error-message"),this.hintEl.hidden=this.backupMode,this.codeHead.hidden=this.backupMode,this.otpInput.hidden=this.backupMode,this.channelActions.hidden="app"===s||this.backupMode,this.backupBlock.hidden=!this.backupMode,this.backupInput.setAttribute("size",i),this.backupInput.toggleAttribute("disabled",n),this.resendBtn.textContent=this.hasAttribute("sending")?"전송 중…":this.getAttribute("resend-label")||"코드 재전송",this.renderTimer(),this.hasAttribute("sending")&&(this.resendBtn.disabled=!0),this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.backupMode?"백업 코드로 인증":this.getAttribute("verify-label")||"인증하기";const u=this.getAttribute("code")||"",c=String(this.backupInput.value||"").replace(/-/g,"");this.verifyBtn.toggleAttribute("disabled",n||(this.backupMode?8!==c.length:u.length<Number(r))),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.backupBtn.hidden=!this.hasAttribute("show-backup")||this.backupMode;const l=this.getAttribute("error-message")||"";this.errorEl.textContent=l,this.errorEl.hidden=!this.hasAttribute("error")||!l}requestVerify(){if(this.backupMode){const t=String(this.backupInput.value||"").replace(/-/g,"");if(8!==t.length||this.hasAttribute("disabled"))return;return void this.dispatchEvent(new CustomEvent("db-verify",{detail:{method:"backup",code:t},bubbles:!0,composed:!0}))}const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{method:this.method,code:t},bubbles:!0,composed:!0}))}}customElements.get("db-two-factor")||customElements.define("db-two-factor",DbTwoFactor);export{DbTwoFactor};
|
|
1
|
+
import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-segment-control.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TWO_FACTOR_SIZES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}function textButton(t,e){const i=el("button",t);return i.type="button",i.addEventListener("click",()=>{i.disabled||e()}),i}class DbTwoFactor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0,this.cooldownLeft=0,this.expired=!1,this.backupMode=!1,this.resendCount=0}static get observedAttributes(){return["method","code","size","disabled","error","error-message","eyebrow","title","description","verify-label","done-label","code-length","show-backup","countdown","resend-cooldown","destination","closable","verified","manual","sending","verifying","auto-submit","resend-label","max-resends"]}get method(){const t=this.getAttribute("method");return"sms"===t||"email"===t||"app"===t?t:"app"}set method(t){this.setAttribute("method",t)}get size(){return s(this.getAttribute("size"),n,"m")}set size(t){this.setAttribute("size",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}set countdown(t){this.setAttribute("countdown",String(t))}get resendCooldown(){const t=Number(this.getAttribute("resend-cooldown")??30);return Number.isFinite(t)&&t>=0?t:30}set resendCooldown(t){this.setAttribute("resend-cooldown",String(t))}get maxResends(){const t=Number(this.getAttribute("max-resends")||3);return Number.isFinite(t)?Math.max(1,Math.min(5,Math.round(t))):3}get usesTimer(){return"app"!==this.method&&!this.hasAttribute("verified")}connectedCallback(){this.build(),this.sync(),this.usesTimer&&!this.hasAttribute("manual")&&this.startTimers()}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&("method"!==t&&"manual"!==t&&"verified"!==t||e===i||("method"===t&&(this.resendCount=0,this.backupMode=!1),!this.usesTimer||this.hasAttribute("manual")?this.clearTimer():this.startTimers()),this.sync())}restartCountdown(){this.usesTimer&&this.startTimers()}markVerified(){this.setAttribute("verified","")}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0,this.cooldownLeft=0,this.expired=!1}startTimers(){this.clearTimer(),this.remaining=this.countdown,this.cooldownLeft=Math.min(this.resendCooldown,this.countdown),this.renderTimer(),this.timerId=setInterval(()=>{this.cooldownLeft>0&&(this.cooldownLeft-=1),this.remaining>0&&(this.remaining-=1,this.remaining<=0&&(this.expired=!0,this.cooldownLeft=0,this.emit("db-countdown-complete"))),this.renderTimer(),this.remaining<=0&&this.cooldownLeft<=0&&this.timerId&&(clearInterval(this.timerId),this.timerId=null)},1e3)}renderTimer(){if(!this.built)return;const i="app"===this.method,s=Math.max(0,Math.floor(this.remaining/60)),n=Math.max(0,this.remaining%60);this.timerEl.hidden=i||this.backupMode||this.hasAttribute("manual")&&this.remaining<=0&&!this.expired,this.timerEl.textContent=`${String(s).padStart(2,"0")}:${String(n).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",t("남은 시간 {0}분 {1}초",[s,n])),this.timerEl.classList.toggle("designbase-wc-two-factor__timer--expired",this.expired),this.expiredEl.hidden=i||!this.expired||this.backupMode,this.otpInput.toggleAttribute("disabled",this.hasAttribute("disabled")||!i&&this.expired);const r=this.resendCount>=this.maxResends,h=this.cooldownLeft>0;this.resendGroup.hidden=i||this.backupMode,this.resendHintEl.textContent=e(r?"재전송 한도를 모두 사용했어요.":"코드를 받지 못하셨나요?"),this.resendBtn.hidden=r,this.resendBtn.textContent=this.hasAttribute("sending")?e("전송 중…"):h?t("재전송 ({0}초)",[this.cooldownLeft]):this.getAttribute("resend-label")||e("재전송"),this.resendBtn.disabled=h||this.hasAttribute("sending")||this.hasAttribute("disabled"),this.syncVerifyDisabled()}syncVerifyDisabled(){const t=this.hasAttribute("disabled");if(this.backupMode){const e=String(this.backupInput.value||"").replace(/-/g,"");return void this.verifyBtn.toggleAttribute("disabled",t||8!==e.length)}const e=Number(this.getAttribute("code-length")||6),i=this.getAttribute("code")||"";this.verifyBtn.toggleAttribute("disabled",t||"app"!==this.method&&this.expired||i.length!==e)}emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}build(){if(this.built)return;this.built=!0;const t="designbase-wc-two-factor";this.replaceChildren();const s=el("div",`${t}__shell`);this.closeBtn=el("button",`${t}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label",e("닫기")),this.closeBtn.append(i("close",18)),this.closeBtn.addEventListener("click",()=>this.emit("db-close")),this.headerEl=el("div",`${t}__header`),this.eyebrowEl=el("span",`${t}__eyebrow`),this.titleEl=el("h3",`${t}__title`),this.descEl=el("p",`${t}__description`),this.headerEl.append(this.eyebrowEl,this.titleEl,this.descEl),this.segment=document.createElement("db-segment-control"),this.segment.setAttribute("full-width",""),this.segment.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"app");e!==this.method&&(this.setAttribute("code",""),this.method=e,this.emit("db-method-change",{method:e}),"app"!==e&&this.emit("db-send-code",{method:e,destination:this.getAttribute("destination")||""}))}),this.codeBlock=el("div",`${t}__code`);const n=el("div",`${t}__code-head`);this.codeLabelEl=el("span",`${t}__code-label`),this.timerEl=el("span",`${t}__timer`),this.timerEl.setAttribute("role","timer"),n.append(this.codeLabelEl,this.timerEl),this.otpInput=document.createElement("db-otp-input"),this.otpInput.setAttribute("full-width",""),this.otpInput.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.setAttribute("code",e),this.emit("db-code-change",{code:e})}),this.otpInput.addEventListener("db-complete",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.emit("db-code-complete",{code:e,method:this.method}),this.hasAttribute("auto-submit")&&this.requestVerify()}),this.backupInput=document.createElement("db-input"),this.backupInput.setAttribute("placeholder","XXXX-XXXX"),this.backupInput.setAttribute("autocomplete","one-time-code"),this.backupInput.setAttribute("full-width",""),this.backupInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value||"").toUpperCase().replace(/[^A-Z0-9]/g,"").slice(0,8),i=e.length>4?`${e.slice(0,4)}-${e.slice(4)}`:e;this.backupInput.value=i,this.syncVerifyDisabled()}),this.backupInput.addEventListener("keydown",t=>{"Enter"===t.key&&this.requestVerify()}),this.expiredEl=el("p",`${t}__expired`),this.expiredEl.setAttribute("role","alert"),this.expiredEl.hidden=!0,this.verifyBtn=document.createElement("db-button"),this.verifyBtn.setAttribute("variant","primary"),this.verifyBtn.setAttribute("full-width",""),this.verifyBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestVerify()}),this.resendBtn=textButton(`${t}__link`,()=>{this.resendCount+=1,this.emit("db-resend",{method:this.method,destination:this.getAttribute("destination")||""}),this.hasAttribute("manual")?this.renderTimer():(this.setAttribute("code",""),this.startTimers())}),this.backupBtn=textButton(`${t}__link ${t}__link--muted`,()=>{this.backupMode=!0,this.sync(),requestAnimationFrame(()=>this.backupInput?.focus?.()),this.emit("db-backup-request")}),this.backupCancelBtn=textButton(`${t}__link ${t}__link--muted`,()=>{this.backupMode=!1,this.sync()});const r=el("div",`${t}__footer`);this.resendGroup=el("span",`${t}__footer-resend`),this.resendHintEl=el("span",`${t}__footer-hint`),this.resendGroup.append(this.resendHintEl,this.resendBtn),r.append(this.resendGroup,this.backupBtn,this.backupCancelBtn),this.codeBlock.append(n,this.otpInput,this.backupInput,this.expiredEl,this.verifyBtn,r),this.verifiedBlock=el("div",`${t}__result ${t}__result--success`);const h=el("div",`${t}__result-icon`);h.append(i("circle-checked",36)),this.verifiedTitleEl=el("h3",`${t}__result-title`),this.verifiedDescEl=el("p",`${t}__result-desc`),this.doneBtn=document.createElement("db-button"),this.doneBtn.setAttribute("variant","primary"),this.doneBtn.setAttribute("full-width",""),this.doneBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.emit("db-done",{method:this.method})}),this.verifiedBlock.append(h,this.verifiedTitleEl,this.verifiedDescEl,this.doneBtn),this.errorEl=el("p",`${t}__error`),this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,s.append(this.closeBtn,this.headerEl,this.segment,this.codeBlock,this.errorEl,this.verifiedBlock),this.append(s)}sync(){const i="designbase-wc-two-factor",s=this.size,n=this.method,r=this.hasAttribute("disabled"),h=this.hasAttribute("verified"),o=this.backupMode&&!h,d=this.getAttribute("code-length")||"6",l=this.getAttribute("destination")||"";this.className=[i,`${i}--${s}`,`${i}--${n}`,o&&`${i}--backup`,h&&`${i}--verified`,this.hasAttribute("closable")&&`${i}--closable`,r&&`${i}--disabled`,this.hasAttribute("error")&&`${i}--error`].filter(Boolean).join(" "),this.closeBtn.hidden=!this.hasAttribute("closable"),this.headerEl.hidden=h;const a=this.getAttribute("eyebrow")||"";if(this.eyebrowEl.textContent=a,this.eyebrowEl.hidden=!a,o)this.titleEl.textContent=e("백업 코드로 인증"),this.descEl.textContent=e("계정 설정 때 저장한 8자리 백업 코드 중 아직 쓰지 않은 코드를 입력해 주세요.");else{this.titleEl.textContent=this.getAttribute("title")||e("2단계 인증");const i=this.getAttribute("description");i?this.descEl.textContent=i:"app"===n?this.descEl.textContent=t("인증 앱(Google Authenticator, 1Password 등)에 표시된 {0}자리 코드를 입력해 주세요.",[d]):l?this.setTextWithValue(this.descEl,"sms"===n?"{0} 번호로 보낸 {1}자리 인증번호를 입력해 주세요.":"{0} 주소로 보낸 {1}자리 인증번호를 입력해 주세요.",l,[d]):this.descEl.textContent=t("sms"===n?"등록된 휴대폰으로 보낸 {0}자리 인증번호를 입력해 주세요.":"등록된 이메일로 보낸 {0}자리 인증번호를 입력해 주세요.",[d])}this.segment.hidden=o||h,this.segment.setAttribute("options",JSON.stringify([{value:"app",label:e("인증 앱")},{value:"sms",label:"SMS"},{value:"email",label:e("이메일")}].map(t=>({value:t.value,label:t.label})))),this.segment.setAttribute("value",n),this.segment.setAttribute("size",s),this.segment.toggleAttribute("disabled",r),this.codeBlock.hidden=h,this.codeLabelEl.textContent=e(o?"백업 코드":"인증 코드"),this.otpInput.hidden=o,this.otpInput.setAttribute("length",d),this.otpInput.setAttribute("size",s),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&!o),this.backupInput.hidden=!o,this.backupInput.setAttribute("size",s),this.backupInput.setAttribute("aria-label",e("백업 코드")),this.backupInput.toggleAttribute("disabled",r),this.backupInput.toggleAttribute("error",this.hasAttribute("error")&&o),this.expiredEl.textContent=e("인증 시간이 만료되었어요. 인증번호를 다시 받아 주세요."),this.verifyBtn.setAttribute("size",s),this.verifyBtn.textContent=this.getAttribute("verify-label")||e("인증하기"),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.backupBtn.textContent=e("백업 코드 사용"),this.backupBtn.hidden=!this.hasAttribute("show-backup")||o,this.backupBtn.disabled=r,this.backupCancelBtn.textContent=e("인증 코드로 돌아가기"),this.backupCancelBtn.hidden=!o,this.verifiedBlock.hidden=!h,this.verifiedTitleEl.textContent=e("2단계 인증 완료"),this.verifiedDescEl.textContent=e("본인 확인이 완료되었어요."),this.doneBtn.setAttribute("size",s),this.doneBtn.textContent=this.getAttribute("done-label")||e("확인");const u=this.getAttribute("error-message")||"";this.errorEl.textContent=u,this.errorEl.hidden=!this.hasAttribute("error")||!u||h;const c=o?this.backupInput:this.otpInput;this.errorEl.previousElementSibling!==c&&c.after(this.errorEl),this.renderTimer()}requestVerify(){if(this.hasAttribute("disabled")||this.hasAttribute("verified"))return;if(this.backupMode){const t=String(this.backupInput.value||"").replace(/-/g,"");if(8!==t.length)return;return void this.emit("db-verify",{method:"backup",code:t})}const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);t.length!==e||"app"!==this.method&&this.expired||this.emit("db-verify",{method:this.method,code:t})}setTextWithValue(t,i,s,n=[]){const r=e(i).replace(/\{(\d+)\}/g,(t,e)=>"0"===e?t:String(n[Number(e)-1]??"")),[h,o=""]=r.split("{0}"),d=document.createElement("strong");d.textContent=s,t.replaceChildren(document.createTextNode(h),d,document.createTextNode(o))}}customElements.get("db-two-factor")||customElements.define("db-two-factor",DbTwoFactor);export{DbTwoFactor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class ControlLabel{constructor(t){this.host=t}connect(t,e){this.disconnect(),this.target!==t&&(this.target=t,this.slot=t.querySelector(":scope > [data-db-children]"),this.text=void 0),this.slot&&(this.observer=new MutationObserver(e),this.observer.observe(this.slot,{childList:!0,characterData:!0,subtree:!0})),this.sync()}sync(){if(!this.target)return;const t=this.host.getAttribute("label");if(null===t)return this.text?.remove(),void(this.slot&&(this.slot.style.display="contents"));this.text??(this.text=this.target.ownerDocument.createTextNode(""));for(const t of Array.from(this.target.childNodes))t!==this.slot&&t!==this.text&&t.remove();this.text.parentNode!==this.target&&this.target.append(this.text),this.text.data!==t&&(this.text.data=t),this.slot&&(this.slot.style.display="none")}get value(){return this.host.getAttribute("label")??this.target?.textContent??""}disconnect(){this.observer?.disconnect(),this.observer=void 0}}export{ControlLabel};
|