@designbasekorea/ui-wc 0.8.13 → 0.9.2

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 (249) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE-PAYMENT-LOGOS.md +437 -0
  3. package/README.md +67 -3
  4. package/dist/esm/components/date-picker-utils.js +1 -1
  5. package/dist/esm/components/db-accordion.js +1 -1
  6. package/dist/esm/components/db-achievement-list.d.ts +31 -0
  7. package/dist/esm/components/db-achievement-list.js +1 -0
  8. package/dist/esm/components/db-achievement-modal.d.ts +38 -0
  9. package/dist/esm/components/db-achievement-modal.js +1 -0
  10. package/dist/esm/components/db-activity-heatmap.js +1 -1
  11. package/dist/esm/components/db-ad-banner.js +1 -1
  12. package/dist/esm/components/db-ai-chain-of-thought.d.ts +14 -0
  13. package/dist/esm/components/db-ai-chain-of-thought.js +1 -0
  14. package/dist/esm/components/db-ai-chat.js +1 -1
  15. package/dist/esm/components/db-ai-checkpoint.d.ts +14 -0
  16. package/dist/esm/components/db-ai-checkpoint.js +1 -0
  17. package/dist/esm/components/db-ai-confirmation.d.ts +14 -0
  18. package/dist/esm/components/db-ai-confirmation.js +1 -0
  19. package/dist/esm/components/db-ai-context.d.ts +15 -0
  20. package/dist/esm/components/db-ai-context.js +1 -0
  21. package/dist/esm/components/db-ai-conversation.d.ts +21 -0
  22. package/dist/esm/components/db-ai-conversation.js +1 -0
  23. package/dist/esm/components/db-ai-execution-quote.d.ts +41 -0
  24. package/dist/esm/components/db-ai-execution-quote.js +1 -0
  25. package/dist/esm/components/db-ai-file-tree.d.ts +14 -0
  26. package/dist/esm/components/db-ai-file-tree.js +1 -0
  27. package/dist/esm/components/db-ai-glow.d.ts +1 -1
  28. package/dist/esm/components/db-ai-inline-citation.d.ts +16 -0
  29. package/dist/esm/components/db-ai-inline-citation.js +1 -0
  30. package/dist/esm/components/db-ai-message.d.ts +19 -0
  31. package/dist/esm/components/db-ai-message.js +1 -0
  32. package/dist/esm/components/db-ai-model-select.d.ts +36 -0
  33. package/dist/esm/components/db-ai-model-select.js +1 -0
  34. package/dist/esm/components/db-ai-plan.d.ts +14 -0
  35. package/dist/esm/components/db-ai-plan.js +1 -0
  36. package/dist/esm/components/db-ai-queue.d.ts +14 -0
  37. package/dist/esm/components/db-ai-queue.js +1 -0
  38. package/dist/esm/components/db-ai-reasoning.d.ts +14 -0
  39. package/dist/esm/components/db-ai-reasoning.js +1 -0
  40. package/dist/esm/components/db-ai-sources.d.ts +14 -0
  41. package/dist/esm/components/db-ai-sources.js +1 -0
  42. package/dist/esm/components/db-ai-stack-trace.d.ts +14 -0
  43. package/dist/esm/components/db-ai-stack-trace.js +1 -0
  44. package/dist/esm/components/db-ai-subagent.d.ts +14 -0
  45. package/dist/esm/components/db-ai-subagent.js +1 -0
  46. package/dist/esm/components/db-ai-task-status.d.ts +26 -0
  47. package/dist/esm/components/db-ai-task-status.js +1 -0
  48. package/dist/esm/components/db-ai-task.d.ts +14 -0
  49. package/dist/esm/components/db-ai-task.js +1 -0
  50. package/dist/esm/components/db-ai-terminal.d.ts +14 -0
  51. package/dist/esm/components/db-ai-terminal.js +1 -0
  52. package/dist/esm/components/db-ai-test-results.d.ts +14 -0
  53. package/dist/esm/components/db-ai-test-results.js +1 -0
  54. package/dist/esm/components/db-ai-tool.d.ts +14 -0
  55. package/dist/esm/components/db-ai-tool.js +1 -0
  56. package/dist/esm/components/db-alert.js +1 -1
  57. package/dist/esm/components/db-app-badge.js +1 -1
  58. package/dist/esm/components/db-attachment-list.d.ts +38 -0
  59. package/dist/esm/components/db-attachment-list.js +1 -0
  60. package/dist/esm/components/db-audio-player.js +1 -1
  61. package/dist/esm/components/db-bento-card.d.ts +55 -0
  62. package/dist/esm/components/db-bento-card.js +1 -0
  63. package/dist/esm/components/db-bento-grid.d.ts +25 -0
  64. package/dist/esm/components/db-bento-grid.js +1 -0
  65. package/dist/esm/components/db-boarding-pass-stack.d.ts +49 -0
  66. package/dist/esm/components/db-boarding-pass-stack.js +1 -0
  67. package/dist/esm/components/db-boarding-pass.d.ts +32 -0
  68. package/dist/esm/components/db-boarding-pass.js +1 -0
  69. package/dist/esm/components/db-border-beam.d.ts +52 -0
  70. package/dist/esm/components/db-border-beam.js +1 -0
  71. package/dist/esm/components/db-bottom-navigation.js +1 -1
  72. package/dist/esm/components/db-bottom-sheet.js +1 -1
  73. package/dist/esm/components/db-breadcrumbs.js +1 -1
  74. package/dist/esm/components/db-button.d.ts +1 -1
  75. package/dist/esm/components/db-button.js +1 -1
  76. package/dist/esm/components/db-calendar.js +1 -1
  77. package/dist/esm/components/db-card.js +1 -1
  78. package/dist/esm/components/db-carousel.d.ts +3 -3
  79. package/dist/esm/components/db-carousel.js +1 -1
  80. package/dist/esm/components/db-chat-composer.d.ts +2 -0
  81. package/dist/esm/components/db-chat-composer.js +1 -1
  82. package/dist/esm/components/db-chat-message.d.ts +1 -1
  83. package/dist/esm/components/db-chat-orb.d.ts +1 -1
  84. package/dist/esm/components/db-chat-room.js +1 -1
  85. package/dist/esm/components/db-chat-widget.d.ts +1 -1
  86. package/dist/esm/components/db-chat-widget.js +1 -1
  87. package/dist/esm/components/db-chip.js +1 -1
  88. package/dist/esm/components/db-code-block.js +1 -1
  89. package/dist/esm/components/db-color-picker.d.ts +1 -0
  90. package/dist/esm/components/db-color-picker.js +1 -1
  91. package/dist/esm/components/db-confetti.d.ts +90 -0
  92. package/dist/esm/components/db-confetti.js +1 -0
  93. package/dist/esm/components/db-context-bar.d.ts +13 -0
  94. package/dist/esm/components/db-context-bar.js +1 -0
  95. package/dist/esm/components/db-credit-balance.d.ts +17 -0
  96. package/dist/esm/components/db-credit-balance.js +1 -0
  97. package/dist/esm/components/db-credit-card.d.ts +51 -0
  98. package/dist/esm/components/db-credit-card.js +1 -0
  99. package/dist/esm/components/db-credit-dropdown.d.ts +31 -0
  100. package/dist/esm/components/db-credit-dropdown.js +1 -0
  101. package/dist/esm/components/db-credit-history.d.ts +31 -0
  102. package/dist/esm/components/db-credit-history.js +1 -0
  103. package/dist/esm/components/db-credit-recharge-modal.d.ts +35 -0
  104. package/dist/esm/components/db-credit-recharge-modal.js +1 -0
  105. package/dist/esm/components/db-credit-recharge.d.ts +39 -0
  106. package/dist/esm/components/db-credit-recharge.js +1 -0
  107. package/dist/esm/components/db-date-picker.js +1 -1
  108. package/dist/esm/components/db-design-canvas.d.ts +137 -0
  109. package/dist/esm/components/db-design-canvas.js +1 -0
  110. package/dist/esm/components/db-design-toolbar.d.ts +60 -0
  111. package/dist/esm/components/db-design-toolbar.js +1 -0
  112. package/dist/esm/components/db-device-mockup.d.ts +100 -0
  113. package/dist/esm/components/db-device-mockup.js +1 -0
  114. package/dist/esm/components/db-download-progress.d.ts +1 -1
  115. package/dist/esm/components/db-download-progress.js +1 -1
  116. package/dist/esm/components/db-drawer.js +1 -1
  117. package/dist/esm/components/db-dropdown.d.ts +2 -0
  118. package/dist/esm/components/db-dropdown.js +1 -1
  119. package/dist/esm/components/db-dropzone.js +1 -1
  120. package/dist/esm/components/db-email-verify.d.ts +1 -7
  121. package/dist/esm/components/db-email-verify.js +1 -1
  122. package/dist/esm/components/db-file-uploader.d.ts +10 -0
  123. package/dist/esm/components/db-file-uploader.js +1 -1
  124. package/dist/esm/components/db-filter-bar.d.ts +34 -0
  125. package/dist/esm/components/db-filter-bar.js +1 -0
  126. package/dist/esm/components/db-flight-status.d.ts +33 -0
  127. package/dist/esm/components/db-flight-status.js +1 -0
  128. package/dist/esm/components/db-floating-action-button.d.ts +24 -14
  129. package/dist/esm/components/db-floating-action-button.js +1 -1
  130. package/dist/esm/components/db-footer.d.ts +3 -0
  131. package/dist/esm/components/db-footer.js +1 -1
  132. package/dist/esm/components/db-gantt.js +1 -1
  133. package/dist/esm/components/db-glyph-matrix.d.ts +58 -0
  134. package/dist/esm/components/db-glyph-matrix.js +1 -0
  135. package/dist/esm/components/db-icons.d.ts +1 -1
  136. package/dist/esm/components/db-icons.js +1 -1
  137. package/dist/esm/components/db-image-list.d.ts +2 -0
  138. package/dist/esm/components/db-image-list.js +1 -1
  139. package/dist/esm/components/db-indicator.js +1 -1
  140. package/dist/esm/components/db-input.js +1 -1
  141. package/dist/esm/components/db-kanban.js +1 -1
  142. package/dist/esm/components/db-lightbox.d.ts +4 -0
  143. package/dist/esm/components/db-lightbox.js +1 -1
  144. package/dist/esm/components/db-markdown-editor.js +1 -1
  145. package/dist/esm/components/db-marquee.d.ts +2 -10
  146. package/dist/esm/components/db-marquee.js +1 -1
  147. package/dist/esm/components/db-menu-item.d.ts +2 -0
  148. package/dist/esm/components/db-menu-item.js +1 -1
  149. package/dist/esm/components/db-modal.d.ts +1 -1
  150. package/dist/esm/components/db-modal.js +1 -1
  151. package/dist/esm/components/db-navbar.d.ts +3 -1
  152. package/dist/esm/components/db-navbar.js +1 -1
  153. package/dist/esm/components/db-navigation-rail.d.ts +1 -1
  154. package/dist/esm/components/db-node.d.ts +83 -0
  155. package/dist/esm/components/db-node.js +1 -0
  156. package/dist/esm/components/db-notification-dropdown.d.ts +30 -0
  157. package/dist/esm/components/db-notification-dropdown.js +1 -0
  158. package/dist/esm/components/db-notification-inbox.d.ts +25 -0
  159. package/dist/esm/components/db-notification-inbox.js +1 -0
  160. package/dist/esm/components/db-onboarding-modal.js +1 -1
  161. package/dist/esm/components/db-otp-input.d.ts +1 -1
  162. package/dist/esm/components/db-otp-input.js +1 -1
  163. package/dist/esm/components/db-page-header.d.ts +8 -0
  164. package/dist/esm/components/db-page-header.js +1 -1
  165. package/dist/esm/components/db-pagination.js +1 -1
  166. package/dist/esm/components/db-phone-verify.d.ts +1 -1
  167. package/dist/esm/components/db-phone-verify.js +1 -1
  168. package/dist/esm/components/db-plan-overview.d.ts +26 -0
  169. package/dist/esm/components/db-plan-overview.js +1 -0
  170. package/dist/esm/components/db-popover.js +1 -1
  171. package/dist/esm/components/db-progress-step.js +1 -1
  172. package/dist/esm/components/db-progressive-blur.d.ts +35 -0
  173. package/dist/esm/components/db-progressive-blur.js +1 -0
  174. package/dist/esm/components/db-receipt.d.ts +37 -0
  175. package/dist/esm/components/db-receipt.js +1 -0
  176. package/dist/esm/components/db-resizable-panels.js +1 -1
  177. package/dist/esm/components/db-search-bar.js +1 -1
  178. package/dist/esm/components/db-section-testimonials.d.ts +1 -4
  179. package/dist/esm/components/db-section-testimonials.js +1 -1
  180. package/dist/esm/components/db-segment-control.d.ts +0 -4
  181. package/dist/esm/components/db-segment-control.js +1 -1
  182. package/dist/esm/components/db-select.js +1 -1
  183. package/dist/esm/components/db-share.js +1 -1
  184. package/dist/esm/components/db-sidebar.d.ts +14 -1
  185. package/dist/esm/components/db-sidebar.js +1 -1
  186. package/dist/esm/components/db-split-view.d.ts +2 -0
  187. package/dist/esm/components/db-split-view.js +1 -1
  188. package/dist/esm/components/db-stepper.d.ts +0 -3
  189. package/dist/esm/components/db-stepper.js +1 -1
  190. package/dist/esm/components/db-table.js +1 -1
  191. package/dist/esm/components/db-testimonial.js +1 -1
  192. package/dist/esm/components/db-textarea.js +1 -1
  193. package/dist/esm/components/db-ticket.d.ts +18 -0
  194. package/dist/esm/components/db-ticket.js +1 -0
  195. package/dist/esm/components/db-time-picker.d.ts +1 -1
  196. package/dist/esm/components/db-time-picker.js +1 -1
  197. package/dist/esm/components/db-tool-button.d.ts +57 -0
  198. package/dist/esm/components/db-tool-button.js +1 -0
  199. package/dist/esm/components/db-top-banner.js +1 -1
  200. package/dist/esm/components/db-tutorial.js +1 -1
  201. package/dist/esm/components/db-tweet-card.d.ts +101 -0
  202. package/dist/esm/components/db-tweet-card.js +1 -0
  203. package/dist/esm/components/db-two-factor.d.ts +5 -11
  204. package/dist/esm/components/db-two-factor.js +1 -1
  205. package/dist/esm/components/db-video-player.js +1 -1
  206. package/dist/esm/components/db-voice-control.d.ts +25 -0
  207. package/dist/esm/components/db-voice-control.js +1 -0
  208. package/dist/esm/components/db-workspace-invite-modal.d.ts +51 -0
  209. package/dist/esm/components/db-workspace-invite-modal.js +1 -0
  210. package/dist/esm/components/db-workspace-members.d.ts +36 -0
  211. package/dist/esm/components/db-workspace-members.js +1 -0
  212. package/dist/esm/components/db-youtube-player.js +1 -1
  213. package/dist/esm/components/device-mockup-style.js +1 -0
  214. package/dist/esm/components/flight-route.js +1 -0
  215. package/dist/esm/components/input-validation.js +1 -1
  216. package/dist/esm/components/node-style.js +1 -0
  217. package/dist/esm/components/paper-card.d.ts +26 -0
  218. package/dist/esm/components/paper-card.js +1 -0
  219. package/dist/esm/components/random-gradient-palettes.d.ts +4 -0
  220. package/dist/esm/core/ai-element.d.ts +47 -0
  221. package/dist/esm/core/ai-element.js +1 -0
  222. package/dist/esm/core/credit-ui.js +1 -0
  223. package/dist/esm/core/i18n-copy.js +1 -0
  224. package/dist/esm/core/i18n-en.js +1 -0
  225. package/dist/esm/core/i18n.d.ts +206 -1
  226. package/dist/esm/core/i18n.js +1 -1
  227. package/dist/esm/core/notification-ui.d.ts +17 -0
  228. package/dist/esm/core/notification-ui.js +1 -0
  229. package/dist/esm/helpers/payment-brands.d.ts +56 -0
  230. package/dist/esm/helpers/payment-brands.js +1 -0
  231. package/dist/esm/helpers/toast.d.ts +2 -3
  232. package/dist/esm/index.d.ts +63 -3
  233. package/dist/esm/index.js +1 -1
  234. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js +1 -0
  235. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-GM4TCAP5.js +1 -0
  236. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-GSN4JZN7.js +1 -0
  237. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-VJJVQGV4.js +1 -0
  238. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-YWLMJGDH.js +1 -0
  239. package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
  240. package/dist/esm/ui-contracts/dist/components.d.d.ts +76 -0
  241. package/dist/esm/ui-contracts/dist/primitives.d.d.ts +21 -0
  242. package/dist/index.cjs +1 -1
  243. package/dist/index.css +1 -1
  244. package/dist/index.d.ts +2223 -63
  245. package/dist/index.esm.js +1 -1
  246. package/dist/react/index.cjs +1 -1
  247. package/dist/react/index.d.ts +793 -6726
  248. package/dist/react/index.esm.js +1 -1
  249. package/package.json +16 -9
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import{coerceToContract as e}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{EMAIL_VERIFY_SIZES as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbEmailVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["mode","email","code","step","size","disabled","error","error-message","countdown","title","description","send-label","resend-label","verify-label","confirm-label","code-length","closable","manual","sending","verifying","auto-submit"]}get mode(){return"confirm"===this.getAttribute("mode")?"confirm":"code"}set mode(t){this.setAttribute("mode",t)}get size(){return e(this.getAttribute("size"),i,"m")}set size(t){this.setAttribute("size",t)}get step(){const t=this.getAttribute("step");return"code"===t||"sent"===t||"verified"===t?t:"email"}set step(t){this.setAttribute("step",t)}get email(){return this.getAttribute("email")||""}set email(t){this.setAttribute("email",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}set countdown(t){this.setAttribute("countdown",String(t))}connectedCallback(){this.build(),this.sync(),"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"!==t&&"mode"!==t||e===i||("code"===this.mode&&"code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"!==this.mode&&(this.mode="code"),"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}markSent(){this.step="sent",this.clearTimer()}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}startTimer(t){this.clearTimer(),this.remaining=t,this.renderTimer(),this.timerId=setInterval(()=>{this.remaining-=1,this.renderTimer(),this.remaining<=0&&(this.clearTimer(),this.resendBtn.disabled=!1,this.dispatchEvent(new CustomEvent("db-countdown-complete",{bubbles:!0,composed:!0})))},1e3)}renderTimer(){const t=Math.max(0,Math.floor(this.remaining/60)),e=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(t).padStart(2,"0")}:${String(e).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",`남은 시간 ${t}분 ${e}초`),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const e="designbase-wc-email-verify";this.replaceChildren();const i=el("div",`${e}__shell`),s=el("div",`${e}__top`),n=el("span",`${e}__eyebrow`);n.dataset.role="eyebrow",this.closeBtn=el("button",`${e}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label","닫기"),this.closeBtn.append(t("close",18)),this.closeBtn.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),s.append(n,this.closeBtn);const r=el("div",`${e}__header`),o=el("h3",`${e}__title`);o.dataset.role="title";const d=el("p",`${e}__description`);d.dataset.role="description",r.append(o,d),this.emailRow=el("div",`${e}__email-row`),this.emailInput=document.createElement("db-input"),this.emailInput.setAttribute("type","email"),this.emailInput.setAttribute("label","이메일"),this.emailInput.setAttribute("placeholder","name@example.com"),this.emailInput.setAttribute("full-width",""),this.emailInput.setAttribute("start-icon","mail"),this.emailInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value??this.emailInput.value??"");this.setAttribute("email",e),this.dispatchEvent(new CustomEvent("db-email-change",{detail:{email:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isEmailValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{email:this.email,mode:this.mode},bubbles:!0,composed:!0})),this.hasAttribute("manual")||("confirm"===this.mode?this.markSent():this.startCodeStep()))}),this.emailRow.append(this.emailInput,this.sendBtn),this.codeBlock=el("div",`${e}__code`);const a=el("div",`${e}__code-head`),l=el("span",`${e}__code-label`);l.textContent="인증 코드",this.timerEl=el("span",`${e}__timer`),a.append(l,this.timerEl),this.otpInput=document.createElement("db-otp-input"),this.otpInput.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.setAttribute("code",e),this.dispatchEvent(new CustomEvent("db-code-change",{detail:{code:e},bubbles:!0,composed:!0}))}),this.otpInput.addEventListener("db-complete",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.dispatchEvent(new CustomEvent("db-code-complete",{detail:{code:e,email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const h=el("div",`${e}__code-actions`);this.resendBtn=el("button",`${e}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),this.verifyBtn=document.createElement("db-button"),this.verifyBtn.setAttribute("variant","primary"),this.verifyBtn.setAttribute("full-width",""),this.verifyBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestVerify()}),h.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(a,this.otpInput,h),this.confirmBlock=el("div",`${e}__confirm`);const c=el("div",`${e}__confirm-icon`);c.append(t("mail",40));const m=el("span",`${e}__confirm-badge`);m.append(t("circle-checked",16)),c.append(m);const u=el("h4",`${e}__confirm-title`);u.dataset.role="confirm-title";const b=el("p",`${e}__confirm-desc`);b.dataset.role="confirm-desc",this.confirmBtn=document.createElement("db-button"),this.confirmBtn.setAttribute("variant","primary"),this.confirmBtn.setAttribute("full-width",""),this.confirmBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-confirm",{detail:{email:this.email},bubbles:!0,composed:!0}))});const p=el("button",`${e}__resend`);p.type="button",p.dataset.role="confirm-resend",p.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0}))}),this.confirmBlock.append(c,u,b,this.confirmBtn,p),this.verifiedBlock=el("div",`${e}__confirm`);const f=el("div",`${e}__confirm-icon`);f.append(t("circle-checked",40));const v=el("h4",`${e}__confirm-title`);v.textContent="이메일 인증 완료";const g=el("p",`${e}__confirm-desc`);g.dataset.role="verified-desc",this.verifiedBlock.append(f,v,g),this.errorEl=el("p",`${e}__error`),this.errorEl.hidden=!0,i.append(s,r,this.emailRow,this.codeBlock,this.confirmBlock,this.verifiedBlock,this.errorEl),this.append(i)}sync(){const t="designbase-wc-email-verify",e=this.size,i=this.mode,s=this.step,n=this.hasAttribute("disabled"),r=this.getAttribute("code-length")||"6",o=this.email;this.className=[t,`${t}--${e}`,`${t}--mode-${i}`,`${t}--step-${s}`,n&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" "),this.emailInput?.toggleAttribute("error",this.hasAttribute("error"));this.querySelector('[data-role="eyebrow"]').textContent="confirm"===i?"회원가입":"이메일 인증";const d=this.querySelector('[data-role="title"]'),a=this.querySelector('[data-role="description"]');d.textContent=this.getAttribute("title")||("confirm"===i?"이메일을 확인해 주세요":"이메일 인증");const l=this.getAttribute("description");l?a.textContent=l:"confirm"===i?this.setEmphasizedText(a,"",o||"your@email.com"," 으로 인증 링크를 보냈어요."):this.setEmphasizedText(a,"인증 코드를 ",o||"이메일"," 로 보내 드릴게요."),this.closeBtn&&(this.closeBtn.hidden=!this.hasAttribute("closable")),this.emailInput.value=o,this.emailInput.setAttribute("size",e),this.emailInput.toggleAttribute("disabled",n||"code"===s||"sent"===s||"verified"===s),this.sendBtn.setAttribute("size",e),this.sendBtn.textContent=this.getAttribute("send-label")||("confirm"===i?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",n||!this.isEmailValid()||"email"!==s),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",r),this.otpInput.setAttribute("size",e),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",n||"code"!==s),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",e),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",n||"code"!==s||(this.getAttribute("code")||"").length!==Number(r)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying"));const h=this.querySelector('[data-role="confirm-title"]'),c=this.querySelector('[data-role="confirm-desc"]');h.textContent="메일함을 확인해 주세요!",this.setEmphasizedText(c,"",o||"your@email.com"," 으로 보낸 링크를 클릭하면 인증이 완료됩니다."),this.confirmBtn.setAttribute("size",e),this.confirmBtn.textContent=this.getAttribute("confirm-label")||"확인";const m=this.querySelector('[data-role="confirm-resend"]');m&&(m.textContent="메일 다시 보내기");const u=this.querySelector('[data-role="verified-desc"]');this.setEmphasizedText(u,"",o||"your@email.com"," 주소가 인증되었습니다."),this.emailRow.hidden="confirm"===i&&("sent"===s||"verified"===s)||"code"===i&&"verified"===s,this.codeBlock.hidden=!("code"===i&&"code"===s),this.confirmBlock.hidden=!("confirm"===i&&("sent"===s||"verified"===s)),this.verifiedBlock.hidden=!("code"===i&&"verified"===s);const b=this.getAttribute("error-message")||"";this.errorEl.textContent=b,this.errorEl.hidden=!this.hasAttribute("error")||!b}isEmailValid(){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email.trim())}requestVerify(){const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{email:this.email,code:t},bubbles:!0,composed:!0}))}setEmphasizedText(t,e,i,s){const n=document.createElement("strong");n.textContent=i,t.replaceChildren(document.createTextNode(e),n,document.createTextNode(s))}}customElements.get("db-email-verify")||customElements.define("db-email-verify",DbEmailVerify);export{DbEmailVerify};
1
+ import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-input.js";import"./db-otp-input.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{EMAIL_VERIFY_SIZES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function el(t,e){const i=document.createElement(t);return e&&(i.className=e),i}class DbEmailVerify extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.timerId=null,this.remaining=0}static get observedAttributes(){return["mode","email","code","step","size","disabled","error","error-message","countdown","title","description","send-label","resend-label","verify-label","confirm-label","code-length","closable","manual","sending","verifying","auto-submit"]}get mode(){return"confirm"===this.getAttribute("mode")?"confirm":"code"}set mode(t){this.setAttribute("mode",t)}get size(){return s(this.getAttribute("size"),n,"m")}set size(t){this.setAttribute("size",t)}get step(){const t=this.getAttribute("step");return"code"===t||"sent"===t||"verified"===t?t:"email"}set step(t){this.setAttribute("step",t)}get email(){return this.getAttribute("email")||""}set email(t){this.setAttribute("email",t)}get countdown(){const t=Number(this.getAttribute("countdown")||180);return Number.isFinite(t)&&t>0?t:180}set countdown(t){this.setAttribute("countdown",String(t))}connectedCallback(){this.build(),this.sync(),"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}disconnectedCallback(){this.clearTimer()}attributeChangedCallback(t,e,i){this.built&&(this.sync(),"step"!==t&&"mode"!==t||e===i||("code"===this.mode&&"code"===this.step?this.startTimer(this.countdown):this.clearTimer()))}startCodeStep(){"code"!==this.mode&&(this.mode="code"),"code"===this.step?this.startTimer(this.countdown):this.step="code",requestAnimationFrame(()=>this.otpInput?.focus?.())}restartCountdown(){"code"===this.mode&&"code"===this.step&&this.startTimer(this.countdown)}markSent(){this.step="sent",this.clearTimer()}markVerified(){this.step="verified",this.clearTimer()}clearTimer(){this.timerId&&clearInterval(this.timerId),this.timerId=null,this.remaining=0}startTimer(t){this.clearTimer(),this.remaining=t,this.renderTimer(),this.timerId=setInterval(()=>{this.remaining-=1,this.renderTimer(),this.remaining<=0&&(this.clearTimer(),this.resendBtn.disabled=!1,this.dispatchEvent(new CustomEvent("db-countdown-complete",{bubbles:!0,composed:!0})))},1e3)}renderTimer(){const e=Math.max(0,Math.floor(this.remaining/60)),i=Math.max(0,this.remaining%60);this.timerEl.textContent=`${String(e).padStart(2,"0")}:${String(i).padStart(2,"0")}`,this.timerEl.setAttribute("aria-label",t("남은 시간 {0}분 {1}초",[e,i])),this.resendBtn.disabled=this.remaining>0||this.hasAttribute("disabled")}build(){if(this.built)return;this.built=!0;const t="designbase-wc-email-verify";this.replaceChildren();const s=el("div",`${t}__shell`),n=el("div",`${t}__top`),r=el("span",`${t}__eyebrow`);r.dataset.role="eyebrow",this.closeBtn=el("button",`${t}__close`),this.closeBtn.type="button",this.closeBtn.setAttribute("aria-label",e("닫기")),this.closeBtn.append(i("close",18)),this.closeBtn.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),n.append(r,this.closeBtn);const o=el("div",`${t}__header`),d=el("h3",`${t}__title`);d.dataset.role="title";const a=el("p",`${t}__description`);a.dataset.role="description",o.append(d,a),this.emailRow=el("div",`${t}__email-row`),this.emailInput=document.createElement("db-input"),this.emailInput.setAttribute("type","email"),this.emailInput.setAttribute("label","이메일"),this.emailInput.setAttribute("placeholder","name@example.com"),this.emailInput.setAttribute("full-width",""),this.emailInput.setAttribute("start-icon","mail"),this.emailInput.addEventListener("db-input",t=>{t.stopPropagation();const e=String(t.detail?.value??this.emailInput.value??"");this.setAttribute("email",e),this.dispatchEvent(new CustomEvent("db-email-change",{detail:{email:e},bubbles:!0,composed:!0}))}),this.sendBtn=document.createElement("db-button"),this.sendBtn.setAttribute("variant","primary"),this.sendBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.isEmailValid()&&(this.dispatchEvent(new CustomEvent("db-send-code",{detail:{email:this.email,mode:this.mode},bubbles:!0,composed:!0})),this.hasAttribute("manual")||("confirm"===this.mode?this.markSent():this.startCodeStep()))}),this.emailRow.append(this.emailInput,this.sendBtn),this.codeBlock=el("div",`${t}__code`);const l=el("div",`${t}__code-head`),h=el("span",`${t}__code-label`);h.textContent=e("인증 코드"),this.timerEl=el("span",`${t}__timer`),l.append(h,this.timerEl),this.otpInput=document.createElement("db-otp-input"),this.otpInput.addEventListener("db-change",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.setAttribute("code",e),this.dispatchEvent(new CustomEvent("db-code-change",{detail:{code:e},bubbles:!0,composed:!0}))}),this.otpInput.addEventListener("db-complete",t=>{t.stopPropagation();const e=String(t.detail?.value||"");this.dispatchEvent(new CustomEvent("db-code-complete",{detail:{code:e,email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("auto-submit")&&this.requestVerify()});const c=el("div",`${t}__code-actions`);this.resendBtn=el("button",`${t}__resend`),this.resendBtn.type="button",this.resendBtn.addEventListener("click",()=>{this.resendBtn.disabled||(this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0})),this.hasAttribute("manual")||this.startTimer(this.countdown))}),this.verifyBtn=document.createElement("db-button"),this.verifyBtn.setAttribute("variant","primary"),this.verifyBtn.setAttribute("full-width",""),this.verifyBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.requestVerify()}),c.append(this.resendBtn,this.verifyBtn),this.codeBlock.append(l,this.otpInput,c),this.confirmBlock=el("div",`${t}__confirm`);const m=el("div",`${t}__confirm-icon`);m.append(i("mail",40));const u=el("span",`${t}__confirm-badge`);u.append(i("circle-checked",16)),m.append(u);const b=el("h4",`${t}__confirm-title`);b.dataset.role="confirm-title";const p=el("p",`${t}__confirm-desc`);p.dataset.role="confirm-desc",this.confirmBtn=document.createElement("db-button"),this.confirmBtn.setAttribute("variant","primary"),this.confirmBtn.setAttribute("full-width",""),this.confirmBtn.addEventListener("db-click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-confirm",{detail:{email:this.email},bubbles:!0,composed:!0}))});const f=el("button",`${t}__resend`);f.type="button",f.dataset.role="confirm-resend",f.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-resend",{detail:{email:this.email},bubbles:!0,composed:!0}))}),this.confirmBlock.append(m,b,p,this.confirmBtn,f),this.verifiedBlock=el("div",`${t}__confirm`);const v=el("div",`${t}__confirm-icon`);v.append(i("circle-checked",40));const g=el("h4",`${t}__confirm-title`);g.textContent=e("이메일 인증 완료");const A=el("p",`${t}__confirm-desc`);A.dataset.role="verified-desc",this.verifiedBlock.append(v,g,A),this.errorEl=el("p",`${t}__error`),this.errorEl.hidden=!0,s.append(n,o,this.emailRow,this.codeBlock,this.confirmBlock,this.verifiedBlock,this.errorEl),this.append(s)}sync(){const t="designbase-wc-email-verify",i=this.size,s=this.mode,n=this.step,r=this.hasAttribute("disabled"),o=this.getAttribute("code-length")||"6",d=this.email;this.className=[t,`${t}--${i}`,`${t}--mode-${s}`,`${t}--step-${n}`,r&&`${t}--disabled`,this.hasAttribute("error")&&`${t}--error`].filter(Boolean).join(" "),this.emailInput?.toggleAttribute("error",this.hasAttribute("error"));this.querySelector('[data-role="eyebrow"]').textContent="confirm"===s?"회원가입":"이메일 인증";const a=this.querySelector('[data-role="title"]'),l=this.querySelector('[data-role="description"]');a.textContent=this.getAttribute("title")||("confirm"===s?"이메일을 확인해 주세요":"이메일 인증");const h=this.getAttribute("description");h?l.textContent=h:"confirm"===s?this.setEmphasizedText(l,"",d||"your@email.com"," 으로 인증 링크를 보냈어요."):this.setEmphasizedText(l,"인증 코드를 ",d||"이메일"," 로 보내 드릴게요."),this.closeBtn&&(this.closeBtn.hidden=!this.hasAttribute("closable")),this.emailInput.value=d,this.emailInput.setAttribute("size",i),this.emailInput.toggleAttribute("disabled",r||"code"===n||"sent"===n||"verified"===n),this.sendBtn.setAttribute("size",i),this.sendBtn.textContent=this.getAttribute("send-label")||("confirm"===s?"인증 메일 보내기":"인증번호 받기"),this.sendBtn.toggleAttribute("disabled",r||!this.isEmailValid()||"email"!==n),this.sendBtn.toggleAttribute("loading",this.hasAttribute("sending")),this.otpInput.setAttribute("length",o),this.otpInput.setAttribute("size",i),this.otpInput.setAttribute("value",this.getAttribute("code")||""),this.otpInput.toggleAttribute("disabled",r||"code"!==n),this.resendBtn.textContent=this.getAttribute("resend-label")||"재전송",this.verifyBtn.setAttribute("size",i),this.verifyBtn.textContent=this.getAttribute("verify-label")||"인증하기",this.verifyBtn.toggleAttribute("disabled",r||"code"!==n||(this.getAttribute("code")||"").length!==Number(o)),this.verifyBtn.toggleAttribute("loading",this.hasAttribute("verifying"));const c=this.querySelector('[data-role="confirm-title"]'),m=this.querySelector('[data-role="confirm-desc"]');c.textContent=e("메일함을 확인해 주세요!"),this.setEmphasizedText(m,"",d||"your@email.com"," 으로 보낸 링크를 클릭하면 인증이 완료됩니다."),this.confirmBtn.setAttribute("size",i),this.confirmBtn.textContent=this.getAttribute("confirm-label")||"확인";const u=this.querySelector('[data-role="confirm-resend"]');u&&(u.textContent=e("메일 다시 보내기"));const b=this.querySelector('[data-role="verified-desc"]');this.setEmphasizedText(b,"",d||"your@email.com"," 주소가 인증되었습니다."),this.emailRow.hidden="confirm"===s&&("sent"===n||"verified"===n)||"code"===s&&"verified"===n,this.codeBlock.hidden=!("code"===s&&"code"===n),this.confirmBlock.hidden=!("confirm"===s&&("sent"===n||"verified"===n)),this.verifiedBlock.hidden=!("code"===s&&"verified"===n);const p=this.getAttribute("error-message")||"";this.errorEl.textContent=p,this.errorEl.hidden=!this.hasAttribute("error")||!p}isEmailValid(){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email.trim())}requestVerify(){const t=(this.getAttribute("code")||this.otpInput.value).replace(/\D/g,""),e=Number(this.getAttribute("code-length")||6);"code"!==this.step||t.length!==e||this.hasAttribute("disabled")||this.dispatchEvent(new CustomEvent("db-verify",{detail:{email:this.email,code:t},bubbles:!0,composed:!0}))}setEmphasizedText(t,e,i,s){const n=document.createElement("strong");n.textContent=i,t.replaceChildren(document.createTextNode(e),n,document.createTextNode(s))}}customElements.get("db-email-verify")||customElements.define("db-email-verify",DbEmailVerify);export{DbEmailVerify};
@@ -1,3 +1,12 @@
1
+ type FileStatus = 'pending' | 'uploading' | 'success' | 'error';
2
+ type UploadFile = {
3
+ file: File;
4
+ id: string;
5
+ status: FileStatus;
6
+ progress: number;
7
+ error?: string;
8
+ uploadedAt?: Date;
9
+ };
1
10
  declare class DbFileUploader extends HTMLElement {
2
11
  static get observedAttributes(): string[];
3
12
  private dropzone?;
@@ -25,3 +34,4 @@ declare global {
25
34
  }
26
35
 
27
36
  export { DbFileUploader };
37
+ export type { FileStatus, UploadFile };
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{FILE_UPLOADER_SIZES as t,FILE_UPLOADER_VARIANTS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbFileUploader extends HTMLElement{constructor(){super(...arguments),this.uploadedFiles=[],this.uploadIntervals=new Map,this.handleFileSelect=e=>{if(this.isDisabled())return;const t=e.detail,s=t?.files??[];if(!s.length)return;const i=s.map(e=>({file:e,id:`${Date.now()}-${Math.random()}`,status:"pending",progress:0}));this.hasAttribute("multiple")?this.uploadedFiles=[...this.uploadedFiles,...i]:this.uploadedFiles=i,this.dispatchEvent(new CustomEvent("db-upload",{bubbles:!0,composed:!0,detail:{files:i}})),this.simulateUpload(i),this.renderFileList()},this.handleRemove=e=>{if(this.isDisabled())return;const t=this.uploadIntervals.get(e);t&&(clearInterval(t),this.uploadIntervals.delete(e)),this.uploadedFiles=this.uploadedFiles.filter(t=>t.id!==e),this.dispatchEvent(new CustomEvent("db-remove",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.renderFileList()},this.handleRetry=e=>{if(this.isDisabled())return;const t=this.uploadedFiles.find(t=>t.id===e);t&&(this.updateFile(e,{status:"pending",progress:0,error:void 0}),this.dispatchEvent(new CustomEvent("db-retry",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.simulateUpload([t]),this.renderFileList())}}static get observedAttributes(){return["size","variant","accept","max-size","multiple","show-file-list","show-progress","disabled","readonly"]}connectedCallback(){this.ensureDropzone(),this.sync(),this.dropzone?.addEventListener("db-file-select",this.handleFileSelect)}disconnectedCallback(){this.dropzone?.removeEventListener("db-file-select",this.handleFileSelect),this.uploadIntervals.forEach(e=>clearInterval(e)),this.uploadIntervals.clear()}attributeChangedCallback(){this.isConnected&&this.sync()}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}ensureDropzone(){this.dropzone||(this.dropzone=document.createElement("db-dropzone"),this.dropzone.setAttribute("data-wc-internal",""),this.prepend(this.dropzone))}formatFileSize(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return`${parseFloat((e/1024**t).toFixed(2))} ${["Bytes","KB","MB","GB"][t]}`}simulateUpload(e){e.forEach((e,t)=>{this.updateFile(e.id,{status:"uploading",progress:0});let s=0;const i=setInterval(()=>{if(s+=20*Math.random(),s>=100)return s=100,clearInterval(i),this.uploadIntervals.delete(e.id),this.updateFile(e.id,{status:"success",progress:100}),void this.renderFileList();this.updateFile(e.id,{progress:s}),this.renderFileList()},100+50*t);this.uploadIntervals.set(e.id,i)})}updateFile(e,t){this.uploadedFiles=this.uploadedFiles.map(s=>s.id===e?{...s,...t}:s)}sync(){if(this.ensureDropzone(),!this.dropzone)return;const e=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default",l=t.includes(e)?e:"m",a=s.includes(i)?i:"default";this.className=["designbase-wc-file-uploader",`designbase-wc-file-uploader--size-${l}`,`designbase-wc-file-uploader--variant-${a}`,this.hasAttribute("disabled")&&"designbase-wc-file-uploader--disabled",this.hasAttribute("readonly")&&"designbase-wc-file-uploader--readonly"].filter(Boolean).join(" "),this.dropzone.setAttribute("size",l),this.dropzone.setAttribute("variant",a),this.getAttribute("accept")?this.dropzone.setAttribute("accept",this.getAttribute("accept")):this.dropzone.removeAttribute("accept"),this.getAttribute("max-size")?this.dropzone.setAttribute("max-size",this.getAttribute("max-size")):this.dropzone.removeAttribute("max-size"),this.dropzone.toggleAttribute("multiple",this.hasAttribute("multiple")),this.dropzone.toggleAttribute("disabled",this.hasAttribute("disabled")),this.dropzone.toggleAttribute("readonly",this.hasAttribute("readonly")),this.renderFileList()}renderStatusIcon(t){if("uploading"===t){const e=document.createElement("db-spinner");return e.setAttribute("type","circular"),e.setAttribute("size","s"),e}return e("success"===t?"done":"error"===t?"error-filled":"gallery",20)}renderFileList(){const e=!this.hasAttribute("show-file-list")||"false"!==this.getAttribute("show-file-list"),t=!this.hasAttribute("show-progress")||"false"!==this.getAttribute("show-progress");if(this.querySelector(":scope > .designbase-wc-file-uploader__file-list")?.remove(),!e||!this.uploadedFiles.length)return;const s=document.createElement("div");s.className="designbase-wc-file-uploader__file-list";const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-list-title",i.textContent=`업로드된 파일들 (${this.uploadedFiles.length}개)`,s.append(i);const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-items",this.uploadedFiles.forEach(e=>{const s=document.createElement("div");s.className=`designbase-wc-file-uploader__file-item designbase-wc-file-uploader__file-item--${e.status}`;const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-info";const a=document.createElement("div");a.className="designbase-wc-file-uploader__file-icon",a.append(this.renderStatusIcon(e.status));const r=document.createElement("div");r.className="designbase-wc-file-uploader__file-details";const d=document.createElement("div");d.className="designbase-wc-file-uploader__file-name",d.textContent=e.file.name;const n=document.createElement("div");if(n.className="designbase-wc-file-uploader__file-size",n.textContent=this.formatFileSize(e.file.size),r.append(d,n),e.error){const t=document.createElement("div");t.className="designbase-wc-file-uploader__file-error",t.textContent=e.error,r.append(t)}if(i.append(a,r),s.append(i),t&&"uploading"===e.status){const t=document.createElement("div");t.className="designbase-wc-file-uploader__progress";const i=document.createElement("db-progressbar");i.setAttribute("value",String(Math.round(e.progress||0))),i.setAttribute("size","s"),i.setAttribute("variant","primary"),i.setAttribute("bar-style","solid"),i.setAttribute("show-label",""),i.setAttribute("label-position","inside"),i.setAttribute("full-width",""),t.append(i),s.append(t)}const o=document.createElement("div");if(o.className="designbase-wc-file-uploader__file-actions","error"===e.status){const t=document.createElement("button");t.type="button",t.className="designbase-wc-file-uploader__retry-button",t.textContent="재시도",t.disabled=this.isDisabled(),t.addEventListener("click",()=>this.handleRetry(e.id)),o.append(t)}const u=document.createElement("button");u.type="button",u.className="designbase-wc-file-uploader__remove-button",u.textContent="삭제",u.disabled=this.isDisabled(),u.addEventListener("click",()=>this.handleRemove(e.id)),o.append(u),s.append(o),l.append(s)}),s.append(l),this.append(s)}}customElements.get("db-file-uploader")||customElements.define("db-file-uploader",DbFileUploader);export{DbFileUploader};
1
+ import{t as e}from"../core/i18n.js";import{createDbIcon as t}from"./db-icons.js";import{FILE_UPLOADER_SIZES as s,FILE_UPLOADER_VARIANTS as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbFileUploader extends HTMLElement{constructor(){super(...arguments),this.uploadedFiles=[],this.uploadIntervals=new Map,this.handleFileSelect=e=>{if(this.isDisabled())return;const t=e.detail,s=t?.files??[];if(!s.length)return;const i=s.map(e=>({file:e,id:`${Date.now()}-${Math.random()}`,status:"pending",progress:0}));this.hasAttribute("multiple")?this.uploadedFiles=[...this.uploadedFiles,...i]:this.uploadedFiles=i,this.dispatchEvent(new CustomEvent("db-upload",{bubbles:!0,composed:!0,detail:{files:i}})),this.simulateUpload(i),this.renderFileList()},this.handleRemove=e=>{if(this.isDisabled())return;const t=this.uploadIntervals.get(e);t&&(clearInterval(t),this.uploadIntervals.delete(e)),this.uploadedFiles=this.uploadedFiles.filter(t=>t.id!==e),this.dispatchEvent(new CustomEvent("db-remove",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.renderFileList()},this.handleRetry=e=>{if(this.isDisabled())return;const t=this.uploadedFiles.find(t=>t.id===e);t&&(this.updateFile(e,{status:"pending",progress:0,error:void 0}),this.dispatchEvent(new CustomEvent("db-retry",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.simulateUpload([t]),this.renderFileList())}}static get observedAttributes(){return["locale","size","variant","accept","max-size","multiple","show-file-list","show-progress","disabled","readonly"]}connectedCallback(){this.ensureDropzone(),this.sync(),this.dropzone?.addEventListener("db-file-select",this.handleFileSelect)}disconnectedCallback(){this.dropzone?.removeEventListener("db-file-select",this.handleFileSelect),this.uploadIntervals.forEach(e=>clearInterval(e)),this.uploadIntervals.clear()}attributeChangedCallback(){this.isConnected&&this.sync()}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}ensureDropzone(){this.dropzone||(this.dropzone=document.createElement("db-dropzone"),this.dropzone.setAttribute("data-wc-internal",""),this.prepend(this.dropzone))}formatFileSize(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return`${parseFloat((e/1024**t).toFixed(2))} ${["Bytes","KB","MB","GB"][t]}`}simulateUpload(e){e.forEach((e,t)=>{this.updateFile(e.id,{status:"uploading",progress:0});let s=0;const i=setInterval(()=>{if(s+=20*Math.random(),s>=100)return s=100,clearInterval(i),this.uploadIntervals.delete(e.id),this.updateFile(e.id,{status:"success",progress:100}),void this.renderFileList();this.updateFile(e.id,{progress:s}),this.renderFileList()},100+50*t);this.uploadIntervals.set(e.id,i)})}updateFile(e,t){this.uploadedFiles=this.uploadedFiles.map(s=>s.id===e?{...s,...t}:s)}sync(){if(this.ensureDropzone(),!this.dropzone)return;const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",l=s.includes(e)?e:"m",a=i.includes(t)?t:"default";this.className=["designbase-wc-file-uploader",`designbase-wc-file-uploader--size-${l}`,`designbase-wc-file-uploader--variant-${a}`,this.hasAttribute("disabled")&&"designbase-wc-file-uploader--disabled",this.hasAttribute("readonly")&&"designbase-wc-file-uploader--readonly"].filter(Boolean).join(" "),this.dropzone.setAttribute("size",l),this.dropzone.setAttribute("variant",a),this.getAttribute("accept")?this.dropzone.setAttribute("accept",this.getAttribute("accept")):this.dropzone.removeAttribute("accept"),this.getAttribute("max-size")?this.dropzone.setAttribute("max-size",this.getAttribute("max-size")):this.dropzone.removeAttribute("max-size"),this.dropzone.toggleAttribute("multiple",this.hasAttribute("multiple")),this.dropzone.toggleAttribute("disabled",this.hasAttribute("disabled")),this.dropzone.toggleAttribute("readonly",this.hasAttribute("readonly")),this.renderFileList()}renderStatusIcon(e){if("uploading"===e){const e=document.createElement("db-spinner");return e.setAttribute("type","circular"),e.setAttribute("size","s"),e}return t("success"===e?"done":"error"===e?"error-filled":"gallery",20)}renderFileList(){const t=!this.hasAttribute("show-file-list")||"false"!==this.getAttribute("show-file-list"),s=!this.hasAttribute("show-progress")||"false"!==this.getAttribute("show-progress");if(this.querySelector(":scope > .designbase-wc-file-uploader__file-list")?.remove(),!t||!this.uploadedFiles.length)return;const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-list";const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-list-title",l.textContent=e("upload.files").replace("{count}",String(this.uploadedFiles.length)),i.append(l);const a=document.createElement("div");a.className="designbase-wc-file-uploader__file-items",this.uploadedFiles.forEach(t=>{const i=document.createElement("div");i.className=`designbase-wc-file-uploader__file-item designbase-wc-file-uploader__file-item--${t.status}`;const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-info";const r=document.createElement("div");r.className="designbase-wc-file-uploader__file-icon",r.append(this.renderStatusIcon(t.status));const d=document.createElement("div");d.className="designbase-wc-file-uploader__file-details";const n=document.createElement("div");n.className="designbase-wc-file-uploader__file-name",n.textContent=t.file.name;const o=document.createElement("div");if(o.className="designbase-wc-file-uploader__file-size",o.textContent=this.formatFileSize(t.file.size),d.append(n,o),t.error){const e=document.createElement("div");e.className="designbase-wc-file-uploader__file-error",e.textContent=t.error,d.append(e)}if(l.append(r,d),i.append(l),s&&"uploading"===t.status){const e=document.createElement("div");e.className="designbase-wc-file-uploader__progress";const s=document.createElement("db-progressbar");s.setAttribute("value",String(Math.round(t.progress||0))),s.setAttribute("size","s"),s.setAttribute("variant","primary"),s.setAttribute("bar-style","solid"),s.setAttribute("show-label",""),s.setAttribute("label-position","inside"),s.setAttribute("full-width",""),e.append(s),i.append(e)}const u=document.createElement("div");if(u.className="designbase-wc-file-uploader__file-actions","error"===t.status){const s=document.createElement("button");s.type="button",s.className="designbase-wc-file-uploader__retry-button",s.textContent=e("upload.retry"),s.disabled=this.isDisabled(),s.addEventListener("click",()=>this.handleRetry(t.id)),u.append(s)}const c=document.createElement("button");c.type="button",c.className="designbase-wc-file-uploader__remove-button",c.textContent=e("upload.remove"),c.disabled=this.isDisabled(),c.addEventListener("click",()=>this.handleRemove(t.id)),u.append(c),i.append(u),a.append(i)}),i.append(a),this.append(i)}}customElements.get("db-file-uploader")||customElements.define("db-file-uploader",DbFileUploader);export{DbFileUploader};
@@ -0,0 +1,34 @@
1
+ declare const FILTER_BAR_SIZES: readonly ["s", "m", "l"];
2
+ declare const FILTER_BAR_VARIANTS: readonly ["plain", "outlined", "filled"];
3
+ declare const FILTER_BAR_ALIGNS: readonly ["start", "end"];
4
+ type FilterBarSize = (typeof FILTER_BAR_SIZES)[number];
5
+ type FilterBarVariant = (typeof FILTER_BAR_VARIANTS)[number];
6
+ type FilterBarAlign = (typeof FILTER_BAR_ALIGNS)[number];
7
+ /**
8
+ * Search/filter composition. Direct children use search, filters, summary and
9
+ * actions slots. No rendering or reparenting: field values, focus, overlays and
10
+ * framework listeners remain owned by the controls supplied by the consumer.
11
+ *
12
+ * This is a labelled group, not an ARIA toolbar: fields keep normal Tab order.
13
+ */
14
+ declare class DbFilterBar extends HTMLElement {
15
+ static get observedAttributes(): string[];
16
+ private decoration;
17
+ get padding(): boolean;
18
+ set padding(value: boolean);
19
+ get border(): boolean;
20
+ set border(value: boolean);
21
+ get background(): boolean;
22
+ set background(value: boolean);
23
+ connectedCallback(): void;
24
+ attributeChangedCallback(): void;
25
+ private syncHostClasses;
26
+ }
27
+ declare global {
28
+ interface HTMLElementTagNameMap {
29
+ 'db-filter-bar': DbFilterBar;
30
+ }
31
+ }
32
+
33
+ export { DbFilterBar };
34
+ export type { FilterBarAlign, FilterBarSize, FilterBarVariant };
@@ -0,0 +1 @@
1
+ import{coerceToContract as t,SIZE_SML as e}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";const i=e,r=["plain","outlined","filled"],s=["start","end"];class DbFilterBar extends HTMLElement{static get observedAttributes(){return["size","variant","align","padding","border","background"]}decoration(e){const i=this.getAttribute(e);if(null!=i)return"false"!==i;const s=t(this.getAttribute("variant"),r,"plain");return"background"===e?"filled"===s:"plain"!==s}get padding(){return this.decoration("padding")}set padding(t){this.setAttribute("padding",String(t))}get border(){return this.decoration("border")}set border(t){this.setAttribute("border",String(t))}get background(){return this.decoration("background")}set background(t){this.setAttribute("background",String(t))}connectedCallback(){this.hasAttribute("role")||this.setAttribute("role","group"),this.hasAttribute("aria-label")||this.hasAttribute("aria-labelledby")||this.setAttribute("aria-label","Filters"),this.syncHostClasses()}attributeChangedCallback(){this.syncHostClasses()}syncHostClasses(){const e=[...this.classList].filter(t=>!t.startsWith("designbase-wc-filter-bar")),a=t(this.getAttribute("size"),i,"m"),n=t(this.getAttribute("variant"),r,"plain"),b=t(this.getAttribute("align"),s,"start");this.className=[...e,"designbase-wc-filter-bar",`designbase-wc-filter-bar--${a}`,`designbase-wc-filter-bar--${n}`,`designbase-wc-filter-bar--${b}`,...["padding","border","background"].filter(t=>this.decoration(t)).map(t=>`designbase-wc-filter-bar--${t}`)].join(" ")}}customElements.get("db-filter-bar")||customElements.define("db-filter-bar",DbFilterBar);export{DbFilterBar};
@@ -0,0 +1,33 @@
1
+ import { DbElement } from '../core/base-element.js';
2
+
3
+ declare const STATUSES: readonly ["scheduled", "boarding", "in-flight", "landed", "delayed", "cancelled"];
4
+ type DbFlightStatusValue = typeof STATUSES[number];
5
+ /** Display data supplied by the application; does not fetch or simulate live flights. */
6
+ declare class DbFlightStatus extends DbElement {
7
+ static get observedAttributes(): string[];
8
+ private view;
9
+ private displayedProgress;
10
+ private animation;
11
+ private resizeObserver;
12
+ private motion;
13
+ private redraw;
14
+ private get targetProgress();
15
+ private stopAnimation;
16
+ private onMotionChange;
17
+ disconnectedCallback(): void;
18
+ get progress(): number;
19
+ set progress(value: number);
20
+ get status(): DbFlightStatusValue;
21
+ set status(value: DbFlightStatusValue);
22
+ connectedCallback(): void;
23
+ attributeChangedCallback(): void;
24
+ private render;
25
+ }
26
+ declare global {
27
+ interface HTMLElementTagNameMap {
28
+ 'db-flight-status': DbFlightStatus;
29
+ }
30
+ }
31
+
32
+ export { DbFlightStatus };
33
+ export type { DbFlightStatusValue };
@@ -0,0 +1 @@
1
+ import{t}from"../core/i18n.js";import{DbElement as e}from"../core/base-element.js";import{createDbIcon as s}from"./db-icons.js";import{paperNode as i}from"./paper-card.js";import{flightRoutePosition as r}from"./flight-route.js";const a=["scheduled","boarding","in-flight","landed","delayed","cancelled"],n={scheduled:"출발 예정",boarding:"탑승 중","in-flight":"운항 중",landed:"도착",delayed:"지연",cancelled:"취소"};class DbFlightStatus extends e{constructor(){super(...arguments),this.view=i("section","db-flight-status__view"),this.displayedProgress=null,this.animation=0,this.resizeObserver=null,this.motion=null,this.redraw=null,this.onMotionChange=()=>{this.motion?.matches&&(this.stopAnimation(),this.displayedProgress=this.targetProgress,this.redraw?.())}}static get observedAttributes(){return["airline","service-number","origin","origin-name","destination","destination-name","departure-time","arrival-time","terminal","gate","status","detail","progress","label"]}get targetProgress(){return"landed"===this.status?100:"scheduled"===this.status||"cancelled"===this.status?0:this.progress}stopAnimation(){this.animation&&cancelAnimationFrame(this.animation),this.animation=0}disconnectedCallback(){this.stopAnimation(),this.resizeObserver?.disconnect(),this.motion?.removeEventListener("change",this.onMotionChange),this.redraw=null,super.disconnectedCallback()}get progress(){const t=Number(this.getAttribute("progress")||0);return Number.isFinite(t)?Math.min(100,Math.max(0,t)):0}set progress(t){this.setAttribute("progress",String(t))}get status(){return a.find(t=>t===this.getAttribute("status"))||"scheduled"}set status(t){this.setAttribute("status",t)}connectedCallback(){this.classList.add("db-flight-status"),this.upgradeProperties(["progress","status"]),this.view.parentNode||this.prepend(this.view),this.motion=window.matchMedia?.("(prefers-reduced-motion: reduce)")||null,this.motion?.addEventListener("change",this.onMotionChange),this.render()}attributeChangedCallback(){this.isConnected&&this.render()}render(){const attr=t=>this.getAttribute(t)||"";this.dataset.status=this.status,this.view.setAttribute("aria-label",attr("label")||`${attr("origin")} → ${attr("destination")} · ${t("flight.title")}`);const e=i("header","db-flight-status__header");e.append(i("strong","",attr("airline")||attr("service-number")||t("flight.title")),i("span","db-flight-status__status",attr("detail")||t(`flight.${this.status}`,n[this.status])));const a=i("div","db-flight-status__route"),endpoint=t=>{const e=i("div","db-flight-status__endpoint");return e.append(i("strong","",attr(t)||"—")),attr(`${t}-name`)&&e.append(i("span","",attr(`${t}-name`))),e},o=i("div","db-flight-status__track"),d=this.targetProgress;this.stopAnimation(),this.resizeObserver?.disconnect(),o.setAttribute("role","progressbar"),o.setAttribute("aria-label",t("flight.progress")),o.setAttribute("aria-valuemin","0"),o.setAttribute("aria-valuemax","100"),o.setAttribute("aria-valuenow",String(d)),o.setAttribute("aria-valuetext",`${t(`flight.${this.status}`,n[this.status])} · ${d}%`);const l="http://www.w3.org/2000/svg",h=document.createElementNS(l,"svg");h.setAttribute("viewBox","0 0 240 64"),h.setAttribute("preserveAspectRatio","none"),h.setAttribute("aria-hidden","true");for(const t of["db-flight-status__path","db-flight-status__travelled"]){const e=document.createElementNS(l,"path");e.setAttribute("d","M12 46 Q120 -8 228 46"),e.setAttribute("pathLength","100"),e.setAttribute("class",t),t.endsWith("travelled")&&(e.style.strokeDasharray=`${d} 100`),h.append(e)}const u=i("span","db-flight-status__plane");u.setAttribute("aria-hidden","true"),u.append(s("plane",20)),o.append(h,u),a.append(endpoint("origin"),o,endpoint("destination"));const g=i("div","db-flight-status__footer");g.append(i("span","",[attr("service-number"),attr("departure-time")&&`${t("boardingPass.departure")} ${attr("departure-time")}`].filter(Boolean).join(" · ")),i("span","",[attr("arrival-time")&&`${t("boardingPass.arrival")} ${attr("arrival-time")}`,attr("terminal")&&`${t("boardingPass.terminal")} ${attr("terminal")}`,attr("gate")&&`${t("boardingPass.gate")} ${attr("gate")}`].filter(Boolean).join(" · "))),this.view.replaceChildren(e,a,g);const c=h.querySelector(".db-flight-status__travelled");let p=o.clientWidth||240,m=o.clientHeight||58;this.redraw=()=>{const t=this.displayedProgress??d,e=r(t,p,m);u.style.left=`${e.x}px`,u.style.top=`${e.y}px`,u.style.transform=`translate(-50%, -50%) rotate(${e.angle}deg)`,c.style.strokeDasharray=`${t} 100`},"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>{p=o.clientWidth||240,m=o.clientHeight||58,this.redraw?.()}),this.resizeObserver.observe(o));const b=this.displayedProgress;if(null===b||b===d||this.motion?.matches)return this.displayedProgress=d,void this.redraw();this.redraw();let v=null;const animate=t=>{v??(v=t);const e=Math.min(1,(t-v)/1e3);this.displayedProgress=b+(d-b)*(1-Math.pow(1-e,3)),this.redraw?.(),this.animation=e<1?requestAnimationFrame(animate):0};this.animation=requestAnimationFrame(animate)}}customElements.get("db-flight-status")||customElements.define("db-flight-status",DbFlightStatus);export{DbFlightStatus};
@@ -1,20 +1,30 @@
1
- declare class DbFloatingActionButton extends HTMLElement {
2
- private detachKeyActivation?;
1
+ import { DbButton } from './db-button.js';
2
+
3
+ /** Floating placement and collapsing label, with the canonical Button behavior and visuals. */
4
+ declare class DbFloatingActionButton extends DbButton {
5
+ private scrollRoot;
6
+ private lastScroll;
7
+ private mappedIcon?;
8
+ private scrollCollapsed;
9
+ private labelObserver?;
3
10
  static get observedAttributes(): string[];
4
- get size(): string;
5
- set size(value: string);
6
- get variant(): string;
7
- set variant(value: string);
8
- get loading(): boolean;
9
- set loading(value: boolean);
10
- get disabled(): boolean;
11
- set disabled(value: boolean);
11
+ get label(): string;
12
+ set label(value: string);
13
+ get collapsed(): boolean;
14
+ set collapsed(value: boolean);
15
+ get collapseOnScroll(): boolean;
16
+ set collapseOnScroll(value: boolean);
17
+ get collapseThreshold(): number;
18
+ set collapseThreshold(value: number);
12
19
  connectedCallback(): void;
13
20
  disconnectedCallback(): void;
14
- attributeChangedCallback(): void;
15
- private handleClick;
16
- private resolveIconName;
17
- private sync;
21
+ attributeChangedCallback(name?: string): void;
22
+ private syncFab;
23
+ private measureLabel;
24
+ private unbindScroll;
25
+ private bindScroll;
26
+ private scrollPosition;
27
+ private onScroll;
18
28
  }
19
29
  declare global {
20
30
  interface HTMLElementTagNameMap {
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{activateOnKey as e}from"../core/a11y.js";import{FLOATING_ACTION_BUTTON_SIZES as i,FLOATING_ACTION_BUTTON_VARIANTS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const n={s:12,m:16,l:20},a={s:"xs",m:"s",l:"m"};class DbFloatingActionButton 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}))}}static get observedAttributes(){return["size","variant","icon","loading","disabled","aria-label"]}get size(){const t=this.getAttribute("size")||"m";return i.includes(t)?t:"m"}set size(t){this.setAttribute("size",t)}get variant(){const t=this.getAttribute("variant")||"primary";return s.includes(t)?t:"primary"}set variant(t){this.setAttribute("variant",t)}get loading(){return this.hasAttribute("loading")}set loading(t){this.toggleAttribute("loading",Boolean(t))}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",Boolean(t))}connectedCallback(){"button"!==this.getAttribute("role")&&this.setAttribute("role","button"),this.hasAttribute("type")||this.setAttribute("type","button"),this.addEventListener("click",this.handleClick),this.detachKeyActivation=e(this,{isDisabled:()=>this.disabled}),this.sync()}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.detachKeyActivation?.(),this.detachKeyActivation=void 0}attributeChangedCallback(){this.isConnected&&this.sync()}resolveIconName(t){if(!t)return;return t in{plus:1,search:1,settings:1,edit:1,close:1}?t:void 0}sync(){this.className=["designbase-wc-fab",`designbase-wc-fab--${this.size}`,`designbase-wc-fab--${this.variant}`,this.disabled&&"designbase-wc-fab--disabled",this.loading&&"designbase-wc-fab--loading"].filter(Boolean).join(" ");const e=this.getAttribute("aria-label")||"Floating action button";this.getAttribute("aria-label")!==e&&this.setAttribute("aria-label",e);const i=String(this.loading);this.getAttribute("aria-busy")!==i&&this.setAttribute("aria-busy",i);const s=String(this.disabled||this.loading);this.getAttribute("aria-disabled")!==s&&this.setAttribute("aria-disabled",s);let r=this.querySelector(":scope > .designbase-wc-fab__icon");if(r||(r=document.createElement("div"),r.className="designbase-wc-fab__icon",this.append(r)),r.replaceChildren(),this.loading){const t=document.createElement("span");return t.className=`designbase-wc-spinner designbase-wc-spinner--circular designbase-wc-spinner--${a[this.size]}`,t.setAttribute("aria-hidden","true"),t.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>',void r.append(t)}const o=this.getAttribute("icon"),c=this.resolveIconName(o);if(c)return void r.append(t(c,n[this.size]));const l=Array.from(this.children).find(t=>t!==r&&!t.hasAttribute("data-wc-internal"));l&&!l.isConnected&&r.append(l)}}customElements.get("db-floating-action-button")||customElements.define("db-floating-action-button",DbFloatingActionButton);export{DbFloatingActionButton};
1
+ import{DbButton as t}from"./db-button.js";class DbFloatingActionButton extends t{constructor(){super(...arguments),this.scrollRoot=null,this.lastScroll=0,this.scrollCollapsed=!1,this.measureLabel=()=>{const t=this.querySelector(".designbase-wc-fab__label-text");this.style.setProperty("--db-fab-label-width",`${t?.scrollWidth||0}px`)},this.onScroll=()=>{const t=this.scrollPosition(),e=t-this.lastScroll;if(t<=this.collapseThreshold)this.scrollCollapsed=!1;else if(e>4)this.scrollCollapsed=!0;else{if(!(e<-4))return;this.scrollCollapsed=!1}this.lastScroll=t,this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed)}}static get observedAttributes(){return[...super.observedAttributes,"icon","label","collapsed","collapse-on-scroll","scroll-target","collapse-threshold"]}get label(){return this.getAttribute("label")||""}set label(t){this.setAttribute("label",t)}get collapsed(){return this.hasAttribute("collapsed")}set collapsed(t){this.toggleAttribute("collapsed",t)}get collapseOnScroll(){return this.hasAttribute("collapse-on-scroll")}set collapseOnScroll(t){this.toggleAttribute("collapse-on-scroll",t)}get collapseThreshold(){const t=Number(this.getAttribute("collapse-threshold")??24);return Number.isFinite(t)?Math.max(0,t):24}set collapseThreshold(t){this.setAttribute("collapse-threshold",String(t))}connectedCallback(){this.hasAttribute("radius")||(this.radius="pill"),this.syncFab(),super.connectedCallback(),this.labelObserver=new ResizeObserver(this.measureLabel);const t=this.querySelector(".designbase-wc-fab__label-text");t&&this.labelObserver.observe(t),this.bindScroll()}disconnectedCallback(){super.disconnectedCallback(),this.unbindScroll(),this.labelObserver?.disconnect(),this.labelObserver=void 0}attributeChangedCallback(t){super.attributeChangedCallback(),this.syncFab(),this.isConnected&&["collapse-on-scroll","scroll-target","collapse-threshold"].includes(t||"")&&this.bindScroll()}syncFab(){this.classList.add("designbase-wc-fab");const t=this.getAttribute("icon");if(t)this.mappedIcon=t,this.getAttribute("start-icon")!==t&&this.setAttribute("start-icon",t);else if(this.mappedIcon){const t=this.mappedIcon;this.mappedIcon=void 0,this.getAttribute("start-icon")===t&&this.removeAttribute("start-icon")}let e=this.querySelector(":scope > .designbase-wc-fab__label");if(!e){e=document.createElement("span"),e.className="designbase-wc-fab__label",e.setAttribute("aria-hidden","true");const t=document.createElement("span");t.className="designbase-wc-fab__label-text",e.append(t),this.append(e)}const l=e.firstElementChild;l.textContent!==this.label&&(l.textContent=this.label),!this.label||this.hasAttribute("aria-label")&&this.getAttribute("data-fab-auto-label")!==this.getAttribute("aria-label")||(this.setAttribute("aria-label",this.label),this.setAttribute("data-fab-auto-label",this.label)),this.hasAttribute("aria-label")||(this.setAttribute("aria-label","Floating action button"),this.setAttribute("data-fab-auto-label","Floating action button")),this.classList.toggle("designbase-wc-fab--extended",Boolean(this.label)),this.classList.toggle("designbase-wc-fab--collapsed",this.collapsed||this.scrollCollapsed),this.measureLabel()}unbindScroll(){this.scrollRoot?.removeEventListener("scroll",this.onScroll),this.scrollRoot=null}bindScroll(){if(this.unbindScroll(),this.scrollCollapsed=!1,this.collapseOnScroll){let t=null;const e=this.getAttribute("scroll-target");if(e)try{t=document.querySelector(e)}catch{}else for(let e=this.parentElement;e;e=e.parentElement)if(/(auto|scroll)/.test(getComputedStyle(e).overflowY)){t=e;break}this.scrollRoot=t||window,this.lastScroll=this.scrollPosition(),this.scrollCollapsed=this.lastScroll>this.collapseThreshold,this.scrollRoot.addEventListener("scroll",this.onScroll,{passive:!0})}this.syncFab()}scrollPosition(){return Math.max(0,this.scrollRoot instanceof HTMLElement?this.scrollRoot.scrollTop:window.scrollY)}}customElements.get("db-floating-action-button")||customElements.define("db-floating-action-button",DbFloatingActionButton);export{DbFloatingActionButton};
@@ -35,6 +35,9 @@ interface DbFooterFamilySite {
35
35
  href: string;
36
36
  }
37
37
  declare class DbFooter extends HTMLElement {
38
+ /** Light-DOM slots retain framework state and listeners across attribute updates. */
39
+ private brandContent;
40
+ private bottomContent;
38
41
  static get observedAttributes(): string[];
39
42
  connectedCallback(): void;
40
43
  attributeChangedCallback(): void;
@@ -1 +1 @@
1
- import{createShareIcon as e}from"./db-share-icons.js";import{sanitizeHref as t}from"../core/safe-url.js";import{FOOTER_SIZES as s,FOOTER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={youtube:"youtube",instagram:"instagram",x:"x",linkedin:"linkedin",facebook:"facebook",email:"mail"};function parseJson(e,t){if(!e)return t;try{return JSON.parse(e)??t}catch{return t}}class DbFooter extends HTMLElement{static get observedAttributes(){return["columns","legal-links","social-links","company-info","family-sites","tagline","copyright","logo-type","variant","size","full-width","show-logo","show-social","family-site-label"]}connectedCallback(){this.render()}attributeChangedCallback(){this.isConnected&&this.render()}get columns(){return parseJson(this.getAttribute("columns"),[])}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}get legalLinks(){return parseJson(this.getAttribute("legal-links"),[])}set legalLinks(e){this.setAttribute("legal-links","string"==typeof e?e:JSON.stringify(e))}get socialLinks(){return parseJson(this.getAttribute("social-links"),[])}set socialLinks(e){this.setAttribute("social-links","string"==typeof e?e:JSON.stringify(e))}get companyInfo(){return parseJson(this.getAttribute("company-info"),{})}set companyInfo(e){this.setAttribute("company-info","string"==typeof e?e:JSON.stringify(e))}get familySites(){return parseJson(this.getAttribute("family-sites"),[])}set familySites(e){this.setAttribute("family-sites","string"==typeof e?e:JSON.stringify(e))}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",a=s.includes(e)?e:"m",i=n.includes(t)?t:"default";this.className=["designbase-wc-footer",`designbase-wc-footer--${a}`,`designbase-wc-footer--${i}`,this.hasAttribute("full-width")&&"designbase-wc-footer--full-width"].filter(Boolean).join(" ")}dispatchLinkClick(e,t){this.dispatchEvent(new CustomEvent("db-link-click",{bubbles:!0,composed:!0,detail:{link:e,source:t}}))}createLink(e,s,n){const a=document.createElement("a");return a.href=t(e.href,"#"),a.className=[s,e.emphasize&&`${s}--emphasize`].filter(Boolean).join(" "),a.textContent=e.label,e.external&&(a.target="_blank",a.rel="noopener noreferrer"),a.addEventListener("click",t=>{t.preventDefault(),this.dispatchLinkClick(e,n)}),a}createSocialLink(s,n){const i=document.createElement("a");i.href=t(s.href,"#"),i.className="designbase-wc-footer__social-link",i.target="_blank",i.rel="noopener noreferrer",i.setAttribute("aria-label",s.label||s.platform);const o=a[s.platform]||"share-alt";return i.append(e(o,n)),i.addEventListener("click",e=>{e.preventDefault(),this.dispatchEvent(new CustomEvent("db-social-click",{bubbles:!0,composed:!0,detail:{link:s}}))}),i}createCompanyInfoRows(e){const t=[],s=[];e.companyName&&s.push(e.companyName),e.representative&&s.push(`대표: ${e.representative}`),e.businessNumber&&s.push(`사업자등록번호: ${e.businessNumber}`),s.length&&t.push(s.join(" | "));const n=[];e.address&&n.push(e.address),e.phone&&n.push(`대표전화: ${e.phone}`),e.customerCenter&&n.push(`고객센터: ${e.customerCenter}`),n.length&&t.push(n.join(" | "));const a=[];return e.email&&a.push(`이메일: ${e.email}`),e.mailOrderNumber&&a.push(`통신판매업신고: ${e.mailOrderNumber}`),e.hostingProvider&&a.push(`호스팅: ${e.hostingProvider}`),a.length&&t.push(a.join(" | ")),t}showLogo(){return!this.hasAttribute("show-logo")||"false"!==this.getAttribute("show-logo")}createLogo(){const e=document.createElement("div");e.className="designbase-wc-footer__logo";const t=document.createElement("db-logo");return t.setAttribute("type",this.getAttribute("logo-type")||"designbase"),t.setAttribute("size","s"),t.setAttribute("clickable",""),t.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),e.append(t),e}renderBrand(e,t={}){const{showTagline:s=!0}=t,n=document.createElement("div");n.className="designbase-wc-footer__brand",this.showLogo()&&n.append(this.createLogo());const a=this.getAttribute("tagline");if(s&&a){const e=document.createElement("p");e.className="designbase-wc-footer__tagline",e.textContent=a,n.append(e)}const i=this.socialLinks;if(i.length&&(!this.hasAttribute("show-social")||"false"!==this.getAttribute("show-social"))){const t=document.createElement("div");t.className="designbase-wc-footer__social",i.forEach(s=>t.append(this.createSocialLink(s,e))),n.append(t)}return n}renderColumns(e){if(!e.length)return null;const t=document.createElement("div");return t.className="designbase-wc-footer__columns",t.style.setProperty("--db-footer-columns",String(Math.min(e.length,4))),e.forEach(e=>{const s=document.createElement("div");s.className="designbase-wc-footer__column";const n=document.createElement("h3");n.className="designbase-wc-footer__column-title",n.textContent=e.title,s.append(n);const a=document.createElement("ul");a.className="designbase-wc-footer__column-list",e.items.forEach(e=>{const t=document.createElement("li");t.append(this.createLink(e,"designbase-wc-footer__column-link","column")),a.append(t)}),s.append(a),t.append(s)}),t}createLegalNav(e){const t=document.createElement("nav");t.className="designbase-wc-footer__legal-nav",t.setAttribute("aria-label","법적 고지");const s=document.createElement("ul");return s.className="designbase-wc-footer__legal-list",e.forEach((t,n)=>{const a=document.createElement("li");if(a.append(this.createLink(t,"designbase-wc-footer__legal-link","legal")),s.append(a),n<e.length-1){const e=document.createElement("span");e.className="designbase-wc-footer__legal-divider",e.setAttribute("aria-hidden","true"),e.textContent="|",a.append(e)}}),t.append(s),t}renderLegalBar(e,t){if(!e.length&&!t.length)return null;const s=document.createElement("div");if(s.className="designbase-wc-footer__legal-bar",e.length&&s.append(this.createLegalNav(e)),t.length){const e=document.createElement("div");e.className="designbase-wc-footer__family-site";const n=document.createElement("select");n.className="designbase-wc-footer__family-select",n.setAttribute("aria-label",this.getAttribute("family-site-label")||"패밀리 사이트");const a=document.createElement("option");a.value="",a.textContent=this.getAttribute("family-site-label")||"패밀리 사이트",a.disabled=!0,a.selected=!0,n.append(a),t.forEach(e=>{const t=document.createElement("option");t.value=e.href,t.textContent=e.label,t.dataset.id=e.id,n.append(t)}),n.addEventListener("change",()=>{const e=t.find(e=>e.href===n.value);e&&(n.selectedIndex=0,this.dispatchEvent(new CustomEvent("db-family-site-change",{bubbles:!0,composed:!0,detail:{site:e}})))}),e.append(n),s.append(e)}return s}renderCompanyInfo(e){const t=this.createCompanyInfoRows(e);if(!t.length)return null;const s=document.createElement("div");return s.className="designbase-wc-footer__company",t.forEach(e=>{const t=document.createElement("p");t.className="designbase-wc-footer__company-line",t.textContent=e,s.append(t)}),s}createCopyright(e){const t=document.createElement("div");t.className="designbase-wc-footer__bottom";const s=document.createElement("p");return s.className="designbase-wc-footer__copyright",s.textContent=e,t.append(s),t}renderMinimal(e,t,s){const n=document.createElement("div");n.className="designbase-wc-footer__minimal-bar";const a=document.createElement("div");if(a.className="designbase-wc-footer__minimal-start",this.showLogo()&&a.append(this.createLogo()),n.append(a),t.length){const e=document.createElement("div");e.className="designbase-wc-footer__minimal-legal",e.append(this.createLegalNav(t)),n.append(e)}e.append(n),e.append(this.createCopyright(s))}render(){this.syncHostClasses(),this.setAttribute("role","contentinfo");const e=this.getAttribute("variant")||"default",t=this.getAttribute("size")||"m",s="s"===t?18:"l"===t?22:20,n="default"===e?this.columns:[],a=this.legalLinks,i=this.companyInfo,o=this.familySites,r=this.getAttribute("copyright")||`© ${(new Date).getFullYear()} Designbase. All rights reserved.`;this.replaceChildren();const l=document.createElement("div");if(l.className=["designbase-wc-footer__container",this.hasAttribute("full-width")&&"designbase-wc-footer__container--full-width"].filter(Boolean).join(" "),"minimal"===e)return this.renderMinimal(l,a,r),void this.append(l);const c=document.createElement("div");c.className="designbase-wc-footer__top",c.append(this.renderBrand(s,{showTagline:"compact"!==e}));const d=this.renderColumns(n);d&&c.append(d),l.append(c);const m=this.renderLegalBar(a,o);m&&l.append(m);const u=this.renderCompanyInfo(i);u&&l.append(u),l.append(this.createCopyright(r)),this.append(l)}}customElements.get("db-footer")||customElements.define("db-footer",DbFooter);export{DbFooter};
1
+ import{dbText as e}from"../core/i18n.js";import{createShareIcon as t}from"./db-share-icons.js";import{sanitizeHref as n}from"../core/safe-url.js";import{FOOTER_SIZES as s,FOOTER_VARIANTS as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={youtube:"youtube",instagram:"instagram",x:"x",linkedin:"linkedin",facebook:"facebook",email:"mail"};function parseJson(e,t){if(!e)return t;try{return JSON.parse(e)??t}catch{return t}}class DbFooter extends HTMLElement{constructor(){super(...arguments),this.brandContent=null,this.bottomContent=null}static get observedAttributes(){return["columns","legal-links","social-links","company-info","family-sites","tagline","copyright","logo-type","variant","size","full-width","show-logo","show-social","family-site-label"]}connectedCallback(){this.render()}attributeChangedCallback(){this.isConnected&&this.render()}get columns(){return parseJson(this.getAttribute("columns"),[])}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}get legalLinks(){return parseJson(this.getAttribute("legal-links"),[])}set legalLinks(e){this.setAttribute("legal-links","string"==typeof e?e:JSON.stringify(e))}get socialLinks(){return parseJson(this.getAttribute("social-links"),[])}set socialLinks(e){this.setAttribute("social-links","string"==typeof e?e:JSON.stringify(e))}get companyInfo(){return parseJson(this.getAttribute("company-info"),{})}set companyInfo(e){this.setAttribute("company-info","string"==typeof e?e:JSON.stringify(e))}get familySites(){return parseJson(this.getAttribute("family-sites"),[])}set familySites(e){this.setAttribute("family-sites","string"==typeof e?e:JSON.stringify(e))}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",n=s.includes(e)?e:"m",a=o.includes(t)?t:"default",i=[...this.classList].filter(e=>!e.startsWith("designbase-wc-footer"));this.className=[...i,"designbase-wc-footer",`designbase-wc-footer--${n}`,`designbase-wc-footer--${a}`,this.hasAttribute("full-width")&&"designbase-wc-footer--full-width"].filter(Boolean).join(" ")}dispatchLinkClick(e,t){this.dispatchEvent(new CustomEvent("db-link-click",{bubbles:!0,composed:!0,detail:{link:e,source:t}}))}createLink(e,t,s){const o=document.createElement("a");return o.href=n(e.href,"#"),o.className=[t,e.emphasize&&`${t}--emphasize`].filter(Boolean).join(" "),o.textContent=e.label,e.external&&(o.target="_blank",o.rel="noopener noreferrer"),o.addEventListener("click",t=>{t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||0!==t.button||(t.preventDefault(),this.dispatchLinkClick(e,s))}),o}createSocialLink(e,s){const o=document.createElement("a");o.href=n(e.href,"#"),o.className="designbase-wc-footer__social-link",o.target="_blank",o.rel="noopener noreferrer",o.setAttribute("aria-label",e.label||e.platform);const i=a[e.platform]||"share-alt";return o.append(t(i,s)),o.addEventListener("click",t=>{t.preventDefault(),this.dispatchEvent(new CustomEvent("db-social-click",{bubbles:!0,composed:!0,detail:{link:e}}))}),o}createCompanyInfoRows(e){const t=[],n=[];e.companyName&&n.push(e.companyName),e.representative&&n.push(`대표: ${e.representative}`),e.businessNumber&&n.push(`사업자등록번호: ${e.businessNumber}`),n.length&&t.push(n.join(" | "));const s=[];e.address&&s.push(e.address),e.phone&&s.push(`대표전화: ${e.phone}`),e.customerCenter&&s.push(`고객센터: ${e.customerCenter}`),s.length&&t.push(s.join(" | "));const o=[];return e.email&&o.push(`이메일: ${e.email}`),e.mailOrderNumber&&o.push(`통신판매업신고: ${e.mailOrderNumber}`),e.hostingProvider&&o.push(`호스팅: ${e.hostingProvider}`),o.length&&t.push(o.join(" | ")),t}showLogo(){return!this.hasAttribute("show-logo")||"false"!==this.getAttribute("show-logo")}createLogo(){const e=document.createElement("div");e.className="designbase-wc-footer__logo";const t=document.createElement("db-logo");return t.setAttribute("type",this.getAttribute("logo-type")||"designbase"),t.setAttribute("size","s"),t.setAttribute("clickable",""),t.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),e.append(t),e}renderBrand(e,t={}){const{showTagline:n=!0}=t,s=document.createElement("div");if(s.className="designbase-wc-footer__brand",this.brandContent)return s.append(this.brandContent),s;this.showLogo()&&s.append(this.createLogo());const o=this.getAttribute("tagline");if(n&&o){const e=document.createElement("p");e.className="designbase-wc-footer__tagline",e.textContent=o,s.append(e)}const a=this.socialLinks;if(a.length&&(!this.hasAttribute("show-social")||"false"!==this.getAttribute("show-social"))){const t=document.createElement("div");t.className="designbase-wc-footer__social",a.forEach(n=>t.append(this.createSocialLink(n,e))),s.append(t)}return s}renderColumns(e){if(!e.length)return null;const t=document.createElement("div");return t.className="designbase-wc-footer__columns",t.style.setProperty("--db-footer-columns",String(Math.min(e.length,4))),e.forEach(e=>{const n=document.createElement("div");n.className="designbase-wc-footer__column";const s=document.createElement("h3");s.className="designbase-wc-footer__column-title",s.textContent=e.title,n.append(s);const o=document.createElement("ul");o.className="designbase-wc-footer__column-list",e.items.forEach(e=>{const t=document.createElement("li");t.append(this.createLink(e,"designbase-wc-footer__column-link","column")),o.append(t)}),n.append(o),t.append(n)}),t}createLegalNav(t){const n=document.createElement("nav");n.className="designbase-wc-footer__legal-nav",n.setAttribute("aria-label",e("법적 고지"));const s=document.createElement("ul");return s.className="designbase-wc-footer__legal-list",t.forEach((e,n)=>{const o=document.createElement("li");if(o.append(this.createLink(e,"designbase-wc-footer__legal-link","legal")),s.append(o),n<t.length-1){const e=document.createElement("span");e.className="designbase-wc-footer__legal-divider",e.setAttribute("aria-hidden","true"),e.textContent="|",o.append(e)}}),n.append(s),n}renderLegalBar(e,t){if(!e.length&&!t.length)return null;const n=document.createElement("div");if(n.className="designbase-wc-footer__legal-bar",e.length&&n.append(this.createLegalNav(e)),t.length){const e=document.createElement("div");e.className="designbase-wc-footer__family-site";const s=document.createElement("select");s.className="designbase-wc-footer__family-select",s.setAttribute("aria-label",this.getAttribute("family-site-label")||"패밀리 사이트");const o=document.createElement("option");o.value="",o.textContent=this.getAttribute("family-site-label")||"패밀리 사이트",o.disabled=!0,o.selected=!0,s.append(o),t.forEach(e=>{const t=document.createElement("option");t.value=e.href,t.textContent=e.label,t.dataset.id=e.id,s.append(t)}),s.addEventListener("change",()=>{const e=t.find(e=>e.href===s.value);e&&(s.selectedIndex=0,this.dispatchEvent(new CustomEvent("db-family-site-change",{bubbles:!0,composed:!0,detail:{site:e}})))}),e.append(s),n.append(e)}return n}renderCompanyInfo(e){const t=this.createCompanyInfoRows(e);if(!t.length)return null;const n=document.createElement("div");return n.className="designbase-wc-footer__company",t.forEach(e=>{const t=document.createElement("p");t.className="designbase-wc-footer__company-line",t.textContent=e,n.append(t)}),n}createCopyright(e){const t=document.createElement("div");t.className="designbase-wc-footer__bottom";const n=document.createElement("p");return n.className="designbase-wc-footer__copyright",n.textContent=e,t.append(n),this.bottomContent&&t.append(this.bottomContent),t}renderMinimal(e,t,n){const s=document.createElement("div");s.className="designbase-wc-footer__minimal-bar";const o=document.createElement("div");if(o.className="designbase-wc-footer__minimal-start",this.brandContent?o.append(this.brandContent):this.showLogo()&&o.append(this.createLogo()),s.append(o),t.length){const e=document.createElement("div");e.className="designbase-wc-footer__minimal-legal",e.append(this.createLegalNav(t)),s.append(e)}e.append(s),e.append(this.createCopyright(n))}render(){this.syncHostClasses(),this.setAttribute("role","contentinfo");const e=this.getAttribute("variant")||"default",t=this.getAttribute("size")||"m",n="s"===t?18:"l"===t?22:20,s="default"===e?this.columns:[],o=this.legalLinks,a=this.companyInfo,i=this.familySites,r=this.getAttribute("copyright")||`© ${(new Date).getFullYear()} Designbase. All rights reserved.`;this.brandContent=this.querySelector('[slot="brand"]'),this.bottomContent=this.querySelector('[slot="bottom"]'),this.brandContent?.remove(),this.bottomContent?.remove(),this.replaceChildren();const l=document.createElement("div");if(l.className=["designbase-wc-footer__container",this.hasAttribute("full-width")&&"designbase-wc-footer__container--full-width"].filter(Boolean).join(" "),"minimal"===e)return this.renderMinimal(l,o,r),void this.append(l);const c=document.createElement("div");c.className="designbase-wc-footer__top",c.append(this.renderBrand(n,{showTagline:"compact"!==e}));const d=this.renderColumns(s);d&&c.append(d),l.append(c);const m=this.renderLegalBar(o,i);m&&l.append(m);const u=this.renderCompanyInfo(a);u&&l.append(u),l.append(this.createCopyright(r)),this.append(l)}}customElements.get("db-footer")||customElements.define("db-footer",DbFooter);export{DbFooter};
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{rafThrottle as t}from"../core/dom.js";const a=["day","week"],s=["#86efac","#fde047","#93c5fd","#c4b5fd","#f9a8d4","#5eead4","#fdba74","#a5b4fc"],r=["일","월","화","수","목","금","토"],n=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function parseDate(e){const[t,a,s]=e.split("-").map(Number);return new Date(t,a-1,s)}function toDateKey(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function addDays(e,t){const a=new Date(e);return a.setDate(a.getDate()+t),a}function daysBetween(e,t){const a=Date.UTC(e.getFullYear(),e.getMonth(),e.getDate()),s=Date.UTC(t.getFullYear(),t.getMonth(),t.getDate());return Math.round((s-a)/864e5)}function clampDate(e,t,a){return e<t?new Date(t):e>a?new Date(a):e}class DbGantt extends HTMLElement{constructor(){super(...arguments),this.collapsedGroups=new Set,this.dragState=null,this.reorderState=null,this.reorderDropIndex=null,this.suppressRender=!1,this.didDrag=!1,this.handlePointerMove=t(e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.updateReorderDropTarget(e.clientY);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",a,"day"),s=this.getNumber("cell-width","week"===t?72:44),{start:r,end:n}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/s);0!==i&&(this.didDrag=!0);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);if("move"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,r,n),o=clampDate(o,r,n),d>o)return;const l=this.items.find(e=>e.id===this.dragState.itemId);l&&this.applyBarGeometry(this.dragState.barEl,{...l,startDate:toDateKey(d),endDate:toDateKey(o)},r,s)}),this.handlePointerUp=e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.finishReorderDrag(e);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",a,"day"),s=this.getNumber("cell-width","week"===t?72:44),{start:r,end:n}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/s);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);const l=this.dragState.mode,c=this.dragState.itemId;"move"===l?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===l?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,r,n),o=clampDate(o,r,n),this.dragState.barEl.releasePointerCapture(e.pointerId),this.dragState.barEl.classList.remove("designbase-wc-gantt__bar--dragging"),this.dragState=null;const g=this.items.find(e=>e.id===c);if(!g)return;const p=toDateKey(d),h=toDateKey(o);p===g.startDate&&h===g.endDate||(this.updateItem(c,{startDate:p,endDate:h},"move"===l?"move":"resize"),this.render())}}static get observedAttributes(){return["groups","rows","items","start-date","end-date","today","scale","cell-width","show-weekends","show-today","sidebar-label","full-width","disabled","draggable","reorderable","locale"]}get groups(){return this.parseJson("groups",[])}set groups(e){this.setAttribute("groups","string"==typeof e?e:JSON.stringify(e))}get rows(){return this.parseJson("rows",[])}set rows(e){this.setAttribute("rows","string"==typeof e?e:JSON.stringify(e))}get items(){return this.parseJson("items",[])}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label","프로젝트 타임라인"),this.addEventListener("pointermove",this.handlePointerMove),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.render()}disconnectedCallback(){this.removeEventListener("pointermove",this.handlePointerMove),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){!this.isConnected||this.suppressRender||this.dragState||this.reorderState||this.render()}parseJson(e,t){try{return JSON.parse(this.getAttribute(e)||"null")??t}catch{return t}}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}getNumber(e,t){const a=Number(this.getAttribute(e));return Number.isFinite(a)&&a>0?a:t}getOption(e,t,a){const s=this.getAttribute(e);return s&&t.includes(s)?s:a}getLocale(){return this.getAttribute("locale")||"ko-KR"}getWeekdays(){return this.getLocale().startsWith("ko")?r:n}getViewRange(){const e=this.getAttribute("start-date"),t=this.getAttribute("end-date");if(e&&t)return{start:parseDate(e),end:parseDate(t)};const a=this.items.flatMap(e=>[parseDate(e.startDate),parseDate(e.endDate)]);if(0===a.length){const e=new Date,t=new Date(e.getFullYear(),e.getMonth(),1);return{start:t,end:addDays(t,29)}}const s=new Date(Math.min(...a.map(e=>e.getTime()))),r=new Date(Math.max(...a.map(e=>e.getTime())));return{start:addDays(s,-2),end:addDays(r,2)}}getTodayDate(){const e=this.getAttribute("today");return e?parseDate(e):new Date}getDateColumns(e,t){const a=daysBetween(e,t)+1;return Array.from({length:a},(t,a)=>addDays(e,a))}getVisibleRows(){const e=this.groups,t=this.rows;if(0===e.length)return t.map(e=>({type:"row",row:e}));const a=[];for(const s of e)a.push({type:"group",group:s}),this.collapsedGroups.has(s.id)||t.filter(e=>e.groupId===s.id).forEach(e=>a.push({type:"row",row:e}));return t.filter(t=>!t.groupId||!e.some(e=>e.id===t.groupId)).forEach(e=>a.push({type:"row",row:e})),a}getMonthSegments(e){const t=[];let a="",s=0;for(const r of e){const e=`${r.getFullYear()}-${r.getMonth()}`;e!==a?(s>0&&t.push({label:a,span:s}),a=e,s=1):s+=1}return s>0&&t.push({label:a,span:s}),t.map(e=>{const[t,a]=e.label.split("-").map(Number);return{label:new Date(t,a,1).toLocaleDateString(this.getLocale(),{year:"numeric",month:"long"}),span:e.span}})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e[0]).join("").slice(0,2).toUpperCase()}updateItem(e,t,a){const s=this.items.map(a=>a.id===e?{...a,...t}:a);this.emitItemsChange(s,a,e)}emitItemsChange(e,t,a){this.suppressRender=!0,this.items=e,this.suppressRender=!1;const s=e.find(e=>e.id===a);this.dispatchEvent(new CustomEvent("db-item-change",{detail:{item:s,items:e,action:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:this.groups,rows:this.rows,items:e},bubbles:!0,composed:!0}))}applyBarGeometry(e,t,a,s){const r=parseDate(t.startDate),n=parseDate(t.endDate),i=daysBetween(a,r),d=daysBetween(r,n)+1;e.style.left=i*s+2+"px",e.style.width=`${Math.max(d*s-4,s-4)}px`}startBarDrag(e,t,a,s){!this.getBool("draggable",!0)||this.getBool("disabled")||t.disabled||(e.preventDefault(),e.stopPropagation(),this.didDrag=!1,s.setPointerCapture(e.pointerId),s.classList.add("designbase-wc-gantt__bar--dragging"),this.dragState={itemId:t.id,mode:a,pointerId:e.pointerId,startX:e.clientX,originalStart:parseDate(t.startDate),originalEnd:parseDate(t.endDate),barEl:s})}canReorder(){return this.getBool("reorderable",!0)&&!this.getBool("disabled")}createDragHandle(t,a,s){const r=document.createElement("span");return r.className="designbase-wc-gantt__drag-handle",r.setAttribute("role","button"),r.setAttribute("aria-label","group"===t?"그룹 순서 변경":"행 순서 변경"),r.append(e("grip-vertical",12)),this.canReorder()?(r.addEventListener("pointerdown",e=>{e.preventDefault(),e.stopPropagation(),this.startReorderDrag(e,t,a,s,r)}),r):r}getGroupIndex(e){return this.groups.findIndex(t=>t.id===e)}getRowScope(e){return this.rows.filter(t=>(t.groupId||"")===(e||""))}getRowIndexInScope(e,t){return this.getRowScope(t).findIndex(t=>t.id===e)}getReorderTargets(e,t){return Array.from(this.querySelectorAll("group"===e?".designbase-wc-gantt__label-cell--group":`.designbase-wc-gantt__label-cell--row[data-group-id="${t||""}"]`))}startReorderDrag(e,t,a,s,r){const n="group"===t?this.getGroupIndex(a):this.getRowIndexInScope(a,s);n<0||(r.setPointerCapture(e.pointerId),this.reorderState={kind:t,id:a,groupId:s,pointerId:e.pointerId,startY:e.clientY,fromIndex:n,captureEl:r},this.classList.add("designbase-wc-gantt--reordering"),this.updateReorderDropTarget(e.clientY))}updateReorderDropTarget(e){if(!this.reorderState)return;const t=this.getReorderTargets(this.reorderState.kind,this.reorderState.groupId);let a=null;t.forEach((t,s)=>{const r=t.getBoundingClientRect(),n=r.top+r.height/2,i=e>=r.top&&e<=r.bottom,d=e>n;t.classList.toggle("designbase-wc-gantt__label-cell--drag-over",i),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-before",i&&!d),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-after",i&&d),i&&(a=d?s+1:s)}),this.reorderDropIndex=a}clearReorderIndicators(){this.querySelectorAll(".designbase-wc-gantt__label-cell--drag-over").forEach(e=>{e.classList.remove("designbase-wc-gantt__label-cell--drag-over","designbase-wc-gantt__label-cell--drag-over-before","designbase-wc-gantt__label-cell--drag-over-after")})}finishReorderDrag(e){if(!this.reorderState)return;const{kind:t,id:a,groupId:s,fromIndex:r,captureEl:n}=this.reorderState;try{n.releasePointerCapture(this.reorderState.pointerId)}catch{}const i=this.reorderDropIndex;if(this.reorderState=null,this.reorderDropIndex=null,this.classList.remove("designbase-wc-gantt--reordering"),this.clearReorderIndicators(),null===i)return;const d=i>r?i-1:i;d<0||d===r||("group"===t?this.reorderGroups(r,d,a):this.reorderRows(r,d,a,s))}emitStructureChange(e,t,a,s){this.suppressRender=!0,this.groups=e,this.rows=t,this.suppressRender=!1,this.dispatchEvent(new CustomEvent(s,{detail:{...a,groups:e,rows:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:e,rows:t,items:this.items},bubbles:!0,composed:!0})),this.render()}reorderGroups(e,t,a){const s=[...this.groups],[r]=s.splice(e,1);r&&(s.splice(t,0,r),this.emitStructureChange(s,this.rows,{groupId:a,fromIndex:e,toIndex:t},"db-group-reorder"))}reorderRows(e,t,a,s){const r=this.getRowScope(s),n=[...r],[i]=n.splice(e,1);if(!i)return;n.splice(t,0,i);const d=new Set(r.map(e=>e.id)),o=[];let l=!1;for(const e of this.rows)d.has(e.id)?l||(o.push(...n),l=!0):o.push(e);l||o.push(...n),this.emitStructureChange(this.groups,o,{rowId:a,groupId:s,fromIndex:e,toIndex:t},"db-row-reorder")}createGroupBadge(e){const t=document.createElement("db-badge");return t.className="designbase-wc-gantt__group-badge",t.setAttribute("type","dot"),t.setAttribute("size","s"),t.setAttribute("variant","primary"),t.setAttribute("aria-hidden","true"),e&&t.style.setProperty("--db-gantt-badge-color",e),t}createGroupChevron(t){const a=document.createElement("span");return a.className=["designbase-wc-gantt__group-chevron",t?"designbase-wc-gantt__group-chevron--collapsed":""].filter(Boolean).join(" "),a.append(e("chevron-down",12)),a}createAssignee(e){const t=document.createElement("span");if(t.className="designbase-wc-gantt__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.src=e.avatar,a.alt=e.name,t.appendChild(a)}else t.textContent=this.getInitials(e);return t}createStatusIcon(e){const t=document.createElement("span");return t.className=`designbase-wc-gantt__status designbase-wc-gantt__status--${e}`,t.setAttribute("aria-hidden","true"),t.textContent="completed"===e?"✓":"!",t}deriveSummaryColor(e,t){if(0===e.length)return t||s[0];const a=e.filter(e=>e.color);if(0===a.length)return t||s[0];return a.reduce((e,t)=>{const a=daysBetween(parseDate(e.startDate),parseDate(e.endDate));return daysBetween(parseDate(t.startDate),parseDate(t.endDate))>a?t:e}).color||t||s[0]}getGroupSummary(e,t){const a=this.rows.filter(t=>t.groupId===e),s=this.items.filter(e=>a.some(t=>t.id===e.rowId));if(0===s.length)return null;const r=s.map(e=>parseDate(e.startDate).getTime()),n=s.map(e=>parseDate(e.endDate).getTime()),i=s.map(e=>e.progress).filter(e=>"number"==typeof e);return{startDate:toDateKey(new Date(Math.min(...r))),endDate:toDateKey(new Date(Math.max(...n))),color:this.deriveSummaryColor(s,t),progress:i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0,count:s.length}}applyBarTone(e,t){const a=function deriveBarTone(e){return{base:`color-mix(in srgb, ${e} 42%, white)`,progress:`color-mix(in srgb, ${e} 58%, white)`}}(t);e.style.setProperty("--db-gantt-bar-color",t),e.style.setProperty("--db-gantt-bar-bg",a.base),e.style.setProperty("--db-gantt-bar-progress-bg",a.progress)}createGroupSummaryBar(e,t,a,s){const r=clampDate(parseDate(e.startDate),t,a),n=clampDate(parseDate(e.endDate),t,a);if(n<t||r>a)return null;const i=daysBetween(t,r),d=daysBetween(r,n)+1,o=Math.min(100,Math.max(0,e.progress)),l=document.createElement("div");if(l.className="designbase-wc-gantt__group-summary",l.setAttribute("aria-hidden","true"),l.title=`${e.count}개 태스크`,this.applyBarTone(l,e.color),l.style.left=i*s+2+"px",l.style.width=`${Math.max(d*s-4,s-4)}px`,o>0){const e=document.createElement("span");e.className="designbase-wc-gantt__group-summary-progress",e.style.width=`${o}%`,l.appendChild(e)}return l}createBar(e,t,a,r){const n=e.color||s[r%s.length],i=document.createElement("div");i.className="designbase-wc-gantt__bar",i.setAttribute("role","button"),i.setAttribute("tabindex",e.disabled?"-1":"0"),i.setAttribute("aria-disabled",String(Boolean(e.disabled)||this.getBool("disabled"))),i.setAttribute("aria-label",`${e.title}, ${e.startDate} – ${e.endDate}`),this.applyBarTone(i,n),e.disabled&&i.classList.add("designbase-wc-gantt__bar--disabled"),this.applyBarGeometry(i,e,t,a);const d="number"==typeof e.progress?Math.min(100,Math.max(0,e.progress)):0;if(d>0){const e=document.createElement("span");e.className="designbase-wc-gantt__bar-progress",e.style.width=`${d}%`,i.appendChild(e)}const o=document.createElement("div");o.className="designbase-wc-gantt__bar-body","delayed"!==e.status&&"at-risk"!==e.status||o.appendChild(this.createStatusIcon(e.status));const l=document.createElement("span");l.className="designbase-wc-gantt__bar-label",l.textContent=e.title,o.appendChild(l),e.assignee&&o.appendChild(this.createAssignee(e.assignee));const c=document.createElement("span");c.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--start",c.setAttribute("aria-hidden","true");const g=document.createElement("span");return g.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--end",g.setAttribute("aria-hidden","true"),i.append(c,o,g),e.disabled||!this.getBool("draggable",!0)||this.getBool("disabled")||(c.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-start",i)),g.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-end",i)),o.addEventListener("pointerdown",t=>{t.target.closest(".designbase-wc-gantt__bar-handle")||this.startBarDrag(t,e,"move",i)})),i.addEventListener("click",t=>{this.dragState||this.didDrag?this.didDrag=!1:(t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:e},bubbles:!0,composed:!0})))}),i}toggleGroup(e){this.collapsedGroups.has(e)?this.collapsedGroups.delete(e):this.collapsedGroups.add(e),this.dispatchEvent(new CustomEvent("db-group-toggle",{detail:{groupId:e,collapsed:this.collapsedGroups.has(e)},bubbles:!0,composed:!0})),this.render()}render(){const e=this.items,t=this.getOption("scale",a,"day"),r=this.getNumber("cell-width","week"===t?72:44),n=this.getBool("show-weekends",!0),i=this.getBool("show-today",!0),d=this.getAttribute("sidebar-label")||"할 일",o=this.getBool("disabled"),l=this.getBool("full-width",!0),c=this.getWeekdays(),{start:g,end:p}=this.getViewRange(),h=this.getDateColumns(g,p),u=toDateKey(this.getTodayDate()),m=h.findIndex(e=>toDateKey(e)===u),b=this.getVisibleRows(),w=h.length*r,D=document.createElement("div");D.className=["designbase-wc-gantt",l?"designbase-wc-gantt--full-width":"",o?"designbase-wc-gantt--disabled":"",this.getBool("draggable",!0)?"designbase-wc-gantt--draggable":""].filter(Boolean).join(" ");const y=document.createElement("div");y.className="designbase-wc-gantt__viewport";const _=document.createElement("div");_.className="designbase-wc-gantt__grid",_.style.setProperty("--db-gantt-chart-width",`${w}px`),_.style.setProperty("--db-gantt-cell-width",`${r}px`);const f=document.createElement("div");f.className="designbase-wc-gantt__corner",f.textContent=d,_.appendChild(f);const v=document.createElement("div");v.className="designbase-wc-gantt__date-header";const E=document.createElement("div");E.className="designbase-wc-gantt__month-row";for(const e of this.getMonthSegments(h)){const t=document.createElement("div");t.className="designbase-wc-gantt__month-cell",t.style.width=e.span*r+"px",t.textContent=e.label,E.appendChild(t)}v.appendChild(E);const S=document.createElement("div");S.className="designbase-wc-gantt__day-row";for(const e of h){const t=toDateKey(e)===u,a=0===e.getDay()||6===e.getDay(),s=document.createElement("div");s.className=["designbase-wc-gantt__day-cell",t&&i?"designbase-wc-gantt__day-cell--today":"",a&&n?"designbase-wc-gantt__day-cell--weekend":""].filter(Boolean).join(" "),s.style.width=`${r}px`;const d=document.createElement("span");d.className="designbase-wc-gantt__day-num",d.textContent=String(e.getDate());const o=document.createElement("span");o.className="designbase-wc-gantt__day-name",o.textContent=c[e.getDay()],s.append(d,o),S.appendChild(s)}v.appendChild(S),_.appendChild(v);const C=new Map;e.forEach((e,t)=>{const a=C.get(e.rowId)||[];a.push({...e,color:e.color||s[t%s.length]}),C.set(e.rowId,a)});let I=0;for(const e of b){if("group"===e.type){const{group:t}=e,a=this.collapsedGroups.has(t.id),s=document.createElement("button");s.type="button",s.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--group",s.setAttribute("aria-expanded",String(!a)),s.dataset.groupId=t.id;const i=document.createElement("span");i.className="designbase-wc-gantt__group-title",i.textContent=t.title,s.append(this.createDragHandle("group",t.id),this.createGroupChevron(a),this.createGroupBadge(t.color),i),s.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.toggleGroup(t.id)}),_.appendChild(s);const d=document.createElement("div");if(d.className="designbase-wc-gantt__track-cell designbase-wc-gantt__track-cell--group",a){const e=this.getGroupSummary(t.id,t.color);if(e){const t=document.createElement("div");t.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const a=document.createElement("div"),s=0===e.getDay()||6===e.getDay();a.className=["designbase-wc-gantt__grid-cell",s&&n?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),a.style.width=`${r}px`,t.appendChild(a)}),d.appendChild(t);const a=document.createElement("div");a.className="designbase-wc-gantt__group-summary-wrap";const s=this.createGroupSummaryBar(e,g,p,r);s&&a.appendChild(s),d.appendChild(a)}}_.appendChild(d);continue}const{row:t}=e,a=document.createElement("button");a.type="button",a.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--row",a.dataset.groupId=t.groupId||"",a.dataset.rowId=t.id;const s=document.createElement("span");s.className="designbase-wc-gantt__row-title",s.textContent=t.label,a.append(this.createDragHandle("row",t.id,t.groupId),s),a.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.dispatchEvent(new CustomEvent("db-row-click",{detail:{row:t},bubbles:!0,composed:!0}))}),_.appendChild(a);const i=document.createElement("div");i.className="designbase-wc-gantt__track-cell";const d=document.createElement("div");d.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const t=document.createElement("div"),a=0===e.getDay()||6===e.getDay();t.className=["designbase-wc-gantt__grid-cell",a&&n?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),t.style.width=`${r}px`,d.appendChild(t)}),i.appendChild(d);const o=document.createElement("div");o.className="designbase-wc-gantt__bars",(C.get(t.id)||[]).forEach(e=>{const t=clampDate(parseDate(e.startDate),g,p),a=clampDate(parseDate(e.endDate),g,p);a<g||t>p||o.appendChild(this.createBar({...e,startDate:toDateKey(t),endDate:toDateKey(a)},g,r,I++))}),i.appendChild(o),_.appendChild(i)}if(y.appendChild(_),i&&m>=0){const e=document.createElement("div");e.className="designbase-wc-gantt__today-line",e.style.left=`calc(var(--db-gantt-label-width) + ${m*r+r/2}px)`,_.appendChild(e)}D.appendChild(y),this.replaceChildren(D)}}customElements.get("db-gantt")||customElements.define("db-gantt",DbGantt);export{DbGantt};
1
+ import{dbText as e,dbFormat as t,getDbLocale as a}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{rafThrottle as r}from"../core/dom.js";const n=["day","week"],i=["#86efac","#fde047","#93c5fd","#c4b5fd","#f9a8d4","#5eead4","#fdba74","#a5b4fc"],d=["일","월","화","수","목","금","토"],o=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function parseDate(e){const[t,a,s]=e.split("-").map(Number);return new Date(t,a-1,s)}function toDateKey(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function addDays(e,t){const a=new Date(e);return a.setDate(a.getDate()+t),a}function daysBetween(e,t){const a=Date.UTC(e.getFullYear(),e.getMonth(),e.getDate()),s=Date.UTC(t.getFullYear(),t.getMonth(),t.getDate());return Math.round((s-a)/864e5)}function clampDate(e,t,a){return e<t?new Date(t):e>a?new Date(a):e}class DbGantt extends HTMLElement{constructor(){super(...arguments),this.collapsedGroups=new Set,this.dragState=null,this.reorderState=null,this.reorderDropIndex=null,this.suppressRender=!1,this.didDrag=!1,this.handlePointerMove=r(e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.updateReorderDropTarget(e.clientY);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/a);0!==i&&(this.didDrag=!0);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);if("move"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===this.dragState.mode?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,s,r),o=clampDate(o,s,r),d>o)return;const l=this.items.find(e=>e.id===this.dragState.itemId);l&&this.applyBarGeometry(this.dragState.barEl,{...l,startDate:toDateKey(d),endDate:toDateKey(o)},s,a)}),this.handlePointerUp=e=>{if(this.reorderState&&e.pointerId===this.reorderState.pointerId)return void this.finishReorderDrag(e);if(!this.dragState||e.pointerId!==this.dragState.pointerId)return;const t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),{start:s,end:r}=this.getViewRange(),i=Math.round((e.clientX-this.dragState.startX)/a);let d=new Date(this.dragState.originalStart),o=new Date(this.dragState.originalEnd);const l=this.dragState.mode,c=this.dragState.itemId;"move"===l?(d=addDays(this.dragState.originalStart,i),o=addDays(this.dragState.originalEnd,i)):"resize-start"===l?(d=addDays(this.dragState.originalStart,i),d>o&&(d=new Date(o))):(o=addDays(this.dragState.originalEnd,i),o<d&&(o=new Date(d))),d=clampDate(d,s,r),o=clampDate(o,s,r),this.dragState.barEl.releasePointerCapture(e.pointerId),this.dragState.barEl.classList.remove("designbase-wc-gantt__bar--dragging"),this.dragState=null;const g=this.items.find(e=>e.id===c);if(!g)return;const p=toDateKey(d),h=toDateKey(o);p===g.startDate&&h===g.endDate||(this.updateItem(c,{startDate:p,endDate:h},"move"===l?"move":"resize"),this.render())}}static get observedAttributes(){return["groups","rows","items","start-date","end-date","today","scale","cell-width","show-weekends","show-today","sidebar-label","full-width","disabled","draggable","reorderable","locale"]}get groups(){return this.parseJson("groups",[])}set groups(e){this.setAttribute("groups","string"==typeof e?e:JSON.stringify(e))}get rows(){return this.parseJson("rows",[])}set rows(e){this.setAttribute("rows","string"==typeof e?e:JSON.stringify(e))}get items(){return this.parseJson("items",[])}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.setAttribute("role","region"),this.setAttribute("aria-label",e("프로젝트 타임라인")),this.addEventListener("pointermove",this.handlePointerMove),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.render()}disconnectedCallback(){this.removeEventListener("pointermove",this.handlePointerMove),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){!this.isConnected||this.suppressRender||this.dragState||this.reorderState||this.render()}parseJson(e,t){try{return JSON.parse(this.getAttribute(e)||"null")??t}catch{return t}}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const a=this.getAttribute(e);return""===a||"true"===a}getNumber(e,t){const a=Number(this.getAttribute(e));return Number.isFinite(a)&&a>0?a:t}getOption(e,t,a){const s=this.getAttribute(e);return s&&t.includes(s)?s:a}getLocale(){return this.getAttribute("locale")||("ko"===a()?"ko-KR":"en-US")}getWeekdays(){return this.getLocale().startsWith("ko")?d:o}getViewRange(){const e=this.getAttribute("start-date"),t=this.getAttribute("end-date");if(e&&t)return{start:parseDate(e),end:parseDate(t)};const a=this.items.flatMap(e=>[parseDate(e.startDate),parseDate(e.endDate)]);if(0===a.length){const e=new Date,t=new Date(e.getFullYear(),e.getMonth(),1);return{start:t,end:addDays(t,29)}}const s=new Date(Math.min(...a.map(e=>e.getTime()))),r=new Date(Math.max(...a.map(e=>e.getTime())));return{start:addDays(s,-2),end:addDays(r,2)}}getTodayDate(){const e=this.getAttribute("today");return e?parseDate(e):new Date}getDateColumns(e,t){const a=daysBetween(e,t)+1;return Array.from({length:a},(t,a)=>addDays(e,a))}getVisibleRows(){const e=this.groups,t=this.rows;if(0===e.length)return t.map(e=>({type:"row",row:e}));const a=[];for(const s of e)a.push({type:"group",group:s}),this.collapsedGroups.has(s.id)||t.filter(e=>e.groupId===s.id).forEach(e=>a.push({type:"row",row:e}));return t.filter(t=>!t.groupId||!e.some(e=>e.id===t.groupId)).forEach(e=>a.push({type:"row",row:e})),a}getMonthSegments(e){const t=[];let a="",s=0;for(const r of e){const e=`${r.getFullYear()}-${r.getMonth()}`;e!==a?(s>0&&t.push({label:a,span:s}),a=e,s=1):s+=1}return s>0&&t.push({label:a,span:s}),t.map(e=>{const[t,a]=e.label.split("-").map(Number);return{label:new Date(t,a,1).toLocaleDateString(this.getLocale(),{year:"numeric",month:"long"}),span:e.span}})}getInitials(e){return e.initials?e.initials:e.name.split(/\s+/).map(e=>e[0]).join("").slice(0,2).toUpperCase()}updateItem(e,t,a){const s=this.items.map(a=>a.id===e?{...a,...t}:a);this.emitItemsChange(s,a,e)}emitItemsChange(e,t,a){this.suppressRender=!0,this.items=e,this.suppressRender=!1;const s=e.find(e=>e.id===a);this.dispatchEvent(new CustomEvent("db-item-change",{detail:{item:s,items:e,action:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:this.groups,rows:this.rows,items:e},bubbles:!0,composed:!0}))}applyBarGeometry(e,t,a,s){const r=parseDate(t.startDate),n=parseDate(t.endDate),i=daysBetween(a,r),d=daysBetween(r,n)+1;e.style.left=i*s+2+"px",e.style.width=`${Math.max(d*s-4,s-4)}px`}startBarDrag(e,t,a,s){!this.getBool("draggable",!0)||this.getBool("disabled")||t.disabled||(e.preventDefault(),e.stopPropagation(),this.didDrag=!1,s.setPointerCapture(e.pointerId),s.classList.add("designbase-wc-gantt__bar--dragging"),this.dragState={itemId:t.id,mode:a,pointerId:e.pointerId,startX:e.clientX,originalStart:parseDate(t.startDate),originalEnd:parseDate(t.endDate),barEl:s})}canReorder(){return this.getBool("reorderable",!0)&&!this.getBool("disabled")}createDragHandle(e,t,a){const r=document.createElement("span");return r.className="designbase-wc-gantt__drag-handle",r.setAttribute("role","button"),r.setAttribute("aria-label","group"===e?"그룹 순서 변경":"행 순서 변경"),r.append(s("grip-vertical",12)),this.canReorder()?(r.addEventListener("pointerdown",s=>{s.preventDefault(),s.stopPropagation(),this.startReorderDrag(s,e,t,a,r)}),r):r}getGroupIndex(e){return this.groups.findIndex(t=>t.id===e)}getRowScope(e){return this.rows.filter(t=>(t.groupId||"")===(e||""))}getRowIndexInScope(e,t){return this.getRowScope(t).findIndex(t=>t.id===e)}getReorderTargets(e,t){return Array.from(this.querySelectorAll("group"===e?".designbase-wc-gantt__label-cell--group":`.designbase-wc-gantt__label-cell--row[data-group-id="${t||""}"]`))}startReorderDrag(e,t,a,s,r){const n="group"===t?this.getGroupIndex(a):this.getRowIndexInScope(a,s);n<0||(r.setPointerCapture(e.pointerId),this.reorderState={kind:t,id:a,groupId:s,pointerId:e.pointerId,startY:e.clientY,fromIndex:n,captureEl:r},this.classList.add("designbase-wc-gantt--reordering"),this.updateReorderDropTarget(e.clientY))}updateReorderDropTarget(e){if(!this.reorderState)return;const t=this.getReorderTargets(this.reorderState.kind,this.reorderState.groupId);let a=null;t.forEach((t,s)=>{const r=t.getBoundingClientRect(),n=r.top+r.height/2,i=e>=r.top&&e<=r.bottom,d=e>n;t.classList.toggle("designbase-wc-gantt__label-cell--drag-over",i),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-before",i&&!d),t.classList.toggle("designbase-wc-gantt__label-cell--drag-over-after",i&&d),i&&(a=d?s+1:s)}),this.reorderDropIndex=a}clearReorderIndicators(){this.querySelectorAll(".designbase-wc-gantt__label-cell--drag-over").forEach(e=>{e.classList.remove("designbase-wc-gantt__label-cell--drag-over","designbase-wc-gantt__label-cell--drag-over-before","designbase-wc-gantt__label-cell--drag-over-after")})}finishReorderDrag(e){if(!this.reorderState)return;const{kind:t,id:a,groupId:s,fromIndex:r,captureEl:n}=this.reorderState;try{n.releasePointerCapture(this.reorderState.pointerId)}catch{}const i=this.reorderDropIndex;if(this.reorderState=null,this.reorderDropIndex=null,this.classList.remove("designbase-wc-gantt--reordering"),this.clearReorderIndicators(),null===i)return;const d=i>r?i-1:i;d<0||d===r||("group"===t?this.reorderGroups(r,d,a):this.reorderRows(r,d,a,s))}emitStructureChange(e,t,a,s){this.suppressRender=!0,this.groups=e,this.rows=t,this.suppressRender=!1,this.dispatchEvent(new CustomEvent(s,{detail:{...a,groups:e,rows:t},bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-change",{detail:{groups:e,rows:t,items:this.items},bubbles:!0,composed:!0})),this.render()}reorderGroups(e,t,a){const s=[...this.groups],[r]=s.splice(e,1);r&&(s.splice(t,0,r),this.emitStructureChange(s,this.rows,{groupId:a,fromIndex:e,toIndex:t},"db-group-reorder"))}reorderRows(e,t,a,s){const r=this.getRowScope(s),n=[...r],[i]=n.splice(e,1);if(!i)return;n.splice(t,0,i);const d=new Set(r.map(e=>e.id)),o=[];let l=!1;for(const e of this.rows)d.has(e.id)?l||(o.push(...n),l=!0):o.push(e);l||o.push(...n),this.emitStructureChange(this.groups,o,{rowId:a,groupId:s,fromIndex:e,toIndex:t},"db-row-reorder")}createGroupBadge(e){const t=document.createElement("db-badge");return t.className="designbase-wc-gantt__group-badge",t.setAttribute("type","dot"),t.setAttribute("size","s"),t.setAttribute("variant","primary"),t.setAttribute("aria-hidden","true"),e&&t.style.setProperty("--db-gantt-badge-color",e),t}createGroupChevron(e){const t=document.createElement("span");return t.className=["designbase-wc-gantt__group-chevron",e?"designbase-wc-gantt__group-chevron--collapsed":""].filter(Boolean).join(" "),t.append(s("chevron-down",12)),t}createAssignee(e){const t=document.createElement("span");if(t.className="designbase-wc-gantt__assignee",t.title=e.name,e.avatar){const a=document.createElement("img");a.src=e.avatar,a.alt=e.name,t.appendChild(a)}else t.textContent=this.getInitials(e);return t}createStatusIcon(e){const t=document.createElement("span");return t.className=`designbase-wc-gantt__status designbase-wc-gantt__status--${e}`,t.setAttribute("aria-hidden","true"),t.textContent="completed"===e?"✓":"!",t}deriveSummaryColor(e,t){if(0===e.length)return t||i[0];const a=e.filter(e=>e.color);if(0===a.length)return t||i[0];return a.reduce((e,t)=>{const a=daysBetween(parseDate(e.startDate),parseDate(e.endDate));return daysBetween(parseDate(t.startDate),parseDate(t.endDate))>a?t:e}).color||t||i[0]}getGroupSummary(e,t){const a=this.rows.filter(t=>t.groupId===e),s=this.items.filter(e=>a.some(t=>t.id===e.rowId));if(0===s.length)return null;const r=s.map(e=>parseDate(e.startDate).getTime()),n=s.map(e=>parseDate(e.endDate).getTime()),i=s.map(e=>e.progress).filter(e=>"number"==typeof e);return{startDate:toDateKey(new Date(Math.min(...r))),endDate:toDateKey(new Date(Math.max(...n))),color:this.deriveSummaryColor(s,t),progress:i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0,count:s.length}}applyBarTone(e,t){const a=function deriveBarTone(e){return{base:`color-mix(in srgb, ${e} 42%, white)`,progress:`color-mix(in srgb, ${e} 58%, white)`}}(t);e.style.setProperty("--db-gantt-bar-color",t),e.style.setProperty("--db-gantt-bar-bg",a.base),e.style.setProperty("--db-gantt-bar-progress-bg",a.progress)}createGroupSummaryBar(e,a,s,r){const n=clampDate(parseDate(e.startDate),a,s),i=clampDate(parseDate(e.endDate),a,s);if(i<a||n>s)return null;const d=daysBetween(a,n),o=daysBetween(n,i)+1,l=Math.min(100,Math.max(0,e.progress)),c=document.createElement("div");if(c.className="designbase-wc-gantt__group-summary",c.setAttribute("aria-hidden","true"),c.title=t("{0}개 태스크",[e.count]),this.applyBarTone(c,e.color),c.style.left=d*r+2+"px",c.style.width=`${Math.max(o*r-4,r-4)}px`,l>0){const e=document.createElement("span");e.className="designbase-wc-gantt__group-summary-progress",e.style.width=`${l}%`,c.appendChild(e)}return c}createBar(e,t,a,s){const r=e.color||i[s%i.length],n=document.createElement("div");n.className="designbase-wc-gantt__bar",n.setAttribute("role","button"),n.setAttribute("tabindex",e.disabled?"-1":"0"),n.setAttribute("aria-disabled",String(Boolean(e.disabled)||this.getBool("disabled"))),n.setAttribute("aria-label",`${e.title}, ${e.startDate} – ${e.endDate}`),this.applyBarTone(n,r),e.disabled&&n.classList.add("designbase-wc-gantt__bar--disabled"),this.applyBarGeometry(n,e,t,a);const d="number"==typeof e.progress?Math.min(100,Math.max(0,e.progress)):0;if(d>0){const e=document.createElement("span");e.className="designbase-wc-gantt__bar-progress",e.style.width=`${d}%`,n.appendChild(e)}const o=document.createElement("div");o.className="designbase-wc-gantt__bar-body","delayed"!==e.status&&"at-risk"!==e.status||o.appendChild(this.createStatusIcon(e.status));const l=document.createElement("span");l.className="designbase-wc-gantt__bar-label",l.textContent=e.title,o.appendChild(l),e.assignee&&o.appendChild(this.createAssignee(e.assignee));const c=document.createElement("span");c.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--start",c.setAttribute("aria-hidden","true");const g=document.createElement("span");return g.className="designbase-wc-gantt__bar-handle designbase-wc-gantt__bar-handle--end",g.setAttribute("aria-hidden","true"),n.append(c,o,g),e.disabled||!this.getBool("draggable",!0)||this.getBool("disabled")||(c.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-start",n)),g.addEventListener("pointerdown",t=>this.startBarDrag(t,e,"resize-end",n)),o.addEventListener("pointerdown",t=>{t.target.closest(".designbase-wc-gantt__bar-handle")||this.startBarDrag(t,e,"move",n)})),n.addEventListener("click",t=>{this.dragState||this.didDrag?this.didDrag=!1:(t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-item-click",{detail:{item:e},bubbles:!0,composed:!0})))}),n}toggleGroup(e){this.collapsedGroups.has(e)?this.collapsedGroups.delete(e):this.collapsedGroups.add(e),this.dispatchEvent(new CustomEvent("db-group-toggle",{detail:{groupId:e,collapsed:this.collapsedGroups.has(e)},bubbles:!0,composed:!0})),this.render()}render(){const e=this.items,t=this.getOption("scale",n,"day"),a=this.getNumber("cell-width","week"===t?72:44),s=this.getBool("show-weekends",!0),r=this.getBool("show-today",!0),d=this.getAttribute("sidebar-label")||"할 일",o=this.getBool("disabled"),l=this.getBool("full-width",!0),c=this.getWeekdays(),{start:g,end:p}=this.getViewRange(),h=this.getDateColumns(g,p),u=toDateKey(this.getTodayDate()),m=h.findIndex(e=>toDateKey(e)===u),b=this.getVisibleRows(),w=h.length*a,D=document.createElement("div");D.className=["designbase-wc-gantt",l?"designbase-wc-gantt--full-width":"",o?"designbase-wc-gantt--disabled":"",this.getBool("draggable",!0)?"designbase-wc-gantt--draggable":""].filter(Boolean).join(" ");const y=document.createElement("div");y.className="designbase-wc-gantt__viewport";const _=document.createElement("div");_.className="designbase-wc-gantt__grid",_.style.setProperty("--db-gantt-chart-width",`${w}px`),_.style.setProperty("--db-gantt-cell-width",`${a}px`);const f=document.createElement("div");f.className="designbase-wc-gantt__corner",f.textContent=d,_.appendChild(f);const v=document.createElement("div");v.className="designbase-wc-gantt__date-header";const E=document.createElement("div");E.className="designbase-wc-gantt__month-row";for(const e of this.getMonthSegments(h)){const t=document.createElement("div");t.className="designbase-wc-gantt__month-cell",t.style.width=e.span*a+"px",t.textContent=e.label,E.appendChild(t)}v.appendChild(E);const S=document.createElement("div");S.className="designbase-wc-gantt__day-row";for(const e of h){const t=toDateKey(e)===u,n=0===e.getDay()||6===e.getDay(),i=document.createElement("div");i.className=["designbase-wc-gantt__day-cell",t&&r?"designbase-wc-gantt__day-cell--today":"",n&&s?"designbase-wc-gantt__day-cell--weekend":""].filter(Boolean).join(" "),i.style.width=`${a}px`;const d=document.createElement("span");d.className="designbase-wc-gantt__day-num",d.textContent=String(e.getDate());const o=document.createElement("span");o.className="designbase-wc-gantt__day-name",o.textContent=c[e.getDay()],i.append(d,o),S.appendChild(i)}v.appendChild(S),_.appendChild(v);const C=new Map;e.forEach((e,t)=>{const a=C.get(e.rowId)||[];a.push({...e,color:e.color||i[t%i.length]}),C.set(e.rowId,a)});let I=0;for(const e of b){if("group"===e.type){const{group:t}=e,r=this.collapsedGroups.has(t.id),n=document.createElement("button");n.type="button",n.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--group",n.setAttribute("aria-expanded",String(!r)),n.dataset.groupId=t.id;const i=document.createElement("span");i.className="designbase-wc-gantt__group-title",i.textContent=t.title,n.append(this.createDragHandle("group",t.id),this.createGroupChevron(r),this.createGroupBadge(t.color),i),n.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.toggleGroup(t.id)}),_.appendChild(n);const d=document.createElement("div");if(d.className="designbase-wc-gantt__track-cell designbase-wc-gantt__track-cell--group",r){const e=this.getGroupSummary(t.id,t.color);if(e){const t=document.createElement("div");t.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const r=document.createElement("div"),n=0===e.getDay()||6===e.getDay();r.className=["designbase-wc-gantt__grid-cell",n&&s?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),r.style.width=`${a}px`,t.appendChild(r)}),d.appendChild(t);const r=document.createElement("div");r.className="designbase-wc-gantt__group-summary-wrap";const n=this.createGroupSummaryBar(e,g,p,a);n&&r.appendChild(n),d.appendChild(r)}}_.appendChild(d);continue}const{row:t}=e,r=document.createElement("button");r.type="button",r.className="designbase-wc-gantt__label-cell designbase-wc-gantt__label-cell--row",r.dataset.groupId=t.groupId||"",r.dataset.rowId=t.id;const n=document.createElement("span");n.className="designbase-wc-gantt__row-title",n.textContent=t.label,r.append(this.createDragHandle("row",t.id,t.groupId),n),r.addEventListener("click",e=>{e.target.closest(".designbase-wc-gantt__drag-handle")||this.dispatchEvent(new CustomEvent("db-row-click",{detail:{row:t},bubbles:!0,composed:!0}))}),_.appendChild(r);const i=document.createElement("div");i.className="designbase-wc-gantt__track-cell";const d=document.createElement("div");d.className="designbase-wc-gantt__grid-bg",h.forEach(e=>{const t=document.createElement("div"),r=0===e.getDay()||6===e.getDay();t.className=["designbase-wc-gantt__grid-cell",r&&s?"designbase-wc-gantt__grid-cell--weekend":""].filter(Boolean).join(" "),t.style.width=`${a}px`,d.appendChild(t)}),i.appendChild(d);const o=document.createElement("div");o.className="designbase-wc-gantt__bars",(C.get(t.id)||[]).forEach(e=>{const t=clampDate(parseDate(e.startDate),g,p),s=clampDate(parseDate(e.endDate),g,p);s<g||t>p||o.appendChild(this.createBar({...e,startDate:toDateKey(t),endDate:toDateKey(s)},g,a,I++))}),i.appendChild(o),_.appendChild(i)}if(y.appendChild(_),r&&m>=0){const e=document.createElement("div");e.className="designbase-wc-gantt__today-line",e.style.left=`calc(var(--db-gantt-label-width) + ${m*a+a/2}px)`,_.appendChild(e)}D.appendChild(y),this.replaceChildren(D)}}customElements.get("db-gantt")||customElements.define("db-gantt",DbGantt);export{DbGantt};
@@ -0,0 +1,58 @@
1
+ import { GlyphMatrixPreset, GlyphMatrixSize } from '../ui-contracts/dist/components.d.js';
2
+
3
+ declare class DbGlyphMatrix extends HTMLElement {
4
+ static get observedAttributes(): string[];
5
+ private built;
6
+ private canvas?;
7
+ private ctx?;
8
+ private ro?;
9
+ private rafId;
10
+ private lastTick;
11
+ private stopped;
12
+ private cols;
13
+ private rows;
14
+ private cells;
15
+ private alphas;
16
+ private rgba;
17
+ private mouseX;
18
+ private mouseY;
19
+ private mouseHandler;
20
+ private mouseLeaveHandler;
21
+ get preset(): GlyphMatrixPreset;
22
+ set preset(value: GlyphMatrixPreset);
23
+ get size(): GlyphMatrixSize;
24
+ set size(value: GlyphMatrixSize);
25
+ get glyphs(): string;
26
+ set glyphs(value: string);
27
+ get cellSize(): number;
28
+ set cellSize(value: number);
29
+ get mutationRate(): number;
30
+ set mutationRate(value: number);
31
+ get interval(): number;
32
+ set interval(value: number);
33
+ get fadeBottom(): number;
34
+ set fadeBottom(value: number);
35
+ get color(): string;
36
+ set color(value: string);
37
+ get interactive(): boolean;
38
+ set interactive(value: boolean);
39
+ connectedCallback(): void;
40
+ disconnectedCallback(): void;
41
+ attributeChangedCallback(name: string, _oldVal: string | null, _newVal: string | null): void;
42
+ private attachMouseEvents;
43
+ private detachMouseEvents;
44
+ private build;
45
+ private syncColor;
46
+ private sync;
47
+ private resize;
48
+ private draw;
49
+ private tick;
50
+ private start;
51
+ }
52
+ declare global {
53
+ interface HTMLElementTagNameMap {
54
+ 'db-glyph-matrix': DbGlyphMatrix;
55
+ }
56
+ }
57
+
58
+ export { DbGlyphMatrix };
@@ -0,0 +1 @@
1
+ import{coerceToContract as t}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{GLYPH_MATRIX_PRESETS as e,GLYPH_MATRIX_SIZES as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const i="designbase-wc-glyph-matrix",a={code:"01·•+*/\\<>=-_",matrix:"ヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ9876543210",binary:"01",dots:"·•:;*+~",alphanumeric:"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"},r={s:10,m:14,l:18};class DbGlyphMatrix extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.rafId=null,this.lastTick=0,this.stopped=!1,this.cols=0,this.rows=0,this.cells=[],this.alphas=[],this.rgba={r:107,g:114,b:128,a:1},this.mouseX=-9999,this.mouseY=-9999,this.mouseHandler=t=>{const e=this.getBoundingClientRect();this.mouseX=t.clientX-e.left,this.mouseY=t.clientY-e.top},this.mouseLeaveHandler=()=>{this.mouseX=-9999,this.mouseY=-9999},this.tick=t=>{if(!this.stopped){if(t-this.lastTick>=this.interval){this.lastTick=t;const e=this.cols*this.rows,s=Math.max(1,Math.floor(e*this.mutationRate)),i=this.glyphs,a=i.length;for(let t=0;t<s;t++){const t=Math.floor(Math.random()*e);this.cells[t]=i[Math.floor(Math.random()*a)]||"0",this.alphas[t]=.05+.45*Math.random()}this.draw()}this.rafId=requestAnimationFrame(this.tick)}}}static get observedAttributes(){return["glyphs","preset","size","cell-size","mutation-rate","interval","fade-bottom","color","interactive"]}get preset(){return t(this.getAttribute("preset"),e,"code")}set preset(t){this.setAttribute("preset",t)}get size(){return t(this.getAttribute("size"),s,"m")}set size(t){this.setAttribute("size",t)}get glyphs(){const t=this.getAttribute("glyphs");return t||(a[this.preset]||a.code)}set glyphs(t){this.setAttribute("glyphs",t)}get cellSize(){const t=this.getAttribute("cell-size");if(t){const e=parseFloat(t);if(Number.isFinite(e)&&e>4)return e}return r[this.size]||14}set cellSize(t){this.setAttribute("cell-size",String(t))}get mutationRate(){const t=parseFloat(this.getAttribute("mutation-rate")||"0.04");return Number.isFinite(t)&&t>=0?t:.04}set mutationRate(t){this.setAttribute("mutation-rate",String(t))}get interval(){const t=parseFloat(this.getAttribute("interval")||"90");return Number.isFinite(t)&&t>10?t:90}set interval(t){this.setAttribute("interval",String(t))}get fadeBottom(){const t=parseFloat(this.getAttribute("fade-bottom")||"0.6");return Number.isFinite(t)?t:.6}set fadeBottom(t){this.setAttribute("fade-bottom",String(t))}get color(){return this.getAttribute("color")||"#6B7280"}set color(t){this.setAttribute("color",t)}get interactive(){return this.hasAttribute("interactive")}set interactive(t){t?this.setAttribute("interactive",""):this.removeAttribute("interactive")}connectedCallback(){this.setAttribute("aria-hidden","true"),this.built||(this.build(),this.built=!0),this.syncColor(),this.sync(),this.interactive&&this.attachMouseEvents(),this.start()}disconnectedCallback(){this.stopped=!0,null!==this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.ro&&(this.ro.disconnect(),this.ro=void 0),this.detachMouseEvents()}attributeChangedCallback(t,e,s){this.built&&("color"===t?this.syncColor():"interactive"===t&&(this.interactive?this.attachMouseEvents():this.detachMouseEvents()),this.sync())}attachMouseEvents(){this.addEventListener("mousemove",this.mouseHandler,{passive:!0}),this.addEventListener("mouseleave",this.mouseLeaveHandler,{passive:!0});const t=this.parentElement;t&&(t.addEventListener("mousemove",this.mouseHandler,{passive:!0}),t.addEventListener("mouseleave",this.mouseLeaveHandler,{passive:!0}))}detachMouseEvents(){this.removeEventListener("mousemove",this.mouseHandler),this.removeEventListener("mouseleave",this.mouseLeaveHandler);const t=this.parentElement;t&&(t.removeEventListener("mousemove",this.mouseHandler),t.removeEventListener("mouseleave",this.mouseLeaveHandler))}build(){this.classList.add(i);const t=document.createElement("canvas");t.className=`${i}__canvas`,t.setAttribute("aria-hidden","true"),this.canvas=t,this.ctx=t.getContext("2d"),this.replaceChildren(t),"undefined"!=typeof ResizeObserver&&(this.ro=new ResizeObserver(()=>{this.resize(),this.draw()}),this.ro.observe(this))}syncColor(){const t=document.createElement("canvas");t.width=1,t.height=1;const e=t.getContext("2d");if(!e)return;e.fillStyle="#6B7280",e.fillStyle=this.color,e.fillRect(0,0,1,1);const[s,i,a,r]=e.getImageData(0,0,1,1).data;this.rgba={r:s,g:i,b:a,a:r/255}}sync(){e.forEach(t=>this.classList.remove(`${i}--${t}`)),s.forEach(t=>this.classList.remove(`${i}--${t}`)),this.classList.add(`${i}--${this.preset}`),this.classList.add(`${i}--${this.size}`),this.resize(),this.draw()}resize(){if(!this.canvas||!this.ctx)return;const t=window.devicePixelRatio||1;let e=this.clientWidth,s=this.clientHeight;if(0===e||0===s){const t=this.parentElement;t&&(e=t.clientWidth,s=t.clientHeight)}0===e&&(e=300),0===s&&(s=300),this.canvas.width=e*t,this.canvas.height=s*t,this.canvas.style.width=`${e}px`,this.canvas.style.height=`${s}px`,this.ctx.setTransform(t,0,0,t,0,0);const i=this.cellSize;this.cols=Math.ceil(e/i),this.rows=Math.ceil(s/i);const a=this.cols*this.rows,r=this.glyphs,h=r.length;this.cells=new Array(a),this.alphas=new Array(a);for(let t=0;t<a;t++)this.cells[t]=r[Math.floor(Math.random()*h)]||"0",this.alphas[t]=.05+.35*Math.random()}draw(){if(!this.ctx||!this.canvas)return;const t=this.ctx,e=this.clientWidth||this.canvas.width/(window.devicePixelRatio||1),s=this.clientHeight||this.canvas.height/(window.devicePixelRatio||1);t.clearRect(0,0,e,s);const i=this.cellSize;t.font=i-2+"px ui-monospace, SFMono-Regular, Menlo, monospace",t.textBaseline="top";const{r:a,g:r,b:h,a:o}=this.rgba,n=this.fadeBottom,l=this.rows,c=this.cols,d=this.interactive&&this.mouseX>=0&&this.mouseY>=0;for(let e=0;e<l;e++){const s=n>0?Math.max(0,1-e/l*n):1,u=e*i;for(let n=0;n<c;n++){const l=e*c+n,m=n*i;let v=this.alphas[l]*s*o;if(d){const t=m-this.mouseX,e=u-this.mouseY,s=t*t+e*e;if(s<6400){const t=Math.max(0,1-Math.sqrt(s)/80);v=Math.min(1,v+.6*t)}}t.fillStyle=`rgba(${a}, ${r}, ${h}, ${v})`,t.fillText(this.cells[l]||"",m,u)}}}start(){this.stopped=!1,this.lastTick=0,window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches?this.draw():(null!==this.rafId&&cancelAnimationFrame(this.rafId),this.rafId=requestAnimationFrame(this.tick))}}customElements.get("db-glyph-matrix")||customElements.define("db-glyph-matrix",DbGlyphMatrix);export{DbGlyphMatrix};
@@ -1,3 +1,3 @@
1
- type DbIconName = 'arrow-bar-left' | 'arrow-bar-right' | 'award' | 'apple' | 'play-store' | 'arrow-right' | 'star' | 'star-filled' | 'star-half' | 'trending-up' | 'cart' | 'bell-active' | 'caret-down-filled' | 'caret-updown-filled' | 'chevron-down' | 'chevron-up' | 'chevron-left' | 'chevron-right' | 'calendar' | 'camera' | 'clock' | 'bulb' | 'circle-checked' | 'cloud-close' | 'close' | 'done' | 'documentation' | 'doughnut-chart' | 'download' | 'error-filled' | 'edit' | 'eyedropper' | 'file-new' | 'home-outline' | 'home-filled' | 'folder' | 'more-horizontal' | 'folder-open' | 'gallery' | 'globe' | 'hide' | 'info-filled' | 'lock' | 'mail' | 'menu' | 'microphone' | 'minus' | 'moon' | 'more-vertical' | 'paperclip' | 'pause' | 'play' | 'plus' | 'copy' | 'code' | 'write' | 'upload' | 'video' | 'volume-up' | 'mute-filled' | 'package' | 'delivery-filled' | 'repeat' | 'settings' | 'refresh' | 'expand' | 'shrink' | 'grip-vertical' | 'grip-horizontal' | 'search' | 'send' | 'share-alt' | 'show' | 'sparkle' | 'stop' | 'sun' | 'thumb-down' | 'thumb-up' | 'trash' | 'user' | 'warning-filled';
1
+ type DbIconName = 'shape-line' | 'shape-triangle' | 'shape-ellipse' | 'shape-rectangle' | 'filp-vertical' | 'filp-horizontal' | 'filter' | 'sort-descending' | 'navigation' | 'move' | 'arrow-back-up' | 'zoom-in' | 'zoom-out' | 'layer' | 'unlock' | 'layout-align-left' | 'layout-align-center' | 'layout-align-right' | 'layout-align-top' | 'layout-align-middle' | 'layout-align-bottom' | 'text' | 'shapes' | 'text-align-left' | 'text-align-center' | 'text-align-right' | 'desktop' | 'tablet' | 'mobile' | 'plane' | 'arrow-bar-left' | 'arrow-bar-right' | 'award' | 'apple' | 'play-store' | 'arrow-right' | 'star' | 'star-filled' | 'star-half' | 'trending-up' | 'cart' | 'credit-card' | 'bell-active' | 'caret-down-filled' | 'caret-updown-filled' | 'chevron-down' | 'chevron-up' | 'chevron-left' | 'chevron-right' | 'calendar' | 'camera' | 'clock' | 'bulb' | 'circle-checked' | 'cloud-close' | 'close' | 'done' | 'documentation' | 'doughnut-chart' | 'download' | 'error-filled' | 'edit' | 'eyedropper' | 'file-new' | 'home-outline' | 'home-filled' | 'folder' | 'more-horizontal' | 'folder-open' | 'gallery' | 'globe' | 'hide' | 'info-filled' | 'lock' | 'mail' | 'menu' | 'microphone' | 'minus' | 'moon' | 'more-vertical' | 'paperclip' | 'pause' | 'play-outline' | 'play' | 'plus' | 'copy' | 'code' | 'write' | 'upload' | 'video' | 'volume-up' | 'mute-filled' | 'package' | 'delivery-filled' | 'repeat' | 'settings' | 'refresh' | 'expand' | 'shrink' | 'grip-vertical' | 'grip-horizontal' | 'search' | 'send' | 'share-alt' | 'show' | 'sparkle' | 'stop' | 'sun' | 'thumb-down' | 'thumb-up' | 'trash' | 'twitter' | 'x-logo' | 'heart' | 'heart-filled' | 'verified-badge' | 'comment' | 'user' | 'warning-filled';
2
2
 
3
3
  export type { DbIconName };