@designbasekorea/ui-wc 0.10.0 → 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.
Files changed (156) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE-WORLD-MAP.md +10 -0
  3. package/README.md +58 -0
  4. package/dist/esm/components/db-achievement-list.d.ts +2 -0
  5. package/dist/esm/components/db-achievement-list.js +1 -1
  6. package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
  7. package/dist/esm/components/db-activity-heatmap.js +1 -1
  8. package/dist/esm/components/db-ad-banner.d.ts +2 -0
  9. package/dist/esm/components/db-ad-banner.js +1 -1
  10. package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
  11. package/dist/esm/components/db-ai-chat-list.js +1 -1
  12. package/dist/esm/components/db-ai-chat.d.ts +2 -0
  13. package/dist/esm/components/db-ai-chat.js +1 -1
  14. package/dist/esm/components/db-ai-file-tree.js +1 -1
  15. package/dist/esm/components/db-alert.d.ts +1 -0
  16. package/dist/esm/components/db-alert.js +1 -1
  17. package/dist/esm/components/db-audio-player.d.ts +2 -0
  18. package/dist/esm/components/db-audio-player.js +1 -1
  19. package/dist/esm/components/db-avatar.d.ts +1 -0
  20. package/dist/esm/components/db-avatar.js +1 -1
  21. package/dist/esm/components/db-banner.d.ts +2 -0
  22. package/dist/esm/components/db-banner.js +1 -1
  23. package/dist/esm/components/db-button.d.ts +7 -1
  24. package/dist/esm/components/db-button.js +1 -1
  25. package/dist/esm/components/db-calendar.d.ts +5 -0
  26. package/dist/esm/components/db-calendar.js +1 -1
  27. package/dist/esm/components/db-card.d.ts +1 -0
  28. package/dist/esm/components/db-card.js +1 -1
  29. package/dist/esm/components/db-chat-composer.d.ts +3 -0
  30. package/dist/esm/components/db-chat-composer.js +1 -1
  31. package/dist/esm/components/db-chat-message.d.ts +2 -0
  32. package/dist/esm/components/db-chat-message.js +1 -1
  33. package/dist/esm/components/db-chat-room.d.ts +1 -0
  34. package/dist/esm/components/db-chat-room.js +1 -1
  35. package/dist/esm/components/db-chat-typing.d.ts +2 -0
  36. package/dist/esm/components/db-chat-typing.js +1 -1
  37. package/dist/esm/components/db-chat-widget.d.ts +9 -0
  38. package/dist/esm/components/db-chat-widget.js +1 -1
  39. package/dist/esm/components/db-chip.d.ts +2 -0
  40. package/dist/esm/components/db-chip.js +1 -1
  41. package/dist/esm/components/db-code-block.d.ts +1 -0
  42. package/dist/esm/components/db-code-block.js +1 -1
  43. package/dist/esm/components/db-color-picker.d.ts +4 -0
  44. package/dist/esm/components/db-color-picker.js +1 -1
  45. package/dist/esm/components/db-color-swatch.d.ts +3 -0
  46. package/dist/esm/components/db-color-swatch.js +1 -1
  47. package/dist/esm/components/db-cookie-banner.d.ts +3 -0
  48. package/dist/esm/components/db-cookie-banner.js +1 -1
  49. package/dist/esm/components/db-countdown.d.ts +2 -1
  50. package/dist/esm/components/db-countdown.js +1 -1
  51. package/dist/esm/components/db-date-picker.d.ts +3 -0
  52. package/dist/esm/components/db-date-picker.js +1 -1
  53. package/dist/esm/components/db-dropdown.d.ts +1 -0
  54. package/dist/esm/components/db-dropdown.js +1 -1
  55. package/dist/esm/components/db-dropzone.d.ts +2 -0
  56. package/dist/esm/components/db-dropzone.js +1 -1
  57. package/dist/esm/components/db-email-verify.d.ts +1 -0
  58. package/dist/esm/components/db-email-verify.js +1 -1
  59. package/dist/esm/components/db-file-uploader.d.ts +2 -0
  60. package/dist/esm/components/db-file-uploader.js +1 -1
  61. package/dist/esm/components/db-form.d.ts +2 -0
  62. package/dist/esm/components/db-form.js +1 -1
  63. package/dist/esm/components/db-gantt.d.ts +2 -0
  64. package/dist/esm/components/db-gantt.js +1 -1
  65. package/dist/esm/components/db-image-list.d.ts +3 -0
  66. package/dist/esm/components/db-image-list.js +1 -1
  67. package/dist/esm/components/db-image.d.ts +1 -0
  68. package/dist/esm/components/db-image.js +1 -1
  69. package/dist/esm/components/db-input-group.d.ts +30 -0
  70. package/dist/esm/components/db-input-group.js +1 -0
  71. package/dist/esm/components/db-input.d.ts +1 -0
  72. package/dist/esm/components/db-input.js +1 -1
  73. package/dist/esm/components/db-kanban.d.ts +3 -0
  74. package/dist/esm/components/db-kanban.js +1 -1
  75. package/dist/esm/components/db-lightbox.d.ts +2 -0
  76. package/dist/esm/components/db-lightbox.js +1 -1
  77. package/dist/esm/components/db-list.d.ts +2 -0
  78. package/dist/esm/components/db-list.js +1 -1
  79. package/dist/esm/components/db-markdown-editor.d.ts +2 -0
  80. package/dist/esm/components/db-markdown-editor.js +1 -1
  81. package/dist/esm/components/db-menu-item.js +1 -1
  82. package/dist/esm/components/db-navbar.d.ts +3 -0
  83. package/dist/esm/components/db-navbar.js +1 -1
  84. package/dist/esm/components/db-node.d.ts +1 -0
  85. package/dist/esm/components/db-node.js +1 -1
  86. package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
  87. package/dist/esm/components/db-onboarding-modal.js +1 -1
  88. package/dist/esm/components/db-otp-input.d.ts +4 -1
  89. package/dist/esm/components/db-otp-input.js +1 -1
  90. package/dist/esm/components/db-page-header.js +1 -1
  91. package/dist/esm/components/db-popover.d.ts +1 -0
  92. package/dist/esm/components/db-popover.js +1 -1
  93. package/dist/esm/components/db-progress-step.d.ts +2 -0
  94. package/dist/esm/components/db-progress-step.js +1 -1
  95. package/dist/esm/components/db-range-slider.d.ts +1 -0
  96. package/dist/esm/components/db-range-slider.js +1 -1
  97. package/dist/esm/components/db-rating.d.ts +1 -0
  98. package/dist/esm/components/db-rating.js +1 -1
  99. package/dist/esm/components/db-search-bar.d.ts +2 -0
  100. package/dist/esm/components/db-search-bar.js +1 -1
  101. package/dist/esm/components/db-section-logo-cloud.js +1 -1
  102. package/dist/esm/components/db-share.d.ts +5 -0
  103. package/dist/esm/components/db-share.js +1 -1
  104. package/dist/esm/components/db-sidebar.d.ts +3 -0
  105. package/dist/esm/components/db-sidebar.js +1 -1
  106. package/dist/esm/components/db-signature.d.ts +2 -0
  107. package/dist/esm/components/db-signature.js +1 -1
  108. package/dist/esm/components/db-spinner.d.ts +2 -0
  109. package/dist/esm/components/db-spinner.js +1 -1
  110. package/dist/esm/components/db-stepper.d.ts +2 -0
  111. package/dist/esm/components/db-stepper.js +1 -1
  112. package/dist/esm/components/db-table.d.ts +2 -0
  113. package/dist/esm/components/db-table.js +1 -1
  114. package/dist/esm/components/db-tabs.d.ts +1 -0
  115. package/dist/esm/components/db-tabs.js +1 -1
  116. package/dist/esm/components/db-ticket.js +1 -1
  117. package/dist/esm/components/db-time-picker.d.ts +2 -0
  118. package/dist/esm/components/db-time-picker.js +1 -1
  119. package/dist/esm/components/db-timeline.d.ts +4 -0
  120. package/dist/esm/components/db-timeline.js +1 -1
  121. package/dist/esm/components/db-toast.d.ts +2 -0
  122. package/dist/esm/components/db-toast.js +1 -1
  123. package/dist/esm/components/db-tool-layout.d.ts +92 -0
  124. package/dist/esm/components/db-tool-layout.js +1 -0
  125. package/dist/esm/components/db-tool-panel.d.ts +50 -0
  126. package/dist/esm/components/db-tool-panel.js +1 -0
  127. package/dist/esm/components/db-top-banner.d.ts +2 -0
  128. package/dist/esm/components/db-top-banner.js +1 -1
  129. package/dist/esm/components/db-video-player.d.ts +3 -0
  130. package/dist/esm/components/db-video-player.js +1 -1
  131. package/dist/esm/components/db-world-map.d.ts +60 -0
  132. package/dist/esm/components/db-world-map.js +1 -0
  133. package/dist/esm/components/db-youtube-player.d.ts +2 -0
  134. package/dist/esm/components/db-youtube-player.js +1 -1
  135. package/dist/esm/components/db-zoom-control.d.ts +52 -0
  136. package/dist/esm/components/db-zoom-control.js +1 -0
  137. package/dist/esm/components/input-validation.js +1 -1
  138. package/dist/esm/components/paper-card.d.ts +2 -0
  139. package/dist/esm/components/paper-card.js +1 -1
  140. package/dist/esm/core/i18n-copy.js +1 -1
  141. package/dist/esm/core/i18n-en.js +1 -1
  142. package/dist/esm/core/i18n.d.ts +31 -1
  143. package/dist/esm/core/i18n.js +1 -1
  144. package/dist/esm/helpers/world-countries.js +1 -0
  145. package/dist/esm/helpers/world-land.js +1 -0
  146. package/dist/esm/index.d.ts +6 -1
  147. package/dist/esm/index.js +1 -1
  148. package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
  149. package/dist/index.cjs +1 -1
  150. package/dist/index.css +1 -1
  151. package/dist/index.d.ts +442 -6
  152. package/dist/index.esm.js +1 -1
  153. package/dist/react/index.cjs +1 -1
  154. package/dist/react/index.d.ts +837 -71
  155. package/dist/react/index.esm.js +1 -1
  156. package/package.json +4 -3
@@ -1 +1 @@
1
- import{dbFormat as e,dbText as t}from"../core/i18n.js";import{createShareIcon as s,createSharePlatformIcon as r}from"./db-share-icons.js";import{sanitizeHref as n}from"../core/safe-url.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{SHARE_VARIANTS as a,SHARE_SIZES as o,SHARE_POSITIONS as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const c=["facebook","x","linkedin","whatsapp","email","link"],h={facebook:{name:"Facebook",color:"#1877f2",shareUrl:"https://www.facebook.com/sharer/sharer.php?u={url}"},x:{name:"X",color:"#000000",shareUrl:"https://twitter.com/intent/tweet?url={url}&text={title}&hashtags={hashtags}"},instagram:{name:"Instagram",color:"#e4405f",shareUrl:"https://www.instagram.com/",customShare:()=>{window.alert("Instagram에 직접 공유하려면 링크를 복사하여 사용하세요.")}},linkedin:{name:"LinkedIn",color:"#0077b5",shareUrl:"https://www.linkedin.com/sharing/share-offsite/?url={url}"},pinterest:{name:"Pinterest",color:"#bd081c",shareUrl:"https://pinterest.com/pin/create/button/?url={url}&description={title}&media={imageUrl}"},whatsapp:{name:"WhatsApp",color:"#25d366",shareUrl:"https://wa.me/?text={title}%20{url}"},telegram:{name:"Telegram",color:"#0088cc",shareUrl:"https://t.me/share/url?url={url}&text={title}"},email:{name:"이메일",color:"#ea4335",shareUrl:"mailto:?subject={title}&body={description}%20{url}"},link:{name:"링크 복사",color:"#6c757d",shareUrl:""},qr:{name:"QR 코드",color:"#6c757d",shareUrl:""}};class DbShare extends HTMLElement{constructor(){super(...arguments),this.isCopied=!1,this.qrCodeData="",this.copyResetTimer=null,this.modalEl=null,this.contentSlot=null,this.dropdownEl=null}static get observedAttributes(){return["url","title","description","image-url","hashtags","variant","size","position","platforms","button-text","modal-title","show-qr-code","qr-code-size","copy-success-message","open"]}connectedCallback(){this.render()}disconnectedCallback(){this.copyResetTimer&&clearTimeout(this.copyResetTimer)}getVariant(){return i(this.getAttribute("variant"),a,"button")}getSize(){return i(this.getAttribute("size"),o,"m")}getPosition(){return i(this.getAttribute("position"),l,"bottom")}attributeChangedCallback(e){"open"===e&&"modal"===this.getVariant()&&this.modalEl?this.syncModalOpen():"url"===e&&this.contentSlot?this.refreshLinkInputValue():this.render()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(e){e?this.setAttribute("open","true"):this.removeAttribute("open")}parseListAttribute(e){const t=this.getAttribute(e);if(!t)return[];try{const e=JSON.parse(t);if(Array.isArray(e))return e.map(e=>String(e).trim()).filter(Boolean)}catch{}return t.split(",").map(e=>e.trim()).filter(Boolean)}getResolvedUrl(){const e=this.getAttribute("url");return e?n(e,""):"undefined"!=typeof window&&window.location?.href?n(window.location.href,""):""}getContext(){return{url:this.getResolvedUrl(),title:this.getAttribute("share-title")||this.getAttribute("title")||"",description:this.getAttribute("description")||"",imageUrl:this.getAttribute("image-url")||"",hashtags:this.parseListAttribute("hashtags"),host:this}}getActivePlatforms(){const e=this.parseListAttribute("platforms");return(e.length>0?e:c).filter(e=>e in h)}replaceUrlVariables(e,t){return e.replace("{url}",encodeURIComponent(t.url)).replace("{title}",encodeURIComponent(t.title)).replace("{description}",encodeURIComponent(t.description)).replace("{imageUrl}",encodeURIComponent(t.imageUrl)).replace("{hashtags}",t.hashtags.join(","))}async handleCopyLink(e){try{await navigator.clipboard.writeText(e.url),this.isCopied=!0,this.dispatchEvent(new CustomEvent("db-copy-success",{bubbles:!0,composed:!0,detail:{url:e.url}})),this.refreshContent(),this.copyResetTimer&&clearTimeout(this.copyResetTimer),this.copyResetTimer=setTimeout(()=>{this.isCopied=!1,this.refreshContent()},3e3)}catch(e){this.dispatchEvent(new CustomEvent("db-copy-error",{bubbles:!0,composed:!0,detail:{error:e}}))}}handleShowQrCode(e){if(this.qrCodeData=e.url,"modal"===this.getVariant())return this.open=!0,void this.refreshContent();this.refreshContent()}handlePlatformShare(e){const t=this.getContext(),s=h[e];if(s)try{if("link"===e)this.handleCopyLink(t);else if("qr"===e)this.handleShowQrCode(t);else if(s.customShare)s.customShare(t);else if(s.shareUrl){const e=this.replaceUrlVariables(s.shareUrl,t),r=n(e,"");if(!r)throw new Error("Invalid share URL");window.open(r,"_blank","noopener,noreferrer,width=600,height=400")}this.dispatchEvent(new CustomEvent("db-share",{bubbles:!0,composed:!0,detail:{platform:e,url:t.url}}))}catch(t){this.dispatchEvent(new CustomEvent("db-share-error",{bubbles:!0,composed:!0,detail:{platform:e,error:t}}))}}getPlacement(){const e=this.getPosition();return"top"===e||"left"===e?"top-left":"right"===e?"bottom-right":"bottom-left"}mapButtonSize(){const e=this.getSize();return"s"===e?"s":"l"===e?"l":"m"}createTriggerButton(e){const t=document.createElement("db-button");return t.className=e||"designbase-wc-share__trigger",t.setAttribute("variant","secondary"),t.setAttribute("size",this.mapButtonSize()),t.textContent=this.getAttribute("button-text")||"공유",t.prepend(s("share-alt",16)),t.addEventListener("db-click",()=>{"modal"!==this.getVariant()?this.open=!this.open:this.open=!0}),t}createPlatformIcon(e){const t=document.createElement("span");return t.className="designbase-wc-share__platform-icon",t.append(r(e,24)),t}createPlatformButton(r){const n=h[r],i=document.createElement("button");i.type="button",i.className=["designbase-wc-share__platform-button",`designbase-wc-share__platform-button--${r}`,"link"===r&&this.isCopied?"designbase-wc-share__platform-button--copied":""].filter(Boolean).join(" "),i.style.setProperty("--platform-color",n.color),i.title=n.name,i.setAttribute("aria-label",e("{0}에 공유하기",[n.name])),i.append(this.createPlatformIcon(r));const a=document.createElement("span");if(a.className="designbase-wc-share__platform-name",a.textContent=n.name,i.append(a),"link"===r&&this.isCopied){const e=document.createElement("span");e.className="designbase-wc-share__copy-success",e.append(s("copy",12));const r=document.createElement("span");r.textContent=t("복사됨!"),e.append(r),i.append(e)}return i.addEventListener("click",()=>this.handlePlatformShare(r)),i}createLinkInput(e){const t=document.createElement("db-input");return t.className="designbase-wc-share__link-input",t.setAttribute("type","text"),t.setAttribute("readonly",""),t.setAttribute("size","s"),t.setAttribute("full-width",""),t.setAttribute("value",e),customElements.whenDefined("db-input").then(()=>{t.setAttribute("value",e),t.value=e}),t}refreshLinkInputValue(){const e=this.getResolvedUrl(),t=this.contentSlot?.querySelector("db-input.designbase-wc-share__link-input");t&&(t.setAttribute("value",e),t.value=e)}createCopyButton(e){const t=document.createElement("db-button");t.className="designbase-wc-share__copy-button",t.setAttribute("size","s"),t.setAttribute("variant","primary");const r=document.createElement("span");return r.className="designbase-wc-button__start-icon",r.setAttribute("aria-hidden","true"),r.append(s(this.isCopied?"copy":"link",16)),t.append(r),t.append(document.createTextNode(this.isCopied?"복사됨!":"복사")),t.addEventListener("db-click",()=>{this.handleCopyLink(e)}),t}generateQrCodeUrl(){const e=Number(this.getAttribute("qr-code-size")||200);return`https://api.qrserver.com/v1/create-qr-code/?size=${e}x${e}&data=${encodeURIComponent(this.qrCodeData)}`}createShareContent(){const e=document.createElement("div");return e.className="designbase-wc-share__content",this.populateShareContent(e),e}populateShareContent(e){const s=document.createElement("div");s.className="designbase-wc-share__platforms",this.getActivePlatforms().forEach(e=>{s.append(this.createPlatformButton(e))}),e.append(s);if("false"!==this.getAttribute("show-qr-code")&&this.qrCodeData){const s=document.createElement("div");s.className="designbase-wc-share__qr-section";const r=document.createElement("h4");r.className="designbase-wc-share__qr-title",r.textContent=t("QR 코드"),s.append(r);const n=document.createElement("div");n.className="designbase-wc-share__qr-code";const i=document.createElement("img"),a=Number(this.getAttribute("qr-code-size")||200);i.src=this.generateQrCodeUrl(),i.alt="QR Code",i.width=a,i.height=a,n.append(i),s.append(n);const o=document.createElement("p");o.className="designbase-wc-share__qr-description",o.textContent=t("QR 코드를 스캔하여 링크에 접속하세요"),s.append(o),e.append(s)}const r=this.getContext(),n=document.createElement("div");n.className="designbase-wc-share__link-preview";const i=document.createElement("h4");i.className="designbase-wc-share__link-title",i.textContent=t("공유 링크"),n.append(i);const a=document.createElement("div");a.className="designbase-wc-share__link-container",a.append(this.createLinkInput(r.url)),a.append(this.createCopyButton(r)),n.append(a),e.append(n)}refreshContent(){const e=this.getVariant();if("inline"===e){const e=this.querySelector(":scope > .designbase-wc-share__content");return void e?.replaceWith(this.createShareContent())}"modal"===e&&this.contentSlot&&(this.contentSlot.replaceChildren(),this.populateShareContent(this.contentSlot))}syncModalOpen(){this.modalEl&&(this.open?(this.refreshLinkInputValue(),this.modalEl.setAttribute("open","true")):this.modalEl.removeAttribute("open"))}renderDropdown(){const e=document.createElement("db-dropdown");e.className="designbase-wc-share__dropdown",e.setAttribute("placement",this.getPlacement()),e.setAttribute("label",this.getAttribute("button-text")||"공유"),e.setAttribute("trigger-variant","secondary"),e.setAttribute("trigger-icon","share-alt"),e.setAttribute("size",this.mapButtonSize()),e.setAttribute("items",JSON.stringify(this.getActivePlatforms().map(e=>({id:e,label:h[e].name})))),e.addEventListener("db-change",e=>{const t=e.detail,s=t?.id;s&&this.handlePlatformShare(s)}),this.dropdownEl=e,this.append(e)}renderModal(){const e=this.createTriggerButton();this.append(e);const t=document.createElement("db-modal");t.className="designbase-wc-share__modal",t.setAttribute("title",this.getAttribute("modal-title")||"공유하기"),t.setAttribute("size","m"),this.contentSlot=document.createElement("div"),this.contentSlot.className="designbase-wc-share designbase-wc-share__content",this.contentSlot.setAttribute("data-modal-part","body"),this.populateShareContent(this.contentSlot),t.append(this.contentSlot),t.addEventListener("db-close",()=>{this.open=!1,this.qrCodeData="",this.contentSlot&&(this.contentSlot.replaceChildren(),this.populateShareContent(this.contentSlot))}),this.modalEl=t,this.append(t),this.syncModalOpen()}render(){const e=this.getVariant();this.className=`designbase-wc-share designbase-wc-share--${e}`,this.replaceChildren(),this.modalEl=null,this.contentSlot=null,this.dropdownEl=null,"inline"!==e?"dropdown"!==e?"modal"!==e?this.append(this.createTriggerButton()):this.renderModal():this.renderDropdown():this.append(this.createShareContent())}}customElements.get("db-share")||customElements.define("db-share",DbShare);export{DbShare};
1
+ import{subscribeDbLocale as t,dbText as e,dbFormat as s}from"../core/i18n.js";import{createShareIcon as r,createSharePlatformIcon as n}from"./db-share-icons.js";import{sanitizeHref as i}from"../core/safe-url.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{SHARE_VARIANTS as o,SHARE_SIZES as l,SHARE_POSITIONS as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const h=["facebook","x","linkedin","whatsapp","email","link"],d={facebook:{name:"Facebook",color:"#1877f2",shareUrl:"https://www.facebook.com/sharer/sharer.php?u={url}"},x:{name:"X",color:"#000000",shareUrl:"https://twitter.com/intent/tweet?url={url}&text={title}&hashtags={hashtags}"},instagram:{name:"Instagram",color:"#e4405f",shareUrl:"https://www.instagram.com/",customShare:()=>{window.alert(e("Instagram에 직접 공유하려면 링크를 복사하여 사용하세요."))}},linkedin:{name:"LinkedIn",color:"#0077b5",shareUrl:"https://www.linkedin.com/sharing/share-offsite/?url={url}"},pinterest:{name:"Pinterest",color:"#bd081c",shareUrl:"https://pinterest.com/pin/create/button/?url={url}&description={title}&media={imageUrl}"},whatsapp:{name:"WhatsApp",color:"#25d366",shareUrl:"https://wa.me/?text={title}%20{url}"},telegram:{name:"Telegram",color:"#0088cc",shareUrl:"https://t.me/share/url?url={url}&text={title}"},email:{name:"이메일",color:"#ea4335",shareUrl:"mailto:?subject={title}&body={description}%20{url}"},link:{name:"링크 복사",color:"#6c757d",shareUrl:""},qr:{name:"QR 코드",color:"#6c757d",shareUrl:""}};class DbShare extends HTMLElement{constructor(){super(...arguments),this.isCopied=!1,this.qrCodeData="",this.copyResetTimer=null,this.modalEl=null,this.contentSlot=null,this.dropdownEl=null}static get observedAttributes(){return["url","title","share-title","description","image-url","hashtags","variant","size","position","platforms","button-text","modal-title","show-qr-code","qr-code-size","copy-success-message","open"]}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.syncLocale()),this.render()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.copyResetTimer&&clearTimeout(this.copyResetTimer)}platformName(t){return["email","link","qr"].includes(t)?e(d[t].name):d[t].name}platformAriaLabel(t){return"email"===t?e("이메일로 공유"):"link"===t?e("링크 복사"):"qr"===t?e("QR 코드 보기"):s("{0}에 공유하기",[this.platformName(t)])}copySuccessLabel(){return this.getAttribute("copy-success-message")||e("복사됨!")}syncLocale(){const t=this.contentSlot||this,s=this.querySelector(".designbase-wc-share__trigger"),r=s&&Array.from(s.childNodes).find(t=>t.nodeType===Node.TEXT_NODE);r&&(r.textContent=this.getAttribute("button-text")||e("공유")),this.modalEl&&this.modalEl.setAttribute("title",this.getAttribute("modal-title")||e("공유하기")),t.querySelectorAll("[data-share-platform]").forEach(t=>{const e=t.dataset.sharePlatform,s=this.platformName(e);t.title=s,t.setAttribute("aria-label",this.platformAriaLabel(e));const r=t.querySelector(".designbase-wc-share__platform-name");r&&(r.textContent=s);const n=t.querySelector(".designbase-wc-share__copy-success span");n&&(n.textContent=this.copySuccessLabel())});const n=t.querySelector(".designbase-wc-share__copy-button"),i=n&&Array.from(n.childNodes).find(t=>t.nodeType===Node.TEXT_NODE);i&&(i.textContent=this.isCopied?this.copySuccessLabel():e("복사"));const a=[[".designbase-wc-share__qr-title","QR 코드"],[".designbase-wc-share__qr-description","QR 코드를 스캔하여 링크에 접속하세요"],[".designbase-wc-share__link-title","공유 링크"]];for(const[s,r]of a){const n=t.querySelector(s);n&&(n.textContent=e(r))}if(this.dropdownEl){const t=document.activeElement,s=Array.from(this.dropdownEl.querySelectorAll(".designbase-wc-dropdown__item")).findIndex(e=>e===t||e.contains(t));this.dropdownEl.setAttribute("label",this.getAttribute("button-text")||e("공유")),this.dropdownEl.setAttribute("items",JSON.stringify(this.getActivePlatforms().map(t=>({id:t,label:this.platformName(t)})))),s>=0&&this.dropdownEl.querySelectorAll(".designbase-wc-dropdown__item")[s]?.focus({preventScroll:!0})}}getVariant(){return a(this.getAttribute("variant"),o,"button")}getSize(){return a(this.getAttribute("size"),l,"m")}getPosition(){return a(this.getAttribute("position"),c,"bottom")}attributeChangedCallback(t){"open"===t&&"modal"===this.getVariant()&&this.modalEl?this.syncModalOpen():"url"===t&&this.contentSlot?this.refreshLinkInputValue():this.render()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open","true"):this.removeAttribute("open")}parseListAttribute(t){const e=this.getAttribute(t);if(!e)return[];try{const t=JSON.parse(e);if(Array.isArray(t))return t.map(t=>String(t).trim()).filter(Boolean)}catch{}return e.split(",").map(t=>t.trim()).filter(Boolean)}getResolvedUrl(){const t=this.getAttribute("url");return t?i(t,""):"undefined"!=typeof window&&window.location?.href?i(window.location.href,""):""}getContext(){return{url:this.getResolvedUrl(),title:this.getAttribute("share-title")||this.getAttribute("title")||"",description:this.getAttribute("description")||"",imageUrl:this.getAttribute("image-url")||"",hashtags:this.parseListAttribute("hashtags"),host:this}}getActivePlatforms(){const t=this.parseListAttribute("platforms");return(t.length>0?t:h).filter(t=>t in d)}replaceUrlVariables(t,e){return t.replace("{url}",encodeURIComponent(e.url)).replace("{title}",encodeURIComponent(e.title)).replace("{description}",encodeURIComponent(e.description)).replace("{imageUrl}",encodeURIComponent(e.imageUrl)).replace("{hashtags}",e.hashtags.join(","))}async handleCopyLink(t){try{await navigator.clipboard.writeText(t.url),this.isCopied=!0,this.dispatchEvent(new CustomEvent("db-copy-success",{bubbles:!0,composed:!0,detail:{url:t.url}})),this.refreshContent(),this.copyResetTimer&&clearTimeout(this.copyResetTimer),this.copyResetTimer=setTimeout(()=>{this.isCopied=!1,this.refreshContent()},3e3)}catch(t){this.dispatchEvent(new CustomEvent("db-copy-error",{bubbles:!0,composed:!0,detail:{error:t}}))}}handleShowQrCode(t){if(this.qrCodeData=t.url,"modal"===this.getVariant())return this.open=!0,void this.refreshContent();this.refreshContent()}handlePlatformShare(t){const e=this.getContext(),s=d[t];if(s)try{if("link"===t)this.handleCopyLink(e);else if("qr"===t)this.handleShowQrCode(e);else if(s.customShare)s.customShare(e);else if(s.shareUrl){const t=this.replaceUrlVariables(s.shareUrl,e),r=i(t,"");if(!r)throw new Error("Invalid share URL");window.open(r,"_blank","noopener,noreferrer,width=600,height=400")}this.dispatchEvent(new CustomEvent("db-share",{bubbles:!0,composed:!0,detail:{platform:t,url:e.url}}))}catch(e){this.dispatchEvent(new CustomEvent("db-share-error",{bubbles:!0,composed:!0,detail:{platform:t,error:e}}))}}getPlacement(){const t=this.getPosition();return"top"===t||"left"===t?"top-left":"right"===t?"bottom-right":"bottom-left"}mapButtonSize(){const t=this.getSize();return"s"===t?"s":"l"===t?"l":"m"}createTriggerButton(t){const s=document.createElement("db-button");return s.className=t||"designbase-wc-share__trigger",s.setAttribute("variant","secondary"),s.setAttribute("size",this.mapButtonSize()),s.textContent=this.getAttribute("button-text")||e("공유"),s.prepend(r("share-alt",16)),s.addEventListener("db-click",()=>{"modal"!==this.getVariant()?this.open=!this.open:this.open=!0}),s}createPlatformIcon(t){const e=document.createElement("span");return e.className="designbase-wc-share__platform-icon",e.append(n(t,24)),e}createPlatformButton(t){const e=d[t],s=document.createElement("button");s.type="button",s.className=["designbase-wc-share__platform-button",`designbase-wc-share__platform-button--${t}`,"link"===t&&this.isCopied?"designbase-wc-share__platform-button--copied":""].filter(Boolean).join(" "),s.style.setProperty("--platform-color",e.color),s.dataset.sharePlatform=t;const n=this.platformName(t);s.title=n,s.setAttribute("aria-label",this.platformAriaLabel(t)),s.append(this.createPlatformIcon(t));const i=document.createElement("span");if(i.className="designbase-wc-share__platform-name",i.textContent=n,s.append(i),"link"===t&&this.isCopied){const t=document.createElement("span");t.className="designbase-wc-share__copy-success",t.append(r("copy",12));const e=document.createElement("span");e.textContent=this.copySuccessLabel(),t.append(e),s.append(t)}return s.addEventListener("click",()=>this.handlePlatformShare(t)),s}createLinkInput(t){const e=document.createElement("db-input");return e.className="designbase-wc-share__link-input",e.setAttribute("type","text"),e.setAttribute("readonly",""),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.setAttribute("value",t),customElements.whenDefined("db-input").then(()=>{e.setAttribute("value",t),e.value=t}),e}refreshLinkInputValue(){const t=this.getResolvedUrl(),e=this.contentSlot?.querySelector("db-input.designbase-wc-share__link-input");e&&(e.setAttribute("value",t),e.value=t)}createCopyButton(t){const s=document.createElement("db-button");s.className="designbase-wc-share__copy-button",s.setAttribute("size","s"),s.setAttribute("variant","primary");const n=document.createElement("span");return n.className="designbase-wc-button__start-icon",n.setAttribute("aria-hidden","true"),n.append(r(this.isCopied?"copy":"link",16)),s.append(n),s.append(document.createTextNode(this.isCopied?this.copySuccessLabel():e("복사"))),s.addEventListener("db-click",()=>{this.handleCopyLink(t)}),s}generateQrCodeUrl(){const t=Number(this.getAttribute("qr-code-size")||200);return`https://api.qrserver.com/v1/create-qr-code/?size=${t}x${t}&data=${encodeURIComponent(this.qrCodeData)}`}createShareContent(){const t=document.createElement("div");return t.className="designbase-wc-share__content",this.populateShareContent(t),t}populateShareContent(t){const s=document.createElement("div");s.className="designbase-wc-share__platforms",this.getActivePlatforms().forEach(t=>{s.append(this.createPlatformButton(t))}),t.append(s);if("false"!==this.getAttribute("show-qr-code")&&this.qrCodeData){const s=document.createElement("div");s.className="designbase-wc-share__qr-section";const r=document.createElement("h4");r.className="designbase-wc-share__qr-title",r.textContent=e("QR 코드"),s.append(r);const n=document.createElement("div");n.className="designbase-wc-share__qr-code";const i=document.createElement("img"),a=Number(this.getAttribute("qr-code-size")||200);i.src=this.generateQrCodeUrl(),i.alt="QR Code",i.width=a,i.height=a,n.append(i),s.append(n);const o=document.createElement("p");o.className="designbase-wc-share__qr-description",o.textContent=e("QR 코드를 스캔하여 링크에 접속하세요"),s.append(o),t.append(s)}const r=this.getContext(),n=document.createElement("div");n.className="designbase-wc-share__link-preview";const i=document.createElement("h4");i.className="designbase-wc-share__link-title",i.textContent=e("공유 링크"),n.append(i);const a=document.createElement("div");a.className="designbase-wc-share__link-container",a.append(this.createLinkInput(r.url)),a.append(this.createCopyButton(r)),n.append(a),t.append(n)}refreshContent(){const t=this.getVariant();if("inline"===t){const t=this.querySelector(":scope > .designbase-wc-share__content");return void t?.replaceWith(this.createShareContent())}"modal"===t&&this.contentSlot&&(this.contentSlot.replaceChildren(),this.populateShareContent(this.contentSlot))}syncModalOpen(){this.modalEl&&(this.open?(this.refreshLinkInputValue(),this.modalEl.setAttribute("open","true")):this.modalEl.removeAttribute("open"))}renderDropdown(){const t=document.createElement("db-dropdown");t.className="designbase-wc-share__dropdown",t.setAttribute("placement",this.getPlacement()),t.setAttribute("label",this.getAttribute("button-text")||e("공유")),t.setAttribute("trigger-variant","secondary"),t.setAttribute("trigger-icon","share-alt"),t.setAttribute("size",this.mapButtonSize()),t.setAttribute("items",JSON.stringify(this.getActivePlatforms().map(t=>({id:t,label:this.platformName(t)})))),t.addEventListener("db-change",t=>{const e=t.detail,s=e?.id;s&&this.handlePlatformShare(s)}),this.dropdownEl=t,this.append(t)}renderModal(){const t=this.createTriggerButton();this.append(t);const s=document.createElement("db-modal");s.className="designbase-wc-share__modal",s.setAttribute("title",this.getAttribute("modal-title")||e("공유하기")),s.setAttribute("size","m"),this.contentSlot=document.createElement("div"),this.contentSlot.className="designbase-wc-share designbase-wc-share__content",this.contentSlot.setAttribute("data-modal-part","body"),this.populateShareContent(this.contentSlot),s.append(this.contentSlot),s.addEventListener("db-close",()=>{this.open=!1,this.qrCodeData="",this.contentSlot&&(this.contentSlot.replaceChildren(),this.populateShareContent(this.contentSlot))}),this.modalEl=s,this.append(s),this.syncModalOpen()}render(){const t=this.getVariant();this.className=`designbase-wc-share designbase-wc-share--${t}`,this.replaceChildren(),this.modalEl=null,this.contentSlot=null,this.dropdownEl=null,"inline"!==t?"dropdown"!==t?"modal"!==t?this.append(this.createTriggerButton()):this.renderModal():this.renderDropdown():this.append(this.createShareContent())}}customElements.get("db-share")||customElements.define("db-share",DbShare);export{DbShare};
@@ -73,6 +73,7 @@ interface DbSidebarUpdateBanner {
73
73
  variant?: 'primary' | 'secondary' | 'tertiary' | 'outline';
74
74
  }
75
75
  declare class DbSidebar extends HTMLElement {
76
+ private autoAriaLabel?;
76
77
  private expandedItems;
77
78
  private userMenuOpen;
78
79
  private projectMenuOpen;
@@ -92,7 +93,9 @@ declare class DbSidebar extends HTMLElement {
92
93
  private createCustomNavSlot;
93
94
  private projectCustomNavSlots;
94
95
  static get observedAttributes(): string[];
96
+ private unsubscribeLocale?;
95
97
  connectedCallback(): void;
98
+ private syncAccessibleName;
96
99
  disconnectedCallback(): void;
97
100
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
98
101
  private bindPanelMediaQuery;
@@ -1 +1 @@
1
- import{dbFormat as e,dbText as t}from"../core/i18n.js";import{createDbIcon as s,isDbIconName as i}from"./db-icons.js";import{sanitizeHref as a}from"../core/safe-url.js";import{SIDEBAR_CUSTOM_NAV_SLOTS as n,SIDEBAR_PANEL_MODES as r,SIDEBAR_TYPES as o,SIDEBAR_SIZES as d,SIDEBAR_THEMES as c,SIDEBAR_POSITIONS as l,SIDEBAR_VARIANTS as u}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const b="240px";class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.flyoutCloseTimer=null,this.userFlyoutCloseTimer=null,this.outsideHandler=null,this.panelMediaQuery=null,this.panelMediaHandler=null,this.resolvedPanelMode="adjacent"}collectCustomNavSlots(){const e=new Map;return n.forEach(t=>{const s=Array.from(this.children).filter(e=>e instanceof HTMLElement&&e.getAttribute("slot")===t),i=Array.from(this.querySelectorAll(`[data-sidebar-slot="${t}"]`)).flatMap(e=>Array.from(e.children).filter(e=>e instanceof HTMLElement&&e.getAttribute("slot")===t));e.set(t,[...new Set([...s,...i])])}),e}createCustomNavSlot(e){const t=document.createElement("div");return t.className=["designbase-wc-sidebar__custom-slot",`designbase-wc-sidebar__custom-slot--${e}`].join(" "),t.dataset.sidebarSlot=e,t}projectCustomNavSlots(e){n.forEach(t=>{const s=this.querySelector(`[data-sidebar-slot="${t}"]`),i=e.get(t)??[];s&&0!==i.length?s.append(...i):s?.remove()})}static get observedAttributes(){return["type","logo-src","logo-alt","items","sections","user-menu-items","user-profile","default-expanded-ids","expanded-ids","accordion-mode","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","update-banner","header-type","back-label","back-href","panels","settings-sections","active-panel","panel-mode","panel-width","panel-breakpoint","size","theme","variant","position","collapsed","collapsible","show-logo","logo-type","logo-text","full-height","shadow"]}connectedCallback(){this.seedExpanded(),this.bindPanelMediaQuery(),this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick(),this.unbindPanelMediaQuery(),this.cancelFlyoutClose(),this.cancelUserFlyoutClose()}attributeChangedCallback(e,t,s){if(this.isConnected&&t!==s){if("default-expanded-ids"===e||"expanded-ids"===e||"accordion-mode"===e)return this.seedExpanded(),void this.syncAccordionState();if("collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.cancelFlyoutClose(),this.cancelUserFlyoutClose()),"panel-mode"!==e&&"panel-breakpoint"!==e||this.bindPanelMediaQuery(),this.render(),"active-panel"===e){const e=this.getActivePanelConfig();this.dispatchEvent(new CustomEvent("db-panel-change",{bubbles:!0,composed:!0,detail:{panel:e?.id??"main",panelConfig:e,mode:this.resolvedPanelMode}}))}}}bindPanelMediaQuery(){this.unbindPanelMediaQuery();const e=this.panelMode;if("auto"!==e)return void(this.resolvedPanelMode=e);if("undefined"==typeof window||"function"!=typeof window.matchMedia)return void(this.resolvedPanelMode="adjacent");const t=window.matchMedia(`(min-width: ${this.panelBreakpoint}px)`);this.panelMediaQuery=t,this.resolvedPanelMode=t.matches?"adjacent":"replace",this.panelMediaHandler=e=>{const t=e.matches?"adjacent":"replace";t!==this.resolvedPanelMode&&(this.resolvedPanelMode=t,this.render(),this.dispatchEvent(new CustomEvent("db-panel-mode-change",{bubbles:!0,composed:!0,detail:{mode:t}})))},t.addEventListener("change",this.panelMediaHandler)}unbindPanelMediaQuery(){this.panelMediaQuery&&this.panelMediaHandler&&this.panelMediaQuery.removeEventListener("change",this.panelMediaHandler),this.panelMediaQuery=null,this.panelMediaHandler=null}seedExpanded(){try{const e=JSON.parse(this.getAttribute("expanded-ids")??this.getAttribute("default-expanded-ids")??"[]"),t=Array.isArray(e)?[...new Set(e.filter(e=>"string"==typeof e))]:[];this.expandedItems=new Set("single"===this.accordionMode?t.slice(0,1):t)}catch{this.expandedItems=new Set}}get expandedIds(){return[...this.expandedItems]}set expandedIds(e){this.setAttribute("expanded-ids","string"==typeof e?e:JSON.stringify(e)),this.isConnected||this.seedExpanded()}get accordionMode(){return"multiple"===this.getAttribute("accordion-mode")?"multiple":"single"}set accordionMode(e){this.setAttribute("accordion-mode",e)}get hideExpandIcon(){return this.hasAttribute("hide-expand-icon")&&"false"!==this.getAttribute("hide-expand-icon")}set hideExpandIcon(e){this.toggleAttribute("hide-expand-icon",e)}get showDepthGuide(){return this.hasAttribute("show-depth-guide")&&"false"!==this.getAttribute("show-depth-guide")}set showDepthGuide(e){this.toggleAttribute("show-depth-guide",e)}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||"프로젝트 관리"}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||"프로젝트"}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||"프로젝트를 추가해 주세요"}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||"프로젝트 추가"}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}get updateBanner(){return this.parseUpdateBanner()}set updateBanner(e){null==e?this.removeAttribute("update-banner"):this.setAttribute("update-banner","string"==typeof e?e:JSON.stringify(e))}get headerType(){return"back"===this.getAttribute("header-type")?"back":"default"}set headerType(e){this.setAttribute("header-type",e)}get backLabel(){return this.getAttribute("back-label")||"뒤로가기"}set backLabel(e){this.setAttribute("back-label",e)}get backHref(){return this.getAttribute("back-href")||""}set backHref(e){e?this.setAttribute("back-href",e):this.removeAttribute("back-href")}get panels(){return this.parsePanels()}set panels(e){this.setAttribute("panels","string"==typeof e?e:JSON.stringify(e))}get settingsSections(){return this.parseSettingsSections()}set settingsSections(e){this.setAttribute("settings-sections","string"==typeof e?e:JSON.stringify(e))}get activePanel(){const e=this.getAttribute("active-panel")||"main";return"main"===e?"main":this.findPanel(e)?e:"main"}set activePanel(e){const t=e&&"main"!==e&&this.findPanel(e)?e:"main";this.setAttribute("active-panel",t)}get panelMode(){const e=this.getAttribute("panel-mode")||"auto";return r.includes(e)?e:"auto"}set panelMode(e){this.setAttribute("panel-mode",r.includes(e)?e:"auto")}get panelWidth(){return this.normalizeCssLength(this.getAttribute("panel-width")||b)}set panelWidth(e){this.setAttribute("panel-width",this.normalizeCssLength(e))}get panelBreakpoint(){const e=Number(this.getAttribute("panel-breakpoint"));return Number.isFinite(e)&&e>0?e:1024}set panelBreakpoint(e){const t=Number.isFinite(e)&&e>0?Math.round(e):1024;this.setAttribute("panel-breakpoint",String(t))}normalizeCssLength(e){if("number"==typeof e)return`${Math.max(0,e)}px`;const t=String(e??"").trim();return t?/^-?\d+(?:\.\d+)?$/.test(t)?`${Math.max(0,Number(t))}px`:t:b}parseSettingsSections(){try{const e=JSON.parse(this.getAttribute("settings-sections")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parsePanels(){let e=[];const t=this.getAttribute("panels");if(t)try{const s=JSON.parse(t);Array.isArray(s)&&(e=s.filter(e=>Boolean(e&&"string"==typeof e.id&&e.id.trim())).map(e=>({...e,id:e.id.trim(),title:String(e.title||e.id).trim(),sections:Array.isArray(e.sections)?e.sections:[]})))}catch{e=[]}const s=this.parseSettingsSections();return s.length&&!e.some(e=>"settings"===e.id)&&e.push({id:"settings",title:"Settings",backLabel:this.backLabel,sections:s}),e}hasPanels(){return this.parsePanels().length>0}findPanel(e){return e&&"main"!==e?this.parsePanels().find(t=>t.id===e)??null:null}getActivePanelConfig(){return this.findPanel(this.getAttribute("active-panel")||"main")}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseUpdateBanner(){const e=this.getAttribute("update-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,this.userFlyoutItemId=null,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.classList.remove("designbase-wc-sidebar--user-menu-open"),this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncAccordionState(){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(e=>{const t=e.getAttribute("data-item-id");t&&(this.expandedItems.has(t)?e.setAttribute("expanded",""):e.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}cancelUserFlyoutClose(){this.userFlyoutCloseTimer&&(clearTimeout(this.userFlyoutCloseTimer),this.userFlyoutCloseTimer=null)}setUserFlyout(e){this.cancelUserFlyoutClose(),this.userFlyoutItemId=e,this.querySelectorAll(".designbase-wc-sidebar__user-menu-item").forEach(t=>{const s=Boolean(e&&t.dataset.itemId===e);t.classList.toggle("designbase-wc-sidebar__user-menu-item--flyout-active",s),t.querySelector(".designbase-wc-sidebar__user-menu-trigger")?.setAttribute("aria-expanded",String(s));const i=t.querySelector(".designbase-wc-sidebar__user-flyout");i&&(i.hidden=!s)})}scheduleUserFlyoutClose(){this.cancelUserFlyoutClose(),this.userFlyoutCloseTimer=setTimeout(()=>{this.userFlyoutCloseTimer=null,this.setUserFlyout(null)},120)}get sidebarType(){const e=this.getAttribute("type");return o.find(t=>t===e)||"app"}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("theme")||"default",s=this.getAttribute("variant")||"default",i=this.getAttribute("position")||"left",a=this.getActivePanelConfig(),n=Boolean(a),r=this.panelWidth;this.style.setProperty("--db-sidebar-panel-width",r),this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--type-${this.sidebarType}`,`designbase-wc-sidebar--${d.includes(e)?e:"m"}`,`designbase-wc-sidebar--${c.includes(t)?t:"default"}`,`designbase-wc-sidebar--${l.includes(i)?i:"left"}`,`designbase-wc-sidebar--panel-${this.resolvedPanelMode}`,u.includes(s)&&"wrapper"===s&&"designbase-wc-sidebar--wrapper",this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow",this.userMenuOpen&&"designbase-wc-sidebar--user-menu-open",("back"===this.headerType||n&&"replace"===this.resolvedPanelMode)&&"designbase-wc-sidebar--header-back",n&&"designbase-wc-sidebar--panel-open",this.hasPanels()&&"designbase-wc-sidebar--has-panels"].filter(Boolean).join(" ")}navigateToPanel(e){const t="main"!==e&&e?this.findPanel(e)?.id:"main";t&&this.activePanel!==t&&("main"!==t&&"replace"===this.resolvedPanelMode&&this.hasAttribute("collapsed")&&this.removeAttribute("collapsed"),this.setAttribute("active-panel",t))}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchBackClick(){const e=this.getActivePanelConfig();e&&this.navigateToPanel("main");const t=new CustomEvent("db-back-click",{bubbles:!0,composed:!0,cancelable:!0,detail:{label:e?.backLabel||this.backLabel,href:this.backHref,panel:e}});this.dispatchEvent(t);const s=a(this.backHref,"");t.defaultPrevented||e||!s||"back"!==this.headerType||window.location.assign(s)}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}dispatchUpdateCtaClick(e){this.dispatchEvent(new CustomEvent("db-update-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(e="s"){const t=document.createElement("span");return t.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${e}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),t.setAttribute("aria-hidden","true"),t.append(s("plus","m"===e?16:14)),t}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("type","text"),t.textContent=e.badge,t}createProjectSelector(e){if(!this.hasAttribute("projects"))return null;const t=this.parseProjects(),i=0===t.length,n=this.getSelectedProject(),r=document.createElement("div");r.className=["designbase-wc-sidebar__project-selector",e&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",i&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const o=this.getAttribute("project-section-label");if(!e&&o&&o.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=o.trim(),r.append(e)}const d=document.createElement("button");if(d.type="button",d.className="designbase-wc-sidebar__project-trigger",d.setAttribute("aria-haspopup","menu"),d.setAttribute("aria-expanded",String(this.projectMenuOpen)),i||!n){if(d.setAttribute("aria-label",this.projectEmptyTriggerLabel),d.append(this.createProjectEmptyMark(e?"m":"s")),!e){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,d.append(e)}}else if(d.setAttribute("aria-label",n.label),d.append(this.createProjectAvatar(n,e?"m":"s")),!e){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=n.label,d.append(e)}const c=document.createElement("span");if(c.className="designbase-wc-sidebar__project-chevron",c.setAttribute("aria-hidden","true"),c.append(s("chevron-down",14)),d.append(c),d.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),r.append(d),this.projectMenuOpen){const e=document.createElement("div");if(e.className="designbase-wc-sidebar__project-dropdown",e.setAttribute("role","menu"),e.setAttribute("aria-label",this.projectSectionLabel),i){const t=document.createElement("div");t.className="designbase-wc-sidebar__project-empty",t.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,t.append(s),e.append(t)}else{const s=document.createElement("ul");s.className="designbase-wc-sidebar__project-list",t.forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",n&&e.id===n.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(e,"s"));const a=document.createElement("span");a.className="designbase-wc-sidebar__project-option-label",a.textContent=e.label,i.append(a);const r=this.createProjectBadge(e);r&&i.append(r),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",e.id),this.dispatchProjectChange(e),this.render()}),t.append(i),s.append(t)}),e.append(s)}const o=document.createElement("button");o.type="button",o.className="designbase-wc-sidebar__project-manage",o.setAttribute("role","menuitem"),o.append(s("plus",14));const d=document.createElement("span");d.textContent=this.projectManageLabel,o.append(d),o.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref,t=a(e,"");t&&window.location.assign(t),this.dispatchProjectManage(),this.render()}),e.append(o),r.append(e)}return r}createFlyout(t,s){const i=this.getAttribute("position")||"left",n=document.createElement("div");n.className=["designbase-wc-sidebar__flyout","right"===i&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),n.setAttribute("role","menu"),n.setAttribute("aria-label",e("{0} 하위 메뉴",[t.label])),n.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),n.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const r=document.createElement("div");r.className="designbase-wc-sidebar__flyout-title",r.textContent=t.label,n.append(r);const o=document.createElement("ul");return o.className="designbase-wc-sidebar__flyout-list",(t.children||[]).forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",s);const n=a(e.href,"");n&&i.setAttribute("href",n),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),t.append(i),o.append(t)}),n.append(o),n}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),n=this.expandedItems.has(e.id),r=this.hasAttribute("collapsed"),o=r&&i,d=document.createElement("li");d.className=["designbase-wc-sidebar__item",o&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),o&&(d.addEventListener("mouseenter",()=>this.showFlyout(e.id)),d.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const c=document.createElement("db-menu-item");c.setAttribute("data-item-id",e.id),c.setAttribute("label",e.label),c.setAttribute("type","block"),c.setAttribute("menu-style","accordion"),c.setAttribute("size",t),c.setAttribute("depth",String(s));const l=a(e.href,"");if(l&&c.setAttribute("href",l),e.icon&&c.setAttribute("icon",e.icon),(e.active||e.openPanel&&e.openPanel===this.activePanel)&&c.setAttribute("active",""),e.disabled&&c.setAttribute("disabled",""),void 0!==e.badge&&c.setAttribute("badge",String(e.badge)),e.badgeColor&&c.setAttribute("badge-color",e.badgeColor),i&&!o&&(c.setAttribute("expandable",""),c.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor,icon:e.icon})),n&&!r&&c.setAttribute("expanded","")),c.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!r){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),s?("single"===this.accordionMode&&this.expandedItems.clear(),this.expandedItems.add(e.id)):this.expandedItems.delete(e.id),this.expandedIds=[...this.expandedItems],this.syncAccordionState(),this.dispatchEvent(new CustomEvent("db-expanded-change",{detail:{itemId:e.id,expanded:s,expandedIds:this.expandedIds},bubbles:!0,composed:!0})),void("app"!==this.sidebarType&&this.dispatchItemClick(e))}if(o)return this.closeOverlayMenus(),void this.showFlyout(e.id);if(this.closeOverlayMenus(),e.openPanel&&this.findPanel(e.openPanel))return this.dispatchItemClick(e),void this.navigateToPanel(e.openPanel);this.dispatchItemClick(e)}}),c.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),d.append(c),r&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),d.append(s)}if(r&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),d.append(t)}return o&&this.flyoutItemId===e.id&&d.append(this.createFlyout(e,t)),d}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const a=document.createElement("div");if(a.className=["designbase-wc-sidebar__section",e.gap&&`designbase-wc-sidebar__section--gap-${e.gap}`].filter(Boolean).join(" "),!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>n.append(this.createSidebarMenuItem(e,t))),a.append(n),i.append(a)}),i}renderNav(){const e=this.getAttribute("size")||"m",t=this.hasAttribute("collapsed"),s=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="main"]');s&&s.replaceChildren(this.renderSectionList(this.parseSections(),e,t),this.createCustomNavSlot("nav"));const i=this.getActivePanelConfig(),a=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="panel"]');a&&i&&a.replaceChildren(this.renderSectionList(i.sections,e,!1))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(n,r=!1){if(!n.length)return null;const o=this.getAttribute("position")||"left",d=document.createElement("div");d.className=["designbase-wc-sidebar__user-dropdown",r&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),d.setAttribute("role","menu"),d.setAttribute("aria-label",t("사용자 메뉴")),d.hidden=!this.userMenuOpen,d.addEventListener("keydown",e=>{"Escape"===e.key&&(e.stopPropagation(),this.userFlyoutItemId?this.setUserFlyout(null):(this.userMenuOpen=!1,this.render()))});const c=document.createElement("ul");return c.className="designbase-wc-sidebar__user-menu",n.forEach(t=>{const n=Boolean(t.children?.length),r=document.createElement("li");r.dataset.itemId=t.id,r.className=["designbase-wc-sidebar__user-menu-item",t.dividerBefore&&"designbase-wc-sidebar__user-menu-item--divider",t.disabled&&"designbase-wc-sidebar__user-menu-item--disabled",n&&"designbase-wc-sidebar__user-menu-item--has-children"].filter(Boolean).join(" ");const d=document.createElement("button");if(d.type="button",d.className="designbase-wc-sidebar__user-menu-trigger",d.setAttribute("role","menuitem"),d.disabled=Boolean(t.disabled),t.icon&&i(t.icon)){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-icon",e.setAttribute("aria-hidden","true"),e.append(s(t.icon,16)),d.append(e)}const l=document.createElement("span");if(l.className="designbase-wc-sidebar__user-menu-label",l.textContent=t.label,d.append(l),t.value){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-value",e.textContent=t.value,d.append(e)}if(n){const n=document.createElement("span");n.className="designbase-wc-sidebar__user-menu-chevron",n.setAttribute("aria-hidden","true"),n.append(s("right"===o?"chevron-left":"chevron-right",16)),d.append(n),d.setAttribute("aria-haspopup","menu"),d.setAttribute("aria-expanded",String(this.userFlyoutItemId===t.id));const openFlyout=()=>this.setUserFlyout(t.id);r.addEventListener("mouseenter",openFlyout),r.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose()),r.addEventListener("focusin",openFlyout),r.addEventListener("focusout",e=>{const t=e.relatedTarget;t&&r.contains(t)||this.scheduleUserFlyoutClose()}),d.addEventListener("click",openFlyout);const c=document.createElement("div");c.className=["designbase-wc-sidebar__user-flyout","right"===o&&"designbase-wc-sidebar__user-flyout--align-left"].filter(Boolean).join(" "),c.setAttribute("role","menu"),c.setAttribute("aria-label",e("{0} 하위 메뉴",[t.label])),c.hidden=this.userFlyoutItemId!==t.id,c.addEventListener("mouseenter",()=>this.cancelUserFlyoutClose()),c.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose());const l=document.createElement("ul");l.className="designbase-wc-sidebar__user-flyout-list",(t.children||[]).forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__user-flyout-item";const n=document.createElement("button");if(n.type="button",n.className=["designbase-wc-sidebar__user-menu-trigger","designbase-wc-sidebar__user-flyout-trigger",e.selected&&"designbase-wc-sidebar__user-flyout-trigger--selected"].filter(Boolean).join(" "),n.setAttribute("role","menuitemradio"),n.setAttribute("aria-checked",String(Boolean(e.selected))),n.disabled=Boolean(e.disabled),e.icon&&i(e.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(s(e.icon,16)),n.append(t)}const r=document.createElement("span");if(r.className="designbase-wc-sidebar__user-menu-label",r.textContent=e.label,n.append(r),e.selected){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-check",e.setAttribute("aria-hidden","true"),e.append(s("done",16)),n.append(e)}n.addEventListener("click",()=>{if(e.disabled)return;this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(e);const t=a(e.href,"");t&&window.location.assign(t),this.render()}),t.append(n),l.append(t)}),c.append(l),r.append(d,c)}else d.addEventListener("click",()=>{if(t.disabled)return;this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(t);const e=a(t.href,"");e&&window.location.assign(e),this.render()}),r.append(d);c.append(r)}),d.append(c),d}createUpdateBanner(e){if("back"===this.headerType)return null;const t=this.parseUpdateBanner();if(!t)return null;if(e)return null;const s=document.createElement("div");s.className="designbase-wc-sidebar__update";const i=document.createElement("db-banner");return i.className="designbase-wc-sidebar__update-banner",i.setAttribute("size","s"),i.setAttribute("variant",t.variant||"outline"),i.setAttribute("title",t.title),t.description&&i.setAttribute("description",t.description),t.icon&&i.setAttribute("icon",t.icon),i.setAttribute("clickable",""),i.setAttribute("aria-label",t.ctaLabel||t.title),i.addEventListener("db-click",()=>{const e=a(t.ctaHref,"");e&&window.location.assign(e),this.dispatchUpdateCtaClick(t)}),s.append(i),s}createPromoBanner(e){if("back"===this.headerType)return null;const t=this.parsePromoBanner();if(!t)return null;if(e){const e=document.createElement("button");e.type="button",e.className="designbase-wc-sidebar__promo-collapsed",e.setAttribute("aria-label",t.ctaLabel||t.title);const a=document.createElement("db-animation-background");a.className="designbase-wc-sidebar__promo-bg",a.setAttribute("type","aurora"),a.setAttribute("theme","light"),a.setAttribute("intensity","subtle"),a.setAttribute("blur","40"),a.setAttribute("speed","4000"),a.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),e.append(a),e.append(s(t.icon&&i(t.icon)?t.icon:"sparkle",18)),e.addEventListener("click",()=>this.dispatchPromoCtaClick(t));const n=document.createElement("span");n.className="designbase-wc-sidebar__item-tooltip",n.textContent=t.title,n.setAttribute("role","tooltip");const r=document.createElement("div");return r.className="designbase-wc-sidebar__promo-collapsed-wrap",r.append(e,n),r}const n=document.createElement("div");n.className="designbase-wc-sidebar__promo";const r=document.createElement("db-animation-background");r.className="designbase-wc-sidebar__promo-bg",r.setAttribute("type","aurora"),r.setAttribute("theme","light"),r.setAttribute("intensity","subtle"),r.setAttribute("blur","60"),r.setAttribute("speed","5000"),r.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),n.append(r);const o=document.createElement("div");o.className="designbase-wc-sidebar__promo-content";const d=document.createElement("div");d.className="designbase-wc-sidebar__promo-title-row";const c=document.createElement("span");c.className="designbase-wc-sidebar__promo-icon",c.setAttribute("aria-hidden","true"),c.append(s(t.icon&&i(t.icon)?t.icon:"sparkle",16));const l=document.createElement("div");if(l.className="designbase-wc-sidebar__promo-title",l.textContent=t.title,d.append(c,l),o.append(d),t.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=t.description,o.append(e)}if(t.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=t.ctaLabel,e.addEventListener("db-click",()=>{const e=a(t.ctaHref,"");e&&window.location.assign(e),this.dispatchPromoCtaClick(t)}),o.append(e)}return n.append(o),n}createMainHeader(e){const{size:t,collapsible:i,showLogo:a,collapsed:n}=e,r="back"===this.headerType,o="l"===t?"m":"s"===t?"xs":"s";if(!r&&!i&&(!a||n))return null;const d=document.createElement("div");if(d.className=["designbase-wc-sidebar__header",(n||!a)&&!r&&"designbase-wc-sidebar__header--collapsed-only",r&&"designbase-wc-sidebar__header--back"].filter(Boolean).join(" "),r){const e=document.createElement("button");if(e.type="button",e.className=["designbase-wc-sidebar__back",n&&"designbase-wc-sidebar__back--collapsed"].filter(Boolean).join(" "),e.setAttribute("aria-label",this.backLabel),e.append(s("chevron-left",18)),!n){const t=document.createElement("span");t.textContent=this.backLabel,e.append(t)}e.addEventListener("click",()=>this.dispatchBackClick()),d.append(e)}else if(!n&&a){const e=document.createElement("div");e.className="designbase-wc-sidebar__logo";const t=this.getAttribute("logo-type")||"designbase",s=this.getAttribute("logo-text")||"",i=this.getAttribute("logo-src");if(i){const t=document.createElement("db-logo");t.setAttribute("type","custom"),t.setAttribute("src",i),t.setAttribute("alt",this.getAttribute("logo-alt")||"홈"),t.setAttribute("size",o),e.append(t)}else if("custom"===t&&s){const t=document.createElement("span");t.className="designbase-wc-sidebar__logo-text",t.textContent=s,e.append(t)}else{const i=document.createElement("db-logo");i.setAttribute("type",t),i.setAttribute("size",o),s&&i.setAttribute("text",s),e.append(i)}e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),d.append(e)}if(i&&!r){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__toggle",e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("icon-only",""),e.setAttribute("start-icon",n?"arrow-bar-right":"arrow-bar-left"),e.setAttribute("aria-label",n?"사이드바 펼치기":"사이드바 접기"),e.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),d.append(e)}return d}createPanelHeader(e){const t="replace"===this.resolvedPanelMode,i=document.createElement("div");if(i.className=["designbase-wc-sidebar__panel-header",t&&"designbase-wc-sidebar__panel-header--replace"].filter(Boolean).join(" "),t){const t=document.createElement("button");t.type="button",t.className="designbase-wc-sidebar__panel-back",t.setAttribute("aria-label",e.backLabel||this.backLabel),t.append(s("chevron-left",18)),t.addEventListener("click",()=>this.dispatchBackClick()),i.append(t)}const a=document.createElement("div");a.className="designbase-wc-sidebar__panel-heading";const n=document.createElement("div");if(n.className="designbase-wc-sidebar__panel-title",n.textContent=e.title,a.append(n),e.description){const t=document.createElement("div");t.className="designbase-wc-sidebar__panel-description",t.textContent=e.description,a.append(t)}return i.append(a),i}createNavWrapper(e){const{mode:s,collapsed:i,includeProjects:a,includeBottom:n,panel:r}=e,o=document.createElement("div");if(o.className="designbase-wc-sidebar__nav-wrapper",a){const e=this.createProjectSelector(i);e&&o.append(e)}"main"===s&&o.append(this.createCustomNavSlot("nav-top"));const d=document.createElement("nav");if(d.className="designbase-wc-sidebar__nav",d.setAttribute("data-panel-nav",s),r&&(d.dataset.panelId=r.id),d.setAttribute("aria-label",r?.ariaLabel||r?.title||"주 메뉴"),o.append(d),"main"===s&&o.append(this.createCustomNavSlot("nav-bottom")),n){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label",t("하단 메뉴")),o.append(e)}return o}createFooter(e){const{collapsed:t,userProfile:i,userMenuItems:a}=e,n=document.createElement("div");n.className="designbase-wc-sidebar__footer";const r=this.createUpdateBanner(t);r&&n.append(r);const o=this.createPromoBanner(t);if(o&&n.append(o),i&&!t){const e=document.createElement("div");e.className="designbase-wc-sidebar__user";const t=this.createUserDropdown(a);t&&e.append(t);const r=document.createElement("div");r.className="designbase-wc-sidebar__user-info",r.setAttribute("role","button"),r.setAttribute("tabindex","0"),r.setAttribute("aria-expanded",String(this.userMenuOpen));const o=document.createElement("db-avatar");o.className="designbase-wc-sidebar__user-avatar",o.setAttribute("size","s"),o.setAttribute("initials",i.name),o.setAttribute("alt",i.name),i.avatar&&o.setAttribute("src",i.avatar);const d=document.createElement("div");d.className="designbase-wc-sidebar__user-details";const c=document.createElement("div");if(c.className="designbase-wc-sidebar__user-name",c.textContent=i.name,d.append(c),i.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=i.email,d.append(e)}if(r.append(o,d),a.length){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-more",e.setAttribute("aria-hidden","true"),e.append(s("more-vertical",16)),r.append(e),r.setAttribute("aria-haspopup","menu")}r.addEventListener("click",()=>{a.length&&(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render())}),r.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),r.click())}),e.append(r),n.append(e)}else if(i&&t){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",i.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),a.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",i.name),t.setAttribute("alt",i.name),i.avatar&&t.setAttribute("src",i.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=i.name,t.setAttribute("role","tooltip"),e.append(t)}const s=this.createUserDropdown(a,!0);s&&e.append(s),e.addEventListener("click",e=>{a.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render()))}),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}),n.append(e)}return n}render(){const e=this.getActivePanelConfig();this.syncHostClasses(),this.setAttribute("role","complementary"),this.setAttribute("aria-label",t("사이드바 네비게이션"));const s=this.getAttribute("size")||"m",i="false"!==(this.getAttribute("collapsible")??("app"===this.sidebarType?"true":"false")),a="false"!==(this.getAttribute("show-logo")??("app"===this.sidebarType?"true":"false")),n=this.hasAttribute("collapsed"),r=this.parseUserProfile(),o=this.parseUserMenuItems(),d=this.parseBottomSections(),c=this.collectCustomNavSlots(),l=Boolean(e),u="replace"===this.resolvedPanelMode;this.replaceChildren();const b=document.createElement("div");b.className="designbase-wc-sidebar__container";const p=document.createElement("div");p.className="designbase-wc-sidebar__panel-viewport";const m=document.createElement("div");m.className="designbase-wc-sidebar__panel-track",m.dataset.active=l&&u?"main":l?"panel":"main";const h=document.createElement("div");h.className=["designbase-wc-sidebar__panel-slide","designbase-wc-sidebar__panel-slide--main"].join(" "),h.dataset.panel="main";const g=l&&u;h.toggleAttribute("inert",g),h.setAttribute("aria-hidden",String(g));const A=this.createMainHeader({size:s,collapsible:i,showLogo:a,collapsed:n});if(A&&h.append(A),h.append(this.createNavWrapper({mode:"main",collapsed:n,includeProjects:"back"!==this.headerType,includeBottom:d.length>0})),h.append(this.createFooter({collapsed:n,userProfile:r,userMenuItems:o})),m.append(h),e){const t=document.createElement("div");t.className=["designbase-wc-sidebar__panel-slide","designbase-wc-sidebar__panel-slide--secondary"].join(" "),t.dataset.panel=e.id,t.setAttribute("aria-hidden","false"),t.append(this.createPanelHeader(e)),t.append(this.createNavWrapper({mode:"panel",collapsed:!1,includeProjects:!1,includeBottom:!1,panel:e})),m.append(t)}p.append(m),b.append(p),this.append(b),this.renderNav(),this.renderBottomNav(),this.projectCustomNavSlots(c),l&&u&&requestAnimationFrame(()=>{this.isConnected&&this.activePanel===e?.id&&(m.dataset.active="panel")})}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
1
+ import{subscribeDbLocale as e,dbText as t,dbFormat as s}from"../core/i18n.js";import{createDbIcon as i,isDbIconName as a}from"./db-icons.js";import{sanitizeHref as n}from"../core/safe-url.js";import{SIDEBAR_CUSTOM_NAV_SLOTS as r,SIDEBAR_PANEL_MODES as o,SIDEBAR_TYPES as d,SIDEBAR_SIZES as c,SIDEBAR_THEMES as l,SIDEBAR_POSITIONS as u,SIDEBAR_VARIANTS as b}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const p="240px";class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.flyoutCloseTimer=null,this.userFlyoutCloseTimer=null,this.outsideHandler=null,this.panelMediaQuery=null,this.panelMediaHandler=null,this.resolvedPanelMode="adjacent"}collectCustomNavSlots(){const e=new Map;return r.forEach(t=>{const s=Array.from(this.children).filter(e=>e instanceof HTMLElement&&e.getAttribute("slot")===t),i=Array.from(this.querySelectorAll(`[data-sidebar-slot="${t}"]`)).flatMap(e=>Array.from(e.children).filter(e=>e instanceof HTMLElement&&e.getAttribute("slot")===t));e.set(t,[...new Set([...s,...i])])}),e}createCustomNavSlot(e){const t=document.createElement("div");return t.className=["designbase-wc-sidebar__custom-slot",`designbase-wc-sidebar__custom-slot--${e}`].join(" "),t.dataset.sidebarSlot=e,t}projectCustomNavSlots(e){r.forEach(t=>{const s=this.querySelector(`[data-sidebar-slot="${t}"]`),i=e.get(t)??[];s&&0!==i.length?s.append(...i):s?.remove()})}static get observedAttributes(){return["type","logo-src","logo-alt","items","sections","user-menu-items","user-profile","default-expanded-ids","expanded-ids","accordion-mode","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","update-banner","header-type","back-label","back-href","panels","settings-sections","active-panel","panel-mode","panel-width","panel-breakpoint","size","theme","variant","position","collapsed","collapsible","show-logo","logo-type","logo-text","full-height","shadow"]}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{this.syncAccessibleName(),this.querySelectorAll("[data-panel-nav]:not([data-panel-id])").forEach(e=>e.setAttribute("aria-label",t("주 메뉴"))),this.querySelectorAll(".designbase-wc-sidebar__bottom-nav").forEach(e=>e.setAttribute("aria-label",t("하단 메뉴"))),this.querySelector(".designbase-wc-sidebar__toggle")?.setAttribute("aria-label",t(this.hasAttribute("collapsed")?"사이드바 펼치기":"사이드바 접기"));const e=this.querySelector("[data-project-empty-trigger]");if(e){e.setAttribute("aria-label",this.projectEmptyTriggerLabel);const t=e.querySelector(".designbase-wc-sidebar__project-label");t&&(t.textContent=this.projectEmptyTriggerLabel)}this.querySelector(".designbase-wc-sidebar__project-dropdown")?.setAttribute("aria-label",this.projectSectionLabel);const s=this.querySelector(".designbase-wc-sidebar__project-empty-text");s&&(s.textContent=this.projectEmptyLabel);const i=this.querySelector(".designbase-wc-sidebar__project-manage span");i&&(i.textContent=this.projectManageLabel);const a=this.querySelector(".designbase-wc-sidebar__back");if(a){a.setAttribute("aria-label",this.backLabel);const e=a.querySelector("span");e&&(e.textContent=this.backLabel)}this.querySelector(".designbase-wc-sidebar__user-dropdown")?.setAttribute("aria-label",t("사용자 메뉴"));const n=this.querySelector(".designbase-wc-sidebar__logo db-logo");n&&n.setAttribute("alt",this.getAttribute("logo-alt")||t("홈"))}),this.seedExpanded(),this.bindPanelMediaQuery(),this.render(),this.bindOutsideClick()}syncAccessibleName(){const e=this.getAttribute("aria-label");e&&e!==this.autoAriaLabel||(this.autoAriaLabel=t("사이드바 네비게이션"),this.setAttribute("aria-label",this.autoAriaLabel))}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.unbindOutsideClick(),this.unbindPanelMediaQuery(),this.cancelFlyoutClose(),this.cancelUserFlyoutClose()}attributeChangedCallback(e,t,s){if(this.isConnected&&t!==s){if("default-expanded-ids"===e||"expanded-ids"===e||"accordion-mode"===e)return this.seedExpanded(),void this.syncAccordionState();if("collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.cancelFlyoutClose(),this.cancelUserFlyoutClose()),"panel-mode"!==e&&"panel-breakpoint"!==e||this.bindPanelMediaQuery(),this.render(),"active-panel"===e){const e=this.getActivePanelConfig();this.dispatchEvent(new CustomEvent("db-panel-change",{bubbles:!0,composed:!0,detail:{panel:e?.id??"main",panelConfig:e,mode:this.resolvedPanelMode}}))}}}bindPanelMediaQuery(){this.unbindPanelMediaQuery();const e=this.panelMode;if("auto"!==e)return void(this.resolvedPanelMode=e);if("undefined"==typeof window||"function"!=typeof window.matchMedia)return void(this.resolvedPanelMode="adjacent");const t=window.matchMedia(`(min-width: ${this.panelBreakpoint}px)`);this.panelMediaQuery=t,this.resolvedPanelMode=t.matches?"adjacent":"replace",this.panelMediaHandler=e=>{const t=e.matches?"adjacent":"replace";t!==this.resolvedPanelMode&&(this.resolvedPanelMode=t,this.render(),this.dispatchEvent(new CustomEvent("db-panel-mode-change",{bubbles:!0,composed:!0,detail:{mode:t}})))},t.addEventListener("change",this.panelMediaHandler)}unbindPanelMediaQuery(){this.panelMediaQuery&&this.panelMediaHandler&&this.panelMediaQuery.removeEventListener("change",this.panelMediaHandler),this.panelMediaQuery=null,this.panelMediaHandler=null}seedExpanded(){try{const e=JSON.parse(this.getAttribute("expanded-ids")??this.getAttribute("default-expanded-ids")??"[]"),t=Array.isArray(e)?[...new Set(e.filter(e=>"string"==typeof e))]:[];this.expandedItems=new Set("single"===this.accordionMode?t.slice(0,1):t)}catch{this.expandedItems=new Set}}get expandedIds(){return[...this.expandedItems]}set expandedIds(e){this.setAttribute("expanded-ids","string"==typeof e?e:JSON.stringify(e)),this.isConnected||this.seedExpanded()}get accordionMode(){return"multiple"===this.getAttribute("accordion-mode")?"multiple":"single"}set accordionMode(e){this.setAttribute("accordion-mode",e)}get hideExpandIcon(){return this.hasAttribute("hide-expand-icon")&&"false"!==this.getAttribute("hide-expand-icon")}set hideExpandIcon(e){this.toggleAttribute("hide-expand-icon",e)}get showDepthGuide(){return this.hasAttribute("show-depth-guide")&&"false"!==this.getAttribute("show-depth-guide")}set showDepthGuide(e){this.toggleAttribute("show-depth-guide",e)}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||t("프로젝트 관리")}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||t("프로젝트")}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||t("프로젝트를 추가해 주세요")}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||t("프로젝트 추가")}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}get updateBanner(){return this.parseUpdateBanner()}set updateBanner(e){null==e?this.removeAttribute("update-banner"):this.setAttribute("update-banner","string"==typeof e?e:JSON.stringify(e))}get headerType(){return"back"===this.getAttribute("header-type")?"back":"default"}set headerType(e){this.setAttribute("header-type",e)}get backLabel(){return this.getAttribute("back-label")||t("뒤로가기")}set backLabel(e){this.setAttribute("back-label",e)}get backHref(){return this.getAttribute("back-href")||""}set backHref(e){e?this.setAttribute("back-href",e):this.removeAttribute("back-href")}get panels(){return this.parsePanels()}set panels(e){this.setAttribute("panels","string"==typeof e?e:JSON.stringify(e))}get settingsSections(){return this.parseSettingsSections()}set settingsSections(e){this.setAttribute("settings-sections","string"==typeof e?e:JSON.stringify(e))}get activePanel(){const e=this.getAttribute("active-panel")||"main";return"main"===e?"main":this.findPanel(e)?e:"main"}set activePanel(e){const t=e&&"main"!==e&&this.findPanel(e)?e:"main";this.setAttribute("active-panel",t)}get panelMode(){const e=this.getAttribute("panel-mode")||"auto";return o.includes(e)?e:"auto"}set panelMode(e){this.setAttribute("panel-mode",o.includes(e)?e:"auto")}get panelWidth(){return this.normalizeCssLength(this.getAttribute("panel-width")||p)}set panelWidth(e){this.setAttribute("panel-width",this.normalizeCssLength(e))}get panelBreakpoint(){const e=Number(this.getAttribute("panel-breakpoint"));return Number.isFinite(e)&&e>0?e:1024}set panelBreakpoint(e){const t=Number.isFinite(e)&&e>0?Math.round(e):1024;this.setAttribute("panel-breakpoint",String(t))}normalizeCssLength(e){if("number"==typeof e)return`${Math.max(0,e)}px`;const t=String(e??"").trim();return t?/^-?\d+(?:\.\d+)?$/.test(t)?`${Math.max(0,Number(t))}px`:t:p}parseSettingsSections(){try{const e=JSON.parse(this.getAttribute("settings-sections")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parsePanels(){let e=[];const t=this.getAttribute("panels");if(t)try{const s=JSON.parse(t);Array.isArray(s)&&(e=s.filter(e=>Boolean(e&&"string"==typeof e.id&&e.id.trim())).map(e=>({...e,id:e.id.trim(),title:String(e.title||e.id).trim(),sections:Array.isArray(e.sections)?e.sections:[]})))}catch{e=[]}const s=this.parseSettingsSections();return s.length&&!e.some(e=>"settings"===e.id)&&e.push({id:"settings",title:"Settings",backLabel:this.backLabel,sections:s}),e}hasPanels(){return this.parsePanels().length>0}findPanel(e){return e&&"main"!==e?this.parsePanels().find(t=>t.id===e)??null:null}getActivePanelConfig(){return this.findPanel(this.getAttribute("active-panel")||"main")}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseUpdateBanner(){const e=this.getAttribute("update-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,this.userFlyoutItemId=null,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.classList.remove("designbase-wc-sidebar--user-menu-open"),this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncAccordionState(){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(e=>{const t=e.getAttribute("data-item-id");t&&(this.expandedItems.has(t)?e.setAttribute("expanded",""):e.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}cancelUserFlyoutClose(){this.userFlyoutCloseTimer&&(clearTimeout(this.userFlyoutCloseTimer),this.userFlyoutCloseTimer=null)}setUserFlyout(e){this.cancelUserFlyoutClose(),this.userFlyoutItemId=e,this.querySelectorAll(".designbase-wc-sidebar__user-menu-item").forEach(t=>{const s=Boolean(e&&t.dataset.itemId===e);t.classList.toggle("designbase-wc-sidebar__user-menu-item--flyout-active",s),t.querySelector(".designbase-wc-sidebar__user-menu-trigger")?.setAttribute("aria-expanded",String(s));const i=t.querySelector(".designbase-wc-sidebar__user-flyout");i&&(i.hidden=!s)})}scheduleUserFlyoutClose(){this.cancelUserFlyoutClose(),this.userFlyoutCloseTimer=setTimeout(()=>{this.userFlyoutCloseTimer=null,this.setUserFlyout(null)},120)}get sidebarType(){const e=this.getAttribute("type");return d.find(t=>t===e)||"app"}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("theme")||"default",s=this.getAttribute("variant")||"default",i=this.getAttribute("position")||"left",a=this.getActivePanelConfig(),n=Boolean(a),r=this.panelWidth;this.style.setProperty("--db-sidebar-panel-width",r),this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--type-${this.sidebarType}`,`designbase-wc-sidebar--${c.includes(e)?e:"m"}`,`designbase-wc-sidebar--${l.includes(t)?t:"default"}`,`designbase-wc-sidebar--${u.includes(i)?i:"left"}`,`designbase-wc-sidebar--panel-${this.resolvedPanelMode}`,b.includes(s)&&"wrapper"===s&&"designbase-wc-sidebar--wrapper",this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow",this.userMenuOpen&&"designbase-wc-sidebar--user-menu-open",("back"===this.headerType||n&&"replace"===this.resolvedPanelMode)&&"designbase-wc-sidebar--header-back",n&&"designbase-wc-sidebar--panel-open",this.hasPanels()&&"designbase-wc-sidebar--has-panels"].filter(Boolean).join(" ")}navigateToPanel(e){const t="main"!==e&&e?this.findPanel(e)?.id:"main";t&&this.activePanel!==t&&("main"!==t&&"replace"===this.resolvedPanelMode&&this.hasAttribute("collapsed")&&this.removeAttribute("collapsed"),this.setAttribute("active-panel",t))}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchBackClick(){const e=this.getActivePanelConfig();e&&this.navigateToPanel("main");const t=new CustomEvent("db-back-click",{bubbles:!0,composed:!0,cancelable:!0,detail:{label:e?.backLabel||this.backLabel,href:this.backHref,panel:e}});this.dispatchEvent(t);const s=n(this.backHref,"");t.defaultPrevented||e||!s||"back"!==this.headerType||window.location.assign(s)}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}dispatchUpdateCtaClick(e){this.dispatchEvent(new CustomEvent("db-update-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(e="s"){const t=document.createElement("span");return t.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${e}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),t.setAttribute("aria-hidden","true"),t.append(i("plus","m"===e?16:14)),t}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("type","text"),t.textContent=e.badge,t}createProjectSelector(e){if(!this.hasAttribute("projects"))return null;const t=this.parseProjects(),s=0===t.length,a=this.getSelectedProject(),r=document.createElement("div");r.className=["designbase-wc-sidebar__project-selector",e&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",s&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const o=this.getAttribute("project-section-label");if(!e&&o&&o.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=o.trim(),r.append(e)}const d=document.createElement("button");if(d.type="button",d.className="designbase-wc-sidebar__project-trigger",d.setAttribute("aria-haspopup","menu"),d.setAttribute("aria-expanded",String(this.projectMenuOpen)),s||!a){if(d.dataset.projectEmptyTrigger="",d.setAttribute("aria-label",this.projectEmptyTriggerLabel),d.append(this.createProjectEmptyMark(e?"m":"s")),!e){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,d.append(e)}}else if(d.setAttribute("aria-label",a.label),d.append(this.createProjectAvatar(a,e?"m":"s")),!e){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=a.label,d.append(e)}const c=document.createElement("span");if(c.className="designbase-wc-sidebar__project-chevron",c.setAttribute("aria-hidden","true"),c.append(i("chevron-down",14)),d.append(c),d.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),r.append(d),this.projectMenuOpen){const e=document.createElement("div");if(e.className="designbase-wc-sidebar__project-dropdown",e.setAttribute("role","menu"),e.setAttribute("aria-label",this.projectSectionLabel),s){const t=document.createElement("div");t.className="designbase-wc-sidebar__project-empty",t.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,t.append(s),e.append(t)}else{const s=document.createElement("ul");s.className="designbase-wc-sidebar__project-list",t.forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",a&&e.id===a.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(e,"s"));const n=document.createElement("span");n.className="designbase-wc-sidebar__project-option-label",n.textContent=e.label,i.append(n);const r=this.createProjectBadge(e);r&&i.append(r),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",e.id),this.dispatchProjectChange(e),this.render()}),t.append(i),s.append(t)}),e.append(s)}const o=document.createElement("button");o.type="button",o.className="designbase-wc-sidebar__project-manage",o.setAttribute("role","menuitem"),o.append(i("plus",14));const d=document.createElement("span");d.textContent=this.projectManageLabel,o.append(d),o.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref,t=n(e,"");t&&window.location.assign(t),this.dispatchProjectManage(),this.render()}),e.append(o),r.append(e)}return r}createFlyout(e,t){const i=this.getAttribute("position")||"left",a=document.createElement("div");a.className=["designbase-wc-sidebar__flyout","right"===i&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),a.setAttribute("role","menu"),a.setAttribute("aria-label",s("{0} 하위 메뉴",[e.label])),a.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),a.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const r=document.createElement("div");r.className="designbase-wc-sidebar__flyout-title",r.textContent=e.label,a.append(r);const o=document.createElement("ul");return o.className="designbase-wc-sidebar__flyout-list",(e.children||[]).forEach(e=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",t);const a=n(e.href,"");a&&i.setAttribute("href",a),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),s.append(i),o.append(s)}),a.append(o),a}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),a=this.expandedItems.has(e.id),r=this.hasAttribute("collapsed"),o=r&&i,d=document.createElement("li");d.className=["designbase-wc-sidebar__item",o&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),o&&(d.addEventListener("mouseenter",()=>this.showFlyout(e.id)),d.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const c=document.createElement("db-menu-item");c.setAttribute("data-item-id",e.id),c.setAttribute("label",e.label),c.setAttribute("type","block"),c.setAttribute("menu-style","accordion"),c.setAttribute("size",t),c.setAttribute("depth",String(s));const l=n(e.href,"");if(l&&c.setAttribute("href",l),e.icon&&c.setAttribute("icon",e.icon),(e.active||e.openPanel&&e.openPanel===this.activePanel)&&c.setAttribute("active",""),e.disabled&&c.setAttribute("disabled",""),void 0!==e.badge&&c.setAttribute("badge",String(e.badge)),e.badgeColor&&c.setAttribute("badge-color",e.badgeColor),i&&!o&&(c.setAttribute("expandable",""),c.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor,icon:e.icon})),a&&!r&&c.setAttribute("expanded","")),c.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!r){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),s?("single"===this.accordionMode&&this.expandedItems.clear(),this.expandedItems.add(e.id)):this.expandedItems.delete(e.id),this.expandedIds=[...this.expandedItems],this.syncAccordionState(),this.dispatchEvent(new CustomEvent("db-expanded-change",{detail:{itemId:e.id,expanded:s,expandedIds:this.expandedIds},bubbles:!0,composed:!0})),void("app"!==this.sidebarType&&this.dispatchItemClick(e))}if(o)return this.closeOverlayMenus(),void this.showFlyout(e.id);if(this.closeOverlayMenus(),e.openPanel&&this.findPanel(e.openPanel))return this.dispatchItemClick(e),void this.navigateToPanel(e.openPanel);this.dispatchItemClick(e)}}),c.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),d.append(c),r&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),d.append(s)}if(r&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),d.append(t)}return o&&this.flyoutItemId===e.id&&d.append(this.createFlyout(e,t)),d}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const a=document.createElement("div");if(a.className=["designbase-wc-sidebar__section",e.gap&&`designbase-wc-sidebar__section--gap-${e.gap}`].filter(Boolean).join(" "),!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>n.append(this.createSidebarMenuItem(e,t))),a.append(n),i.append(a)}),i}renderNav(){const e=this.getAttribute("size")||"m",t=this.hasAttribute("collapsed"),s=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="main"]');s&&s.replaceChildren(this.renderSectionList(this.parseSections(),e,t),this.createCustomNavSlot("nav"));const i=this.getActivePanelConfig(),a=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="panel"]');a&&i&&a.replaceChildren(this.renderSectionList(i.sections,e,!1))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(e,r=!1){if(!e.length)return null;const o=this.getAttribute("position")||"left",d=document.createElement("div");d.className=["designbase-wc-sidebar__user-dropdown",r&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),d.setAttribute("role","menu"),d.setAttribute("aria-label",t("사용자 메뉴")),d.hidden=!this.userMenuOpen,d.addEventListener("keydown",e=>{"Escape"===e.key&&(e.stopPropagation(),this.userFlyoutItemId?this.setUserFlyout(null):(this.userMenuOpen=!1,this.render()))});const c=document.createElement("ul");return c.className="designbase-wc-sidebar__user-menu",e.forEach(e=>{const t=Boolean(e.children?.length),r=document.createElement("li");r.dataset.itemId=e.id,r.className=["designbase-wc-sidebar__user-menu-item",e.dividerBefore&&"designbase-wc-sidebar__user-menu-item--divider",e.disabled&&"designbase-wc-sidebar__user-menu-item--disabled",t&&"designbase-wc-sidebar__user-menu-item--has-children"].filter(Boolean).join(" ");const d=document.createElement("button");if(d.type="button",d.className="designbase-wc-sidebar__user-menu-trigger",d.setAttribute("role","menuitem"),d.disabled=Boolean(e.disabled),e.icon&&a(e.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(i(e.icon,16)),d.append(t)}const l=document.createElement("span");if(l.className="designbase-wc-sidebar__user-menu-label",l.textContent=e.label,d.append(l),e.value){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-value",t.textContent=e.value,d.append(t)}if(t){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-chevron",t.setAttribute("aria-hidden","true"),t.append(i("right"===o?"chevron-left":"chevron-right",16)),d.append(t),d.setAttribute("aria-haspopup","menu"),d.setAttribute("aria-expanded",String(this.userFlyoutItemId===e.id));const openFlyout=()=>this.setUserFlyout(e.id);r.addEventListener("mouseenter",openFlyout),r.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose()),r.addEventListener("focusin",openFlyout),r.addEventListener("focusout",e=>{const t=e.relatedTarget;t&&r.contains(t)||this.scheduleUserFlyoutClose()}),d.addEventListener("click",openFlyout);const c=document.createElement("div");c.className=["designbase-wc-sidebar__user-flyout","right"===o&&"designbase-wc-sidebar__user-flyout--align-left"].filter(Boolean).join(" "),c.setAttribute("role","menu"),c.setAttribute("aria-label",s("{0} 하위 메뉴",[e.label])),c.hidden=this.userFlyoutItemId!==e.id,c.addEventListener("mouseenter",()=>this.cancelUserFlyoutClose()),c.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose());const l=document.createElement("ul");l.className="designbase-wc-sidebar__user-flyout-list",(e.children||[]).forEach(e=>{const t=document.createElement("li");t.className="designbase-wc-sidebar__user-flyout-item";const s=document.createElement("button");if(s.type="button",s.className=["designbase-wc-sidebar__user-menu-trigger","designbase-wc-sidebar__user-flyout-trigger",e.selected&&"designbase-wc-sidebar__user-flyout-trigger--selected"].filter(Boolean).join(" "),s.setAttribute("role","menuitemradio"),s.setAttribute("aria-checked",String(Boolean(e.selected))),s.disabled=Boolean(e.disabled),e.icon&&a(e.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(i(e.icon,16)),s.append(t)}const r=document.createElement("span");if(r.className="designbase-wc-sidebar__user-menu-label",r.textContent=e.label,s.append(r),e.selected){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-check",e.setAttribute("aria-hidden","true"),e.append(i("done",16)),s.append(e)}s.addEventListener("click",()=>{if(e.disabled)return;this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(e);const t=n(e.href,"");t&&window.location.assign(t),this.render()}),t.append(s),l.append(t)}),c.append(l),r.append(d,c)}else d.addEventListener("click",()=>{if(e.disabled)return;this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(e);const t=n(e.href,"");t&&window.location.assign(t),this.render()}),r.append(d);c.append(r)}),d.append(c),d}createUpdateBanner(e){if("back"===this.headerType)return null;const t=this.parseUpdateBanner();if(!t)return null;if(e)return null;const s=document.createElement("div");s.className="designbase-wc-sidebar__update";const i=document.createElement("db-banner");return i.className="designbase-wc-sidebar__update-banner",i.setAttribute("size","s"),i.setAttribute("variant",t.variant||"outline"),i.setAttribute("title",t.title),t.description&&i.setAttribute("description",t.description),t.icon&&i.setAttribute("icon",t.icon),i.setAttribute("clickable",""),i.setAttribute("aria-label",t.ctaLabel||t.title),i.addEventListener("db-click",()=>{const e=n(t.ctaHref,"");e&&window.location.assign(e),this.dispatchUpdateCtaClick(t)}),s.append(i),s}createPromoBanner(e){if("back"===this.headerType)return null;const t=this.parsePromoBanner();if(!t)return null;if(e){const e=document.createElement("button");e.type="button",e.className="designbase-wc-sidebar__promo-collapsed",e.setAttribute("aria-label",t.ctaLabel||t.title);const s=document.createElement("db-animation-background");s.className="designbase-wc-sidebar__promo-bg",s.setAttribute("type","aurora"),s.setAttribute("theme","light"),s.setAttribute("intensity","subtle"),s.setAttribute("blur","40"),s.setAttribute("speed","4000"),s.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),e.append(s),e.append(i(t.icon&&a(t.icon)?t.icon:"sparkle",18)),e.addEventListener("click",()=>this.dispatchPromoCtaClick(t));const n=document.createElement("span");n.className="designbase-wc-sidebar__item-tooltip",n.textContent=t.title,n.setAttribute("role","tooltip");const r=document.createElement("div");return r.className="designbase-wc-sidebar__promo-collapsed-wrap",r.append(e,n),r}const s=document.createElement("div");s.className="designbase-wc-sidebar__promo";const r=document.createElement("db-animation-background");r.className="designbase-wc-sidebar__promo-bg",r.setAttribute("type","aurora"),r.setAttribute("theme","light"),r.setAttribute("intensity","subtle"),r.setAttribute("blur","60"),r.setAttribute("speed","5000"),r.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),s.append(r);const o=document.createElement("div");o.className="designbase-wc-sidebar__promo-content";const d=document.createElement("div");d.className="designbase-wc-sidebar__promo-title-row";const c=document.createElement("span");c.className="designbase-wc-sidebar__promo-icon",c.setAttribute("aria-hidden","true"),c.append(i(t.icon&&a(t.icon)?t.icon:"sparkle",16));const l=document.createElement("div");if(l.className="designbase-wc-sidebar__promo-title",l.textContent=t.title,d.append(c,l),o.append(d),t.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=t.description,o.append(e)}if(t.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=t.ctaLabel,e.addEventListener("db-click",()=>{const e=n(t.ctaHref,"");e&&window.location.assign(e),this.dispatchPromoCtaClick(t)}),o.append(e)}return s.append(o),s}createMainHeader(e){const{size:s,collapsible:a,showLogo:n,collapsed:r}=e,o="back"===this.headerType,d="l"===s?"m":"s"===s?"xs":"s";if(!o&&!a&&(!n||r))return null;const c=document.createElement("div");if(c.className=["designbase-wc-sidebar__header",(r||!n)&&!o&&"designbase-wc-sidebar__header--collapsed-only",o&&"designbase-wc-sidebar__header--back"].filter(Boolean).join(" "),o){const e=document.createElement("button");if(e.type="button",e.className=["designbase-wc-sidebar__back",r&&"designbase-wc-sidebar__back--collapsed"].filter(Boolean).join(" "),e.setAttribute("aria-label",this.backLabel),e.append(i("chevron-left",18)),!r){const t=document.createElement("span");t.textContent=this.backLabel,e.append(t)}e.addEventListener("click",()=>this.dispatchBackClick()),c.append(e)}else if(!r&&n){const e=document.createElement("div");e.className="designbase-wc-sidebar__logo";const s=this.getAttribute("logo-type")||"designbase",i=this.getAttribute("logo-text")||"",a=this.getAttribute("logo-src");if(a){const s=document.createElement("db-logo");s.setAttribute("type","custom"),s.setAttribute("src",a),s.setAttribute("alt",this.getAttribute("logo-alt")||t("홈")),s.setAttribute("size",d),e.append(s)}else if("custom"===s&&i){const t=document.createElement("span");t.className="designbase-wc-sidebar__logo-text",t.textContent=i,e.append(t)}else{const t=document.createElement("db-logo");t.setAttribute("type",s),t.setAttribute("size",d),i&&t.setAttribute("text",i),e.append(t)}e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),c.append(e)}if(a&&!o){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__toggle",e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("icon-only",""),e.setAttribute("start-icon",r?"arrow-bar-right":"arrow-bar-left"),e.setAttribute("aria-label",t(r?"사이드바 펼치기":"사이드바 접기")),e.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),c.append(e)}return c}createPanelHeader(e){const t="replace"===this.resolvedPanelMode,s=document.createElement("div");if(s.className=["designbase-wc-sidebar__panel-header",t&&"designbase-wc-sidebar__panel-header--replace"].filter(Boolean).join(" "),t){const t=document.createElement("button");t.type="button",t.className="designbase-wc-sidebar__panel-back",t.setAttribute("aria-label",e.backLabel||this.backLabel),t.append(i("chevron-left",18)),t.addEventListener("click",()=>this.dispatchBackClick()),s.append(t)}const a=document.createElement("div");a.className="designbase-wc-sidebar__panel-heading";const n=document.createElement("div");if(n.className="designbase-wc-sidebar__panel-title",n.textContent=e.title,a.append(n),e.description){const t=document.createElement("div");t.className="designbase-wc-sidebar__panel-description",t.textContent=e.description,a.append(t)}return s.append(a),s}createNavWrapper(e){const{mode:s,collapsed:i,includeProjects:a,includeBottom:n,panel:r}=e,o=document.createElement("div");if(o.className="designbase-wc-sidebar__nav-wrapper",a){const e=this.createProjectSelector(i);e&&o.append(e)}"main"===s&&o.append(this.createCustomNavSlot("nav-top"));const d=document.createElement("nav");if(d.className="designbase-wc-sidebar__nav",d.setAttribute("data-panel-nav",s),r&&(d.dataset.panelId=r.id),d.setAttribute("aria-label",r?.ariaLabel||r?.title||t("주 메뉴")),o.append(d),"main"===s&&o.append(this.createCustomNavSlot("nav-bottom")),n){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label",t("하단 메뉴")),o.append(e)}return o}createFooter(e){const{collapsed:t,userProfile:s,userMenuItems:a}=e,n=document.createElement("div");n.className="designbase-wc-sidebar__footer";const r=this.createUpdateBanner(t);r&&n.append(r);const o=this.createPromoBanner(t);if(o&&n.append(o),s&&!t){const e=document.createElement("div");e.className="designbase-wc-sidebar__user";const t=this.createUserDropdown(a);t&&e.append(t);const r=document.createElement("div");r.className="designbase-wc-sidebar__user-info",r.setAttribute("role","button"),r.setAttribute("tabindex","0"),r.setAttribute("aria-expanded",String(this.userMenuOpen));const o=document.createElement("db-avatar");o.className="designbase-wc-sidebar__user-avatar",o.setAttribute("size","s"),o.setAttribute("initials",s.name),o.setAttribute("alt",s.name),s.avatar&&o.setAttribute("src",s.avatar);const d=document.createElement("div");d.className="designbase-wc-sidebar__user-details";const c=document.createElement("div");if(c.className="designbase-wc-sidebar__user-name",c.textContent=s.name,d.append(c),s.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=s.email,d.append(e)}if(r.append(o,d),a.length){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-more",e.setAttribute("aria-hidden","true"),e.append(i("more-vertical",16)),r.append(e),r.setAttribute("aria-haspopup","menu")}r.addEventListener("click",()=>{a.length&&(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render())}),r.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),r.click())}),e.append(r),n.append(e)}else if(s&&t){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",s.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),a.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",s.name),t.setAttribute("alt",s.name),s.avatar&&t.setAttribute("src",s.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=s.name,t.setAttribute("role","tooltip"),e.append(t)}const i=this.createUserDropdown(a,!0);i&&e.append(i),e.addEventListener("click",e=>{a.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render()))}),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}),n.append(e)}return n}render(){const e=this.getActivePanelConfig();this.syncHostClasses(),this.setAttribute("role","complementary"),this.syncAccessibleName();const t=this.getAttribute("size")||"m",s="false"!==(this.getAttribute("collapsible")??("app"===this.sidebarType?"true":"false")),i="false"!==(this.getAttribute("show-logo")??("app"===this.sidebarType?"true":"false")),a=this.hasAttribute("collapsed"),n=this.parseUserProfile(),r=this.parseUserMenuItems(),o=this.parseBottomSections(),d=this.collectCustomNavSlots(),c=Boolean(e),l="replace"===this.resolvedPanelMode;this.replaceChildren();const u=document.createElement("div");u.className="designbase-wc-sidebar__container";const b=document.createElement("div");b.className="designbase-wc-sidebar__panel-viewport";const p=document.createElement("div");p.className="designbase-wc-sidebar__panel-track",p.dataset.active=c&&l?"main":c?"panel":"main";const m=document.createElement("div");m.className=["designbase-wc-sidebar__panel-slide","designbase-wc-sidebar__panel-slide--main"].join(" "),m.dataset.panel="main";const h=c&&l;m.toggleAttribute("inert",h),m.setAttribute("aria-hidden",String(h));const g=this.createMainHeader({size:t,collapsible:s,showLogo:i,collapsed:a});if(g&&m.append(g),m.append(this.createNavWrapper({mode:"main",collapsed:a,includeProjects:"back"!==this.headerType,includeBottom:o.length>0})),m.append(this.createFooter({collapsed:a,userProfile:n,userMenuItems:r})),p.append(m),e){const t=document.createElement("div");t.className=["designbase-wc-sidebar__panel-slide","designbase-wc-sidebar__panel-slide--secondary"].join(" "),t.dataset.panel=e.id,t.setAttribute("aria-hidden","false"),t.append(this.createPanelHeader(e)),t.append(this.createNavWrapper({mode:"panel",collapsed:!1,includeProjects:!1,includeBottom:!1,panel:e})),p.append(t)}b.append(p),u.append(b),this.append(u),this.renderNav(),this.renderBottomNav(),this.projectCustomNavSlots(d),c&&l&&requestAnimationFrame(()=>{this.isConnected&&this.activePanel===e?.id&&(p.dataset.active="panel")})}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
@@ -19,6 +19,7 @@ declare class DbSignature extends HTMLElement {
19
19
  private canvas;
20
20
  private placeholderEl;
21
21
  private clearButton;
22
+ private unsubscribeLocale?;
22
23
  private resizeObserver;
23
24
  private themeObserver;
24
25
  private strokes;
@@ -42,6 +43,7 @@ declare class DbSignature extends HTMLElement {
42
43
  private get maxWidth();
43
44
  private get interactive();
44
45
  private getPenColor;
46
+ private refreshLocale;
45
47
  private render;
46
48
  private updateState;
47
49
  private syncCanvasSize;
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{coerceToContract as e}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{SIGNATURE_VARIANTS as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const s=i;class DbSignature extends HTMLElement{constructor(){super(...arguments),this.canvas=null,this.placeholderEl=null,this.clearButton=null,this.resizeObserver=null,this.themeObserver=null,this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.lastWidth=0,this.lastVelocity=0,this.backgroundImage=null,this.activePointerId=null,this.handlePointerDown=t=>{if(!this.interactive||0!==t.button)return;t.preventDefault(),this.focus({preventScroll:!0}),this.activePointerId=t.pointerId;try{this.canvas?.setPointerCapture(t.pointerId)}catch{}this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2;const e=this.getPoint(t);this.currentStroke=[e],this.lastMid=e,this.dispatchEvent(new CustomEvent("db-begin",{bubbles:!0,composed:!0}))},this.handlePointerMove=t=>{if(!this.currentStroke||this.activePointerId!==t.pointerId)return;t.preventDefault();const e="function"==typeof t.getCoalescedEvents?t.getCoalescedEvents():[t];for(const t of e){const e=this.canvas.getBoundingClientRect();this.appendPoint({x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()})}},this.handlePointerUp=t=>{const e=this.currentStroke;if(!e||this.activePointerId!==t.pointerId)return;this.activePointerId=null,this.currentStroke=null;const i=this.canvas?.getContext("2d");if(i)if(1===e.length)this.drawDot(i,e[0],this.getPenColor());else{const t=e[e.length-1],s=this.lastMid??t,n=this.lastWidth||(this.minWidth+this.maxWidth)/2;this.drawCurveSegment(i,s,t,t,this.getPenColor(),n)}this.lastMid=null,this.strokes.push(e),this.redoStack=[],this.updateState(),this.dispatchEvent(new CustomEvent("db-end",{bubbles:!0,composed:!0})),this.emitChange()},this.handleClearClick=()=>{this.interactive&&(this.clear(),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0})),this.emitChange())},this.handleKeyDown=t=>{if(!this.interactive)return;if(!(t.metaKey||t.ctrlKey))return;const e=t.key.toLowerCase();return"z"===e&&t.shiftKey?(t.preventDefault(),void this.redo()):"z"===e?(t.preventDefault(),void this.undo()):void("y"===e&&(t.preventDefault(),this.redo()))}}static get observedAttributes(){return["height","variant","pen-color","background-color","min-width","max-width","placeholder","show-clear","clear-label","disabled","readonly","value"]}connectedCallback(){this.render(),this.syncCanvasSize(),this.addEventListener("keydown",this.handleKeyDown),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>this.syncCanvasSize()),this.resizeObserver.observe(this)),"undefined"!=typeof MutationObserver&&(this.themeObserver=new MutationObserver(()=>{this.getAttribute("pen-color")||this.redraw()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme","data-color-mode","class"]}));const t=this.getAttribute("value");t&&this.fromDataURL(t)}disconnectedCallback(){this.removeEventListener("keydown",this.handleKeyDown),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.themeObserver?.disconnect(),this.themeObserver=null}attributeChangedCallback(t,e,i){this.isConnected&&e!==i&&("value"!==t?(this.render(),this.syncCanvasSize(),this.redraw()):i?this.fromDataURL(i):this.clear())}get value(){return this.toDataURL()}set value(t){t?this.fromDataURL(t):this.clear()}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}getBooleanAttr(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getVariant(){return e(this.getAttribute("variant"),s,"dashed")}get minWidth(){return this.getNumberAttr("min-width",1)}get maxWidth(){return this.getNumberAttr("max-width",3.2)}get interactive(){return!this.getBooleanAttr("disabled")&&!this.getBooleanAttr("readonly")}getPenColor(){const t=this.getAttribute("pen-color");if(t)return t;return getComputedStyle(this).getPropertyValue("--db-text-primary").trim()||"#2c3542"}render(){const e=this.getVariant(),i=this.getAttribute("placeholder")??"",s=this.getBooleanAttr("show-clear",!0);if(this.className=["designbase-wc-signature",`designbase-wc-signature--${e}`,this.getBooleanAttr("disabled")&&"designbase-wc-signature--disabled",this.getBooleanAttr("readonly")&&"designbase-wc-signature--readonly",this.isEmpty()&&"designbase-wc-signature--empty"].filter(Boolean).join(" "),this.style.height=`${this.getNumberAttr("height",220)}px`,this.interactive?this.tabIndex=0:this.removeAttribute("tabindex"),this.canvas||(this.canvas=document.createElement("canvas"),this.canvas.className="designbase-wc-signature__canvas",this.canvas.setAttribute("role","img"),this.canvas.addEventListener("pointerdown",this.handlePointerDown),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerup",this.handlePointerUp),this.canvas.addEventListener("pointercancel",this.handlePointerUp),this.append(this.canvas)),this.canvas.setAttribute("aria-label",i||"서명 입력 영역"),i?(this.placeholderEl||(this.placeholderEl=document.createElement("span"),this.placeholderEl.className="designbase-wc-signature__placeholder",this.append(this.placeholderEl)),this.placeholderEl.textContent=i,this.placeholderEl.hidden=!this.isEmpty()):(this.placeholderEl?.remove(),this.placeholderEl=null),s){this.clearButton||(this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="designbase-wc-signature__clear",this.clearButton.addEventListener("click",this.handleClearClick),this.clearButton.append(t("trash",20)),this.append(this.clearButton));const e=this.getAttribute("clear-label")||"서명 지우기";this.clearButton.setAttribute("aria-label",e),this.clearButton.title=e,this.clearButton.disabled=!this.interactive||this.isEmpty()}else this.clearButton?.remove(),this.clearButton=null}updateState(){const t=this.isEmpty();this.classList.toggle("designbase-wc-signature--empty",t),this.placeholderEl&&(this.placeholderEl.hidden=!t),this.clearButton&&(this.clearButton.disabled=!this.interactive||t)}syncCanvasSize(){const t=this.canvas;if(!t)return;const e=window.devicePixelRatio||1,i=t.getBoundingClientRect();if(0===i.width||0===i.height)return;const s=Math.round(i.width*e),n=Math.round(i.height*e);t.width===s&&t.height===n||(t.width=s,t.height=n,t.getContext("2d")?.scale(e,e),this.redraw())}resetCanvas(t,e,i){t.clearRect(0,0,e,i);const s=this.getAttribute("background-color");s&&"transparent"!==s&&(t.fillStyle=s,t.fillRect(0,0,e,i)),this.backgroundImage&&t.drawImage(this.backgroundImage,0,0,e,i)}resolveWidth(t,e){const i=e.x-t.x,s=e.y-t.y,n=.55*(Math.sqrt(i*i+s*s)/Math.max(e.t-t.t,1))+(1-.55)*this.lastVelocity;this.lastVelocity=n;const{minWidth:r,maxWidth:a}=this,h=Math.min(Math.max(a/(.85*n+1),r),a),o=(this.lastWidth+h)/2;return this.lastWidth=h,o}drawCurveSegment(t,e,i,s,n,r){t.strokeStyle=n,t.lineWidth=r,t.lineCap="round",t.lineJoin="round",t.beginPath(),t.moveTo(e.x,e.y),t.quadraticCurveTo(i.x,i.y,s.x,s.y),t.stroke()}drawDot(t,e,i){t.fillStyle=i,t.beginPath(),t.arc(e.x,e.y,(this.minWidth+this.maxWidth)/4,0,2*Math.PI),t.fill()}drawStroke(t,e,i){if(this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2,0===e.length)return;if(1===e.length)return void this.drawDot(t,e[0],i);if(2===e.length){const s=this.resolveWidth(e[0],e[1]);return void this.drawCurveSegment(t,e[0],e[0],e[1],i,s)}let s=e[0];for(let n=1;n<e.length-1;n+=1){const r=e[n],a=e[n+1],h={x:(r.x+a.x)/2,y:(r.y+a.y)/2,t:r.t},o=this.resolveWidth(e[n-1],r);this.drawCurveSegment(t,s,r,h,i,o),s=h}const n=e[e.length-1],r=e[e.length-2],a=this.resolveWidth(r,n);this.drawCurveSegment(t,s,n,n,i,a)}redraw(){const t=this.canvas,e=t?.getContext("2d");if(!t||!e)return;const i=window.devicePixelRatio||1;this.resetCanvas(e,t.width/i,t.height/i);const s=this.getPenColor();for(const t of this.strokes)this.drawStroke(e,t,s)}getPoint(t){const e=t.currentTarget.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()}}appendPoint(t){const e=this.currentStroke,i=this.canvas?.getContext("2d");if(!e||!i)return;const s=e[e.length-1],n=t.x-s.x,r=t.y-s.y;if(Math.sqrt(n*n+r*r)<1.5)return;e.push(t);const a=this.getPenColor(),h=this.lastMid??s,o={x:(s.x+t.x)/2,y:(s.y+t.y)/2,t:t.t},l=this.resolveWidth(s,t);this.drawCurveSegment(i,h,s,o,a,l),this.lastMid=o}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.toDataURL()}}))}isEmpty(){return 0===this.strokes.length&&!this.backgroundImage}clear(){this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.backgroundImage=null,this.redraw(),this.updateState()}undo(){if(this.currentStroke)return;if(0===this.strokes.length)return;const t=this.strokes[this.strokes.length-1];this.strokes=this.strokes.slice(0,-1),this.redoStack=[...this.redoStack,t],this.redraw(),this.updateState(),this.emitChange()}redo(){if(this.currentStroke)return;if(0===this.redoStack.length)return;const t=this.redoStack[this.redoStack.length-1];this.redoStack=this.redoStack.slice(0,-1),this.strokes=[...this.strokes,t],this.redraw(),this.updateState(),this.emitChange()}toDataURL(t="image/png",e){return!this.canvas||this.isEmpty()?null:this.canvas.toDataURL(t,e)}fromDataURL(t){const e=new Image;e.crossOrigin="anonymous",e.onload=()=>{this.backgroundImage=e,this.strokes=[],this.redoStack=[],this.redraw(),this.updateState()},e.src=t}getCanvas(){return this.canvas}}customElements.get("db-signature")||customElements.define("db-signature",DbSignature);export{DbSignature};
1
+ import{subscribeDbLocale as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{SIGNATURE_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const n=r;class DbSignature extends HTMLElement{constructor(){super(...arguments),this.canvas=null,this.placeholderEl=null,this.clearButton=null,this.resizeObserver=null,this.themeObserver=null,this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.lastWidth=0,this.lastVelocity=0,this.backgroundImage=null,this.activePointerId=null,this.handlePointerDown=t=>{if(!this.interactive||0!==t.button)return;t.preventDefault(),this.focus({preventScroll:!0}),this.activePointerId=t.pointerId;try{this.canvas?.setPointerCapture(t.pointerId)}catch{}this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2;const e=this.getPoint(t);this.currentStroke=[e],this.lastMid=e,this.dispatchEvent(new CustomEvent("db-begin",{bubbles:!0,composed:!0}))},this.handlePointerMove=t=>{if(!this.currentStroke||this.activePointerId!==t.pointerId)return;t.preventDefault();const e="function"==typeof t.getCoalescedEvents?t.getCoalescedEvents():[t];for(const t of e){const e=this.canvas.getBoundingClientRect();this.appendPoint({x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()})}},this.handlePointerUp=t=>{const e=this.currentStroke;if(!e||this.activePointerId!==t.pointerId)return;this.activePointerId=null,this.currentStroke=null;const i=this.canvas?.getContext("2d");if(i)if(1===e.length)this.drawDot(i,e[0],this.getPenColor());else{const t=e[e.length-1],s=this.lastMid??t,r=this.lastWidth||(this.minWidth+this.maxWidth)/2;this.drawCurveSegment(i,s,t,t,this.getPenColor(),r)}this.lastMid=null,this.strokes.push(e),this.redoStack=[],this.updateState(),this.dispatchEvent(new CustomEvent("db-end",{bubbles:!0,composed:!0})),this.emitChange()},this.handleClearClick=()=>{this.interactive&&(this.clear(),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0})),this.emitChange())},this.handleKeyDown=t=>{if(!this.interactive)return;if(!(t.metaKey||t.ctrlKey))return;const e=t.key.toLowerCase();return"z"===e&&t.shiftKey?(t.preventDefault(),void this.redo()):"z"===e?(t.preventDefault(),void this.undo()):void("y"===e&&(t.preventDefault(),this.redo()))}}static get observedAttributes(){return["height","variant","pen-color","background-color","min-width","max-width","placeholder","show-clear","clear-label","disabled","readonly","value"]}connectedCallback(){this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.refreshLocale()),this.syncCanvasSize(),this.addEventListener("keydown",this.handleKeyDown),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>this.syncCanvasSize()),this.resizeObserver.observe(this)),"undefined"!=typeof MutationObserver&&(this.themeObserver=new MutationObserver(()=>{this.getAttribute("pen-color")||this.redraw()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme","data-color-mode","class"]}));const e=this.getAttribute("value");e&&this.fromDataURL(e)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("keydown",this.handleKeyDown),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.themeObserver?.disconnect(),this.themeObserver=null}attributeChangedCallback(t,e,i){this.isConnected&&e!==i&&("value"!==t?(this.render(),this.syncCanvasSize(),this.redraw()):i?this.fromDataURL(i):this.clear())}get value(){return this.toDataURL()}set value(t){t?this.fromDataURL(t):this.clear()}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}getBooleanAttr(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getVariant(){return s(this.getAttribute("variant"),n,"dashed")}get minWidth(){return this.getNumberAttr("min-width",1)}get maxWidth(){return this.getNumberAttr("max-width",3.2)}get interactive(){return!this.getBooleanAttr("disabled")&&!this.getBooleanAttr("readonly")}getPenColor(){const t=this.getAttribute("pen-color");if(t)return t;return getComputedStyle(this).getPropertyValue("--db-text-primary").trim()||"#2c3542"}refreshLocale(){if(this.canvas?.setAttribute("aria-label",this.getAttribute("placeholder")||e("서명 입력 영역")),this.clearButton){const t=this.getAttribute("clear-label")||e("서명 지우기");this.clearButton.setAttribute("aria-label",t),this.clearButton.title=t}}render(){const t=this.getVariant(),s=this.getAttribute("placeholder")??"",r=this.getBooleanAttr("show-clear",!0);if(this.className=["designbase-wc-signature",`designbase-wc-signature--${t}`,this.getBooleanAttr("disabled")&&"designbase-wc-signature--disabled",this.getBooleanAttr("readonly")&&"designbase-wc-signature--readonly",this.isEmpty()&&"designbase-wc-signature--empty"].filter(Boolean).join(" "),this.style.height=`${this.getNumberAttr("height",220)}px`,this.interactive?this.tabIndex=0:this.removeAttribute("tabindex"),this.canvas||(this.canvas=document.createElement("canvas"),this.canvas.className="designbase-wc-signature__canvas",this.canvas.setAttribute("role","img"),this.canvas.addEventListener("pointerdown",this.handlePointerDown),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerup",this.handlePointerUp),this.canvas.addEventListener("pointercancel",this.handlePointerUp),this.append(this.canvas)),this.canvas.setAttribute("aria-label",s||e("서명 입력 영역")),s?(this.placeholderEl||(this.placeholderEl=document.createElement("span"),this.placeholderEl.className="designbase-wc-signature__placeholder",this.append(this.placeholderEl)),this.placeholderEl.textContent=s,this.placeholderEl.hidden=!this.isEmpty()):(this.placeholderEl?.remove(),this.placeholderEl=null),r){this.clearButton||(this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="designbase-wc-signature__clear",this.clearButton.addEventListener("click",this.handleClearClick),this.clearButton.append(i("trash",20)),this.append(this.clearButton));const t=this.getAttribute("clear-label")||e("서명 지우기");this.clearButton.setAttribute("aria-label",t),this.clearButton.title=t,this.clearButton.disabled=!this.interactive||this.isEmpty()}else this.clearButton?.remove(),this.clearButton=null}updateState(){const t=this.isEmpty();this.classList.toggle("designbase-wc-signature--empty",t),this.placeholderEl&&(this.placeholderEl.hidden=!t),this.clearButton&&(this.clearButton.disabled=!this.interactive||t)}syncCanvasSize(){const t=this.canvas;if(!t)return;const e=window.devicePixelRatio||1,i=t.getBoundingClientRect();if(0===i.width||0===i.height)return;const s=Math.round(i.width*e),r=Math.round(i.height*e);t.width===s&&t.height===r||(t.width=s,t.height=r,t.getContext("2d")?.scale(e,e),this.redraw())}resetCanvas(t,e,i){t.clearRect(0,0,e,i);const s=this.getAttribute("background-color");s&&"transparent"!==s&&(t.fillStyle=s,t.fillRect(0,0,e,i)),this.backgroundImage&&t.drawImage(this.backgroundImage,0,0,e,i)}resolveWidth(t,e){const i=e.x-t.x,s=e.y-t.y,r=.55*(Math.sqrt(i*i+s*s)/Math.max(e.t-t.t,1))+(1-.55)*this.lastVelocity;this.lastVelocity=r;const{minWidth:n,maxWidth:a}=this,h=Math.min(Math.max(a/(.85*r+1),n),a),o=(this.lastWidth+h)/2;return this.lastWidth=h,o}drawCurveSegment(t,e,i,s,r,n){t.strokeStyle=r,t.lineWidth=n,t.lineCap="round",t.lineJoin="round",t.beginPath(),t.moveTo(e.x,e.y),t.quadraticCurveTo(i.x,i.y,s.x,s.y),t.stroke()}drawDot(t,e,i){t.fillStyle=i,t.beginPath(),t.arc(e.x,e.y,(this.minWidth+this.maxWidth)/4,0,2*Math.PI),t.fill()}drawStroke(t,e,i){if(this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2,0===e.length)return;if(1===e.length)return void this.drawDot(t,e[0],i);if(2===e.length){const s=this.resolveWidth(e[0],e[1]);return void this.drawCurveSegment(t,e[0],e[0],e[1],i,s)}let s=e[0];for(let r=1;r<e.length-1;r+=1){const n=e[r],a=e[r+1],h={x:(n.x+a.x)/2,y:(n.y+a.y)/2,t:n.t},o=this.resolveWidth(e[r-1],n);this.drawCurveSegment(t,s,n,h,i,o),s=h}const r=e[e.length-1],n=e[e.length-2],a=this.resolveWidth(n,r);this.drawCurveSegment(t,s,r,r,i,a)}redraw(){const t=this.canvas,e=t?.getContext("2d");if(!t||!e)return;const i=window.devicePixelRatio||1;this.resetCanvas(e,t.width/i,t.height/i);const s=this.getPenColor();for(const t of this.strokes)this.drawStroke(e,t,s)}getPoint(t){const e=t.currentTarget.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()}}appendPoint(t){const e=this.currentStroke,i=this.canvas?.getContext("2d");if(!e||!i)return;const s=e[e.length-1],r=t.x-s.x,n=t.y-s.y;if(Math.sqrt(r*r+n*n)<1.5)return;e.push(t);const a=this.getPenColor(),h=this.lastMid??s,o={x:(s.x+t.x)/2,y:(s.y+t.y)/2,t:t.t},l=this.resolveWidth(s,t);this.drawCurveSegment(i,h,s,o,a,l),this.lastMid=o}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.toDataURL()}}))}isEmpty(){return 0===this.strokes.length&&!this.backgroundImage}clear(){this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.backgroundImage=null,this.redraw(),this.updateState()}undo(){if(this.currentStroke)return;if(0===this.strokes.length)return;const t=this.strokes[this.strokes.length-1];this.strokes=this.strokes.slice(0,-1),this.redoStack=[...this.redoStack,t],this.redraw(),this.updateState(),this.emitChange()}redo(){if(this.currentStroke)return;if(0===this.redoStack.length)return;const t=this.redoStack[this.redoStack.length-1];this.redoStack=this.redoStack.slice(0,-1),this.strokes=[...this.strokes,t],this.redraw(),this.updateState(),this.emitChange()}toDataURL(t="image/png",e){return!this.canvas||this.isEmpty()?null:this.canvas.toDataURL(t,e)}fromDataURL(t){const e=new Image;e.crossOrigin="anonymous",e.onload=()=>{this.backgroundImage=e,this.strokes=[],this.redoStack=[],this.redraw(),this.updateState()},e.src=t}getCanvas(){return this.canvas}}customElements.get("db-signature")||customElements.define("db-signature",DbSignature);export{DbSignature};
@@ -3,6 +3,7 @@ declare class DbSpinner extends HTMLElement {
3
3
  private renderedType?;
4
4
  private graphicEl?;
5
5
  private labelEl?;
6
+ private unsubscribeLocale?;
6
7
  static get observedAttributes(): string[];
7
8
  get type(): string;
8
9
  set type(value: string);
@@ -17,6 +18,7 @@ declare class DbSpinner extends HTMLElement {
17
18
  get showLabel(): boolean;
18
19
  set showLabel(value: boolean);
19
20
  connectedCallback(): void;
21
+ disconnectedCallback(): void;
20
22
  attributeChangedCallback(): void;
21
23
  private render;
22
24
  private renderSpinner;
@@ -1 +1 @@
1
- import{SPINNER_TYPES as e,SPINNER_SIZES as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbSpinner extends HTMLElement{static get observedAttributes(){return["type","size","color","speed","label","show-label"]}get type(){return this.getAttribute("type")||"circular"}set type(e){this.setAttribute("type",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get color(){return this.getAttribute("color")||""}set color(e){e?this.setAttribute("color",e):this.removeAttribute("color")}get speed(){return Number(this.getAttribute("speed")||1)}set speed(e){this.setAttribute("speed",String(e))}get label(){return this.getAttribute("label")||"로딩 중..."}set label(e){this.setAttribute("label",e)}get showLabel(){return this.hasAttribute("show-label")}set showLabel(e){this.toggleAttribute("show-label",e)}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}render(){this.className=Array.from(this.classList).filter(e=>!e.startsWith("designbase-wc-spinner")).join(" "),this.classList.add("designbase-wc-spinner"),this.classList.add(`designbase-wc-spinner--${e.includes(this.type)?this.type:"circular"}`),this.classList.add(`designbase-wc-spinner--${s.includes(this.size)?this.size:"m"}`),this.setAttribute("role","status"),this.setAttribute("aria-live","polite"),this.setAttribute("aria-busy","true"),this.showLabel&&this.setAttribute("aria-label",this.label),this.style.setProperty("--spinner-speed",`${this.speed}s`),this.color?this.style.setProperty("--spinner-color",this.color):this.style.removeProperty("--spinner-color");const t=e.includes(this.type)?this.type:"circular";if(this.renderedType!==t||!this.graphicEl?.isConnected){const e=document.createElement("template");e.innerHTML=this.renderSpinner(),this.graphicEl=e.content.firstElementChild,this.renderedType=t,this.labelEl=void 0,this.replaceChildren(this.graphicEl)}Boolean(this.showLabel&&this.label)?(this.labelEl?.isConnected||(this.labelEl=document.createElement("span"),this.labelEl.className="designbase-wc-spinner__label",this.labelEl.setAttribute("aria-hidden","true"),this.append(this.labelEl)),this.labelEl.textContent=this.label):(this.labelEl?.remove(),this.labelEl=void 0)}renderSpinner(){switch(this.type){case"dots":return'<span class="designbase-wc-spinner__dots" aria-hidden="true"><span class="designbase-wc-spinner__dot"></span><span class="designbase-wc-spinner__dot"></span><span class="designbase-wc-spinner__dot"></span></span>';case"bars":return'<span class="designbase-wc-spinner__bars" aria-hidden="true"><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span></span>';case"pulse":return'<span class="designbase-wc-spinner__pulse" aria-hidden="true"></span>';case"ripple":return'<span class="designbase-wc-spinner__ripple" aria-hidden="true"><span class="designbase-wc-spinner__ripple-circle"></span><span class="designbase-wc-spinner__ripple-circle"></span></span>';default:return'<svg class="designbase-wc-spinner__circular" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle class="designbase-wc-spinner__circular-track" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"></circle><circle class="designbase-wc-spinner__circular-indicator" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"></circle></svg>'}}escape(e){return e.replace(/[&<>"']/g,e=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[e]||e))}}customElements.get("db-spinner")||customElements.define("db-spinner",DbSpinner);export{DbSpinner};
1
+ import{dbText as e,subscribeDbLocale as s}from"../core/i18n.js";import{SPINNER_TYPES as t,SPINNER_SIZES as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbSpinner extends HTMLElement{static get observedAttributes(){return["type","size","color","speed","label","show-label"]}get type(){return this.getAttribute("type")||"circular"}set type(e){this.setAttribute("type",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get color(){return this.getAttribute("color")||""}set color(e){e?this.setAttribute("color",e):this.removeAttribute("color")}get speed(){return Number(this.getAttribute("speed")||1)}set speed(e){this.setAttribute("speed",String(e))}get label(){return this.getAttribute("label")||e("로딩 중...")}set label(e){this.setAttribute("label",e)}get showLabel(){return this.hasAttribute("show-label")}set showLabel(e){this.toggleAttribute("show-label",e)}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=s(()=>this.render()),this.render()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(){this.render()}render(){this.className=Array.from(this.classList).filter(e=>!e.startsWith("designbase-wc-spinner")).join(" "),this.classList.add("designbase-wc-spinner"),this.classList.add(`designbase-wc-spinner--${t.includes(this.type)?this.type:"circular"}`),this.classList.add(`designbase-wc-spinner--${i.includes(this.size)?this.size:"m"}`),this.setAttribute("role","status"),this.setAttribute("aria-live","polite"),this.setAttribute("aria-busy","true"),this.showLabel&&this.setAttribute("aria-label",this.label),this.style.setProperty("--spinner-speed",`${this.speed}s`),this.color?this.style.setProperty("--spinner-color",this.color):this.style.removeProperty("--spinner-color");const e=t.includes(this.type)?this.type:"circular";if(this.renderedType!==e||!this.graphicEl?.isConnected){const s=document.createElement("template");s.innerHTML=this.renderSpinner(),this.graphicEl=s.content.firstElementChild,this.renderedType=e,this.labelEl=void 0,this.replaceChildren(this.graphicEl)}Boolean(this.showLabel&&this.label)?(this.labelEl?.isConnected||(this.labelEl=document.createElement("span"),this.labelEl.className="designbase-wc-spinner__label",this.labelEl.setAttribute("aria-hidden","true"),this.append(this.labelEl)),this.labelEl.textContent=this.label):(this.labelEl?.remove(),this.labelEl=void 0)}renderSpinner(){switch(this.type){case"dots":return'<span class="designbase-wc-spinner__dots" aria-hidden="true"><span class="designbase-wc-spinner__dot"></span><span class="designbase-wc-spinner__dot"></span><span class="designbase-wc-spinner__dot"></span></span>';case"bars":return'<span class="designbase-wc-spinner__bars" aria-hidden="true"><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span><span class="designbase-wc-spinner__bar"></span></span>';case"pulse":return'<span class="designbase-wc-spinner__pulse" aria-hidden="true"></span>';case"ripple":return'<span class="designbase-wc-spinner__ripple" aria-hidden="true"><span class="designbase-wc-spinner__ripple-circle"></span><span class="designbase-wc-spinner__ripple-circle"></span></span>';default:return'<svg class="designbase-wc-spinner__circular" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle class="designbase-wc-spinner__circular-track" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"></circle><circle class="designbase-wc-spinner__circular-indicator" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"></circle></svg>'}}escape(e){return e.replace(/[&<>"']/g,e=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"}[e]||e))}}customElements.get("db-spinner")||customElements.define("db-spinner",DbSpinner);export{DbSpinner};
@@ -1,4 +1,5 @@
1
1
  declare class DbStepper extends HTMLElement {
2
+ private unsubscribeLocale?;
2
3
  static get observedAttributes(): string[];
3
4
  private decrementBtn;
4
5
  private incrementBtn;
@@ -11,6 +12,7 @@ declare class DbStepper extends HTMLElement {
11
12
  private boundInputPaste;
12
13
  private boundInputBlur;
13
14
  connectedCallback(): void;
15
+ disconnectedCallback(): void;
14
16
  attributeChangedCallback(name: string): void;
15
17
  get value(): number;
16
18
  set value(value: number);
@@ -1 +1 @@
1
- import{dbText as t,dbFormat as e}from"../core/i18n.js";const i="designbase-wc-stepper",n=["s","m","l"],s={display:"block",width:"100%",minWidth:"0",height:"auto",padding:"0",margin:"0",border:"0",background:"transparent",color:"inherit",fontFamily:"inherit",fontWeight:"600",lineHeight:"1",textAlign:"center",outline:"none",boxShadow:"none",boxSizing:"border-box",appearance:"none"};class DbStepper extends HTMLElement{constructor(){super(...arguments),this.decrementBtn=null,this.incrementBtn=null,this.valueWrapEl=null,this.valueTextEl=null,this.valueInputEl=null,this.descriptionEl=null,this.boundInputKeyDown=t=>this.handleInputKeyDown(t),this.boundInputInput=()=>this.handleInputInput(),this.boundInputPaste=t=>this.handleInputPaste(t),this.boundInputBlur=()=>this.commitInputValue()}static get observedAttributes(){return["value","min","max","step","size","editable","full-width","disabled","readonly"]}connectedCallback(){this.querySelector(`.${i}__button`)||this.build(),this.syncFromAttributes()}attributeChangedCallback(t){this.decrementBtn&&this.syncFromAttributes()}get value(){return Number(this.getAttribute("value")||0)}set value(t){this.setAttribute("value",String(t))}build(){this.decrementBtn=document.createElement("button"),this.decrementBtn.type="button",this.decrementBtn.className=`${i}__button ${i}__button--decrement`,this.decrementBtn.setAttribute("aria-label",t("감소")),this.decrementBtn.innerHTML='<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/></svg>',this.valueWrapEl=document.createElement("div"),this.valueWrapEl.className=`${i}__value`,this.valueTextEl=document.createElement("span"),this.valueTextEl.className=`${i}__value-text`,this.valueWrapEl.appendChild(this.valueTextEl),this.incrementBtn=document.createElement("button"),this.incrementBtn.type="button",this.incrementBtn.className=`${i}__button ${i}__button--increment`,this.incrementBtn.setAttribute("aria-label",t("증가")),this.incrementBtn.innerHTML='<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>',this.descriptionEl=document.createElement("div"),this.descriptionEl.id="stepper-description",this.descriptionEl.className="sr-only",this.decrementBtn.addEventListener("click",()=>this.change(this.value-this.getStep())),this.incrementBtn.addEventListener("click",()=>this.change(this.value+this.getStep())),this.append(this.decrementBtn,this.valueWrapEl,this.incrementBtn,this.descriptionEl)}isEditable(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")&&"false"!==this.getAttribute("editable")}syncFromAttributes(){const t=this.getAttribute("size")||"m",s=this.hasAttribute("disabled"),l=this.hasAttribute("readonly"),u=this.getMin(),a=this.getMax(),r=this.getStep(),h=this.clamp(this.snapToStep(this.value));if(this.getAttribute("value")!==String(h)&&this.setAttribute("value",String(h)),this.className=[i,`${i}--${n.includes(t)?t:"m"}`,this.hasAttribute("full-width")&&`${i}--full-width`,this.isEditable()&&`${i}--editable`,s&&`${i}--disabled`,l&&`${i}--readonly`].filter(Boolean).join(" "),this.syncValueField(h),this.descriptionEl){const t=this.isEditable()?"값을 직접 입력할 수 있습니다. ":"";this.descriptionEl.textContent=e("{0}숫자 조정기. +/- 버튼으로 값을 조정할 수 있습니다. 현재 값: {1}, 최소값: {2}, 최대값: {3}, 단계: {4}",[t,h,u,a,r])}this.decrementBtn?.setAttribute("aria-describedby","stepper-description"),this.incrementBtn?.setAttribute("aria-describedby","stepper-description"),this.updateButtons()}applyValueInputAppearance(){this.valueInputEl&&(Object.assign(this.valueInputEl.style,s),this.valueInputEl.style.setProperty("-webkit-appearance","none"),this.valueInputEl.style.setProperty("-moz-appearance","textfield"))}syncValueField(e){if(this.valueWrapEl){if(this.isEditable())return this.valueInputEl||(this.valueInputEl=document.createElement("input"),this.valueInputEl.className=`${i}__value-input`,this.valueInputEl.type="text",this.valueInputEl.setAttribute("inputmode",this.allowsDecimal()?"decimal":"numeric"),this.valueInputEl.setAttribute("pattern",this.buildInputPattern()),this.valueInputEl.setAttribute("aria-label",t("값 입력")),this.valueInputEl.autocomplete="off",this.valueInputEl.spellcheck=!1,this.valueInputEl.addEventListener("keydown",this.boundInputKeyDown),this.valueInputEl.addEventListener("input",this.boundInputInput),this.valueInputEl.addEventListener("paste",this.boundInputPaste),this.valueInputEl.addEventListener("blur",this.boundInputBlur),this.applyValueInputAppearance()),this.applyValueInputAppearance(),this.valueInputEl.setAttribute("inputmode",this.allowsDecimal()?"decimal":"numeric"),this.valueInputEl.setAttribute("pattern",this.buildInputPattern()),this.valueInputEl.setAttribute("aria-valuemin",String(this.getMin())),this.valueInputEl.setAttribute("aria-valuemax",String(this.getMax())),this.valueInputEl.disabled=!1,document.activeElement!==this.valueInputEl&&(this.valueInputEl.value=String(e)),this.valueTextEl?.remove(),void(this.valueWrapEl.contains(this.valueInputEl)||this.valueWrapEl.appendChild(this.valueInputEl));this.valueInputEl&&(this.valueInputEl.removeEventListener("keydown",this.boundInputKeyDown),this.valueInputEl.removeEventListener("input",this.boundInputInput),this.valueInputEl.removeEventListener("paste",this.boundInputPaste),this.valueInputEl.removeEventListener("blur",this.boundInputBlur),this.valueInputEl.remove(),this.valueInputEl=null),this.valueTextEl||(this.valueTextEl=document.createElement("span"),this.valueTextEl.className=`${i}__value-text`),this.valueTextEl.textContent=String(e),this.valueWrapEl.contains(this.valueTextEl)||this.valueWrapEl.appendChild(this.valueTextEl)}}allowsNegative(){return this.getMin()<0}allowsDecimal(){const t=this.getStep();return!Number.isInteger(t)}buildInputPattern(){return`^${this.allowsNegative()?"-?":""}\\d*${this.allowsDecimal()?"(\\.\\d*)?":""}$`}sanitizeInputString(t){let e="",i=!1,n=!1;for(let s=0;s<t.length;s++){const l=t[s];"-"!==l||!this.allowsNegative()||0!==e.length||i?"."!==l||!this.allowsDecimal()||n?/\d/.test(l)&&(e+=l):(e+=l,n=!0):(e+=l,i=!0)}return e}parseInputValue(t){const e=t.trim();if(""===e||"-"===e||"."===e)return null;const i=Number(e);return Number.isFinite(i)?i:null}enforceInputBounds(t,e={}){const i=this.sanitizeInputString(t),n=this.parseInputValue(i);if(null===n)return i;const s=this.getMin(),l=this.getMax();return n>l?String(l):e.clampMin&&n<s?String(s):i}handleInputKeyDown(t){if(!["Backspace","Delete","Tab","Escape","ArrowLeft","ArrowRight","Home","End"].includes(t.key)){if("Enter"===t.key)return t.preventDefault(),this.commitInputValue(),void this.valueInputEl?.blur();if("-"===t.key&&this.allowsNegative()){const t=this.valueInputEl;if(t&&0===t.selectionStart&&0===t.selectionEnd&&!t.value.includes("-"))return}"."===t.key&&this.allowsDecimal()&&!this.valueInputEl?.value.includes(".")||/^\d$/.test(t.key)||t.preventDefault()}}handleInputInput(){if(!this.valueInputEl)return;const t=this.enforceInputBounds(this.valueInputEl.value);this.valueInputEl.value!==t&&(this.valueInputEl.value=t)}handleInputPaste(t){if(t.preventDefault(),!this.valueInputEl)return;const e=t.clipboardData?.getData("text")??"",i=this.enforceInputBounds(this.sanitizeInputString(this.valueInputEl.value+e));this.valueInputEl.value=i,this.handleInputInput()}commitInputValue(){if(!this.valueInputEl||!this.isEditable())return;const t=this.valueInputEl.value.trim();if(""===t||"-"===t||"."===t)return void(this.valueInputEl.value=String(this.value));const e=this.parseInputValue(t);if(null===e)return void(this.valueInputEl.value=String(this.value));const i=this.snapToStep(e);this.valueInputEl.value=String(i),this.change(i)}getMin(){return Number(this.getAttribute("min")??0)}getMax(){return Number(this.getAttribute("max")??100)}getStep(){return Number(this.getAttribute("step")??1)}snapToStep(t){const e=this.getStep(),i=Math.round(t/e)*e;return this.clamp(i)}clamp(t){return Math.max(this.getMin(),Math.min(this.getMax(),t))}updateButtons(){const t=this.getMin(),e=this.getMax(),n=this.hasAttribute("disabled"),s=this.hasAttribute("readonly"),l=this.value,u=l<=t,a=l>=e;if(this.decrementBtn){const t=n||s||u;this.decrementBtn.disabled=t,this.decrementBtn.classList.toggle(`${i}__button--disabled`,t)}if(this.incrementBtn){const t=n||s||a;this.incrementBtn.disabled=t,this.incrementBtn.classList.toggle(`${i}__button--disabled`,t)}}change(t){if(this.hasAttribute("disabled")||this.hasAttribute("readonly"))return;const i=this.getMin(),n=this.getMax(),s=this.clamp(this.snapToStep(t)),l=this.value;if(s!==l){if(this.setAttribute("value",String(s)),this.valueTextEl&&(this.valueTextEl.textContent=String(s)),this.valueInputEl&&(this.valueInputEl.value=String(s)),this.updateButtons(),this.descriptionEl){const t=this.getStep(),l=this.isEditable()?"값을 직접 입력할 수 있습니다. ":"";this.descriptionEl.textContent=e("{0}숫자 조정기. +/- 버튼으로 값을 조정할 수 있습니다. 현재 값: {1}, 최소값: {2}, 최대값: {3}, 단계: {4}",[l,s,i,n,t])}this.dispatchEvent(new CustomEvent("db-change",{detail:{value:s,minReached:s<=i,maxReached:s>=n},bubbles:!0,composed:!0})),s<=i&&l>i&&this.dispatchEvent(new CustomEvent("db-min-reached",{bubbles:!0,composed:!0,detail:{value:s}})),s>=n&&l<n&&this.dispatchEvent(new CustomEvent("db-max-reached",{bubbles:!0,composed:!0,detail:{value:s}}))}else this.valueInputEl&&(this.valueInputEl.value=String(s))}}customElements.get("db-stepper")||customElements.define("db-stepper",DbStepper);export{DbStepper};
1
+ import{subscribeDbLocale as t,dbText as e,dbFormat as i}from"../core/i18n.js";const n="designbase-wc-stepper",s=["s","m","l"],l={display:"block",width:"100%",minWidth:"0",height:"auto",padding:"0",margin:"0",border:"0",background:"transparent",color:"inherit",fontFamily:"inherit",fontWeight:"600",lineHeight:"1",textAlign:"center",outline:"none",boxShadow:"none",boxSizing:"border-box",appearance:"none"};class DbStepper extends HTMLElement{constructor(){super(...arguments),this.decrementBtn=null,this.incrementBtn=null,this.valueWrapEl=null,this.valueTextEl=null,this.valueInputEl=null,this.descriptionEl=null,this.boundInputKeyDown=t=>this.handleInputKeyDown(t),this.boundInputInput=()=>this.handleInputInput(),this.boundInputPaste=t=>this.handleInputPaste(t),this.boundInputBlur=()=>this.commitInputValue()}static get observedAttributes(){return["value","min","max","step","size","editable","full-width","disabled","readonly"]}connectedCallback(){this.querySelector(`.${n}__button`)||this.build(),this.syncFromAttributes(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>{this.decrementBtn?.setAttribute("aria-label",e("감소")),this.incrementBtn?.setAttribute("aria-label",e("증가")),this.valueInputEl?.setAttribute("aria-label",e("값 입력")),this.syncFromAttributes()})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(t){this.decrementBtn&&this.syncFromAttributes()}get value(){return Number(this.getAttribute("value")||0)}set value(t){this.setAttribute("value",String(t))}build(){this.decrementBtn=document.createElement("button"),this.decrementBtn.type="button",this.decrementBtn.className=`${n}__button ${n}__button--decrement`,this.decrementBtn.setAttribute("aria-label",e("감소")),this.decrementBtn.innerHTML='<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/></svg>',this.valueWrapEl=document.createElement("div"),this.valueWrapEl.className=`${n}__value`,this.valueTextEl=document.createElement("span"),this.valueTextEl.className=`${n}__value-text`,this.valueWrapEl.appendChild(this.valueTextEl),this.incrementBtn=document.createElement("button"),this.incrementBtn.type="button",this.incrementBtn.className=`${n}__button ${n}__button--increment`,this.incrementBtn.setAttribute("aria-label",e("증가")),this.incrementBtn.innerHTML='<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>',this.descriptionEl=document.createElement("div"),this.descriptionEl.id="stepper-description",this.descriptionEl.className="sr-only",this.decrementBtn.addEventListener("click",()=>this.change(this.value-this.getStep())),this.incrementBtn.addEventListener("click",()=>this.change(this.value+this.getStep())),this.append(this.decrementBtn,this.valueWrapEl,this.incrementBtn,this.descriptionEl)}isEditable(){return!this.hasAttribute("disabled")&&!this.hasAttribute("readonly")&&"false"!==this.getAttribute("editable")}syncFromAttributes(){const t=this.getAttribute("size")||"m",l=this.hasAttribute("disabled"),u=this.hasAttribute("readonly"),a=this.getMin(),r=this.getMax(),h=this.getStep(),p=this.clamp(this.snapToStep(this.value));if(this.getAttribute("value")!==String(p)&&this.setAttribute("value",String(p)),this.className=[n,`${n}--${s.includes(t)?t:"m"}`,this.hasAttribute("full-width")&&`${n}--full-width`,this.isEditable()&&`${n}--editable`,l&&`${n}--disabled`,u&&`${n}--readonly`].filter(Boolean).join(" "),this.syncValueField(p),this.descriptionEl){const t=this.isEditable()?`${e("값을 직접 입력할 수 있습니다.")} `:"";this.descriptionEl.textContent=i("{0}숫자 조정기. +/- 버튼으로 값을 조정할 수 있습니다. 현재 값: {1}, 최소값: {2}, 최대값: {3}, 단계: {4}",[t,p,a,r,h])}this.decrementBtn?.setAttribute("aria-describedby","stepper-description"),this.incrementBtn?.setAttribute("aria-describedby","stepper-description"),this.updateButtons()}applyValueInputAppearance(){this.valueInputEl&&(Object.assign(this.valueInputEl.style,l),this.valueInputEl.style.setProperty("-webkit-appearance","none"),this.valueInputEl.style.setProperty("-moz-appearance","textfield"))}syncValueField(t){if(this.valueWrapEl){if(this.isEditable())return this.valueInputEl||(this.valueInputEl=document.createElement("input"),this.valueInputEl.className=`${n}__value-input`,this.valueInputEl.type="text",this.valueInputEl.setAttribute("inputmode",this.allowsDecimal()?"decimal":"numeric"),this.valueInputEl.setAttribute("pattern",this.buildInputPattern()),this.valueInputEl.setAttribute("aria-label",e("값 입력")),this.valueInputEl.autocomplete="off",this.valueInputEl.spellcheck=!1,this.valueInputEl.addEventListener("keydown",this.boundInputKeyDown),this.valueInputEl.addEventListener("input",this.boundInputInput),this.valueInputEl.addEventListener("paste",this.boundInputPaste),this.valueInputEl.addEventListener("blur",this.boundInputBlur),this.applyValueInputAppearance()),this.applyValueInputAppearance(),this.valueInputEl.setAttribute("inputmode",this.allowsDecimal()?"decimal":"numeric"),this.valueInputEl.setAttribute("pattern",this.buildInputPattern()),this.valueInputEl.setAttribute("aria-valuemin",String(this.getMin())),this.valueInputEl.setAttribute("aria-valuemax",String(this.getMax())),this.valueInputEl.disabled=!1,document.activeElement!==this.valueInputEl&&(this.valueInputEl.value=String(t)),this.valueTextEl?.remove(),void(this.valueWrapEl.contains(this.valueInputEl)||this.valueWrapEl.appendChild(this.valueInputEl));this.valueInputEl&&(this.valueInputEl.removeEventListener("keydown",this.boundInputKeyDown),this.valueInputEl.removeEventListener("input",this.boundInputInput),this.valueInputEl.removeEventListener("paste",this.boundInputPaste),this.valueInputEl.removeEventListener("blur",this.boundInputBlur),this.valueInputEl.remove(),this.valueInputEl=null),this.valueTextEl||(this.valueTextEl=document.createElement("span"),this.valueTextEl.className=`${n}__value-text`),this.valueTextEl.textContent=String(t),this.valueWrapEl.contains(this.valueTextEl)||this.valueWrapEl.appendChild(this.valueTextEl)}}allowsNegative(){return this.getMin()<0}allowsDecimal(){const t=this.getStep();return!Number.isInteger(t)}buildInputPattern(){return`^${this.allowsNegative()?"-?":""}\\d*${this.allowsDecimal()?"(\\.\\d*)?":""}$`}sanitizeInputString(t){let e="",i=!1,n=!1;for(let s=0;s<t.length;s++){const l=t[s];"-"!==l||!this.allowsNegative()||0!==e.length||i?"."!==l||!this.allowsDecimal()||n?/\d/.test(l)&&(e+=l):(e+=l,n=!0):(e+=l,i=!0)}return e}parseInputValue(t){const e=t.trim();if(""===e||"-"===e||"."===e)return null;const i=Number(e);return Number.isFinite(i)?i:null}enforceInputBounds(t,e={}){const i=this.sanitizeInputString(t),n=this.parseInputValue(i);if(null===n)return i;const s=this.getMin(),l=this.getMax();return n>l?String(l):e.clampMin&&n<s?String(s):i}handleInputKeyDown(t){if(!["Backspace","Delete","Tab","Escape","ArrowLeft","ArrowRight","Home","End"].includes(t.key)){if("Enter"===t.key)return t.preventDefault(),this.commitInputValue(),void this.valueInputEl?.blur();if("-"===t.key&&this.allowsNegative()){const t=this.valueInputEl;if(t&&0===t.selectionStart&&0===t.selectionEnd&&!t.value.includes("-"))return}"."===t.key&&this.allowsDecimal()&&!this.valueInputEl?.value.includes(".")||/^\d$/.test(t.key)||t.preventDefault()}}handleInputInput(){if(!this.valueInputEl)return;const t=this.enforceInputBounds(this.valueInputEl.value);this.valueInputEl.value!==t&&(this.valueInputEl.value=t)}handleInputPaste(t){if(t.preventDefault(),!this.valueInputEl)return;const e=t.clipboardData?.getData("text")??"",i=this.enforceInputBounds(this.sanitizeInputString(this.valueInputEl.value+e));this.valueInputEl.value=i,this.handleInputInput()}commitInputValue(){if(!this.valueInputEl||!this.isEditable())return;const t=this.valueInputEl.value.trim();if(""===t||"-"===t||"."===t)return void(this.valueInputEl.value=String(this.value));const e=this.parseInputValue(t);if(null===e)return void(this.valueInputEl.value=String(this.value));const i=this.snapToStep(e);this.valueInputEl.value=String(i),this.change(i)}getMin(){return Number(this.getAttribute("min")??0)}getMax(){return Number(this.getAttribute("max")??100)}getStep(){return Number(this.getAttribute("step")??1)}snapToStep(t){const e=this.getStep(),i=Math.round(t/e)*e;return this.clamp(i)}clamp(t){return Math.max(this.getMin(),Math.min(this.getMax(),t))}updateButtons(){const t=this.getMin(),e=this.getMax(),i=this.hasAttribute("disabled"),s=this.hasAttribute("readonly"),l=this.value,u=l<=t,a=l>=e;if(this.decrementBtn){const t=i||s||u;this.decrementBtn.disabled=t,this.decrementBtn.classList.toggle(`${n}__button--disabled`,t)}if(this.incrementBtn){const t=i||s||a;this.incrementBtn.disabled=t,this.incrementBtn.classList.toggle(`${n}__button--disabled`,t)}}change(t){if(this.hasAttribute("disabled")||this.hasAttribute("readonly"))return;const n=this.getMin(),s=this.getMax(),l=this.clamp(this.snapToStep(t)),u=this.value;if(l!==u){if(this.setAttribute("value",String(l)),this.valueTextEl&&(this.valueTextEl.textContent=String(l)),this.valueInputEl&&(this.valueInputEl.value=String(l)),this.updateButtons(),this.descriptionEl){const t=this.getStep(),u=this.isEditable()?`${e("값을 직접 입력할 수 있습니다.")} `:"";this.descriptionEl.textContent=i("{0}숫자 조정기. +/- 버튼으로 값을 조정할 수 있습니다. 현재 값: {1}, 최소값: {2}, 최대값: {3}, 단계: {4}",[u,l,n,s,t])}this.dispatchEvent(new CustomEvent("db-change",{detail:{value:l,minReached:l<=n,maxReached:l>=s},bubbles:!0,composed:!0})),l<=n&&u>n&&this.dispatchEvent(new CustomEvent("db-min-reached",{bubbles:!0,composed:!0,detail:{value:l}})),l>=s&&u<s&&this.dispatchEvent(new CustomEvent("db-max-reached",{bubbles:!0,composed:!0,detail:{value:l}}))}else this.valueInputEl&&(this.valueInputEl.value=String(l))}}customElements.get("db-stepper")||customElements.define("db-stepper",DbStepper);export{DbStepper};
@@ -7,6 +7,7 @@ interface TableColumn {
7
7
  }
8
8
  type RowData = Record<string, unknown>;
9
9
  declare class DbTable extends HTMLElement {
10
+ private unsubscribeLocale?;
10
11
  static get observedAttributes(): string[];
11
12
  private internalSelectedRows;
12
13
  private internalSortColumn;
@@ -17,6 +18,7 @@ declare class DbTable extends HTMLElement {
17
18
  get data(): RowData[];
18
19
  set data(value: RowData[] | string);
19
20
  connectedCallback(): void;
21
+ disconnectedCallback(): void;
20
22
  attributeChangedCallback(name: string): void;
21
23
  private syncSelectedRowsFromAttribute;
22
24
  private syncSortFromAttributes;