@designbasekorea/ui-wc 0.9.3 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +2 -0
- package/dist/esm/components/date-picker-utils.js +1 -1
- package/dist/esm/components/db-accordion.d.ts +22 -10
- package/dist/esm/components/db-accordion.js +1 -1
- package/dist/esm/components/db-activity-heatmap.js +1 -1
- package/dist/esm/components/db-ai-file-tree.js +1 -1
- package/dist/esm/components/db-avatar.js +1 -1
- package/dist/esm/components/db-button.d.ts +33 -1
- package/dist/esm/components/db-button.js +1 -1
- package/dist/esm/components/db-calendar.d.ts +2 -1
- package/dist/esm/components/db-calendar.js +1 -1
- package/dist/esm/components/db-carousel.d.ts +2 -0
- package/dist/esm/components/db-carousel.js +1 -1
- package/dist/esm/components/db-chat-orb.d.ts +13 -0
- package/dist/esm/components/db-chat-orb.js +1 -1
- package/dist/esm/components/db-chat-room.js +1 -1
- package/dist/esm/components/db-chat-widget.js +1 -1
- package/dist/esm/components/db-checkbox.d.ts +18 -1
- package/dist/esm/components/db-checkbox.js +1 -1
- package/dist/esm/components/db-confetti.d.ts +11 -5
- package/dist/esm/components/db-confetti.js +1 -1
- package/dist/esm/components/db-confirm.d.ts +2 -0
- package/dist/esm/components/db-confirm.js +1 -1
- package/dist/esm/components/db-credit-card.d.ts +3 -4
- package/dist/esm/components/db-credit-card.js +1 -1
- package/dist/esm/components/db-date-picker.d.ts +2 -1
- package/dist/esm/components/db-date-picker.js +1 -1
- package/dist/esm/components/db-design-toolbar.js +1 -1
- package/dist/esm/components/db-device-mockup.js +1 -1
- package/dist/esm/components/db-email-verify.d.ts +36 -7
- package/dist/esm/components/db-email-verify.js +1 -1
- package/dist/esm/components/db-flight-status.d.ts +2 -2
- package/dist/esm/components/db-flight-status.js +1 -1
- package/dist/esm/components/db-floating-action-button.d.ts +1 -1
- package/dist/esm/components/db-floating-action-button.js +1 -1
- package/dist/esm/components/db-gantt.js +1 -1
- package/dist/esm/components/db-indicator.d.ts +1 -0
- package/dist/esm/components/db-indicator.js +1 -1
- package/dist/esm/components/db-input.d.ts +8 -1
- package/dist/esm/components/db-input.js +1 -1
- package/dist/esm/components/db-kanban.js +1 -1
- package/dist/esm/components/db-navbar.d.ts +3 -0
- package/dist/esm/components/db-navbar.js +1 -1
- package/dist/esm/components/db-node.d.ts +1 -3
- package/dist/esm/components/db-node.js +1 -1
- package/dist/esm/components/db-otp-input.js +1 -1
- package/dist/esm/components/db-page-header.d.ts +11 -0
- package/dist/esm/components/db-page-header.js +1 -1
- package/dist/esm/components/db-phone-verify.d.ts +33 -11
- package/dist/esm/components/db-phone-verify.js +1 -1
- package/dist/esm/components/db-radio.d.ts +22 -1
- package/dist/esm/components/db-radio.js +1 -1
- package/dist/esm/components/db-range-slider.d.ts +35 -7
- package/dist/esm/components/db-range-slider.js +1 -1
- package/dist/esm/components/db-receipt.js +1 -1
- package/dist/esm/components/db-select.d.ts +35 -6
- package/dist/esm/components/db-select.js +1 -1
- package/dist/esm/components/db-tabs.d.ts +36 -13
- package/dist/esm/components/db-tabs.js +1 -1
- package/dist/esm/components/db-textarea.d.ts +13 -1
- package/dist/esm/components/db-textarea.js +1 -1
- package/dist/esm/components/db-toggle.d.ts +33 -4
- package/dist/esm/components/db-toggle.js +1 -1
- package/dist/esm/components/db-tool-button.js +1 -1
- package/dist/esm/components/db-two-factor.d.ts +35 -12
- package/dist/esm/components/db-two-factor.js +1 -1
- package/dist/esm/components/db-voice-control.js +1 -1
- package/dist/esm/core/ai-element.d.ts +2 -1
- package/dist/esm/core/ai-element.js +1 -1
- package/dist/esm/core/control-label.js +1 -0
- package/dist/esm/core/i18n-copy.js +1 -1
- package/dist/esm/core/i18n-en.js +1 -1
- package/dist/esm/core/i18n.d.ts +4 -0
- package/dist/esm/core/i18n.js +1 -1
- package/dist/esm/core/range-values.js +1 -0
- package/dist/esm/core/text-field-state.js +1 -0
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/esm/ui-contracts/dist/components.d.d.ts +9 -2
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +420 -90
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +5455 -636
- package/dist/react/index.esm.js +1 -1
- package/package.json +7 -3
|
@@ -4,31 +4,44 @@ import './db-otp-input.js';
|
|
|
4
4
|
import './db-select.js';
|
|
5
5
|
import { PHONE_VERIFY_SIZES } from '../ui-contracts/dist/components.d.js';
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* ui-wc — db-phone-verify (수동 작성, 자동 동기화 대상 아님)
|
|
9
|
-
*
|
|
10
|
-
* 한국형 휴대폰 본인인증: 통신사 → 번호 → 인증번호 발송 → OTP + 타이머/재전송.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
7
|
type Size = (typeof PHONE_VERIFY_SIZES)[number];
|
|
8
|
+
type Step = 'phone' | 'code' | 'verified';
|
|
14
9
|
declare class DbPhoneVerify extends HTMLElement {
|
|
15
10
|
static get observedAttributes(): string[];
|
|
16
11
|
private built;
|
|
17
12
|
private timerId;
|
|
13
|
+
/** 인증번호 유효 시간(초) */
|
|
18
14
|
private remaining;
|
|
15
|
+
/** 재전송 버튼이 다시 열리기까지 남은 시간(초) */
|
|
16
|
+
private cooldownLeft;
|
|
17
|
+
private expired;
|
|
18
|
+
private closeBtn;
|
|
19
|
+
private headerEl;
|
|
20
|
+
private eyebrowEl;
|
|
21
|
+
private titleEl;
|
|
22
|
+
private descEl;
|
|
23
|
+
private formEl;
|
|
19
24
|
private carrierSelect;
|
|
20
25
|
private phoneInput;
|
|
21
26
|
private sendBtn;
|
|
27
|
+
private codeBlock;
|
|
28
|
+
private codeLabelEl;
|
|
22
29
|
private otpInput;
|
|
23
30
|
private timerEl;
|
|
24
|
-
private
|
|
31
|
+
private expiredEl;
|
|
25
32
|
private verifyBtn;
|
|
26
|
-
private
|
|
33
|
+
private resendHintEl;
|
|
34
|
+
private resendBtn;
|
|
35
|
+
private changeBtn;
|
|
36
|
+
private verifiedBlock;
|
|
37
|
+
private verifiedTitleEl;
|
|
38
|
+
private verifiedDescEl;
|
|
39
|
+
private doneBtn;
|
|
27
40
|
private errorEl;
|
|
28
41
|
get size(): Size;
|
|
29
42
|
set size(v: Size);
|
|
30
|
-
get step():
|
|
31
|
-
set step(v:
|
|
43
|
+
get step(): Step;
|
|
44
|
+
set step(v: Step);
|
|
32
45
|
get phone(): string;
|
|
33
46
|
set phone(v: string);
|
|
34
47
|
get carrier(): string;
|
|
@@ -37,6 +50,9 @@ declare class DbPhoneVerify extends HTMLElement {
|
|
|
37
50
|
set code(v: string);
|
|
38
51
|
get countdown(): number;
|
|
39
52
|
set countdown(v: number);
|
|
53
|
+
/** 재전송을 다시 누를 수 있기까지 기다리는 시간(초). 기본 30초. 0이면 바로 누를 수 있다. */
|
|
54
|
+
get resendCooldown(): number;
|
|
55
|
+
set resendCooldown(v: number);
|
|
40
56
|
connectedCallback(): void;
|
|
41
57
|
disconnectedCallback(): void;
|
|
42
58
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -46,13 +62,19 @@ declare class DbPhoneVerify extends HTMLElement {
|
|
|
46
62
|
restartCountdown(): void;
|
|
47
63
|
/** 인증 완료 상태로 전환합니다. */
|
|
48
64
|
markVerified(): void;
|
|
65
|
+
/** 번호 입력 단계로 돌아갑니다 (입력한 코드는 지웁니다). */
|
|
66
|
+
editPhone(): void;
|
|
49
67
|
private clearTimer;
|
|
50
|
-
private
|
|
68
|
+
private startTimers;
|
|
51
69
|
private renderTimer;
|
|
70
|
+
private emit;
|
|
52
71
|
private build;
|
|
53
72
|
private sync;
|
|
54
73
|
private isPhoneValid;
|
|
74
|
+
private requestSend;
|
|
55
75
|
private requestVerify;
|
|
76
|
+
/** 번역 문장 안의 {0} 자리에 값을 굵게 넣는다 — 언어마다 어순이 달라 조각내 번역하지 않는다. */
|
|
77
|
+
private setTextWithValue;
|
|
56
78
|
}
|
|
57
79
|
declare global {
|
|
58
80
|
interface HTMLElementTagNameMap {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbFormat as t,dbText as e,t as i}from"../core/i18n.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-select.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{PHONE_VERIFY_SIZES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const DEFAULT_CARRIERS=()=>[{value:"skt",label:"SKT"},{value:"kt",label:"KT"},{value:"lgu",label:"LG U+"},{value:"mvno",label:e("알뜰폰")}];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 s(this.getAttribute("size"),r,"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 e=Math.max(0,Math.floor(this.remaining/60)),i=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(e).padStart(2,"0")}:${String(i).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",t("남은 시간 {0}분 {1}초",[e,i])),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 s=el("div",`${t}__header`),r=el("h3",`${t}__title`);r.dataset.role="title";const n=el("p",`${t}__description`);n.dataset.role="description",s.append(r,n);const o=el("div",`${t}__field`);this.carrierSelect=document.createElement("db-select"),this.carrierSelect.setAttribute("label","통신사"),this.carrierSelect.setAttribute("full-width",""),this.carrierSelect.setAttribute("placeholder",e("통신사 선택")),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}))}),o.append(this.carrierSelect);const h=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())}),h.append(this.phoneInput,this.sendBtn),this.codeBlock=el("div",`${t}__code`);const a=el("div",`${t}__code-head`),d=el("span",`${t}__code-label`);d.textContent=e("인증번호"),this.timerEl=el("span",`${t}__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,carrier:this.carrier,phone:this.phone},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const l=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()}),l.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(a,this.otpInput,l),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0;const c=el("div",`${t}__verified`);c.dataset.role="verified";const u=el("span",`${t}__verified-badge`);u.textContent=i("verify.done");const p=document.createElement("p");p.className=`${t}__verified-text`,p.textContent=i("verify.phoneDone"),c.append(u,p),this.append(s,o,h,this.codeBlock,this.errorEl,c)}sync(){const t="designbase-wc-phone-verify",e=this.size,i=this.step,s=this.hasAttribute("disabled"),r=function parseCarriers(t){if(!t)return DEFAULT_CARRIERS();try{const e=JSON.parse(t);return Array.isArray(e)&&e.length?e:DEFAULT_CARRIERS()}catch{return DEFAULT_CARRIERS()}}(this.getAttribute("carrier-options")),n=this.getAttribute("code-length")||"6";this.className=[t,`${t}--${e}`,`${t}--step-${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")||"휴대폰 인증",h.textContent=this.getAttribute("description")||"본인 명의의 휴대폰 번호를 입력하고 인증번호를 받아 주세요.",this.carrierSelect.setAttribute("options",JSON.stringify(r)),this.carrierSelect.setAttribute("value",this.carrier),this.carrierSelect.setAttribute("size",e),this.carrierSelect.toggleAttribute("disabled",s||"verified"===i);const a=this.getAttribute("phone")||"";this.phoneInput.value=a,this.phoneInput.setAttribute("size",e),this.phoneInput.toggleAttribute("disabled",s||"phone"!==i),this.phoneInput.toggleAttribute("error",this.hasAttribute("error")&&"phone"===i),this.sendBtn.setAttribute("size",e),this.sendBtn.textContent=this.getAttribute("send-label")||"인증번호 받기",this.sendBtn.toggleAttribute("disabled",s||"phone"!==i||!this.isPhoneValid()),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",n),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",s||"code"!==i),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&"code"===i),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",s||(this.getAttribute("code")||"").length<Number(n)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.codeBlock.hidden="phone"===i;this.querySelector('[data-role="verified"]').hidden="verified"!==i;const d=this.getAttribute("error-message")||"";this.errorEl.textContent=d,this.errorEl.hidden=!this.hasAttribute("error")||!d}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{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import"./db-select.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{PHONE_VERIFY_SIZES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const DEFAULT_CARRIERS=()=>[{value:"skt",label:"SKT"},{value:"kt",label:"KT"},{value:"lgu",label:"LG U+"},{value:"mvno",label:e("알뜰폰")}];function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}function textButton(t,e){const i=el("button",t);return i.type="button",i.addEventListener("click",()=>{i.disabled||e()}),i}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,this.cooldownLeft=0,this.expired=!1}static get observedAttributes(){return["carrier","phone","code","step","size","disabled","error","error-message","carrier-options","countdown","resend-cooldown","eyebrow","title","description","send-label","resend-label","verify-label","done-label","code-length","closable","manual","sending","verifying","auto-submit"]}get size(){return s(this.getAttribute("size"),r,"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))}get resendCooldown(){const t=Number(this.getAttribute("resend-cooldown")??30);return Number.isFinite(t)&&t>=0?t:30}set resendCooldown(t){this.setAttribute("resend-cooldown",String(t))}connectedCallback(){this.build(),this.sync(),"code"===this.step&&this.startTimers()}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&("step"===t&&e!==i&&("code"===this.step?this.startTimers():this.clearTimer()),this.sync())}startCodeStep(){"code"===this.step?this.startTimers():this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.step&&this.startTimers()}markVerified(){this.step="verified"}editPhone(){this.removeAttribute("code"),this.step="phone",requestAnimationFrame(()=>this.phoneInput?.focus?.())}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0,this.cooldownLeft=0,this.expired=!1}startTimers(){this.clearTimer(),this.remaining=this.countdown,this.cooldownLeft=Math.min(this.resendCooldown,this.countdown),this.renderTimer(),this.timerId=setInterval(()=>{this.cooldownLeft>0&&(this.cooldownLeft-=1),this.remaining>0&&(this.remaining-=1,this.remaining<=0&&(this.expired=!0,this.cooldownLeft=0,this.emit("db-countdown-complete"))),this.renderTimer(),this.remaining<=0&&this.cooldownLeft<=0&&this.timerId&&(clearInterval(this.timerId),this.timerId=null)},1e3)}renderTimer(){if(!this.built)return;const i=Math.max(0,Math.floor(this.remaining/60)),s=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(i).padStart(2,"0")}:${String(s).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",t("남은 시간 {0}분 {1}초",[i,s])),this.timerEl.classList.toggle("designbase-wc-phone-verify__timer--expired",this.expired),this.expiredEl.hidden=!this.expired,this.otpInput.toggleAttribute("disabled",this.hasAttribute("disabled")||"code"!==this.step||this.expired);const r=this.cooldownLeft>0;this.resendBtn.textContent=r?t("재전송 ({0}초)",[this.cooldownLeft]):this.getAttribute("resend-label")||e("재전송"),this.resendBtn.disabled=r||this.hasAttribute("disabled");const n=Number(this.getAttribute("code-length")||6);this.verifyBtn.toggleAttribute("disabled",this.hasAttribute("disabled")||"code"!==this.step||this.expired||this.code.length!==n)}emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}build(){if(this.built)return;this.built=!0;const t="designbase-wc-phone-verify";this.replaceChildren();const s=el("div",`${t}__shell`);this.closeBtn=el("button",`${t}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label",e("닫기")),this.closeBtn.append(i("close",18)),this.closeBtn.addEventListener("click",()=>this.emit("db-close")),this.headerEl=el("div",`${t}__header`),this.eyebrowEl=el("span",`${t}__eyebrow`),this.titleEl=el("h3",`${t}__title`),this.descEl=el("p",`${t}__description`),this.headerEl.append(this.eyebrowEl,this.titleEl,this.descEl),this.formEl=el("div",`${t}__form`),this.carrierSelect=document.createElement("db-select"),this.carrierSelect.setAttribute("full-width",""),this.carrierSelect.addEventListener("db-change",t=>{t.stopPropagation();const e=t.detail?.value??this.carrierSelect.value;this.carrier=String(e||""),this.emit("db-carrier-change",{carrier:this.carrier})});const r=el("div",`${t}__phone-row`);this.phoneInput=document.createElement("db-input"),this.phoneInput.setAttribute("type","tel"),this.phoneInput.setAttribute("inputmode","numeric"),this.phoneInput.setAttribute("autocomplete","tel-national"),this.phoneInput.setAttribute("placeholder","010-0000-0000"),this.phoneInput.setAttribute("full-width",""),this.phoneInput.setAttribute("start-icon","mobile"),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.emit("db-phone-change",{phone:e.replace(/\D/g,""),formatted:e})}),this.phoneInput.addEventListener("keydown",t=>{"Enter"===t.key&&this.requestSend()}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestSend()}),r.append(this.phoneInput,this.sendBtn),this.formEl.append(this.carrierSelect,r),this.codeBlock=el("div",`${t}__code`);const n=el("div",`${t}__code-head`);this.codeLabelEl=el("span",`${t}__code-label`),this.timerEl=el("span",`${t}__timer`),this.timerEl.setAttribute("role","timer"),n.append(this.codeLabelEl,this.timerEl),this.otpInput=document.createElement("db-otp-input"),this.otpInput.setAttribute("full-width",""),this.otpInput.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.setAttribute("code",e),this.emit("db-code-change",{code:e})}),this.otpInput.addEventListener("db-complete",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.emit("db-code-complete",{code:e,carrier:this.carrier,phone:this.phone}),this.hasAttribute("auto-submit")&&this.requestVerify()}),this.expiredEl=el("p",`${t}__expired`),this.expiredEl.setAttribute("role","alert"),this.expiredEl.hidden=!0,this.verifyBtn=document.createElement("db-button"),this.verifyBtn.setAttribute("variant","primary"),this.verifyBtn.setAttribute("full-width",""),this.verifyBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestVerify()}),this.resendBtn=textButton(`${t}__link`,()=>{this.emit("db-resend",{carrier:this.carrier,phone:this.phone}),this.hasAttribute("manual")||(this.removeAttribute("code"),this.startTimers())}),this.changeBtn=textButton(`${t}__link ${t}__link--muted`,()=>{this.emit("db-change-phone",{carrier:this.carrier,phone:this.phone}),this.hasAttribute("manual")||this.editPhone()});const h=el("div",`${t}__footer`),o=el("span",`${t}__footer-resend`);this.resendHintEl=el("span",`${t}__footer-hint`),o.append(this.resendHintEl,this.resendBtn),h.append(o,this.changeBtn),this.codeBlock.append(n,this.otpInput,this.expiredEl,this.verifyBtn,h),this.verifiedBlock=el("div",`${t}__result ${t}__result--success`);const d=el("div",`${t}__result-icon`);d.append(i("circle-checked",36)),this.verifiedTitleEl=el("h3",`${t}__result-title`),this.verifiedDescEl=el("p",`${t}__result-desc`),this.doneBtn=document.createElement("db-button"),this.doneBtn.setAttribute("variant","primary"),this.doneBtn.setAttribute("full-width",""),this.doneBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.emit("db-done",{carrier:this.carrier,phone:this.phone})}),this.verifiedBlock.append(d,this.verifiedTitleEl,this.verifiedDescEl,this.doneBtn),this.errorEl=el("p",`${t}__error`),this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,s.append(this.closeBtn,this.headerEl,this.formEl,this.errorEl,this.codeBlock,this.verifiedBlock),this.append(s)}sync(){const t="designbase-wc-phone-verify",i=this.size,s=this.step,r=this.hasAttribute("disabled"),n=function parseCarriers(t){if(!t)return DEFAULT_CARRIERS();try{const e=JSON.parse(t);return Array.isArray(e)&&e.length?e:DEFAULT_CARRIERS()}catch{return DEFAULT_CARRIERS()}}(this.getAttribute("carrier-options")),h=this.getAttribute("code-length")||"6",o=formatPhone(this.getAttribute("phone")||"")||"010-0000-0000";this.className=[t,`${t}--${i}`,`${t}--step-${s}`,this.hasAttribute("closable")&&`${t}--closable`,r&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" "),this.closeBtn.hidden=!this.hasAttribute("closable"),this.headerEl.hidden="verified"===s;const d=this.getAttribute("eyebrow")||"";this.eyebrowEl.textContent=d,this.eyebrowEl.hidden=!d,"code"===s?(this.titleEl.textContent=e("인증번호를 입력해 주세요"),this.setTextWithValue(this.descEl,"{0} 번호로 {1}자리 인증번호를 보냈어요.",o,[h])):(this.titleEl.textContent=this.getAttribute("title")||e("휴대폰 인증"),this.descEl.textContent=this.getAttribute("description")||e("본인 명의의 휴대폰 번호를 입력해 주세요. 입력한 번호로 인증번호를 보내 드려요.")),this.formEl.hidden="phone"!==s,this.carrierSelect.setAttribute("label",e("통신사")),this.carrierSelect.setAttribute("placeholder",e("통신사 선택")),this.carrierSelect.setAttribute("options",JSON.stringify(n)),this.carrierSelect.setAttribute("value",this.carrier),this.carrierSelect.setAttribute("size",i),this.carrierSelect.toggleAttribute("disabled",r),this.phoneInput.setAttribute("label",e("휴대폰 번호")),this.phoneInput.value=this.getAttribute("phone")||"",this.phoneInput.setAttribute("size",i),this.phoneInput.toggleAttribute("disabled",r),this.phoneInput.toggleAttribute("error",this.hasAttribute("error")&&"phone"===s),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||e("인증번호 받기"),this.sendBtn.toggleAttribute("disabled",r||!this.isPhoneValid()),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.codeBlock.hidden="code"!==s,this.codeLabelEl.textContent=e("인증번호"),this.otpInput.setAttribute("length",h),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.code),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&"code"===s),this.expiredEl.textContent=e("인증 시간이 만료되었어요. 인증번호를 다시 받아 주세요."),this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.getAttribute("verify-label")||e("인증하기"),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying")),this.resendHintEl.textContent=e("문자를 받지 못하셨나요?"),this.changeBtn.textContent=e("번호 변경"),this.changeBtn.disabled=r,this.verifiedBlock.hidden="verified"!==s,this.verifiedTitleEl.textContent=e("휴대폰 인증 완료"),this.setTextWithValue(this.verifiedDescEl,"{0} 번호가 인증되었어요.",o),this.doneBtn.setAttribute("size",i),this.doneBtn.textContent=this.getAttribute("done-label")||e("확인");const l=this.getAttribute("error-message")||"";this.errorEl.textContent=l,this.errorEl.hidden=!this.hasAttribute("error")||!l||"verified"===s;const a="code"===s?this.otpInput:this.formEl;this.errorEl.previousElementSibling!==a&&a.after(this.errorEl),this.renderTimer()}isPhoneValid(){return/^01[016789]\d{7,8}$/.test(this.phone)&&Boolean(this.carrier)}requestSend(){"phone"===this.step&&(this.hasAttribute("disabled")||this.hasAttribute("sending")||!this.isPhoneValid()||(this.emit("db-send-code",{carrier:this.carrier,phone:this.phone}),this.hasAttribute("manual")||this.startCodeStep()))}requestVerify(){const t=(this.code||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||this.expired||t.length!==e||this.hasAttribute("disabled")||this.emit("db-verify",{carrier:this.carrier,phone:this.phone,code:t})}setTextWithValue(t,i,s,r=[]){const n=e(i).replace(/\{(\d+)\}/g,(t,e)=>"0"===e?t:String(r[Number(e)-1]??"")),[h,o=""]=n.split("{0}"),d=document.createElement("strong");d.textContent=s,t.replaceChildren(document.createTextNode(h),d,document.createTextNode(o))}}customElements.get("db-phone-verify")||customElements.define("db-phone-verify",DbPhoneVerify);export{DbPhoneVerify};
|
|
@@ -5,10 +5,27 @@ declare class DbRadio extends HTMLElement {
|
|
|
5
5
|
private visual?;
|
|
6
6
|
private dot?;
|
|
7
7
|
private labelEl?;
|
|
8
|
+
private readonly labelContent;
|
|
8
9
|
private built;
|
|
9
10
|
private userInteracted;
|
|
11
|
+
private resetChecked?;
|
|
12
|
+
private readonly cleanups;
|
|
13
|
+
focus(options?: FocusOptions): void;
|
|
14
|
+
get label(): string;
|
|
15
|
+
set label(value: string);
|
|
16
|
+
get name(): string;
|
|
17
|
+
set name(value: string);
|
|
18
|
+
get value(): string;
|
|
19
|
+
set value(value: string);
|
|
20
|
+
get defaultChecked(): boolean;
|
|
21
|
+
set defaultChecked(value: boolean);
|
|
22
|
+
get defaultSelected(): boolean;
|
|
23
|
+
set defaultSelected(value: boolean);
|
|
24
|
+
private upgradeProperties;
|
|
10
25
|
get checked(): boolean;
|
|
11
26
|
set checked(value: boolean);
|
|
27
|
+
get selected(): boolean;
|
|
28
|
+
set selected(value: boolean);
|
|
12
29
|
get disabled(): boolean;
|
|
13
30
|
set disabled(value: boolean);
|
|
14
31
|
get readOnly(): boolean;
|
|
@@ -18,10 +35,14 @@ declare class DbRadio extends HTMLElement {
|
|
|
18
35
|
get size(): string;
|
|
19
36
|
set size(value: string);
|
|
20
37
|
connectedCallback(): void;
|
|
38
|
+
disconnectedCallback(): void;
|
|
21
39
|
attributeChangedCallback(name: string): void;
|
|
22
|
-
|
|
40
|
+
get hasLabel(): boolean;
|
|
41
|
+
set hasLabel(value: boolean);
|
|
23
42
|
private build;
|
|
24
43
|
private handleChange;
|
|
44
|
+
private groupPeers;
|
|
45
|
+
private syncGroup;
|
|
25
46
|
private syncState;
|
|
26
47
|
private syncVisual;
|
|
27
48
|
private syncClasses;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ControlLabel as t}from"../core/control-label.js";import{CleanupBag as e}from"../core/dom.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{RADIO_SIZES as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbRadio extends HTMLElement{constructor(){super(...arguments),this.labelContent=new t(this),this.built=!1,this.userInteracted=!1,this.cleanups=new e,this.handleChange=()=>{if(!this.input||this.disabled||this.readOnly)return;this.userInteracted=!0;const t=this.input.checked;this.removeAttribute("selected"),this.toggleAttribute("checked",t),this.syncGroup(),this.syncVisual(),this.syncClasses(),this.dispatchEvent(new CustomEvent("db-change",{detail:{checked:t,selected:t,value:this.input.value},bubbles:!0,composed:!0}))}}static get observedAttributes(){return["checked","selected","default-checked","default-selected","size","disabled","readonly","required","name","value","label","has-label","aria-label","aria-labelledby","aria-describedby"]}focus(t){this.input?.focus(t)}get label(){return this.labelContent.value}set label(t){this.setAttribute("label",t)}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get value(){return this.getAttribute("value")??"on"}set value(t){this.setAttribute("value",t)}get defaultChecked(){return this.hasAttribute("default-checked")||this.hasAttribute("default-selected")}set defaultChecked(t){this.removeAttribute("default-selected"),this.toggleAttribute("default-checked",t)}get defaultSelected(){return this.defaultChecked}set defaultSelected(t){this.defaultChecked=t}upgradeProperties(){for(const t of["checked","selected","defaultChecked","defaultSelected","name","value","label","disabled","readOnly","required","hasLabel","size"]){if(!Object.prototype.hasOwnProperty.call(this,t))continue;const e=this,s=e[t];delete e[t],e[t]=s}}get checked(){return this.input?.checked??(this.hasAttribute("checked")||this.hasAttribute("selected"))}set checked(t){this.userInteracted=!0,this.removeAttribute("selected"),this.toggleAttribute("checked",t),this.input&&(this.input.checked=t,this.syncVisual(),this.syncClasses(),this.syncGroup())}get selected(){return this.checked}set selected(t){this.checked=t}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t),this.input&&(this.input.disabled=t),this.syncClasses()}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t),this.input&&(this.input.readOnly=t),this.syncClasses()}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",t),this.input&&(this.input.required=t)}get size(){return s(this.getAttribute("size"),i,"m")}set size(t){this.setAttribute("size",t)}connectedCallback(){this.upgradeProperties(),this.style.display="contents",this.built||this.build(),this.labelContent.connect(this.labelEl,()=>this.syncClasses()),this.syncState(),this.input?.form&&this.cleanups.listen(this.input.form,"reset",()=>{window.setTimeout(()=>{this.input&&this.isConnected&&(this.toggleAttribute("checked",this.input.checked),this.removeAttribute("selected"),this.syncClasses())},0)})}disconnectedCallback(){this.cleanups.run(),this.labelContent.disconnect()}attributeChangedCallback(t){if(this.built){if("default-checked"!==t&&"default-selected"!==t||(this.resetChecked=this.hasAttribute("default-checked")||this.hasAttribute("default-selected")),"checked"===t||"selected"===t)return this.userInteracted=!0,this.input&&(this.input.checked=this.hasAttribute("checked")||this.hasAttribute("selected")),this.syncVisual(),this.syncClasses(),void this.syncGroup();this.syncState()}}get hasLabel(){return!this.hasAttribute("has-label")||"false"!==this.getAttribute("has-label")}set hasLabel(t){this.setAttribute("has-label",String(t))}build(){for(this.root=document.createElement("label"),this.root.className="designbase-wc-radio",this.input=document.createElement("input"),this.input.type="radio",this.input.className="designbase-wc-radio__input",this.visual=document.createElement("span"),this.visual.className="designbase-wc-radio__visual",this.visual.setAttribute("aria-hidden","true"),this.dot=document.createElement("span"),this.dot.className="designbase-wc-radio__dot",this.visual.appendChild(this.dot),this.labelEl=document.createElement("span"),this.labelEl.className="designbase-wc-radio__label";this.firstChild;)this.labelEl.appendChild(this.firstChild);this.root.append(this.input,this.visual,this.labelEl),this.appendChild(this.root),this.input.addEventListener("click",t=>{this.readOnly&&t.preventDefault()}),this.input.addEventListener("keydown",t=>{const e=["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"];if(this.readOnly&&(" "===t.key||e.includes(t.key)))return void t.preventDefault();const s=this.groupPeers();if(!e.includes(t.key)||!s.some(t=>t.readOnly))return;const i=s.filter(t=>!t.disabled&&!t.readOnly);if(!i.length)return;t.preventDefault();const a="rtl"===getComputedStyle(this).direction,r="ArrowDown"===t.key||t.key===(a?"ArrowLeft":"ArrowRight"),h=i[(i.indexOf(this)+(r?1:-1)+i.length)%i.length];h.input?.focus(),h.input?.click()}),this.input.addEventListener("change",this.handleChange),this.built=!0}groupPeers(){if(!this.input?.name)return[this];const t=this.getRootNode();return Array.from(t.querySelectorAll("db-radio")).filter(t=>t.input?.name===this.input.name&&t.input?.form===this.input.form)}syncGroup(){if(this.input?.checked&&this.input.name){const t=this.getRootNode();for(const e of t.querySelectorAll("db-radio"))e!==this&&e.input&&e.input.name===this.input.name&&e.input.form===this.input.form&&(e.userInteracted=!0,e.removeAttribute("checked"),e.removeAttribute("selected"),e.syncClasses())}}syncState(){if(!this.root||!this.input||!this.visual)return;this.labelContent.sync();const t=this.hasAttribute("checked")||this.hasAttribute("selected")||!this.userInteracted&&(this.hasAttribute("default-checked")||this.hasAttribute("default-selected"));this.resetChecked??(this.resetChecked=t),this.input.defaultChecked=this.resetChecked,this.input.checked=t,this.input.disabled=this.disabled,this.input.readOnly=this.readOnly,this.input.setAttribute("aria-disabled",String(this.disabled||this.readOnly)),this.input.required=this.required,this.input.name=this.getAttribute("name")||"",this.input.value=this.getAttribute("value")??"on";for(const t of["aria-label","aria-labelledby","aria-describedby"]){const e=this.getAttribute(t);e?this.input.setAttribute(t,e):this.input.removeAttribute(t)}this.hasLabel?this.labelEl?.removeAttribute("hidden"):this.labelEl?.setAttribute("hidden",""),this.syncVisual(),this.syncClasses()}syncVisual(){}syncClasses(){if(!this.root||!this.input)return;const t=i.includes(this.size)?this.size:"m",e=this.hasLabel&&Boolean(this.label.trim());this.root.className=["designbase-wc-radio",`designbase-wc-radio--${t}`,this.input.checked&&"designbase-wc-radio--selected",this.disabled&&"designbase-wc-radio--disabled",this.readOnly&&"designbase-wc-radio--readonly",!e&&"designbase-wc-radio--no-label"].filter(Boolean).join(" ")}}customElements.get("db-radio")||customElements.define("db-radio",DbRadio);export{DbRadio};
|
|
@@ -8,6 +8,11 @@ declare class DbRangeSlider extends HTMLElement {
|
|
|
8
8
|
private trackEl;
|
|
9
9
|
private fillEl;
|
|
10
10
|
private thumbEls;
|
|
11
|
+
private initialized;
|
|
12
|
+
private reflecting;
|
|
13
|
+
private pointerId;
|
|
14
|
+
private pointerThumb;
|
|
15
|
+
private tooltipResize?;
|
|
11
16
|
private currentValue;
|
|
12
17
|
private currentRange;
|
|
13
18
|
private isDragging;
|
|
@@ -15,15 +20,35 @@ declare class DbRangeSlider extends HTMLElement {
|
|
|
15
20
|
private boundTrackClick;
|
|
16
21
|
private boundPointerMove;
|
|
17
22
|
private boundPointerUp;
|
|
23
|
+
private boundPointerCancel;
|
|
18
24
|
private eventsBound;
|
|
19
25
|
connectedCallback(): void;
|
|
20
26
|
disconnectedCallback(): void;
|
|
21
|
-
attributeChangedCallback(name: string): void;
|
|
27
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
22
28
|
private isStructuralAttribute;
|
|
23
29
|
get value(): number;
|
|
24
30
|
set value(v: number);
|
|
25
31
|
get range(): [number, number] | undefined;
|
|
26
32
|
set range(v: [number, number] | string | undefined);
|
|
33
|
+
get min(): number;
|
|
34
|
+
set min(value: number);
|
|
35
|
+
get max(): number;
|
|
36
|
+
set max(value: number);
|
|
37
|
+
get step(): number;
|
|
38
|
+
set step(value: number);
|
|
39
|
+
get size(): string;
|
|
40
|
+
set size(value: string);
|
|
41
|
+
get variant(): string;
|
|
42
|
+
set variant(value: string);
|
|
43
|
+
get disabled(): boolean;
|
|
44
|
+
set disabled(value: boolean);
|
|
45
|
+
get readOnly(): boolean;
|
|
46
|
+
set readOnly(value: boolean);
|
|
47
|
+
get vertical(): boolean;
|
|
48
|
+
set vertical(value: boolean);
|
|
49
|
+
focus(options?: FocusOptions): void;
|
|
50
|
+
private get bounds();
|
|
51
|
+
private normalizeValues;
|
|
27
52
|
private build;
|
|
28
53
|
private getValuePosition;
|
|
29
54
|
private shouldShowLabel;
|
|
@@ -37,32 +62,35 @@ declare class DbRangeSlider extends HTMLElement {
|
|
|
37
62
|
private isMarkActive;
|
|
38
63
|
private syncVisuals;
|
|
39
64
|
private syncThumbTooltips;
|
|
65
|
+
private fitFloatingText;
|
|
66
|
+
private syncMarkLabelBounds;
|
|
40
67
|
private syncA11y;
|
|
41
68
|
private setThumbPosition;
|
|
42
69
|
private valueToPercent;
|
|
43
70
|
private percentToValue;
|
|
44
|
-
private snapToStep;
|
|
45
71
|
private clamp;
|
|
72
|
+
/** snap-marks: the marks are the only selectable values. */
|
|
73
|
+
private snapStops;
|
|
74
|
+
private adjacentStop;
|
|
46
75
|
private getNumberAttr;
|
|
47
76
|
private normalizeRangeInput;
|
|
48
77
|
private parseRangeAttr;
|
|
49
78
|
private parseMarks;
|
|
79
|
+
private readMarks;
|
|
50
80
|
private parseMarkLabels;
|
|
51
81
|
private isInteractive;
|
|
52
82
|
private getTrackPercent;
|
|
53
83
|
private handleThumbPointerDown;
|
|
54
84
|
private handleTrackClick;
|
|
55
|
-
/**
|
|
56
|
-
* 포인터 이동을 프레임당 1회로 병합한다. preventDefault 를 쓰지 않으므로 안전하다. (PERF-RAF)
|
|
57
|
-
* 메서드가 아니라 필드로 선언해야 rafThrottle 로 감쌀 수 있다.
|
|
58
|
-
*/
|
|
59
85
|
private handlePointerMove;
|
|
60
86
|
private handlePointerUp;
|
|
87
|
+
private cancelDrag;
|
|
61
88
|
private setThumbActive;
|
|
89
|
+
private reflectCurrent;
|
|
62
90
|
private applyDragValue;
|
|
91
|
+
private applyValue;
|
|
63
92
|
private commitValueAtPosition;
|
|
64
93
|
private handleKeyDown;
|
|
65
|
-
private afterKeyboard;
|
|
66
94
|
private dispatchValueChange;
|
|
67
95
|
private dispatchRangeChange;
|
|
68
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{rafThrottle as t}from"../core/dom.js";const e="designbase-wc-range-slider";class DbRangeSlider extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.headerEl=null,this.labelEl=null,this.valuesEl=null,this.containerEl=null,this.trackEl=null,this.fillEl=null,this.thumbEls=[],this.currentValue=50,this.currentRange=[25,75],this.isDragging=!1,this.activeThumb=null,this.boundTrackClick=t=>this.handleTrackClick(t),this.boundPointerMove=t=>this.handlePointerMove(t),this.boundPointerUp=()=>this.handlePointerUp(),this.eventsBound=!1,this.handlePointerMove=t(t=>{if(!this.isDragging||!this.isInteractive())return;const e=this.getTrackPercent(t.clientX,t.clientY),i=this.percentToValue(e);this.applyDragValue(i)})}static get observedAttributes(){return["value","range","min","max","step","size","variant","show-value","show-label","label","value-position","value-fixed","show-thumb-tooltip","show-marks","marks","mark-labels","disabled","readonly","full-width","vertical"]}connectedCallback(){this.built||(this.build(),this.built=!0),this.readAttributeValues(),this.syncClasses(),this.syncDomOrder(),this.syncStructure(),this.syncVisuals(),this.syncA11y(),this.bindEvents()}disconnectedCallback(){this.unbindEvents()}attributeChangedCallback(t){this.built&&(this.readAttributeValues(),this.syncClasses(),this.isStructuralAttribute(t)&&(this.syncDomOrder(),this.syncStructure()),this.syncVisuals(),this.syncA11y())}isStructuralAttribute(t){return["range","show-value","show-label","label","value-position","show-marks","marks","mark-labels","vertical"].includes(t)}get value(){return this.currentValue}set value(t){this.currentValue=this.clamp(t),this.setAttribute("value",String(this.currentValue)),this.syncVisuals()}get range(){if(this.hasAttribute("range"))return[...this.currentRange]}set range(t){if(null==t)return this.removeAttribute("range"),void(this.built&&(this.syncStructure(),this.syncVisuals()));const e=this.normalizeRangeInput(t);if(!e)return;const i=[Math.min(e[0],e[1]),Math.max(e[0],e[1])];this.currentRange=[this.clamp(i[0]),this.clamp(i[1])];const s=`${this.currentRange[0]},${this.currentRange[1]}`;this.getAttribute("range")!==s&&this.setAttribute("range",s),this.built&&this.syncVisuals()}build(){this.classList.add(e),this.headerEl=document.createElement("div"),this.headerEl.className=`${e}__header`,this.labelEl=document.createElement("span"),this.labelEl.className=`${e}__label`,this.valuesEl=document.createElement("div"),this.valuesEl.className=`${e}__values`,this.containerEl=document.createElement("div"),this.containerEl.className=`${e}__container`,this.trackEl=document.createElement("div"),this.trackEl.className=`${e}__track`,this.fillEl=document.createElement("div"),this.fillEl.className=`${e}__fill`,this.trackEl.appendChild(this.fillEl),this.containerEl.appendChild(this.trackEl)}getValuePosition(){const t=this.getAttribute("value-position");return t||(this.shouldShowLabel()?"top":"right")}shouldShowLabel(){return this.hasAttribute("show-label")&&Boolean(this.getAttribute("label")?.trim())}formatValue(t){const e=this.getAttribute("value-fixed");if(null!==e&&""!==e){const i=Number(e);if(Number.isFinite(i))return t.toFixed(i)}return String(t)}syncDomOrder(){if(!this.headerEl||!this.valuesEl||!this.containerEl)return;const t=this.getValuePosition(),e=this.shouldShowLabel(),i=this.hasAttribute("show-value"),s=this.hasAttribute("range");return this.replaceChildren(),this.labelEl&&(this.labelEl.textContent=this.getAttribute("label")?.trim()||""),s||"top"===t?(this.headerEl.replaceChildren(),e&&this.labelEl&&this.headerEl.appendChild(this.labelEl),i&&this.headerEl.appendChild(this.valuesEl),this.headerEl.childElementCount>0&&this.append(this.headerEl),void this.append(this.containerEl)):"bottom"===t?(e&&this.labelEl&&(this.headerEl.replaceChildren(this.labelEl),this.append(this.headerEl)),this.append(this.containerEl),void(i&&this.append(this.valuesEl))):void(i?this.append(this.valuesEl,this.containerEl):this.append(this.containerEl))}bindEvents(){this.eventsBound||(this.trackEl?.addEventListener("click",this.boundTrackClick),this.eventsBound=!0)}unbindEvents(){this.eventsBound&&(this.trackEl?.removeEventListener("click",this.boundTrackClick),document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.eventsBound=!1)}readAttributeValues(){const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.getNumberAttr("step",1);if(this.hasAttribute("range")){const s=this.parseRangeAttr(this.getAttribute("range"));s?this.currentRange=[this.clamp(s[0],t,e,i),this.clamp(s[1],t,e,i)]:this.currentRange.every(Number.isFinite)||(this.currentRange=[25,75])}else this.currentValue=this.clamp(this.getNumberAttr("value",50),t,e,i)}syncClasses(){const t=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default",s=this.hasAttribute("range"),r=this.getValuePosition(),a=s?"top":r,n=this.hasAttribute("show-marks")&&this.parseMarks().length>0&&Object.keys(this.parseMarkLabels()).length>0,h=[e,`${e}--${t}`,`${e}--${i}`,`${e}--value-${a}`,this.shouldShowLabel()?`${e}--has-label`:"",this.hasAttribute("disabled")?`${e}--disabled`:"",this.hasAttribute("readonly")?`${e}--readonly`:"",this.hasAttribute("full-width")?`${e}--full-width`:"",this.hasAttribute("vertical")?`${e}--vertical`:"",this.hasAttribute("show-thumb-tooltip")?`${e}--show-tooltip`:"",s?`${e}--range`:"",n?`${e}--has-mark-labels`:""].filter(Boolean);if(this.className=h.join(" "),this.trackEl){const t=[`${e}__track`];this.hasAttribute("disabled")&&t.push(`${e}__track--disabled`),this.hasAttribute("readonly")&&t.push(`${e}__track--readonly`),this.trackEl.className=t.join(" ")}}syncStructure(){if(!this.valuesEl||!this.trackEl||!this.fillEl)return;const t=this.hasAttribute("show-value"),i=this.hasAttribute("range"),s=this.hasAttribute("show-marks");if(this.valuesEl.innerHTML="",this.valuesEl.hidden=!t,t)if(i){const t=document.createElement("span");t.className=`${e}__value ${e}__value--min`;const i=document.createElement("span");i.className=`${e}__value-separator`,i.textContent="~",i.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className=`${e}__value ${e}__value--max`,this.valuesEl.append(t,i,s)}else{const t=document.createElement("span");t.className=`${e}__value ${e}__value--single`,this.valuesEl.appendChild(t)}if(this.thumbEls.forEach(t=>t.remove()),this.thumbEls=[],this.trackEl.querySelectorAll(`.${e}__mark`).forEach(t=>t.remove()),s){const t=this.parseMarks();if(t.length>0){const i=this.parseMarkLabels();t.forEach(t=>{const s=document.createElement("div");if(s.className=`${e}__mark`,s.setAttribute("aria-hidden","true"),this.isMarkActive(t)&&s.classList.add(`${e}__mark--active`),this.hasAttribute("vertical")?s.style.bottom=`${this.valueToPercent(t)}%`:s.style.left=`${this.valueToPercent(t)}%`,void 0!==i[t]){const r=document.createElement("span");r.className=`${e}__mark-label`,r.textContent=i[t],s.appendChild(r)}this.trackEl.insertBefore(s,this.fillEl)})}}const r=i?2:1,a=this.hasAttribute("disabled")||this.hasAttribute("readonly");for(let t=0;t<r;t++){const s=document.createElement("div");s.className=`${e}__thumb`,s.setAttribute("role","slider"),s.setAttribute("draggable","false"),s.setAttribute("tabindex",a?"-1":"0");const r=i?0===t?"min":"max":"single";i&&(s.dataset.thumb=r),s.addEventListener("pointerdown",t=>this.handleThumbPointerDown(t,r)),s.addEventListener("keydown",t=>this.handleKeyDown(t,r));const n=document.createElement("span");n.className=`${e}__thumb-tooltip`,n.setAttribute("aria-hidden","true"),n.hidden=!0,s.appendChild(n),this.trackEl.appendChild(s),this.thumbEls.push(s)}}isMarkActive(t){if(this.hasAttribute("range")){const[e,i]=this.currentRange;return t>=e&&t<=i}return t<=this.currentValue}syncVisuals(){if(!this.fillEl)return;const t=this.hasAttribute("range"),i=this.getNumberAttr("min",0),s=this.getNumberAttr("max",100);if(t){const[t,r]=this.currentRange,a=this.valueToPercent(t),n=this.valueToPercent(r);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom=`${a}%`,this.fillEl.style.height=n-a+"%"):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left=`${a}%`,this.fillEl.style.width=n-a+"%"),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],a),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(r)),this.thumbEls[0].setAttribute("aria-valuenow",String(t))),this.thumbEls[1]&&(this.setThumbPosition(this.thumbEls[1],n),this.thumbEls[1].setAttribute("aria-valuemin",String(t)),this.thumbEls[1].setAttribute("aria-valuemax",String(s)),this.thumbEls[1].setAttribute("aria-valuenow",String(r)));const h=this.valuesEl?.querySelector(`.${e}__value--min`),l=this.valuesEl?.querySelector(`.${e}__value--max`);h&&(h.textContent=this.formatValue(t)),l&&(l.textContent=this.formatValue(r))}else{const t=this.valueToPercent(this.currentValue);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom="0",this.fillEl.style.height=`${t}%`):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left="0",this.fillEl.style.width=`${t}%`),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],t),this.thumbEls[0].setAttribute("aria-valuemin",String(i)),this.thumbEls[0].setAttribute("aria-valuemax",String(s)),this.thumbEls[0].setAttribute("aria-valuenow",String(this.currentValue)));const r=this.valuesEl?.querySelector(`.${e}__value--single`);r&&(r.textContent=this.formatValue(this.currentValue))}this.syncThumbTooltips(),this.trackEl?.querySelectorAll(`.${e}__mark`).forEach(t=>{const i=t instanceof HTMLElement?parseFloat(t.style.left):NaN,s=t instanceof HTMLElement?parseFloat(t.style.bottom):NaN,r=Number.isFinite(i)?i:s;if(!Number.isFinite(r))return;const a=this.percentToValue(r);t.classList.toggle(`${e}__mark--active`,this.isMarkActive(a))})}syncThumbTooltips(){const t=this.hasAttribute("range"),i=this.hasAttribute("show-thumb-tooltip");this.thumbEls.forEach((s,r)=>{const a=s.querySelector(`.${e}__thumb-tooltip`);if(!a)return;if(!i)return void(a.hidden=!0);a.hidden=!1;const n=t?0===r?this.currentRange[0]:this.currentRange[1]:this.currentValue;a.textContent=this.formatValue(n)})}syncA11y(){if(!this.containerEl)return;const t=this.getNumberAttr("min",0),e=this.getNumberAttr("max",100),i=this.hasAttribute("range"),s=this.hasAttribute("disabled"),r=this.hasAttribute("readonly");this.containerEl.removeAttribute("role"),this.containerEl.removeAttribute("tabindex"),["aria-valuemin","aria-valuemax","aria-valuenow","aria-valuetext","aria-disabled","aria-readonly"].forEach(t=>this.containerEl?.removeAttribute(t));const a=this.getAttribute("label")?.trim()||"값";this.thumbEls.forEach((n,h)=>{const l=i?0===h?this.currentRange[0]:this.currentRange[1]:this.currentValue,u=i?`${a} ${0===h?"최소값":"최대값"}`:a;n.setAttribute("aria-label",u),n.setAttribute("aria-valuemin",String(i&&1===h?this.currentRange[0]:t)),n.setAttribute("aria-valuemax",String(i&&0===h?this.currentRange[1]:e)),n.setAttribute("aria-valuenow",String(l)),n.setAttribute("aria-valuetext",String(l)),n.setAttribute("aria-disabled",String(s)),n.setAttribute("aria-readonly",String(r)),n.setAttribute("tabindex",s||r?"-1":"0")})}setThumbPosition(t,e){this.hasAttribute("vertical")?(t.style.left="",t.style.bottom=`${e}%`):(t.style.bottom="",t.style.left=`${e}%`)}valueToPercent(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100);return i===e?0:(t-e)/(i-e)*100}percentToValue(t){const e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1),r=e+t/100*(i-e);return this.snapToStep(r,e,i,s)}snapToStep(t,e,i,s){const r=Math.round(t/s)*s;return Math.min(i,Math.max(e,r))}clamp(t,e=this.getNumberAttr("min",0),i=this.getNumberAttr("max",100),s=this.getNumberAttr("step",1)){return this.snapToStep(Math.min(i,Math.max(e,t)),e,i,s)}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}normalizeRangeInput(t){if("string"==typeof t)return this.parseRangeAttr(t);if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null}parseRangeAttr(t){if(!t)return null;if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e)&&2===e.length){const t=Number(e[0]),i=Number(e[1]);if(Number.isFinite(t)&&Number.isFinite(i))return[t,i]}}catch{return null}return null}const e=t.split(",").map(t=>Number(t.trim()));return 2!==e.length||e.some(t=>!Number.isFinite(t))?null:[e[0],e[1]]}parseMarks(){const t=this.getAttribute("marks");if(!t)return[];if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e))return e.map(t=>Number(t)).filter(t=>Number.isFinite(t))}catch{return[]}return[]}return t.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t))}parseMarkLabels(){const t=this.getAttribute("mark-labels");if(!t)return{};try{const e=JSON.parse(t),i={};return Object.entries(e).forEach(([t,e])=>{i[Number(t)]=e}),i}catch{return{}}}isInteractive(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")}getTrackPercent(t,e){if(!this.trackEl)return 0;const i=this.trackEl.getBoundingClientRect();if(this.hasAttribute("vertical")){const t=Math.max(i.top,Math.min(i.bottom,e));return(i.bottom-t)/i.height*100}return(Math.max(i.left,Math.min(i.right,t))-i.left)/i.width*100}handleThumbPointerDown(t,e){this.isInteractive()&&(t.preventDefault(),this.isDragging=!0,this.activeThumb=e,this.setThumbActive(e,!0),document.addEventListener("pointermove",this.boundPointerMove),document.addEventListener("pointerup",this.boundPointerUp))}handleTrackClick(t){if(!this.isInteractive()||!this.trackEl)return;if(t.target.closest(`.${e}__thumb`))return;const i=this.getTrackPercent(t.clientX,t.clientY),s=this.percentToValue(i);this.commitValueAtPosition(s)}handlePointerUp(){this.isDragging&&(this.activeThumb&&this.setThumbActive(this.activeThumb,!1),this.isDragging=!1,this.activeThumb=null,document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),this.syncThumbTooltips(),this.hasAttribute("range")?this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`):this.setAttribute("value",String(this.currentValue)),this.syncA11y())}setThumbActive(t,i){if(this.hasAttribute("range")){const s=this.thumbEls["min"===t?0:1];return void s?.classList.toggle(`${e}__thumb--active`,i)}this.thumbEls[0]?.classList.toggle(`${e}__thumb--active`,i)}applyDragValue(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange;if("min"===this.activeThumb)this.currentRange=[Math.min(e,i),i];else if("max"===this.activeThumb)this.currentRange=[t,Math.max(e,t)];else{Math.abs(e-t)<=Math.abs(e-i)?(this.currentRange=[Math.min(e,i),i],this.activeThumb="min"):(this.currentRange=[t,Math.max(e,t)],this.activeThumb="max")}this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}commitValueAtPosition(t){const e=this.clamp(t);if(this.hasAttribute("range")){const[t,i]=this.currentRange,s=Math.abs(e-t),r=Math.abs(e-i);this.currentRange=s<=r?[Math.min(e,i),i]:[t,Math.max(e,t)],this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()}else this.currentValue=e,this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange()}handleKeyDown(t,e="single"){if(!this.isInteractive())return;const i=this.getNumberAttr("step",1),s=this.getNumberAttr("min",0),r=this.getNumberAttr("max",100);let a;if(this.hasAttribute("range")&&"single"!==e){const n="min"===e?this.currentRange[0]:this.currentRange[1];switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(n-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(n+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}const h=[...this.currentRange];if("min"===e?h[0]=a:h[1]=a,h[0]>h[1])return;return t.preventDefault(),this.currentRange=h,void this.afterKeyboard()}if(!this.hasAttribute("range")){switch(t.key){case"ArrowLeft":case"ArrowDown":a=this.clamp(this.currentValue-i,s,r);break;case"ArrowRight":case"ArrowUp":a=this.clamp(this.currentValue+i,s,r);break;case"Home":a=s;break;case"End":a=r;break;default:return}t.preventDefault(),this.currentValue=a,this.afterKeyboard()}}afterKeyboard(){this.hasAttribute("range")?(this.setAttribute("range",`${this.currentRange[0]},${this.currentRange[1]}`),this.syncVisuals(),this.dispatchRangeChange()):(this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y(),this.dispatchValueChange())}dispatchValueChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.currentValue}}))}dispatchRangeChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{range:[...this.currentRange]}}))}}customElements.get("db-range-slider")||customElements.define("db-range-slider",DbRangeSlider);export{DbRangeSlider};
|
|
1
|
+
import{rafThrottle as t}from"../core/dom.js";import{setHostClasses as e}from"../core/host-class.js";import{dbUid as i}from"../core/uid.js";import{sliderBounds as s,sliderPercent as r,sliderValueAt as a,sliderValue as n}from"../core/range-values.js";import{coerceToContract as l}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{RANGE_SLIDER_SIZES as h,RANGE_SLIDER_VARIANTS as u,RANGE_SLIDER_VALUE_POSITIONS as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const c="designbase-wc-range-slider";class DbRangeSlider extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.headerEl=null,this.labelEl=null,this.valuesEl=null,this.containerEl=null,this.trackEl=null,this.fillEl=null,this.thumbEls=[],this.initialized=!1,this.reflecting=!1,this.pointerId=null,this.pointerThumb=null,this.currentValue=50,this.currentRange=[25,75],this.isDragging=!1,this.activeThumb=null,this.boundTrackClick=t=>this.handleTrackClick(t),this.boundPointerMove=t=>{t.pointerId===this.pointerId&&this.handlePointerMove(t)},this.boundPointerUp=t=>this.handlePointerUp(t),this.boundPointerCancel=t=>{t.pointerId===this.pointerId&&this.cancelDrag()},this.eventsBound=!1,this.handlePointerMove=t(t=>{this.isDragging&&this.isInteractive()&&t.pointerId===this.pointerId&&this.applyDragValue(this.percentToValue(this.getTrackPercent(t.clientX,t.clientY)))})}static get observedAttributes(){return["value","range","min","max","step","size","variant","show-value","show-label","label","value-position","value-fixed","show-thumb-tooltip","show-marks","marks","mark-labels","snap-marks","disabled","readonly","full-width","vertical","aria-label","aria-labelledby","aria-describedby","label-minimum","label-maximum"]}connectedCallback(){for(const t of["value","range","min","max","step","size","variant","disabled","readOnly","vertical"]){if(!Object.prototype.hasOwnProperty.call(this,t))continue;const e=this,i=e[t];delete e[t],e[t]=i}this.built||(this.build(),this.built=!0),this.readAttributeValues(),this.syncClasses(),this.syncDomOrder(),this.syncStructure(),this.syncVisuals(),this.syncA11y(),this.bindEvents(),this.tooltipResize??(this.tooltipResize=new ResizeObserver(()=>{this.isConnected&&(this.syncThumbTooltips(),this.syncMarkLabelBounds())})),this.tooltipResize.observe(this)}disconnectedCallback(){this.cancelDrag(),this.unbindEvents(),this.tooltipResize?.disconnect()}attributeChangedCallback(t,e,i){if(!this.built||this.reflecting)return;const s="range"===t&&null===e!=(null===i);this.isInteractive()&&!s&&"vertical"!==t||this.cancelDrag();const r=this.thumbEls.findIndex(t=>t===this.ownerDocument.activeElement),a=this.thumbEls[r];this.readAttributeValues(t),this.syncClasses(),(s||this.isStructuralAttribute(t))&&(this.syncDomOrder(),this.syncStructure()),this.syncVisuals(),this.syncA11y();const n=a?.isConnected?a:r>=0?this.thumbEls[Math.min(r,this.thumbEls.length-1)]:void 0;n&&!this.disabled&&this.ownerDocument.activeElement!==n&&n.focus({preventScroll:!0})}isStructuralAttribute(t){return["min","max","step","show-value","show-label","label","value-position","show-marks","marks","mark-labels","vertical","aria-label","aria-labelledby","aria-describedby","label-minimum","label-maximum"].includes(t)}get value(){return this.built?this.currentValue:this.clamp(this.getNumberAttr("value",50))}set value(t){this.currentValue=this.clamp(Number.isFinite(t)?t:50),this.setAttribute("value",String(this.currentValue)),this.syncVisuals(),this.syncA11y()}get range(){if(!this.hasAttribute("range"))return;const t=this.built?this.currentRange:this.parseRangeAttr(this.getAttribute("range"))??this.currentRange;return this.normalizeValues(t)}set range(t){if(null==t)return this.removeAttribute("range"),void(this.built&&(this.syncStructure(),this.syncVisuals()));const e=this.normalizeRangeInput(t);if(!e)return;this.currentRange=this.normalizeValues(e);const i=`${this.currentRange[0]},${this.currentRange[1]}`;this.getAttribute("range")!==i&&this.setAttribute("range",i),this.built&&(this.syncVisuals(),this.syncA11y())}get min(){return this.getNumberAttr("min",0)}set min(t){this.setAttribute("min",String(t))}get max(){return Math.max(this.min,this.getNumberAttr("max",100))}set max(t){this.setAttribute("max",String(t))}get step(){const t=this.getNumberAttr("step",1);return t>0?t:1}set step(t){this.setAttribute("step",String(t))}get size(){return l(this.getAttribute("size"),h,"m")}set size(t){this.setAttribute("size",t)}get variant(){return l(this.getAttribute("variant"),u,"default")}set variant(t){this.setAttribute("variant",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",Boolean(t))}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",Boolean(t))}get vertical(){return this.hasAttribute("vertical")}set vertical(t){this.toggleAttribute("vertical",Boolean(t))}focus(t){this.thumbEls[0]?.focus(t)}get bounds(){return s(this.min,this.max,this.step)}normalizeValues(t){const e=this.clamp(t[0]),i=this.clamp(t[1]);return[Math.min(e,i),Math.max(e,i)]}build(){this.classList.add(c),this.headerEl=document.createElement("div"),this.headerEl.className=`${c}__header`,this.labelEl=document.createElement("span"),this.labelEl.className=`${c}__label`,this.valuesEl=document.createElement("div"),this.valuesEl.className=`${c}__values`,this.containerEl=document.createElement("div"),this.containerEl.className=`${c}__container`,this.trackEl=document.createElement("div"),this.trackEl.className=`${c}__track`,this.fillEl=document.createElement("div"),this.fillEl.className=`${c}__fill`,this.trackEl.appendChild(this.fillEl),this.containerEl.appendChild(this.trackEl)}getValuePosition(){const t=this.getAttribute("value-position");return t?l(t,o,this.shouldShowLabel()?"top":"right"):this.shouldShowLabel()?"top":"right"}shouldShowLabel(){return this.hasAttribute("show-label")&&Boolean(this.getAttribute("label")?.trim())}formatValue(t){const e=this.getAttribute("value-fixed");if(null!==e&&""!==e){const i=Number(e);if(Number.isFinite(i))return t.toFixed(Math.min(100,Math.max(0,Math.trunc(i))))}return String(t)}syncDomOrder(){if(!(this.headerEl&&this.valuesEl&&this.containerEl&&this.labelEl))return;const t=this.getValuePosition(),e=this.shouldShowLabel(),i=this.hasAttribute("show-value"),s=this.hasAttribute("range")||"top"===t;this.labelEl.textContent=this.getAttribute("label")?.trim()||"";const r=[...e?[this.labelEl]:[],...i&&s?[this.valuesEl]:[]];this.headerEl.replaceChildren(...r),this.containerEl.parentNode!==this&&this.append(this.containerEl),i&&!s?"bottom"===t?this.lastElementChild!==this.valuesEl&&this.append(this.valuesEl):this.valuesEl.nextElementSibling!==this.containerEl&&this.insertBefore(this.valuesEl,this.containerEl):s&&i||this.valuesEl.remove();const a=i&&!s&&"bottom"!==t?this.valuesEl:this.containerEl;r.length?this.headerEl.nextElementSibling!==a&&this.insertBefore(this.headerEl,a):this.headerEl.remove();const n=new Set([this.containerEl,...r.length?[this.headerEl]:[],...i&&!s?[this.valuesEl]:[]]);for(const t of Array.from(this.children))n.has(t)||t.remove()}bindEvents(){this.eventsBound||(this.containerEl?.addEventListener("click",this.boundTrackClick),this.eventsBound=!0)}unbindEvents(){this.eventsBound&&(this.containerEl?.removeEventListener("click",this.boundTrackClick),document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),document.removeEventListener("pointercancel",this.boundPointerCancel),this.handlePointerMove.cancel(),this.eventsBound=!1)}readAttributeValues(t){const e=!this.initialized;if((e||"value"===t)&&(this.currentValue=this.clamp(this.getNumberAttr("value",50))),e||"range"===t){const t=this.parseRangeAttr(this.getAttribute("range"))??(this.hasAttribute("range")&&!this.getAttribute("range")?this.parseRangeAttr(this.getAttribute("value")):null);this.currentRange=t?this.normalizeValues(t):this.normalizeValues(this.currentRange)}this.currentValue=this.clamp(this.currentValue),this.currentRange=this.normalizeValues(this.currentRange),this.initialized=!0}syncClasses(){const t=this.size,i=this.variant,s=this.hasAttribute("range"),r=this.getValuePosition(),a=s?"top":r,n=this.hasAttribute("show-marks")&&this.parseMarks().length>0&&Object.keys(this.parseMarkLabels()).length>0,l=[c,`${c}--${t}`,`${c}--${i}`,`${c}--value-${a}`,this.shouldShowLabel()?`${c}--has-label`:"",this.hasAttribute("disabled")?`${c}--disabled`:"",this.hasAttribute("readonly")?`${c}--readonly`:"",this.hasAttribute("full-width")?`${c}--full-width`:"",this.hasAttribute("vertical")?`${c}--vertical`:"",this.hasAttribute("show-thumb-tooltip")?`${c}--show-tooltip`:"",s?`${c}--range`:"",n?`${c}--has-mark-labels`:""].filter(Boolean);if(e(this,l),this.trackEl){const t=[`${c}__track`];this.hasAttribute("disabled")&&t.push(`${c}__track--disabled`),this.hasAttribute("readonly")&&t.push(`${c}__track--readonly`),this.trackEl.className=t.join(" ")}}syncStructure(){if(!this.valuesEl||!this.trackEl||!this.fillEl)return;const t=this.hasAttribute("show-value"),e=this.hasAttribute("range"),i=this.hasAttribute("show-marks");if(this.valuesEl.innerHTML="",this.valuesEl.hidden=!t,t)if(e){const t=document.createElement("span");t.className=`${c}__value ${c}__value--min`;const e=document.createElement("span");e.className=`${c}__value-separator`,e.textContent="~",e.setAttribute("aria-hidden","true");const i=document.createElement("span");i.className=`${c}__value ${c}__value--max`,this.valuesEl.append(t,e,i)}else{const t=document.createElement("span");t.className=`${c}__value ${c}__value--single`,this.valuesEl.appendChild(t)}if(this.trackEl.querySelectorAll(`.${c}__mark`).forEach(t=>t.remove()),i){const t=this.parseMarks();if(t.length>0){const e=this.parseMarkLabels();t.forEach(t=>{const i=document.createElement("div");if(i.className=`${c}__mark`,i.setAttribute("aria-hidden","true"),i.dataset.value=String(t),this.isMarkActive(t)&&i.classList.add(`${c}__mark--active`),this.hasAttribute("vertical")?i.style.bottom=`${this.valueToPercent(t)}%`:i.style.left=`${this.valueToPercent(t)}%`,void 0!==e[t]){const s=document.createElement("span");s.className=`${c}__mark-label`,s.textContent=e[t],i.appendChild(s)}this.trackEl.insertBefore(i,this.fillEl)})}}const s=e?2:1;for(;this.thumbEls.length>s;)this.thumbEls.pop()?.remove();for(;this.thumbEls.length<s;){const t=document.createElement("div");t.className=`${c}__thumb`,t.setAttribute("role","slider"),t.setAttribute("draggable","false");const kind=()=>t.dataset.thumb||"single";t.addEventListener("pointerdown",t=>this.handleThumbPointerDown(t,kind())),t.addEventListener("keydown",t=>this.handleKeyDown(t,kind())),t.addEventListener("lostpointercapture",t=>{t.pointerId===this.pointerId&&this.cancelDrag()});const e=document.createElement("span");e.className=`${c}__thumb-tooltip`,e.setAttribute("aria-hidden","true"),e.hidden=!0,t.append(e),this.trackEl.append(t),this.thumbEls.push(t)}this.thumbEls.forEach((t,i)=>t.dataset.thumb=e?0===i?"min":"max":"single")}isMarkActive(t){if(this.hasAttribute("range")){const[e,i]=this.currentRange;return t>=e&&t<=i}return t<=this.currentValue}syncVisuals(){if(!this.fillEl)return;const t=this.hasAttribute("range"),e=this.min,i=this.max;if(t){const[t,s]=this.currentRange,r=this.valueToPercent(t),a=this.valueToPercent(s);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom=`${r}%`,this.fillEl.style.height=a-r+"%"):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left=`${r}%`,this.fillEl.style.width=a-r+"%"),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],r),this.thumbEls[0].setAttribute("aria-valuemin",String(e)),this.thumbEls[0].setAttribute("aria-valuemax",String(s)),this.thumbEls[0].setAttribute("aria-valuenow",String(t))),this.thumbEls[1]&&(this.setThumbPosition(this.thumbEls[1],a),this.thumbEls[1].setAttribute("aria-valuemin",String(t)),this.thumbEls[1].setAttribute("aria-valuemax",String(i)),this.thumbEls[1].setAttribute("aria-valuenow",String(s)));const n=this.valuesEl?.querySelector(`.${c}__value--min`),l=this.valuesEl?.querySelector(`.${c}__value--max`);n&&(n.textContent=this.formatValue(t)),l&&(l.textContent=this.formatValue(s))}else{const t=this.valueToPercent(this.currentValue);this.hasAttribute("vertical")?(this.fillEl.style.left="",this.fillEl.style.width="",this.fillEl.style.bottom="0",this.fillEl.style.height=`${t}%`):(this.fillEl.style.bottom="",this.fillEl.style.height="",this.fillEl.style.left="0",this.fillEl.style.width=`${t}%`),this.thumbEls[0]&&(this.setThumbPosition(this.thumbEls[0],t),this.thumbEls[0].setAttribute("aria-valuemin",String(e)),this.thumbEls[0].setAttribute("aria-valuemax",String(i)),this.thumbEls[0].setAttribute("aria-valuenow",String(this.currentValue)));const s=this.valuesEl?.querySelector(`.${c}__value--single`);s&&(s.textContent=this.formatValue(this.currentValue))}this.syncThumbTooltips(),this.syncMarkLabelBounds(),this.trackEl?.querySelectorAll(`.${c}__mark`).forEach(t=>{const e=Number(t.dataset.value);t.classList.toggle(`${c}__mark--active`,this.isMarkActive(e))})}syncThumbTooltips(){const t=this.hasAttribute("range"),e=this.hasAttribute("show-thumb-tooltip");this.thumbEls.forEach((i,s)=>{const r=i.querySelector(`.${c}__thumb-tooltip`);if(!r)return;if(!e)return void(r.hidden=!0);r.hidden=!1;const a=t?0===s?this.currentRange[0]:this.currentRange[1]:this.currentValue;r.textContent=this.formatValue(a),this.fitFloatingText(r)})}fitFloatingText(t){const e=this.getBoundingClientRect();if(!e.width)return;t.style.maxWidth=`${e.width}px`,t.style.marginLeft="0px";const i=t.getBoundingClientRect(),s=i.left<e.left?e.left-i.left:i.right>e.right?e.right-i.right:0;s&&(t.style.marginLeft=`${s}px`)}syncMarkLabelBounds(){this.trackEl?.querySelectorAll(`.${c}__mark-label`).forEach(t=>this.fitFloatingText(t))}syncA11y(){if(!this.containerEl)return;const t=this.min,e=this.max,s=this.hasAttribute("range"),r=this.hasAttribute("disabled"),a=this.hasAttribute("readonly");this.containerEl.removeAttribute("role"),this.containerEl.removeAttribute("tabindex"),["aria-valuemin","aria-valuemax","aria-valuenow","aria-valuetext","aria-disabled","aria-readonly"].forEach(t=>this.containerEl?.removeAttribute(t));const n=this.getAttribute("aria-label")?.trim()||this.getAttribute("label")?.trim()||"Value";this.thumbEls.forEach((l,h)=>{const u=s?0===h?this.currentRange[0]:this.currentRange[1]:this.currentValue,o=s?`${n} ${0===h?this.getAttribute("label-minimum")||"minimum":this.getAttribute("label-maximum")||"maximum"}`:n;l.setAttribute("aria-label",o);const c=this.getAttribute("aria-labelledby");if(c)if(s){const t=l.querySelector("[data-range-endpoint]")??document.createElement("span");t.dataset.rangeEndpoint="",t.hidden=!0,t.id||(t.id=i("slider-endpoint")),t.textContent=0===h?this.getAttribute("label-minimum")||"minimum":this.getAttribute("label-maximum")||"maximum",t.parentNode||l.append(t),l.setAttribute("aria-labelledby",c+" "+t.id)}else l.setAttribute("aria-labelledby",c);else l.removeAttribute("aria-labelledby");const b=this.getAttribute("aria-describedby");b?l.setAttribute("aria-describedby",b):l.removeAttribute("aria-describedby"),l.setAttribute("aria-orientation",this.vertical?"vertical":"horizontal"),l.setAttribute("aria-valuemin",String(s&&1===h?this.currentRange[0]:t)),l.setAttribute("aria-valuemax",String(s&&0===h?this.currentRange[1]:e)),l.setAttribute("aria-valuenow",String(u)),l.setAttribute("aria-valuetext",this.formatValue(u)),l.setAttribute("aria-disabled",String(r)),l.setAttribute("aria-readonly",String(a)),l.setAttribute("tabindex",r?"-1":"0")})}setThumbPosition(t,e){this.hasAttribute("vertical")?(t.style.left="",t.style.bottom=`${e}%`):(t.style.bottom="",t.style.left=`${e}%`)}valueToPercent(t){return r(t,this.bounds)}percentToValue(t){return a(t,this.bounds)}clamp(t,e=this.min,i=this.max,r=this.step){const a=this.snapStops();return a.length>0&&Number.isFinite(t)?a.reduce((e,i)=>Math.abs(i-t)<Math.abs(e-t)?i:e,a[0]):n(t,s(e,i,r))}snapStops(){return this.hasAttribute("snap-marks")?this.parseMarks():[]}adjacentStop(t,e){const i=this.snapStops();return(e>0?i.find(e=>e>t):[...i].reverse().find(e=>e<t))??t}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}normalizeRangeInput(t){if("string"==typeof t)return this.parseRangeAttr(t);if(!Array.isArray(t)||t.length<2)return null;const e=Number(t[0]),i=Number(t[1]);return Number.isFinite(e)&&Number.isFinite(i)?[e,i]:null}parseRangeAttr(t){if(!t)return null;if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e)&&2===e.length){const t=Number(e[0]),i=Number(e[1]);if(Number.isFinite(t)&&Number.isFinite(i))return[t,i]}}catch{return null}return null}const e=t.split(",").map(t=>Number(t.trim()));return 2!==e.length||e.some(t=>!Number.isFinite(t))?null:[e[0],e[1]]}parseMarks(){return[...new Set(this.readMarks())].filter(t=>t>=this.min&&t<=this.max).sort((t,e)=>t-e)}readMarks(){const t=this.getAttribute("marks");if(!t)return[];if(t.startsWith("[")){try{const e=JSON.parse(t);if(Array.isArray(e))return e.map(t=>Number(t)).filter(t=>Number.isFinite(t))}catch{return[]}return[]}return t.split(",").map(t=>Number(t.trim())).filter(t=>Number.isFinite(t))}parseMarkLabels(){const t=this.getAttribute("mark-labels");if(!t)return{};try{const e=JSON.parse(t);if(!e||"object"!=typeof e||Array.isArray(e))return{};const i={};return Object.entries(e).forEach(([t,e])=>{!Number.isFinite(Number(t))||"string"!=typeof e&&"number"!=typeof e||(i[Number(t)]=String(e))}),i}catch{return{}}}isInteractive(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")}getTrackPercent(t,e){if(!this.trackEl)return 0;const i=this.trackEl.getBoundingClientRect();if(!i.width||!i.height)return 0;if(this.hasAttribute("vertical")){const t=Math.max(i.top,Math.min(i.bottom,e));return(i.bottom-t)/i.height*100}return(Math.max(i.left,Math.min(i.right,t))-i.left)/i.width*100}handleThumbPointerDown(t,e){if(this.isInteractive()&&0===t.button&&!1!==t.isPrimary&&!this.isDragging){t.preventDefault(),this.isDragging=!0,this.pointerId=t.pointerId,this.activeThumb=e,this.pointerThumb=t.currentTarget,this.pointerThumb.focus({preventScroll:!0}),this.setThumbActive(e,!0);try{this.pointerThumb.setPointerCapture(t.pointerId)}catch{}document.addEventListener("pointermove",this.boundPointerMove),document.addEventListener("pointerup",this.boundPointerUp),document.addEventListener("pointercancel",this.boundPointerCancel)}}handleTrackClick(t){this.isInteractive()&&this.trackEl&&!t.target.closest(`.${c}__thumb`)&&this.commitValueAtPosition(this.percentToValue(this.getTrackPercent(t.clientX,t.clientY)))}handlePointerUp(t){this.isDragging&&t.pointerId===this.pointerId&&(this.handlePointerMove.cancel(),this.isInteractive()&&this.applyDragValue(this.percentToValue(this.getTrackPercent(t.clientX,t.clientY))),this.cancelDrag())}cancelDrag(){this.handlePointerMove.cancel(),this.activeThumb&&this.setThumbActive(this.activeThumb,!1);const t=this.pointerThumb,e=this.pointerId;this.isDragging=!1,this.activeThumb=null,this.pointerId=null,this.pointerThumb=null,document.removeEventListener("pointermove",this.boundPointerMove),document.removeEventListener("pointerup",this.boundPointerUp),document.removeEventListener("pointercancel",this.boundPointerCancel);try{t&&null!==e&&t.hasPointerCapture(e)&&t.releasePointerCapture(e)}catch{}}setThumbActive(t,e){if(this.hasAttribute("range")){const i=this.thumbEls["min"===t?0:1];return void i?.classList.toggle(`${c}__thumb--active`,e)}this.thumbEls[0]?.classList.toggle(`${c}__thumb--active`,e)}reflectCurrent(){this.reflecting=!0;try{const t=this.hasAttribute("range")?"range":"value",e="range"===t?this.currentRange.join(","):String(this.currentValue);this.getAttribute(t)!==e&&this.setAttribute(t,e)}finally{this.reflecting=!1}}applyDragValue(t){this.applyValue(t,this.activeThumb??"single")}applyValue(t,e){const i=this.clamp(t);if(this.hasAttribute("range")){const[t,s]=this.currentRange,r="min"===e?[Math.min(i,s),s]:[t,Math.max(i,t)];if(r[0]===t&&r[1]===s)return;this.currentRange=r}else{if(i===this.currentValue)return;this.currentValue=i}this.reflectCurrent(),this.syncVisuals(),this.syncA11y(),this.hasAttribute("range")?this.dispatchRangeChange():this.dispatchValueChange()}commitValueAtPosition(t){const e=this.hasAttribute("range")?Math.abs(t-this.currentRange[0])<=Math.abs(t-this.currentRange[1])?"min":"max":"single";this.thumbEls["max"===e?1:0]?.focus({preventScroll:!0}),this.applyValue(t,e)}handleKeyDown(t,e="single"){if(!this.isInteractive())return;const i=this.hasAttribute("range")?this.currentRange["max"===e?1:0]:this.currentValue;let s;if(this.snapStops().length>0){switch(t.key){case"ArrowLeft":case"ArrowDown":case"PageDown":s=this.adjacentStop(i,-1);break;case"ArrowRight":case"ArrowUp":case"PageUp":s=this.adjacentStop(i,1);break;case"Home":s=this.min;break;case"End":s=this.max;break;default:return}return t.preventDefault(),void this.applyValue(s,e)}switch(t.key){case"ArrowLeft":case"ArrowDown":s=i-this.step;break;case"ArrowRight":case"ArrowUp":s=i+this.step;break;case"PageDown":s=i-10*this.step;break;case"PageUp":s=i+10*this.step;break;case"Home":s=this.min;break;case"End":s=this.max;break;default:return}t.preventDefault(),this.applyValue(s,e)}dispatchValueChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.currentValue}}))}dispatchRangeChange(){const t=[...this.currentRange];for(const e of["db-change","db-range-change"])this.dispatchEvent(new CustomEvent(e,{bubbles:!0,composed:!0,detail:{range:[...t]}}))}}customElements.get("db-range-slider")||customElements.define("db-range-slider",DbRangeSlider);export{DbRangeSlider};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t,getDbLocale as e}from"../core/i18n.js";import{DbPaperCard as a,paperJson as r,paperNode as i,paperDetails as s}from"./paper-card.js";const
|
|
1
|
+
import{t,getDbLocale as e}from"../core/i18n.js";import{DbPaperCard as a,paperJson as r,paperNode as i,paperDetails as s}from"./paper-card.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{RECEIPT_VARIANTS as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const p={quantity:"수량",subtotal:"소계",discount:"할인",tax:"세금",total:"합계",payment:"결제수단",empty:"표시할 품목이 없습니다.",invalid:"품목과 금액 정보를 확인해주세요."},minor=t=>"number"==typeof t&&Number.isSafeInteger(t)&&t>=0;class DbReceipt extends a{constructor(){super(...arguments),this.data=void 0,this.customLabels={}}static get observedAttributes(){return["variant","code-image-src","code-alt","merchant","merchant-detail","reference","issued-at","items","currency","locale","discount-amount","tax-amount","payment-method","note","edge","action-label","disabled"]}upgradeNames(){return["items","labels"]}get items(){const t=this.data??r(this.attr("items"));return Array.isArray(t)?t.map(t=>({...t})):[]}set items(t){this.data=null==t?void 0:Array.isArray(t)?t.map(t=>({...t})):t,this.isConnected&&this.render()}get labels(){return{...Object.fromEntries(Object.entries(p).map(([e,a])=>[e,t(`receipt.${e}`,a)])),...this.customLabels}}set labels(t){this.customLabels={};for(const e of Object.keys(p))"string"==typeof t?.[e]&&(this.customLabels[e]=t[e]);this.isConnected&&this.render()}render(){const a="compact"===n(this.getAttribute("variant"),o,"default");this.dataset.variant=a?"compact":"default";const r=this.labels,p=i("section","db-paper__main");p.append(i("h3","db-paper__title",this.attr("merchant")||t("receipt.title"))),this.attr("merchant-detail")&&p.append(i("p","db-paper__description",this.attr("merchant-detail")));const c=i("div","db-paper__receipt-meta");let d;this.attr("issued-at")&&c.append(i("span","",this.attr("issued-at"))),!a&&this.attr("reference")&&c.append(i("span","",this.attr("reference"))),p.append(c);try{d=new Intl.NumberFormat(this.attr("locale")||("ko"===e()?"ko-KR":"en-US"),{style:"currency",currency:this.attr("currency")||"KRW"})}catch{d=new Intl.NumberFormat("ko"===e()?"ko-KR":"en-US",{style:"currency",currency:"KRW"})}const m=d.resolvedOptions().maximumFractionDigits||0,u=BigInt(10**m),l=new Intl.NumberFormat(d.resolvedOptions().locale,{useGrouping:!1,minimumIntegerDigits:Math.max(1,m),maximumFractionDigits:0}),money=t=>{const e=BigInt(t);return d.formatToParts(e/u).map(t=>"fraction"===t.type?l.format(e%u):t.value).join("")};let b=this.data;if(void 0===b)try{b=this.hasAttribute("items")?JSON.parse(this.attr("items")):[]}catch{b=null}const h=Array.isArray(b)?b:[];let y=Array.isArray(b),f=0;for(const t of h){if(!t||"string"!=typeof t.name||!Number.isSafeInteger(t.quantity)||t.quantity<=0||!minor(t.unitAmount)||!Number.isSafeInteger(t.quantity*t.unitAmount)){y=!1;break}if(f+=t.quantity*t.unitAmount,!Number.isSafeInteger(f)){y=!1;break}}const amount=t=>this.hasAttribute(t)&&""===this.attr(t).trim()?NaN:Number(this.getAttribute(t)??0),g=amount("discount-amount"),_=amount("tax-amount");y=y&&minor(g)&&minor(_)&&g<=f&&Number.isSafeInteger(f-g+_);const v=i("div","db-paper__receipt-items");if(y)if(h.length)for(const t of h){const e=i("div","db-paper__receipt-item"),a=i("div","");a.append(i("strong","",t.name),i("span","db-paper__label",`${r.quantity} ${t.quantity} × ${money(t.unitAmount)}`)),e.append(a,i("span","",money(t.unitAmount*t.quantity))),v.append(e)}else v.append(i("p","db-paper__note",r.empty));else{const t=i("p","db-paper__error",r.invalid);t.setAttribute("role","alert"),v.append(t)}p.append(v);const A=i("div","db-paper__stub"),N=a?p:A;if(y&&(!a||g||_)){const t=[{label:r.subtotal,value:money(f)}];g&&t.push({label:r.discount,value:"−"+money(g)}),_&&t.push({label:r.tax,value:money(_)}),N.append(s(t))}const I=i("div","db-paper__receipt-total");I.append(i("strong","",r.total),i("strong","db-paper__amount",y?money(f-g+_):"—")),N.append(I),this.attr("payment-method")&&N.append(s([{label:r.payment,value:this.attr("payment-method")}])),this.attr("note")&&N.append(i("p","db-paper__note",this.attr("note"))),(a||this.attr("code-image-src"))&&A.append(this.code(this.attr("reference")));const k=this.action(this.attr("reference"));k&&(k.toggleAttribute("disabled",!y||this.hasAttribute("disabled")),A.append(k)),this.replace(p,A)}}customElements.get("db-receipt")||customElements.define("db-receipt",DbReceipt);export{DbReceipt};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import './db-checkbox.js';
|
|
2
|
-
|
|
3
1
|
declare class DbSelect extends HTMLElement {
|
|
4
2
|
static readonly formAssociated = true;
|
|
5
3
|
static get observedAttributes(): string[];
|
|
@@ -19,18 +17,45 @@ declare class DbSelect extends HTMLElement {
|
|
|
19
17
|
private built;
|
|
20
18
|
private searchTerm;
|
|
21
19
|
private focusedIndex;
|
|
20
|
+
private initialValue?;
|
|
21
|
+
private awaitingValue;
|
|
22
|
+
private userInteracted;
|
|
23
|
+
private formDisabled;
|
|
24
|
+
private wasOpen;
|
|
25
|
+
private searchFocusFrame?;
|
|
26
|
+
private typeahead;
|
|
27
|
+
private typeaheadAt;
|
|
28
|
+
get defaultValue(): string;
|
|
29
|
+
set defaultValue(value: string | string[]);
|
|
30
|
+
get disabled(): boolean;
|
|
31
|
+
set disabled(value: boolean);
|
|
32
|
+
get readOnly(): boolean;
|
|
33
|
+
set readOnly(value: boolean);
|
|
34
|
+
get required(): boolean;
|
|
35
|
+
set required(value: boolean);
|
|
36
|
+
get form(): HTMLFormElement | null;
|
|
37
|
+
get validity(): ValidityState;
|
|
38
|
+
get validationMessage(): string;
|
|
39
|
+
get willValidate(): boolean;
|
|
40
|
+
checkValidity(): boolean;
|
|
41
|
+
reportValidity(): boolean;
|
|
42
|
+
focus(options?: FocusOptions): void;
|
|
43
|
+
private get unavailable();
|
|
44
|
+
private get locked();
|
|
45
|
+
private captureDefault;
|
|
22
46
|
get name(): string;
|
|
23
47
|
set name(value: string);
|
|
24
48
|
get open(): boolean;
|
|
25
49
|
set open(value: boolean);
|
|
26
50
|
get value(): string;
|
|
27
|
-
set value(value: string);
|
|
51
|
+
set value(value: string | string[]);
|
|
28
52
|
connectedCallback(): void;
|
|
29
53
|
formAssociatedCallback(): void;
|
|
30
54
|
disconnectedCallback(): void;
|
|
31
55
|
formResetCallback(): void;
|
|
56
|
+
formStateRestoreCallback(state: string | File | FormData | null): void;
|
|
32
57
|
formDisabledCallback(disabled: boolean): void;
|
|
33
|
-
attributeChangedCallback(name: string): void;
|
|
58
|
+
attributeChangedCallback(name: string, oldValue: string | null): void;
|
|
34
59
|
get multiple(): boolean;
|
|
35
60
|
set multiple(value: boolean);
|
|
36
61
|
get searchable(): boolean;
|
|
@@ -50,6 +75,8 @@ declare class DbSelect extends HTMLElement {
|
|
|
50
75
|
private handleClear;
|
|
51
76
|
private handleSearchInput;
|
|
52
77
|
private handleDocumentMouseDown;
|
|
78
|
+
private handleFocusOut;
|
|
79
|
+
private moveFocus;
|
|
53
80
|
private handleDocumentKeyDown;
|
|
54
81
|
private getFilteredOptions;
|
|
55
82
|
private selectOption;
|
|
@@ -58,12 +85,14 @@ declare class DbSelect extends HTMLElement {
|
|
|
58
85
|
* combobox 트리거에 접근 가능한 이름을 붙인다.
|
|
59
86
|
*
|
|
60
87
|
* 트리거는 `<div role="combobox">` 라서 `<label for>` 로는 연결되지 않는다.
|
|
61
|
-
*
|
|
62
|
-
*
|
|
88
|
+
* 명시적 aria-labelledby/aria-label, 보이는 label, placeholder 순으로
|
|
89
|
+
* 실제 trigger와 검색 입력 및 목록의 이름을 동기화한다. (A11Y-NAME)
|
|
63
90
|
*/
|
|
64
91
|
private syncAccessibleName;
|
|
65
92
|
private syncState;
|
|
66
93
|
private syncOpenState;
|
|
94
|
+
private cancelSearchFocus;
|
|
95
|
+
private scheduleSearchFocus;
|
|
67
96
|
private syncTrigger;
|
|
68
97
|
private syncOptions;
|
|
69
98
|
private escape;
|