@designbasekorea/ui-wc 0.9.4 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE-WORLD-MAP.md +10 -0
  3. package/README.md +60 -0
  4. package/dist/esm/components/db-accordion.d.ts +22 -10
  5. package/dist/esm/components/db-accordion.js +1 -1
  6. package/dist/esm/components/db-achievement-list.d.ts +2 -0
  7. package/dist/esm/components/db-achievement-list.js +1 -1
  8. package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
  9. package/dist/esm/components/db-activity-heatmap.js +1 -1
  10. package/dist/esm/components/db-ad-banner.d.ts +2 -0
  11. package/dist/esm/components/db-ad-banner.js +1 -1
  12. package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
  13. package/dist/esm/components/db-ai-chat-list.js +1 -1
  14. package/dist/esm/components/db-ai-chat.d.ts +2 -0
  15. package/dist/esm/components/db-ai-chat.js +1 -1
  16. package/dist/esm/components/db-ai-file-tree.js +1 -1
  17. package/dist/esm/components/db-alert.d.ts +1 -0
  18. package/dist/esm/components/db-alert.js +1 -1
  19. package/dist/esm/components/db-audio-player.d.ts +2 -0
  20. package/dist/esm/components/db-audio-player.js +1 -1
  21. package/dist/esm/components/db-avatar.d.ts +1 -0
  22. package/dist/esm/components/db-avatar.js +1 -1
  23. package/dist/esm/components/db-banner.d.ts +2 -0
  24. package/dist/esm/components/db-banner.js +1 -1
  25. package/dist/esm/components/db-button.d.ts +40 -2
  26. package/dist/esm/components/db-button.js +1 -1
  27. package/dist/esm/components/db-calendar.d.ts +5 -0
  28. package/dist/esm/components/db-calendar.js +1 -1
  29. package/dist/esm/components/db-card.d.ts +1 -0
  30. package/dist/esm/components/db-card.js +1 -1
  31. package/dist/esm/components/db-chat-composer.d.ts +3 -0
  32. package/dist/esm/components/db-chat-composer.js +1 -1
  33. package/dist/esm/components/db-chat-message.d.ts +2 -0
  34. package/dist/esm/components/db-chat-message.js +1 -1
  35. package/dist/esm/components/db-chat-orb.d.ts +13 -0
  36. package/dist/esm/components/db-chat-orb.js +1 -1
  37. package/dist/esm/components/db-chat-room.d.ts +1 -0
  38. package/dist/esm/components/db-chat-room.js +1 -1
  39. package/dist/esm/components/db-chat-typing.d.ts +2 -0
  40. package/dist/esm/components/db-chat-typing.js +1 -1
  41. package/dist/esm/components/db-chat-widget.d.ts +9 -0
  42. package/dist/esm/components/db-chat-widget.js +1 -1
  43. package/dist/esm/components/db-checkbox.d.ts +3 -0
  44. package/dist/esm/components/db-checkbox.js +1 -1
  45. package/dist/esm/components/db-chip.d.ts +2 -0
  46. package/dist/esm/components/db-chip.js +1 -1
  47. package/dist/esm/components/db-code-block.d.ts +1 -0
  48. package/dist/esm/components/db-code-block.js +1 -1
  49. package/dist/esm/components/db-color-picker.d.ts +4 -0
  50. package/dist/esm/components/db-color-picker.js +1 -1
  51. package/dist/esm/components/db-color-swatch.d.ts +3 -0
  52. package/dist/esm/components/db-color-swatch.js +1 -1
  53. package/dist/esm/components/db-confetti.d.ts +11 -5
  54. package/dist/esm/components/db-confetti.js +1 -1
  55. package/dist/esm/components/db-cookie-banner.d.ts +3 -0
  56. package/dist/esm/components/db-cookie-banner.js +1 -1
  57. package/dist/esm/components/db-countdown.d.ts +2 -1
  58. package/dist/esm/components/db-countdown.js +1 -1
  59. package/dist/esm/components/db-date-picker.d.ts +3 -0
  60. package/dist/esm/components/db-date-picker.js +1 -1
  61. package/dist/esm/components/db-dropdown.d.ts +1 -0
  62. package/dist/esm/components/db-dropdown.js +1 -1
  63. package/dist/esm/components/db-dropzone.d.ts +2 -0
  64. package/dist/esm/components/db-dropzone.js +1 -1
  65. package/dist/esm/components/db-email-verify.d.ts +37 -7
  66. package/dist/esm/components/db-email-verify.js +1 -1
  67. package/dist/esm/components/db-file-uploader.d.ts +2 -0
  68. package/dist/esm/components/db-file-uploader.js +1 -1
  69. package/dist/esm/components/db-floating-action-button.d.ts +1 -1
  70. package/dist/esm/components/db-floating-action-button.js +1 -1
  71. package/dist/esm/components/db-form.d.ts +2 -0
  72. package/dist/esm/components/db-form.js +1 -1
  73. package/dist/esm/components/db-gantt.d.ts +2 -0
  74. package/dist/esm/components/db-gantt.js +1 -1
  75. package/dist/esm/components/db-image-list.d.ts +3 -0
  76. package/dist/esm/components/db-image-list.js +1 -1
  77. package/dist/esm/components/db-image.d.ts +1 -0
  78. package/dist/esm/components/db-image.js +1 -1
  79. package/dist/esm/components/db-input-group.d.ts +30 -0
  80. package/dist/esm/components/db-input-group.js +1 -0
  81. package/dist/esm/components/db-input.d.ts +9 -1
  82. package/dist/esm/components/db-input.js +1 -1
  83. package/dist/esm/components/db-kanban.d.ts +3 -0
  84. package/dist/esm/components/db-kanban.js +1 -1
  85. package/dist/esm/components/db-lightbox.d.ts +2 -0
  86. package/dist/esm/components/db-lightbox.js +1 -1
  87. package/dist/esm/components/db-list.d.ts +2 -0
  88. package/dist/esm/components/db-list.js +1 -1
  89. package/dist/esm/components/db-markdown-editor.d.ts +2 -0
  90. package/dist/esm/components/db-markdown-editor.js +1 -1
  91. package/dist/esm/components/db-menu-item.js +1 -1
  92. package/dist/esm/components/db-navbar.d.ts +6 -0
  93. package/dist/esm/components/db-navbar.js +1 -1
  94. package/dist/esm/components/db-node.d.ts +1 -0
  95. package/dist/esm/components/db-node.js +1 -1
  96. package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
  97. package/dist/esm/components/db-onboarding-modal.js +1 -1
  98. package/dist/esm/components/db-otp-input.d.ts +4 -1
  99. package/dist/esm/components/db-otp-input.js +1 -1
  100. package/dist/esm/components/db-page-header.d.ts +11 -0
  101. package/dist/esm/components/db-page-header.js +1 -1
  102. package/dist/esm/components/db-phone-verify.d.ts +33 -11
  103. package/dist/esm/components/db-phone-verify.js +1 -1
  104. package/dist/esm/components/db-popover.d.ts +1 -0
  105. package/dist/esm/components/db-popover.js +1 -1
  106. package/dist/esm/components/db-progress-step.d.ts +2 -0
  107. package/dist/esm/components/db-progress-step.js +1 -1
  108. package/dist/esm/components/db-radio.d.ts +3 -0
  109. package/dist/esm/components/db-radio.js +1 -1
  110. package/dist/esm/components/db-range-slider.d.ts +36 -7
  111. package/dist/esm/components/db-range-slider.js +1 -1
  112. package/dist/esm/components/db-rating.d.ts +1 -0
  113. package/dist/esm/components/db-rating.js +1 -1
  114. package/dist/esm/components/db-search-bar.d.ts +2 -0
  115. package/dist/esm/components/db-search-bar.js +1 -1
  116. package/dist/esm/components/db-section-logo-cloud.js +1 -1
  117. package/dist/esm/components/db-select.d.ts +35 -6
  118. package/dist/esm/components/db-select.js +1 -1
  119. package/dist/esm/components/db-share.d.ts +5 -0
  120. package/dist/esm/components/db-share.js +1 -1
  121. package/dist/esm/components/db-sidebar.d.ts +3 -0
  122. package/dist/esm/components/db-sidebar.js +1 -1
  123. package/dist/esm/components/db-signature.d.ts +2 -0
  124. package/dist/esm/components/db-signature.js +1 -1
  125. package/dist/esm/components/db-spinner.d.ts +2 -0
  126. package/dist/esm/components/db-spinner.js +1 -1
  127. package/dist/esm/components/db-stepper.d.ts +2 -0
  128. package/dist/esm/components/db-stepper.js +1 -1
  129. package/dist/esm/components/db-table.d.ts +2 -0
  130. package/dist/esm/components/db-table.js +1 -1
  131. package/dist/esm/components/db-tabs.d.ts +37 -13
  132. package/dist/esm/components/db-tabs.js +1 -1
  133. package/dist/esm/components/db-textarea.d.ts +13 -1
  134. package/dist/esm/components/db-textarea.js +1 -1
  135. package/dist/esm/components/db-ticket.js +1 -1
  136. package/dist/esm/components/db-time-picker.d.ts +2 -0
  137. package/dist/esm/components/db-time-picker.js +1 -1
  138. package/dist/esm/components/db-timeline.d.ts +4 -0
  139. package/dist/esm/components/db-timeline.js +1 -1
  140. package/dist/esm/components/db-toast.d.ts +2 -0
  141. package/dist/esm/components/db-toast.js +1 -1
  142. package/dist/esm/components/db-toggle.d.ts +33 -4
  143. package/dist/esm/components/db-toggle.js +1 -1
  144. package/dist/esm/components/db-tool-layout.d.ts +92 -0
  145. package/dist/esm/components/db-tool-layout.js +1 -0
  146. package/dist/esm/components/db-tool-panel.d.ts +50 -0
  147. package/dist/esm/components/db-tool-panel.js +1 -0
  148. package/dist/esm/components/db-top-banner.d.ts +2 -0
  149. package/dist/esm/components/db-top-banner.js +1 -1
  150. package/dist/esm/components/db-two-factor.d.ts +35 -12
  151. package/dist/esm/components/db-two-factor.js +1 -1
  152. package/dist/esm/components/db-video-player.d.ts +3 -0
  153. package/dist/esm/components/db-video-player.js +1 -1
  154. package/dist/esm/components/db-world-map.d.ts +60 -0
  155. package/dist/esm/components/db-world-map.js +1 -0
  156. package/dist/esm/components/db-youtube-player.d.ts +2 -0
  157. package/dist/esm/components/db-youtube-player.js +1 -1
  158. package/dist/esm/components/db-zoom-control.d.ts +52 -0
  159. package/dist/esm/components/db-zoom-control.js +1 -0
  160. package/dist/esm/components/input-validation.js +1 -1
  161. package/dist/esm/components/paper-card.d.ts +2 -0
  162. package/dist/esm/components/paper-card.js +1 -1
  163. package/dist/esm/core/control-label.js +1 -0
  164. package/dist/esm/core/i18n-copy.js +1 -1
  165. package/dist/esm/core/i18n-en.js +1 -1
  166. package/dist/esm/core/i18n.d.ts +31 -1
  167. package/dist/esm/core/i18n.js +1 -1
  168. package/dist/esm/core/range-values.js +1 -0
  169. package/dist/esm/core/text-field-state.js +1 -0
  170. package/dist/esm/helpers/world-countries.js +1 -0
  171. package/dist/esm/helpers/world-land.js +1 -0
  172. package/dist/esm/index.d.ts +6 -1
  173. package/dist/esm/index.js +1 -1
  174. package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
  175. package/dist/index.cjs +1 -1
  176. package/dist/index.css +1 -1
  177. package/dist/index.d.ts +804 -83
  178. package/dist/index.esm.js +1 -1
  179. package/dist/react/index.cjs +1 -1
  180. package/dist/react/index.d.ts +6211 -648
  181. package/dist/react/index.esm.js +1 -1
  182. package/package.json +9 -4
@@ -1 +1 @@
1
- import{dbText as t}from"../core/i18n.js";import{setHostClasses as e}from"../core/host-class.js";import"./db-button.js";import{createDbIcon as s}from"./db-icons.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{ALERT_VARIANTS as n,ALERT_SIZES as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-alert";class DbAlert extends HTMLElement{constructor(){super(...arguments),this.renderedSlotted=!1}static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render(),this.observer??(this.observer=new MutationObserver(()=>this.adoptChildren())),this.observer.observe(this,{childList:!0}),this.slotObserver??(this.slotObserver=new MutationObserver(()=>{this.hasSlotted()!==this.renderedSlotted&&this.render()})),this.slotObserver.observe(this.getSlot(),{childList:!0,subtree:!0,characterData:!0})}disconnectedCallback(){this.observer?.disconnect(),this.slotObserver?.disconnect()}attributeChangedCallback(){this.isConnected&&this.render()}getSlot(){return this.slotEl||(this.slotEl=document.createElement("div"),this.slotEl.className=`${r}__slot`,this.slotEl.setAttribute("data-wc-internal","")),this.slotEl}moveChildrenToSlot(){const t=this.getSlot();let e=!1;for(const s of Array.from(this.childNodes))s instanceof Element&&s.hasAttribute("data-wc-internal")||s.nodeType!==Node.COMMENT_NODE&&(s.nodeType!==Node.TEXT_NODE||s.textContent?.trim()?(t.append(s),e=!0):s.remove());return e}adoptChildren(){this.moveChildrenToSlot()&&this.render()}hasSlotted(){const hasContent=t=>t.nodeType===Node.TEXT_NODE?Boolean(t.textContent?.trim()):t instanceof Element&&(!t.hasAttribute("data-db-children")||Array.from(t.childNodes).some(hasContent));return Boolean(this.slotEl&&Array.from(this.slotEl.childNodes).some(hasContent))}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const a=i(this.getAttribute("variant"),n,"default"),l=i(this.getAttribute("size"),o,"m"),c="false"!==this.getAttribute("show-icon"),d=this.hasAttribute("closable")&&"false"!==this.getAttribute("closable"),h=this.getAttribute("title")?.trim()||"",b=this.getAttribute("message")?.trim()||"",m=this.getAttribute("action-label"),u=this.getAttribute("action-variant")||"tertiary",p=this.parseActionButtons(),v=Boolean(b),E=Boolean(h);this.moveChildrenToSlot();const A=this.hasSlotted();this.renderedSlotted=A;const g=1===Number(E)+Number(v)+Number(A),f=p.length>0?p:m?[{label:m,variant:u}]:[];e(this,[r,`${r}--${a}`,`${r}--${l}`,c&&`${r}--with-icon`,d&&`${r}--closable`,g&&`${r}--text-single`,f.length>0&&`${r}--has-actions`]),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite");const N=this.getSlot(),_=document.createElement("div");if(_.className=`${r}__content`,_.setAttribute("data-wc-internal",""),c){const t=document.createElement("div");t.className=`${r}__icon`,t.append(s(this.getIconName(a),"s"===l?16:"l"===l?24:20)),_.append(t)}const C=document.createElement("div");if(C.className=`${r}__body`,E){const t=document.createElement("div");t.className=`${r}__title`,t.textContent=h,C.append(t)}if(v){const t=document.createElement("div");t.className=`${r}__message`,t.textContent=b,C.append(t)}if(A?C.append(N):N.remove(),_.append(C),f.length>0){const t=document.createElement("div");t.className=`${r}__actions`,t.setAttribute("data-wc-internal","");const e=document.createElement("div");e.className=`${r}__action-buttons`,f.forEach((t,s)=>{const i=document.createElement("db-button");i.setAttribute("variant",t.variant||"tertiary"),i.setAttribute("size",t.size||l),i.textContent=t.label,t.disabled&&i.setAttribute("disabled",""),i.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:s,label:t.label}}))}),e.append(i)}),t.append(e),_.append(t)}if(d){const e=document.createElement("button");e.type="button",e.className=`${r}__close`,e.setAttribute("aria-label",t("알림 닫기")),e.append(s("close",20)),e.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),_.append(e)}this.observer?.disconnect(),this.replaceChildren(_),this.isConnected&&this.observer?.observe(this,{childList:!0})}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
1
+ import{subscribeDbLocale as t,dbText as e}from"../core/i18n.js";import{setHostClasses as s}from"../core/host-class.js";import"./db-button.js";import{createDbIcon as i}from"./db-icons.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{ALERT_VARIANTS as o,ALERT_SIZES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a="designbase-wc-alert";class DbAlert extends HTMLElement{constructor(){super(...arguments),this.renderedSlotted=!1}static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.querySelector(`.${a}__close`)?.setAttribute("aria-label",e("알림 닫기"))),this.observer??(this.observer=new MutationObserver(()=>this.adoptChildren())),this.observer.observe(this,{childList:!0}),this.slotObserver??(this.slotObserver=new MutationObserver(()=>{this.hasSlotted()!==this.renderedSlotted&&this.render()})),this.slotObserver.observe(this.getSlot(),{childList:!0,subtree:!0,characterData:!0})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.observer?.disconnect(),this.slotObserver?.disconnect()}attributeChangedCallback(){this.isConnected&&this.render()}getSlot(){return this.slotEl||(this.slotEl=document.createElement("div"),this.slotEl.className=`${a}__slot`,this.slotEl.setAttribute("data-wc-internal","")),this.slotEl}moveChildrenToSlot(){const t=this.getSlot();let e=!1;for(const s of Array.from(this.childNodes))s instanceof Element&&s.hasAttribute("data-wc-internal")||s.nodeType!==Node.COMMENT_NODE&&(s.nodeType!==Node.TEXT_NODE||s.textContent?.trim()?(t.append(s),e=!0):s.remove());return e}adoptChildren(){this.moveChildrenToSlot()&&this.render()}hasSlotted(){const hasContent=t=>t.nodeType===Node.TEXT_NODE?Boolean(t.textContent?.trim()):t instanceof Element&&(!t.hasAttribute("data-db-children")||Array.from(t.childNodes).some(hasContent));return Boolean(this.slotEl&&Array.from(this.slotEl.childNodes).some(hasContent))}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const t=n(this.getAttribute("variant"),o,"default"),l=n(this.getAttribute("size"),r,"m"),c="false"!==this.getAttribute("show-icon"),d=this.hasAttribute("closable")&&"false"!==this.getAttribute("closable"),b=this.getAttribute("title")?.trim()||"",h=this.getAttribute("message")?.trim()||"",u=this.getAttribute("action-label"),m=this.getAttribute("action-variant")||"tertiary",p=this.parseActionButtons(),v=Boolean(h),E=Boolean(b);this.moveChildrenToSlot();const A=this.hasSlotted();this.renderedSlotted=A;const g=1===Number(E)+Number(v)+Number(A),f=p.length>0?p:u?[{label:u,variant:m}]:[];s(this,[a,`${a}--${t}`,`${a}--${l}`,c&&`${a}--with-icon`,d&&`${a}--closable`,g&&`${a}--text-single`,f.length>0&&`${a}--has-actions`]),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite");const N=this.getSlot(),_=document.createElement("div");if(_.className=`${a}__content`,_.setAttribute("data-wc-internal",""),c){const e=document.createElement("div");e.className=`${a}__icon`,e.append(i(this.getIconName(t),"s"===l?16:"l"===l?24:20)),_.append(e)}const C=document.createElement("div");if(C.className=`${a}__body`,E){const t=document.createElement("div");t.className=`${a}__title`,t.textContent=b,C.append(t)}if(v){const t=document.createElement("div");t.className=`${a}__message`,t.textContent=h,C.append(t)}if(A?C.append(N):N.remove(),_.append(C),f.length>0){const t=document.createElement("div");t.className=`${a}__actions`,t.setAttribute("data-wc-internal","");const e=document.createElement("div");e.className=`${a}__action-buttons`,f.forEach((t,s)=>{const i=document.createElement("db-button");i.setAttribute("variant",t.variant||"tertiary"),i.setAttribute("size",t.size||l),i.textContent=t.label,t.disabled&&i.setAttribute("disabled",""),i.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:s,label:t.label}}))}),e.append(i)}),t.append(e),_.append(t)}if(d){const t=document.createElement("button");t.type="button",t.className=`${a}__close`,t.setAttribute("aria-label",e("알림 닫기")),t.append(i("close",20)),t.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),_.append(t)}this.observer?.disconnect(),this.replaceChildren(_),this.isConnected&&this.observer?.observe(this,{childList:!0})}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
@@ -1,6 +1,7 @@
1
1
  declare class DbAudioPlayer extends HTMLElement {
2
2
  static get observedAttributes(): string[];
3
3
  private built;
4
+ private unsubscribeLocale?;
4
5
  private audioEl?;
5
6
  private progressEl?;
6
7
  private progressBarEl?;
@@ -75,6 +76,7 @@ declare class DbAudioPlayer extends HTMLElement {
75
76
  private rebuildControlButtons;
76
77
  private rebuildPlaylist;
77
78
  private updatePlaylistActive;
79
+ private refreshLocale;
78
80
  private updateUI;
79
81
  }
80
82
  declare global {
@@ -1 +1 @@
1
- import{dbText as t,t as e}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{AUDIO_PLAYER_SIZES as l,AUDIO_PLAYER_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const n="designbase-wc-audio-player";class DbAudioPlayer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.isPlaying=!1,this.isMuted=!1,this.volume=1,this.currentTime=0,this.duration=0,this.showSettingsMenu=!1,this.playbackRate=1,this.currentRepeatMode="none",this.isShuffle=!1,this.isLoading=!1,this.error=null,this.playlistIndex=0,this.shuffledPlaylist=[],this.boundKeyDown=t=>this.handleKeyDown(t)}static get observedAttributes(){return["src","title","artist","album","album-art","size","variant","theme","auto-play","loop","muted","show-controls","enable-keyboard","show-progress","show-time","show-volume","show-settings","playlist","current-index","playback-rates","default-playback-rate","repeat-mode","shuffle"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build(),this.bindAudioEvents()),this.syncFromAttributes(),this.updateUI(),this.getBool("enable-keyboard",!0)&&document.addEventListener("keydown",this.boundKeyDown)}disconnectedCallback(){document.removeEventListener("keydown",this.boundKeyDown)}attributeChangedCallback(t){if(this.built){if("current-index"===t)return this.playlistIndex=Number(this.getAttribute("current-index")||0),void this.loadCurrentTrack();"repeat-mode"===t&&(this.currentRepeatMode=this.getAttribute("repeat-mode")||"none"),"shuffle"===t&&(this.isShuffle=this.getBool("shuffle"),this.refreshShuffledPlaylist()),"default-playback-rate"===t&&(this.playbackRate=Number(this.getAttribute("default-playback-rate")||1),this.audioEl&&(this.audioEl.playbackRate=this.playbackRate)),this.updateUI()}}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const s=this.getAttribute(t);return""===s||"true"===s}getPlaylist(){try{const t=this.getAttribute("playlist"),e=t?JSON.parse(t):[];return Array.isArray(e)?e:[]}catch{return[]}}getPlaybackRates(){try{const t=this.getAttribute("playback-rates"),e=t?JSON.parse(t):[.5,.75,1,1.25,1.5,2];return Array.isArray(e)&&e.length>0?e:[.5,.75,1,1.25,1.5,2]}catch{return[.5,.75,1,1.25,1.5,2]}}getIconSize(){const t=i(this.getAttribute("size"),l,"m");return"s"===t?16:"l"===t?24:"xl"===t?32:20}getCurrentTrack(){const t=this.getPlaylist();if(t.length>0){return t[this.isShuffle&&this.shuffledPlaylist.length>0?this.shuffledPlaylist[this.playlistIndex]??this.playlistIndex:this.playlistIndex]||t[0]}return{src:this.getAttribute("src")||"",title:this.getAttribute("title")||void 0,artist:this.getAttribute("artist")||void 0,album:this.getAttribute("album")||void 0,albumArt:this.getAttribute("album-art")||void 0}}refreshShuffledPlaylist(){const t=this.getPlaylist();if(t.length>0&&this.isShuffle){const e=Array.from({length:t.length},(t,e)=>e);this.shuffledPlaylist=[...e].sort(()=>Math.random()-.5)}else this.shuffledPlaylist=[]}formatTime(t){return`${Math.floor(t/60)}:${Math.floor(t%60).toString().padStart(2,"0")}`}syncFromAttributes(){this.playlistIndex=Number(this.getAttribute("current-index")||0),this.currentRepeatMode=this.getAttribute("repeat-mode")||"none",this.isShuffle=this.getBool("shuffle"),this.playbackRate=Number(this.getAttribute("default-playback-rate")||1),this.isMuted=this.getBool("muted"),this.volume=this.isMuted?0:1,this.refreshShuffledPlaylist(),this.loadCurrentTrack()}loadCurrentTrack(){if(!this.audioEl)return;const t=this.getCurrentTrack(),e=t?.src||this.getAttribute("src")||"";this.audioEl.src!==e&&e&&(this.audioEl.src=e,this.audioEl.load()),this.updateTrackInfo(),this.updatePlaylistActive()}bindAudioEvents(){const t=this.audioEl;t&&(t.addEventListener("play",()=>{this.isPlaying=!0,this.dispatchEvent(new CustomEvent("db-play",{bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("pause",()=>{this.isPlaying=!1,this.dispatchEvent(new CustomEvent("db-pause",{bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("timeupdate",()=>{this.currentTime=t.currentTime,this.duration=t.duration||0,this.dispatchEvent(new CustomEvent("db-time-update",{detail:{currentTime:this.currentTime,duration:this.duration},bubbles:!0,composed:!0})),this.updateProgress(),this.updateTime()}),t.addEventListener("volumechange",()=>{this.volume=t.volume,this.isMuted=t.muted,this.dispatchEvent(new CustomEvent("db-volume-change",{detail:{volume:this.volume},bubbles:!0,composed:!0})),this.updateVolumeUI()}),t.addEventListener("ended",()=>this.handleEnded()),t.addEventListener("error",()=>{this.error="오디오를 재생할 수 없습니다.",this.dispatchEvent(new CustomEvent("db-error",{detail:{error:this.error},bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("loadstart",()=>{this.isLoading=!0,this.error=null,this.updateUI()}),t.addEventListener("canplay",()=>{this.isLoading=!1,this.updateUI()}))}handleEnded(){this.isPlaying=!1,this.dispatchEvent(new CustomEvent("db-ended",{bubbles:!0,composed:!0}));const t=this.getPlaylist();if(t.length>0){if("one"===this.currentRepeatMode)this.audioEl&&(this.audioEl.currentTime=0,this.audioEl.play());else if("all"===this.currentRepeatMode||this.playlistIndex<t.length-1){const e=this.playlistIndex+1;e<t.length?this.setPlaylistIndex(e):"all"===this.currentRepeatMode&&this.setPlaylistIndex(0)}}else this.getBool("loop")&&this.audioEl&&(this.audioEl.currentTime=0,this.audioEl.play());this.updateUI()}setPlaylistIndex(t){this.playlistIndex=t,this.dispatchEvent(new CustomEvent("db-playlist-change",{detail:{index:t},bubbles:!0,composed:!0})),this.loadCurrentTrack(),this.audioEl&&this.audioEl.play()}togglePlay(){this.audioEl&&(this.isPlaying?this.audioEl.pause():this.audioEl.play())}toggleMute(){this.audioEl&&(this.audioEl.muted=!this.isMuted)}toggleRepeatMode(){const t=["none","one","all"],e=t[(t.indexOf(this.currentRepeatMode)+1)%t.length];this.currentRepeatMode=e,this.dispatchEvent(new CustomEvent("db-repeat-mode-change",{detail:{mode:e},bubbles:!0,composed:!0})),this.updateUI()}toggleShuffle(){this.isShuffle=!this.isShuffle,this.refreshShuffledPlaylist(),this.dispatchEvent(new CustomEvent("db-shuffle-change",{detail:{shuffle:this.isShuffle},bubbles:!0,composed:!0})),this.updateUI()}handlePlaybackRateChange(t){this.audioEl&&(this.audioEl.playbackRate=t,this.playbackRate=t,this.dispatchEvent(new CustomEvent("db-playback-rate-change",{detail:{rate:t},bubbles:!0,composed:!0})))}handleKeyDown(t){if(this.audioEl&&this.getBool("enable-keyboard",!0))switch(t.code){case"Space":t.preventDefault(),this.togglePlay();break;case"ArrowLeft":t.preventDefault(),this.audioEl.currentTime=Math.max(0,this.currentTime-10);break;case"ArrowRight":t.preventDefault(),this.audioEl.currentTime=Math.min(this.duration,this.currentTime+10);break;case"ArrowUp":t.preventDefault(),this.audioEl.volume=Math.min(1,this.volume+.1),this.audioEl.muted=!1;break;case"ArrowDown":t.preventDefault(),this.audioEl.volume=Math.max(0,this.volume-.1),this.audioEl.muted=0===this.audioEl.volume;break;case"KeyM":t.preventDefault(),this.toggleMute();break;case"KeyR":t.preventDefault(),this.toggleRepeatMode();break;case"KeyS":t.preventDefault(),this.toggleShuffle()}}iconButton(t,e,i,l){const a=document.createElement("button");return a.type="button",a.className=`${n}__control-button`,a.setAttribute("aria-label",e),a.append(s(t,this.getIconSize())),l?.disabled&&(a.disabled=!0),l?.data&&Object.entries(l.data).forEach(([t,e])=>a.setAttribute(`data-${t}`,e)),a.addEventListener("click",i),a}build(){const s=i(this.getAttribute("size"),l,"m"),o=i(this.getAttribute("variant"),a,"default"),r=this.getAttribute("theme")||"auto";this.className=[n,`${n}--size-${s}`,`${n}--variant-${o}`,`${n}--theme-${r}`].join(" "),this.audioEl=document.createElement("audio"),this.audioEl.preload="metadata",this.audioEl.hidden=!0;const h=document.createElement("div");h.className=`${n}__loading`;const u=document.createElement("div");u.className=`${n}__spinner`,h.append(u);const d=document.createElement("div");d.className=`${n}__error`;const c=document.createElement("p");c.textContent=t("오디오를 재생할 수 없습니다.");const m=document.createElement("button");m.type="button",m.textContent=t("다시 시도"),m.addEventListener("click",()=>window.location.reload()),d.append(c,m);const p=document.createElement("div");p.className=`${n}__album-art`,this.albumImgEl=document.createElement("img"),this.albumImgEl.addEventListener("error",()=>{this.albumImgEl&&(this.albumImgEl.style.display="none"),this.albumPlaceholderEl?.classList.remove("album-placeholder")}),this.albumPlaceholderEl=document.createElement("div"),this.albumPlaceholderEl.className="album-placeholder",this.albumPlaceholderEl.textContent="🎵",p.append(this.albumImgEl,this.albumPlaceholderEl);const E=document.createElement("div");E.className=`${n}__main`;const g=document.createElement("div");g.className=`${n}__info`,this.titleEl=document.createElement("div"),this.titleEl.className=`${n}__title`,this.artistEl=document.createElement("div"),this.artistEl.className=`${n}__artist`,this.albumEl=document.createElement("div"),this.albumEl.className=`${n}__album`,g.append(this.titleEl,this.artistEl,this.albumEl),this.progressEl=document.createElement("div"),this.progressEl.className=`${n}__progress`,this.progressBarEl=document.createElement("div"),this.progressBarEl.className=`${n}__progress-bar`,this.progressHandleEl=document.createElement("div"),this.progressHandleEl.className=`${n}__progress-handle`,this.progressEl.append(this.progressBarEl,this.progressHandleEl),this.progressEl.addEventListener("click",t=>{if(!this.audioEl||!this.progressEl)return;const e=this.progressEl.getBoundingClientRect(),s=(t.clientX-e.left)/e.width;this.audioEl.currentTime=s*(this.duration||0)});const b=document.createElement("div");b.className=`${n}__controls`;const y=document.createElement("div");y.className=`${n}__left-controls`;const v=document.createElement("div");v.className=`${n}__center-controls`;const f=document.createElement("div");f.className=`${n}__right-controls`,this.playButtonEl=document.createElement("button"),this.playButtonEl.type="button",this.playButtonEl.className=`${n}__play-button`,this.playButtonEl.addEventListener("click",()=>this.togglePlay()),v.append(this.playButtonEl),b.append(y,v,f);const _=document.createElement("div");_.className=`${n}__bottom-controls`;const k=document.createElement("div");k.className=`${n}__left-bottom`;const C=document.createElement("div");C.className=`${n}__right-bottom`;const I=document.createElement("div");I.className=`${n}__time`,this.timeCurrentEl=document.createElement("span");const $=document.createElement("span");$.textContent="/",this.timeDurationEl=document.createElement("span"),I.append(this.timeCurrentEl,$,this.timeDurationEl),k.append(I);const A=document.createElement("div");A.className=`${n}__volume`;const P=this.iconButton(this.isMuted||0===this.volume?"mute-filled":"volume-up",this.isMuted||0===this.volume?e("media.unmute"):e("media.mute"),()=>this.toggleMute());P.title=this.isMuted||0===this.volume?"음소거 해제":"음소거";const x=document.createElement("div");x.className=`${n}__volume-slider`;const M=document.createElement("div");M.className="volume-label";const w=document.createElement("span");w.textContent="🔊";const B=document.createElement("span");M.append(w,B),this.volumeInputEl=document.createElement("input"),this.volumeInputEl.type="range",this.volumeInputEl.min="0",this.volumeInputEl.max="1",this.volumeInputEl.step="0.1",this.volumeInputEl.addEventListener("input",()=>{if(!this.audioEl||!this.volumeInputEl)return;const t=parseFloat(this.volumeInputEl.value);this.audioEl.volume=t,this.audioEl.muted=0===t}),x.append(M,this.volumeInputEl),A.append(P,x);const N=document.createElement("div");N.className=`${n}__settings`;const T=this.iconButton("settings",e("media.settings"),()=>{this.showSettingsMenu=!this.showSettingsMenu,this.updateSettingsMenu()});this.settingsMenuEl=document.createElement("div"),this.settingsMenuEl.className=`${n}__settings-menu`,this.settingsMenuEl.hidden=!0;const S=document.createElement("div");S.className=`${n}__setting-group`;const R=document.createElement("label");R.textContent=t("재생 속도");const L=document.createElement("select");L.addEventListener("change",()=>this.handlePlaybackRateChange(parseFloat(L.value))),S.append(R,L),this.settingsMenuEl.append(S),N.append(T,this.settingsMenuEl),C.append(A,N),_.append(k,C),E.append(g,this.progressEl,b,_);const D=document.createElement("div");D.className=`${n}__playlist`,D.hidden=!0;const U=document.createElement("h4");U.textContent=t("플레이리스트"),this.playlistTracksEl=document.createElement("div"),this.playlistTracksEl.className=`${n}__playlist-tracks`,D.append(U,this.playlistTracksEl),this.append(this.audioEl,h,d,p,E,D),this._leftControls=y,this._rightControls=f,this._controls=b,this._time=I,this._volumeWrap=A,this._settings=N,this._playlist=D,this._rateSelect=L,this._volumePercent=B,this._muteButton=P}get leftControls(){return this._leftControls}get rightControls(){return this._rightControls}get controlsEl(){return this._controls}get timeEl(){return this._time}get volumeWrap(){return this._volumeWrap}get settingsEl(){return this._settings}get playlistEl(){return this._playlist}get rateSelect(){return this._rateSelect}get volumePercent(){return this._volumePercent}get muteButton(){return this._muteButton}updateTrackInfo(){const t=this.getCurrentTrack();this.titleEl&&(this.titleEl.textContent=t?.title||"Unknown Track"),this.artistEl&&(this.artistEl.textContent=t?.artist||"Unknown Artist"),this.albumEl&&(t?.album?(this.albumEl.textContent=t.album,this.albumEl.hidden=!1):this.albumEl.hidden=!0),this.albumImgEl&&this.albumPlaceholderEl&&(t?.albumArt?(this.albumImgEl.src=t.albumArt,this.albumImgEl.alt=t.title||"Album Art",this.albumImgEl.style.display=""):(this.albumImgEl.removeAttribute("src"),this.albumImgEl.style.display="none"),this.albumPlaceholderEl.className="album-placeholder")}updateProgress(){const t=this.duration>0?this.currentTime/this.duration*100:0;this.progressBarEl&&(this.progressBarEl.style.width=`${t}%`),this.progressHandleEl&&(this.progressHandleEl.style.left=`${t}%`,this.progressHandleEl.style.transform=t<=0?"translate(0, -50%)":t>=100?"translate(-100%, -50%)":"translate(-50%, -50%)")}updateTime(){this.timeCurrentEl&&(this.timeCurrentEl.textContent=this.formatTime(this.currentTime)),this.timeDurationEl&&(this.timeDurationEl.textContent=this.formatTime(this.duration))}updateVolumeUI(){this.volumeInputEl&&(this.volumeInputEl.value=String(this.volume)),this.volumePercent&&(this.volumePercent.textContent=`${Math.round(100*this.volume)}%`),this.muteButton&&(this.muteButton.replaceChildren(s(this.isMuted||0===this.volume?"mute-filled":"volume-up",this.getIconSize())),this.muteButton.title=this.isMuted||0===this.volume?"음소거 해제":"음소거")}updateSettingsMenu(){this.settingsMenuEl&&(this.settingsMenuEl.hidden=!this.showSettingsMenu)}rebuildControlButtons(){const t=this.getPlaylist(),i=1.2*this.getIconSize();this.leftControls.replaceChildren(),this.rightControls.replaceChildren(),t.length>0&&this.leftControls.append(this.iconButton("refresh",e("media.shuffle"),()=>this.toggleShuffle(),{data:{shuffle:"true"}})),this.leftControls.append(this.iconButton("chevron-left",e("media.previous"),()=>{if(t.length>0){const t=this.playlistIndex-1;t>=0&&this.setPlaylistIndex(t)}else this.audioEl&&(this.audioEl.currentTime=0)},{disabled:t.length>0&&0===this.playlistIndex})),this.playButtonEl&&this.playButtonEl.replaceChildren(s(this.isPlaying?"pause":"play",i)),this.rightControls.append(this.iconButton("chevron-right",e("media.next"),()=>{if(t.length>0){const e=this.playlistIndex+1;e<t.length&&this.setPlaylistIndex(e)}},{disabled:t.length>0&&this.playlistIndex===t.length-1})),t.length>0&&this.rightControls.append(this.iconButton("repeat",e("media.repeat"),()=>this.toggleRepeatMode(),{data:{repeat:"true"}}))}rebuildPlaylist(){if(!this.playlistTracksEl)return;const t=this.getPlaylist(),e=i(this.getAttribute("variant"),a,"default");this.playlistEl.hidden=!("full"===e&&t.length>0),this.playlistTracksEl.replaceChildren(),t.forEach((t,e)=>{const s=document.createElement("div");if(s.className=`${n}__playlist-track${e===this.playlistIndex?` ${n}__playlist-track--active`:""}`,s.addEventListener("click",()=>this.setPlaylistIndex(e)),t.albumArt){const e=document.createElement("img");e.src=t.albumArt,e.alt=t.title||"Album Art",s.append(e)}const i=document.createElement("div");i.className=`${n}__playlist-track-info`;const l=document.createElement("div");l.className=`${n}__playlist-track-title`,l.textContent=t.title||"Unknown Track";const a=document.createElement("div");a.className=`${n}__playlist-track-artist`,a.textContent=t.artist||"Unknown Artist",i.append(l,a),s.append(i),this.playlistTracksEl?.append(s)})}updatePlaylistActive(){this.playlistTracksEl&&Array.from(this.playlistTracksEl.children).forEach((t,e)=>{t.classList.toggle(`${n}__playlist-track--active`,e===this.playlistIndex)})}updateUI(){const t=i(this.getAttribute("size"),l,"m"),e=i(this.getAttribute("variant"),a,"default"),s=this.getAttribute("theme")||"auto",o=this.getBool("show-controls",!0),r=this.getBool("show-progress",!0),h=this.getBool("show-time",!0),u=this.getBool("show-volume",!0),d=this.getBool("show-settings",!1);this.className=[n,`${n}--size-${t}`,`${n}--variant-${e}`,`${n}--theme-${s}`,this.isPlaying&&`${n}--playing`,!this.isPlaying&&`${n}--paused`,this.isMuted&&`${n}--muted`,this.isLoading&&`${n}--loading`,this.error&&`${n}--error`,this.isShuffle&&`${n}--shuffle`,`${n}--repeat-${this.currentRepeatMode}`].filter(Boolean).join(" "),this.audioEl&&(this.audioEl.autoplay=this.getBool("auto-play"),this.audioEl.loop=this.getBool("loop"),this.audioEl.muted=this.getBool("muted"),this.audioEl.playbackRate=this.playbackRate),this.progressEl&&(this.progressEl.hidden=!r),this.controlsEl&&(this.controlsEl.hidden=!o),this.timeEl&&(this.timeEl.hidden=!h),this.volumeWrap&&(this.volumeWrap.hidden=!u),this.settingsEl&&(this.settingsEl.hidden=!d),this.rateSelect.replaceChildren(...this.getPlaybackRates().map(t=>{const e=document.createElement("option");return e.value=String(t),e.textContent=`${t}x`,t===this.playbackRate&&(e.selected=!0),e})),this.rebuildControlButtons(),this.updateTrackInfo(),this.updateProgress(),this.updateTime(),this.updateVolumeUI(),this.updateSettingsMenu(),this.rebuildPlaylist()}}customElements.get("db-audio-player")||customElements.define("db-audio-player",DbAudioPlayer);export{DbAudioPlayer};
1
+ import{subscribeDbLocale as t,dbText as e,t as s}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{coerceToContract as l}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{AUDIO_PLAYER_SIZES as a,AUDIO_PLAYER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-audio-player";class DbAudioPlayer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.isPlaying=!1,this.isMuted=!1,this.volume=1,this.currentTime=0,this.duration=0,this.showSettingsMenu=!1,this.playbackRate=1,this.currentRepeatMode="none",this.isShuffle=!1,this.isLoading=!1,this.error=null,this.playlistIndex=0,this.shuffledPlaylist=[],this.boundKeyDown=t=>this.handleKeyDown(t)}static get observedAttributes(){return["src","title","artist","album","album-art","size","variant","theme","auto-play","loop","muted","show-controls","enable-keyboard","show-progress","show-time","show-volume","show-settings","playlist","current-index","playback-rates","default-playback-rate","repeat-mode","shuffle"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build(),this.bindAudioEvents()),this.syncFromAttributes(),this.updateUI(),this.unsubscribeLocale?.(),this.unsubscribeLocale=t(()=>this.refreshLocale()),this.refreshLocale(),this.getBool("enable-keyboard",!0)&&document.addEventListener("keydown",this.boundKeyDown)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,document.removeEventListener("keydown",this.boundKeyDown)}attributeChangedCallback(t){if(this.built){if("current-index"===t)return this.playlistIndex=Number(this.getAttribute("current-index")||0),void this.loadCurrentTrack();"repeat-mode"===t&&(this.currentRepeatMode=this.getAttribute("repeat-mode")||"none"),"shuffle"===t&&(this.isShuffle=this.getBool("shuffle"),this.refreshShuffledPlaylist()),"default-playback-rate"===t&&(this.playbackRate=Number(this.getAttribute("default-playback-rate")||1),this.audioEl&&(this.audioEl.playbackRate=this.playbackRate)),this.updateUI()}}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const s=this.getAttribute(t);return""===s||"true"===s}getPlaylist(){try{const t=this.getAttribute("playlist"),e=t?JSON.parse(t):[];return Array.isArray(e)?e:[]}catch{return[]}}getPlaybackRates(){try{const t=this.getAttribute("playback-rates"),e=t?JSON.parse(t):[.5,.75,1,1.25,1.5,2];return Array.isArray(e)&&e.length>0?e:[.5,.75,1,1.25,1.5,2]}catch{return[.5,.75,1,1.25,1.5,2]}}getIconSize(){const t=l(this.getAttribute("size"),a,"m");return"s"===t?16:"l"===t?24:"xl"===t?32:20}getCurrentTrack(){const t=this.getPlaylist();if(t.length>0){return t[this.isShuffle&&this.shuffledPlaylist.length>0?this.shuffledPlaylist[this.playlistIndex]??this.playlistIndex:this.playlistIndex]||t[0]}return{src:this.getAttribute("src")||"",title:this.getAttribute("title")||void 0,artist:this.getAttribute("artist")||void 0,album:this.getAttribute("album")||void 0,albumArt:this.getAttribute("album-art")||void 0}}refreshShuffledPlaylist(){const t=this.getPlaylist();if(t.length>0&&this.isShuffle){const e=Array.from({length:t.length},(t,e)=>e);this.shuffledPlaylist=[...e].sort(()=>Math.random()-.5)}else this.shuffledPlaylist=[]}formatTime(t){return`${Math.floor(t/60)}:${Math.floor(t%60).toString().padStart(2,"0")}`}syncFromAttributes(){this.playlistIndex=Number(this.getAttribute("current-index")||0),this.currentRepeatMode=this.getAttribute("repeat-mode")||"none",this.isShuffle=this.getBool("shuffle"),this.playbackRate=Number(this.getAttribute("default-playback-rate")||1),this.isMuted=this.getBool("muted"),this.volume=this.isMuted?0:1,this.refreshShuffledPlaylist(),this.loadCurrentTrack()}loadCurrentTrack(){if(!this.audioEl)return;const t=this.getCurrentTrack(),e=t?.src||this.getAttribute("src")||"";this.audioEl.src!==e&&e&&(this.audioEl.src=e,this.audioEl.load()),this.updateTrackInfo(),this.updatePlaylistActive()}bindAudioEvents(){const t=this.audioEl;t&&(t.addEventListener("play",()=>{this.isPlaying=!0,this.dispatchEvent(new CustomEvent("db-play",{bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("pause",()=>{this.isPlaying=!1,this.dispatchEvent(new CustomEvent("db-pause",{bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("timeupdate",()=>{this.currentTime=t.currentTime,this.duration=t.duration||0,this.dispatchEvent(new CustomEvent("db-time-update",{detail:{currentTime:this.currentTime,duration:this.duration},bubbles:!0,composed:!0})),this.updateProgress(),this.updateTime()}),t.addEventListener("volumechange",()=>{this.volume=t.volume,this.isMuted=t.muted,this.dispatchEvent(new CustomEvent("db-volume-change",{detail:{volume:this.volume},bubbles:!0,composed:!0})),this.updateVolumeUI()}),t.addEventListener("ended",()=>this.handleEnded()),t.addEventListener("error",()=>{this.error=e("오디오를 재생할 수 없습니다."),this.dispatchEvent(new CustomEvent("db-error",{detail:{error:this.error},bubbles:!0,composed:!0})),this.updateUI()}),t.addEventListener("loadstart",()=>{this.isLoading=!0,this.error=null,this.updateUI()}),t.addEventListener("canplay",()=>{this.isLoading=!1,this.updateUI()}))}handleEnded(){this.isPlaying=!1,this.dispatchEvent(new CustomEvent("db-ended",{bubbles:!0,composed:!0}));const t=this.getPlaylist();if(t.length>0){if("one"===this.currentRepeatMode)this.audioEl&&(this.audioEl.currentTime=0,this.audioEl.play());else if("all"===this.currentRepeatMode||this.playlistIndex<t.length-1){const e=this.playlistIndex+1;e<t.length?this.setPlaylistIndex(e):"all"===this.currentRepeatMode&&this.setPlaylistIndex(0)}}else this.getBool("loop")&&this.audioEl&&(this.audioEl.currentTime=0,this.audioEl.play());this.updateUI()}setPlaylistIndex(t){this.playlistIndex=t,this.dispatchEvent(new CustomEvent("db-playlist-change",{detail:{index:t},bubbles:!0,composed:!0})),this.loadCurrentTrack(),this.audioEl&&this.audioEl.play()}togglePlay(){this.audioEl&&(this.isPlaying?this.audioEl.pause():this.audioEl.play())}toggleMute(){this.audioEl&&(this.audioEl.muted=!this.isMuted)}toggleRepeatMode(){const t=["none","one","all"],e=t[(t.indexOf(this.currentRepeatMode)+1)%t.length];this.currentRepeatMode=e,this.dispatchEvent(new CustomEvent("db-repeat-mode-change",{detail:{mode:e},bubbles:!0,composed:!0})),this.updateUI()}toggleShuffle(){this.isShuffle=!this.isShuffle,this.refreshShuffledPlaylist(),this.dispatchEvent(new CustomEvent("db-shuffle-change",{detail:{shuffle:this.isShuffle},bubbles:!0,composed:!0})),this.updateUI()}handlePlaybackRateChange(t){this.audioEl&&(this.audioEl.playbackRate=t,this.playbackRate=t,this.dispatchEvent(new CustomEvent("db-playback-rate-change",{detail:{rate:t},bubbles:!0,composed:!0})))}handleKeyDown(t){if(this.audioEl&&this.getBool("enable-keyboard",!0))switch(t.code){case"Space":t.preventDefault(),this.togglePlay();break;case"ArrowLeft":t.preventDefault(),this.audioEl.currentTime=Math.max(0,this.currentTime-10);break;case"ArrowRight":t.preventDefault(),this.audioEl.currentTime=Math.min(this.duration,this.currentTime+10);break;case"ArrowUp":t.preventDefault(),this.audioEl.volume=Math.min(1,this.volume+.1),this.audioEl.muted=!1;break;case"ArrowDown":t.preventDefault(),this.audioEl.volume=Math.max(0,this.volume-.1),this.audioEl.muted=0===this.audioEl.volume;break;case"KeyM":t.preventDefault(),this.toggleMute();break;case"KeyR":t.preventDefault(),this.toggleRepeatMode();break;case"KeyS":t.preventDefault(),this.toggleShuffle()}}iconButton(t,e,s,l){const a=document.createElement("button");return a.type="button",a.className=`${r}__control-button`,a.setAttribute("aria-label",e),a.append(i(t,this.getIconSize())),l?.disabled&&(a.disabled=!0),l?.data&&Object.entries(l.data).forEach(([t,e])=>a.setAttribute(`data-${t}`,e)),a.addEventListener("click",s),a}build(){const t=l(this.getAttribute("size"),a,"m"),i=l(this.getAttribute("variant"),n,"default"),o=this.getAttribute("theme")||"auto";this.className=[r,`${r}--size-${t}`,`${r}--variant-${i}`,`${r}--theme-${o}`].join(" "),this.audioEl=document.createElement("audio"),this.audioEl.preload="metadata",this.audioEl.hidden=!0;const h=document.createElement("div");h.className=`${r}__loading`;const u=document.createElement("div");u.className=`${r}__spinner`,h.append(u);const d=document.createElement("div");d.className=`${r}__error`;const c=document.createElement("p");c.textContent=e("오디오를 재생할 수 없습니다.");const m=document.createElement("button");m.type="button",m.textContent=e("다시 시도"),m.addEventListener("click",()=>window.location.reload()),d.append(c,m);const p=document.createElement("div");p.className=`${r}__album-art`,this.albumImgEl=document.createElement("img"),this.albumImgEl.addEventListener("error",()=>{this.albumImgEl&&(this.albumImgEl.style.display="none"),this.albumPlaceholderEl?.classList.remove("album-placeholder")}),this.albumPlaceholderEl=document.createElement("div"),this.albumPlaceholderEl.className="album-placeholder",this.albumPlaceholderEl.textContent="🎵",p.append(this.albumImgEl,this.albumPlaceholderEl);const E=document.createElement("div");E.className=`${r}__main`;const b=document.createElement("div");b.className=`${r}__info`,this.titleEl=document.createElement("div"),this.titleEl.className=`${r}__title`,this.artistEl=document.createElement("div"),this.artistEl.className=`${r}__artist`,this.albumEl=document.createElement("div"),this.albumEl.className=`${r}__album`,b.append(this.titleEl,this.artistEl,this.albumEl),this.progressEl=document.createElement("div"),this.progressEl.className=`${r}__progress`,this.progressBarEl=document.createElement("div"),this.progressBarEl.className=`${r}__progress-bar`,this.progressHandleEl=document.createElement("div"),this.progressHandleEl.className=`${r}__progress-handle`,this.progressEl.append(this.progressBarEl,this.progressHandleEl),this.progressEl.addEventListener("click",t=>{if(!this.audioEl||!this.progressEl)return;const e=this.progressEl.getBoundingClientRect(),s=(t.clientX-e.left)/e.width;this.audioEl.currentTime=s*(this.duration||0)});const g=document.createElement("div");g.className=`${r}__controls`;const y=document.createElement("div");y.className=`${r}__left-controls`;const v=document.createElement("div");v.className=`${r}__center-controls`;const f=document.createElement("div");f.className=`${r}__right-controls`,this.playButtonEl=document.createElement("button"),this.playButtonEl.type="button",this.playButtonEl.className=`${r}__play-button`,this.playButtonEl.addEventListener("click",()=>this.togglePlay()),v.append(this.playButtonEl),g.append(y,v,f);const _=document.createElement("div");_.className=`${r}__bottom-controls`;const k=document.createElement("div");k.className=`${r}__left-bottom`;const C=document.createElement("div");C.className=`${r}__right-bottom`;const $=document.createElement("div");$.className=`${r}__time`,this.timeCurrentEl=document.createElement("span");const A=document.createElement("span");A.textContent="/",this.timeDurationEl=document.createElement("span"),$.append(this.timeCurrentEl,A,this.timeDurationEl),k.append($);const I=document.createElement("div");I.className=`${r}__volume`;const P=this.iconButton(this.isMuted||0===this.volume?"mute-filled":"volume-up",this.isMuted||0===this.volume?s("media.unmute"):s("media.mute"),()=>this.toggleMute());P.title=s(this.isMuted||0===this.volume?"media.unmute":"media.mute");const x=document.createElement("div");x.className=`${r}__volume-slider`;const M=document.createElement("div");M.className="volume-label";const B=document.createElement("span");B.textContent="🔊";const w=document.createElement("span");M.append(B,w),this.volumeInputEl=document.createElement("input"),this.volumeInputEl.type="range",this.volumeInputEl.min="0",this.volumeInputEl.max="1",this.volumeInputEl.step="0.1",this.volumeInputEl.addEventListener("input",()=>{if(!this.audioEl||!this.volumeInputEl)return;const t=parseFloat(this.volumeInputEl.value);this.audioEl.volume=t,this.audioEl.muted=0===t}),x.append(M,this.volumeInputEl),I.append(P,x);const S=document.createElement("div");S.className=`${r}__settings`;const N=this.iconButton("settings",s("media.settings"),()=>{this.showSettingsMenu=!this.showSettingsMenu,this.updateSettingsMenu()});this.settingsMenuEl=document.createElement("div"),this.settingsMenuEl.className=`${r}__settings-menu`,this.settingsMenuEl.hidden=!0;const T=document.createElement("div");T.className=`${r}__setting-group`;const L=document.createElement("label");L.textContent=e("재생 속도");const R=document.createElement("select");R.addEventListener("change",()=>this.handlePlaybackRateChange(parseFloat(R.value))),T.append(L,R),this.settingsMenuEl.append(T),S.append(N,this.settingsMenuEl),C.append(I,S),_.append(k,C),E.append(b,this.progressEl,g,_);const D=document.createElement("div");D.className=`${r}__playlist`,D.hidden=!0;const U=document.createElement("h4");U.textContent=e("플레이리스트"),this.playlistTracksEl=document.createElement("div"),this.playlistTracksEl.className=`${r}__playlist-tracks`,D.append(U,this.playlistTracksEl),this.append(this.audioEl,h,d,p,E,D),this._leftControls=y,this._rightControls=f,this._controls=g,this._time=$,this._volumeWrap=I,this._settings=S,this._playlist=D,this._rateSelect=R,this._volumePercent=w,this._muteButton=P}get leftControls(){return this._leftControls}get rightControls(){return this._rightControls}get controlsEl(){return this._controls}get timeEl(){return this._time}get volumeWrap(){return this._volumeWrap}get settingsEl(){return this._settings}get playlistEl(){return this._playlist}get rateSelect(){return this._rateSelect}get volumePercent(){return this._volumePercent}get muteButton(){return this._muteButton}updateTrackInfo(){const t=this.getCurrentTrack();this.titleEl&&(this.titleEl.textContent=t?.title||"Unknown Track"),this.artistEl&&(this.artistEl.textContent=t?.artist||"Unknown Artist"),this.albumEl&&(t?.album?(this.albumEl.textContent=t.album,this.albumEl.hidden=!1):this.albumEl.hidden=!0),this.albumImgEl&&this.albumPlaceholderEl&&(t?.albumArt?(this.albumImgEl.src=t.albumArt,this.albumImgEl.alt=t.title||"Album Art",this.albumImgEl.style.display=""):(this.albumImgEl.removeAttribute("src"),this.albumImgEl.style.display="none"),this.albumPlaceholderEl.className="album-placeholder")}updateProgress(){const t=this.duration>0?this.currentTime/this.duration*100:0;this.progressBarEl&&(this.progressBarEl.style.width=`${t}%`),this.progressHandleEl&&(this.progressHandleEl.style.left=`${t}%`,this.progressHandleEl.style.transform=t<=0?"translate(0, -50%)":t>=100?"translate(-100%, -50%)":"translate(-50%, -50%)")}updateTime(){this.timeCurrentEl&&(this.timeCurrentEl.textContent=this.formatTime(this.currentTime)),this.timeDurationEl&&(this.timeDurationEl.textContent=this.formatTime(this.duration))}updateVolumeUI(){this.volumeInputEl&&(this.volumeInputEl.value=String(this.volume)),this.volumePercent&&(this.volumePercent.textContent=`${Math.round(100*this.volume)}%`),this.muteButton&&(this.muteButton.replaceChildren(i(this.isMuted||0===this.volume?"mute-filled":"volume-up",this.getIconSize())),this.muteButton.title=s(this.isMuted||0===this.volume?"media.unmute":"media.mute"),this.muteButton.setAttribute("aria-label",this.muteButton.title))}updateSettingsMenu(){this.settingsMenuEl&&(this.settingsMenuEl.hidden=!this.showSettingsMenu)}rebuildControlButtons(){const t=this.getPlaylist(),e=1.2*this.getIconSize();this.leftControls.replaceChildren(),this.rightControls.replaceChildren(),t.length>0&&this.leftControls.append(this.iconButton("refresh",s("media.shuffle"),()=>this.toggleShuffle(),{data:{shuffle:"true"}})),this.leftControls.append(this.iconButton("chevron-left",s("media.previous"),()=>{if(t.length>0){const t=this.playlistIndex-1;t>=0&&this.setPlaylistIndex(t)}else this.audioEl&&(this.audioEl.currentTime=0)},{disabled:t.length>0&&0===this.playlistIndex})),this.playButtonEl&&(this.playButtonEl.setAttribute("aria-label",s(this.isPlaying?"media.pause":"media.play")),this.playButtonEl.replaceChildren(i(this.isPlaying?"pause":"play",e))),this.rightControls.append(this.iconButton("chevron-right",s("media.next"),()=>{if(t.length>0){const e=this.playlistIndex+1;e<t.length&&this.setPlaylistIndex(e)}},{disabled:t.length>0&&this.playlistIndex===t.length-1})),t.length>0&&this.rightControls.append(this.iconButton("repeat",s("media.repeat"),()=>this.toggleRepeatMode(),{data:{repeat:"true"}}))}rebuildPlaylist(){if(!this.playlistTracksEl)return;const t=this.getPlaylist(),e=l(this.getAttribute("variant"),n,"default");this.playlistEl.hidden=!("full"===e&&t.length>0),this.playlistTracksEl.replaceChildren(),t.forEach((t,e)=>{const s=document.createElement("div");if(s.className=`${r}__playlist-track${e===this.playlistIndex?` ${r}__playlist-track--active`:""}`,s.addEventListener("click",()=>this.setPlaylistIndex(e)),t.albumArt){const e=document.createElement("img");e.src=t.albumArt,e.alt=t.title||"Album Art",s.append(e)}const i=document.createElement("div");i.className=`${r}__playlist-track-info`;const l=document.createElement("div");l.className=`${r}__playlist-track-title`,l.textContent=t.title||"Unknown Track";const a=document.createElement("div");a.className=`${r}__playlist-track-artist`,a.textContent=t.artist||"Unknown Artist",i.append(l,a),s.append(i),this.playlistTracksEl?.append(s)})}updatePlaylistActive(){this.playlistTracksEl&&Array.from(this.playlistTracksEl.children).forEach((t,e)=>{t.classList.toggle(`${r}__playlist-track--active`,e===this.playlistIndex)})}refreshLocale(){const text=(t,e)=>{const s=this.querySelector(t);s&&(s.textContent=e)};text(`.${r}__error p`,e("오디오를 재생할 수 없습니다.")),text(`.${r}__error button`,e("다시 시도")),text(`.${r}__setting-group label`,e("재생 속도")),text(`.${r}__playlist h4`,e("플레이리스트")),this.querySelector(`.${r}__settings > button`)?.setAttribute("aria-label",s("media.settings")),this.leftControls.querySelector("[data-shuffle]")?.setAttribute("aria-label",s("media.shuffle")),this.leftControls.querySelector("button:not([data-shuffle])")?.setAttribute("aria-label",s("media.previous")),this.rightControls.querySelector("button:not([data-repeat])")?.setAttribute("aria-label",s("media.next")),this.rightControls.querySelector("[data-repeat]")?.setAttribute("aria-label",s("media.repeat")),this.playButtonEl?.setAttribute("aria-label",s(this.isPlaying?"media.pause":"media.play")),this.updateVolumeUI()}updateUI(){const t=l(this.getAttribute("size"),a,"m"),e=l(this.getAttribute("variant"),n,"default"),s=this.getAttribute("theme")||"auto",i=this.getBool("show-controls",!0),o=this.getBool("show-progress",!0),h=this.getBool("show-time",!0),u=this.getBool("show-volume",!0),d=this.getBool("show-settings",!1);this.className=[r,`${r}--size-${t}`,`${r}--variant-${e}`,`${r}--theme-${s}`,this.isPlaying&&`${r}--playing`,!this.isPlaying&&`${r}--paused`,this.isMuted&&`${r}--muted`,this.isLoading&&`${r}--loading`,this.error&&`${r}--error`,this.isShuffle&&`${r}--shuffle`,`${r}--repeat-${this.currentRepeatMode}`].filter(Boolean).join(" "),this.audioEl&&(this.audioEl.autoplay=this.getBool("auto-play"),this.audioEl.loop=this.getBool("loop"),this.audioEl.muted=this.getBool("muted"),this.audioEl.playbackRate=this.playbackRate),this.progressEl&&(this.progressEl.hidden=!o),this.controlsEl&&(this.controlsEl.hidden=!i),this.timeEl&&(this.timeEl.hidden=!h),this.volumeWrap&&(this.volumeWrap.hidden=!u),this.settingsEl&&(this.settingsEl.hidden=!d),this.rateSelect.replaceChildren(...this.getPlaybackRates().map(t=>{const e=document.createElement("option");return e.value=String(t),e.textContent=`${t}x`,t===this.playbackRate&&(e.selected=!0),e})),this.rebuildControlButtons(),this.updateTrackInfo(),this.updateProgress(),this.updateTime(),this.updateVolumeUI(),this.updateSettingsMenu(),this.rebuildPlaylist()}}customElements.get("db-audio-player")||customElements.define("db-audio-player",DbAudioPlayer);export{DbAudioPlayer};
@@ -2,6 +2,7 @@ declare class DbAvatar extends HTMLElement {
2
2
  static get observedAttributes(): string[];
3
3
  private imageFailed;
4
4
  private imageLoaded;
5
+ private unsubscribeLocale?;
5
6
  connectedCallback(): void;
6
7
  disconnectedCallback(): void;
7
8
  attributeChangedCallback(name: string): void;
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{AVATAR_SIZES as e,AVATAR_VARIANTS as a,AVATAR_STATUSES as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const i=["#E3F2FD","#F3E5F5","#E8F5E8","#FFF3E0","#FCE4EC","#E0F2F1","#FFF8E1","#F1F8E9","#E8EAF6","#FFEBEE"],n=["#1976D2","#7B1FA2","#388E3C","#F57C00","#C2185B","#00796B","#F9A825","#689F38","#3F51B5","#D32F2F"];class DbAvatar extends HTMLElement{constructor(){super(...arguments),this.imageFailed=!1,this.imageLoaded=!1,this.handleClick=()=>{!this.hasAttribute("disabled")&&this.hasAttribute("clickable")&&this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.handleKeyDown=t=>{this.hasAttribute("clickable")&&!this.hasAttribute("disabled")&&("Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleClick()))}}static get observedAttributes(){return["src","alt","initials","size","variant","status","disabled","clickable","badge","badge-max-count","badge-variant","badge-type","badge-text"]}connectedCallback(){this.render(),this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown)}attributeChangedCallback(t){"src"===t&&(this.imageFailed=!1,this.imageLoaded=!1),this.render()}render(){const r=e.includes(this.getAttribute("size")||"m")&&this.getAttribute("size")||"m",d=a.includes(this.getAttribute("variant")||"default")&&this.getAttribute("variant")||"default",c=this.hasAttribute("disabled"),l=this.hasAttribute("clickable"),o=this.getAttribute("src"),b=this.getAttribute("initials")||"",h=Boolean(o&&!this.imageFailed),u=h&&!this.imageLoaded;if(this.className=["designbase-wc-avatar",`designbase-wc-avatar--${r}`,`designbase-wc-avatar--${d}`,l&&"designbase-wc-avatar--clickable",c&&"designbase-wc-avatar--disabled",u&&"designbase-wc-avatar--loading"].filter(Boolean).join(" "),l&&!c?(this.setAttribute("role","button"),this.tabIndex=0):(this.removeAttribute("role"),this.removeAttribute("tabindex")),this.toggleAttribute("aria-disabled",c),this.replaceChildren(),u){const t=document.createElement("div");t.className="designbase-wc-avatar__loading";const e=document.createElement("div");e.className="designbase-wc-avatar__skeleton",t.append(e),this.append(t)}if(h){const t=document.createElement("img");t.className="designbase-wc-avatar__image",t.src=o,t.alt=this.getAttribute("alt")||"아바타 이미지",t.loading="lazy",t.addEventListener("load",()=>{this.imageLoaded=!0,this.classList.remove("designbase-wc-avatar--loading"),this.querySelector(".designbase-wc-avatar__loading")?.remove()}),t.addEventListener("error",()=>{this.imageFailed=!0,this.imageLoaded=!1,this.render()}),this.append(t)}else if(b){const t=document.createElement("div");if(t.className="designbase-wc-avatar__initials","default"===d){const e=function initialsColor(t){let e=0;for(let a=0;a<t.length;a++)e=t.charCodeAt(a)+((e<<5)-e);const a=Math.abs(e)%i.length;return{backgroundColor:i[a],color:n[a]}}(b);t.style.backgroundColor=e.backgroundColor,t.style.color=e.color}t.textContent=b.charAt(0).toUpperCase(),this.append(t)}else{const e=document.createElement("div");e.className="designbase-wc-avatar__icon",e.append(t("user",function iconSize(t){return"xs"===t?12:"s"===t?16:"m"===t?20:"l"===t?24:"xl"===t?32:40}(r))),this.append(e)}const g=this.getAttribute("status")||"";if(s.includes(g)){const t=document.createElement("span");t.className=`designbase-wc-avatar__status designbase-wc-avatar__status--${g}`,this.append(t)}if(this.hasAttribute("badge")){const t=document.createElement("div");t.className="designbase-wc-avatar__badge";const e=document.createElement("db-badge");e.setAttribute("count",this.getAttribute("badge")||"0");const a=this.getAttribute("badge-type")||"number";e.setAttribute("type",a),this.hasAttribute("badge-max-count")&&e.setAttribute("max-count",this.getAttribute("badge-max-count")),e.setAttribute("variant",this.getAttribute("badge-variant")||"danger"),this.hasAttribute("badge-text")&&(e.textContent=this.getAttribute("badge-text"));const s="xl"===r||"2xl"===r?"m":"s";e.setAttribute("size",s),t.append(e),this.append(t)}}}customElements.get("db-avatar")||customElements.define("db-avatar",DbAvatar);export{DbAvatar};
1
+ import{setHostClasses as t}from"../core/host-class.js";import{subscribeDbLocale as e,dbText as a}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{AVATAR_SIZES as i,AVATAR_VARIANTS as n,AVATAR_STATUSES as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const d=["#E3F2FD","#F3E5F5","#E8F5E8","#FFF3E0","#FCE4EC","#E0F2F1","#FFF8E1","#F1F8E9","#E8EAF6","#FFEBEE"],c=["#1976D2","#7B1FA2","#388E3C","#F57C00","#C2185B","#00796B","#F9A825","#689F38","#3F51B5","#D32F2F"];class DbAvatar extends HTMLElement{constructor(){super(...arguments),this.imageFailed=!1,this.imageLoaded=!1,this.handleClick=()=>{!this.hasAttribute("disabled")&&this.hasAttribute("clickable")&&this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.handleKeyDown=t=>{this.hasAttribute("clickable")&&!this.hasAttribute("disabled")&&("Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleClick()))}}static get observedAttributes(){return["src","alt","initials","size","variant","status","disabled","clickable","badge","badge-max-count","badge-variant","badge-type","badge-text"]}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{const t=this.querySelector(".designbase-wc-avatar__image");t&&!this.getAttribute("alt")&&(t.alt=a("아바타 이미지"))}),this.render(),this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown)}attributeChangedCallback(t){"src"===t&&(this.imageFailed=!1,this.imageLoaded=!1),this.render()}render(){const e=i.includes(this.getAttribute("size")||"m")&&this.getAttribute("size")||"m",o=n.includes(this.getAttribute("variant")||"default")&&this.getAttribute("variant")||"default",l=this.hasAttribute("disabled"),b=this.hasAttribute("clickable"),h=this.getAttribute("src"),u=this.getAttribute("initials")||"",g=Boolean(h&&!this.imageFailed),m=g&&!this.imageLoaded,v=["designbase-wc-avatar",`designbase-wc-avatar--${e}`,`designbase-wc-avatar--${o}`,b&&"designbase-wc-avatar--clickable",l&&"designbase-wc-avatar--disabled",m&&"designbase-wc-avatar--loading"];if(t(this,v),b&&!l?(this.setAttribute("role","button"),this.tabIndex=0):(this.removeAttribute("role"),this.removeAttribute("tabindex")),this.toggleAttribute("aria-disabled",l),this.replaceChildren(),m){const t=document.createElement("div");t.className="designbase-wc-avatar__loading";const e=document.createElement("div");e.className="designbase-wc-avatar__skeleton",t.append(e),this.append(t)}if(g){const e=document.createElement("img");e.className="designbase-wc-avatar__image",e.src=h,e.alt=this.getAttribute("alt")||a("아바타 이미지"),e.loading="lazy",e.addEventListener("load",()=>{this.imageLoaded=!0,t(this,v.filter(t=>"designbase-wc-avatar--loading"!==t)),this.querySelector(".designbase-wc-avatar__loading")?.remove()}),e.addEventListener("error",()=>{this.imageFailed=!0,this.imageLoaded=!1,this.render()}),this.append(e)}else if(u){const t=document.createElement("div");if(t.className="designbase-wc-avatar__initials","default"===o){const e=function initialsColor(t){let e=0;for(let a=0;a<t.length;a++)e=t.charCodeAt(a)+((e<<5)-e);const a=Math.abs(e)%d.length;return{backgroundColor:d[a],color:c[a]}}(u);t.style.backgroundColor=e.backgroundColor,t.style.color=e.color}t.textContent=u.charAt(0).toUpperCase(),this.append(t)}else{const t=document.createElement("div");t.className="designbase-wc-avatar__icon",t.append(s("user",function iconSize(t){return"xs"===t?12:"s"===t?16:"m"===t?20:"l"===t?24:"xl"===t?32:40}(e))),this.append(t)}const A=this.getAttribute("status")||"";if(r.includes(A)){const t=document.createElement("span");t.className=`designbase-wc-avatar__status designbase-wc-avatar__status--${A}`,this.append(t)}if(this.hasAttribute("badge")){const t=document.createElement("div");t.className="designbase-wc-avatar__badge";const a=document.createElement("db-badge");a.setAttribute("count",this.getAttribute("badge")||"0");const s=this.getAttribute("badge-type")||"number";a.setAttribute("type",s),this.hasAttribute("badge-max-count")&&a.setAttribute("max-count",this.getAttribute("badge-max-count")),a.setAttribute("variant",this.getAttribute("badge-variant")||"danger"),this.hasAttribute("badge-text")&&(a.textContent=this.getAttribute("badge-text"));const i="xl"===e||"2xl"===e?"m":"s";a.setAttribute("size",i),t.append(a),this.append(t)}}}customElements.get("db-avatar")||customElements.define("db-avatar",DbAvatar);export{DbAvatar};
@@ -8,10 +8,12 @@ interface DbBannerAction {
8
8
  iconOnly?: boolean;
9
9
  }
10
10
  declare class DbBanner extends HTMLElement {
11
+ private unsubscribeLocale?;
11
12
  private clickHandler?;
12
13
  private keydownHandler?;
13
14
  static get observedAttributes(): string[];
14
15
  connectedCallback(): void;
16
+ disconnectedCallback(): void;
15
17
  attributeChangedCallback(): void;
16
18
  private parseActions;
17
19
  private getIconSize;
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{sanitizeHref as t}from"../core/safe-url.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BANNER_SIZES as s,BANNER_VARIANTS as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={primary:"primary",secondary:"secondary",outline:"tertiary",ghost:"ghost"},r={s:"s",sm:"s",m:"m",md:"m",l:"l",lg:"l"};class DbBanner extends HTMLElement{static get observedAttributes(){return["title","description","icon","image","image-alt","actions","size","variant","background-image","href","target","clickable","closable","close-label"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}parseActions(){const e=this.getAttribute("actions");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}getIconSize(e){return"s"===e?16:"l"===e?24:20}getActionIconSize(e){return"s"===e?16:"l"===e?20:18}resolveIconName(e){if(e)return e in{close:1,"info-filled":1}?e:void 0}createActionControl(n,s,i,a){const r=this.resolveIconName(n.icon),o=Boolean(n.iconOnly&&r),c=t(n.href,"");if(c){const t=document.createElement("a");return t.className=`designbase-wc-button designbase-wc-button--${i} designbase-wc-button--${a}`,o&&t.classList.add("designbase-wc-button--icon-only"),t.href=c,t.setAttribute("aria-label",n.text),t.addEventListener("click",e=>e.stopPropagation()),o&&r?t.append(e(r,this.getActionIconSize(a))):t.textContent=n.text,n.external&&(t.target="_blank",t.rel="noopener noreferrer"),t}const l=document.createElement("db-button");return l.setAttribute("variant",i),l.setAttribute("size",a),o?(l.setAttribute("icon-only",""),l.setAttribute("aria-label",n.text),r&&l.append(e(r,this.getActionIconSize(a)))):l.textContent=n.text,(e=>{e.addEventListener("click",e=>e.stopPropagation()),e.addEventListener("db-click",e=>{e.stopPropagation(),this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:s,action:n}}))})})(l),l}render(){const o=this.getAttribute("title")||"",c=this.getAttribute("description")||"",l=this.getAttribute("icon"),d=this.getAttribute("image"),b=this.getAttribute("image-alt")||o||"Banner image",m=n(this.getAttribute("size"),s,"m"),u=n(this.getAttribute("variant"),i,"primary"),p=this.getAttribute("background-image"),h=this.parseActions(),g=this.getAttribute("href"),v=t(g,""),k=this.hasAttribute("clickable")||Boolean(v),A=this.hasAttribute("closable");if(this.className=["designbase-wc-banner",`designbase-wc-banner--${m}`,`designbase-wc-banner--${u}`,k&&"designbase-wc-banner--clickable"].filter(Boolean).join(" "),this.replaceChildren(),this.setupInteractivity(k,v),"image"===u&&p){const e=document.createElement("div");e.className="designbase-wc-banner__background",e.style.backgroundImage=`url(${p})`,e.style.backgroundSize="cover",e.style.backgroundPosition="center",e.style.backgroundRepeat="no-repeat",this.append(e);const t=document.createElement("div");t.className="designbase-wc-banner__overlay",this.append(t)}const w=document.createElement("div");if(w.className="designbase-wc-banner__container",l){const t=document.createElement("div");t.className="designbase-wc-banner__icon",t.append(e(l,this.getIconSize(m))),w.append(t)}if(d){const e=document.createElement("div");e.className="designbase-wc-banner__image";const t=document.createElement("img");t.src=d,t.alt=b,e.append(t),w.append(e)}const E=document.createElement("div");if(E.className="designbase-wc-banner__content",o){const e=document.createElement("h3");e.className="designbase-wc-banner__title",e.textContent=o,E.append(e)}if(c){const e=document.createElement("p");e.className="designbase-wc-banner__description",e.textContent=c,E.append(e)}if(w.append(E),h.length>0){const e=document.createElement("div");e.className="designbase-wc-banner__actions",h.forEach((t,n)=>{const s=a[t.variant||"primary"]||"primary",i=r[t.size||"sm"]||"s";e.append(this.createActionControl(t,n,s,i))}),w.append(e)}A&&w.append(this.createCloseButton(m)),this.append(w)}createCloseButton(t){const n=this.getAttribute("close-label")||"Close",s=document.createElement("button");return s.type="button",s.className="designbase-wc-banner__close",s.setAttribute("aria-label",n),s.append(e("close","l"===t?20:16)),s.addEventListener("click",e=>{e.stopPropagation(),this.handleClose()}),s}handleClose(){const e=new CustomEvent("db-close",{bubbles:!0,composed:!0,cancelable:!0,detail:{}});this.dispatchEvent(e)&&this.remove()}setupInteractivity(e,t){if(this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0),this.keydownHandler&&(this.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=void 0),!e)return this.removeAttribute("role"),void this.removeAttribute("tabindex");this.setAttribute("role","button"),this.hasAttribute("tabindex")||this.setAttribute("tabindex","0");const activate=()=>{const e=this.getAttribute("target")||"_self";this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0,detail:{href:t}})),t&&("_blank"===e?window.open(t,"_blank","noopener,noreferrer"):window.location.assign(t))};this.clickHandler=()=>activate(),this.keydownHandler=e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),activate())},this.addEventListener("click",this.clickHandler),this.addEventListener("keydown",this.keydownHandler)}}customElements.get("db-banner")||customElements.define("db-banner",DbBanner);export{DbBanner};
1
+ import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{createDbIcon as n}from"./db-icons.js";import{sanitizeHref as s}from"../core/safe-url.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BANNER_SIZES as a,BANNER_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const o={primary:"primary",secondary:"secondary",outline:"tertiary",ghost:"ghost"},c={s:"s",sm:"s",m:"m",md:"m",l:"l",lg:"l"};class DbBanner extends HTMLElement{static get observedAttributes(){return["title","description","icon","image","image-alt","actions","size","variant","background-image","href","target","clickable","closable","close-label"]}connectedCallback(){this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{this.querySelector(".designbase-wc-banner__close")?.setAttribute("aria-label",this.getAttribute("close-label")||t("닫기"))})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(){this.render()}parseActions(){const e=this.getAttribute("actions");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}getIconSize(e){return"s"===e?16:"l"===e?24:20}getActionIconSize(e){return"s"===e?16:"l"===e?20:18}resolveIconName(e){if(e)return e in{close:1,"info-filled":1}?e:void 0}createActionControl(e,t,i,a){const r=this.resolveIconName(e.icon),o=Boolean(e.iconOnly&&r),c=s(e.href,"");if(c){const t=document.createElement("a");return t.className=`designbase-wc-button designbase-wc-button--${i} designbase-wc-button--${a}`,o&&t.classList.add("designbase-wc-button--icon-only"),t.href=c,t.setAttribute("aria-label",e.text),t.addEventListener("click",e=>e.stopPropagation()),o&&r?t.append(n(r,this.getActionIconSize(a))):t.textContent=e.text,e.external&&(t.target="_blank",t.rel="noopener noreferrer"),t}const l=document.createElement("db-button");return l.setAttribute("variant",i),l.setAttribute("size",a),o?(l.setAttribute("icon-only",""),l.setAttribute("aria-label",e.text),r&&l.append(n(r,this.getActionIconSize(a)))):l.textContent=e.text,(n=>{n.addEventListener("click",e=>e.stopPropagation()),n.addEventListener("db-click",n=>{n.stopPropagation(),this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:t,action:e}}))})})(l),l}render(){const e=this.getAttribute("title")||"",t=this.getAttribute("description")||"",l=this.getAttribute("icon"),d=this.getAttribute("image"),b=this.getAttribute("image-alt")||e||"Banner image",u=i(this.getAttribute("size"),a,"m"),m=i(this.getAttribute("variant"),r,"primary"),h=this.getAttribute("background-image"),p=this.parseActions(),g=this.getAttribute("href"),v=s(g,""),k=this.hasAttribute("clickable")||Boolean(v),A=this.hasAttribute("closable");if(this.className=["designbase-wc-banner",`designbase-wc-banner--${u}`,`designbase-wc-banner--${m}`,k&&"designbase-wc-banner--clickable"].filter(Boolean).join(" "),this.replaceChildren(),this.setupInteractivity(k,v),"image"===m&&h){const e=document.createElement("div");e.className="designbase-wc-banner__background",e.style.backgroundImage=`url(${h})`,e.style.backgroundSize="cover",e.style.backgroundPosition="center",e.style.backgroundRepeat="no-repeat",this.append(e);const t=document.createElement("div");t.className="designbase-wc-banner__overlay",this.append(t)}const w=document.createElement("div");if(w.className="designbase-wc-banner__container",l){const e=document.createElement("div");e.className="designbase-wc-banner__icon",e.append(n(l,this.getIconSize(u))),w.append(e)}if(d){const e=document.createElement("div");e.className="designbase-wc-banner__image";const t=document.createElement("img");t.src=d,t.alt=b,e.append(t),w.append(e)}const y=document.createElement("div");if(y.className="designbase-wc-banner__content",e){const t=document.createElement("h3");t.className="designbase-wc-banner__title",t.textContent=e,y.append(t)}if(t){const e=document.createElement("p");e.className="designbase-wc-banner__description",e.textContent=t,y.append(e)}if(w.append(y),p.length>0){const e=document.createElement("div");e.className="designbase-wc-banner__actions",p.forEach((t,n)=>{const s=o[t.variant||"primary"]||"primary",i=c[t.size||"sm"]||"s";e.append(this.createActionControl(t,n,s,i))}),w.append(e)}A&&w.append(this.createCloseButton(u)),this.append(w)}createCloseButton(e){const s=this.getAttribute("close-label")||t("닫기"),i=document.createElement("button");return i.type="button",i.className="designbase-wc-banner__close",i.setAttribute("aria-label",s),i.append(n("close","l"===e?20:16)),i.addEventListener("click",e=>{e.stopPropagation(),this.handleClose()}),i}handleClose(){const e=new CustomEvent("db-close",{bubbles:!0,composed:!0,cancelable:!0,detail:{}});this.dispatchEvent(e)&&this.remove()}setupInteractivity(e,t){if(this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0),this.keydownHandler&&(this.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=void 0),!e)return this.removeAttribute("role"),void this.removeAttribute("tabindex");this.setAttribute("role","button"),this.hasAttribute("tabindex")||this.setAttribute("tabindex","0");const activate=()=>{const e=this.getAttribute("target")||"_self";this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0,detail:{href:t}})),t&&("_blank"===e?window.open(t,"_blank","noopener,noreferrer"):window.location.assign(t))};this.clickHandler=()=>activate(),this.keydownHandler=e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),activate())},this.addEventListener("click",this.clickHandler),this.addEventListener("keydown",this.keydownHandler)}}customElements.get("db-banner")||customElements.define("db-banner",DbBanner);export{DbBanner};
@@ -5,6 +5,17 @@
5
5
  * their renderer. This keeps React/Vue slots stable while sharing one element.
6
6
  */
7
7
  declare class DbButton extends HTMLElement {
8
+ static readonly formAssociated = true;
9
+ private readonly internals;
10
+ private formDisabled;
11
+ private spacePressed;
12
+ private syncing;
13
+ private pendingSync;
14
+ private managedLoadingLabel;
15
+ private actionEpoch;
16
+ private implicitSubmitter?;
17
+ private childObserver?;
18
+ private desiredTabIndex;
8
19
  static get observedAttributes(): string[];
9
20
  /**
10
21
  * 계약에 없는 값이 attribute 로 들어오면 기본값으로 되돌린다 — throw 하지 않는다.
@@ -19,8 +30,31 @@ declare class DbButton extends HTMLElement {
19
30
  set radius(value: string);
20
31
  get accentStyle(): string;
21
32
  set accentStyle(value: string);
33
+ get destructiveStyle(): string;
34
+ set destructiveStyle(value: string);
35
+ /** Space-separated display keys, e.g. "⌘ ↵". Bind application shortcuts separately. */
36
+ get shortcut(): string;
37
+ set shortcut(value: string);
22
38
  get type(): string;
23
39
  set type(value: string);
40
+ get form(): HTMLFormElement | null;
41
+ get name(): string;
42
+ set name(value: string);
43
+ get value(): string;
44
+ set value(value: string);
45
+ get formNoValidate(): boolean;
46
+ set formNoValidate(value: boolean);
47
+ get formAction(): string;
48
+ set formAction(value: string);
49
+ get formMethod(): string;
50
+ set formMethod(value: string);
51
+ get formEnctype(): string;
52
+ set formEnctype(value: string);
53
+ get formTarget(): string;
54
+ set formTarget(value: string);
55
+ private get blocked();
56
+ formDisabledCallback(disabled: boolean): void;
57
+ click(): void;
24
58
  get href(): string;
25
59
  set href(value: string);
26
60
  get loadingText(): string;
@@ -35,14 +69,18 @@ declare class DbButton extends HTMLElement {
35
69
  set fullWidth(value: boolean);
36
70
  connectedCallback(): void;
37
71
  disconnectedCallback(): void;
38
- attributeChangedCallback(): void;
72
+ attributeChangedCallback(name?: string, oldValue?: string | null, value?: string | null): void;
39
73
  private handleClick;
74
+ private followLink;
40
75
  private handleKeyDown;
41
76
  private handleKeyUp;
77
+ private handleBlur;
42
78
  private handlePointerDown;
43
79
  private handlePointerUp;
44
80
  private syncAttributes;
45
81
  private getIconSize;
82
+ private syncShortcut;
83
+ private syncImplicitSubmitter;
46
84
  private resolveIconName;
47
85
  private isManagedIconNode;
48
86
  private syncIcons;
@@ -50,7 +88,7 @@ declare class DbButton extends HTMLElement {
50
88
  private syncRadius;
51
89
  private syncAccentStyle;
52
90
  /**
53
- * outline·prism 스타일의 회전하는 테두리 레이어.
91
+ * prism(구 outline) 스타일의 회전하는 테두리 레이어.
54
92
  *
55
93
  * conic-gradient 의 각도를 직접 애니메이션하려면 `@property` 가 필요해 기준선이 올라간다.
56
94
  * 대신 넘치는 정사각형을 `overflow: hidden` 컨테이너 안에서 회전시키고,
@@ -1 +1 @@
1
- import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{sanitizeHref as s}from"../core/safe-url.js";import{coerceWithAliases as i,coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BUTTON_RADII as r,BUTTON_SIZES as a,BUTTON_ACCENT_STYLES as c,BUTTON_VARIANTS as o,BUTTON_VARIANT_ALIASES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const l=["disabled","loading","icon-only","full-width"];class DbButton extends HTMLElement{constructor(){super(...arguments),this.handleClick=t=>{if(this.disabled||this.loading)return t.preventDefault(),void t.stopPropagation();this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}));const e=this.href;if(e){"_blank"===(this.getAttribute("target")||"_self")?window.open(e,"_blank","noopener,noreferrer"):window.location.assign(e)}},this.handleKeyDown=t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed"),this.click())},this.handleKeyUp=t=>{"Enter"!==t.key&&" "!==t.key||this.classList.remove("designbase-wc-button--pressed")},this.handlePointerDown=()=>{this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed")},this.handlePointerUp=()=>{this.classList.remove("designbase-wc-button--pressed")}}static get observedAttributes(){return["variant","size","radius","accent-style","type","href","loading-text","start-icon","end-icon",...l]}get variant(){return i(this.getAttribute("variant"),o,d,"primary")}set variant(t){this.setAttribute("variant",t)}get size(){return n(this.getAttribute("size"),a,"m")}set size(t){this.setAttribute("size",t)}get radius(){const t=this.getAttribute("radius");return t?n(t,r,r[0]):""}set radius(t){t?this.setAttribute("radius",t):this.removeAttribute("radius")}get accentStyle(){return n(this.getAttribute("accent-style"),c,"solid")}set accentStyle(t){t?this.setAttribute("accent-style",t):this.removeAttribute("accent-style")}get type(){return this.getAttribute("type")||"button"}set type(t){this.setAttribute("type",t)}get href(){return s(this.getAttribute("href"),"")}set href(t){t?this.setAttribute("href",t):this.removeAttribute("href")}get loadingText(){return this.getAttribute("loading-text")||""}set loadingText(t){t?this.setAttribute("loading-text",t):this.removeAttribute("loading-text")}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get loading(){return this.hasAttribute("loading")}set loading(t){this.toggleAttribute("loading",t)}get iconOnly(){return this.hasAttribute("icon-only")}set iconOnly(t){this.toggleAttribute("icon-only",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.addEventListener("keyup",this.handleKeyUp),this.addEventListener("pointerdown",this.handlePointerDown),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointerleave",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.syncAttributes()}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown),this.removeEventListener("keyup",this.handleKeyUp),this.removeEventListener("pointerdown",this.handlePointerDown),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointerleave",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){this.syncAttributes()}syncAttributes(){this.classList.add("designbase-wc-button"),this.setAttribute("role","button"),this.setAttribute("aria-disabled",String(this.disabled||this.loading)),this.loading?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy"),this.disabled||this.loading?this.removeAttribute("tabindex"):this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.syncModifier("variant",this.variant),this.syncModifier("size",this.size),this.syncRadius(),this.syncAccentStyle(),this.syncAccentField(),this.syncAccentRing(),this.syncBooleanModifier("disabled"),this.syncBooleanModifier("icon-only"),this.syncBooleanModifier("full-width"),this.syncLoadingVisual(),this.loading?(this.querySelector(":scope > .designbase-wc-button__start-icon")?.remove(),this.querySelector(":scope > .designbase-wc-button__end-icon")?.remove()):this.syncIcons()}getIconSize(){return"s"===this.size?16:"l"===this.size?24:20}resolveIconName(e){if(e&&t(e))return e}isManagedIconNode(t){return t instanceof HTMLElement&&(t.classList.contains("designbase-wc-button__start-icon")||t.classList.contains("designbase-wc-button__end-icon")||t.classList.contains("designbase-wc-button__spinner")||t.classList.contains("designbase-wc-button__accent-field")||t.classList.contains("designbase-wc-button__accent-glass")||t.classList.contains("designbase-wc-button__accent-orb")||t.classList.contains("designbase-wc-button__accent-ring"))}syncIcons(){const t=this.resolveIconName(this.getAttribute("start-icon")),s=this.resolveIconName(this.getAttribute("end-icon")),i=this.getIconSize();let n=this.querySelector(":scope > .designbase-wc-button__start-icon");if(t){if(!n){n=document.createElement("span"),n.className="designbase-wc-button__start-icon",n.setAttribute("aria-hidden","true");const t=Array.from(this.childNodes).find(t=>!this.isManagedIconNode(t));t?this.insertBefore(n,t):this.append(n)}n.replaceChildren(e(t,i))}else n?.remove();let r=this.querySelector(":scope > .designbase-wc-button__end-icon");s?(r||(r=document.createElement("span"),r.className="designbase-wc-button__end-icon",r.setAttribute("aria-hidden","true")),r.replaceChildren(e(s,i)),this.append(r)):r?.remove()}getDefaultRadiusClass(){if(r.includes(this.radius))return`designbase-wc-button--radius-${this.radius}`;const t=a.includes(this.size)?this.size:"m";return`designbase-wc-button--radius-${"s"===t||"l"===t?t:"m"}`}syncRadius(){r.forEach(t=>this.classList.remove(`designbase-wc-button--radius-${t}`)),this.classList.add(this.getDefaultRadiusClass())}syncAccentStyle(){if(c.forEach(t=>this.classList.remove(`designbase-wc-button--accent-${t}`)),"accent"!==this.variant)return;const t=this.accentStyle,e=c.includes(t)?t:"solid";this.classList.add(`designbase-wc-button--accent-${e}`)}syncAccentRing(){const t="accent"===this.variant&&["outline","prism"].includes(this.accentStyle),e=this.querySelector(":scope > .designbase-wc-button__accent-ring");if(!t)return void e?.remove();if(e)return;const s=document.createElement("span");s.className="designbase-wc-button__accent-ring",s.setAttribute("aria-hidden","true");const i=document.createElement("span");i.className="designbase-wc-button__accent-ring-spin",s.appendChild(i),this.insertBefore(s,this.firstChild)}syncAccentField(){const t="accent"===this.variant&&"gradient"===this.accentStyle,e=this.querySelector(":scope > .designbase-wc-button__accent-field"),s=this.querySelector(":scope > .designbase-wc-button__accent-glass");if(!t)return e?.remove(),void s?.remove();let i=e;if(!i){i=document.createElement("span"),i.className="designbase-wc-button__accent-field",i.setAttribute("aria-hidden","true");for(let t=1;t<=5;t+=1){const e=document.createElement("span");e.className=`designbase-wc-button__accent-orb designbase-wc-button__accent-orb--${t}`,i.appendChild(e)}this.insertBefore(i,this.firstChild)}if(!s){const t=document.createElement("span");t.className="designbase-wc-button__accent-glass",t.setAttribute("aria-hidden","true"),i.insertAdjacentElement("afterend",t)}}syncModifier(t,e){if(Array.from(this.classList).filter(e=>e.startsWith(`designbase-wc-button--${t}-`)).forEach(t=>this.classList.remove(t)),"variant"===t||"size"===t){("variant"===t?o:a).forEach(t=>this.classList.remove(`designbase-wc-button--${t}`)),this.classList.add(`designbase-wc-button--${e}`)}}syncBooleanModifier(t){const e=`designbase-wc-button--${t}`;this.classList.toggle(e,this.hasAttribute(t))}getSpinnerSize(){return a.includes(this.size)?this.size:"m"}syncLoadingVisual(){this.classList.toggle("designbase-wc-button--loading",this.loading);const t=this.querySelector(":scope > .designbase-wc-button__spinner");if(!this.loading)return void t?.remove();const e=`designbase-wc-button__spinner designbase-wc-spinner designbase-wc-spinner--circular designbase-wc-spinner--${this.getSpinnerSize()}`;if(t)return t.className=e,void t.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className=e,s.setAttribute("aria-hidden","true"),s.innerHTML='<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>',this.insertBefore(s,this.firstChild)}}customElements.get("db-button")||customElements.define("db-button",DbButton);export{DbButton};
1
+ import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{sanitizeHref as i}from"../core/safe-url.js";import{coerceWithAliases as s,coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BUTTON_RADII as r,BUTTON_SIZES as a,BUTTON_ACCENT_STYLES as o,BUTTON_VARIANTS as c,BUTTON_VARIANT_ALIASES as l,BUTTON_DESTRUCTIVE_STYLES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const h=["disabled","loading","icon-only","full-width"];class DbButton extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.formDisabled=!1,this.spacePressed=!1,this.syncing=!1,this.pendingSync=!1,this.managedLoadingLabel=null,this.actionEpoch=0,this.desiredTabIndex=null,this.handleClick=t=>{if(t.target!==this&&t.target instanceof Element&&t.target.closest('button,a,input,select,textarea,[contenteditable="true"]'))return;if(this.blocked)return t.preventDefault(),void t.stopImmediatePropagation();if(t.defaultPrevented)return;const e=this.actionEpoch,i=new CustomEvent("db-click",{bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(i),setTimeout(()=>{if(e!==this.actionEpoch||t.defaultPrevented||i.defaultPrevented||this.blocked||!this.isConnected)return;if(this.href)return void this.followLink(t);const s=this.form;if(!s)return;if("reset"===this.type)return void HTMLFormElement.prototype.reset.call(s);if("submit"!==this.type)return;const n=document.createElement("button");n.type="submit",n.hidden=!0,n.tabIndex=-1,n.name=this.name,n.value=this.value;for(const t of["formaction","formmethod","formenctype","formtarget","formnovalidate"])this.hasAttribute(t)&&n.setAttribute(t,this.getAttribute(t));n.setAttribute("data-db-submitter",""),s.append(n);try{HTMLFormElement.prototype.requestSubmit.call(s,n)}finally{n.remove()}},0)},this.handleKeyDown=t=>{t.target!==this||t.defaultPrevented||t.isComposing||"Enter"!==t.key&&" "!==t.key||this.href&&" "===t.key||(t.preventDefault(),this.blocked||t.repeat||(this.classList.add("designbase-wc-button--pressed")," "===t.key?this.spacePressed=!0:this.click()))},this.handleKeyUp=t=>{if(t.target!==this||"Enter"!==t.key&&" "!==t.key)return;const e=" "===t.key&&this.spacePressed&&!t.defaultPrevented&&!this.blocked;this.handleBlur(),e&&(t.preventDefault(),this.click())},this.handleBlur=()=>{this.spacePressed=!1,this.classList.remove("designbase-wc-button--pressed")},this.handlePointerDown=()=>{this.blocked||this.classList.add("designbase-wc-button--pressed")},this.handlePointerUp=()=>{this.classList.remove("designbase-wc-button--pressed")}}static get observedAttributes(){return["variant","size","radius","accent-style","destructive-style","shortcut","type","href","loading-text","start-icon","end-icon","tabindex","aria-label","aria-labelledby","form","name","value","formaction","formmethod","formenctype","formtarget","formnovalidate","target","rel","download",...h]}get variant(){return s(this.getAttribute("variant"),c,l,"primary")}set variant(t){this.setAttribute("variant",t)}get size(){return n(this.getAttribute("size"),a,"m")}set size(t){this.setAttribute("size",t)}get radius(){const t=this.getAttribute("radius");return t?n(t,r,r[0]):""}set radius(t){t?this.setAttribute("radius",t):this.removeAttribute("radius")}get accentStyle(){return n(this.getAttribute("accent-style"),o,"solid")}set accentStyle(t){t?this.setAttribute("accent-style",t):this.removeAttribute("accent-style")}get destructiveStyle(){return n(this.getAttribute("destructive-style"),d,"solid")}set destructiveStyle(t){this.setAttribute("destructive-style",t)}get shortcut(){return this.getAttribute("shortcut")||""}set shortcut(t){t?this.setAttribute("shortcut",t):this.removeAttribute("shortcut")}get type(){const t=this.getAttribute("type")?.toLowerCase();return"submit"===t||"reset"===t?t:"button"}set type(t){this.setAttribute("type",t)}get form(){return this.internals.form}get name(){return this.getAttribute("name")||""}set name(t){this.setAttribute("name",t)}get value(){return this.getAttribute("value")||""}set value(t){this.setAttribute("value",t)}get formNoValidate(){return this.hasAttribute("formnovalidate")}set formNoValidate(t){this.toggleAttribute("formnovalidate",t)}get formAction(){return this.getAttribute("formaction")||""}set formAction(t){this.setAttribute("formaction",t)}get formMethod(){return this.getAttribute("formmethod")||""}set formMethod(t){this.setAttribute("formmethod",t)}get formEnctype(){return this.getAttribute("formenctype")||""}set formEnctype(t){this.setAttribute("formenctype",t)}get formTarget(){return this.getAttribute("formtarget")||""}set formTarget(t){this.setAttribute("formtarget",t)}get blocked(){return this.disabled||this.loading||this.formDisabled}formDisabledCallback(t){this.formDisabled!==t&&(this.formDisabled=t,this.syncing?this.pendingSync=!0:this.syncAttributes())}click(){this.blocked||super.click()}get href(){return i(this.getAttribute("href"),"")}set href(t){t?this.setAttribute("href",t):this.removeAttribute("href")}get loadingText(){return this.getAttribute("loading-text")||""}set loadingText(t){t?this.setAttribute("loading-text",t):this.removeAttribute("loading-text")}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get loading(){return this.hasAttribute("loading")}set loading(t){this.toggleAttribute("loading",t)}get iconOnly(){return this.hasAttribute("icon-only")}set iconOnly(t){this.toggleAttribute("icon-only",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){for(const t of["variant","size","radius","accentStyle","destructiveStyle","shortcut","type","href","loadingText","disabled","loading","iconOnly","fullWidth","name","value","formNoValidate","formAction","formMethod","formEnctype","formTarget"])if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.addEventListener("keyup",this.handleKeyUp),this.addEventListener("pointerdown",this.handlePointerDown),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointerleave",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.addEventListener("blur",this.handleBlur),this.syncAttributes(),this.childObserver??(this.childObserver=new MutationObserver(t=>{t.some(t=>Array.from(t.removedNodes).some(t=>(this.isManagedIconNode(t)||t instanceof Element&&t.classList.contains("designbase-wc-button__shortcut"))&&t.parentNode!==this))&&this.syncAttributes()})),this.childObserver.observe(this,{childList:!0})}disconnectedCallback(){this.actionEpoch++,this.childObserver?.disconnect(),this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown),this.removeEventListener("keyup",this.handleKeyUp),this.removeEventListener("pointerdown",this.handlePointerDown),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointerleave",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp),this.removeEventListener("blur",this.handleBlur),this.handleBlur()}attributeChangedCallback(t,e,i){this.syncing||t&&e===i||("tabindex"===t&&(this.desiredTabIndex=i??null),"aria-label"===t&&i!==this.managedLoadingLabel&&(this.managedLoadingLabel=null),this.syncAttributes())}followLink(t){const e=document.createElement("a");e.href=this.href,e.hidden=!0;for(const t of["target","download","rel"])this.hasAttribute(t)&&e.setAttribute(t,this.getAttribute(t));"_blank"===e.target&&(e.rel=`${e.rel} noopener noreferrer`.trim()),document.body.append(e);try{e.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,ctrlKey:t.ctrlKey,metaKey:t.metaKey,shiftKey:t.shiftKey,altKey:t.altKey,button:t.button}))}finally{e.remove()}}syncAttributes(){if(!this.syncing){this.syncing=!0;try{this.classList.add("designbase-wc-button"),this.setAttribute("role",this.href?"link":"button"),this.setAttribute("aria-disabled",String(this.blocked)),this.loading?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy"),this.setAttribute("tabindex",this.blocked?"-1":this.desiredTabIndex??"0"),this.blocked&&(this.actionEpoch++,this.handleBlur()),this.syncModifier("variant",this.variant),this.syncModifier("size",this.size),this.syncRadius(),this.classList.toggle("designbase-wc-button--destructive-soft","destructive"===this.variant&&"soft"===this.destructiveStyle),this.syncShortcut(),this.syncAccentStyle(),this.syncAccentField(),this.syncAccentRing(),this.syncBooleanModifier("disabled"),this.classList.toggle("designbase-wc-button--disabled",this.disabled||this.formDisabled),this.syncBooleanModifier("icon-only"),this.syncBooleanModifier("full-width"),this.syncLoadingVisual(),this.syncImplicitSubmitter(),this.loading?(this.querySelector(":scope > .designbase-wc-button__start-icon")?.remove(),this.querySelector(":scope > .designbase-wc-button__end-icon")?.remove()):this.syncIcons()}finally{this.syncing=!1,this.pendingSync&&(this.pendingSync=!1,this.syncAttributes())}}}getIconSize(){return"s"===this.size?16:"l"===this.size?24:20}syncShortcut(){let t=this.querySelector(":scope > .designbase-wc-button__shortcut");const e=this.shortcut.trim().split(/\s+/).filter(Boolean);!e.length||this.iconOnly||this.loading?t?.remove():t?.dataset.keys!==JSON.stringify(e)&&(t||(t=document.createElement("span"),t.className="designbase-wc-button__shortcut",t.setAttribute("aria-hidden","true"),this.append(t)),t.dataset.keys=JSON.stringify(e),t.replaceChildren(...e.map(t=>{const e=document.createElement("kbd");return e.textContent=t,e})))}syncImplicitSubmitter(){if("submit"!==this.type||this.href)return this.implicitSubmitter?.remove(),void(this.implicitSubmitter=void 0);if(!this.implicitSubmitter){const t=document.createElement("button");t.type="submit",t.hidden=!0,t.style.display="none",t.tabIndex=-1,t.className="designbase-wc-button__submit-proxy",t.setAttribute("aria-hidden","true"),t.setAttribute("data-db-implicit-submitter",""),t.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.click()}),this.implicitSubmitter=t}this.implicitSubmitter.disabled=this.blocked,this.hasAttribute("form")?this.implicitSubmitter.setAttribute("form",this.getAttribute("form")):this.implicitSubmitter.removeAttribute("form"),this.implicitSubmitter.parentElement!==this&&this.append(this.implicitSubmitter)}resolveIconName(e){if(e&&t(e))return e}isManagedIconNode(t){return t instanceof HTMLElement&&(t.classList.contains("designbase-wc-button__start-icon")||t.classList.contains("designbase-wc-button__end-icon")||t.classList.contains("designbase-wc-button__spinner")||t.classList.contains("designbase-wc-button__loading-label")||t.classList.contains("designbase-wc-button__submit-proxy")||t.classList.contains("designbase-wc-button__accent-field")||t.classList.contains("designbase-wc-button__accent-glass")||t.classList.contains("designbase-wc-button__accent-orb")||t.classList.contains("designbase-wc-button__accent-ring"))}syncIcons(){const t=this.resolveIconName(this.getAttribute("start-icon")),i=this.resolveIconName(this.getAttribute("end-icon")),s=this.getIconSize();let n=this.querySelector(":scope > .designbase-wc-button__start-icon");if(t){if(!n){n=document.createElement("span"),n.className="designbase-wc-button__start-icon",n.setAttribute("aria-hidden","true");const t=Array.from(this.childNodes).find(t=>!this.isManagedIconNode(t));t?this.insertBefore(n,t):this.append(n)}n.replaceChildren(e(t,s))}else n?.remove();let r=this.querySelector(":scope > .designbase-wc-button__end-icon");i?(r||(r=document.createElement("span"),r.className="designbase-wc-button__end-icon",r.setAttribute("aria-hidden","true")),r.replaceChildren(e(i,s)),this.append(r)):r?.remove()}getDefaultRadiusClass(){if(r.includes(this.radius))return`designbase-wc-button--radius-${this.radius}`;const t=a.includes(this.size)?this.size:"m";return`designbase-wc-button--radius-${"s"===t||"l"===t?t:"m"}`}syncRadius(){r.forEach(t=>this.classList.remove(`designbase-wc-button--radius-${t}`)),this.classList.add(this.getDefaultRadiusClass())}syncAccentStyle(){if(o.forEach(t=>this.classList.remove(`designbase-wc-button--accent-${t}`)),"accent"!==this.variant)return;const t=this.accentStyle,e="outline"===t?"prism":o.includes(t)?t:"solid";this.classList.add(`designbase-wc-button--accent-${e}`)}syncAccentRing(){const t="accent"===this.variant&&["outline","prism"].includes(this.accentStyle),e=this.querySelector(":scope > .designbase-wc-button__accent-ring");if(!t)return void e?.remove();if(e)return;const i=document.createElement("span");i.className="designbase-wc-button__accent-ring",i.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className="designbase-wc-button__accent-ring-spin",i.appendChild(s),this.insertBefore(i,this.firstChild)}syncAccentField(){const t="accent"===this.variant&&"gradient"===this.accentStyle,e=this.querySelector(":scope > .designbase-wc-button__accent-field"),i=this.querySelector(":scope > .designbase-wc-button__accent-glass");if(!t)return e?.remove(),void i?.remove();let s=e;if(!s){s=document.createElement("span"),s.className="designbase-wc-button__accent-field",s.setAttribute("aria-hidden","true");for(let t=1;t<=5;t+=1){const e=document.createElement("span");e.className=`designbase-wc-button__accent-orb designbase-wc-button__accent-orb--${t}`,s.appendChild(e)}this.insertBefore(s,this.firstChild)}if(!i){const t=document.createElement("span");t.className="designbase-wc-button__accent-glass",t.setAttribute("aria-hidden","true"),s.insertAdjacentElement("afterend",t)}}syncModifier(t,e){if(Array.from(this.classList).filter(e=>e.startsWith(`designbase-wc-button--${t}-`)).forEach(t=>this.classList.remove(t)),"variant"===t||"size"===t){("variant"===t?c:a).forEach(t=>this.classList.remove(`designbase-wc-button--${t}`)),this.classList.add(`designbase-wc-button--${e}`)}}syncBooleanModifier(t){const e=`designbase-wc-button--${t}`;this.classList.toggle(e,this.hasAttribute(t))}getSpinnerSize(){return a.includes(this.size)?this.size:"m"}syncLoadingVisual(){this.classList.toggle("designbase-wc-button--loading",this.loading);const t=this.loading&&!!this.loadingText;this.classList.toggle("designbase-wc-button--loading-text",t);const e=this.getAttribute("aria-label");!t||this.hasAttribute("aria-labelledby")||this.hasAttribute("aria-label")&&e!==this.managedLoadingLabel?null!==this.managedLoadingLabel&&(e===this.managedLoadingLabel&&this.removeAttribute("aria-label"),this.managedLoadingLabel=null):(this.managedLoadingLabel=this.loadingText,this.setAttribute("aria-label",this.loadingText));let i=this.querySelector(":scope > .designbase-wc-button__loading-label");t?(i||(i=document.createElement("span"),i.className="designbase-wc-button__loading-label",i.setAttribute("aria-hidden","true"),this.append(i)),i.textContent=this.loadingText):i?.remove();const s=this.querySelector(":scope > .designbase-wc-button__spinner");if(!this.loading)return void s?.remove();const n=`designbase-wc-button__spinner designbase-wc-spinner designbase-wc-spinner--circular designbase-wc-spinner--${this.getSpinnerSize()}`;if(s)return s.className=n,void s.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className=n,r.setAttribute("aria-hidden","true"),r.innerHTML='<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>',this.insertBefore(r,this.firstChild)}}DbButton.formAssociated=!0,customElements.get("db-button")||customElements.define("db-button",DbButton);export{DbButton};
@@ -21,9 +21,12 @@ type CalendarEventData = {
21
21
  declare class DbCalendar extends HTMLElement {
22
22
  static get observedAttributes(): string[];
23
23
  private built;
24
+ private unsubscribeLocale?;
24
25
  private headerEl?;
25
26
  private bodyEl?;
26
27
  private modalEl?;
28
+ private modalBody?;
29
+ private modalFooter?;
27
30
  private currentView;
28
31
  private selectedDate;
29
32
  private _events;
@@ -35,6 +38,7 @@ declare class DbCalendar extends HTMLElement {
35
38
  private selectedDateRange;
36
39
  private eventForm;
37
40
  connectedCallback(): void;
41
+ disconnectedCallback(): void;
38
42
  attributeChangedCallback(): void;
39
43
  get locale(): string;
40
44
  set locale(value: string);
@@ -67,6 +71,7 @@ declare class DbCalendar extends HTMLElement {
67
71
  private renderYearView;
68
72
  private renderWeekView;
69
73
  private renderModal;
74
+ private syncLocale;
70
75
  private render;
71
76
  }
72
77
  declare global {
@@ -1 +1 @@
1
- import{dbText as e}from"../core/i18n.js";import{createDbIcon as t,getDbComponentIconSize as a}from"./db-icons.js";import{resolveDateLocale as n,parseISODate as s,toISODate as i}from"./date-picker-utils.js";import"./db-modal.js";import"./db-input.js";import"./db-select.js";import"./db-date-picker.js";import"./db-time-picker.js";import"./db-button.js";const d="designbase-wc-calendar";class DbCalendar extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.currentView="month",this.selectedDate=new Date,this._events=[],this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.draggedEvent=null,this.dragOverDate=null,this.selectedDateRange={start:null,end:null},this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""}}static get observedAttributes(){return["view","current-date","events","locale","show-weekends","highlight-today","show-outside-days"]}connectedCallback(){this.built||this.build(),this.readAttributes(),this.render()}attributeChangedCallback(){this.built&&(this.readAttributes(),this.render())}get locale(){return n(this.getAttribute("locale"))}set locale(e){this.setAttribute("locale",e||"")}get showWeekends(){return"false"!==this.getAttribute("show-weekends")}get highlightToday(){return"false"!==this.getAttribute("highlight-today")}get showOutsideDays(){return"false"!==this.getAttribute("show-outside-days")}get events(){return this._events}set events(e){"string"!=typeof e?(this._events=Array.isArray(e)?e:[],this.setAttribute("events",JSON.stringify(this._events))):this.setAttribute("events",e)}build(){this.built=!0,this.headerEl=document.createElement("div"),this.headerEl.className=`${d}__header`,this.bodyEl=document.createElement("div"),this.bodyEl.className=`${d}__body`,this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","m"),this.modalEl.addEventListener("db-close",()=>this.closeModal())}readAttributes(){this.currentView="month";const e=s(this.getAttribute("current-date"));e&&(this.selectedDate=e);const t=this.getAttribute("events");if(t)try{const e=JSON.parse(t);this._events=Array.isArray(e)?e:[]}catch{this._events=[]}else this._events=[]}isSameDate(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}eventsForDate(e){return this._events.filter(t=>{const a=s(t.date);return!!a&&this.isSameDate(a,e)})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}handleViewChange(e){this.currentView="month",this.emit("db-view-change",{view:e}),this.render()}shiftMonth(e){const t=new Date(this.selectedDate);t.setMonth(t.getMonth()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}shiftYear(e){const t=new Date(this.selectedDate);t.setFullYear(t.getFullYear()+e),this.selectedDate=t,this.emit("db-month-change",{date:i(t)}),this.render()}handleDateClick(e){this.selectedDate=e,this.emit("db-date-click",{date:i(e)}),!this.selectedDateRange.start||this.selectedDateRange.start&&this.selectedDateRange.end?this.selectedDateRange={start:e,end:null}:this.selectedDateRange.start&&!this.selectedDateRange.end&&(e<this.selectedDateRange.start?this.selectedDateRange={start:e,end:this.selectedDateRange.start}:this.selectedDateRange={start:this.selectedDateRange.start,end:e}),this.openAddModal(e)}handleDragStart(e,t){this.draggedEvent=e,t.dataTransfer?.setData("text/plain",e.id),t.dataTransfer?.setData("application/json",JSON.stringify(e)),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")}handleDragOver(e,t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"),this.dragOverDate=e,this.render()}handleDragLeave(e){const t=e.relatedTarget,a=e.currentTarget;a&&t&&a.contains(t)||(this.dragOverDate=null,this.render())}handleDrop(e,t){if(t.preventDefault(),!this.draggedEvent)return;const a={...this.draggedEvent,date:i(e)};this.emit("db-event-edit",{event:a}),this.draggedEvent=null,this.dragOverDate=null,this.render()}handleDragEnd(){this.draggedEvent=null,this.dragOverDate=null,this.render()}handleEventClick(e,t){t.stopPropagation(),this.selectedEvent=e,this.isEditing=!0;const a=s(e.date);a&&(this.selectedDate=a),this.eventForm={title:e.title,description:e.description||"",startTime:e.startTime||"09:00",endTime:e.endTime||"10:00",type:e.type,color:e.color||"#17a2b8",isAllDay:e.isAllDay||!1,location:e.location||""},this.emit("db-event-click",{event:e}),this.showEventModal=!0,this.render()}openAddModal(e){this.selectedDate=e,this.selectedEvent=null,this.isEditing=!1,this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""},this.showEventModal=!0,this.render()}closeModal(){this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.render()}saveEvent(){if(!this.eventForm.title.trim())return void window.alert("제목을 입력해주세요.");const e={title:this.eventForm.title.trim(),description:this.eventForm.description,date:i(this.selectedDate),startTime:this.eventForm.startTime,endTime:this.eventForm.endTime,type:this.eventForm.type,color:this.eventForm.color,isAllDay:this.eventForm.isAllDay,location:this.eventForm.location};if(this.isEditing&&this.selectedEvent){const t={...this.selectedEvent,...e};this.emit("db-event-edit",{event:t})}else this.emit("db-event-add",{event:e});this.closeModal()}deleteEvent(){this.selectedEvent&&window.confirm("정말로 이 일정을 삭제하시겠습니까?")&&(this.emit("db-event-delete",{eventId:this.selectedEvent.id}),this.closeModal())}renderHeader(){if(!this.headerEl)return;this.headerEl.replaceChildren();const n=document.createElement("div");n.className=`${d}__navigation`;const s=a("m"),i=document.createElement("button");i.type="button",i.className=`${d}__nav-button`,i.setAttribute("aria-label",e("이전")),i.appendChild(t("chevron-left",s)),i.addEventListener("click",()=>{this.shiftMonth(-1)});const l=document.createElement("div");l.className=`${d}__title`,l.textContent=this.selectedDate.toLocaleDateString(this.locale,{year:"numeric",month:"long"});const r=document.createElement("button");r.type="button",r.className=`${d}__nav-button`,r.setAttribute("aria-label",e("다음")),r.appendChild(t("chevron-right",s)),r.addEventListener("click",()=>{this.shiftMonth(1)}),n.append(i,l,r),this.headerEl.appendChild(n)}renderMonthView(){const e=document.createElement("div");e.className=`${d}__month-view`;const t=document.createElement("div");t.className=`${d}__weekdays`,["일","월","화","수","목","금","토"].forEach(e=>{const a=document.createElement("div");a.className=`${d}__weekday`,a.textContent=e,t.appendChild(a)}),e.appendChild(t);const a=document.createElement("div");a.className=`${d}__days`;const n=this.selectedDate.getFullYear(),s=this.selectedDate.getMonth(),i=new Date(n,s,1),l=new Date(i);l.setDate(l.getDate()-i.getDay());const r=new Date;for(let e=0;e<42;e+=1){const t=new Date(l);t.setDate(l.getDate()+e);const n=t.getMonth()===s;if(!this.showOutsideDays&&!n)continue;const i=0===t.getDay()||6===t.getDay();if(!this.showWeekends&&i)continue;const o=document.createElement("div"),c=this.selectedDateRange.start&&this.selectedDateRange.end&&t>=this.selectedDateRange.start&&t<=this.selectedDateRange.end,h=this.selectedDateRange.start&&t.toDateString()===this.selectedDateRange.start.toDateString(),m=this.selectedDateRange.end&&t.toDateString()===this.selectedDateRange.end.toDateString(),u=Boolean(c&&!h&&!m);o.className=[`${d}__day`,n&&`${d}__day--current-month`,this.highlightToday&&t.toDateString()===r.toDateString()&&`${d}__day--today`,this.isSameDate(t,this.selectedDate)&&`${d}__day--selected`,h&&`${d}__day--selected--start`,m&&`${d}__day--selected--end`,u&&`${d}__day--selected--middle`,!this.showWeekends&&i&&`${d}__day--weekend`].filter(Boolean).join(" "),o.addEventListener("click",()=>this.handleDateClick(t));const v=document.createElement("span");v.className=`${d}__day-number`,v.textContent=String(t.getDate()),o.appendChild(v);const p=this.eventsForDate(t);if(p.length){const e=document.createElement("div");if(e.className=`${d}__day-events`,p.slice(0,2).forEach(t=>{const a=document.createElement("div");a.className=[`${d}__event-bar`,`${d}__event-bar--${t.type}`].filter(Boolean).join(" "),t.color&&(a.style.backgroundColor=t.color),this.draggedEvent?.id===t.id&&a.classList.add(`${d}__event-bar--dragging`),a.title=t.title,a.draggable=!0;const n=document.createElement("span");n.className=`${d}__event-title`,n.textContent=t.title,a.appendChild(n),a.addEventListener("click",e=>this.handleEventClick(t,e)),a.addEventListener("dragstart",e=>this.handleDragStart(t,e)),a.addEventListener("dragend",()=>this.handleDragEnd()),e.appendChild(a)}),p.length>2){const t=document.createElement("div");t.className=`${d}__more-events`,t.textContent=`+${p.length-2} more`,e.appendChild(t)}o.appendChild(e)}const g=document.createElement("div");g.className=[`${d}__drop-zone`,this.dragOverDate&&this.isSameDate(this.dragOverDate,t)&&`${d}__drop-zone--active`].filter(Boolean).join(" "),g.addEventListener("dragover",e=>this.handleDragOver(t,e)),g.addEventListener("dragleave",e=>this.handleDragLeave(e)),g.addEventListener("drop",e=>this.handleDrop(t,e)),o.appendChild(g),a.appendChild(o)}return e.appendChild(a),e}renderYearView(){const e=document.createElement("div");e.className=`${d}__year-view`;const t=this.selectedDate.getFullYear();for(let a=0;a<12;a+=1){const n=new Date(t,a,1),i=this._events.filter(e=>{const n=s(e.date);return n&&n.getFullYear()===t&&n.getMonth()===a}),l=document.createElement("div");l.className=`${d}__year-month`,l.addEventListener("click",()=>{this.selectedDate=n,this.handleViewChange("month")});const r=document.createElement("h3");if(r.className=`${d}__year-month-title`,r.textContent=n.toLocaleDateString(this.locale,{month:"long"}),l.appendChild(r),i.length){const e=document.createElement("div");if(e.className=`${d}__year-month-events`,i.slice(0,4).forEach(t=>{const a=document.createElement("span");a.className=[`${d}__year-event`,`${d}__year-event--${t.type}`].join(" "),t.color&&(a.style.backgroundColor=t.color),e.appendChild(a)}),i.length>4){const t=document.createElement("span");t.className=`${d}__year-more-events`,t.textContent=`+${i.length-4} more`,e.appendChild(t)}l.appendChild(e)}e.appendChild(l)}return e}renderWeekView(){const e=document.createElement("div");e.className=`${d}__week-view`;const t=new Date,a=new Date(this.selectedDate);a.setDate(this.selectedDate.getDate()-this.selectedDate.getDay());const n=document.createElement("div");n.className=`${d}__week-header`;const s=document.createElement("div");s.className=`${d}__time-column-header`,n.appendChild(s);for(let e=0;e<7;e+=1){const s=new Date(a);s.setDate(a.getDate()+e);const i=document.createElement("div");i.className=[`${d}__week-day-header`,s.toDateString()===t.toDateString()&&`${d}__week-day-header--today`].filter(Boolean).join(" ");const l=document.createElement("span");l.className=`${d}__week-day-name`,l.textContent=s.toLocaleDateString(this.locale,{weekday:"short"});const r=document.createElement("span");r.className=`${d}__week-day-number`,r.textContent=String(s.getDate()),i.append(l,r),n.appendChild(i)}e.appendChild(n);const i=document.createElement("div");i.className=`${d}__week-grid`;const l=document.createElement("div");l.className=`${d}__week-time-column`;for(let e=6;e<=22;e+=1){const t=document.createElement("div");t.className=`${d}__time-slot`;const a=document.createElement("span");a.className=`${d}__time-label`,a.textContent=`${String(e).padStart(2,"0")}:00`,t.appendChild(a),l.appendChild(t)}i.appendChild(l);const r=document.createElement("div");r.className=`${d}__week-columns`;for(let e=0;e<7;e+=1){const t=new Date(a);t.setDate(a.getDate()+e);const n=document.createElement("div");n.className=`${d}__week-column`;for(let e=6;e<=22;e+=1){const a=document.createElement("div");a.className=`${d}__week-cell`,a.title=`${t.toLocaleDateString()} ${String(e).padStart(2,"0")}:00`,a.addEventListener("click",()=>{this.selectedDate=new Date(t),this.eventForm.startTime=`${String(e).padStart(2,"0")}:00`,this.eventForm.endTime=`${String(e+1).padStart(2,"0")}:00`,this.openAddModal(this.selectedDate)}),n.appendChild(a)}this.eventsForDate(t).forEach(e=>{if(!e.startTime)return;const[t,a]=e.startTime.split(":").map(Number),s=.8*(60*(t-6)+(a||0)),i=(e.endTime||e.startTime).split(":").map(Number),l=60*(i[0]||t)+(i[1]||0),r=60*t+(a||0),o=Math.max(20,48*(l-r)/60),c=document.createElement("div");c.className=[`${d}__week-event`,`${d}__week-event--${e.type}`].filter(Boolean).join(" "),c.textContent=e.title,c.title=e.title,c.style.backgroundColor=e.color||"#17a2b8",c.style.top=`${s}px`,c.style.height=`${o}px`,c.addEventListener("click",t=>this.handleEventClick(e,t)),n.appendChild(c)}),r.appendChild(n)}return i.appendChild(r),e.appendChild(i),e}renderModal(){if(!this.modalEl)return;if(this.modalEl.replaceChildren(),!this.showEventModal)return void this.modalEl.removeAttribute("open");this.modalEl.setAttribute("open","true"),this.modalEl.setAttribute("title",this.isEditing?"일정 편집":"새 일정 추가");const t=document.createElement("div");t.className=`${d}__event-form`;const a=document.createElement("db-input");a.setAttribute("label","제목 *"),a.setAttribute("placeholder",e("일정 제목을 입력하세요")),a.setAttribute("full-width",""),a.setAttribute("value",this.eventForm.title),a.addEventListener("db-input",e=>{this.eventForm.title=e.detail.value});const n=document.createElement("db-input");n.setAttribute("label","설명"),n.setAttribute("placeholder",e("일정 설명을 입력하세요")),n.setAttribute("full-width",""),n.setAttribute("value",this.eventForm.description),n.addEventListener("db-input",e=>{this.eventForm.description=e.detail.value});const l=document.createElement("db-date-picker");l.setAttribute("label","날짜"),l.setAttribute("full-width",""),l.setAttribute("value",i(this.selectedDate)),l.addEventListener("db-change",e=>{const t=s(e.detail.value);t&&(this.selectedDate=t)});const r=document.createElement("db-select");r.setAttribute("label","일정 타입"),r.setAttribute("full-width",""),r.setAttribute("options",JSON.stringify([{value:"meeting",label:e("회의")},{value:"task",label:e("업무")},{value:"reminder",label:e("알림")},{value:"birthday",label:e("생일")},{value:"holiday",label:e("휴일")},{value:"custom",label:e("기타")}])),r.setAttribute("value",this.eventForm.type),r.addEventListener("db-change",e=>{this.eventForm.type=e.detail.value});const o=document.createElement("db-select");o.setAttribute("label","색상"),o.setAttribute("full-width",""),o.setAttribute("options",JSON.stringify([{value:"#17a2b8",label:e("청록")},{value:"#0d6efd",label:e("파랑")},{value:"#198754",label:e("초록")},{value:"#ffc107",label:e("노랑")},{value:"#dc3545",label:e("빨강")},{value:"#6f42c1",label:e("보라")}])),o.setAttribute("value",this.eventForm.color),o.addEventListener("db-change",e=>{this.eventForm.color=e.detail.value});const c=document.createElement("db-time-picker");c.setAttribute("label","시작 시간"),c.setAttribute("full-width",""),c.setAttribute("value",this.eventForm.startTime),c.addEventListener("db-change",e=>{this.eventForm.startTime=e.detail.value});const h=document.createElement("db-time-picker");h.setAttribute("label","종료 시간"),h.setAttribute("full-width",""),h.setAttribute("value",this.eventForm.endTime),h.addEventListener("db-change",e=>{this.eventForm.endTime=e.detail.value}),t.append(a,n,l,r,o,c,h);const m=document.createElement("div");m.className="designbase-wc-modal__body",m.setAttribute("data-modal-part","body"),m.appendChild(t);const u=document.createElement("div");u.className="designbase-wc-modal__footer",u.setAttribute("data-modal-part","footer");const v=document.createElement("div");if(v.className=`${d}__modal-actions`,this.isEditing){const t=document.createElement("db-button");t.setAttribute("variant","destructive"),t.textContent=e("삭제"),t.addEventListener("click",()=>this.deleteEvent()),v.appendChild(t)}const p=document.createElement("div");p.className=`${d}__modal-buttons`;const g=document.createElement("db-button");g.setAttribute("variant","secondary"),g.textContent=e("취소"),g.addEventListener("click",()=>this.closeModal());const b=document.createElement("db-button");b.setAttribute("variant","primary"),b.textContent=this.isEditing?"수정":"저장",b.addEventListener("click",()=>this.saveEvent()),p.append(g,b),v.appendChild(p),u.appendChild(v),this.modalEl.append(m,u)}render(){this.className=d,this.replaceChildren(),this.headerEl&&this.bodyEl&&(this.renderHeader(),this.bodyEl.replaceChildren(),this.bodyEl.appendChild(this.renderMonthView()),this.append(this.headerEl,this.bodyEl),this.renderModal(),this.showEventModal&&this.modalEl&&this.appendChild(this.modalEl))}}customElements.get("db-calendar")||customElements.define("db-calendar",DbCalendar);export{DbCalendar};
1
+ import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{createDbIcon as a,getDbComponentIconSize as n}from"./db-icons.js";import{resolveDateLocale as s,parseISODate as i,toISODate as l}from"./date-picker-utils.js";import"./db-modal.js";import"./db-input.js";import"./db-select.js";import"./db-date-picker.js";import"./db-time-picker.js";import"./db-button.js";const d="designbase-wc-calendar",EVENT_TYPE_OPTIONS=()=>[{value:"meeting",label:t("회의")},{value:"task",label:t("업무")},{value:"reminder",label:t("알림")},{value:"birthday",label:t("생일")},{value:"holiday",label:t("휴일")},{value:"custom",label:t("기타")}],COLOR_OPTIONS=()=>[{value:"#17a2b8",label:t("청록")},{value:"#0d6efd",label:t("파랑")},{value:"#198754",label:t("초록")},{value:"#ffc107",label:t("노랑")},{value:"#dc3545",label:t("빨강")},{value:"#6f42c1",label:t("보라")}];class DbCalendar extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.currentView="month",this.selectedDate=new Date,this._events=[],this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.draggedEvent=null,this.dragOverDate=null,this.selectedDateRange={start:null,end:null},this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""}}static get observedAttributes(){return["view","current-date","events","locale","show-weekends","highlight-today","show-outside-days"]}connectedCallback(){this.built||this.build(),this.readAttributes(),this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(){this.built&&(this.readAttributes(),this.render())}get locale(){return s(this.getAttribute("locale"))}set locale(e){this.setAttribute("locale",e||"")}get showWeekends(){return"false"!==this.getAttribute("show-weekends")}get highlightToday(){return"false"!==this.getAttribute("highlight-today")}get showOutsideDays(){return"false"!==this.getAttribute("show-outside-days")}get events(){return this._events}set events(e){"string"!=typeof e?(this._events=Array.isArray(e)?e:[],this.setAttribute("events",JSON.stringify(this._events))):this.setAttribute("events",e)}build(){this.built=!0,this.headerEl=document.createElement("div"),this.headerEl.className=`${d}__header`,this.bodyEl=document.createElement("div"),this.bodyEl.className=`${d}__body`,this.modalEl=document.createElement("db-modal"),this.modalEl.setAttribute("size","m"),this.modalEl.addEventListener("db-close",()=>this.closeModal())}readAttributes(){this.currentView="month";const e=i(this.getAttribute("current-date"));e&&(this.selectedDate=e);const t=this.getAttribute("events");if(t)try{const e=JSON.parse(t);this._events=Array.isArray(e)?e:[]}catch{this._events=[]}else this._events=[]}isSameDate(e,t){return e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate()}eventsForDate(e){return this._events.filter(t=>{const a=i(t.date);return!!a&&this.isSameDate(a,e)})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}handleViewChange(e){this.currentView="month",this.emit("db-view-change",{view:e}),this.render()}shiftMonth(e){const t=new Date(this.selectedDate);t.setMonth(t.getMonth()+e),this.selectedDate=t,this.emit("db-month-change",{date:l(t)}),this.render()}shiftYear(e){const t=new Date(this.selectedDate);t.setFullYear(t.getFullYear()+e),this.selectedDate=t,this.emit("db-month-change",{date:l(t)}),this.render()}handleDateClick(e){this.selectedDate=e,this.emit("db-date-click",{date:l(e)}),!this.selectedDateRange.start||this.selectedDateRange.start&&this.selectedDateRange.end?this.selectedDateRange={start:e,end:null}:this.selectedDateRange.start&&!this.selectedDateRange.end&&(e<this.selectedDateRange.start?this.selectedDateRange={start:e,end:this.selectedDateRange.start}:this.selectedDateRange={start:this.selectedDateRange.start,end:e}),this.openAddModal(e)}handleDragStart(e,t){this.draggedEvent=e,t.dataTransfer?.setData("text/plain",e.id),t.dataTransfer?.setData("application/json",JSON.stringify(e)),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")}handleDragOver(e,t){t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"),this.dragOverDate=e,this.render()}handleDragLeave(e){const t=e.relatedTarget,a=e.currentTarget;a&&t&&a.contains(t)||(this.dragOverDate=null,this.render())}handleDrop(e,t){if(t.preventDefault(),!this.draggedEvent)return;const a={...this.draggedEvent,date:l(e)};this.emit("db-event-edit",{event:a}),this.draggedEvent=null,this.dragOverDate=null,this.render()}handleDragEnd(){this.draggedEvent=null,this.dragOverDate=null,this.render()}handleEventClick(e,t){t.stopPropagation(),this.selectedEvent=e,this.isEditing=!0;const a=i(e.date);a&&(this.selectedDate=a),this.eventForm={title:e.title,description:e.description||"",startTime:e.startTime||"09:00",endTime:e.endTime||"10:00",type:e.type,color:e.color||"#17a2b8",isAllDay:e.isAllDay||!1,location:e.location||""},this.emit("db-event-click",{event:e}),this.showEventModal=!0,this.render()}openAddModal(e){this.selectedDate=e,this.selectedEvent=null,this.isEditing=!1,this.eventForm={title:"",description:"",startTime:"09:00",endTime:"10:00",type:"meeting",color:"#17a2b8",isAllDay:!1,location:""},this.showEventModal=!0,this.render()}closeModal(){this.showEventModal=!1,this.selectedEvent=null,this.isEditing=!1,this.render()}saveEvent(){if(!this.eventForm.title.trim())return void window.alert(t("제목을 입력해주세요."));const e={title:this.eventForm.title.trim(),description:this.eventForm.description,date:l(this.selectedDate),startTime:this.eventForm.startTime,endTime:this.eventForm.endTime,type:this.eventForm.type,color:this.eventForm.color,isAllDay:this.eventForm.isAllDay,location:this.eventForm.location};if(this.isEditing&&this.selectedEvent){const t={...this.selectedEvent,...e};this.emit("db-event-edit",{event:t})}else this.emit("db-event-add",{event:e});this.closeModal()}deleteEvent(){this.selectedEvent&&window.confirm(t("정말로 이 일정을 삭제하시겠습니까?"))&&(this.emit("db-event-delete",{eventId:this.selectedEvent.id}),this.closeModal())}renderHeader(){if(!this.headerEl)return;this.headerEl.replaceChildren();const e=document.createElement("div");e.className=`${d}__navigation`;const s=n("m"),i=document.createElement("button");i.type="button",i.className=`${d}__nav-button`,i.setAttribute("aria-label",t("이전")),i.appendChild(a("chevron-left",s)),i.addEventListener("click",()=>{this.shiftMonth(-1)});const l=document.createElement("div");l.className=`${d}__title`,l.textContent=this.selectedDate.toLocaleDateString(this.locale,{year:"numeric",month:"long"});const r=document.createElement("button");r.type="button",r.className=`${d}__nav-button`,r.setAttribute("aria-label",t("다음")),r.appendChild(a("chevron-right",s)),r.addEventListener("click",()=>{this.shiftMonth(1)}),e.append(i,l,r),this.headerEl.appendChild(e)}renderMonthView(){const e=document.createElement("div");e.className=`${d}__month-view`;const t=document.createElement("div");t.className=`${d}__weekdays`,Array.from({length:7},(e,t)=>new Date(Date.UTC(2021,0,3+t)).toLocaleDateString(this.locale,{weekday:"short",timeZone:"UTC"})).forEach(e=>{const a=document.createElement("div");a.className=`${d}__weekday`,a.textContent=e,t.appendChild(a)}),e.appendChild(t);const a=document.createElement("div");a.className=`${d}__days`;const n=this.selectedDate.getFullYear(),s=this.selectedDate.getMonth(),i=new Date(n,s,1),l=new Date(i);l.setDate(l.getDate()-i.getDay());const r=new Date;for(let e=0;e<42;e+=1){const t=new Date(l);t.setDate(l.getDate()+e);const n=t.getMonth()===s;if(!this.showOutsideDays&&!n)continue;const i=0===t.getDay()||6===t.getDay();if(!this.showWeekends&&i)continue;const o=document.createElement("div"),c=this.selectedDateRange.start&&this.selectedDateRange.end&&t>=this.selectedDateRange.start&&t<=this.selectedDateRange.end,h=this.selectedDateRange.start&&t.toDateString()===this.selectedDateRange.start.toDateString(),m=this.selectedDateRange.end&&t.toDateString()===this.selectedDateRange.end.toDateString(),u=Boolean(c&&!h&&!m);o.className=[`${d}__day`,n&&`${d}__day--current-month`,this.highlightToday&&t.toDateString()===r.toDateString()&&`${d}__day--today`,this.isSameDate(t,this.selectedDate)&&`${d}__day--selected`,h&&`${d}__day--selected--start`,m&&`${d}__day--selected--end`,u&&`${d}__day--selected--middle`,!this.showWeekends&&i&&`${d}__day--weekend`].filter(Boolean).join(" "),o.addEventListener("click",()=>this.handleDateClick(t));const v=document.createElement("span");v.className=`${d}__day-number`,v.textContent=String(t.getDate()),o.appendChild(v);const b=this.eventsForDate(t);if(b.length){const e=document.createElement("div");if(e.className=`${d}__day-events`,b.slice(0,2).forEach(t=>{const a=document.createElement("div");a.className=[`${d}__event-bar`,`${d}__event-bar--${t.type}`].filter(Boolean).join(" "),t.color&&(a.style.backgroundColor=t.color),this.draggedEvent?.id===t.id&&a.classList.add(`${d}__event-bar--dragging`),a.title=t.title,a.draggable=!0;const n=document.createElement("span");n.className=`${d}__event-title`,n.textContent=t.title,a.appendChild(n),a.addEventListener("click",e=>this.handleEventClick(t,e)),a.addEventListener("dragstart",e=>this.handleDragStart(t,e)),a.addEventListener("dragend",()=>this.handleDragEnd()),e.appendChild(a)}),b.length>2){const t=document.createElement("div");t.className=`${d}__more-events`,t.textContent=`+${b.length-2} more`,e.appendChild(t)}o.appendChild(e)}const p=document.createElement("div");p.className=[`${d}__drop-zone`,this.dragOverDate&&this.isSameDate(this.dragOverDate,t)&&`${d}__drop-zone--active`].filter(Boolean).join(" "),p.addEventListener("dragover",e=>this.handleDragOver(t,e)),p.addEventListener("dragleave",e=>this.handleDragLeave(e)),p.addEventListener("drop",e=>this.handleDrop(t,e)),o.appendChild(p),a.appendChild(o)}return e.appendChild(a),e}renderYearView(){const e=document.createElement("div");e.className=`${d}__year-view`;const t=this.selectedDate.getFullYear();for(let a=0;a<12;a+=1){const n=new Date(t,a,1),s=this._events.filter(e=>{const n=i(e.date);return n&&n.getFullYear()===t&&n.getMonth()===a}),l=document.createElement("div");l.className=`${d}__year-month`,l.addEventListener("click",()=>{this.selectedDate=n,this.handleViewChange("month")});const r=document.createElement("h3");if(r.className=`${d}__year-month-title`,r.textContent=n.toLocaleDateString(this.locale,{month:"long"}),l.appendChild(r),s.length){const e=document.createElement("div");if(e.className=`${d}__year-month-events`,s.slice(0,4).forEach(t=>{const a=document.createElement("span");a.className=[`${d}__year-event`,`${d}__year-event--${t.type}`].join(" "),t.color&&(a.style.backgroundColor=t.color),e.appendChild(a)}),s.length>4){const t=document.createElement("span");t.className=`${d}__year-more-events`,t.textContent=`+${s.length-4} more`,e.appendChild(t)}l.appendChild(e)}e.appendChild(l)}return e}renderWeekView(){const e=document.createElement("div");e.className=`${d}__week-view`;const t=new Date,a=new Date(this.selectedDate);a.setDate(this.selectedDate.getDate()-this.selectedDate.getDay());const n=document.createElement("div");n.className=`${d}__week-header`;const s=document.createElement("div");s.className=`${d}__time-column-header`,n.appendChild(s);for(let e=0;e<7;e+=1){const s=new Date(a);s.setDate(a.getDate()+e);const i=document.createElement("div");i.className=[`${d}__week-day-header`,s.toDateString()===t.toDateString()&&`${d}__week-day-header--today`].filter(Boolean).join(" ");const l=document.createElement("span");l.className=`${d}__week-day-name`,l.textContent=s.toLocaleDateString(this.locale,{weekday:"short"});const r=document.createElement("span");r.className=`${d}__week-day-number`,r.textContent=String(s.getDate()),i.append(l,r),n.appendChild(i)}e.appendChild(n);const i=document.createElement("div");i.className=`${d}__week-grid`;const l=document.createElement("div");l.className=`${d}__week-time-column`;for(let e=6;e<=22;e+=1){const t=document.createElement("div");t.className=`${d}__time-slot`;const a=document.createElement("span");a.className=`${d}__time-label`,a.textContent=`${String(e).padStart(2,"0")}:00`,t.appendChild(a),l.appendChild(t)}i.appendChild(l);const r=document.createElement("div");r.className=`${d}__week-columns`;for(let e=0;e<7;e+=1){const t=new Date(a);t.setDate(a.getDate()+e);const n=document.createElement("div");n.className=`${d}__week-column`;for(let e=6;e<=22;e+=1){const a=document.createElement("div");a.className=`${d}__week-cell`,a.title=`${t.toLocaleDateString()} ${String(e).padStart(2,"0")}:00`,a.addEventListener("click",()=>{this.selectedDate=new Date(t),this.eventForm.startTime=`${String(e).padStart(2,"0")}:00`,this.eventForm.endTime=`${String(e+1).padStart(2,"0")}:00`,this.openAddModal(this.selectedDate)}),n.appendChild(a)}this.eventsForDate(t).forEach(e=>{if(!e.startTime)return;const[t,a]=e.startTime.split(":").map(Number),s=.8*(60*(t-6)+(a||0)),i=(e.endTime||e.startTime).split(":").map(Number),l=60*(i[0]||t)+(i[1]||0),r=60*t+(a||0),o=Math.max(20,48*(l-r)/60),c=document.createElement("div");c.className=[`${d}__week-event`,`${d}__week-event--${e.type}`].filter(Boolean).join(" "),c.textContent=e.title,c.title=e.title,c.style.backgroundColor=e.color||"#17a2b8",c.style.top=`${s}px`,c.style.height=`${o}px`,c.addEventListener("click",t=>this.handleEventClick(e,t)),n.appendChild(c)}),r.appendChild(n)}return i.appendChild(r),e.appendChild(i),e}renderModal(){if(!this.modalEl)return;if(this.modalEl.replaceChildren(),!this.showEventModal)return void this.modalEl.removeAttribute("open");this.modalEl.setAttribute("open","true"),this.modalEl.setAttribute("title",t(this.isEditing?"일정 편집":"새 일정 추가"));const e=document.createElement("div");e.className=`${d}__event-form`;const a=document.createElement("db-input");a.setAttribute("label",t("제목 *")),a.setAttribute("placeholder",t("일정 제목을 입력하세요")),a.setAttribute("full-width",""),a.setAttribute("value",this.eventForm.title),a.addEventListener("db-input",e=>{this.eventForm.title=e.detail.value});const n=document.createElement("db-input");n.setAttribute("label",t("설명")),n.setAttribute("placeholder",t("일정 설명을 입력하세요")),n.setAttribute("full-width",""),n.setAttribute("value",this.eventForm.description),n.addEventListener("db-input",e=>{this.eventForm.description=e.detail.value});const s=document.createElement("db-date-picker");s.setAttribute("label",t("날짜")),s.setAttribute("full-width",""),s.setAttribute("value",l(this.selectedDate)),s.addEventListener("db-change",e=>{const t=i(e.detail.value);t&&(this.selectedDate=t)});const r=document.createElement("db-select");r.setAttribute("label",t("일정 타입")),r.setAttribute("full-width",""),r.setAttribute("options",JSON.stringify(EVENT_TYPE_OPTIONS())),r.setAttribute("value",this.eventForm.type),r.addEventListener("db-change",e=>{this.eventForm.type=e.detail.value});const o=document.createElement("db-select");o.setAttribute("label",t("색상")),o.setAttribute("full-width",""),o.setAttribute("options",JSON.stringify(COLOR_OPTIONS())),o.setAttribute("value",this.eventForm.color),o.addEventListener("db-change",e=>{this.eventForm.color=e.detail.value});const c=document.createElement("db-time-picker");c.setAttribute("label",t("시작 시간")),c.setAttribute("full-width",""),c.setAttribute("value",this.eventForm.startTime),c.addEventListener("db-change",e=>{this.eventForm.startTime=e.detail.value});const h=document.createElement("db-time-picker");h.setAttribute("label",t("종료 시간")),h.setAttribute("full-width",""),h.setAttribute("value",this.eventForm.endTime),h.addEventListener("db-change",e=>{this.eventForm.endTime=e.detail.value}),e.append(a,n,s,r,o,c,h);const m=document.createElement("div");this.modalBody=m,m.className="designbase-wc-modal__body",m.setAttribute("data-modal-part","body"),m.appendChild(e);const u=document.createElement("div");this.modalFooter=u,u.className="designbase-wc-modal__footer",u.setAttribute("data-modal-part","footer");const v=document.createElement("div");if(v.className=`${d}__modal-actions`,this.isEditing){const e=document.createElement("db-button");e.setAttribute("variant","destructive"),e.textContent=t("삭제"),e.addEventListener("click",()=>this.deleteEvent()),v.appendChild(e)}const b=document.createElement("div");b.className=`${d}__modal-buttons`;const p=document.createElement("db-button");p.setAttribute("variant","secondary"),p.textContent=t("취소"),p.addEventListener("click",()=>this.closeModal());const g=document.createElement("db-button");g.setAttribute("variant","primary"),g.textContent=t(this.isEditing?"수정":"저장"),g.addEventListener("click",()=>this.saveEvent()),b.append(p,g),v.appendChild(b),u.appendChild(v),this.modalEl.append(m,u)}syncLocale(){if(!this.built||!this.bodyEl)return;if(this.renderHeader(),this.bodyEl.replaceChildren(this.renderMonthView()),!this.showEventModal||!this.modalEl)return;this.modalEl.setAttribute("title",t(this.isEditing?"일정 편집":"새 일정 추가"));const[e,a]=this.modalBody?.querySelectorAll("db-input")??[];e?.setAttribute("label",t("제목 *")),e?.setAttribute("placeholder",t("일정 제목을 입력하세요")),a?.setAttribute("label",t("설명")),a?.setAttribute("placeholder",t("일정 설명을 입력하세요")),this.modalBody?.querySelector("db-date-picker")?.setAttribute("label",t("날짜"));const[n,s]=this.modalBody?.querySelectorAll("db-select")??[];n?.setAttribute("label",t("일정 타입")),n?.setAttribute("options",JSON.stringify(EVENT_TYPE_OPTIONS())),s?.setAttribute("label",t("색상")),s?.setAttribute("options",JSON.stringify(COLOR_OPTIONS()));const[i,l]=this.modalBody?.querySelectorAll("db-time-picker")??[];i?.setAttribute("label",t("시작 시간")),l?.setAttribute("label",t("종료 시간"));const d=this.modalFooter?.querySelectorAll("db-button")??[];this.isEditing&&d[0]&&(d[0].textContent=t("삭제"));const r=d[d.length-2],o=d[d.length-1];r&&(r.textContent=t("취소")),o&&(o.textContent=t(this.isEditing?"수정":"저장"))}render(){this.className=d,this.replaceChildren(),this.headerEl&&this.bodyEl&&(this.renderHeader(),this.bodyEl.replaceChildren(),this.bodyEl.appendChild(this.renderMonthView()),this.append(this.headerEl,this.bodyEl),this.renderModal(),this.showEventModal&&this.modalEl&&this.appendChild(this.modalEl))}}customElements.get("db-calendar")||customElements.define("db-calendar",DbCalendar);export{DbCalendar};
@@ -1,4 +1,5 @@
1
1
  declare class DbCard extends HTMLElement {
2
+ private unsubscribeLocale?;
2
3
  static get observedAttributes(): string[];
3
4
  private selectCheckbox;
4
5
  private imageNode;
@@ -1 +1 @@
1
- import{dbText as e}from"../core/i18n.js";import{CARD_VARIANTS as t,CARD_SIZES as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbCard extends HTMLElement{constructor(){super(...arguments),this.selectCheckbox=null,this.imageNode=null,this.handleClick=e=>{if(this.disabled||this.loading)return e.preventDefault(),void e.stopPropagation();this.clickable&&this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.handleKeyDown=e=>{!this.clickable||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.click())},this.handleSelect=e=>{if(e?.stopPropagation(),this.disabled||this.loading||!this.selectable)return;const t=!this.selected;this.toggleAttribute("selected",t),this.selectCheckbox&&(t?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked")),this.dispatchEvent(new CustomEvent("db-select",{bubbles:!0,composed:!0,detail:{selected:t}}))}}static get observedAttributes(){return["variant","size","prism","full-width","clickable","hoverable","selectable","selected","disabled","loading","image","image-alt"]}get variant(){return this.getAttribute("variant")||"default"}set variant(e){this.setAttribute("variant",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get clickable(){return this.hasAttribute("clickable")}set clickable(e){this.toggleAttribute("clickable",e)}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get loading(){return this.hasAttribute("loading")}set loading(e){this.toggleAttribute("loading",e)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}get hoverable(){return this.hasAttribute("hoverable")}set hoverable(e){this.toggleAttribute("hoverable",e)}get selectable(){return this.hasAttribute("selectable")}set selectable(e){this.toggleAttribute("selectable",e)}get selected(){return this.hasAttribute("selected")}set selected(e){this.toggleAttribute("selected",e)}connectedCallback(){this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.sync()}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown)}attributeChangedCallback(e){this.isConnected&&(this.sync(),"selected"===e&&this.selectCheckbox&&(this.selected?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked")))}hasMediaSection(){return!!this.getAttribute("image")||null!==this.querySelector(':scope > .designbase-wc-card__thumbnail, :scope > .designbase-wc-card__media, :scope > [slot="media"], :scope > [slot="thumbnail"]')}hasFooterSection(){return null!==this.querySelector(':scope > .designbase-wc-card__footer, :scope > [slot="footer"]')}syncImageMedia(){const e=this.getAttribute("image"),t=this.querySelector(':scope > .designbase-wc-card__thumbnail, :scope > .designbase-wc-card__media, :scope > [slot="media"], :scope > [slot="thumbnail"]');if(!e)return void(this.imageNode&&(this.imageNode.remove(),this.imageNode=null));if(t&&t!==this.imageNode)return void(this.imageNode&&(this.imageNode.remove(),this.imageNode=null));if(!this.imageNode){this.imageNode=document.createElement("div"),this.imageNode.className="designbase-wc-card__media designbase-wc-card__thumbnail",this.imageNode.setAttribute("slot","media");const e=document.createElement("img");e.className="designbase-wc-card__thumbnail-image",this.imageNode.append(e);const t=this.querySelector(':scope > .designbase-wc-card__body, :scope > [slot="body"], :scope > .designbase-wc-card__footer, :scope > [slot="footer"]');t?this.insertBefore(this.imageNode,t):this.insertBefore(this.imageNode,this.firstChild)}const s=this.imageNode.querySelector("img");s&&(s.src=e,s.alt=this.getAttribute("image-alt")||"")}sync(){this.syncImageMedia(),this.syncAttributes(),this.syncOverlays()}syncOverlays(){const t=this.querySelector(":scope > .designbase-wc-card__loading-overlay"),s=this.querySelector(":scope > .designbase-wc-card__select-overlay");if(this.loading){if(!t){const e=document.createElement("div");e.className="designbase-wc-card__loading-overlay",e.setAttribute("aria-live","polite"),e.setAttribute("aria-busy","true");const t=document.createElement("div");t.className="designbase-wc-card__loading-spinner",e.append(t),this.append(e)}}else t?.remove();if(this.selectable)if(s)this.selectCheckbox&&(this.selected?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked"));else{const t=document.createElement("div");t.className="designbase-wc-card__select-overlay",t.addEventListener("click",e=>this.handleSelect(e));const s=document.createElement("db-checkbox");s.className="designbase-wc-card__select-checkbox",s.setAttribute("size","s"),s.setAttribute("has-label","false"),s.setAttribute("aria-label",e("카드 선택")),this.selected&&s.setAttribute("checked",""),s.addEventListener("click",e=>e.stopPropagation()),s.addEventListener("db-change",e=>{e.stopPropagation(),this.handleSelect()}),t.append(s),this.append(t),this.selectCheckbox=s}else s?.remove(),this.selectCheckbox=null}syncAttributes(){this.classList.add("designbase-wc-card"),this.setAttribute("aria-disabled",String(this.disabled||this.loading)),!this.clickable||this.disabled||this.loading?(this.removeAttribute("role"),this.removeAttribute("tabindex"),this.removeAttribute("aria-pressed")):(this.setAttribute("role","button"),this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.setAttribute("aria-pressed",String(this.hasAttribute("selected")))),t.forEach(e=>this.classList.remove(`designbase-wc-card--${e}`)),s.forEach(e=>this.classList.remove(`designbase-wc-card--${e}`)),this.classList.add(`designbase-wc-card--${t.includes(this.variant)?this.variant:"default"}`),this.classList.add(`designbase-wc-card--${s.includes(this.size)?this.size:"m"}`),this.classList.toggle("designbase-wc-card--prism",this.hasAttribute("prism")),this.classList.toggle("designbase-wc-card--full-width",this.hasAttribute("full-width")),this.classList.toggle("designbase-wc-card--clickable",this.clickable),this.classList.toggle("designbase-wc-card--hoverable",this.hasAttribute("hoverable")),this.classList.toggle("designbase-wc-card--selectable",this.hasAttribute("selectable")),this.classList.toggle("designbase-wc-card--selected",this.hasAttribute("selected")),this.classList.toggle("designbase-wc-card--disabled",this.disabled),this.classList.toggle("designbase-wc-card--loading",this.loading),this.classList.toggle("designbase-wc-card--with-media",this.hasMediaSection()),this.classList.toggle("designbase-wc-card--with-thumbnail",this.hasMediaSection()),this.classList.toggle("designbase-wc-card--with-footer",this.hasFooterSection())}}customElements.get("db-card")||customElements.define("db-card",DbCard);export{DbCard};
1
+ import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{CARD_VARIANTS as s,CARD_SIZES as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbCard extends HTMLElement{constructor(){super(...arguments),this.selectCheckbox=null,this.imageNode=null,this.handleClick=e=>{if(this.disabled||this.loading)return e.preventDefault(),void e.stopPropagation();this.clickable&&this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.handleKeyDown=e=>{!this.clickable||"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.click())},this.handleSelect=e=>{if(e?.stopPropagation(),this.disabled||this.loading||!this.selectable)return;const t=!this.selected;this.toggleAttribute("selected",t),this.selectCheckbox&&(t?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked")),this.dispatchEvent(new CustomEvent("db-select",{bubbles:!0,composed:!0,detail:{selected:t}}))}}static get observedAttributes(){return["variant","size","prism","full-width","clickable","hoverable","selectable","selected","disabled","loading","image","image-alt"]}get variant(){return this.getAttribute("variant")||"default"}set variant(e){this.setAttribute("variant",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get clickable(){return this.hasAttribute("clickable")}set clickable(e){this.toggleAttribute("clickable",e)}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get loading(){return this.hasAttribute("loading")}set loading(e){this.toggleAttribute("loading",e)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}get hoverable(){return this.hasAttribute("hoverable")}set hoverable(e){this.toggleAttribute("hoverable",e)}get selectable(){return this.hasAttribute("selectable")}set selectable(e){this.toggleAttribute("selectable",e)}get selected(){return this.hasAttribute("selected")}set selected(e){this.toggleAttribute("selected",e)}connectedCallback(){this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.sync(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.selectCheckbox?.setAttribute("aria-label",t("카드 선택")))}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown)}attributeChangedCallback(e){this.isConnected&&(this.sync(),"selected"===e&&this.selectCheckbox&&(this.selected?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked")))}hasMediaSection(){return!!this.getAttribute("image")||null!==this.querySelector(':scope > .designbase-wc-card__thumbnail, :scope > .designbase-wc-card__media, :scope > [slot="media"], :scope > [slot="thumbnail"]')}hasFooterSection(){return null!==this.querySelector(':scope > .designbase-wc-card__footer, :scope > [slot="footer"]')}syncImageMedia(){const e=this.getAttribute("image"),t=this.querySelector(':scope > .designbase-wc-card__thumbnail, :scope > .designbase-wc-card__media, :scope > [slot="media"], :scope > [slot="thumbnail"]');if(!e)return void(this.imageNode&&(this.imageNode.remove(),this.imageNode=null));if(t&&t!==this.imageNode)return void(this.imageNode&&(this.imageNode.remove(),this.imageNode=null));if(!this.imageNode){this.imageNode=document.createElement("div"),this.imageNode.className="designbase-wc-card__media designbase-wc-card__thumbnail",this.imageNode.setAttribute("slot","media");const e=document.createElement("img");e.className="designbase-wc-card__thumbnail-image",this.imageNode.append(e);const t=this.querySelector(':scope > .designbase-wc-card__body, :scope > [slot="body"], :scope > .designbase-wc-card__footer, :scope > [slot="footer"]');t?this.insertBefore(this.imageNode,t):this.insertBefore(this.imageNode,this.firstChild)}const s=this.imageNode.querySelector("img");s&&(s.src=e,s.alt=this.getAttribute("image-alt")||"")}sync(){this.syncImageMedia(),this.syncAttributes(),this.syncOverlays()}syncOverlays(){const e=this.querySelector(":scope > .designbase-wc-card__loading-overlay"),s=this.querySelector(":scope > .designbase-wc-card__select-overlay");if(this.loading){if(!e){const e=document.createElement("div");e.className="designbase-wc-card__loading-overlay",e.setAttribute("aria-live","polite"),e.setAttribute("aria-busy","true");const t=document.createElement("div");t.className="designbase-wc-card__loading-spinner",e.append(t),this.append(e)}}else e?.remove();if(this.selectable)if(s)this.selectCheckbox&&(this.selected?this.selectCheckbox.setAttribute("checked",""):this.selectCheckbox.removeAttribute("checked"));else{const e=document.createElement("div");e.className="designbase-wc-card__select-overlay",e.addEventListener("click",e=>this.handleSelect(e));const s=document.createElement("db-checkbox");s.className="designbase-wc-card__select-checkbox",s.setAttribute("size","s"),s.setAttribute("has-label","false"),s.setAttribute("aria-label",t("카드 선택")),this.selected&&s.setAttribute("checked",""),s.addEventListener("click",e=>e.stopPropagation()),s.addEventListener("db-change",e=>{e.stopPropagation(),this.handleSelect()}),e.append(s),this.append(e),this.selectCheckbox=s}else s?.remove(),this.selectCheckbox=null}syncAttributes(){this.classList.add("designbase-wc-card"),this.setAttribute("aria-disabled",String(this.disabled||this.loading)),!this.clickable||this.disabled||this.loading?(this.removeAttribute("role"),this.removeAttribute("tabindex"),this.removeAttribute("aria-pressed")):(this.setAttribute("role","button"),this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.setAttribute("aria-pressed",String(this.hasAttribute("selected")))),s.forEach(e=>this.classList.remove(`designbase-wc-card--${e}`)),i.forEach(e=>this.classList.remove(`designbase-wc-card--${e}`)),this.classList.add(`designbase-wc-card--${s.includes(this.variant)?this.variant:"default"}`),this.classList.add(`designbase-wc-card--${i.includes(this.size)?this.size:"m"}`),this.classList.toggle("designbase-wc-card--prism",this.hasAttribute("prism")),this.classList.toggle("designbase-wc-card--full-width",this.hasAttribute("full-width")),this.classList.toggle("designbase-wc-card--clickable",this.clickable),this.classList.toggle("designbase-wc-card--hoverable",this.hasAttribute("hoverable")),this.classList.toggle("designbase-wc-card--selectable",this.hasAttribute("selectable")),this.classList.toggle("designbase-wc-card--selected",this.hasAttribute("selected")),this.classList.toggle("designbase-wc-card--disabled",this.disabled),this.classList.toggle("designbase-wc-card--loading",this.loading),this.classList.toggle("designbase-wc-card--with-media",this.hasMediaSection()),this.classList.toggle("designbase-wc-card--with-thumbnail",this.hasMediaSection()),this.classList.toggle("designbase-wc-card--with-footer",this.hasFooterSection())}}customElements.get("db-card")||customElements.define("db-card",DbCard);export{DbCard};
@@ -61,6 +61,8 @@ interface DbChatAttachment {
61
61
  declare class DbChatComposer extends HTMLElement {
62
62
  static get observedAttributes(): string[];
63
63
  private built;
64
+ private unsubscribeLocale?;
65
+ private defaultAttachOptions;
64
66
  private _tools;
65
67
  private _attachOptions;
66
68
  private _attachments;
@@ -92,6 +94,7 @@ declare class DbChatComposer extends HTMLElement {
92
94
  get attachments(): DbChatAttachment[];
93
95
  connectedCallback(): void;
94
96
  disconnectedCallback(): void;
97
+ private syncLocale;
95
98
  attributeChangedCallback(name: string): void;
96
99
  private build;
97
100
  private makeIconButton;