@designbasekorea/ui-wc 0.9.4 → 0.11.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 +20 -0
- package/LICENSE-WORLD-MAP.md +10 -0
- package/README.md +60 -0
- package/dist/esm/components/db-accordion.d.ts +22 -10
- package/dist/esm/components/db-accordion.js +1 -1
- package/dist/esm/components/db-achievement-list.d.ts +2 -0
- package/dist/esm/components/db-achievement-list.js +1 -1
- package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
- package/dist/esm/components/db-activity-heatmap.js +1 -1
- package/dist/esm/components/db-ad-banner.d.ts +2 -0
- package/dist/esm/components/db-ad-banner.js +1 -1
- package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
- package/dist/esm/components/db-ai-chat-list.js +1 -1
- package/dist/esm/components/db-ai-chat.d.ts +2 -0
- package/dist/esm/components/db-ai-chat.js +1 -1
- package/dist/esm/components/db-ai-file-tree.js +1 -1
- package/dist/esm/components/db-alert.d.ts +1 -0
- package/dist/esm/components/db-alert.js +1 -1
- package/dist/esm/components/db-audio-player.d.ts +2 -0
- package/dist/esm/components/db-audio-player.js +1 -1
- package/dist/esm/components/db-avatar.d.ts +1 -0
- package/dist/esm/components/db-avatar.js +1 -1
- package/dist/esm/components/db-banner.d.ts +2 -0
- package/dist/esm/components/db-banner.js +1 -1
- package/dist/esm/components/db-button.d.ts +40 -2
- package/dist/esm/components/db-button.js +1 -1
- package/dist/esm/components/db-calendar.d.ts +5 -0
- package/dist/esm/components/db-calendar.js +1 -1
- package/dist/esm/components/db-card.d.ts +1 -0
- package/dist/esm/components/db-card.js +1 -1
- package/dist/esm/components/db-chat-composer.d.ts +3 -0
- package/dist/esm/components/db-chat-composer.js +1 -1
- package/dist/esm/components/db-chat-message.d.ts +2 -0
- package/dist/esm/components/db-chat-message.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.d.ts +1 -0
- package/dist/esm/components/db-chat-room.js +1 -1
- package/dist/esm/components/db-chat-typing.d.ts +2 -0
- package/dist/esm/components/db-chat-typing.js +1 -1
- package/dist/esm/components/db-chat-widget.d.ts +9 -0
- package/dist/esm/components/db-chat-widget.js +1 -1
- package/dist/esm/components/db-checkbox.d.ts +3 -0
- package/dist/esm/components/db-checkbox.js +1 -1
- package/dist/esm/components/db-chip.d.ts +2 -0
- package/dist/esm/components/db-chip.js +1 -1
- package/dist/esm/components/db-code-block.d.ts +1 -0
- package/dist/esm/components/db-code-block.js +1 -1
- package/dist/esm/components/db-color-picker.d.ts +4 -0
- package/dist/esm/components/db-color-picker.js +1 -1
- package/dist/esm/components/db-color-swatch.d.ts +3 -0
- package/dist/esm/components/db-color-swatch.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-cookie-banner.d.ts +3 -0
- package/dist/esm/components/db-cookie-banner.js +1 -1
- package/dist/esm/components/db-countdown.d.ts +2 -1
- package/dist/esm/components/db-countdown.js +1 -1
- package/dist/esm/components/db-date-picker.d.ts +3 -0
- package/dist/esm/components/db-date-picker.js +1 -1
- package/dist/esm/components/db-dropdown.d.ts +1 -0
- package/dist/esm/components/db-dropdown.js +1 -1
- package/dist/esm/components/db-dropzone.d.ts +2 -0
- package/dist/esm/components/db-dropzone.js +1 -1
- package/dist/esm/components/db-email-verify.d.ts +37 -7
- package/dist/esm/components/db-email-verify.js +1 -1
- package/dist/esm/components/db-file-uploader.d.ts +2 -0
- package/dist/esm/components/db-file-uploader.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-form.d.ts +2 -0
- package/dist/esm/components/db-form.js +1 -1
- package/dist/esm/components/db-gantt.d.ts +2 -0
- package/dist/esm/components/db-gantt.js +1 -1
- package/dist/esm/components/db-image-list.d.ts +3 -0
- package/dist/esm/components/db-image-list.js +1 -1
- package/dist/esm/components/db-image.d.ts +1 -0
- package/dist/esm/components/db-image.js +1 -1
- package/dist/esm/components/db-input-group.d.ts +30 -0
- package/dist/esm/components/db-input-group.js +1 -0
- package/dist/esm/components/db-input.d.ts +9 -1
- package/dist/esm/components/db-input.js +1 -1
- package/dist/esm/components/db-kanban.d.ts +3 -0
- package/dist/esm/components/db-kanban.js +1 -1
- package/dist/esm/components/db-lightbox.d.ts +2 -0
- package/dist/esm/components/db-lightbox.js +1 -1
- package/dist/esm/components/db-list.d.ts +2 -0
- package/dist/esm/components/db-list.js +1 -1
- package/dist/esm/components/db-markdown-editor.d.ts +2 -0
- package/dist/esm/components/db-markdown-editor.js +1 -1
- package/dist/esm/components/db-menu-item.js +1 -1
- package/dist/esm/components/db-navbar.d.ts +6 -0
- package/dist/esm/components/db-navbar.js +1 -1
- package/dist/esm/components/db-node.d.ts +1 -0
- package/dist/esm/components/db-node.js +1 -1
- package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
- package/dist/esm/components/db-onboarding-modal.js +1 -1
- package/dist/esm/components/db-otp-input.d.ts +4 -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-popover.d.ts +1 -0
- package/dist/esm/components/db-popover.js +1 -1
- package/dist/esm/components/db-progress-step.d.ts +2 -0
- package/dist/esm/components/db-progress-step.js +1 -1
- package/dist/esm/components/db-radio.d.ts +3 -0
- package/dist/esm/components/db-radio.js +1 -1
- package/dist/esm/components/db-range-slider.d.ts +36 -7
- package/dist/esm/components/db-range-slider.js +1 -1
- package/dist/esm/components/db-rating.d.ts +1 -0
- package/dist/esm/components/db-rating.js +1 -1
- package/dist/esm/components/db-search-bar.d.ts +2 -0
- package/dist/esm/components/db-search-bar.js +1 -1
- package/dist/esm/components/db-section-logo-cloud.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-share.d.ts +5 -0
- package/dist/esm/components/db-share.js +1 -1
- package/dist/esm/components/db-sidebar.d.ts +3 -0
- package/dist/esm/components/db-sidebar.js +1 -1
- package/dist/esm/components/db-signature.d.ts +2 -0
- package/dist/esm/components/db-signature.js +1 -1
- package/dist/esm/components/db-spinner.d.ts +2 -0
- package/dist/esm/components/db-spinner.js +1 -1
- package/dist/esm/components/db-stepper.d.ts +2 -0
- package/dist/esm/components/db-stepper.js +1 -1
- package/dist/esm/components/db-table.d.ts +2 -0
- package/dist/esm/components/db-table.js +1 -1
- package/dist/esm/components/db-tabs.d.ts +37 -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-ticket.js +1 -1
- package/dist/esm/components/db-time-picker.d.ts +2 -0
- package/dist/esm/components/db-time-picker.js +1 -1
- package/dist/esm/components/db-timeline.d.ts +4 -0
- package/dist/esm/components/db-timeline.js +1 -1
- package/dist/esm/components/db-toast.d.ts +2 -0
- package/dist/esm/components/db-toast.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-layout.d.ts +92 -0
- package/dist/esm/components/db-tool-layout.js +1 -0
- package/dist/esm/components/db-tool-panel.d.ts +50 -0
- package/dist/esm/components/db-tool-panel.js +1 -0
- package/dist/esm/components/db-top-banner.d.ts +2 -0
- package/dist/esm/components/db-top-banner.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-video-player.d.ts +3 -0
- package/dist/esm/components/db-video-player.js +1 -1
- package/dist/esm/components/db-world-map.d.ts +60 -0
- package/dist/esm/components/db-world-map.js +1 -0
- package/dist/esm/components/db-youtube-player.d.ts +2 -0
- package/dist/esm/components/db-youtube-player.js +1 -1
- package/dist/esm/components/db-zoom-control.d.ts +52 -0
- package/dist/esm/components/db-zoom-control.js +1 -0
- package/dist/esm/components/input-validation.js +1 -1
- package/dist/esm/components/paper-card.d.ts +2 -0
- package/dist/esm/components/paper-card.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 +31 -1
- 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/helpers/world-countries.js +1 -0
- package/dist/esm/helpers/world-land.js +1 -0
- package/dist/esm/index.d.ts +6 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +804 -83
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +6211 -648
- package/dist/react/index.esm.js +1 -1
- package/package.json +9 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
import{setHostClasses as e}from"../core/host-class.js";import{isDbIconName as t,createDbIcon as i}from"./db-icons.js";import{DROPDOWN_SIZES as r,DROPDOWN_PLACEMENTS as s,DROPDOWN_TRIGGER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDropdown extends HTMLElement{constructor(){super(...arguments),this.focusedIndex=-1,this.onTriggerActivate=null,this.lastTriggerSignature="",this.handleTriggerKeyDown=e=>{if(!this.menu?.contains(e.target))return"Enter"!==e.key&&" "!==e.key&&"ArrowDown"!==e.key||this.open?void("Escape"===e.key&&this.open&&(e.preventDefault(),this.open=!1,this.render())):(e.preventDefault(),this.open=!0,requestAnimationFrame(()=>this.focusItem(0)),void this.render())},this.handleDocumentKeyDown=e=>{if(!this.open)return;if("Escape"===e.key)return e.preventDefault(),this.open=!1,this.render(),void this.triggerWrap?.querySelector("[aria-haspopup]")?.focus();if(this.menu?.querySelector(':scope > [slot="content"]'))return;const t=this.enabledItems();if(!t.length)return;const i=t.findIndex(e=>this.parsedItems.indexOf(e)===this.focusedIndex);switch(e.key){case"ArrowDown":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i+1)%t.length]));break;case"ArrowUp":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i-1+t.length)%t.length]));break;case"Home":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[0]));break;case"End":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[t.length-1]));break;case"Enter":case" ":{e.preventDefault();const t=this.parsedItems[this.focusedIndex];!t||t.divider||t.disabled||this.selectItem(t);break}}},this.handleDocumentMouseDown=e=>{this.open&&(this.contains(e.target)||(this.open=!1,this.render()))}}static get observedAttributes(){return["options","items","placeholder","label","value","size","placement","full-width","disabled","open","trigger-variant","trigger-icon","icon-only","show-chevron"]}get showChevron(){return"false"!==this.getAttribute("show-chevron")}set showChevron(e){this.setAttribute("show-chevron",String(e))}get parsedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return(this.getAttribute("options")||"").split(",").map(e=>e.trim()).filter(Boolean).map((e,t)=>({id:`option-${t}`,label:e}))}get options(){return this.parsedItems.map(e=>e.label||e.id)}set options(e){this.setAttribute("options",Array.isArray(e)?e.join(","):e)}get items(){return this.parsedItems}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get value(){return this.getAttribute("value")||""}set value(e){e?this.setAttribute("value",e):this.removeAttribute("value")}get open(){return this.hasAttribute("open")}set open(e){const t=this.open;this.toggleAttribute("open",e),t!==e&&this.dispatchEvent(new CustomEvent("db-open",{detail:{open:e},bubbles:!0,composed:!0}))}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get placement(){return this.getAttribute("placement")||"bottom-left"}set placement(e){this.setAttribute("placement",e)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(e){e?this.setAttribute("placeholder",e):this.removeAttribute("placeholder")}get label(){return this.getAttribute("label")||""}set label(e){e?this.setAttribute("label",e):this.removeAttribute("label")}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}connectedCallback(){requestAnimationFrame(()=>this.render()),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.unbindTrigger()}attributeChangedCallback(e){this.isConnected&&("open"!==e||this.open||(this.focusedIndex=-1),this.render())}resolvedSize(){return r.includes(this.size)?this.size:"m"}resolvedPlacement(){return s.includes(this.placement)?this.placement:"bottom-left"}menuItemIconSize(){const e=this.resolvedSize();return"s"===e?14:"l"===e?18:16}triggerLabel(){return this.label?this.label:this.placeholder?this.placeholder:this.value?this.value:"메뉴"}enabledItems(){return this.parsedItems.filter(e=>!e.disabled&&!e.divider)}collectTriggerChildren(){const isInternalNode=e=>"content"===e.getAttribute("slot")||e.hasAttribute("data-wc-internal")||e===this.triggerWrap||e===this.menu||e===this.defaultTrigger,e=Array.from(this.children).filter(e=>!isInternalNode(e));return e.length>0?e:Array.from(this.triggerWrap?.children||[]).filter(e=>!isInternalNode(e))}hasCustomTrigger(){return this.collectTriggerChildren().length>0}bindTrigger(){this.triggerWrap&&(this.unbindTrigger(),this.onTriggerActivate=e=>{this.disabled||this.menu?.contains(e.target)||(e.preventDefault(),e.stopPropagation(),this.toggleOpen())},this.triggerWrap.addEventListener("click",this.onTriggerActivate),this.triggerWrap.addEventListener("keydown",this.handleTriggerKeyDown))}unbindTrigger(){this.triggerWrap&&this.onTriggerActivate&&this.triggerWrap.removeEventListener("click",this.onTriggerActivate),this.triggerWrap&&this.triggerWrap.removeEventListener("keydown",this.handleTriggerKeyDown),this.onTriggerActivate=null}toggleOpen(){this.disabled||(this.open=!this.open,this.open&&requestAnimationFrame(()=>this.focusItem(0)),this.render())}triggerSignature(){return[this.resolvedSize(),this.getAttribute("trigger-variant")||"tertiary",this.hasAttribute("icon-only")?"1":"0",this.getAttribute("trigger-icon")||"",this.fullWidth?"1":"0",this.showChevron?"1":"0"].join("|")}renderDefaultTrigger(){const e=this.resolvedSize(),i=this.getAttribute("trigger-variant")||"tertiary",r=n.includes(i)?i:"tertiary",s=this.hasAttribute("icon-only"),o=this.getAttribute("trigger-icon"),a=document.createElement("db-button");if(a.setAttribute("type","button"),a.setAttribute("variant",r),a.setAttribute("size",e),a.className="designbase-wc-dropdown__trigger",a.setAttribute("aria-haspopup","menu"),a.setAttribute("aria-label",this.triggerLabel()),this.fullWidth&&a.setAttribute("full-width",""),s)a.setAttribute("icon-only",""),a.setAttribute("start-icon",o&&t(o)?o:"edit"),a.removeAttribute("end-icon");else{a.removeAttribute("icon-only"),o&&t(o)?a.setAttribute("start-icon",o):a.removeAttribute("start-icon");const e=document.createElement("span");e.className="designbase-wc-dropdown__trigger-label",e.textContent=this.triggerLabel(),a.append(e),this.showChevron&&a.setAttribute("end-icon","chevron-down")}return a}syncDefaultTriggerState(e){e.setAttribute("aria-expanded",String(this.open)),e.setAttribute("aria-label",this.triggerLabel()),e.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),this.disabled?e.setAttribute("disabled",""):e.removeAttribute("disabled");const t=e.querySelector(".designbase-wc-dropdown__trigger-label");t&&(t.textContent=this.triggerLabel())}ensureStructure(){this.triggerWrap||(this.triggerWrap=document.createElement("div"),this.triggerWrap.className="designbase-wc-dropdown__trigger-wrap",this.triggerWrap.setAttribute("data-wc-internal","")),this.menu||(this.menu=document.createElement("div"),this.menu.className="designbase-wc-dropdown__menu",this.menu.setAttribute("data-wc-internal",""),this.menu.setAttribute("role","menu"));const e=this.triggerWrap,t=this.menu;e&&t&&(this.contains(e)||this.append(e),e.contains(t)||e.append(t),Array.from(this.children).forEach(i=>{i===e||i.hasAttribute("data-wc-internal")||("content"===i.getAttribute("slot")?t.append(i):e.insertBefore(i,t))}))}renderTrigger(){const e=this.triggerWrap,t=this.menu;if(!e||!t)return;const i=this.collectTriggerChildren();if(i.length>0){this.defaultTrigger?.remove(),this.defaultTrigger=void 0;Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),i.forEach(i=>{i.setAttribute("aria-haspopup","menu"),i.setAttribute("aria-expanded",String(this.open)),i.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),e.insertBefore(i,t)})}else{Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),this.defaultTrigger&&this.triggerSignature()===this.lastTriggerSignature||(this.defaultTrigger?.remove(),this.defaultTrigger=this.renderDefaultTrigger(),this.lastTriggerSignature=this.triggerSignature(),e.insertBefore(this.defaultTrigger,t)),this.defaultTrigger&&this.syncDefaultTriggerState(this.defaultTrigger)}this.bindTrigger()}renderMenu(){const e=this.resolvedPlacement();this.menu.className=`designbase-wc-dropdown__menu designbase-wc-dropdown__menu--${e}${this.open?" designbase-wc-dropdown__menu--open":""}`,this.menu.setAttribute("aria-hidden",String(!this.open)),this.menu.setAttribute("aria-label",this.triggerLabel());const t=this.menu.querySelector(':scope > [slot="content"]');if(this.menu.setAttribute("role",t?"dialog":"menu"),t)return this.menu.inert=!this.open,this.menu.setAttribute("aria-modal","false"),this.menu.classList.add("designbase-wc-dropdown__menu--custom"),void this.triggerWrap?.querySelector("[aria-haspopup]")?.setAttribute("aria-haspopup","dialog");this.menu.inert=!1,this.menu.removeAttribute("aria-modal"),this.menu.replaceChildren();const r=this.menuItemIconSize();this.parsedItems.forEach((e,t)=>{if(e.divider){const e=document.createElement("div");return e.className="designbase-wc-dropdown__divider",e.setAttribute("role","separator"),void this.menu?.append(e)}e.id||e.label||String(t);const s=e.label||e.id,n=Boolean(e.disabled||this.disabled),o=this.focusedIndex===t,a=document.createElement("button");if(a.type="button",a.className=["designbase-wc-dropdown__item",n&&"designbase-wc-dropdown__item--disabled",o&&"designbase-wc-dropdown__item--focused"].filter(Boolean).join(" "),a.setAttribute("role","menuitem"),a.disabled=n,a.tabIndex=o?0:-1,a.dataset.index=String(t),e.icon){const t=i(e.icon,r);t.classList.add("designbase-wc-dropdown__item-icon"),a.append(t)}const d=document.createElement("span");d.className="designbase-wc-dropdown__item-label",d.textContent=s,a.append(d),a.addEventListener("click",t=>{t.stopPropagation(),this.selectItem(e)}),this.menu?.append(a)})}render(){const t=this.resolvedSize();e(this,["designbase-wc-dropdown",`designbase-wc-dropdown--${t}`,this.open&&"designbase-wc-dropdown--open",this.fullWidth&&"designbase-wc-dropdown--full-width",this.disabled&&"designbase-wc-dropdown--disabled"]),this.ensureStructure(),this.renderTrigger(),this.renderMenu()}selectItem(e){e.disabled||e.divider||(this.open=!1,this.focusedIndex=-1,this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.label||e.id,id:e.id,item:e},bubbles:!0,composed:!0})),this.render(),this.triggerWrap?.querySelector("[aria-haspopup]")?.focus())}focusItem(e){if(this.menu?.querySelector(':scope > [slot="content"]'))return void this.menu.querySelector('input:not([disabled]), button:not([disabled]), [tabindex="0"]')?.focus();const t=this.enabledItems();if(!t.length)return;const i=t[Math.max(0,Math.min(e,t.length-1))],r=this.parsedItems.indexOf(i);this.focusedIndex=r;Array.from(this.menu?.querySelectorAll(".designbase-wc-dropdown__item")||[]).forEach(e=>{const t=Number(e.dataset.index)===r;e.classList.toggle("designbase-wc-dropdown__item--focused",t),e.tabIndex=t?0:-1,t&&e.focus()})}}customElements.get("db-dropdown")||customElements.define("db-dropdown",DbDropdown);export{DbDropdown};
|
|
1
|
+
import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{setHostClasses as i}from"../core/host-class.js";import{isDbIconName as r,createDbIcon as s}from"./db-icons.js";import{DROPDOWN_SIZES as n,DROPDOWN_PLACEMENTS as o,DROPDOWN_TRIGGER_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDropdown extends HTMLElement{constructor(){super(...arguments),this.focusedIndex=-1,this.onTriggerActivate=null,this.lastTriggerSignature="",this.handleTriggerKeyDown=e=>{if(!this.menu?.contains(e.target))return"Enter"!==e.key&&" "!==e.key&&"ArrowDown"!==e.key||this.open?void("Escape"===e.key&&this.open&&(e.preventDefault(),this.open=!1,this.render())):(e.preventDefault(),this.open=!0,requestAnimationFrame(()=>this.focusItem(0)),void this.render())},this.handleDocumentKeyDown=e=>{if(!this.open)return;if("Escape"===e.key)return e.preventDefault(),this.open=!1,this.render(),void this.triggerWrap?.querySelector("[aria-haspopup]")?.focus();if(this.menu?.querySelector(':scope > [slot="content"]'))return;const t=this.enabledItems();if(!t.length)return;const i=t.findIndex(e=>this.parsedItems.indexOf(e)===this.focusedIndex);switch(e.key){case"ArrowDown":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i+1)%t.length]));break;case"ArrowUp":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i-1+t.length)%t.length]));break;case"Home":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[0]));break;case"End":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[t.length-1]));break;case"Enter":case" ":{e.preventDefault();const t=this.parsedItems[this.focusedIndex];!t||t.divider||t.disabled||this.selectItem(t);break}}},this.handleDocumentMouseDown=e=>{this.open&&(this.contains(e.target)||(this.open=!1,this.render()))}}static get observedAttributes(){return["options","items","placeholder","label","value","size","placement","full-width","disabled","open","trigger-variant","trigger-icon","icon-only","show-chevron"]}get showChevron(){return"false"!==this.getAttribute("show-chevron")}set showChevron(e){this.setAttribute("show-chevron",String(e))}get parsedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return(this.getAttribute("options")||"").split(",").map(e=>e.trim()).filter(Boolean).map((e,t)=>({id:`option-${t}`,label:e}))}get options(){return this.parsedItems.map(e=>e.label||e.id)}set options(e){this.setAttribute("options",Array.isArray(e)?e.join(","):e)}get items(){return this.parsedItems}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get value(){return this.getAttribute("value")||""}set value(e){e?this.setAttribute("value",e):this.removeAttribute("value")}get open(){return this.hasAttribute("open")}set open(e){const t=this.open;this.toggleAttribute("open",e),t!==e&&this.dispatchEvent(new CustomEvent("db-open",{detail:{open:e},bubbles:!0,composed:!0}))}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get placement(){return this.getAttribute("placement")||"bottom-left"}set placement(e){this.setAttribute("placement",e)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(e){e?this.setAttribute("placeholder",e):this.removeAttribute("placeholder")}get label(){return this.getAttribute("label")||""}set label(e){e?this.setAttribute("label",e):this.removeAttribute("label")}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}connectedCallback(){requestAnimationFrame(()=>this.render()),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{this.defaultTrigger&&this.syncDefaultTriggerState(this.defaultTrigger),this.menu?.setAttribute("aria-label",this.triggerLabel())}),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.unbindTrigger()}attributeChangedCallback(e){this.isConnected&&("open"!==e||this.open||(this.focusedIndex=-1),this.render())}resolvedSize(){return n.includes(this.size)?this.size:"m"}resolvedPlacement(){return o.includes(this.placement)?this.placement:"bottom-left"}menuItemIconSize(){const e=this.resolvedSize();return"s"===e?14:"l"===e?18:16}triggerLabel(){return this.label?this.label:this.placeholder?this.placeholder:this.value?this.value:t("메뉴")}enabledItems(){return this.parsedItems.filter(e=>!e.disabled&&!e.divider)}collectTriggerChildren(){const isInternalNode=e=>"content"===e.getAttribute("slot")||e.hasAttribute("data-wc-internal")||e===this.triggerWrap||e===this.menu||e===this.defaultTrigger,e=Array.from(this.children).filter(e=>!isInternalNode(e));return e.length>0?e:Array.from(this.triggerWrap?.children||[]).filter(e=>!isInternalNode(e))}hasCustomTrigger(){return this.collectTriggerChildren().length>0}bindTrigger(){this.triggerWrap&&(this.unbindTrigger(),this.onTriggerActivate=e=>{this.disabled||this.menu?.contains(e.target)||(e.preventDefault(),e.stopPropagation(),this.toggleOpen())},this.triggerWrap.addEventListener("click",this.onTriggerActivate),this.triggerWrap.addEventListener("keydown",this.handleTriggerKeyDown))}unbindTrigger(){this.triggerWrap&&this.onTriggerActivate&&this.triggerWrap.removeEventListener("click",this.onTriggerActivate),this.triggerWrap&&this.triggerWrap.removeEventListener("keydown",this.handleTriggerKeyDown),this.onTriggerActivate=null}toggleOpen(){this.disabled||(this.open=!this.open,this.open&&requestAnimationFrame(()=>this.focusItem(0)),this.render())}triggerSignature(){return[this.resolvedSize(),this.getAttribute("trigger-variant")||"tertiary",this.hasAttribute("icon-only")?"1":"0",this.getAttribute("trigger-icon")||"",this.fullWidth?"1":"0",this.showChevron?"1":"0"].join("|")}renderDefaultTrigger(){const e=this.resolvedSize(),t=this.getAttribute("trigger-variant")||"tertiary",i=a.includes(t)?t:"tertiary",s=this.hasAttribute("icon-only"),n=this.getAttribute("trigger-icon"),o=document.createElement("db-button");if(o.setAttribute("type","button"),o.setAttribute("variant",i),o.setAttribute("size",e),o.className="designbase-wc-dropdown__trigger",o.setAttribute("aria-haspopup","menu"),o.setAttribute("aria-label",this.triggerLabel()),this.fullWidth&&o.setAttribute("full-width",""),s)o.setAttribute("icon-only",""),o.setAttribute("start-icon",n&&r(n)?n:"edit"),o.removeAttribute("end-icon");else{o.removeAttribute("icon-only"),n&&r(n)?o.setAttribute("start-icon",n):o.removeAttribute("start-icon");const e=document.createElement("span");e.className="designbase-wc-dropdown__trigger-label",e.textContent=this.triggerLabel(),o.append(e),this.showChevron&&o.setAttribute("end-icon","chevron-down")}return o}syncDefaultTriggerState(e){e.setAttribute("aria-expanded",String(this.open)),e.setAttribute("aria-label",this.triggerLabel()),e.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),this.disabled?e.setAttribute("disabled",""):e.removeAttribute("disabled");const t=e.querySelector(".designbase-wc-dropdown__trigger-label");t&&(t.textContent=this.triggerLabel())}ensureStructure(){this.triggerWrap||(this.triggerWrap=document.createElement("div"),this.triggerWrap.className="designbase-wc-dropdown__trigger-wrap",this.triggerWrap.setAttribute("data-wc-internal","")),this.menu||(this.menu=document.createElement("div"),this.menu.className="designbase-wc-dropdown__menu",this.menu.setAttribute("data-wc-internal",""),this.menu.setAttribute("role","menu"));const e=this.triggerWrap,t=this.menu;e&&t&&(this.contains(e)||this.append(e),e.contains(t)||e.append(t),Array.from(this.children).forEach(i=>{i===e||i.hasAttribute("data-wc-internal")||("content"===i.getAttribute("slot")?t.append(i):e.insertBefore(i,t))}))}renderTrigger(){const e=this.triggerWrap,t=this.menu;if(!e||!t)return;const i=this.collectTriggerChildren();if(i.length>0){this.defaultTrigger?.remove(),this.defaultTrigger=void 0;Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),i.forEach(i=>{i.setAttribute("aria-haspopup","menu"),i.setAttribute("aria-expanded",String(this.open)),i.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),e.insertBefore(i,t)})}else{Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),this.defaultTrigger&&this.triggerSignature()===this.lastTriggerSignature||(this.defaultTrigger?.remove(),this.defaultTrigger=this.renderDefaultTrigger(),this.lastTriggerSignature=this.triggerSignature(),e.insertBefore(this.defaultTrigger,t)),this.defaultTrigger&&this.syncDefaultTriggerState(this.defaultTrigger)}this.bindTrigger()}renderMenu(){const e=this.resolvedPlacement();this.menu.className=`designbase-wc-dropdown__menu designbase-wc-dropdown__menu--${e}${this.open?" designbase-wc-dropdown__menu--open":""}`,this.menu.setAttribute("aria-hidden",String(!this.open)),this.menu.setAttribute("aria-label",this.triggerLabel());const t=this.menu.querySelector(':scope > [slot="content"]');if(this.menu.setAttribute("role",t?"dialog":"menu"),t)return this.menu.inert=!this.open,this.menu.setAttribute("aria-modal","false"),this.menu.classList.add("designbase-wc-dropdown__menu--custom"),void this.triggerWrap?.querySelector("[aria-haspopup]")?.setAttribute("aria-haspopup","dialog");this.menu.inert=!1,this.menu.removeAttribute("aria-modal"),this.menu.replaceChildren();const i=this.menuItemIconSize();this.parsedItems.forEach((e,t)=>{if(e.divider){const e=document.createElement("div");return e.className="designbase-wc-dropdown__divider",e.setAttribute("role","separator"),void this.menu?.append(e)}e.id||e.label||String(t);const r=e.label||e.id,n=Boolean(e.disabled||this.disabled),o=this.focusedIndex===t,a=document.createElement("button");if(a.type="button",a.className=["designbase-wc-dropdown__item",n&&"designbase-wc-dropdown__item--disabled",o&&"designbase-wc-dropdown__item--focused"].filter(Boolean).join(" "),a.setAttribute("role","menuitem"),a.disabled=n,a.tabIndex=o?0:-1,a.dataset.index=String(t),e.icon){const t=s(e.icon,i);t.classList.add("designbase-wc-dropdown__item-icon"),a.append(t)}const d=document.createElement("span");d.className="designbase-wc-dropdown__item-label",d.textContent=r,a.append(d),a.addEventListener("click",t=>{t.stopPropagation(),this.selectItem(e)}),this.menu?.append(a)})}render(){const e=this.resolvedSize();i(this,["designbase-wc-dropdown",`designbase-wc-dropdown--${e}`,this.open&&"designbase-wc-dropdown--open",this.fullWidth&&"designbase-wc-dropdown--full-width",this.disabled&&"designbase-wc-dropdown--disabled"]),this.ensureStructure(),this.renderTrigger(),this.renderMenu()}selectItem(e){e.disabled||e.divider||(this.open=!1,this.focusedIndex=-1,this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.label||e.id,id:e.id,item:e},bubbles:!0,composed:!0})),this.render(),this.triggerWrap?.querySelector("[aria-haspopup]")?.focus())}focusItem(e){if(this.menu?.querySelector(':scope > [slot="content"]'))return void this.menu.querySelector('input:not([disabled]), button:not([disabled]), [tabindex="0"]')?.focus();const t=this.enabledItems();if(!t.length)return;const i=t[Math.max(0,Math.min(e,t.length-1))],r=this.parsedItems.indexOf(i);this.focusedIndex=r;Array.from(this.menu?.querySelectorAll(".designbase-wc-dropdown__item")||[]).forEach(e=>{const t=Number(e.dataset.index)===r;e.classList.toggle("designbase-wc-dropdown__item--focused",t),e.tabIndex=t?0:-1,t&&e.focus()})}}customElements.get("db-dropdown")||customElements.define("db-dropdown",DbDropdown);export{DbDropdown};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
declare class DbDropzone extends HTMLElement {
|
|
2
2
|
static get observedAttributes(): string[];
|
|
3
|
+
private unsubscribeLocale?;
|
|
3
4
|
private fileInput?;
|
|
4
5
|
private internalDragOver;
|
|
5
6
|
connectedCallback(): void;
|
|
6
7
|
disconnectedCallback(): void;
|
|
7
8
|
attributeChangedCallback(): void;
|
|
9
|
+
private syncLocale;
|
|
8
10
|
private ensureInput;
|
|
9
11
|
private isDisabled;
|
|
10
12
|
private isDragOver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{subscribeDbLocale as e,t}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{DROPZONE_SIZES as s,DROPZONE_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDropzone extends HTMLElement{constructor(){super(...arguments),this.internalDragOver=!1,this.handleFileInputChange=()=>{this.emitFiles(this.fileInput?.files??null),this.fileInput&&(this.fileInput.value="")},this.handleDragOver=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!0,this.syncClasses(),this.dispatchEvent(new CustomEvent("db-drag-over",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleDragLeave=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!1,this.syncClasses(),this.dispatchEvent(new CustomEvent("db-drag-leave",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleDrop=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!1,this.syncClasses(),this.emitFiles(e.dataTransfer?.files??null),this.dispatchEvent(new CustomEvent("db-drop",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleClick=e=>{this.isDisabled()||e.target.closest(".designbase-wc-dropzone__button")||(this.fileInput?.click(),this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0,detail:{event:e}})))}}static get observedAttributes(){return["locale","size","variant","show-icon","icon","image","title","description","button-text","show-button","accept","max-size","multiple","drag-over","disabled","readonly"]}connectedCallback(){this.ensureInput(),this.sync(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale()),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop),this.addEventListener("click",this.handleClick)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this.removeEventListener("click",this.handleClick)}attributeChangedCallback(){this.isConnected&&this.sync()}syncLocale(){const e=this.querySelector(":scope > .designbase-wc-dropzone__content[data-wc-internal]");if(!e)return;const i=e.querySelector(".designbase-wc-dropzone__title"),s=e.querySelector(".designbase-wc-dropzone__description"),n=e.querySelector(".designbase-wc-dropzone__button"),a=e.querySelector("img");i&&!this.getAttribute("title")&&(i.textContent=t("upload.title")),s&&!this.getAttribute("description")&&(s.textContent=this.getDescriptionText()),n&&!this.getAttribute("button-text")&&(n.textContent=t("upload.choose")),a&&(a.alt=t("upload.illustration"))}ensureInput(){this.fileInput||(this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.style.display="none",this.fileInput.setAttribute("data-wc-internal",""),this.fileInput.addEventListener("change",this.handleFileInputChange),this.append(this.fileInput))}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}isDragOver(){return this.hasAttribute("drag-over")?"false"!==this.getAttribute("drag-over"):this.internalDragOver}validateFile(e){const t=this.getAttribute("accept");if(t){const i=t.split(",").map(e=>e.trim()),s=e.type,n=`.${e.name.split(".").pop()?.toLowerCase()}`;if(!i.some(e=>e.startsWith(".")?n===e.toLowerCase():s===e||s.startsWith(e.replace("*",""))))return!1}const i=Number(this.getAttribute("max-size")||0);return!(i>0&&e.size>i)}emitFiles(e){if(!e||0===e.length)return;const t=Array.from(e).filter(e=>this.validateFile(e));t.length&&this.dispatchEvent(new CustomEvent("db-file-select",{bubbles:!0,composed:!0,detail:{files:t}}))}getDescriptionText(){const e=this.getAttribute("description");if(e)return e;const i=(this.getAttribute("accept")||"").split(",").filter(Boolean).map(e=>{const t=e.trim();return t.startsWith(".")?t.toUpperCase():t.includes("*")?t.replace("*","").toUpperCase():t});let s=i.length?i.join(", "):t("upload.allFormats");const n=Number(this.getAttribute("max-size")||0);if(n>0){const e=1024,i=["Bytes","KB","MB","GB"],a=Math.floor(Math.log(n)/Math.log(e)),r=`${parseFloat((n/e**a).toFixed(2))} ${i[a]}`;s+=t("upload.maximum").replace("{size}",r)}return s}collectChildren(){return Array.from(this.children).filter(e=>e!==this.fileInput&&!e.hasAttribute("data-wc-internal"))}syncClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",i=s.includes(e)?e:"m",a=n.includes(t)?t:"default";this.className=["designbase-wc-dropzone",`designbase-wc-dropzone--size-${i}`,`designbase-wc-dropzone--variant-${a}`,this.isDragOver()&&"designbase-wc-dropzone--drag-over",this.hasAttribute("disabled")&&"designbase-wc-dropzone--disabled",this.hasAttribute("readonly")&&"designbase-wc-dropzone--readonly"].filter(Boolean).join(" ")}sync(){this.ensureInput(),this.syncClasses();const e=this.getAttribute("accept"),n=this.hasAttribute("multiple");this.fileInput&&(e?this.fileInput.setAttribute("accept",e):this.fileInput.removeAttribute("accept"),this.fileInput.toggleAttribute("multiple",n),this.fileInput.disabled=this.isDisabled());const a=this.collectChildren(),r=this.querySelector(":scope > .designbase-wc-dropzone__content[data-wc-internal]");if(a.length)return void r?.remove();let o=r;o||(o=document.createElement("div"),o.className="designbase-wc-dropzone__content",o.setAttribute("data-wc-internal",""),this.append(o)),o.replaceChildren();const l=this.getAttribute("size")||"m",d=s.includes(l)?l:"m",c=this.getAttribute("image"),h="false"!==this.getAttribute("show-icon"),u=this.getAttribute("icon")||"gallery",p=this.getAttribute("title")||t("upload.title"),b=this.getDescriptionText(),g=this.hasAttribute("show-button"),m=this.getAttribute("button-text")||t("upload.choose");if(c){const e=document.createElement("div");e.className="designbase-wc-dropzone__image";const i=document.createElement("img");i.src=c,i.alt=t("upload.illustration"),e.append(i),o.append(e)}else if(h){const e=document.createElement("div");e.className="designbase-wc-dropzone__icon";const t="s"===d?32:"l"===d?56:48;e.append(i(u,t)),o.append(e)}if(p){const e=document.createElement("div");e.className="designbase-wc-dropzone__title",e.textContent=p,o.append(e)}if(b){const e=document.createElement("div");e.className="designbase-wc-dropzone__description",e.textContent=b,o.append(e)}if(g){const e=document.createElement("button");e.type="button",e.className="designbase-wc-dropzone__button",e.textContent=m,e.disabled=this.isDisabled(),e.addEventListener("click",e=>{e.stopPropagation(),this.isDisabled()||this.fileInput?.click()}),o.append(e)}}}customElements.get("db-dropzone")||customElements.define("db-dropzone",DbDropzone);export{DbDropzone};
|
|
@@ -4,34 +4,54 @@ import './db-otp-input.js';
|
|
|
4
4
|
import { EMAIL_VERIFY_SIZES } from '../ui-contracts/dist/components.d.js';
|
|
5
5
|
|
|
6
6
|
type Size = (typeof EMAIL_VERIFY_SIZES)[number];
|
|
7
|
+
type Step = 'email' | 'code' | 'sent' | 'verified';
|
|
7
8
|
declare class DbEmailVerify extends HTMLElement {
|
|
8
9
|
static get observedAttributes(): string[];
|
|
9
10
|
private built;
|
|
11
|
+
private unsubscribeLocale?;
|
|
10
12
|
private timerId;
|
|
13
|
+
/** 인증번호 유효 시간(초) — code 모드에서만 쓴다 */
|
|
11
14
|
private remaining;
|
|
15
|
+
/** 재전송 버튼이 다시 열리기까지 남은 시간(초) */
|
|
16
|
+
private cooldownLeft;
|
|
17
|
+
private expired;
|
|
18
|
+
private eyebrowEl;
|
|
19
|
+
private headerEl;
|
|
20
|
+
private titleEl;
|
|
21
|
+
private descEl;
|
|
12
22
|
private emailInput;
|
|
13
23
|
private sendBtn;
|
|
14
24
|
private otpInput;
|
|
15
25
|
private timerEl;
|
|
16
|
-
private
|
|
26
|
+
private expiredEl;
|
|
27
|
+
private codeResendBtn;
|
|
28
|
+
private codeChangeBtn;
|
|
17
29
|
private verifyBtn;
|
|
18
30
|
private confirmBtn;
|
|
31
|
+
private doneBtn;
|
|
32
|
+
private sentResendBtn;
|
|
33
|
+
private sentChangeBtn;
|
|
34
|
+
private sentDescEl;
|
|
35
|
+
private verifiedDescEl;
|
|
19
36
|
private codeBlock;
|
|
20
|
-
private
|
|
37
|
+
private sentBlock;
|
|
21
38
|
private verifiedBlock;
|
|
22
39
|
private emailRow;
|
|
23
40
|
private errorEl;
|
|
24
|
-
private closeBtn
|
|
41
|
+
private closeBtn;
|
|
25
42
|
get mode(): 'code' | 'confirm';
|
|
26
43
|
set mode(v: 'code' | 'confirm');
|
|
27
44
|
get size(): Size;
|
|
28
45
|
set size(v: Size);
|
|
29
|
-
get step():
|
|
30
|
-
set step(v:
|
|
46
|
+
get step(): Step;
|
|
47
|
+
set step(v: Step);
|
|
31
48
|
get email(): string;
|
|
32
49
|
set email(v: string);
|
|
33
50
|
get countdown(): number;
|
|
34
51
|
set countdown(v: number);
|
|
52
|
+
/** 재전송을 다시 누를 수 있기까지 기다리는 시간(초). 기본 30초. 0이면 바로 누를 수 있다. */
|
|
53
|
+
get resendCooldown(): number;
|
|
54
|
+
set resendCooldown(v: number);
|
|
35
55
|
connectedCallback(): void;
|
|
36
56
|
disconnectedCallback(): void;
|
|
37
57
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
@@ -40,14 +60,24 @@ declare class DbEmailVerify extends HTMLElement {
|
|
|
40
60
|
restartCountdown(): void;
|
|
41
61
|
markSent(): void;
|
|
42
62
|
markVerified(): void;
|
|
63
|
+
/** 이메일 입력 단계로 돌아갑니다 (입력한 코드는 지웁니다). */
|
|
64
|
+
editEmail(): void;
|
|
65
|
+
private startTimersForStep;
|
|
43
66
|
private clearTimer;
|
|
44
|
-
private
|
|
67
|
+
private startTimers;
|
|
45
68
|
private renderTimer;
|
|
69
|
+
private syncVerifyDisabled;
|
|
70
|
+
private emit;
|
|
71
|
+
private handleResend;
|
|
72
|
+
private handleChangeEmail;
|
|
46
73
|
private build;
|
|
74
|
+
private buildFooter;
|
|
47
75
|
private sync;
|
|
48
76
|
private isEmailValid;
|
|
77
|
+
private requestSend;
|
|
49
78
|
private requestVerify;
|
|
50
|
-
|
|
79
|
+
/** 번역 문장 안의 {0} 자리에 이메일을 굵게 넣는다 — 언어마다 어순이 달라 조각내 번역하지 않는다. */
|
|
80
|
+
private setTextWithEmail;
|
|
51
81
|
}
|
|
52
82
|
declare global {
|
|
53
83
|
interface HTMLElementTagNameMap {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{EMAIL_VERIFY_SIZES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class 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 s(this.getAttribute("size"),n,"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 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-email-verify";this.replaceChildren();const s=el("div",`${t}__shell`),n=el("div",`${t}__top`),r=el("span",`${t}__eyebrow`);r.dataset.role="eyebrow",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.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),n.append(r,this.closeBtn);const o=el("div",`${t}__header`),d=el("h3",`${t}__title`);d.dataset.role="title";const a=el("p",`${t}__description`);a.dataset.role="description",o.append(d,a),this.emailRow=el("div",`${t}__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",`${t}__code`);const l=el("div",`${t}__code-head`),h=el("span",`${t}__code-label`);h.textContent=e("인증 코드"),this.timerEl=el("span",`${t}__timer`),l.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,email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const c=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:{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()}),c.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(l,this.otpInput,c),this.confirmBlock=el("div",`${t}__confirm`);const m=el("div",`${t}__confirm-icon`);m.append(i("mail",40));const u=el("span",`${t}__confirm-badge`);u.append(i("circle-checked",16)),m.append(u);const b=el("h4",`${t}__confirm-title`);b.dataset.role="confirm-title";const p=el("p",`${t}__confirm-desc`);p.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 f=el("button",`${t}__resend`);f.type="button",f.dataset.role="confirm-resend",f.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0}))}),this.confirmBlock.append(m,b,p,this.confirmBtn,f),this.verifiedBlock=el("div",`${t}__confirm`);const v=el("div",`${t}__confirm-icon`);v.append(i("circle-checked",40));const g=el("h4",`${t}__confirm-title`);g.textContent=e("이메일 인증 완료");const A=el("p",`${t}__confirm-desc`);A.dataset.role="verified-desc",this.verifiedBlock.append(v,g,A),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0,s.append(n,o,this.emailRow,this.codeBlock,this.confirmBlock,this.verifiedBlock,this.errorEl),this.append(s)}sync(){const t="designbase-wc-email-verify",i=this.size,s=this.mode,n=this.step,r=this.hasAttribute("disabled"),o=this.getAttribute("code-length")||"6",d=this.email;this.className=[t,`${t}--${i}`,`${t}--mode-${s}`,`${t}--step-${n}`,r&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" "),this.emailInput?.toggleAttribute("error",this.hasAttribute("error"));this.querySelector('[data-role="eyebrow"]').textContent="confirm"===s?"회원가입":"이메일 인증";const a=this.querySelector('[data-role="title"]'),l=this.querySelector('[data-role="description"]');a.textContent=this.getAttribute("title")||("confirm"===s?"이메일을 확인해 주세요":"이메일 인증");const h=this.getAttribute("description");h?l.textContent=h:"confirm"===s?this.setEmphasizedText(l,"",d||"your@email.com"," 으로 인증 링크를 보냈어요."):this.setEmphasizedText(l,"인증 코드를 ",d||"이메일"," 로 보내 드릴게요."),this.closeBtn&&(this.closeBtn.hidden=!this.hasAttribute("closable")),this.emailInput.value=d,this.emailInput.setAttribute("size",i),this.emailInput.toggleAttribute("disabled",r||"code"===n||"sent"===n||"verified"===n),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||("confirm"===s?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",r||!this.isEmailValid()||"email"!==n),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"!==n),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",r||"code"!==n||(this.getAttribute("code")||"").length!==Number(o)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying"));const c=this.querySelector('[data-role="confirm-title"]'),m=this.querySelector('[data-role="confirm-desc"]');c.textContent=e("메일함을 확인해 주세요!"),this.setEmphasizedText(m,"",d||"your@email.com"," 으로 보낸 링크를 클릭하면 인증이 완료됩니다."),this.confirmBtn.setAttribute("size",i),this.confirmBtn.textContent=this.getAttribute("confirm-label")||"확인";const u=this.querySelector('[data-role="confirm-resend"]');u&&(u.textContent=e("메일 다시 보내기"));const b=this.querySelector('[data-role="verified-desc"]');this.setEmphasizedText(b,"",d||"your@email.com"," 주소가 인증되었습니다."),this.emailRow.hidden="confirm"===s&&("sent"===n||"verified"===n)||"code"===s&&"verified"===n,this.codeBlock.hidden=!("code"===s&&"code"===n),this.confirmBlock.hidden=!("confirm"===s&&("sent"===n||"verified"===n)),this.verifiedBlock.hidden=!("code"===s&&"verified"===n);const p=this.getAttribute("error-message")||"";this.errorEl.textContent=p,this.errorEl.hidden=!this.hasAttribute("error")||!p}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{subscribeDbLocale as t,dbText as e,dbFormat as i}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{EMAIL_VERIFY_SIZES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}function textButton(t,e){const i=el("button",t);return i.type="button",i.addEventListener("click",()=>{i.disabled||e()}),i}class DbEmailVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0,this.cooldownLeft=0,this.expired=!1}static get observedAttributes(){return["mode","email","code","step","size","disabled","error","error-message","countdown","resend-cooldown","eyebrow","title","description","send-label","resend-label","verify-label","confirm-label","done-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 n(this.getAttribute("size"),r,"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))}get resendCooldown(){const t=this.getAttribute("resend-cooldown"),e=Number(t??30);return Number.isFinite(e)&&e>=0?e:30}set resendCooldown(t){this.setAttribute("resend-cooldown",String(t))}connectedCallback(){this.build(),this.sync(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>{this.closeBtn.setAttribute("aria-label",e("닫기")),this.sync()}),this.startTimersForStep()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&("step"!==t&&"mode"!==t||e===i||this.startTimersForStep(),this.sync())}startCodeStep(){"code"!==this.mode&&(this.mode="code"),"code"===this.step?this.startTimers():this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"!==this.step&&"sent"!==this.step||this.startTimers()}markSent(){this.step="sent"}markVerified(){this.step="verified"}editEmail(){this.removeAttribute("code"),this.step="email",requestAnimationFrame(()=>this.emailInput?.focus?.())}startTimersForStep(){const t=this.step;"code"===this.mode&&"code"===t||"confirm"===this.mode&&"sent"===t?this.startTimers():this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0,this.cooldownLeft=0,this.expired=!1}startTimers(){this.clearTimer();const t="code"===this.mode;this.remaining=t?this.countdown:0,this.cooldownLeft=t?Math.min(this.resendCooldown,this.countdown):this.resendCooldown,this.renderTimer(),this.remaining<=0&&this.cooldownLeft<=0||(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.dispatchEvent(new CustomEvent("db-countdown-complete",{bubbles:!0,composed:!0})))),this.renderTimer(),this.remaining<=0&&this.cooldownLeft<=0&&this.timerId&&(clearInterval(this.timerId),this.timerId=null)},1e3))}renderTimer(){if(!this.built)return;const t=Math.max(0,Math.floor(this.remaining/60)),s=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(s).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",i("남은 시간 {0}분 {1}초",[t,s])),this.timerEl.classList.toggle("designbase-wc-email-verify__timer--expired",this.expired),this.expiredEl.hidden=!this.expired;const n=this.hasAttribute("disabled"),r=this.cooldownLeft>0,o=this.getAttribute("resend-label")||e("재전송"),l=r?i("재전송 ({0}초)",[this.cooldownLeft]):o;for(const t of[this.codeResendBtn,this.sentResendBtn])t.textContent=l,t.disabled=r||n;this.syncVerifyDisabled()}syncVerifyDisabled(){const t=Number(this.getAttribute("code-length")||6);this.verifyBtn.toggleAttribute("disabled",this.hasAttribute("disabled")||"code"!==this.step||this.expired||(this.getAttribute("code")||"").length!==t)}emit(t,e={}){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}handleResend(){this.emit("db-resend",{email:this.email,mode:this.mode}),this.hasAttribute("manual")||(this.removeAttribute("code"),this.startTimers())}handleChangeEmail(){this.emit("db-change-email",{email:this.email}),this.hasAttribute("manual")||this.editEmail()}build(){if(this.built)return;this.built=!0;const t="designbase-wc-email-verify";this.replaceChildren();const i=el("div",`${t}__shell`);this.closeBtn=el("button",`${t}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label",e("닫기")),this.closeBtn.append(s("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.emailRow=el("div",`${t}__email-row`),this.emailInput=document.createElement("db-input"),this.emailInput.setAttribute("type","email"),this.emailInput.setAttribute("placeholder","name@example.com"),this.emailInput.setAttribute("autocomplete","email"),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.emit("db-email-change",{email:e})}),this.emailInput.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()}),this.emailRow.append(this.emailInput,this.sendBtn),this.codeBlock=el("div",`${t}__code`);const n=el("div",`${t}__code-head`),r=el("span",`${t}__code-label`);r.dataset.role="code-label",this.timerEl=el("span",`${t}__timer`),this.timerEl.setAttribute("role","timer"),n.append(r,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,email:this.email}),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.codeResendBtn=textButton(`${t}__link`,()=>this.handleResend()),this.codeChangeBtn=textButton(`${t}__link ${t}__link--muted`,()=>this.handleChangeEmail());const o=this.buildFooter(this.codeResendBtn,this.codeChangeBtn);this.codeBlock.append(n,this.otpInput,this.expiredEl,this.verifyBtn,o),this.sentBlock=el("div",`${t}__result`);const l=el("div",`${t}__result-icon`);l.append(s("mail",36));const h=el("h3",`${t}__result-title`);h.dataset.role="sent-title",this.sentDescEl=el("p",`${t}__result-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.emit("db-confirm",{email:this.email})}),this.sentResendBtn=textButton(`${t}__link`,()=>this.handleResend()),this.sentChangeBtn=textButton(`${t}__link ${t}__link--muted`,()=>this.handleChangeEmail());const d=this.buildFooter(this.sentResendBtn,this.sentChangeBtn);this.sentBlock.append(l,h,this.sentDescEl,this.confirmBtn,d),this.verifiedBlock=el("div",`${t}__result ${t}__result--success`);const a=el("div",`${t}__result-icon`);a.append(s("circle-checked",36));const c=el("h3",`${t}__result-title`);c.dataset.role="verified-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",{email:this.email})}),this.verifiedBlock.append(a,c,this.verifiedDescEl,this.doneBtn),this.errorEl=el("p",`${t}__error`),this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,i.append(this.closeBtn,this.headerEl,this.emailRow,this.errorEl,this.codeBlock,this.sentBlock,this.verifiedBlock),this.append(i)}buildFooter(t,e){const i="designbase-wc-email-verify",s=el("div",`${i}__footer`),n=el("span",`${i}__footer-resend`),r=el("span",`${i}__footer-hint`);return r.dataset.role="resend-hint",n.append(r,t),s.append(n,e),s}sync(){const t="designbase-wc-email-verify",i=this.size,s=this.mode,n=this.step,r=this.hasAttribute("disabled"),o=this.getAttribute("code-length")||"6",l=this.email,h=l||"your@email.com",d="confirm"===s&&"code"===n?"email":"code"===s&&"sent"===n?"code":n,a="sent"===d||"verified"===d;this.className=[t,`${t}--${i}`,`${t}--mode-${s}`,`${t}--step-${d}`,this.hasAttribute("closable")&&`${t}--closable`,r&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" "),this.emailInput.toggleAttribute("error",this.hasAttribute("error")&&"email"===d),this.closeBtn.hidden=!this.hasAttribute("closable"),this.headerEl.hidden=a;const c=this.getAttribute("eyebrow")||"";this.eyebrowEl.textContent=c,this.eyebrowEl.hidden=!c,"code"===d?(this.titleEl.textContent=e("인증번호를 입력해 주세요"),this.setTextWithEmail(this.descEl,"{0} 주소로 {1}자리 인증번호를 보냈어요.",h,[o])):(this.titleEl.textContent=this.getAttribute("title")||e("이메일 인증"),this.descEl.textContent=this.getAttribute("description")||e("confirm"===s?"인증받을 이메일 주소를 입력해 주세요. 입력한 주소로 인증 링크를 보내 드려요.":"인증받을 이메일 주소를 입력해 주세요. 입력한 주소로 인증번호를 보내 드려요.")),this.emailRow.hidden="email"!==d,this.emailInput.setAttribute("label",e("이메일 주소")),this.emailInput.value=l,this.emailInput.setAttribute("size",i),this.emailInput.toggleAttribute("disabled",r),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||e("confirm"===s?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",r||!this.isEmailValid()),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.codeBlock.hidden="code"!==d;this.querySelector('[data-role="code-label"]').textContent=e("인증번호"),this.otpInput.setAttribute("length",o),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",r||"code"!==d||this.expired),this.otpInput.toggleAttribute("error",this.hasAttribute("error")&&"code"===d),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.sentBlock.hidden="sent"!==d,this.querySelector('[data-role="sent-title"]').textContent=e("메일함을 확인해 주세요"),this.setTextWithEmail(this.sentDescEl,"{0} 주소로 인증 링크를 보냈어요. 메일의 링크를 누르면 인증이 완료돼요.",h),this.confirmBtn.setAttribute("size",i),this.confirmBtn.textContent=this.getAttribute("confirm-label")||e("확인"),this.verifiedBlock.hidden="verified"!==d,this.querySelector('[data-role="verified-title"]').textContent=e("이메일 인증 완료"),this.setTextWithEmail(this.verifiedDescEl,"{0} 주소가 인증되었어요.",h),this.doneBtn.setAttribute("size",i),this.doneBtn.textContent=this.getAttribute("done-label")||e("확인"),this.querySelectorAll('[data-role="resend-hint"]').forEach(t=>{t.textContent=e("메일을 받지 못하셨나요?")});for(const t of[this.codeChangeBtn,this.sentChangeBtn])t.textContent=e("이메일 변경"),t.disabled=r;const m=this.getAttribute("error-message")||"";this.errorEl.textContent=m,this.errorEl.hidden=!this.hasAttribute("error")||!m||a;const u="code"===d?this.otpInput:this.emailRow;this.errorEl.previousElementSibling!==u&&u.after(this.errorEl),this.renderTimer()}isEmailValid(){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email.trim())}requestSend(){("email"===this.step||"confirm"===this.mode&&"code"===this.step)&&(this.hasAttribute("disabled")||this.hasAttribute("sending")||!this.isEmailValid()||(this.emit("db-send-code",{email:this.email,mode:this.mode}),this.hasAttribute("manual")||("confirm"===this.mode?this.markSent():this.startCodeStep())))}requestVerify(){const t=(this.getAttribute("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",{email:this.email,code:t})}setTextWithEmail(t,i,s,n=[]){const r=e(i).replace(/\{(\d+)\}/g,(t,e)=>"0"===e?t:String(n[Number(e)-1]??"")),[o,l=""]=r.split("{0}"),h=document.createElement("strong");h.textContent=s,t.replaceChildren(document.createTextNode(o),h,document.createTextNode(l))}}customElements.get("db-email-verify")||customElements.define("db-email-verify",DbEmailVerify);export{DbEmailVerify};
|
|
@@ -8,12 +8,14 @@ type UploadFile = {
|
|
|
8
8
|
uploadedAt?: Date;
|
|
9
9
|
};
|
|
10
10
|
declare class DbFileUploader extends HTMLElement {
|
|
11
|
+
private unsubscribeLocale?;
|
|
11
12
|
static get observedAttributes(): string[];
|
|
12
13
|
private dropzone?;
|
|
13
14
|
private uploadedFiles;
|
|
14
15
|
private uploadIntervals;
|
|
15
16
|
connectedCallback(): void;
|
|
16
17
|
disconnectedCallback(): void;
|
|
18
|
+
private syncLocale;
|
|
17
19
|
attributeChangedCallback(): void;
|
|
18
20
|
private isDisabled;
|
|
19
21
|
private ensureDropzone;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{subscribeDbLocale as e,t}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{FILE_UPLOADER_SIZES as i,FILE_UPLOADER_VARIANTS as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbFileUploader extends HTMLElement{constructor(){super(...arguments),this.uploadedFiles=[],this.uploadIntervals=new Map,this.handleFileSelect=e=>{if(this.isDisabled())return;const t=e.detail,s=t?.files??[];if(!s.length)return;const i=s.map(e=>({file:e,id:`${Date.now()}-${Math.random()}`,status:"pending",progress:0}));this.hasAttribute("multiple")?this.uploadedFiles=[...this.uploadedFiles,...i]:this.uploadedFiles=i,this.dispatchEvent(new CustomEvent("db-upload",{bubbles:!0,composed:!0,detail:{files:i}})),this.simulateUpload(i),this.renderFileList()},this.handleRemove=e=>{if(this.isDisabled())return;const t=this.uploadIntervals.get(e);t&&(clearInterval(t),this.uploadIntervals.delete(e)),this.uploadedFiles=this.uploadedFiles.filter(t=>t.id!==e),this.dispatchEvent(new CustomEvent("db-remove",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.renderFileList()},this.handleRetry=e=>{if(this.isDisabled())return;const t=this.uploadedFiles.find(t=>t.id===e);t&&(this.updateFile(e,{status:"pending",progress:0,error:void 0}),this.dispatchEvent(new CustomEvent("db-retry",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.simulateUpload([t]),this.renderFileList())}}static get observedAttributes(){return["locale","size","variant","accept","max-size","multiple","show-file-list","show-progress","disabled","readonly"]}connectedCallback(){this.ensureDropzone(),this.sync(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale()),this.dropzone?.addEventListener("db-file-select",this.handleFileSelect)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.dropzone?.removeEventListener("db-file-select",this.handleFileSelect),this.uploadIntervals.forEach(e=>clearInterval(e)),this.uploadIntervals.clear()}syncLocale(){const e=this.querySelector(":scope > .designbase-wc-file-uploader__file-list .designbase-wc-file-uploader__file-list-title");e&&(e.textContent=t("upload.files").replace("{count}",String(this.uploadedFiles.length))),this.querySelectorAll(":scope > .designbase-wc-file-uploader__file-list .designbase-wc-file-uploader__retry-button").forEach(e=>{e.textContent=t("upload.retry")}),this.querySelectorAll(":scope > .designbase-wc-file-uploader__file-list .designbase-wc-file-uploader__remove-button").forEach(e=>{e.textContent=t("upload.remove")})}attributeChangedCallback(){this.isConnected&&this.sync()}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}ensureDropzone(){this.dropzone||(this.dropzone=document.createElement("db-dropzone"),this.dropzone.setAttribute("data-wc-internal",""),this.prepend(this.dropzone))}formatFileSize(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return`${parseFloat((e/1024**t).toFixed(2))} ${["Bytes","KB","MB","GB"][t]}`}simulateUpload(e){e.forEach((e,t)=>{this.updateFile(e.id,{status:"uploading",progress:0});let s=0;const i=setInterval(()=>{if(s+=20*Math.random(),s>=100)return s=100,clearInterval(i),this.uploadIntervals.delete(e.id),this.updateFile(e.id,{status:"success",progress:100}),void this.renderFileList();this.updateFile(e.id,{progress:s}),this.renderFileList()},100+50*t);this.uploadIntervals.set(e.id,i)})}updateFile(e,t){this.uploadedFiles=this.uploadedFiles.map(s=>s.id===e?{...s,...t}:s)}sync(){if(this.ensureDropzone(),!this.dropzone)return;const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",s=i.includes(e)?e:"m",a=l.includes(t)?t:"default";this.className=["designbase-wc-file-uploader",`designbase-wc-file-uploader--size-${s}`,`designbase-wc-file-uploader--variant-${a}`,this.hasAttribute("disabled")&&"designbase-wc-file-uploader--disabled",this.hasAttribute("readonly")&&"designbase-wc-file-uploader--readonly"].filter(Boolean).join(" "),this.dropzone.setAttribute("size",s),this.dropzone.setAttribute("variant",a),this.getAttribute("accept")?this.dropzone.setAttribute("accept",this.getAttribute("accept")):this.dropzone.removeAttribute("accept"),this.getAttribute("max-size")?this.dropzone.setAttribute("max-size",this.getAttribute("max-size")):this.dropzone.removeAttribute("max-size"),this.dropzone.toggleAttribute("multiple",this.hasAttribute("multiple")),this.dropzone.toggleAttribute("disabled",this.hasAttribute("disabled")),this.dropzone.toggleAttribute("readonly",this.hasAttribute("readonly")),this.renderFileList()}renderStatusIcon(e){if("uploading"===e){const e=document.createElement("db-spinner");return e.setAttribute("type","circular"),e.setAttribute("size","s"),e}return s("success"===e?"done":"error"===e?"error-filled":"gallery",20)}renderFileList(){const e=!this.hasAttribute("show-file-list")||"false"!==this.getAttribute("show-file-list"),s=!this.hasAttribute("show-progress")||"false"!==this.getAttribute("show-progress");if(this.querySelector(":scope > .designbase-wc-file-uploader__file-list")?.remove(),!e||!this.uploadedFiles.length)return;const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-list";const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-list-title",l.textContent=t("upload.files").replace("{count}",String(this.uploadedFiles.length)),i.append(l);const a=document.createElement("div");a.className="designbase-wc-file-uploader__file-items",this.uploadedFiles.forEach(e=>{const i=document.createElement("div");i.className=`designbase-wc-file-uploader__file-item designbase-wc-file-uploader__file-item--${e.status}`;const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-info";const r=document.createElement("div");r.className="designbase-wc-file-uploader__file-icon",r.append(this.renderStatusIcon(e.status));const d=document.createElement("div");d.className="designbase-wc-file-uploader__file-details";const o=document.createElement("div");o.className="designbase-wc-file-uploader__file-name",o.textContent=e.file.name;const n=document.createElement("div");if(n.className="designbase-wc-file-uploader__file-size",n.textContent=this.formatFileSize(e.file.size),d.append(o,n),e.error){const t=document.createElement("div");t.className="designbase-wc-file-uploader__file-error",t.textContent=e.error,d.append(t)}if(l.append(r,d),i.append(l),s&&"uploading"===e.status){const t=document.createElement("div");t.className="designbase-wc-file-uploader__progress";const s=document.createElement("db-progressbar");s.setAttribute("value",String(Math.round(e.progress||0))),s.setAttribute("size","s"),s.setAttribute("variant","primary"),s.setAttribute("bar-style","solid"),s.setAttribute("show-label",""),s.setAttribute("label-position","inside"),s.setAttribute("full-width",""),t.append(s),i.append(t)}const u=document.createElement("div");if(u.className="designbase-wc-file-uploader__file-actions","error"===e.status){const s=document.createElement("button");s.type="button",s.className="designbase-wc-file-uploader__retry-button",s.textContent=t("upload.retry"),s.disabled=this.isDisabled(),s.addEventListener("click",()=>this.handleRetry(e.id)),u.append(s)}const c=document.createElement("button");c.type="button",c.className="designbase-wc-file-uploader__remove-button",c.textContent=t("upload.remove"),c.disabled=this.isDisabled(),c.addEventListener("click",()=>this.handleRemove(e.id)),u.append(c),i.append(u),a.append(i)}),i.append(a),this.append(i)}}customElements.get("db-file-uploader")||customElements.define("db-file-uploader",DbFileUploader);export{DbFileUploader};
|
|
@@ -18,7 +18,7 @@ declare class DbFloatingActionButton extends DbButton {
|
|
|
18
18
|
set collapseThreshold(value: number);
|
|
19
19
|
connectedCallback(): void;
|
|
20
20
|
disconnectedCallback(): void;
|
|
21
|
-
attributeChangedCallback(name?: string): void;
|
|
21
|
+
attributeChangedCallback(name?: string, oldValue?: string | null, value?: string | null): void;
|
|
22
22
|
private syncFab;
|
|
23
23
|
private measureLabel;
|
|
24
24
|
private unbindScroll;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DbButton as t}from"./db-button.js";class DbFloatingActionButton extends t{constructor(){super(...arguments),this.scrollRoot=null,this.lastScroll=0,this.scrollCollapsed=!1,this.measureLabel=()=>{const t=this.querySelector(".designbase-wc-fab__label-text");this.style.setProperty("--db-fab-label-width",`${t?.scrollWidth||0}px`)},this.onScroll=()=>{const t=this.scrollPosition(),e=t-this.lastScroll;if(t<=this.collapseThreshold)this.scrollCollapsed=!1;else if(e>4)this.scrollCollapsed=!0;else{if(!(e<-4))return;this.scrollCollapsed=!1}this.lastScroll=t,this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed)}}static get observedAttributes(){return[...super.observedAttributes,"icon","label","collapsed","collapse-on-scroll","scroll-target","collapse-threshold"]}get label(){return this.getAttribute("label")||""}set label(t){this.setAttribute("label",t)}get collapsed(){return this.hasAttribute("collapsed")}set collapsed(t){this.toggleAttribute("collapsed",t)}get collapseOnScroll(){return this.hasAttribute("collapse-on-scroll")}set collapseOnScroll(t){this.toggleAttribute("collapse-on-scroll",t)}get collapseThreshold(){const t=Number(this.getAttribute("collapse-threshold")??24);return Number.isFinite(t)?Math.max(0,t):24}set collapseThreshold(t){this.setAttribute("collapse-threshold",String(t))}connectedCallback(){this.hasAttribute("radius")||(this.radius="pill"),this.syncFab(),super.connectedCallback(),this.labelObserver=new ResizeObserver(this.measureLabel);const t=this.querySelector(".designbase-wc-fab__label-text");t&&this.labelObserver.observe(t),this.bindScroll()}disconnectedCallback(){super.disconnectedCallback(),this.unbindScroll(),this.labelObserver?.disconnect(),this.labelObserver=void 0}attributeChangedCallback(t){super.attributeChangedCallback(),this.syncFab(),this.isConnected&&["collapse-on-scroll","scroll-target","collapse-threshold"].includes(t||"")&&this.bindScroll()}syncFab(){this.classList.add("designbase-wc-fab");const t=this.getAttribute("icon");if(t)this.mappedIcon=t,this.getAttribute("start-icon")!==t&&this.setAttribute("start-icon",t);else if(this.mappedIcon){const t=this.mappedIcon;this.mappedIcon=void 0,this.getAttribute("start-icon")===t&&this.removeAttribute("start-icon")}let e=this.querySelector(":scope > .designbase-wc-fab__label");if(!e){e=document.createElement("span"),e.className="designbase-wc-fab__label",e.setAttribute("aria-hidden","true");const t=document.createElement("span");t.className="designbase-wc-fab__label-text",e.append(t),this.append(e)}const l=e.firstElementChild;l.textContent!==this.label&&(l.textContent=this.label),!this.label||this.hasAttribute("aria-label")&&this.getAttribute("data-fab-auto-label")!==this.getAttribute("aria-label")||(this.setAttribute("aria-label",this.label),this.setAttribute("data-fab-auto-label",this.label)),this.hasAttribute("aria-label")||(this.setAttribute("aria-label","Floating action button"),this.setAttribute("data-fab-auto-label","Floating action button")),this.classList.toggle("designbase-wc-fab--extended",Boolean(this.label)),this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed),this.measureLabel()}unbindScroll(){this.scrollRoot?.removeEventListener("scroll",this.onScroll),this.scrollRoot=null}bindScroll(){if(this.unbindScroll(),this.scrollCollapsed=!1,this.collapseOnScroll){let t=null;const e=this.getAttribute("scroll-target");if(e)try{t=document.querySelector(e)}catch{}else for(let e=this.parentElement;e;e=e.parentElement)if(/(auto|scroll)/.test(getComputedStyle(e).overflowY)){t=e;break}this.scrollRoot=t||window,this.lastScroll=this.scrollPosition(),this.scrollCollapsed=this.lastScroll>this.collapseThreshold,this.scrollRoot.addEventListener("scroll",this.onScroll,{passive:!0})}this.syncFab()}scrollPosition(){return Math.max(0,this.scrollRoot instanceof HTMLElement?this.scrollRoot.scrollTop:window.scrollY)}}customElements.get("db-floating-action-button")||customElements.define("db-floating-action-button",DbFloatingActionButton);export{DbFloatingActionButton};
|
|
1
|
+
import{DbButton as t}from"./db-button.js";class DbFloatingActionButton extends t{constructor(){super(...arguments),this.scrollRoot=null,this.lastScroll=0,this.scrollCollapsed=!1,this.measureLabel=()=>{const t=this.querySelector(".designbase-wc-fab__label-text");this.style.setProperty("--db-fab-label-width",`${t?.scrollWidth||0}px`)},this.onScroll=()=>{const t=this.scrollPosition(),e=t-this.lastScroll;if(t<=this.collapseThreshold)this.scrollCollapsed=!1;else if(e>4)this.scrollCollapsed=!0;else{if(!(e<-4))return;this.scrollCollapsed=!1}this.lastScroll=t,this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed)}}static get observedAttributes(){return[...super.observedAttributes,"icon","label","collapsed","collapse-on-scroll","scroll-target","collapse-threshold"]}get label(){return this.getAttribute("label")||""}set label(t){this.setAttribute("label",t)}get collapsed(){return this.hasAttribute("collapsed")}set collapsed(t){this.toggleAttribute("collapsed",t)}get collapseOnScroll(){return this.hasAttribute("collapse-on-scroll")}set collapseOnScroll(t){this.toggleAttribute("collapse-on-scroll",t)}get collapseThreshold(){const t=Number(this.getAttribute("collapse-threshold")??24);return Number.isFinite(t)?Math.max(0,t):24}set collapseThreshold(t){this.setAttribute("collapse-threshold",String(t))}connectedCallback(){this.hasAttribute("radius")||(this.radius="pill"),this.syncFab(),super.connectedCallback(),this.labelObserver=new ResizeObserver(this.measureLabel);const t=this.querySelector(".designbase-wc-fab__label-text");t&&this.labelObserver.observe(t),this.bindScroll()}disconnectedCallback(){super.disconnectedCallback(),this.unbindScroll(),this.labelObserver?.disconnect(),this.labelObserver=void 0}attributeChangedCallback(t,e,l){t&&e===l||(super.attributeChangedCallback(t,e,l),this.syncFab(),this.isConnected&&["collapse-on-scroll","scroll-target","collapse-threshold"].includes(t||"")&&this.bindScroll())}syncFab(){this.classList.add("designbase-wc-fab");const t=this.getAttribute("icon");if(t)this.mappedIcon=t,this.getAttribute("start-icon")!==t&&this.setAttribute("start-icon",t);else if(this.mappedIcon){const t=this.mappedIcon;this.mappedIcon=void 0,this.getAttribute("start-icon")===t&&this.removeAttribute("start-icon")}let e=this.querySelector(":scope > .designbase-wc-fab__label");if(!e){e=document.createElement("span"),e.className="designbase-wc-fab__label",e.setAttribute("aria-hidden","true");const t=document.createElement("span");t.className="designbase-wc-fab__label-text",e.append(t),this.append(e)}const l=e.firstElementChild;l.textContent!==this.label&&(l.textContent=this.label),!this.label||this.hasAttribute("aria-label")&&this.getAttribute("data-fab-auto-label")!==this.getAttribute("aria-label")||(this.setAttribute("aria-label",this.label),this.setAttribute("data-fab-auto-label",this.label)),this.hasAttribute("aria-label")||(this.setAttribute("aria-label","Floating action button"),this.setAttribute("data-fab-auto-label","Floating action button")),this.classList.toggle("designbase-wc-fab--extended",Boolean(this.label)),this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed),this.measureLabel()}unbindScroll(){this.scrollRoot?.removeEventListener("scroll",this.onScroll),this.scrollRoot=null}bindScroll(){if(this.unbindScroll(),this.scrollCollapsed=!1,this.collapseOnScroll){let t=null;const e=this.getAttribute("scroll-target");if(e)try{t=document.querySelector(e)}catch{}else for(let e=this.parentElement;e;e=e.parentElement)if(/(auto|scroll)/.test(getComputedStyle(e).overflowY)){t=e;break}this.scrollRoot=t||window,this.lastScroll=this.scrollPosition(),this.scrollCollapsed=this.lastScroll>this.collapseThreshold,this.scrollRoot.addEventListener("scroll",this.onScroll,{passive:!0})}this.syncFab()}scrollPosition(){return Math.max(0,this.scrollRoot instanceof HTMLElement?this.scrollRoot.scrollTop:window.scrollY)}}customElements.get("db-floating-action-button")||customElements.define("db-floating-action-button",DbFloatingActionButton);export{DbFloatingActionButton};
|
|
@@ -49,6 +49,7 @@ interface DbFormFieldData {
|
|
|
49
49
|
declare class DbForm extends HTMLElement {
|
|
50
50
|
static get observedAttributes(): string[];
|
|
51
51
|
private built;
|
|
52
|
+
private unsubscribeLocale?;
|
|
52
53
|
private formEl;
|
|
53
54
|
private headerEl;
|
|
54
55
|
private fieldsEl;
|
|
@@ -63,6 +64,7 @@ declare class DbForm extends HTMLElement {
|
|
|
63
64
|
private boundSubmit;
|
|
64
65
|
private boundReset;
|
|
65
66
|
connectedCallback(): void;
|
|
67
|
+
disconnectedCallback(): void;
|
|
66
68
|
attributeChangedCallback(name: string): void;
|
|
67
69
|
get fields(): DbFormFieldData[];
|
|
68
70
|
set fields(value: DbFormFieldData[] | string);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./db-input.js";import"./db-textarea.js";import"./db-select.js";import"./db-checkbox.js";import"./db-radio.js";import"./db-button.js";const e="designbase-wc-form";class DbForm extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.formEl=null,this.headerEl=null,this.fieldsEl=null,this.actionsEl=null,this.submitBtn=null,this.resetBtn=null,this.values={},this.errors={},this.touched={},this.initialValues={},this.fieldWrappers=new Map,this.boundSubmit=e=>this.handleSubmit(e),this.boundReset=e=>this.handleReset(e)}static get observedAttributes(){return["fields","columns","size","variant","title","description","submit-text","reset-text","show-reset","submit-loading","submit-disabled","initial-values"]}connectedCallback(){this.built||(this.buildShell(),this.built=!0),this.bootstrapValues(),this.syncAll()}attributeChangedCallback(e){this.built&&("initial-values"===e&&this.bootstrapValues(),"fields"===e&&this.bootstrapValues(),this.syncAll())}get fields(){return this.parseFields(this.getAttribute("fields"))}set fields(e){this.setAttribute("fields","string"==typeof e?e:JSON.stringify(e))}parseFields(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}parseInitialValues(){const e=this.getAttribute("initial-values");if(!e)return{};try{const t=JSON.parse(e);return t&&"object"==typeof t?t:{}}catch{return{}}}bootstrapValues(){this.initialValues=this.parseInitialValues();const e={...this.initialValues};this.fields.forEach(t=>{void 0===e[t.name]&&(void 0===t.value?void 0===t.defaultValue?"checkbox"===t.type&&t.checkboxGroup?e[t.name]=[]:"checkbox"!==t.type?e[t.name]="":e[t.name]=!1:e[t.name]=t.defaultValue:e[t.name]=t.value)}),this.values=e}buildShell(){this.formEl=document.createElement("form"),this.formEl.className=`${e}__native`,this.formEl.noValidate=!0,this.formEl.addEventListener("submit",this.boundSubmit),this.headerEl=document.createElement("div"),this.headerEl.className=`${e}__header`,this.fieldsEl=document.createElement("div"),this.fieldsEl.className=`${e}__fields`,this.actionsEl=document.createElement("div"),this.actionsEl.className=`${e}__actions`,this.submitBtn=document.createElement("db-button"),this.submitBtn.setAttribute("type","submit"),this.submitBtn.setAttribute("variant","primary"),this.resetBtn=document.createElement("db-button"),this.resetBtn.setAttribute("type","button"),this.resetBtn.setAttribute("variant","secondary"),this.resetBtn.addEventListener("click",this.boundReset),this.actionsEl.append(this.submitBtn,this.resetBtn),this.formEl.append(this.fieldsEl,this.actionsEl),this.append(this.headerEl,this.formEl)}syncAll(){this.syncClasses(),this.syncHeader(),this.renderFields(),this.syncActions()}syncClasses(){const t=this.getAttribute("columns")||"1",i=this.getAttribute("size")||"m",s=this.getAttribute("variant")||"default";this.className=[e,`${e}--columns-${t}`,`${e}--${i}`,`${e}--${s}`,this.hasAttribute("submit-loading")&&`${e}--loading`].filter(Boolean).join(" ")}syncHeader(){if(!this.headerEl)return;const t=this.getAttribute("title")||"",i=this.getAttribute("description")||"";if(this.headerEl.innerHTML="",t||i){if(this.headerEl.hidden=!1,t){const i=document.createElement("h3");i.className=`${e}__title`,i.textContent=t,this.headerEl.appendChild(i)}if(i){const t=document.createElement("p");t.className=`${e}__description`,t.textContent=i,this.headerEl.appendChild(t)}}else this.headerEl.hidden=!0}syncActions(){const e=this.getAttribute("submit-text")||"제출",t=this.getAttribute("reset-text")||"리셋",i=this.hasAttribute("show-reset");this.submitBtn&&(this.submitBtn.textContent=e,this.hasAttribute("submit-loading")?this.submitBtn.setAttribute("loading",""):this.submitBtn.removeAttribute("loading"),this.hasAttribute("submit-disabled")?this.submitBtn.setAttribute("disabled",""):this.submitBtn.removeAttribute("disabled")),this.resetBtn&&(this.resetBtn.textContent=t,this.resetBtn.hidden=!i)}renderFields(){if(!this.fieldsEl)return;const t=this.getAttribute("size")||"m";this.fieldsEl.innerHTML="",this.fieldWrappers.clear(),this.fields.forEach(i=>{const s=document.createElement("div");if(s.className=`${e}__field-wrapper ${e}__field-wrapper--${i.type||"text"}`,s.dataset.field=i.name,i.label&&("checkbox"!==i.type||i.checkboxGroup)){const t=document.createElement("label");if(t.className=`${e}__label`,t.htmlFor=`db-form-${i.name}`,t.textContent=i.label,i.required||i.validation?.required){const i=document.createElement("span");i.className=`${e}__required`,i.textContent="*",i.setAttribute("aria-hidden","true"),t.appendChild(i)}s.appendChild(t)}s.appendChild(this.createFieldControl(i,t)),this.fieldsEl.appendChild(s),this.fieldWrappers.set(i.name,s),this.refreshFieldState(i.name)})}refreshFieldState(t){const i=this.fields.find(e=>e.name===t),s=this.fieldWrappers.get(t);if(!i||!s)return;const r=Boolean(this.touched[t]&&this.errors[t]);s.classList.toggle(`${e}__field-wrapper--error`,r),s.querySelector(`.${e}__error`)?.remove(),s.querySelector(`.${e}__help`)?.remove();const a=s.querySelector(`.${e}__field, db-input, db-textarea, db-select, db-checkbox`);a&&(r?(a.setAttribute("error",""),a.setAttribute("error-message",this.errors[t])):(a.removeAttribute("error"),a.removeAttribute("error-message")));const n=a&&["DB-INPUT","DB-TEXTAREA","DB-SELECT"].includes(a.tagName);if(!r||!n){if(r){const i=document.createElement("div");return i.className=`${e}__error`,i.textContent=this.errors[t],void s.appendChild(i)}if(i.helpText){const t=document.createElement("div");t.className=`${e}__help`,t.textContent=i.helpText,s.appendChild(t)}}}refreshAllFieldStates(){this.fields.forEach(e=>this.refreshFieldState(e.name))}createFieldControl(t,i){const s=t.type||"text",r=this.values[t.name],a=Boolean(this.touched[t.name]&&this.errors[t.name]),n=a?this.errors[t.name]:"";if("textarea"===s){const s=document.createElement("db-textarea");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),s.setAttribute("full-width",""),t.placeholder&&s.setAttribute("placeholder",t.placeholder),void 0!==r&&s.setAttribute("value",String(r)),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),t.maxLength&&s.setAttribute("max-length",String(t.maxLength)),a&&(s.setAttribute("error",""),s.setAttribute("error-message",n)),s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),s.addEventListener("db-input",e=>{const i=e.detail;this.handleFieldChange(t,i.value,!1)}),s}if("select"===s){const s=document.createElement("db-select");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),s.setAttribute("full-width",""),t.placeholder&&s.setAttribute("placeholder",t.placeholder),t.options&&s.setAttribute("options",JSON.stringify(t.options)),t.multiple&&s.setAttribute("multiple",""),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),void 0!==r&&s.setAttribute("value",Array.isArray(r)?JSON.stringify(r):String(r)),a&&(s.setAttribute("error",""),s.setAttribute("error-message",n)),s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),s}if("radio"===s&&t.radioGroup){const s=document.createElement("div");return s.className=`${e}__radio-group`,s.setAttribute("role","radiogroup"),(t.options||[]).forEach(e=>{const a=document.createElement("db-radio");a.setAttribute("name",t.name),a.setAttribute("value",e.value),a.setAttribute("size",i),r===e.value&&a.setAttribute("checked",""),(t.disabled||e.disabled)&&a.setAttribute("disabled",""),a.textContent=e.label,a.addEventListener("db-change",i=>{i.detail.checked&&this.handleFieldChange(t,e.value)}),s.appendChild(a)}),s}if("checkbox"===s&&t.checkboxGroup){const s=document.createElement("div");s.className=`${e}__checkbox-group`;const a=Array.isArray(r)?r:[];return(t.options||[]).forEach(e=>{const r=document.createElement("db-checkbox");r.setAttribute("name",t.name),r.setAttribute("value",e.value),r.setAttribute("size",i),a.includes(e.value)&&r.setAttribute("checked",""),(t.disabled||e.disabled)&&r.setAttribute("disabled",""),r.textContent=e.label,r.addEventListener("db-change",i=>{const s=i.detail,r=Array.isArray(this.values[t.name])?[...this.values[t.name]]:[],a=s.checked?[...new Set([...r,e.value])]:r.filter(t=>t!==e.value);this.handleFieldChange(t,a)}),s.appendChild(r)}),s}if("checkbox"===s){const s=document.createElement("db-checkbox");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),r&&s.setAttribute("checked",""),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),s.textContent=t.label||"",s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.checked)}),s}const l=document.createElement("db-input");return l.className=`${e}__field`,l.setAttribute("name",t.name),l.id=`db-form-${t.name}`,l.setAttribute("type",s),l.setAttribute("size",i),l.setAttribute("full-width",""),t.placeholder&&l.setAttribute("placeholder",t.placeholder),void 0!==r&&!1!==r&&l.setAttribute("value",String(r)),t.disabled&&l.setAttribute("disabled",""),t.readOnly&&l.setAttribute("readonly",""),t.required&&l.setAttribute("required",""),void 0!==t.min&&l.setAttribute("min",String(t.min)),void 0!==t.max&&l.setAttribute("max",String(t.max)),void 0!==t.minLength&&l.setAttribute("minlength",String(t.minLength)),void 0!==t.maxLength&&l.setAttribute("maxlength",String(t.maxLength)),t.pattern&&l.setAttribute("pattern",t.pattern),a&&(l.setAttribute("error",""),l.setAttribute("error-message",n)),l.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),l.addEventListener("db-input",e=>{const i=e.detail;this.handleFieldChange(t,i.value,!1)}),l}handleFieldChange(e,t,i=!0){this.values[e.name]=t,i&&(this.touched[e.name]=!0);const s=this.validateField(e,t);this.errors[e.name]=s||"",this.refreshFieldState(e.name),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}validateField(e,t){const i=e.validation||{};if((i.required??e.required)&&(null==t||""===t||!1===t||Array.isArray(t)&&0===t.length))return e.errorMessage||`${e.label||e.name}은(는) 필수입니다.`;if(void 0!==i.min&&Number(t)<i.min)return e.errorMessage||`최소값은 ${i.min}입니다.`;if(void 0!==i.max&&Number(t)>i.max)return e.errorMessage||`최대값은 ${i.max}입니다.`;if(void 0!==i.minLength&&String(t).length<i.minLength)return e.errorMessage||`최소 ${i.minLength}자 이상 입력해주세요.`;if(void 0!==i.maxLength&&String(t).length>i.maxLength)return e.errorMessage||`최대 ${i.maxLength}자까지 입력 가능합니다.`;const s=i.pattern||e.pattern;if(s&&String(t))try{if(!new RegExp(s).test(String(t)))return e.errorMessage||"올바른 형식으로 입력해주세요."}catch{}}validateForm(){let e=!0;return this.fields.forEach(t=>{const i=this.validateField(t,this.values[t.name]);i?(this.errors[t.name]=i,e=!1):this.errors[t.name]=""}),e}handleSubmit(e){e.preventDefault(),this.fields.forEach(e=>{this.touched[e.name]=!0}),this.validateForm()?this.dispatchEvent(new CustomEvent("db-submit",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})):this.refreshAllFieldStates()}handleReset(e){e.preventDefault(),this.values={...this.initialValues},this.bootstrapValues(),this.errors={},this.touched={},this.renderFields(),this.dispatchEvent(new CustomEvent("db-reset",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}}customElements.get("db-form")||customElements.define("db-form",DbForm);export{DbForm};
|
|
1
|
+
import"./db-input.js";import"./db-textarea.js";import"./db-select.js";import"./db-checkbox.js";import"./db-radio.js";import"./db-button.js";import{subscribeDbLocale as e,dbText as t,dbFormat as i}from"../core/i18n.js";const s="designbase-wc-form";class DbForm extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.formEl=null,this.headerEl=null,this.fieldsEl=null,this.actionsEl=null,this.submitBtn=null,this.resetBtn=null,this.values={},this.errors={},this.touched={},this.initialValues={},this.fieldWrappers=new Map,this.boundSubmit=e=>this.handleSubmit(e),this.boundReset=e=>this.handleReset(e)}static get observedAttributes(){return["fields","columns","size","variant","title","description","submit-text","reset-text","show-reset","submit-loading","submit-disabled","initial-values"]}connectedCallback(){this.built||(this.buildShell(),this.built=!0),this.bootstrapValues(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{this.syncActions();for(const e of this.fields)this.errors[e.name]&&(this.errors[e.name]=this.validateField(e,this.values[e.name])||"",this.refreshFieldState(e.name))}),this.syncAll()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(e){this.built&&("initial-values"===e&&this.bootstrapValues(),"fields"===e&&this.bootstrapValues(),this.syncAll())}get fields(){return this.parseFields(this.getAttribute("fields"))}set fields(e){this.setAttribute("fields","string"==typeof e?e:JSON.stringify(e))}parseFields(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}parseInitialValues(){const e=this.getAttribute("initial-values");if(!e)return{};try{const t=JSON.parse(e);return t&&"object"==typeof t?t:{}}catch{return{}}}bootstrapValues(){this.initialValues=this.parseInitialValues();const e={...this.initialValues};this.fields.forEach(t=>{void 0===e[t.name]&&(void 0===t.value?void 0===t.defaultValue?"checkbox"===t.type&&t.checkboxGroup?e[t.name]=[]:"checkbox"!==t.type?e[t.name]="":e[t.name]=!1:e[t.name]=t.defaultValue:e[t.name]=t.value)}),this.values=e}buildShell(){this.formEl=document.createElement("form"),this.formEl.className=`${s}__native`,this.formEl.noValidate=!0,this.formEl.addEventListener("submit",this.boundSubmit),this.headerEl=document.createElement("div"),this.headerEl.className=`${s}__header`,this.fieldsEl=document.createElement("div"),this.fieldsEl.className=`${s}__fields`,this.actionsEl=document.createElement("div"),this.actionsEl.className=`${s}__actions`,this.submitBtn=document.createElement("db-button"),this.submitBtn.setAttribute("type","submit"),this.submitBtn.setAttribute("variant","primary"),this.resetBtn=document.createElement("db-button"),this.resetBtn.setAttribute("type","button"),this.resetBtn.setAttribute("variant","secondary"),this.resetBtn.addEventListener("click",this.boundReset),this.actionsEl.append(this.submitBtn,this.resetBtn),this.formEl.append(this.fieldsEl,this.actionsEl),this.append(this.headerEl,this.formEl)}syncAll(){this.syncClasses(),this.syncHeader(),this.renderFields(),this.syncActions()}syncClasses(){const e=this.getAttribute("columns")||"1",t=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default";this.className=[s,`${s}--columns-${e}`,`${s}--${t}`,`${s}--${i}`,this.hasAttribute("submit-loading")&&`${s}--loading`].filter(Boolean).join(" ")}syncHeader(){if(!this.headerEl)return;const e=this.getAttribute("title")||"",t=this.getAttribute("description")||"";if(this.headerEl.innerHTML="",e||t){if(this.headerEl.hidden=!1,e){const t=document.createElement("h3");t.className=`${s}__title`,t.textContent=e,this.headerEl.appendChild(t)}if(t){const e=document.createElement("p");e.className=`${s}__description`,e.textContent=t,this.headerEl.appendChild(e)}}else this.headerEl.hidden=!0}syncActions(){const e=this.getAttribute("submit-text")||t("제출"),i=this.getAttribute("reset-text")||t("리셋"),s=this.hasAttribute("show-reset");this.submitBtn&&(this.submitBtn.textContent=e,this.hasAttribute("submit-loading")?this.submitBtn.setAttribute("loading",""):this.submitBtn.removeAttribute("loading"),this.hasAttribute("submit-disabled")?this.submitBtn.setAttribute("disabled",""):this.submitBtn.removeAttribute("disabled")),this.resetBtn&&(this.resetBtn.textContent=i,this.resetBtn.hidden=!s)}renderFields(){if(!this.fieldsEl)return;const e=this.getAttribute("size")||"m";this.fieldsEl.innerHTML="",this.fieldWrappers.clear(),this.fields.forEach(t=>{const i=document.createElement("div");if(i.className=`${s}__field-wrapper ${s}__field-wrapper--${t.type||"text"}`,i.dataset.field=t.name,t.label&&("checkbox"!==t.type||t.checkboxGroup)){const e=document.createElement("label");if(e.className=`${s}__label`,e.htmlFor=`db-form-${t.name}`,e.textContent=t.label,t.required||t.validation?.required){const t=document.createElement("span");t.className=`${s}__required`,t.textContent="*",t.setAttribute("aria-hidden","true"),e.appendChild(t)}i.appendChild(e)}i.appendChild(this.createFieldControl(t,e)),this.fieldsEl.appendChild(i),this.fieldWrappers.set(t.name,i),this.refreshFieldState(t.name)})}refreshFieldState(e){const t=this.fields.find(t=>t.name===e),i=this.fieldWrappers.get(e);if(!t||!i)return;const r=Boolean(this.touched[e]&&this.errors[e]);i.classList.toggle(`${s}__field-wrapper--error`,r),i.querySelector(`.${s}__error`)?.remove(),i.querySelector(`.${s}__help`)?.remove();const a=i.querySelector(`.${s}__field, db-input, db-textarea, db-select, db-checkbox`);a&&(r?(a.setAttribute("error",""),a.setAttribute("error-message",this.errors[e])):(a.removeAttribute("error"),a.removeAttribute("error-message")));const n=a&&["DB-INPUT","DB-TEXTAREA","DB-SELECT"].includes(a.tagName);if(!r||!n){if(r){const t=document.createElement("div");return t.className=`${s}__error`,t.textContent=this.errors[e],void i.appendChild(t)}if(t.helpText){const e=document.createElement("div");e.className=`${s}__help`,e.textContent=t.helpText,i.appendChild(e)}}}refreshAllFieldStates(){this.fields.forEach(e=>this.refreshFieldState(e.name))}createFieldControl(e,t){const i=e.type||"text",r=this.values[e.name],a=Boolean(this.touched[e.name]&&this.errors[e.name]),n=a?this.errors[e.name]:"";if("textarea"===i){const i=document.createElement("db-textarea");return i.className=`${s}__field`,i.setAttribute("name",e.name),i.id=`db-form-${e.name}`,i.setAttribute("size",t),i.setAttribute("full-width",""),e.placeholder&&i.setAttribute("placeholder",e.placeholder),void 0!==r&&i.setAttribute("value",String(r)),e.disabled&&i.setAttribute("disabled",""),e.readOnly&&i.setAttribute("readonly",""),e.required&&i.setAttribute("required",""),e.maxLength&&i.setAttribute("max-length",String(e.maxLength)),a&&(i.setAttribute("error",""),i.setAttribute("error-message",n)),i.addEventListener("db-change",t=>{const i=t.detail;this.handleFieldChange(e,i.value)}),i.addEventListener("db-input",t=>{const i=t.detail;this.handleFieldChange(e,i.value,!1)}),i}if("select"===i){const i=document.createElement("db-select");return i.className=`${s}__field`,i.setAttribute("name",e.name),i.id=`db-form-${e.name}`,i.setAttribute("size",t),i.setAttribute("full-width",""),e.placeholder&&i.setAttribute("placeholder",e.placeholder),e.options&&i.setAttribute("options",JSON.stringify(e.options)),e.multiple&&i.setAttribute("multiple",""),e.disabled&&i.setAttribute("disabled",""),e.readOnly&&i.setAttribute("readonly",""),e.required&&i.setAttribute("required",""),void 0!==r&&i.setAttribute("value",Array.isArray(r)?JSON.stringify(r):String(r)),a&&(i.setAttribute("error",""),i.setAttribute("error-message",n)),i.addEventListener("db-change",t=>{const i=t.detail;this.handleFieldChange(e,i.value)}),i}if("radio"===i&&e.radioGroup){const i=document.createElement("div");return i.className=`${s}__radio-group`,i.setAttribute("role","radiogroup"),(e.options||[]).forEach(s=>{const a=document.createElement("db-radio");a.setAttribute("name",e.name),a.setAttribute("value",s.value),a.setAttribute("size",t),r===s.value&&a.setAttribute("checked",""),(e.disabled||s.disabled)&&a.setAttribute("disabled",""),a.textContent=s.label,a.addEventListener("db-change",t=>{t.detail.checked&&this.handleFieldChange(e,s.value)}),i.appendChild(a)}),i}if("checkbox"===i&&e.checkboxGroup){const i=document.createElement("div");i.className=`${s}__checkbox-group`;const a=Array.isArray(r)?r:[];return(e.options||[]).forEach(s=>{const r=document.createElement("db-checkbox");r.setAttribute("name",e.name),r.setAttribute("value",s.value),r.setAttribute("size",t),a.includes(s.value)&&r.setAttribute("checked",""),(e.disabled||s.disabled)&&r.setAttribute("disabled",""),r.textContent=s.label,r.addEventListener("db-change",t=>{const i=t.detail,r=Array.isArray(this.values[e.name])?[...this.values[e.name]]:[],a=i.checked?[...new Set([...r,s.value])]:r.filter(e=>e!==s.value);this.handleFieldChange(e,a)}),i.appendChild(r)}),i}if("checkbox"===i){const i=document.createElement("db-checkbox");return i.className=`${s}__field`,i.setAttribute("name",e.name),i.id=`db-form-${e.name}`,i.setAttribute("size",t),r&&i.setAttribute("checked",""),e.disabled&&i.setAttribute("disabled",""),e.readOnly&&i.setAttribute("readonly",""),e.required&&i.setAttribute("required",""),i.textContent=e.label||"",i.addEventListener("db-change",t=>{const i=t.detail;this.handleFieldChange(e,i.checked)}),i}const l=document.createElement("db-input");return l.className=`${s}__field`,l.setAttribute("name",e.name),l.id=`db-form-${e.name}`,l.setAttribute("type",i),l.setAttribute("size",t),l.setAttribute("full-width",""),e.placeholder&&l.setAttribute("placeholder",e.placeholder),void 0!==r&&!1!==r&&l.setAttribute("value",String(r)),e.disabled&&l.setAttribute("disabled",""),e.readOnly&&l.setAttribute("readonly",""),e.required&&l.setAttribute("required",""),void 0!==e.min&&l.setAttribute("min",String(e.min)),void 0!==e.max&&l.setAttribute("max",String(e.max)),void 0!==e.minLength&&l.setAttribute("minlength",String(e.minLength)),void 0!==e.maxLength&&l.setAttribute("maxlength",String(e.maxLength)),e.pattern&&l.setAttribute("pattern",e.pattern),a&&(l.setAttribute("error",""),l.setAttribute("error-message",n)),l.addEventListener("db-change",t=>{const i=t.detail;this.handleFieldChange(e,i.value)}),l.addEventListener("db-input",t=>{const i=t.detail;this.handleFieldChange(e,i.value,!1)}),l}handleFieldChange(e,t,i=!0){this.values[e.name]=t,i&&(this.touched[e.name]=!0);const s=this.validateField(e,t);this.errors[e.name]=s||"",this.refreshFieldState(e.name),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}validateField(e,s){const r=e.validation||{};if((r.required??e.required)&&(null==s||""===s||!1===s||Array.isArray(s)&&0===s.length))return e.errorMessage||i("{0}은(는) 필수입니다.",[e.label||e.name]);if(void 0!==r.min&&Number(s)<r.min)return e.errorMessage||i("최소값은 {0}입니다.",[r.min]);if(void 0!==r.max&&Number(s)>r.max)return e.errorMessage||i("최대값은 {0}입니다.",[r.max]);if(void 0!==r.minLength&&String(s).length<r.minLength)return e.errorMessage||i("최소 {0}자 이상 입력해주세요.",[r.minLength]);if(void 0!==r.maxLength&&String(s).length>r.maxLength)return e.errorMessage||i("최대 {0}자까지 입력 가능합니다.",[r.maxLength]);const a=r.pattern||e.pattern;if(a&&String(s))try{if(!new RegExp(a).test(String(s)))return e.errorMessage||t("올바른 형식으로 입력해주세요.")}catch{}}validateForm(){let e=!0;return this.fields.forEach(t=>{const i=this.validateField(t,this.values[t.name]);i?(this.errors[t.name]=i,e=!1):this.errors[t.name]=""}),e}handleSubmit(e){e.preventDefault(),this.fields.forEach(e=>{this.touched[e.name]=!0}),this.validateForm()?this.dispatchEvent(new CustomEvent("db-submit",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})):this.refreshAllFieldStates()}handleReset(e){e.preventDefault(),this.values={...this.initialValues},this.bootstrapValues(),this.errors={},this.touched={},this.renderFields(),this.dispatchEvent(new CustomEvent("db-reset",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}}customElements.get("db-form")||customElements.define("db-form",DbForm);export{DbForm};
|
|
@@ -29,6 +29,7 @@ type DbGanttGroup = {
|
|
|
29
29
|
declare class DbGantt extends HTMLElement {
|
|
30
30
|
private collapsedGroups;
|
|
31
31
|
private dragState;
|
|
32
|
+
private unsubscribeLocale?;
|
|
32
33
|
private reorderState;
|
|
33
34
|
private reorderDropIndex;
|
|
34
35
|
private suppressRender;
|
|
@@ -43,6 +44,7 @@ declare class DbGantt extends HTMLElement {
|
|
|
43
44
|
connectedCallback(): void;
|
|
44
45
|
disconnectedCallback(): void;
|
|
45
46
|
attributeChangedCallback(): void;
|
|
47
|
+
private refreshLocale;
|
|
46
48
|
private parseJson;
|
|
47
49
|
private getBool;
|
|
48
50
|
private getNumber;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dbText as e,getDbLocale as t,dbFormat as a}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{rafThrottle as r}from"../core/dom.js";const n=["day","week"],i=["#86efac","#fde047","#93c5fd","#c4b5fd","#f9a8d4","#5eead4","#fdba74","#a5b4fc"],d=["일","월","화","수","목","금","토"],o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function parseDate(e){const[t,a,s]=e.split("-").map(Number);return new Date(t,a-1,s)}function toDateKey(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function addDays(e,t){const a=new Date(e);return a.setDate(a.getDate()+t),a}function daysBetween(e,t){const a=Date.UTC(e.getFullYear(),e.getMonth(),e.getDate()),s=Date.UTC(t.getFullYear(),t.getMonth(),t.getDate());return Math.round((s-a)/864e5)}function clampDate(e,t,a){return e<t?new Date(t):e>a?new Date(a):e}class DbGantt extends HTMLElement{constructor(){super(...arguments),this.collapsedGroups=new Set,this.dragState=null,this.reorderState=null,this.reorderDropIndex=null,this.suppressRender=!1,this.didDrag=!1,this.handlePointerMove=r(e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.updateReorderDropTarget(e.clientY);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/a);0!==i&&(this.didDrag=!0);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);if("move"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,s,r),o=clampDate(o,s,r),d>o)return;const l=this.items.find(e=>e.id===this.dragState.itemId);l&&this.applyBarGeometry(this.dragState.barEl,{...l,startDate:toDateKey(d),endDate:toDateKey(o)},s,a)}),this.handlePointerUp=e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.finishReorderDrag(e);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/a);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);const l=this.dragState.mode,c=this.dragState.itemId;"move"===l?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===l?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,s,r),o=clampDate(o,s,r),this.dragState.barEl.releasePointerCapture(e.pointerId),this.dragState.barEl.classList.remove("designbase-wc-gantt__bar--dragging"),this.dragState=null;const g=this.items.find(e=>e.id===c);if(!g)return;const p=toDateKey(d),h=toDateKey(o);p===g.startDate&&h===g.endDate||(this.updateItem(c,{startDate:p,endDate:h},"move"===l?"move":"resize"),this.render())}}static get observedAttributes(){return["groups","rows","items","start-date","end-date","today","scale","cell-width","show-weekends","show-today","sidebar-label","full-width","disabled","draggable","reorderable","locale"]}get groups(){return this.parseJson("groups",[])}set groups(e){this.setAttribute("groups","string"==typeof e?e:JSON.stringify(e))}get rows(){return this.parseJson("rows",[])}set rows(e){this.setAttribute("rows","string"==typeof e?e:JSON.stringify(e))}get items(){return this.parseJson("items",[])}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label",e("프로젝트 타임라인")),this.addEventListener("pointermove",this.handlePointerMove),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.render()}disconnectedCallback(){this.removeEventListener("pointermove",this.handlePointerMove),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){!this.isConnected||this.suppressRender||this.dragState||this.reorderState||this.render()}parseJson(e,t){try{return JSON.parse(this.getAttribute(e)||"null")??t}catch{return t}}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}getNumber(e,t){const a=Number(this.getAttribute(e));return Number.isFinite(a)&&a>0?a:t}getOption(e,t,a){const s=this.getAttribute(e);return s&&t.includes(s)?s:a}getLocale(){return this.getAttribute("locale")||("ko"===t()?"ko-KR":"en-US")}getWeekdays(){return this.getLocale().startsWith("ko")?d:o}getViewRange(){const e=this.getAttribute("start-date"),t=this.getAttribute("end-date");if(e&&t)return{start:parseDate(e),end:parseDate(t)};const a=this.items.flatMap(e=>[parseDate(e.startDate),parseDate(e.endDate)]);if(0===a.length){const e=new Date,t=new Date(e.getFullYear(),e.getMonth(),1);return{start:t,end:addDays(t,29)}}const s=new Date(Math.min(...a.map(e=>e.getTime()))),r=new Date(Math.max(...a.map(e=>e.getTime())));return{start:addDays(s,-2),end:addDays(r,2)}}getTodayDate(){const e=this.getAttribute("today");return e?parseDate(e):new Date}getDateColumns(e,t){const a=daysBetween(e,t)+1;return Array.from({length:a},(t,a)=>addDays(e,a))}getVisibleRows(){const e=this.groups,t=this.rows;if(0===e.length)return t.map(e=>({type:"row",row:e}));const a=[];for(const s of e)a.push({type:"group",group:s}),this.collapsedGroups.has(s.id)||t.filter(e=>e.groupId===s.id).forEach(e=>a.push({type:"row",row:e}));return t.filter(t=>!t.groupId||!e.some(e=>e.id===t.groupId)).forEach(e=>a.push({type:"row",row:e})),a}getMonthSegments(e){const t=[];let a="",s=0;for(const r of e){const e=`${r.getFullYear()}-${r.getMonth()}`;e!==a?(s>0&&t.push({label:a,span:s}),a=e,s=1):s+=1}return s>0&&t.push({label:a,span:s}),t.map(e=>{const[t,a]=e.label.split("-").map(Number);return{label:new Date(t,a,1).toLocaleDateString(this.getLocale(),{year:"numeric",month:"long"}),span:e.span}})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e[0]).join("").slice(0,2).toUpperCase()}updateItem(e,t,a){const s=this.items.map(a=>a.id===e?{...a,...t}:a);this.emitItemsChange(s,a,e)}emitItemsChange(e,t,a){this.suppressRender=!0,this.items=e,this.suppressRender=!1;const s=e.find(e=>e.id===a);this.dispatchEvent(new CustomEvent("db-item-change",{detail:{item:s,items:e,action:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:this.groups,rows:this.rows,items:e},bubbles:!0,composed:!0}))}applyBarGeometry(e,t,a,s){const r=parseDate(t.startDate),n=parseDate(t.endDate),i=daysBetween(a,r),d=daysBetween(r,n)+1;e.style.left=i*s+2+"px",e.style.width=`${Math.max(d*s-4,s-4)}px`}startBarDrag(e,t,a,s){!this.getBool("draggable",!0)||this.getBool("disabled")||t.disabled||(e.preventDefault(),e.stopPropagation(),this.didDrag=!1,s.setPointerCapture(e.pointerId),s.classList.add("designbase-wc-gantt__bar--dragging"),this.dragState={itemId:t.id,mode:a,pointerId:e.pointerId,startX:e.clientX,originalStart:parseDate(t.startDate),originalEnd:parseDate(t.endDate),barEl:s})}canReorder(){return this.getBool("reorderable",!0)&&!this.getBool("disabled")}createDragHandle(e,t,a){const r=document.createElement("span");return r.className="designbase-wc-gantt__drag-handle",r.setAttribute("role","button"),r.setAttribute("aria-label","group"===e?"그룹 순서 변경":"행 순서 변경"),r.append(s("grip-vertical",12)),this.canReorder()?(r.addEventListener("pointerdown",s=>{s.preventDefault(),s.stopPropagation(),this.startReorderDrag(s,e,t,a,r)}),r):r}getGroupIndex(e){return this.groups.findIndex(t=>t.id===e)}getRowScope(e){return this.rows.filter(t=>(t.groupId||"")===(e||""))}getRowIndexInScope(e,t){return this.getRowScope(t).findIndex(t=>t.id===e)}getReorderTargets(e,t){return Array.from(this.querySelectorAll("group"===e?".designbase-wc-gantt__label-cell--group":`.designbase-wc-gantt__label-cell--row[data-group-id="${t||""}"]`))}startReorderDrag(e,t,a,s,r){const n="group"===t?this.getGroupIndex(a):this.getRowIndexInScope(a,s);n<0||(r.setPointerCapture(e.pointerId),this.reorderState={kind:t,id:a,groupId:s,pointerId:e.pointerId,startY:e.clientY,fromIndex:n,captureEl:r},this.classList.add("designbase-wc-gantt--reordering"),this.updateReorderDropTarget(e.clientY))}updateReorderDropTarget(e){if(!this.reorderState)return;const t=this.getReorderTargets(this.reorderState.kind,this.reorderState.groupId);let a=null;t.forEach((t,s)=>{const r=t.getBoundingClientRect(),n=r.top+r.height/2,i=e>=r.top&&e<=r.bottom,d=e>n;t.classList.toggle("designbase-wc-gantt__label-cell--drag-over",i),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-before",i&&!d),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-after",i&&d),i&&(a=d?s+1:s)}),this.reorderDropIndex=a}clearReorderIndicators(){this.querySelectorAll(".designbase-wc-gantt__label-cell--drag-over").forEach(e=>{e.classList.remove("designbase-wc-gantt__label-cell--drag-over","designbase-wc-gantt__label-cell--drag-over-before","designbase-wc-gantt__label-cell--drag-over-after")})}finishReorderDrag(e){if(!this.reorderState)return;const{kind:t,id:a,groupId:s,fromIndex:r,captureEl:n}=this.reorderState;try{n.releasePointerCapture(this.reorderState.pointerId)}catch{}const i=this.reorderDropIndex;if(this.reorderState=null,this.reorderDropIndex=null,this.classList.remove("designbase-wc-gantt--reordering"),this.clearReorderIndicators(),null===i)return;const d=i>r?i-1:i;d<0||d===r||("group"===t?this.reorderGroups(r,d,a):this.reorderRows(r,d,a,s))}emitStructureChange(e,t,a,s){this.suppressRender=!0,this.groups=e,this.rows=t,this.suppressRender=!1,this.dispatchEvent(new CustomEvent(s,{detail:{...a,groups:e,rows:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:e,rows:t,items:this.items},bubbles:!0,composed:!0})),this.render()}reorderGroups(e,t,a){const s=[...this.groups],[r]=s.splice(e,1);r&&(s.splice(t,0,r),this.emitStructureChange(s,this.rows,{groupId:a,fromIndex:e,toIndex:t},"db-group-reorder"))}reorderRows(e,t,a,s){const r=this.getRowScope(s),n=[...r],[i]=n.splice(e,1);if(!i)return;n.splice(t,0,i);const d=new Set(r.map(e=>e.id)),o=[];let l=!1;for(const e of this.rows)d.has(e.id)?l||(o.push(...n),l=!0):o.push(e);l||o.push(...n),this.emitStructureChange(this.groups,o,{rowId:a,groupId:s,fromIndex:e,toIndex:t},"db-row-reorder")}createGroupBadge(e){const t=document.createElement("db-badge");return t.className="designbase-wc-gantt__group-badge",t.setAttribute("type","dot"),t.setAttribute("size","s"),t.setAttribute("variant","primary"),t.setAttribute("aria-hidden","true"),e&&t.style.setProperty("--db-gantt-badge-color",e),t}createGroupChevron(e){const t=document.createElement("span");return t.className=["designbase-wc-gantt__group-chevron",e?"designbase-wc-gantt__group-chevron--collapsed":""].filter(Boolean).join(" "),t.append(s("chevron-down",12)),t}createAssignee(e){const t=document.createElement("span");if(t.className="designbase-wc-gantt__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.src=e.avatar,a.alt=e.name,t.appendChild(a)}else t.textContent=this.getInitials(e);return t}createStatusIcon(e){const t=document.createElement("span");return t.className=`designbase-wc-gantt__status designbase-wc-gantt__status--${e}`,t.setAttribute("aria-hidden","true"),t.textContent="completed"===e?"✓":"!",t}deriveSummaryColor(e,t){if(0===e.length)return t||i[0];const a=e.filter(e=>e.color);if(0===a.length)return t||i[0];return a.reduce((e,t)=>{const a=daysBetween(parseDate(e.startDate),parseDate(e.endDate));return daysBetween(parseDate(t.startDate),parseDate(t.endDate))>a?t:e}).color||t||i[0]}getGroupSummary(e,t){const a=this.rows.filter(t=>t.groupId===e),s=this.items.filter(e=>a.some(t=>t.id===e.rowId));if(0===s.length)return null;const r=s.map(e=>parseDate(e.startDate).getTime()),n=s.map(e=>parseDate(e.endDate).getTime()),i=s.map(e=>e.progress).filter(e=>"number"==typeof e);return{startDate:toDateKey(new Date(Math.min(...r))),endDate:toDateKey(new Date(Math.max(...n))),color:this.deriveSummaryColor(s,t),progress:i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0,count:s.length}}applyBarTone(e,t){const a=function deriveBarTone(e){return{base:`color-mix(in srgb, ${e} 42%, white)`,progress:`color-mix(in srgb, ${e} 58%, white)`}}(t);e.style.setProperty("--db-gantt-bar-color",t),e.style.setProperty("--db-gantt-bar-bg",a.base),e.style.setProperty("--db-gantt-bar-progress-bg",a.progress)}createGroupSummaryBar(e,t,s,r){const n=clampDate(parseDate(e.startDate),t,s),i=clampDate(parseDate(e.endDate),t,s);if(i<t||n>s)return null;const d=daysBetween(t,n),o=daysBetween(n,i)+1,l=Math.min(100,Math.max(0,e.progress)),c=document.createElement("div");if(c.className="designbase-wc-gantt__group-summary",c.setAttribute("aria-hidden","true"),c.title=a("{0}개 태스크",[e.count]),this.applyBarTone(c,e.color),c.style.left=d*r+2+"px",c.style.width=`${Math.max(o*r-4,r-4)}px`,l>0){const e=document.createElement("span");e.className="designbase-wc-gantt__group-summary-progress",e.style.width=`${l}%`,c.appendChild(e)}return c}createBar(e,t,a,s){const r=e.color||i[s%i.length],n=document.createElement("div");n.className="designbase-wc-gantt__bar",n.setAttribute("role","button"),n.setAttribute("tabindex",e.disabled?"-1":"0"),n.setAttribute("aria-disabled",String(Boolean(e.disabled)||this.getBool("disabled"))),n.setAttribute("aria-label",`${e.title}, ${e.startDate} – ${e.endDate}`),this.applyBarTone(n,r),e.disabled&&n.classList.add("designbase-wc-gantt__bar--disabled"),this.applyBarGeometry(n,e,t,a);const d="number"==typeof e.progress?Math.min(100,Math.max(0,e.progress)):0;if(d>0){const e=document.createElement("span");e.className="designbase-wc-gantt__bar-progress",e.style.width=`${d}%`,n.appendChild(e)}const o=document.createElement("div");o.className="designbase-wc-gantt__bar-body","delayed"!==e.status&&"at-risk"!==e.status||o.appendChild(this.createStatusIcon(e.status));const l=document.createElement("span");l.className="designbase-wc-gantt__bar-label",l.textContent=e.title,o.appendChild(l),e.assignee&&o.appendChild(this.createAssignee(e.assignee));const c=document.createElement("span");c.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--start",c.setAttribute("aria-hidden","true");const g=document.createElement("span");return g.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--end",g.setAttribute("aria-hidden","true"),n.append(c,o,g),e.disabled||!this.getBool("draggable",!0)||this.getBool("disabled")||(c.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-start",n)),g.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-end",n)),o.addEventListener("pointerdown",t=>{t.target.closest(".designbase-wc-gantt__bar-handle")||this.startBarDrag(t,e,"move",n)})),n.addEventListener("click",t=>{this.dragState||this.didDrag?this.didDrag=!1:(t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:e},bubbles:!0,composed:!0})))}),n}toggleGroup(e){this.collapsedGroups.has(e)?this.collapsedGroups.delete(e):this.collapsedGroups.add(e),this.dispatchEvent(new CustomEvent("db-group-toggle",{detail:{groupId:e,collapsed:this.collapsedGroups.has(e)},bubbles:!0,composed:!0})),this.render()}render(){const e=this.items,t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),s=this.getBool("show-weekends",!0),r=this.getBool("show-today",!0),d=this.getAttribute("sidebar-label")||"할 일",o=this.getBool("disabled"),l=this.getBool("full-width",!0),c=this.getWeekdays(),{start:g,end:p}=this.getViewRange(),h=this.getDateColumns(g,p),u=toDateKey(this.getTodayDate()),m=h.findIndex(e=>toDateKey(e)===u),b=this.getVisibleRows(),w=h.length*a,D=document.createElement("div");D.className=["designbase-wc-gantt",l?"designbase-wc-gantt--full-width":"",o?"designbase-wc-gantt--disabled":"",this.getBool("draggable",!0)?"designbase-wc-gantt--draggable":""].filter(Boolean).join(" ");const y=document.createElement("div");y.className="designbase-wc-gantt__viewport";const _=document.createElement("div");_.className="designbase-wc-gantt__grid",_.style.setProperty("--db-gantt-chart-width",`${w}px`),_.style.setProperty("--db-gantt-cell-width",`${a}px`);const f=document.createElement("div");f.className="designbase-wc-gantt__corner",f.textContent=d,_.appendChild(f);const v=document.createElement("div");v.className="designbase-wc-gantt__date-header";const E=document.createElement("div");E.className="designbase-wc-gantt__month-row";for(const e of this.getMonthSegments(h)){const t=document.createElement("div");t.className="designbase-wc-gantt__month-cell",t.style.width=e.span*a+"px",t.textContent=e.label,E.appendChild(t)}v.appendChild(E);const S=document.createElement("div");S.className="designbase-wc-gantt__day-row";for(const e of h){const t=toDateKey(e)===u,n=0===e.getDay()||6===e.getDay(),i=document.createElement("div");i.className=["designbase-wc-gantt__day-cell",t&&r?"designbase-wc-gantt__day-cell--today":"",n&&s?"designbase-wc-gantt__day-cell--weekend":""].filter(Boolean).join(" "),i.style.width=`${a}px`;const d=document.createElement("span");d.className="designbase-wc-gantt__day-num",d.textContent=String(e.getDate());const o=document.createElement("span");o.className="designbase-wc-gantt__day-name",o.textContent=c[e.getDay()],i.append(d,o),S.appendChild(i)}v.appendChild(S),_.appendChild(v);const C=new Map;e.forEach((e,t)=>{const a=C.get(e.rowId)||[];a.push({...e,color:e.color||i[t%i.length]}),C.set(e.rowId,a)});let I=0;for(const e of b){if("group"===e.type){const{group:t}=e,r=this.collapsedGroups.has(t.id),n=document.createElement("button");n.type="button",n.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--group",n.setAttribute("aria-expanded",String(!r)),n.dataset.groupId=t.id;const i=document.createElement("span");i.className="designbase-wc-gantt__group-title",i.textContent=t.title,n.append(this.createDragHandle("group",t.id),this.createGroupChevron(r),this.createGroupBadge(t.color),i),n.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.toggleGroup(t.id)}),_.appendChild(n);const d=document.createElement("div");if(d.className="designbase-wc-gantt__track-cell designbase-wc-gantt__track-cell--group",r){const e=this.getGroupSummary(t.id,t.color);if(e){const t=document.createElement("div");t.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const r=document.createElement("div"),n=0===e.getDay()||6===e.getDay();r.className=["designbase-wc-gantt__grid-cell",n&&s?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),r.style.width=`${a}px`,t.appendChild(r)}),d.appendChild(t);const r=document.createElement("div");r.className="designbase-wc-gantt__group-summary-wrap";const n=this.createGroupSummaryBar(e,g,p,a);n&&r.appendChild(n),d.appendChild(r)}}_.appendChild(d);continue}const{row:t}=e,r=document.createElement("button");r.type="button",r.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--row",r.dataset.groupId=t.groupId||"",r.dataset.rowId=t.id;const n=document.createElement("span");n.className="designbase-wc-gantt__row-title",n.textContent=t.label,r.append(this.createDragHandle("row",t.id,t.groupId),n),r.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.dispatchEvent(new CustomEvent("db-row-click",{detail:{row:t},bubbles:!0,composed:!0}))}),_.appendChild(r);const i=document.createElement("div");i.className="designbase-wc-gantt__track-cell";const d=document.createElement("div");d.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const t=document.createElement("div"),r=0===e.getDay()||6===e.getDay();t.className=["designbase-wc-gantt__grid-cell",r&&s?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),t.style.width=`${a}px`,d.appendChild(t)}),i.appendChild(d);const o=document.createElement("div");o.className="designbase-wc-gantt__bars",(C.get(t.id)||[]).forEach(e=>{const t=clampDate(parseDate(e.startDate),g,p),s=clampDate(parseDate(e.endDate),g,p);s<g||t>p||o.appendChild(this.createBar({...e,startDate:toDateKey(t),endDate:toDateKey(s)},g,a,I++))}),i.appendChild(o),_.appendChild(i)}if(y.appendChild(_),r&&m>=0){const e=document.createElement("div");e.className="designbase-wc-gantt__today-line",e.style.left=`calc(var(--db-gantt-label-width) + ${m*a+a/2}px)`,_.appendChild(e)}D.appendChild(y),this.replaceChildren(D)}}customElements.get("db-gantt")||customElements.define("db-gantt",DbGantt);export{DbGantt};
|
|
1
|
+
import{dbText as e,subscribeDbLocale as t,dbFormat as a,getDbLocale as s}from"../core/i18n.js";import{createDbIcon as r}from"./db-icons.js";import{rafThrottle as n}from"../core/dom.js";const i=["day","week"],o=["#86efac","#fde047","#93c5fd","#c4b5fd","#f9a8d4","#5eead4","#fdba74","#a5b4fc"],d=["일","월","화","수","목","금","토"],l=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function parseDate(e){const[t,a,s]=e.split("-").map(Number);return new Date(t,a-1,s)}function toDateKey(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function addDays(e,t){const a=new Date(e);return a.setDate(a.getDate()+t),a}function daysBetween(e,t){const a=Date.UTC(e.getFullYear(),e.getMonth(),e.getDate()),s=Date.UTC(t.getFullYear(),t.getMonth(),t.getDate());return Math.round((s-a)/864e5)}function clampDate(e,t,a){return e<t?new Date(t):e>a?new Date(a):e}class DbGantt extends HTMLElement{constructor(){super(...arguments),this.collapsedGroups=new Set,this.dragState=null,this.reorderState=null,this.reorderDropIndex=null,this.suppressRender=!1,this.didDrag=!1,this.handlePointerMove=n(e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.updateReorderDropTarget(e.clientY);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",i,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),n=Math.round((e.clientX-this.dragState.startX)/a);0!==n&&(this.didDrag=!0);let o=new Date(this.dragState.originalStart),d=new Date(this.dragState.originalEnd);if("move"===this.dragState.mode?(o=addDays(this.dragState.originalStart,n),d=addDays(this.dragState.originalEnd,n)):"resize-start"===this.dragState.mode?(o=addDays(this.dragState.originalStart,n),o>d&&(o=new Date(d))):(d=addDays(this.dragState.originalEnd,n),d<o&&(d=new Date(o))),o=clampDate(o,s,r),d=clampDate(d,s,r),o>d)return;const l=this.items.find(e=>e.id===this.dragState.itemId);l&&this.applyBarGeometry(this.dragState.barEl,{...l,startDate:toDateKey(o),endDate:toDateKey(d)},s,a)}),this.handlePointerUp=e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.finishReorderDrag(e);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",i,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),n=Math.round((e.clientX-this.dragState.startX)/a);let o=new Date(this.dragState.originalStart),d=new Date(this.dragState.originalEnd);const l=this.dragState.mode,c=this.dragState.itemId;"move"===l?(o=addDays(this.dragState.originalStart,n),d=addDays(this.dragState.originalEnd,n)):"resize-start"===l?(o=addDays(this.dragState.originalStart,n),o>d&&(o=new Date(d))):(d=addDays(this.dragState.originalEnd,n),d<o&&(d=new Date(o))),o=clampDate(o,s,r),d=clampDate(d,s,r),this.dragState.barEl.releasePointerCapture(e.pointerId),this.dragState.barEl.classList.remove("designbase-wc-gantt__bar--dragging"),this.dragState=null;const g=this.items.find(e=>e.id===c);if(!g)return;const p=toDateKey(o),h=toDateKey(d);p===g.startDate&&h===g.endDate||(this.updateItem(c,{startDate:p,endDate:h},"move"===l?"move":"resize"),this.render())}}static get observedAttributes(){return["groups","rows","items","start-date","end-date","today","scale","cell-width","show-weekends","show-today","sidebar-label","full-width","disabled","draggable","reorderable","locale"]}get groups(){return this.parseJson("groups",[])}set groups(e){this.setAttribute("groups","string"==typeof e?e:JSON.stringify(e))}get rows(){return this.parseJson("rows",[])}set rows(e){this.setAttribute("rows","string"==typeof e?e:JSON.stringify(e))}get items(){return this.parseJson("items",[])}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label",e("프로젝트 타임라인")),this.addEventListener("pointermove",this.handlePointerMove),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.refreshLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("pointermove",this.handlePointerMove),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){!this.isConnected||this.suppressRender||this.dragState||this.reorderState||this.render()}refreshLocale(){this.setAttribute("aria-label",e("프로젝트 타임라인"));const t=this.querySelector(".designbase-wc-gantt__corner");t&&!this.getAttribute("sidebar-label")&&(t.textContent=e("할 일")),this.querySelectorAll("[data-reorder-kind]").forEach(t=>{t.setAttribute("aria-label",e("group"===t.dataset.reorderKind?"그룹 순서 변경":"행 순서 변경"))}),this.querySelectorAll("[data-summary-count]").forEach(e=>{e.title=a("{0}개 태스크",[e.dataset.summaryCount])});const{start:s,end:r}=this.getViewRange(),n=this.getDateColumns(s,r),i=this.getMonthSegments(n);this.querySelectorAll(".designbase-wc-gantt__month-cell").forEach((e,t)=>{i[t]&&(e.textContent=i[t].label)});const o=this.getWeekdays();this.querySelectorAll(".designbase-wc-gantt__day-name").forEach((e,t)=>{n[t]&&(e.textContent=o[n[t].getDay()])})}parseJson(e,t){try{return JSON.parse(this.getAttribute(e)||"null")??t}catch{return t}}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}getNumber(e,t){const a=Number(this.getAttribute(e));return Number.isFinite(a)&&a>0?a:t}getOption(e,t,a){const s=this.getAttribute(e);return s&&t.includes(s)?s:a}getLocale(){return this.getAttribute("locale")||("ko"===s()?"ko-KR":"en-US")}getWeekdays(){return this.getLocale().startsWith("ko")?d:l}getViewRange(){const e=this.getAttribute("start-date"),t=this.getAttribute("end-date");if(e&&t)return{start:parseDate(e),end:parseDate(t)};const a=this.items.flatMap(e=>[parseDate(e.startDate),parseDate(e.endDate)]);if(0===a.length){const e=new Date,t=new Date(e.getFullYear(),e.getMonth(),1);return{start:t,end:addDays(t,29)}}const s=new Date(Math.min(...a.map(e=>e.getTime()))),r=new Date(Math.max(...a.map(e=>e.getTime())));return{start:addDays(s,-2),end:addDays(r,2)}}getTodayDate(){const e=this.getAttribute("today");return e?parseDate(e):new Date}getDateColumns(e,t){const a=daysBetween(e,t)+1;return Array.from({length:a},(t,a)=>addDays(e,a))}getVisibleRows(){const e=this.groups,t=this.rows;if(0===e.length)return t.map(e=>({type:"row",row:e}));const a=[];for(const s of e)a.push({type:"group",group:s}),this.collapsedGroups.has(s.id)||t.filter(e=>e.groupId===s.id).forEach(e=>a.push({type:"row",row:e}));return t.filter(t=>!t.groupId||!e.some(e=>e.id===t.groupId)).forEach(e=>a.push({type:"row",row:e})),a}getMonthSegments(e){const t=[];let a="",s=0;for(const r of e){const e=`${r.getFullYear()}-${r.getMonth()}`;e!==a?(s>0&&t.push({label:a,span:s}),a=e,s=1):s+=1}return s>0&&t.push({label:a,span:s}),t.map(e=>{const[t,a]=e.label.split("-").map(Number);return{label:new Date(t,a,1).toLocaleDateString(this.getLocale(),{year:"numeric",month:"long"}),span:e.span}})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e[0]).join("").slice(0,2).toUpperCase()}updateItem(e,t,a){const s=this.items.map(a=>a.id===e?{...a,...t}:a);this.emitItemsChange(s,a,e)}emitItemsChange(e,t,a){this.suppressRender=!0,this.items=e,this.suppressRender=!1;const s=e.find(e=>e.id===a);this.dispatchEvent(new CustomEvent("db-item-change",{detail:{item:s,items:e,action:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:this.groups,rows:this.rows,items:e},bubbles:!0,composed:!0}))}applyBarGeometry(e,t,a,s){const r=parseDate(t.startDate),n=parseDate(t.endDate),i=daysBetween(a,r),o=daysBetween(r,n)+1;e.style.left=i*s+2+"px",e.style.width=`${Math.max(o*s-4,s-4)}px`}startBarDrag(e,t,a,s){!this.getBool("draggable",!0)||this.getBool("disabled")||t.disabled||(e.preventDefault(),e.stopPropagation(),this.didDrag=!1,s.setPointerCapture(e.pointerId),s.classList.add("designbase-wc-gantt__bar--dragging"),this.dragState={itemId:t.id,mode:a,pointerId:e.pointerId,startX:e.clientX,originalStart:parseDate(t.startDate),originalEnd:parseDate(t.endDate),barEl:s})}canReorder(){return this.getBool("reorderable",!0)&&!this.getBool("disabled")}createDragHandle(t,a,s){const n=document.createElement("span");return n.className="designbase-wc-gantt__drag-handle",n.setAttribute("role","button"),n.dataset.reorderKind=t,n.setAttribute("aria-label",e("group"===t?"그룹 순서 변경":"행 순서 변경")),n.append(r("grip-vertical",12)),this.canReorder()?(n.addEventListener("pointerdown",e=>{e.preventDefault(),e.stopPropagation(),this.startReorderDrag(e,t,a,s,n)}),n):n}getGroupIndex(e){return this.groups.findIndex(t=>t.id===e)}getRowScope(e){return this.rows.filter(t=>(t.groupId||"")===(e||""))}getRowIndexInScope(e,t){return this.getRowScope(t).findIndex(t=>t.id===e)}getReorderTargets(e,t){return Array.from(this.querySelectorAll("group"===e?".designbase-wc-gantt__label-cell--group":`.designbase-wc-gantt__label-cell--row[data-group-id="${t||""}"]`))}startReorderDrag(e,t,a,s,r){const n="group"===t?this.getGroupIndex(a):this.getRowIndexInScope(a,s);n<0||(r.setPointerCapture(e.pointerId),this.reorderState={kind:t,id:a,groupId:s,pointerId:e.pointerId,startY:e.clientY,fromIndex:n,captureEl:r},this.classList.add("designbase-wc-gantt--reordering"),this.updateReorderDropTarget(e.clientY))}updateReorderDropTarget(e){if(!this.reorderState)return;const t=this.getReorderTargets(this.reorderState.kind,this.reorderState.groupId);let a=null;t.forEach((t,s)=>{const r=t.getBoundingClientRect(),n=r.top+r.height/2,i=e>=r.top&&e<=r.bottom,o=e>n;t.classList.toggle("designbase-wc-gantt__label-cell--drag-over",i),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-before",i&&!o),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-after",i&&o),i&&(a=o?s+1:s)}),this.reorderDropIndex=a}clearReorderIndicators(){this.querySelectorAll(".designbase-wc-gantt__label-cell--drag-over").forEach(e=>{e.classList.remove("designbase-wc-gantt__label-cell--drag-over","designbase-wc-gantt__label-cell--drag-over-before","designbase-wc-gantt__label-cell--drag-over-after")})}finishReorderDrag(e){if(!this.reorderState)return;const{kind:t,id:a,groupId:s,fromIndex:r,captureEl:n}=this.reorderState;try{n.releasePointerCapture(this.reorderState.pointerId)}catch{}const i=this.reorderDropIndex;if(this.reorderState=null,this.reorderDropIndex=null,this.classList.remove("designbase-wc-gantt--reordering"),this.clearReorderIndicators(),null===i)return;const o=i>r?i-1:i;o<0||o===r||("group"===t?this.reorderGroups(r,o,a):this.reorderRows(r,o,a,s))}emitStructureChange(e,t,a,s){this.suppressRender=!0,this.groups=e,this.rows=t,this.suppressRender=!1,this.dispatchEvent(new CustomEvent(s,{detail:{...a,groups:e,rows:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:e,rows:t,items:this.items},bubbles:!0,composed:!0})),this.render()}reorderGroups(e,t,a){const s=[...this.groups],[r]=s.splice(e,1);r&&(s.splice(t,0,r),this.emitStructureChange(s,this.rows,{groupId:a,fromIndex:e,toIndex:t},"db-group-reorder"))}reorderRows(e,t,a,s){const r=this.getRowScope(s),n=[...r],[i]=n.splice(e,1);if(!i)return;n.splice(t,0,i);const o=new Set(r.map(e=>e.id)),d=[];let l=!1;for(const e of this.rows)o.has(e.id)?l||(d.push(...n),l=!0):d.push(e);l||d.push(...n),this.emitStructureChange(this.groups,d,{rowId:a,groupId:s,fromIndex:e,toIndex:t},"db-row-reorder")}createGroupBadge(e){const t=document.createElement("db-badge");return t.className="designbase-wc-gantt__group-badge",t.setAttribute("type","dot"),t.setAttribute("size","s"),t.setAttribute("variant","primary"),t.setAttribute("aria-hidden","true"),e&&t.style.setProperty("--db-gantt-badge-color",e),t}createGroupChevron(e){const t=document.createElement("span");return t.className=["designbase-wc-gantt__group-chevron",e?"designbase-wc-gantt__group-chevron--collapsed":""].filter(Boolean).join(" "),t.append(r("chevron-down",12)),t}createAssignee(e){const t=document.createElement("span");if(t.className="designbase-wc-gantt__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.src=e.avatar,a.alt=e.name,t.appendChild(a)}else t.textContent=this.getInitials(e);return t}createStatusIcon(e){const t=document.createElement("span");return t.className=`designbase-wc-gantt__status designbase-wc-gantt__status--${e}`,t.setAttribute("aria-hidden","true"),t.textContent="completed"===e?"✓":"!",t}deriveSummaryColor(e,t){if(0===e.length)return t||o[0];const a=e.filter(e=>e.color);if(0===a.length)return t||o[0];return a.reduce((e,t)=>{const a=daysBetween(parseDate(e.startDate),parseDate(e.endDate));return daysBetween(parseDate(t.startDate),parseDate(t.endDate))>a?t:e}).color||t||o[0]}getGroupSummary(e,t){const a=this.rows.filter(t=>t.groupId===e),s=this.items.filter(e=>a.some(t=>t.id===e.rowId));if(0===s.length)return null;const r=s.map(e=>parseDate(e.startDate).getTime()),n=s.map(e=>parseDate(e.endDate).getTime()),i=s.map(e=>e.progress).filter(e=>"number"==typeof e);return{startDate:toDateKey(new Date(Math.min(...r))),endDate:toDateKey(new Date(Math.max(...n))),color:this.deriveSummaryColor(s,t),progress:i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0,count:s.length}}applyBarTone(e,t){const a=function deriveBarTone(e){return{base:`color-mix(in srgb, ${e} 42%, white)`,progress:`color-mix(in srgb, ${e} 58%, white)`}}(t);e.style.setProperty("--db-gantt-bar-color",t),e.style.setProperty("--db-gantt-bar-bg",a.base),e.style.setProperty("--db-gantt-bar-progress-bg",a.progress)}createGroupSummaryBar(e,t,s,r){const n=clampDate(parseDate(e.startDate),t,s),i=clampDate(parseDate(e.endDate),t,s);if(i<t||n>s)return null;const o=daysBetween(t,n),d=daysBetween(n,i)+1,l=Math.min(100,Math.max(0,e.progress)),c=document.createElement("div");if(c.className="designbase-wc-gantt__group-summary",c.setAttribute("aria-hidden","true"),c.dataset.summaryCount=String(e.count),c.title=a("{0}개 태스크",[e.count]),this.applyBarTone(c,e.color),c.style.left=o*r+2+"px",c.style.width=`${Math.max(d*r-4,r-4)}px`,l>0){const e=document.createElement("span");e.className="designbase-wc-gantt__group-summary-progress",e.style.width=`${l}%`,c.appendChild(e)}return c}createBar(e,t,a,s){const r=e.color||o[s%o.length],n=document.createElement("div");n.className="designbase-wc-gantt__bar",n.setAttribute("role","button"),n.setAttribute("tabindex",e.disabled?"-1":"0"),n.setAttribute("aria-disabled",String(Boolean(e.disabled)||this.getBool("disabled"))),n.setAttribute("aria-label",`${e.title}, ${e.startDate} – ${e.endDate}`),this.applyBarTone(n,r),e.disabled&&n.classList.add("designbase-wc-gantt__bar--disabled"),this.applyBarGeometry(n,e,t,a);const i="number"==typeof e.progress?Math.min(100,Math.max(0,e.progress)):0;if(i>0){const e=document.createElement("span");e.className="designbase-wc-gantt__bar-progress",e.style.width=`${i}%`,n.appendChild(e)}const d=document.createElement("div");d.className="designbase-wc-gantt__bar-body","delayed"!==e.status&&"at-risk"!==e.status||d.appendChild(this.createStatusIcon(e.status));const l=document.createElement("span");l.className="designbase-wc-gantt__bar-label",l.textContent=e.title,d.appendChild(l),e.assignee&&d.appendChild(this.createAssignee(e.assignee));const c=document.createElement("span");c.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--start",c.setAttribute("aria-hidden","true");const g=document.createElement("span");return g.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--end",g.setAttribute("aria-hidden","true"),n.append(c,d,g),e.disabled||!this.getBool("draggable",!0)||this.getBool("disabled")||(c.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-start",n)),g.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-end",n)),d.addEventListener("pointerdown",t=>{t.target.closest(".designbase-wc-gantt__bar-handle")||this.startBarDrag(t,e,"move",n)})),n.addEventListener("click",t=>{this.dragState||this.didDrag?this.didDrag=!1:(t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:e},bubbles:!0,composed:!0})))}),n}toggleGroup(e){this.collapsedGroups.has(e)?this.collapsedGroups.delete(e):this.collapsedGroups.add(e),this.dispatchEvent(new CustomEvent("db-group-toggle",{detail:{groupId:e,collapsed:this.collapsedGroups.has(e)},bubbles:!0,composed:!0})),this.render()}render(){const t=this.items,a=this.getOption("scale",i,"day"),s=this.getNumber("cell-width","week"===a?72:44),r=this.getBool("show-weekends",!0),n=this.getBool("show-today",!0),d=this.getAttribute("sidebar-label")||e("할 일"),l=this.getBool("disabled"),c=this.getBool("full-width",!0),g=this.getWeekdays(),{start:p,end:h}=this.getViewRange(),u=this.getDateColumns(p,h),m=toDateKey(this.getTodayDate()),b=u.findIndex(e=>toDateKey(e)===m),w=this.getVisibleRows(),D=u.length*s,y=document.createElement("div");y.className=["designbase-wc-gantt",c?"designbase-wc-gantt--full-width":"",l?"designbase-wc-gantt--disabled":"",this.getBool("draggable",!0)?"designbase-wc-gantt--draggable":""].filter(Boolean).join(" ");const _=document.createElement("div");_.className="designbase-wc-gantt__viewport";const f=document.createElement("div");f.className="designbase-wc-gantt__grid",f.style.setProperty("--db-gantt-chart-width",`${D}px`),f.style.setProperty("--db-gantt-cell-width",`${s}px`);const S=document.createElement("div");S.className="designbase-wc-gantt__corner",S.textContent=d,f.appendChild(S);const E=document.createElement("div");E.className="designbase-wc-gantt__date-header";const v=document.createElement("div");v.className="designbase-wc-gantt__month-row";for(const e of this.getMonthSegments(u)){const t=document.createElement("div");t.className="designbase-wc-gantt__month-cell",t.style.width=e.span*s+"px",t.textContent=e.label,v.appendChild(t)}E.appendChild(v);const C=document.createElement("div");C.className="designbase-wc-gantt__day-row";for(const e of u){const t=toDateKey(e)===m,a=0===e.getDay()||6===e.getDay(),i=document.createElement("div");i.className=["designbase-wc-gantt__day-cell",t&&n?"designbase-wc-gantt__day-cell--today":"",a&&r?"designbase-wc-gantt__day-cell--weekend":""].filter(Boolean).join(" "),i.style.width=`${s}px`;const o=document.createElement("span");o.className="designbase-wc-gantt__day-num",o.textContent=String(e.getDate());const d=document.createElement("span");d.className="designbase-wc-gantt__day-name",d.textContent=g[e.getDay()],i.append(o,d),C.appendChild(i)}E.appendChild(C),f.appendChild(E);const I=new Map;t.forEach((e,t)=>{const a=I.get(e.rowId)||[];a.push({...e,color:e.color||o[t%o.length]}),I.set(e.rowId,a)});let x=0;for(const e of w){if("group"===e.type){const{group:t}=e,a=this.collapsedGroups.has(t.id),n=document.createElement("button");n.type="button",n.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--group",n.setAttribute("aria-expanded",String(!a)),n.dataset.groupId=t.id;const i=document.createElement("span");i.className="designbase-wc-gantt__group-title",i.textContent=t.title,n.append(this.createDragHandle("group",t.id),this.createGroupChevron(a),this.createGroupBadge(t.color),i),n.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.toggleGroup(t.id)}),f.appendChild(n);const o=document.createElement("div");if(o.className="designbase-wc-gantt__track-cell designbase-wc-gantt__track-cell--group",a){const e=this.getGroupSummary(t.id,t.color);if(e){const t=document.createElement("div");t.className="designbase-wc-gantt__grid-bg",u.forEach(e=>{const a=document.createElement("div"),n=0===e.getDay()||6===e.getDay();a.className=["designbase-wc-gantt__grid-cell",n&&r?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),a.style.width=`${s}px`,t.appendChild(a)}),o.appendChild(t);const a=document.createElement("div");a.className="designbase-wc-gantt__group-summary-wrap";const n=this.createGroupSummaryBar(e,p,h,s);n&&a.appendChild(n),o.appendChild(a)}}f.appendChild(o);continue}const{row:t}=e,a=document.createElement("button");a.type="button",a.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--row",a.dataset.groupId=t.groupId||"",a.dataset.rowId=t.id;const n=document.createElement("span");n.className="designbase-wc-gantt__row-title",n.textContent=t.label,a.append(this.createDragHandle("row",t.id,t.groupId),n),a.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.dispatchEvent(new CustomEvent("db-row-click",{detail:{row:t},bubbles:!0,composed:!0}))}),f.appendChild(a);const i=document.createElement("div");i.className="designbase-wc-gantt__track-cell";const o=document.createElement("div");o.className="designbase-wc-gantt__grid-bg",u.forEach(e=>{const t=document.createElement("div"),a=0===e.getDay()||6===e.getDay();t.className=["designbase-wc-gantt__grid-cell",a&&r?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),t.style.width=`${s}px`,o.appendChild(t)}),i.appendChild(o);const d=document.createElement("div");d.className="designbase-wc-gantt__bars",(I.get(t.id)||[]).forEach(e=>{const t=clampDate(parseDate(e.startDate),p,h),a=clampDate(parseDate(e.endDate),p,h);a<p||t>h||d.appendChild(this.createBar({...e,startDate:toDateKey(t),endDate:toDateKey(a)},p,s,x++))}),i.appendChild(d),f.appendChild(i)}if(_.appendChild(f),n&&b>=0){const e=document.createElement("div");e.className="designbase-wc-gantt__today-line",e.style.left=`calc(var(--db-gantt-label-width) + ${b*s+s/2}px)`,f.appendChild(e)}y.appendChild(_),this.replaceChildren(y)}}customElements.get("db-gantt")||customElements.define("db-gantt",DbGantt);export{DbGantt};
|