@designbasekorea/ui-wc 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/db-email-verify.d.ts +2 -0
- package/dist/esm/components/db-email-verify.js +1 -1
- package/dist/esm/components/db-phone-verify.d.ts +2 -0
- package/dist/esm/components/db-phone-verify.js +1 -1
- package/dist/esm/components/db-sidebar.d.ts +20 -0
- package/dist/esm/components/db-sidebar.js +1 -1
- package/dist/esm/components/db-two-factor.d.ts +11 -0
- package/dist/esm/components/db-two-factor.js +1 -1
- package/dist/esm/components/highlight-code.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +83 -33
- package/dist/react/index.esm.js +1 -1
- package/package.json +2 -2
- /package/dist/chunks/{lottie-0e23d630.js → lottie-35a9b0f5.js} +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-bash.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-clike.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-css.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-javascript.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-json.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-jsx.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-markup.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-scss.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-tsx.js +0 -0
- /package/dist/esm/node_modules/{.pnpm/prismjs@1.30.0/node_modules/prismjs → prismjs}/components/prism-typescript.js +0 -0
|
@@ -31,11 +31,13 @@ declare class DbEmailVerify extends HTMLElement {
|
|
|
31
31
|
get mode(): 'code' | 'confirm';
|
|
32
32
|
set mode(v: 'code' | 'confirm');
|
|
33
33
|
get size(): Size;
|
|
34
|
+
set size(v: Size);
|
|
34
35
|
get step(): 'email' | 'code' | 'sent' | 'verified';
|
|
35
36
|
set step(v: 'email' | 'code' | 'sent' | 'verified');
|
|
36
37
|
get email(): string;
|
|
37
38
|
set email(v: string);
|
|
38
39
|
get countdown(): number;
|
|
40
|
+
set countdown(v: number);
|
|
39
41
|
connectedCallback(): void;
|
|
40
42
|
disconnectedCallback(): void;
|
|
41
43
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as t}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";const e=["s","m","l"];function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbEmailVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["mode","email","code","step","size","disabled","error","error-message","countdown","title","description","send-label","resend-label","verify-label","confirm-label","code-length","closable","manual","sending","verifying","auto-submit"]}get mode(){return"confirm"===this.getAttribute("mode")?"confirm":"code"}set mode(t){this.setAttribute("mode",t)}get size(){return function pick(t,e,i){return t.includes(e)?e:i}(e,this.getAttribute("size"),"m")}get step(){const t=this.getAttribute("step");return"code"===t||"sent"===t||"verified"===t?t:"email"}set step(t){this.setAttribute("step",t)}get email(){return this.getAttribute("email")||""}set email(t){this.setAttribute("email",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}connectedCallback(){this.build(),this.sync(),"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"!==t&&"mode"!==t||e===i||("code"===this.mode&&"code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"!==this.mode&&(this.mode="code"),"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}markSent(){this.step="sent",this.clearTimer()}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const e="designbase-wc-email-verify";this.replaceChildren();const i=el("div",`${e}__shell`),s=el("div",`${e}__top`),n=el("span",`${e}__eyebrow`);n.dataset.role="eyebrow",this.closeBtn=el("button",`${e}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label","닫기"),this.closeBtn.append(t("close",18)),this.closeBtn.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),s.append(n,this.closeBtn);const r=el("div",`${e}__header`),o=el("h3",`${e}__title`);o.dataset.role="title";const d=el("p",`${e}__description`);d.dataset.role="description",r.append(o,d),this.emailRow=el("div",`${e}__email-row`),this.emailInput=document.createElement("db-input"),this.emailInput.setAttribute("type","email"),this.emailInput.setAttribute("label","이메일"),this.emailInput.setAttribute("placeholder","name@example.com"),this.emailInput.setAttribute("full-width",""),this.emailInput.setAttribute("start-icon","mail"),this.emailInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value??this.emailInput.value??"");this.setAttribute("email",e),this.dispatchEvent(new CustomEvent("db-email-change",{detail:{email:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isEmailValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{email:this.email,mode:this.mode},bubbles:!0,composed:!0})),this.hasAttribute("manual")||("confirm"===this.mode?this.markSent():this.startCodeStep()))}),this.emailRow.append(this.emailInput,this.sendBtn),this.codeBlock=el("div",`${e}__code`);const a=el("div",`${e}__code-head`),l=el("span",`${e}__code-label`);l.textContent="인증 코드",this.timerEl=el("span",`${e}__timer`),a.append(l,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,email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const h=el("div",`${e}__code-actions`);this.resendBtn=el("button",`${e}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),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()}),h.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(a,this.otpInput,h),this.confirmBlock=el("div",`${e}__confirm`);const c=el("div",`${e}__confirm-icon`);c.append(t("mail",40));const m=el("span",`${e}__confirm-badge`);m.append(t("circle-checked",16)),c.append(m);const u=el("h4",`${e}__confirm-title`);u.dataset.role="confirm-title";const b=el("p",`${e}__confirm-desc`);b.dataset.role="confirm-desc",this.confirmBtn=document.createElement("db-button"),this.confirmBtn.setAttribute("variant","primary"),this.confirmBtn.setAttribute("full-width",""),this.confirmBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-confirm",{detail:{email:this.email},bubbles:!0,composed:!0}))});const p=el("button",`${e}__resend`);p.type="button",p.dataset.role="confirm-resend",p.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0}))}),this.confirmBlock.append(c,u,b,this.confirmBtn,p),this.verifiedBlock=el("div",`${e}__confirm`);const f=el("div",`${e}__confirm-icon`);f.append(t("circle-checked",40));const v=el("h4",`${e}__confirm-title`);v.textContent="이메일 인증 완료";const g=el("p",`${e}__confirm-desc`);g.dataset.role="verified-desc",this.verifiedBlock.append(f,v,g),this.errorEl=el("p",`${e}__error`),this.errorEl.hidden=!0,i.append(s,r,this.emailRow,this.codeBlock,this.confirmBlock,this.verifiedBlock,this.errorEl),this.append(i)}sync(){const t="designbase-wc-email-verify",e=this.size,i=this.mode,s=this.step,n=this.hasAttribute("disabled"),r=this.getAttribute("code-length")||"6",o=this.email;this.className=[t,`${t}--${e}`,`${t}--mode-${i}`,`${t}--step-${s}`,n&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" ");this.querySelector('[data-role="eyebrow"]').textContent="confirm"===i?"회원가입":"이메일 인증";const d=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');d.textContent=this.getAttribute("title")||("confirm"===i?"이메일을 확인해 주세요":"이메일 인증");const l=this.getAttribute("description");l?a.textContent=l:"confirm"===i?this.setEmphasizedText(a,"",o||"your@email.com"," 으로 인증 링크를 보냈어요."):this.setEmphasizedText(a,"인증 코드를 ",o||"이메일"," 로 보내 드릴게요."),this.closeBtn&&(this.closeBtn.hidden=!this.hasAttribute("closable")),this.emailInput.value=o,this.emailInput.setAttribute("size",e),this.emailInput.toggleAttribute("disabled",n||"code"===s||"sent"===s||"verified"===s),this.sendBtn.setAttribute("size",e),this.sendBtn.textContent=this.getAttribute("send-label")||("confirm"===i?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",n||!this.isEmailValid()||"email"!==s),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",r),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",n||"code"!==s),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",n||"code"!==s||(this.getAttribute("code")||"").length!==Number(r)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying"));const h=this.querySelector('[data-role="confirm-title"]'),c=this.querySelector('[data-role="confirm-desc"]');h.textContent="메일함을 확인해 주세요!",this.setEmphasizedText(c,"",o||"your@email.com"," 으로 보낸 링크를 클릭하면 인증이 완료됩니다."),this.confirmBtn.setAttribute("size",e),this.confirmBtn.textContent=this.getAttribute("confirm-label")||"확인";const m=this.querySelector('[data-role="confirm-resend"]');m&&(m.textContent="메일 다시 보내기");const u=this.querySelector('[data-role="verified-desc"]');this.setEmphasizedText(u,"",o||"your@email.com"," 주소가 인증되었습니다."),this.emailRow.hidden="confirm"===i&&("sent"===s||"verified"===s)||"code"===i&&"verified"===s,this.codeBlock.hidden=!("code"===i&&"code"===s),this.confirmBlock.hidden=!("confirm"===i&&("sent"===s||"verified"===s)),this.verifiedBlock.hidden=!("code"===i&&"verified"===s);const b=this.getAttribute("error-message")||"";this.errorEl.textContent=b,this.errorEl.hidden=!this.hasAttribute("error")||!b}isEmailValid(){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email.trim())}requestVerify(){const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{email:this.email,code:t},bubbles:!0,composed:!0}))}setEmphasizedText(t,e,i,s){const n=document.createElement("strong");n.textContent=i,t.replaceChildren(document.createTextNode(e),n,document.createTextNode(s))}}customElements.get("db-email-verify")||customElements.define("db-email-verify",DbEmailVerify);export{DbEmailVerify};
|
|
1
|
+
import{createDbIcon as t}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";const e=["s","m","l"];function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbEmailVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["mode","email","code","step","size","disabled","error","error-message","countdown","title","description","send-label","resend-label","verify-label","confirm-label","code-length","closable","manual","sending","verifying","auto-submit"]}get mode(){return"confirm"===this.getAttribute("mode")?"confirm":"code"}set mode(t){this.setAttribute("mode",t)}get size(){return function pick(t,e,i){return t.includes(e)?e:i}(e,this.getAttribute("size"),"m")}set size(t){this.setAttribute("size",t)}get step(){const t=this.getAttribute("step");return"code"===t||"sent"===t||"verified"===t?t:"email"}set step(t){this.setAttribute("step",t)}get email(){return this.getAttribute("email")||""}set email(t){this.setAttribute("email",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))}connectedCallback(){this.build(),this.sync(),"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"!==t&&"mode"!==t||e===i||("code"===this.mode&&"code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"!==this.mode&&(this.mode="code"),"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}markSent(){this.step="sent",this.clearTimer()}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const e="designbase-wc-email-verify";this.replaceChildren();const i=el("div",`${e}__shell`),s=el("div",`${e}__top`),n=el("span",`${e}__eyebrow`);n.dataset.role="eyebrow",this.closeBtn=el("button",`${e}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label","닫기"),this.closeBtn.append(t("close",18)),this.closeBtn.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),s.append(n,this.closeBtn);const r=el("div",`${e}__header`),o=el("h3",`${e}__title`);o.dataset.role="title";const d=el("p",`${e}__description`);d.dataset.role="description",r.append(o,d),this.emailRow=el("div",`${e}__email-row`),this.emailInput=document.createElement("db-input"),this.emailInput.setAttribute("type","email"),this.emailInput.setAttribute("label","이메일"),this.emailInput.setAttribute("placeholder","name@example.com"),this.emailInput.setAttribute("full-width",""),this.emailInput.setAttribute("start-icon","mail"),this.emailInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value??this.emailInput.value??"");this.setAttribute("email",e),this.dispatchEvent(new CustomEvent("db-email-change",{detail:{email:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isEmailValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{email:this.email,mode:this.mode},bubbles:!0,composed:!0})),this.hasAttribute("manual")||("confirm"===this.mode?this.markSent():this.startCodeStep()))}),this.emailRow.append(this.emailInput,this.sendBtn),this.codeBlock=el("div",`${e}__code`);const a=el("div",`${e}__code-head`),l=el("span",`${e}__code-label`);l.textContent="인증 코드",this.timerEl=el("span",`${e}__timer`),a.append(l,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,email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const h=el("div",`${e}__code-actions`);this.resendBtn=el("button",`${e}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),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()}),h.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(a,this.otpInput,h),this.confirmBlock=el("div",`${e}__confirm`);const c=el("div",`${e}__confirm-icon`);c.append(t("mail",40));const m=el("span",`${e}__confirm-badge`);m.append(t("circle-checked",16)),c.append(m);const u=el("h4",`${e}__confirm-title`);u.dataset.role="confirm-title";const b=el("p",`${e}__confirm-desc`);b.dataset.role="confirm-desc",this.confirmBtn=document.createElement("db-button"),this.confirmBtn.setAttribute("variant","primary"),this.confirmBtn.setAttribute("full-width",""),this.confirmBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-confirm",{detail:{email:this.email},bubbles:!0,composed:!0}))});const p=el("button",`${e}__resend`);p.type="button",p.dataset.role="confirm-resend",p.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0}))}),this.confirmBlock.append(c,u,b,this.confirmBtn,p),this.verifiedBlock=el("div",`${e}__confirm`);const f=el("div",`${e}__confirm-icon`);f.append(t("circle-checked",40));const v=el("h4",`${e}__confirm-title`);v.textContent="이메일 인증 완료";const g=el("p",`${e}__confirm-desc`);g.dataset.role="verified-desc",this.verifiedBlock.append(f,v,g),this.errorEl=el("p",`${e}__error`),this.errorEl.hidden=!0,i.append(s,r,this.emailRow,this.codeBlock,this.confirmBlock,this.verifiedBlock,this.errorEl),this.append(i)}sync(){const t="designbase-wc-email-verify",e=this.size,i=this.mode,s=this.step,n=this.hasAttribute("disabled"),r=this.getAttribute("code-length")||"6",o=this.email;this.className=[t,`${t}--${e}`,`${t}--mode-${i}`,`${t}--step-${s}`,n&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" ");this.querySelector('[data-role="eyebrow"]').textContent="confirm"===i?"회원가입":"이메일 인증";const d=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');d.textContent=this.getAttribute("title")||("confirm"===i?"이메일을 확인해 주세요":"이메일 인증");const l=this.getAttribute("description");l?a.textContent=l:"confirm"===i?this.setEmphasizedText(a,"",o||"your@email.com"," 으로 인증 링크를 보냈어요."):this.setEmphasizedText(a,"인증 코드를 ",o||"이메일"," 로 보내 드릴게요."),this.closeBtn&&(this.closeBtn.hidden=!this.hasAttribute("closable")),this.emailInput.value=o,this.emailInput.setAttribute("size",e),this.emailInput.toggleAttribute("disabled",n||"code"===s||"sent"===s||"verified"===s),this.sendBtn.setAttribute("size",e),this.sendBtn.textContent=this.getAttribute("send-label")||("confirm"===i?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",n||!this.isEmailValid()||"email"!==s),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",r),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",n||"code"!==s),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",n||"code"!==s||(this.getAttribute("code")||"").length!==Number(r)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying"));const h=this.querySelector('[data-role="confirm-title"]'),c=this.querySelector('[data-role="confirm-desc"]');h.textContent="메일함을 확인해 주세요!",this.setEmphasizedText(c,"",o||"your@email.com"," 으로 보낸 링크를 클릭하면 인증이 완료됩니다."),this.confirmBtn.setAttribute("size",e),this.confirmBtn.textContent=this.getAttribute("confirm-label")||"확인";const m=this.querySelector('[data-role="confirm-resend"]');m&&(m.textContent="메일 다시 보내기");const u=this.querySelector('[data-role="verified-desc"]');this.setEmphasizedText(u,"",o||"your@email.com"," 주소가 인증되었습니다."),this.emailRow.hidden="confirm"===i&&("sent"===s||"verified"===s)||"code"===i&&"verified"===s,this.codeBlock.hidden=!("code"===i&&"code"===s),this.confirmBlock.hidden=!("confirm"===i&&("sent"===s||"verified"===s)),this.verifiedBlock.hidden=!("code"===i&&"verified"===s);const b=this.getAttribute("error-message")||"";this.errorEl.textContent=b,this.errorEl.hidden=!this.hasAttribute("error")||!b}isEmailValid(){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email.trim())}requestVerify(){const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{email:this.email,code:t},bubbles:!0,composed:!0}))}setEmphasizedText(t,e,i,s){const n=document.createElement("strong");n.textContent=i,t.replaceChildren(document.createTextNode(e),n,document.createTextNode(s))}}customElements.get("db-email-verify")||customElements.define("db-email-verify",DbEmailVerify);export{DbEmailVerify};
|
|
@@ -26,6 +26,7 @@ declare class DbPhoneVerify extends HTMLElement {
|
|
|
26
26
|
private codeBlock;
|
|
27
27
|
private errorEl;
|
|
28
28
|
get size(): Size;
|
|
29
|
+
set size(v: Size);
|
|
29
30
|
get step(): 'phone' | 'code' | 'verified';
|
|
30
31
|
set step(v: 'phone' | 'code' | 'verified');
|
|
31
32
|
get phone(): string;
|
|
@@ -35,6 +36,7 @@ declare class DbPhoneVerify extends HTMLElement {
|
|
|
35
36
|
get code(): string;
|
|
36
37
|
set code(v: string);
|
|
37
38
|
get countdown(): number;
|
|
39
|
+
set countdown(v: number);
|
|
38
40
|
connectedCallback(): void;
|
|
39
41
|
disconnectedCallback(): void;
|
|
40
42
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-select.js";const t=[{value:"skt",label:"SKT"},{value:"kt",label:"KT"},{value:"lgu",label:"LG U+"},{value:"mvno",label:"알뜰폰"}],e=["s","m","l"];function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}function formatPhone(t){const e=t.replace(/\D/g,"").slice(0,11);return e.length<=3?e:e.length<=7?`${e.slice(0,3)}-${e.slice(3)}`:`${e.slice(0,3)}-${e.slice(3,7)}-${e.slice(7)}`}class DbPhoneVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["carrier","phone","code","step","size","disabled","error","error-message","carrier-options","countdown","title","description","send-label","resend-label","verify-label","code-length","manual","sending","verifying","auto-submit"]}get size(){return function pick(t,e,i){return t.includes(e)?e:i}(e,this.getAttribute("size"),"m")}get step(){const t=this.getAttribute("step");return"code"===t||"verified"===t?t:"phone"}set step(t){this.setAttribute("step",t)}get phone(){return(this.getAttribute("phone")||"").replace(/\D/g,"")}set phone(t){this.setAttribute("phone",formatPhone(t))}get carrier(){return this.getAttribute("carrier")||"skt"}set carrier(t){this.setAttribute("carrier",t)}get code(){return this.getAttribute("code")||""}set code(t){this.setAttribute("code",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}connectedCallback(){this.build(),this.sync(),"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"===t&&e!==i&&("code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.step&&this.startTimer(this.countdown)}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const t="designbase-wc-phone-verify";this.replaceChildren();const e=el("div",`${t}__header`),i=el("h3",`${t}__title`);i.dataset.role="title";const s=el("p",`${t}__description`);s.dataset.role="description",e.append(i,s);const r=el("div",`${t}__field`);this.carrierSelect=document.createElement("db-select"),this.carrierSelect.setAttribute("label","통신사"),this.carrierSelect.setAttribute("full-width",""),this.carrierSelect.setAttribute("placeholder","통신사 선택"),this.carrierSelect.addEventListener("db-change",t=>{t.stopPropagation();const e=t.detail?.value??this.carrierSelect.value;this.carrier=String(e||""),this.dispatchEvent(new CustomEvent("db-carrier-change",{detail:{carrier:this.carrier},bubbles:!0,composed:!0}))}),r.append(this.carrierSelect);const n=el("div",`${t}__phone-row`);this.phoneInput=document.createElement("db-input"),this.phoneInput.setAttribute("type","tel"),this.phoneInput.setAttribute("label","휴대폰 번호"),this.phoneInput.setAttribute("placeholder","010-0000-0000"),this.phoneInput.setAttribute("full-width",""),this.phoneInput.setAttribute("start-icon","user"),this.phoneInput.addEventListener("db-input",t=>{t.stopPropagation();const e=formatPhone(String(t.detail?.value??this.phoneInput.value??""));this.phoneInput.value=e,this.setAttribute("phone",e),this.dispatchEvent(new CustomEvent("db-phone-change",{detail:{phone:e.replace(/\D/g,""),formatted:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isPhoneValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startCodeStep())}),n.append(this.phoneInput,this.sendBtn),this.codeBlock=el("div",`${t}__code`);const o=el("div",`${t}__code-head`),h=el("span",`${t}__code-label`);h.textContent="인증번호",this.timerEl=el("span",`${t}__timer`),o.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,carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const a=el("div",`${t}__code-actions`);this.resendBtn=el("button",`${t}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),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()}),a.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(o,this.otpInput,a),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0;const d=el("div",`${t}__verified`);d.dataset.role="verified",d.innerHTML=`<span class="${t}__verified-badge">인증 완료</span><p class="${t}__verified-text">휴대폰 번호 인증이 완료되었습니다.</p>`,this.append(e,r,n,this.codeBlock,this.errorEl,d)}sync(){const e="designbase-wc-phone-verify",i=this.size,s=this.step,r=this.hasAttribute("disabled"),n=function parseCarriers(e){if(!e)return t;try{const i=JSON.parse(e);return Array.isArray(i)&&i.length?i:t}catch{return t}}(this.getAttribute("carrier-options")),o=this.getAttribute("code-length")||"6";this.className=[e,`${e}--${i}`,`${e}--step-${s}`,r&&`${e}--disabled`,this.hasAttribute("error")&&`${e}--error`].filter(Boolean).join(" ");const h=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');h.textContent=this.getAttribute("title")||"휴대폰 인증",a.textContent=this.getAttribute("description")||"본인 명의의 휴대폰 번호를 입력하고 인증번호를 받아 주세요.",this.carrierSelect.setAttribute("options",JSON.stringify(n)),this.carrierSelect.setAttribute("value",this.carrier),this.carrierSelect.setAttribute("size",i),this.carrierSelect.toggleAttribute("disabled",r||"verified"===s);const d=this.getAttribute("phone")||"";this.phoneInput.value=d,this.phoneInput.setAttribute("size",i),this.phoneInput.toggleAttribute("disabled",r||"phone"!==s),this.phoneInput.toggleAttribute("error",this.hasAttribute("error")&&"phone"===s),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||"인증번호 받기",this.sendBtn.toggleAttribute("disabled",r||"phone"!==s||!this.isPhoneValid()),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",o),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",r||"code"!==s),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&"code"===s),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",r||(this.getAttribute("code")||"").length<Number(o)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.codeBlock.hidden="phone"===s;this.querySelector('[data-role="verified"]').hidden="verified"!==s;const l=this.getAttribute("error-message")||"";this.errorEl.textContent=l,this.errorEl.hidden=!this.hasAttribute("error")||!l}isPhoneValid(){return/^01[016789]\d{7,8}$/.test(this.phone)&&Boolean(this.carrier)}requestVerify(){const t=(this.code||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{carrier:this.carrier,phone:this.phone,code:t},bubbles:!0,composed:!0}))}}customElements.get("db-phone-verify")||customElements.define("db-phone-verify",DbPhoneVerify);export{DbPhoneVerify};
|
|
1
|
+
import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-select.js";const t=[{value:"skt",label:"SKT"},{value:"kt",label:"KT"},{value:"lgu",label:"LG U+"},{value:"mvno",label:"알뜰폰"}],e=["s","m","l"];function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}function formatPhone(t){const e=t.replace(/\D/g,"").slice(0,11);return e.length<=3?e:e.length<=7?`${e.slice(0,3)}-${e.slice(3)}`:`${e.slice(0,3)}-${e.slice(3,7)}-${e.slice(7)}`}class DbPhoneVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["carrier","phone","code","step","size","disabled","error","error-message","carrier-options","countdown","title","description","send-label","resend-label","verify-label","code-length","manual","sending","verifying","auto-submit"]}get size(){return function pick(t,e,i){return t.includes(e)?e:i}(e,this.getAttribute("size"),"m")}set size(t){this.setAttribute("size",t)}get step(){const t=this.getAttribute("step");return"code"===t||"verified"===t?t:"phone"}set step(t){this.setAttribute("step",t)}get phone(){return(this.getAttribute("phone")||"").replace(/\D/g,"")}set phone(t){this.setAttribute("phone",formatPhone(t))}get carrier(){return this.getAttribute("carrier")||"skt"}set carrier(t){this.setAttribute("carrier",t)}get code(){return this.getAttribute("code")||""}set code(t){this.setAttribute("code",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))}connectedCallback(){this.build(),this.sync(),"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"===t&&e!==i&&("code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.step&&this.startTimer(this.countdown)}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const t="designbase-wc-phone-verify";this.replaceChildren();const e=el("div",`${t}__header`),i=el("h3",`${t}__title`);i.dataset.role="title";const s=el("p",`${t}__description`);s.dataset.role="description",e.append(i,s);const r=el("div",`${t}__field`);this.carrierSelect=document.createElement("db-select"),this.carrierSelect.setAttribute("label","통신사"),this.carrierSelect.setAttribute("full-width",""),this.carrierSelect.setAttribute("placeholder","통신사 선택"),this.carrierSelect.addEventListener("db-change",t=>{t.stopPropagation();const e=t.detail?.value??this.carrierSelect.value;this.carrier=String(e||""),this.dispatchEvent(new CustomEvent("db-carrier-change",{detail:{carrier:this.carrier},bubbles:!0,composed:!0}))}),r.append(this.carrierSelect);const n=el("div",`${t}__phone-row`);this.phoneInput=document.createElement("db-input"),this.phoneInput.setAttribute("type","tel"),this.phoneInput.setAttribute("label","휴대폰 번호"),this.phoneInput.setAttribute("placeholder","010-0000-0000"),this.phoneInput.setAttribute("full-width",""),this.phoneInput.setAttribute("start-icon","user"),this.phoneInput.addEventListener("db-input",t=>{t.stopPropagation();const e=formatPhone(String(t.detail?.value??this.phoneInput.value??""));this.phoneInput.value=e,this.setAttribute("phone",e),this.dispatchEvent(new CustomEvent("db-phone-change",{detail:{phone:e.replace(/\D/g,""),formatted:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isPhoneValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startCodeStep())}),n.append(this.phoneInput,this.sendBtn),this.codeBlock=el("div",`${t}__code`);const o=el("div",`${t}__code-head`),h=el("span",`${t}__code-label`);h.textContent="인증번호",this.timerEl=el("span",`${t}__timer`),o.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,carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const a=el("div",`${t}__code-actions`);this.resendBtn=el("button",`${t}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),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()}),a.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(o,this.otpInput,a),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0;const d=el("div",`${t}__verified`);d.dataset.role="verified",d.innerHTML=`<span class="${t}__verified-badge">인증 완료</span><p class="${t}__verified-text">휴대폰 번호 인증이 완료되었습니다.</p>`,this.append(e,r,n,this.codeBlock,this.errorEl,d)}sync(){const e="designbase-wc-phone-verify",i=this.size,s=this.step,r=this.hasAttribute("disabled"),n=function parseCarriers(e){if(!e)return t;try{const i=JSON.parse(e);return Array.isArray(i)&&i.length?i:t}catch{return t}}(this.getAttribute("carrier-options")),o=this.getAttribute("code-length")||"6";this.className=[e,`${e}--${i}`,`${e}--step-${s}`,r&&`${e}--disabled`,this.hasAttribute("error")&&`${e}--error`].filter(Boolean).join(" ");const h=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');h.textContent=this.getAttribute("title")||"휴대폰 인증",a.textContent=this.getAttribute("description")||"본인 명의의 휴대폰 번호를 입력하고 인증번호를 받아 주세요.",this.carrierSelect.setAttribute("options",JSON.stringify(n)),this.carrierSelect.setAttribute("value",this.carrier),this.carrierSelect.setAttribute("size",i),this.carrierSelect.toggleAttribute("disabled",r||"verified"===s);const d=this.getAttribute("phone")||"";this.phoneInput.value=d,this.phoneInput.setAttribute("size",i),this.phoneInput.toggleAttribute("disabled",r||"phone"!==s),this.phoneInput.toggleAttribute("error",this.hasAttribute("error")&&"phone"===s),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||"인증번호 받기",this.sendBtn.toggleAttribute("disabled",r||"phone"!==s||!this.isPhoneValid()),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",o),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",r||"code"!==s),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&"code"===s),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",r||(this.getAttribute("code")||"").length<Number(o)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.codeBlock.hidden="phone"===s;this.querySelector('[data-role="verified"]').hidden="verified"!==s;const l=this.getAttribute("error-message")||"";this.errorEl.textContent=l,this.errorEl.hidden=!this.hasAttribute("error")||!l}isPhoneValid(){return/^01[016789]\d{7,8}$/.test(this.phone)&&Boolean(this.carrier)}requestVerify(){const t=(this.code||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{carrier:this.carrier,phone:this.phone,code:t},bubbles:!0,composed:!0}))}}customElements.get("db-phone-verify")||customElements.define("db-phone-verify",DbPhoneVerify);export{DbPhoneVerify};
|
|
@@ -7,11 +7,19 @@ interface DbSidebarItem {
|
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
badge?: string | number;
|
|
9
9
|
badgeColor?: string;
|
|
10
|
+
/** 프로필 메뉴 우측에 표시할 현재 값 (예: "System", "한국어") */
|
|
11
|
+
value?: string;
|
|
12
|
+
/** 2depth 선택 상태. 선택된 항목에는 체크 아이콘이 표시됩니다. */
|
|
13
|
+
selected?: boolean;
|
|
14
|
+
/** 프로필 메뉴에서 이 항목 앞에 구분선을 표시합니다. */
|
|
15
|
+
dividerBefore?: boolean;
|
|
10
16
|
children?: DbSidebarItem[];
|
|
11
17
|
}
|
|
12
18
|
interface DbSidebarSection {
|
|
13
19
|
id: string;
|
|
14
20
|
title?: string;
|
|
21
|
+
/** 이전 섹션과의 간격 */
|
|
22
|
+
gap?: 'none' | 's' | 'm' | 'l';
|
|
15
23
|
items: DbSidebarItem[];
|
|
16
24
|
}
|
|
17
25
|
interface DbSidebarUserProfile {
|
|
@@ -42,7 +50,9 @@ declare class DbSidebar extends HTMLElement {
|
|
|
42
50
|
private userMenuOpen;
|
|
43
51
|
private projectMenuOpen;
|
|
44
52
|
private flyoutItemId;
|
|
53
|
+
private userFlyoutItemId;
|
|
45
54
|
private flyoutCloseTimer;
|
|
55
|
+
private userFlyoutCloseTimer;
|
|
46
56
|
private outsideHandler;
|
|
47
57
|
static get observedAttributes(): string[];
|
|
48
58
|
connectedCallback(): void;
|
|
@@ -77,6 +87,12 @@ declare class DbSidebar extends HTMLElement {
|
|
|
77
87
|
set bottomSections(value: DbSidebarSection[] | string);
|
|
78
88
|
get promoBanner(): DbSidebarPromoBanner | null;
|
|
79
89
|
set promoBanner(value: DbSidebarPromoBanner | string | null);
|
|
90
|
+
get headerType(): 'default' | 'back';
|
|
91
|
+
set headerType(value: 'default' | 'back');
|
|
92
|
+
get backLabel(): string;
|
|
93
|
+
set backLabel(value: string);
|
|
94
|
+
get backHref(): string;
|
|
95
|
+
set backHref(value: string);
|
|
80
96
|
private parseSections;
|
|
81
97
|
private parseUserMenuItems;
|
|
82
98
|
private parseUserProfile;
|
|
@@ -92,9 +108,13 @@ declare class DbSidebar extends HTMLElement {
|
|
|
92
108
|
private cancelFlyoutClose;
|
|
93
109
|
private showFlyout;
|
|
94
110
|
private scheduleFlyoutClose;
|
|
111
|
+
private cancelUserFlyoutClose;
|
|
112
|
+
private setUserFlyout;
|
|
113
|
+
private scheduleUserFlyoutClose;
|
|
95
114
|
private syncHostClasses;
|
|
96
115
|
private dispatchItemClick;
|
|
97
116
|
private dispatchUserMenuItemClick;
|
|
117
|
+
private dispatchBackClick;
|
|
98
118
|
private dispatchProjectChange;
|
|
99
119
|
private dispatchProjectManage;
|
|
100
120
|
private dispatchPromoCtaClick;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as e,isDbIconName as t}from"./db-icons.js";const s=["s","m","l"],i=["default","dark","light"],r=["left","right"];class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.flyoutCloseTimer=null,this.outsideHandler=null}static get observedAttributes(){return["items","sections","user-menu-items","user-profile","default-expanded-ids","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","size","variant","position","collapsed","collapsible","show-logo","full-height","shadow"]}connectedCallback(){this.seedExpanded(),this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick(),this.cancelFlyoutClose()}attributeChangedCallback(e){this.isConnected&&("default-expanded-ids"===e&&this.seedExpanded(),"collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.cancelFlyoutClose()),this.render())}seedExpanded(){try{const e=JSON.parse(this.getAttribute("default-expanded-ids")||"[]");Array.isArray(e)&&(this.expandedItems=new Set(e))}catch{this.expandedItems=new Set}}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||"프로젝트 관리"}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||"프로젝트"}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||"프로젝트를 추가해 주세요"}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||"프로젝트 추가"}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncExclusiveAccordion(e){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(t=>{const s=t.getAttribute("data-item-id");s&&(e&&s===e?t.setAttribute("expanded",""):t.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",a=this.getAttribute("position")||"left";this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--${s.includes(e)?e:"m"}`,`designbase-wc-sidebar--${i.includes(t)?t:"default"}`,`designbase-wc-sidebar--${r.includes(a)?a:"left"}`,this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow"].filter(Boolean).join(" ")}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(t="s"){const s=document.createElement("span");return s.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${t}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),s.setAttribute("aria-hidden","true"),s.append(e("plus","m"===t?16:14)),s}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("badge-style","text"),t.textContent=e.badge,t}createProjectSelector(t){if(!this.hasAttribute("projects"))return null;const s=this.parseProjects(),i=0===s.length,r=this.getSelectedProject(),a=document.createElement("div");a.className=["designbase-wc-sidebar__project-selector",t&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",i&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const n=this.getAttribute("project-section-label");if(!t&&n&&n.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=n.trim(),a.append(e)}const o=document.createElement("button");if(o.type="button",o.className="designbase-wc-sidebar__project-trigger",o.setAttribute("aria-haspopup","menu"),o.setAttribute("aria-expanded",String(this.projectMenuOpen)),i||!r){if(o.setAttribute("aria-label",this.projectEmptyTriggerLabel),o.append(this.createProjectEmptyMark(t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,o.append(e)}}else if(o.setAttribute("aria-label",r.label),o.append(this.createProjectAvatar(r,t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=r.label,o.append(e)}const c=document.createElement("span");if(c.className="designbase-wc-sidebar__project-chevron",c.setAttribute("aria-hidden","true"),c.append(e("chevron-down",14)),o.append(c),o.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),a.append(o),this.projectMenuOpen){const t=document.createElement("div");if(t.className="designbase-wc-sidebar__project-dropdown",t.setAttribute("role","menu"),t.setAttribute("aria-label",this.projectSectionLabel),i){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-empty",e.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,e.append(s),t.append(e)}else{const e=document.createElement("ul");e.className="designbase-wc-sidebar__project-list",s.forEach(t=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",r&&t.id===r.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(t,"s"));const a=document.createElement("span");a.className="designbase-wc-sidebar__project-option-label",a.textContent=t.label,i.append(a);const n=this.createProjectBadge(t);n&&i.append(n),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",t.id),this.dispatchProjectChange(t),this.render()}),s.append(i),e.append(s)}),t.append(e)}const n=document.createElement("button");n.type="button",n.className="designbase-wc-sidebar__project-manage",n.setAttribute("role","menuitem"),n.append(e("plus",14));const o=document.createElement("span");o.textContent=this.projectManageLabel,n.append(o),n.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref;e&&window.location.assign(e),this.dispatchProjectManage(),this.render()}),t.append(n),a.append(t)}return a}createFlyout(e,t){const s=this.getAttribute("position")||"left",i=document.createElement("div");i.className=["designbase-wc-sidebar__flyout","right"===s&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),i.setAttribute("role","menu"),i.setAttribute("aria-label",`${e.label} 하위 메뉴`),i.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),i.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const r=document.createElement("div");r.className="designbase-wc-sidebar__flyout-title",r.textContent=e.label,i.append(r);const a=document.createElement("ul");return a.className="designbase-wc-sidebar__flyout-list",(e.children||[]).forEach(e=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",t),e.href&&i.setAttribute("href",e.href),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),s.append(i),a.append(s)}),i.append(a),i}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),r=this.expandedItems.has(e.id),a=this.hasAttribute("collapsed"),n=a&&i,o=document.createElement("li");o.className=["designbase-wc-sidebar__item",n&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),n&&(o.addEventListener("mouseenter",()=>this.showFlyout(e.id)),o.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const c=document.createElement("db-menu-item");if(c.setAttribute("data-item-id",e.id),c.setAttribute("label",e.label),c.setAttribute("type","block"),c.setAttribute("menu-style","accordion"),c.setAttribute("size",t),c.setAttribute("depth",String(s)),e.href&&c.setAttribute("href",e.href),e.icon&&c.setAttribute("icon",e.icon),e.active&&c.setAttribute("active",""),e.disabled&&c.setAttribute("disabled",""),void 0!==e.badge&&c.setAttribute("badge",String(e.badge)),e.badgeColor&&c.setAttribute("badge-color",e.badgeColor),i&&!n&&(c.setAttribute("expandable",""),c.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor})),r&&!a&&c.setAttribute("expanded","")),c.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!a){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),void(s?(this.expandedItems.clear(),this.expandedItems.add(e.id),this.syncExclusiveAccordion(e.id)):(this.expandedItems.delete(e.id),this.syncExclusiveAccordion(null)))}if(n)return this.closeOverlayMenus(),void this.showFlyout(e.id);this.closeOverlayMenus(),this.dispatchItemClick(e)}}),c.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),o.append(c),a&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),o.append(s)}if(a&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),o.append(t)}return n&&this.flyoutItemId===e.id&&o.append(this.createFlyout(e,t)),o}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const r=document.createElement("div");if(r.className="designbase-wc-sidebar__section",!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,r.append(t)}const a=document.createElement("ul");a.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>a.append(this.createSidebarMenuItem(e,t))),r.append(a),i.append(r)}),i}renderNav(){const e=this.querySelector(".designbase-wc-sidebar__nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseSections(),t,s))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(e,t=!1){if(!e.length)return null;const s=this.getAttribute("size")||"m",i=document.createElement("div");i.className=["designbase-wc-sidebar__user-dropdown",t&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),i.setAttribute("role","menu"),i.setAttribute("aria-label","사용자 메뉴"),i.hidden=!this.userMenuOpen;const r=document.createElement("ul");return r.className="designbase-wc-sidebar__user-menu",e.forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__user-menu-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","accordion"),i.setAttribute("size",s),e.icon&&i.setAttribute("icon",e.icon),e.href&&i.setAttribute("href",e.href),i.addEventListener("db-click",()=>{this.userMenuOpen=!1,this.dispatchUserMenuItemClick(e),this.render()}),t.append(i),r.append(t)}),i.append(r),i}createPromoBanner(s){const i=this.parsePromoBanner();if(!i)return null;if(s){const s=document.createElement("button");s.type="button",s.className="designbase-wc-sidebar__promo-collapsed",s.setAttribute("aria-label",i.ctaLabel||i.title);const r=document.createElement("db-animation-background");r.className="designbase-wc-sidebar__promo-bg",r.setAttribute("type","aurora"),r.setAttribute("theme","light"),r.setAttribute("intensity","subtle"),r.setAttribute("blur","40"),r.setAttribute("speed","4000"),r.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),s.append(r),s.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",18)),s.addEventListener("click",()=>this.dispatchPromoCtaClick(i));const a=document.createElement("span");a.className="designbase-wc-sidebar__item-tooltip",a.textContent=i.title,a.setAttribute("role","tooltip");const n=document.createElement("div");return n.className="designbase-wc-sidebar__promo-collapsed-wrap",n.append(s,a),n}const r=document.createElement("div");r.className="designbase-wc-sidebar__promo";const a=document.createElement("db-animation-background");a.className="designbase-wc-sidebar__promo-bg",a.setAttribute("type","aurora"),a.setAttribute("theme","light"),a.setAttribute("intensity","subtle"),a.setAttribute("blur","60"),a.setAttribute("speed","5000"),a.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),r.append(a);const n=document.createElement("div");n.className="designbase-wc-sidebar__promo-content";const o=document.createElement("div");o.className="designbase-wc-sidebar__promo-title-row";const c=document.createElement("span");c.className="designbase-wc-sidebar__promo-icon",c.setAttribute("aria-hidden","true"),c.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",16));const d=document.createElement("div");if(d.className="designbase-wc-sidebar__promo-title",d.textContent=i.title,o.append(c,d),n.append(o),i.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=i.description,n.append(e)}if(i.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=i.ctaLabel,e.addEventListener("db-click",()=>{i.ctaHref&&window.location.assign(i.ctaHref),this.dispatchPromoCtaClick(i)}),n.append(e)}return r.append(n),r}render(){this.syncHostClasses(),this.setAttribute("role","complementary"),this.setAttribute("aria-label","사이드바 네비게이션");const t=this.getAttribute("size")||"m",s="false"!==this.getAttribute("collapsible"),i="false"!==this.getAttribute("show-logo"),r=this.hasAttribute("collapsed"),a=this.parseUserProfile(),n=this.parseUserMenuItems(),o=this.parseBottomSections(),c="l"===t?"m":"s"===t?"xs":"s";this.replaceChildren();const d=document.createElement("div");if(d.className="designbase-wc-sidebar__container",s||i&&!r){const e=document.createElement("div");if(e.className=["designbase-wc-sidebar__header",(r||!i)&&"designbase-wc-sidebar__header--collapsed-only"].filter(Boolean).join(" "),!r&&i){const t=document.createElement("div");t.className="designbase-wc-sidebar__logo";const s=document.createElement("db-logo");s.setAttribute("type","designbase"),s.setAttribute("size",c),t.append(s),t.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),e.append(t)}if(s){const t=document.createElement("db-button");t.className="designbase-wc-sidebar__toggle",t.setAttribute("variant","tertiary"),t.setAttribute("size","s"),t.setAttribute("icon-only",""),t.setAttribute("start-icon",r?"arrow-bar-right":"arrow-bar-left"),t.setAttribute("aria-label",r?"사이드바 펼치기":"사이드바 접기"),t.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),e.append(t)}d.append(e)}const l=document.createElement("div");l.className="designbase-wc-sidebar__nav-wrapper";const b=this.createProjectSelector(r);b&&l.append(b);const u=document.createElement("nav");if(u.className="designbase-wc-sidebar__nav",u.setAttribute("aria-label","주 메뉴"),l.append(u),o.length>0){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label","하단 메뉴"),l.append(e)}d.append(l);const p=document.createElement("div");p.className="designbase-wc-sidebar__footer";const m=this.createPromoBanner(r);if(m&&p.append(m),a&&!r){const t=document.createElement("div");t.className="designbase-wc-sidebar__user";const s=this.createUserDropdown(n);s&&t.append(s);const i=document.createElement("div");i.className="designbase-wc-sidebar__user-info",i.setAttribute("role","button"),i.setAttribute("tabindex","0"),i.setAttribute("aria-expanded",String(this.userMenuOpen));const r=document.createElement("db-avatar");r.className="designbase-wc-sidebar__user-avatar",r.setAttribute("size","s"),r.setAttribute("initials",a.name),r.setAttribute("alt",a.name),a.avatar&&r.setAttribute("src",a.avatar);const o=document.createElement("div");o.className="designbase-wc-sidebar__user-details";const c=document.createElement("div");if(c.className="designbase-wc-sidebar__user-name",c.textContent=a.name,o.append(c),a.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=a.email,o.append(e)}if(i.append(r,o),n.length){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-more",t.setAttribute("aria-hidden","true"),t.append(e("more-vertical",16)),i.append(t),i.setAttribute("aria-haspopup","menu")}i.addEventListener("click",()=>{n.length&&(this.userMenuOpen=!this.userMenuOpen,this.projectMenuOpen=!1,this.render())}),t.append(i),p.append(t)}else if(a&&r){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",a.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),n.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",a.name),t.setAttribute("alt",a.name),a.avatar&&t.setAttribute("src",a.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=a.name,t.setAttribute("role","tooltip"),e.append(t)}const s=this.createUserDropdown(n,!0);s&&e.append(s),e.addEventListener("click",e=>{n.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.projectMenuOpen=!1,this.render()))}),p.append(e)}d.append(p),this.append(d),this.renderNav(),this.renderBottomNav()}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
|
|
1
|
+
import{createDbIcon as e,isDbIconName as t}from"./db-icons.js";const s=["s","m","l"],i=["default","dark","light"],r=["left","right"];class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.flyoutCloseTimer=null,this.userFlyoutCloseTimer=null,this.outsideHandler=null}static get observedAttributes(){return["items","sections","user-menu-items","user-profile","default-expanded-ids","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","header-type","back-label","back-href","size","variant","position","collapsed","collapsible","show-logo","full-height","shadow"]}connectedCallback(){this.seedExpanded(),this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick(),this.cancelFlyoutClose(),this.cancelUserFlyoutClose()}attributeChangedCallback(e){this.isConnected&&("default-expanded-ids"===e&&this.seedExpanded(),"collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.cancelFlyoutClose(),this.cancelUserFlyoutClose()),this.render())}seedExpanded(){try{const e=JSON.parse(this.getAttribute("default-expanded-ids")||"[]");Array.isArray(e)&&(this.expandedItems=new Set(e))}catch{this.expandedItems=new Set}}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||"프로젝트 관리"}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||"프로젝트"}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||"프로젝트를 추가해 주세요"}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||"프로젝트 추가"}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}get headerType(){return"back"===this.getAttribute("header-type")?"back":"default"}set headerType(e){this.setAttribute("header-type",e)}get backLabel(){return this.getAttribute("back-label")||"뒤로가기"}set backLabel(e){this.setAttribute("back-label",e)}get backHref(){return this.getAttribute("back-href")||""}set backHref(e){e?this.setAttribute("back-href",e):this.removeAttribute("back-href")}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,this.userFlyoutItemId=null,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.classList.remove("designbase-wc-sidebar--user-menu-open"),this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncExclusiveAccordion(e){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(t=>{const s=t.getAttribute("data-item-id");s&&(e&&s===e?t.setAttribute("expanded",""):t.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}cancelUserFlyoutClose(){this.userFlyoutCloseTimer&&(clearTimeout(this.userFlyoutCloseTimer),this.userFlyoutCloseTimer=null)}setUserFlyout(e){this.cancelUserFlyoutClose(),this.userFlyoutItemId=e,this.querySelectorAll(".designbase-wc-sidebar__user-menu-item").forEach(t=>{const s=Boolean(e&&t.dataset.itemId===e);t.classList.toggle("designbase-wc-sidebar__user-menu-item--flyout-active",s),t.querySelector(".designbase-wc-sidebar__user-menu-trigger")?.setAttribute("aria-expanded",String(s));const i=t.querySelector(".designbase-wc-sidebar__user-flyout");i&&(i.hidden=!s)})}scheduleUserFlyoutClose(){this.cancelUserFlyoutClose(),this.userFlyoutCloseTimer=setTimeout(()=>{this.userFlyoutCloseTimer=null,this.setUserFlyout(null)},120)}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",a=this.getAttribute("position")||"left";this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--${s.includes(e)?e:"m"}`,`designbase-wc-sidebar--${i.includes(t)?t:"default"}`,`designbase-wc-sidebar--${r.includes(a)?a:"left"}`,this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow",this.userMenuOpen&&"designbase-wc-sidebar--user-menu-open","back"===this.headerType&&"designbase-wc-sidebar--header-back"].filter(Boolean).join(" ")}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchBackClick(){const e=new CustomEvent("db-back-click",{bubbles:!0,composed:!0,cancelable:!0,detail:{label:this.backLabel,href:this.backHref}});this.dispatchEvent(e),!e.defaultPrevented&&this.backHref&&window.location.assign(this.backHref)}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(t="s"){const s=document.createElement("span");return s.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${t}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),s.setAttribute("aria-hidden","true"),s.append(e("plus","m"===t?16:14)),s}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("badge-style","text"),t.textContent=e.badge,t}createProjectSelector(t){if(!this.hasAttribute("projects"))return null;const s=this.parseProjects(),i=0===s.length,r=this.getSelectedProject(),a=document.createElement("div");a.className=["designbase-wc-sidebar__project-selector",t&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",i&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const n=this.getAttribute("project-section-label");if(!t&&n&&n.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=n.trim(),a.append(e)}const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__project-trigger",c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.projectMenuOpen)),i||!r){if(c.setAttribute("aria-label",this.projectEmptyTriggerLabel),c.append(this.createProjectEmptyMark(t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,c.append(e)}}else if(c.setAttribute("aria-label",r.label),c.append(this.createProjectAvatar(r,t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=r.label,c.append(e)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__project-chevron",o.setAttribute("aria-hidden","true"),o.append(e("chevron-down",14)),c.append(o),c.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),a.append(c),this.projectMenuOpen){const t=document.createElement("div");if(t.className="designbase-wc-sidebar__project-dropdown",t.setAttribute("role","menu"),t.setAttribute("aria-label",this.projectSectionLabel),i){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-empty",e.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,e.append(s),t.append(e)}else{const e=document.createElement("ul");e.className="designbase-wc-sidebar__project-list",s.forEach(t=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",r&&t.id===r.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(t,"s"));const a=document.createElement("span");a.className="designbase-wc-sidebar__project-option-label",a.textContent=t.label,i.append(a);const n=this.createProjectBadge(t);n&&i.append(n),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",t.id),this.dispatchProjectChange(t),this.render()}),s.append(i),e.append(s)}),t.append(e)}const n=document.createElement("button");n.type="button",n.className="designbase-wc-sidebar__project-manage",n.setAttribute("role","menuitem"),n.append(e("plus",14));const c=document.createElement("span");c.textContent=this.projectManageLabel,n.append(c),n.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref;e&&window.location.assign(e),this.dispatchProjectManage(),this.render()}),t.append(n),a.append(t)}return a}createFlyout(e,t){const s=this.getAttribute("position")||"left",i=document.createElement("div");i.className=["designbase-wc-sidebar__flyout","right"===s&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),i.setAttribute("role","menu"),i.setAttribute("aria-label",`${e.label} 하위 메뉴`),i.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),i.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const r=document.createElement("div");r.className="designbase-wc-sidebar__flyout-title",r.textContent=e.label,i.append(r);const a=document.createElement("ul");return a.className="designbase-wc-sidebar__flyout-list",(e.children||[]).forEach(e=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",t),e.href&&i.setAttribute("href",e.href),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),s.append(i),a.append(s)}),i.append(a),i}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),r=this.expandedItems.has(e.id),a=this.hasAttribute("collapsed"),n=a&&i,c=document.createElement("li");c.className=["designbase-wc-sidebar__item",n&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),n&&(c.addEventListener("mouseenter",()=>this.showFlyout(e.id)),c.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const o=document.createElement("db-menu-item");if(o.setAttribute("data-item-id",e.id),o.setAttribute("label",e.label),o.setAttribute("type","block"),o.setAttribute("menu-style","accordion"),o.setAttribute("size",t),o.setAttribute("depth",String(s)),e.href&&o.setAttribute("href",e.href),e.icon&&o.setAttribute("icon",e.icon),e.active&&o.setAttribute("active",""),e.disabled&&o.setAttribute("disabled",""),void 0!==e.badge&&o.setAttribute("badge",String(e.badge)),e.badgeColor&&o.setAttribute("badge-color",e.badgeColor),i&&!n&&(o.setAttribute("expandable",""),o.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor})),r&&!a&&o.setAttribute("expanded","")),o.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!a){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),void(s?(this.expandedItems.clear(),this.expandedItems.add(e.id),this.syncExclusiveAccordion(e.id)):(this.expandedItems.delete(e.id),this.syncExclusiveAccordion(null)))}if(n)return this.closeOverlayMenus(),void this.showFlyout(e.id);this.closeOverlayMenus(),this.dispatchItemClick(e)}}),o.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),c.append(o),a&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),c.append(s)}if(a&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),c.append(t)}return n&&this.flyoutItemId===e.id&&c.append(this.createFlyout(e,t)),c}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const r=document.createElement("div");if(r.className=["designbase-wc-sidebar__section",e.gap&&`designbase-wc-sidebar__section--gap-${e.gap}`].filter(Boolean).join(" "),!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,r.append(t)}const a=document.createElement("ul");a.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>a.append(this.createSidebarMenuItem(e,t))),r.append(a),i.append(r)}),i}renderNav(){const e=this.querySelector(".designbase-wc-sidebar__nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseSections(),t,s))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(s,i=!1){if(!s.length)return null;const r=this.getAttribute("position")||"left",a=document.createElement("div");a.className=["designbase-wc-sidebar__user-dropdown",i&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),a.setAttribute("role","menu"),a.setAttribute("aria-label","사용자 메뉴"),a.hidden=!this.userMenuOpen,a.addEventListener("keydown",e=>{"Escape"===e.key&&(e.stopPropagation(),this.userFlyoutItemId?this.setUserFlyout(null):(this.userMenuOpen=!1,this.render()))});const n=document.createElement("ul");return n.className="designbase-wc-sidebar__user-menu",s.forEach(s=>{const i=Boolean(s.children?.length),a=document.createElement("li");a.dataset.itemId=s.id,a.className=["designbase-wc-sidebar__user-menu-item",s.dividerBefore&&"designbase-wc-sidebar__user-menu-item--divider",s.disabled&&"designbase-wc-sidebar__user-menu-item--disabled",i&&"designbase-wc-sidebar__user-menu-item--has-children"].filter(Boolean).join(" ");const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__user-menu-trigger",c.setAttribute("role","menuitem"),c.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),c.append(t)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__user-menu-label",o.textContent=s.label,c.append(o),s.value){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-value",e.textContent=s.value,c.append(e)}if(i){const i=document.createElement("span");i.className="designbase-wc-sidebar__user-menu-chevron",i.setAttribute("aria-hidden","true"),i.append(e("right"===r?"chevron-left":"chevron-right",16)),c.append(i),c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.userFlyoutItemId===s.id));const openFlyout=()=>this.setUserFlyout(s.id);a.addEventListener("mouseenter",openFlyout),a.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose()),a.addEventListener("focusin",openFlyout),a.addEventListener("focusout",e=>{const t=e.relatedTarget;t&&a.contains(t)||this.scheduleUserFlyoutClose()}),c.addEventListener("click",openFlyout);const n=document.createElement("div");n.className=["designbase-wc-sidebar__user-flyout","right"===r&&"designbase-wc-sidebar__user-flyout--align-left"].filter(Boolean).join(" "),n.setAttribute("role","menu"),n.setAttribute("aria-label",`${s.label} 하위 메뉴`),n.hidden=this.userFlyoutItemId!==s.id,n.addEventListener("mouseenter",()=>this.cancelUserFlyoutClose()),n.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose());const o=document.createElement("ul");o.className="designbase-wc-sidebar__user-flyout-list",(s.children||[]).forEach(s=>{const i=document.createElement("li");i.className="designbase-wc-sidebar__user-flyout-item";const r=document.createElement("button");if(r.type="button",r.className=["designbase-wc-sidebar__user-menu-trigger","designbase-wc-sidebar__user-flyout-trigger",s.selected&&"designbase-wc-sidebar__user-flyout-trigger--selected"].filter(Boolean).join(" "),r.setAttribute("role","menuitemradio"),r.setAttribute("aria-checked",String(Boolean(s.selected))),r.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),r.append(t)}const a=document.createElement("span");if(a.className="designbase-wc-sidebar__user-menu-label",a.textContent=s.label,r.append(a),s.selected){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-check",t.setAttribute("aria-hidden","true"),t.append(e("done",16)),r.append(t)}r.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),i.append(r),o.append(i)}),n.append(o),a.append(c,n)}else c.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),a.append(c);n.append(a)}),a.append(n),a}createPromoBanner(s){if("back"===this.headerType)return null;const i=this.parsePromoBanner();if(!i)return null;if(s){const s=document.createElement("button");s.type="button",s.className="designbase-wc-sidebar__promo-collapsed",s.setAttribute("aria-label",i.ctaLabel||i.title);const r=document.createElement("db-animation-background");r.className="designbase-wc-sidebar__promo-bg",r.setAttribute("type","aurora"),r.setAttribute("theme","light"),r.setAttribute("intensity","subtle"),r.setAttribute("blur","40"),r.setAttribute("speed","4000"),r.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),s.append(r),s.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",18)),s.addEventListener("click",()=>this.dispatchPromoCtaClick(i));const a=document.createElement("span");a.className="designbase-wc-sidebar__item-tooltip",a.textContent=i.title,a.setAttribute("role","tooltip");const n=document.createElement("div");return n.className="designbase-wc-sidebar__promo-collapsed-wrap",n.append(s,a),n}const r=document.createElement("div");r.className="designbase-wc-sidebar__promo";const a=document.createElement("db-animation-background");a.className="designbase-wc-sidebar__promo-bg",a.setAttribute("type","aurora"),a.setAttribute("theme","light"),a.setAttribute("intensity","subtle"),a.setAttribute("blur","60"),a.setAttribute("speed","5000"),a.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),r.append(a);const n=document.createElement("div");n.className="designbase-wc-sidebar__promo-content";const c=document.createElement("div");c.className="designbase-wc-sidebar__promo-title-row";const o=document.createElement("span");o.className="designbase-wc-sidebar__promo-icon",o.setAttribute("aria-hidden","true"),o.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",16));const d=document.createElement("div");if(d.className="designbase-wc-sidebar__promo-title",d.textContent=i.title,c.append(o,d),n.append(c),i.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=i.description,n.append(e)}if(i.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=i.ctaLabel,e.addEventListener("db-click",()=>{i.ctaHref&&window.location.assign(i.ctaHref),this.dispatchPromoCtaClick(i)}),n.append(e)}return r.append(n),r}render(){this.syncHostClasses(),this.setAttribute("role","complementary"),this.setAttribute("aria-label","사이드바 네비게이션");const t=this.getAttribute("size")||"m",s="false"!==this.getAttribute("collapsible"),i="false"!==this.getAttribute("show-logo"),r=this.hasAttribute("collapsed"),a=this.parseUserProfile(),n=this.parseUserMenuItems(),c=this.parseBottomSections(),o="l"===t?"m":"s"===t?"xs":"s";this.replaceChildren();const d=document.createElement("div");if(d.className="designbase-wc-sidebar__container","back"===this.headerType||s||i&&!r){const t=document.createElement("div");if(t.className=["designbase-wc-sidebar__header",(r||!i)&&"designbase-wc-sidebar__header--collapsed-only","back"===this.headerType&&"designbase-wc-sidebar__header--back"].filter(Boolean).join(" "),"back"===this.headerType){const s=document.createElement("button");if(s.type="button",s.className=["designbase-wc-sidebar__back",r&&"designbase-wc-sidebar__back--collapsed"].filter(Boolean).join(" "),s.setAttribute("aria-label",this.backLabel),s.append(e("chevron-left",18)),!r){const e=document.createElement("span");e.textContent=this.backLabel,s.append(e)}s.addEventListener("click",()=>this.dispatchBackClick()),t.append(s)}else if(!r&&i){const e=document.createElement("div");e.className="designbase-wc-sidebar__logo";const s=document.createElement("db-logo");s.setAttribute("type","designbase"),s.setAttribute("size",o),e.append(s),e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),t.append(e)}if(s){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__toggle",e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("icon-only",""),e.setAttribute("start-icon",r?"arrow-bar-right":"arrow-bar-left"),e.setAttribute("aria-label",r?"사이드바 펼치기":"사이드바 접기"),e.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),t.append(e)}d.append(t)}const l=document.createElement("div");l.className="designbase-wc-sidebar__nav-wrapper";const u=this.createProjectSelector(r);u&&l.append(u);const b=document.createElement("nav");if(b.className="designbase-wc-sidebar__nav",b.setAttribute("aria-label","주 메뉴"),l.append(b),c.length>0){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label","하단 메뉴"),l.append(e)}d.append(l);const p=document.createElement("div");p.className="designbase-wc-sidebar__footer";const m=this.createPromoBanner(r);if(m&&p.append(m),a&&!r){const t=document.createElement("div");t.className="designbase-wc-sidebar__user";const s=this.createUserDropdown(n);s&&t.append(s);const i=document.createElement("div");i.className="designbase-wc-sidebar__user-info",i.setAttribute("role","button"),i.setAttribute("tabindex","0"),i.setAttribute("aria-expanded",String(this.userMenuOpen));const r=document.createElement("db-avatar");r.className="designbase-wc-sidebar__user-avatar",r.setAttribute("size","s"),r.setAttribute("initials",a.name),r.setAttribute("alt",a.name),a.avatar&&r.setAttribute("src",a.avatar);const c=document.createElement("div");c.className="designbase-wc-sidebar__user-details";const o=document.createElement("div");if(o.className="designbase-wc-sidebar__user-name",o.textContent=a.name,c.append(o),a.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=a.email,c.append(e)}if(i.append(r,c),n.length){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-more",t.setAttribute("aria-hidden","true"),t.append(e("more-vertical",16)),i.append(t),i.setAttribute("aria-haspopup","menu")}i.addEventListener("click",()=>{n.length&&(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render())}),i.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),i.click())}),t.append(i),p.append(t)}else if(a&&r){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",a.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),n.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",a.name),t.setAttribute("alt",a.name),a.avatar&&t.setAttribute("src",a.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=a.name,t.setAttribute("role","tooltip"),e.append(t)}const s=this.createUserDropdown(n,!0);s&&e.append(s),e.addEventListener("click",e=>{n.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render()))}),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}),p.append(e)}d.append(p),this.append(d),this.renderNav(),this.renderBottomNav()}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import './db-button.js';
|
|
2
|
+
import './db-input.js';
|
|
2
3
|
import './db-otp-input.js';
|
|
3
4
|
import './db-segment-control.js';
|
|
4
5
|
|
|
@@ -30,15 +31,25 @@ declare class DbTwoFactor extends HTMLElement {
|
|
|
30
31
|
private otpInput;
|
|
31
32
|
private hintEl;
|
|
32
33
|
private timerEl;
|
|
34
|
+
private codeHead;
|
|
33
35
|
private resendBtn;
|
|
34
36
|
private verifyBtn;
|
|
35
37
|
private backupBtn;
|
|
36
38
|
private errorEl;
|
|
37
39
|
private channelActions;
|
|
40
|
+
private resendStatus;
|
|
41
|
+
private backupBlock;
|
|
42
|
+
private backupInput;
|
|
43
|
+
private backupCancelBtn;
|
|
44
|
+
private backupMode;
|
|
45
|
+
private resendCount;
|
|
38
46
|
get method(): Method;
|
|
39
47
|
set method(v: Method);
|
|
40
48
|
get size(): Size;
|
|
49
|
+
set size(v: Size);
|
|
41
50
|
get countdown(): number;
|
|
51
|
+
set countdown(v: number);
|
|
52
|
+
get maxResends(): number;
|
|
42
53
|
connectedCallback(): void;
|
|
43
54
|
disconnectedCallback(): void;
|
|
44
55
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDbIcon as t}from"./db-icons.js";import"./db-button.js";import"./db-otp-input.js";import"./db-segment-control.js";const e=[{value:"app",label:"인증 앱"},{value:"sms",label:"SMS"},{value:"email",label:"이메일"}],i=["s","m","l"];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}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"]}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 function pick(t,e,i){return t.includes(e)?e:i}(i,this.getAttribute("size"),"m")}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}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||("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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent="app"===this.method?"":`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,"app"!==this.method?this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`):this.timerEl.removeAttribute("aria-label"),this.resendBtn.disabled="app"===this.method||this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const i="designbase-wc-two-factor";this.replaceChildren();const s=el("div",`${i}__header`),n=el("div",`${i}__icon`);n.append(t("lock",22));const r=el("div",`${i}__titles`),o=el("h3",`${i}__title`);o.dataset.role="title";const h=el("p",`${i}__description`);h.dataset.role="description",r.append(o,h),s.append(n,r),this.segment=document.createElement("db-segment-control"),this.segment.setAttribute("options",JSON.stringify(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",`${i}__hint`),this.hintEl.dataset.role="hint";const a=el("div",`${i}__code-head`),d=el("span",`${i}__code-label`);d.textContent="인증 코드",this.timerEl=el("span",`${i}__timer`),a.append(d,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",`${i}__channel`),this.resendBtn=el("button",`${i}__resend`),this.resendBtn.type="button",this.resendBtn.textContent="코드 재전송",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{method:this.method,destination:this.getAttribute("destination")||""},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),this.channelActions.append(this.resendBtn),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",`${i}__backup`),this.backupBtn.type="button",this.backupBtn.textContent="백업 코드로 인증",this.backupBtn.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-backup-request",{bubbles:!0,composed:!0}))}),this.errorEl=el("p",`${i}__error`),this.errorEl.hidden=!0,this.append(s,this.segment,this.hintEl,a,this.otpInput,this.channelActions,this.verifyBtn,this.backupBtn,this.errorEl)}sync(){const t="designbase-wc-two-factor",e=this.size,i=this.method,s=this.hasAttribute("disabled"),n=this.getAttribute("code-length")||"6",r=this.getAttribute("destination")||"";this.className=[t,`${t}--${e}`,`${t}--${i}`,s&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" ");const o=this.querySelector('[data-role="title"]'),h=this.querySelector('[data-role="description"]');o.textContent=this.getAttribute("title")||"2단계 인증",h.textContent=this.getAttribute("description")||"계속하려면 인증 코드를 입력해 주세요.",this.segment.setAttribute("value",i),this.segment.setAttribute("size",e),this.segment.toggleAttribute("disabled",s);const a=this.querySelector('[data-role="hint"]');a.textContent="app"===i?"인증 앱(Google Authenticator, 1Password 등)에 표시된 6자리 코드를 입력하세요.":"sms"===i?r?`${r} 으로 보낸 SMS 인증 코드를 입력하세요.`:"등록된 휴대폰으로 보낸 SMS 인증 코드를 입력하세요.":r?`${r} 으로 보낸 이메일 인증 코드를 입력하세요.`:"등록된 이메일로 보낸 인증 코드를 입력하세요.",this.otpInput.setAttribute("length",n),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",s),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.channelActions.hidden="app"===i,this.resendBtn.textContent=this.hasAttribute("sending")?"전송 중…":this.getAttribute("resend-label")||"코드 재전송",this.renderTimer(),this.hasAttribute("sending")&&(this.resendBtn.disabled=!0),this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기";const d=this.getAttribute("code")||"";this.verifyBtn.toggleAttribute("disabled",s||d.length<Number(n)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.backupBtn.hidden=!this.hasAttribute("show-backup");const l=this.getAttribute("error-message")||"";this.errorEl.textContent=l,this.errorEl.hidden=!this.hasAttribute("error")||!l}requestVerify(){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{createDbIcon as t}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-segment-control.js";const e=[{value:"app",label:"인증 앱"},{value:"sms",label:"SMS"},{value:"email",label:"이메일"}],i=["s","m","l"];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 function pick(t,e,i){return t.includes(e)?e:i}(i,this.getAttribute("size"),"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 t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent="app"===this.method?"":`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,"app"!==this.method?this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`):this.timerEl.removeAttribute("aria-label");const i=this.resendCount>=this.maxResends;this.resendBtn.disabled="app"===this.method||this.remaining>0||i||this.hasAttribute("disabled"),"app"===this.method?this.resendStatus.textContent="":i?this.resendStatus.textContent="재전송 한도에 도달했습니다. 새 인증을 시작해 주세요.":this.remaining>0?this.resendStatus.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")} 후 재전송 가능 · 남은 횟수 ${this.maxResends-this.resendCount}회`:this.resendStatus.textContent=`재전송 가능 · 남은 횟수 ${this.maxResends-this.resendCount}회`}build(){if(this.built)return;this.built=!0;const i="designbase-wc-two-factor";this.replaceChildren();const s=el("div",`${i}__header`),n=el("div",`${i}__icon`);n.append(t("lock",22));const r=el("div",`${i}__titles`),h=el("h3",`${i}__title`);h.dataset.role="title";const a=el("p",`${i}__description`);a.dataset.role="description",r.append(h,a),s.append(n,r),this.segment=document.createElement("db-segment-control"),this.segment.setAttribute("options",JSON.stringify(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",`${i}__hint`),this.hintEl.dataset.role="hint",this.codeHead=el("div",`${i}__code-head`);const o=el("span",`${i}__code-label`);o.textContent="인증 코드",this.timerEl=el("span",`${i}__timer`),this.codeHead.append(o,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",`${i}__channel`),this.resendBtn=el("button",`${i}__resend`),this.resendBtn.type="button",this.resendBtn.textContent="코드 재전송",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",`${i}__resend-status`),this.resendStatus.setAttribute("aria-live","polite"),this.channelActions.append(this.resendBtn,this.resendStatus),this.backupBlock=el("div",`${i}__backup-block`);const d=el("p",`${i}__hint`);d.textContent="계정 설정 시 저장한 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",`${i}__backup`),this.backupCancelBtn.type="button",this.backupCancelBtn.textContent="인증 코드로 돌아가기",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",`${i}__backup`),this.backupBtn.type="button",this.backupBtn.textContent="백업 코드로 인증",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",`${i}__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",e=this.size,i=this.method,s=this.hasAttribute("disabled"),n=this.getAttribute("code-length")||"6",r=this.getAttribute("destination")||"";this.className=[t,`${t}--${e}`,`${t}--${i}`,s&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" ");const h=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');h.textContent=this.getAttribute("title")||"2단계 인증",a.textContent=this.getAttribute("description")||"계속하려면 인증 코드를 입력해 주세요.",this.segment.setAttribute("value",i),this.segment.setAttribute("size",e),this.segment.toggleAttribute("disabled",s),this.segment.toggleAttribute("hidden",this.backupMode);const o=this.querySelector('[data-role="hint"]');o.textContent="app"===i?"인증 앱(Google Authenticator, 1Password 등)에 표시된 6자리 코드를 입력하세요.":"sms"===i?r?`${r} 으로 보낸 SMS 인증 코드를 입력하세요.`:"등록된 휴대폰으로 보낸 SMS 인증 코드를 입력하세요.":r?`${r} 으로 보낸 이메일 인증 코드를 입력하세요.`:"등록된 이메일로 보낸 인증 코드를 입력하세요.",this.otpInput.setAttribute("length",n),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",s),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"===i||this.backupMode,this.backupBlock.hidden=!this.backupMode,this.backupInput.setAttribute("size",e),this.backupInput.toggleAttribute("disabled",s),this.resendBtn.textContent=this.hasAttribute("sending")?"전송 중…":this.getAttribute("resend-label")||"코드 재전송",this.renderTimer(),this.hasAttribute("sending")&&(this.resendBtn.disabled=!0),this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.backupMode?"백업 코드로 인증":this.getAttribute("verify-label")||"인증하기";const d=this.getAttribute("code")||"",u=String(this.backupInput.value||"").replace(/-/g,"");this.verifyBtn.toggleAttribute("disabled",s||(this.backupMode?8!==u.length:d.length<Number(n))),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 +1 @@
|
|
|
1
|
-
import*as s from"prismjs";import"../node_modules
|
|
1
|
+
import*as s from"prismjs";import"../node_modules/prismjs/components/prism-clike.js";import"../node_modules/prismjs/components/prism-markup.js";import"../node_modules/prismjs/components/prism-css.js";import"../node_modules/prismjs/components/prism-scss.js";import"../node_modules/prismjs/components/prism-bash.js";import"../node_modules/prismjs/components/prism-json.js";import"../node_modules/prismjs/components/prism-javascript.js";import"../node_modules/prismjs/components/prism-typescript.js";import"../node_modules/prismjs/components/prism-jsx.js";import"../node_modules/prismjs/components/prism-tsx.js";const o={js:"javascript",ts:"typescript",sh:"bash",shell:"bash",html:"markup",xml:"markup",svg:"markup"},r={javascript:"JavaScript",typescript:"TypeScript",tsx:"TSX",jsx:"JSX",css:"CSS",scss:"SCSS",json:"JSON",bash:"Bash",markup:"HTML"},resolvePrismLanguage=s=>{const r=s.toLowerCase().trim();return o[r]??r},formatLanguageLabel=s=>{const o=resolvePrismLanguage(s);return r[o]??s.toUpperCase()},highlightWithPrism=(o,r)=>{const m=(()=>{const o=globalThis.Prism;return o?.languages?o:s.default??s})(),p=resolvePrismLanguage(r),t=m.languages[p];if(!t)return null;try{return m.highlight(o,t,p)}catch{return null}},ensureHighlightReady=()=>Promise.resolve(),highlightCodeSync=(s,o)=>highlightWithPrism(s,o);export{ensureHighlightReady,formatLanguageLabel,highlightCodeSync,resolvePrismLanguage};
|