@designbasekorea/ui-wc 0.5.5 → 0.5.6

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 (155) hide show
  1. package/dist/chunks/lottie-e273b936.js +17032 -0
  2. package/dist/esm/components/animation-background/canvas-controller.js +121 -1
  3. package/dist/esm/components/animation-background/controls.js +180 -1
  4. package/dist/esm/components/animation-background/graphite-controller.js +196 -1
  5. package/dist/esm/components/animation-background/graphite-presets.js +42 -1
  6. package/dist/esm/components/animation-background/graphite-shader.js +111 -1
  7. package/dist/esm/components/animation-background/layers.js +369 -1
  8. package/dist/esm/components/animation-background/lumina-presets.js +53 -1
  9. package/dist/esm/components/animation-background/lumina-shaders.js +181 -1
  10. package/dist/esm/components/animation-background/lumina-utils.js +60 -1
  11. package/dist/esm/components/animation-background/particle-defaults.js +36 -1
  12. package/dist/esm/components/animation-background/renderers.js +167 -1
  13. package/dist/esm/components/animation-background/shader-controller.js +154 -1
  14. package/dist/esm/components/color-picker-utils.js +134 -1
  15. package/dist/esm/components/date-picker-utils.js +140 -1
  16. package/dist/esm/components/db-accordion.js +304 -1
  17. package/dist/esm/components/db-ad-banner.js +455 -1
  18. package/dist/esm/components/db-alert.js +149 -1
  19. package/dist/esm/components/db-animation-background.js +486 -1
  20. package/dist/esm/components/db-animation-text.js +601 -1
  21. package/dist/esm/components/db-app-badge.js +88 -1
  22. package/dist/esm/components/db-audio-player.js +752 -1
  23. package/dist/esm/components/db-avatar.js +188 -1
  24. package/dist/esm/components/db-backdrop.js +139 -1
  25. package/dist/esm/components/db-badge.js +91 -1
  26. package/dist/esm/components/db-banner.js +188 -1
  27. package/dist/esm/components/db-bottom-navigation.js +146 -1
  28. package/dist/esm/components/db-bottom-sheet.js +481 -1
  29. package/dist/esm/components/db-breadcrumbs.js +329 -1
  30. package/dist/esm/components/db-button.js +316 -1
  31. package/dist/esm/components/db-calendar.js +675 -1
  32. package/dist/esm/components/db-card.js +265 -1
  33. package/dist/esm/components/db-carousel.js +264 -1
  34. package/dist/esm/components/db-checkbox.js +202 -1
  35. package/dist/esm/components/db-chip.js +104 -1
  36. package/dist/esm/components/db-code-block.js +304 -1
  37. package/dist/esm/components/db-color-picker.js +746 -1
  38. package/dist/esm/components/db-confirm.js +191 -1
  39. package/dist/esm/components/db-container.js +39 -1
  40. package/dist/esm/components/db-context-menu.js +265 -1
  41. package/dist/esm/components/db-countdown.js +146 -1
  42. package/dist/esm/components/db-cursor-follower.js +173 -1
  43. package/dist/esm/components/db-date-picker.js +837 -1
  44. package/dist/esm/components/db-divider.js +66 -1
  45. package/dist/esm/components/db-drawer.js +245 -1
  46. package/dist/esm/components/db-dropdown.js +493 -1
  47. package/dist/esm/components/db-dropzone.js +266 -1
  48. package/dist/esm/components/db-empty-state.js +97 -1
  49. package/dist/esm/components/db-file-uploader.js +256 -1
  50. package/dist/esm/components/db-floating-action-button.js +139 -1
  51. package/dist/esm/components/db-footer.js +385 -1
  52. package/dist/esm/components/db-form.js +566 -1
  53. package/dist/esm/components/db-gantt.js +882 -1
  54. package/dist/esm/components/db-gradient.js +133 -1
  55. package/dist/esm/components/db-grid-background.js +909 -1
  56. package/dist/esm/components/db-grid.js +73 -1
  57. package/dist/esm/components/db-icons.js +82 -1
  58. package/dist/esm/components/db-image-list.js +214 -1
  59. package/dist/esm/components/db-image-placeholder.js +96 -1
  60. package/dist/esm/components/db-image.js +289 -1
  61. package/dist/esm/components/db-indicator.js +517 -1
  62. package/dist/esm/components/db-input.js +420 -1
  63. package/dist/esm/components/db-kanban.js +538 -1
  64. package/dist/esm/components/db-label.js +66 -1
  65. package/dist/esm/components/db-lightbox.js +372 -1
  66. package/dist/esm/components/db-list.js +340 -1
  67. package/dist/esm/components/db-logo-svg.js +72 -1
  68. package/dist/esm/components/db-logo.js +106 -1
  69. package/dist/esm/components/db-lottie.js +109 -1
  70. package/dist/esm/components/db-markdown-editor.js +458 -1
  71. package/dist/esm/components/db-marquee.js +402 -1
  72. package/dist/esm/components/db-masonry.js +94 -1
  73. package/dist/esm/components/db-menu-item.js +211 -1
  74. package/dist/esm/components/db-modal.js +522 -1
  75. package/dist/esm/components/db-navbar.js +680 -1
  76. package/dist/esm/components/db-onboarding-modal.js +322 -1
  77. package/dist/esm/components/db-page-header.js +312 -1
  78. package/dist/esm/components/db-pagination.js +271 -1
  79. package/dist/esm/components/db-popover.js +580 -1
  80. package/dist/esm/components/db-progress-step.js +166 -1
  81. package/dist/esm/components/db-progress.js +171 -1
  82. package/dist/esm/components/db-progressbar.js +72 -1
  83. package/dist/esm/components/db-radio.js +172 -1
  84. package/dist/esm/components/db-random-gradient.js +121 -1
  85. package/dist/esm/components/db-range-slider.js +811 -1
  86. package/dist/esm/components/db-rating.js +325 -1
  87. package/dist/esm/components/db-reorder.js +286 -1
  88. package/dist/esm/components/db-resizable-panels.js +282 -1
  89. package/dist/esm/components/db-scroll-area.js +126 -1
  90. package/dist/esm/components/db-search-bar.js +668 -1
  91. package/dist/esm/components/db-section-app-download.js +101 -1
  92. package/dist/esm/components/db-section-contact.js +102 -1
  93. package/dist/esm/components/db-section-cta.js +150 -1
  94. package/dist/esm/components/db-section-faq.js +120 -1
  95. package/dist/esm/components/db-section-feature-grid.js +137 -1
  96. package/dist/esm/components/db-section-feature.js +179 -1
  97. package/dist/esm/components/db-section-hero.js +243 -1
  98. package/dist/esm/components/db-section-logo-cloud.js +138 -1
  99. package/dist/esm/components/db-section-pricing.js +166 -1
  100. package/dist/esm/components/db-section-stats.js +129 -1
  101. package/dist/esm/components/db-section-testimonials.js +252 -1
  102. package/dist/esm/components/db-section.js +385 -1
  103. package/dist/esm/components/db-segment-control.js +231 -1
  104. package/dist/esm/components/db-select.js +571 -1
  105. package/dist/esm/components/db-share-icons.js +40 -1
  106. package/dist/esm/components/db-share.js +489 -1
  107. package/dist/esm/components/db-sidebar.js +1068 -1
  108. package/dist/esm/components/db-skeleton.js +94 -1
  109. package/dist/esm/components/db-spinner.js +102 -1
  110. package/dist/esm/components/db-split-view.js +297 -1
  111. package/dist/esm/components/db-stack.js +46 -1
  112. package/dist/esm/components/db-stat.js +218 -1
  113. package/dist/esm/components/db-stepper.js +398 -1
  114. package/dist/esm/components/db-table.js +412 -1
  115. package/dist/esm/components/db-tabs.js +335 -1
  116. package/dist/esm/components/db-testimonial.js +162 -1
  117. package/dist/esm/components/db-textarea.js +233 -1
  118. package/dist/esm/components/db-time-picker.js +523 -1
  119. package/dist/esm/components/db-timeline.js +174 -1
  120. package/dist/esm/components/db-toast.js +158 -1
  121. package/dist/esm/components/db-toggle.js +162 -1
  122. package/dist/esm/components/db-toolbar.js +94 -1
  123. package/dist/esm/components/db-tooltip.js +440 -1
  124. package/dist/esm/components/db-top-banner.js +121 -1
  125. package/dist/esm/components/db-tutorial.js +324 -1
  126. package/dist/esm/components/db-video-player.js +503 -1
  127. package/dist/esm/components/db-youtube-player.js +194 -1
  128. package/dist/esm/components/highlight-code.js +65 -1
  129. package/dist/esm/components/input-validation.js +50 -1
  130. package/dist/esm/components/marketing-block-host-utils.js +9 -1
  131. package/dist/esm/components/number-scrub.js +117 -1
  132. package/dist/esm/components/random-gradient-palettes.js +67 -1
  133. package/dist/esm/components/section-block-header-utils.js +48 -1
  134. package/dist/esm/helpers/confirm.js +52 -1
  135. package/dist/esm/helpers/toast.js +73 -1
  136. package/dist/esm/index.js +111 -1
  137. package/dist/esm/node_modules/prismjs/components/prism-bash.js +235 -1
  138. package/dist/esm/node_modules/prismjs/components/prism-clike.js +31 -1
  139. package/dist/esm/node_modules/prismjs/components/prism-css.js +64 -1
  140. package/dist/esm/node_modules/prismjs/components/prism-javascript.js +172 -1
  141. package/dist/esm/node_modules/prismjs/components/prism-json.js +27 -1
  142. package/dist/esm/node_modules/prismjs/components/prism-jsx.js +143 -1
  143. package/dist/esm/node_modules/prismjs/components/prism-markup.js +186 -1
  144. package/dist/esm/node_modules/prismjs/components/prism-scss.js +81 -1
  145. package/dist/esm/node_modules/prismjs/components/prism-tsx.js +15 -1
  146. package/dist/esm/node_modules/prismjs/components/prism-typescript.js +60 -1
  147. package/dist/index.cjs +55414 -1
  148. package/dist/index.css +1 -1
  149. package/dist/index.esm.js +38284 -1
  150. package/dist/react/chunks/lottie-72a4c6d4.js +17032 -0
  151. package/dist/react/index.cjs +56503 -1
  152. package/dist/react/index.esm.js +39373 -1
  153. package/package.json +1 -1
  154. package/dist/chunks/lottie-2637aa0f.js +0 -1
  155. package/dist/react/chunks/lottie-14e7addb.js +0 -1
@@ -1 +1,455 @@
1
- import{createDbIcon as t}from"./db-icons.js";const e="designbase-wc-ad-banner",i={hero:"지금 바로 시작하세요",topbar:"🎉 신규 가입 시 10,000원 적립금 증정!",card:"프리미엄 멤버십",floating:"오늘만 특가!"},s={hero:"최대 50% 할인된 가격으로 프리미엄 서비스를 경험해보세요. 기간 한정 특별 혜택!",topbar:"오늘 하루만 특별 혜택",card:"무제한 서비스 이용권을 특별가에 만나보세요",floating:"장바구니에 담긴 상품 추가 20% 할인"},n={hero:"자세히 보기",topbar:"지금 가입하기",card:"알아보기",floating:"할인받기"},r="star-filled",a={primary:"primary",secondary:"secondary",success:"success",warning:"warning",error:"error"};class DbAdBanner extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.visible=!0,this.progress=100}static get observedAttributes(){return["type","variant","size","title","subtitle","cta-text","image","image-alt","href","target","auto-close","close-delay","background","animation-type","grid-type","use-random-gradient","gradient-scheme","gradient-tone","gradient-animated","countdown-end-date","show-countdown","open"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}disconnectedCallback(){this.stopAutoClose()}attributeChangedCallback(t){this.built&&("open"===t&&(this.visible="false"!==this.getAttribute("open")),this.updateUI())}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getType(){const t=this.getAttribute("type")||"hero";return["hero","topbar","card","floating"].includes(t)?t:"hero"}getVariant(){const t=this.getAttribute("variant")||"primary";return["primary","secondary","success","warning","error"].includes(t)?t:"primary"}getSize(){const t=this.getAttribute("size")||"m";return["s","m","l"].includes(t)?t:"m"}ctaButtonSize(t,e){return"card"===t?"s":"floating"===t?"s"===e?"s":"m":e}build(){this.rootEl=document.createElement("div"),this.contentEl=document.createElement("div"),this.contentEl.className=`${e}__content`,this.closeBtn=document.createElement("button"),this.closeBtn.type="button",this.closeBtn.className=`${e}__close`,this.closeBtn.setAttribute("aria-label","닫기"),this.closeBtn.append(t("close",16)),this.closeBtn.addEventListener("click",t=>{t.stopPropagation(),this.handleClose()}),this.imageEl=document.createElement("img"),this.imageEl.className=`${e}__image`,this.imageEl.loading="lazy";const i=document.createElement("div");i.className=`${e}__main`,this.mainEl=i,this.iconEl=document.createElement("div"),this.iconEl.className=`${e}__icon`,this.labelEl=document.createElement("span"),this.labelEl.className=`${e}__label`,this.labelEl.textContent="특별 이벤트",this.badgeEl=document.createElement("span"),this.badgeEl.className=`${e}__badge`,this.badgeEl.textContent="HOT DEAL",this.titleEl=document.createElement("h2"),this.titleEl.className=`${e}__title`,this.subtitleEl=document.createElement("p"),this.subtitleEl.className=`${e}__subtitle`;const s=document.createElement("div");s.className=`${e}__text`,this.textEl=s,this.countdownWrapEl=document.createElement("div"),this.countdownWrapEl.className=`${e}__countdown`,s.append(this.titleEl,this.subtitleEl),this.actionsEl=document.createElement("div"),this.actionsEl.className=`${e}__actions`,this.ctaEl=document.createElement("db-button"),this.ctaEl.className=`${e}__cta`,this.ctaEl.setAttribute("variant","primary"),this.ctaEl.setAttribute("end-icon","arrow-right"),this.ctaEl.addEventListener("click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-cta-click",{bubbles:!0,composed:!0}))}),this.actionsEl.append(this.ctaEl),i.append(s,this.actionsEl),this.progressEl=document.createElement("div"),this.progressEl.className=`${e}__progress`,this.progressBarEl=document.createElement("div"),this.progressBarEl.className=`${e}__progress-bar`,this.progressEl.append(this.progressBarEl),this.contentEl.append(this.closeBtn,i,this.progressEl),this.rootEl.append(this.contentEl),this.append(this.rootEl),this.contentEl.addEventListener("click",t=>{"topbar"===this.getType()&&(t.target?.closest(`.${e}__close`)||this.dispatchEvent(new CustomEvent("db-cta-click",{bubbles:!0,composed:!0})))})}handleClose(){this.visible=!1,this.style.display="none",this.setAttribute("open","false"),this.stopAutoClose(),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}stopAutoClose(){this.autoCloseTimer&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=void 0)}startAutoClose(t){this.stopAutoClose(),this.progress=100,this.autoCloseTimer=window.setInterval(()=>{this.progress-=100/(t/100),this.progressBarEl&&(this.progressBarEl.style.width=`${Math.max(this.progress,0)}%`),this.progress<=0&&this.handleClose()},100)}getBackground(){const t=this.getAttribute("background");return t&&["solid","gradient","animation","grid"].includes(t)?t:this.getBool("use-random-gradient")?"gradient":"solid"}ensureAnimBg(){if(!this.animBgEl){const t=document.createElement("div");t.className=`${e}__backdrop`;const i=document.createElement("db-animation-background");i.className=`${e}__anim-bg`,i.setAttribute("width","100%"),i.setAttribute("height","100%"),t.append(i),this.animBgEl=t,this.animBgInner=i}return this.animBgEl}ensureGridBg(){if(!this.gridBgEl){const t=document.createElement("div");t.className=`${e}__backdrop`;const i=document.createElement("db-grid-background");i.className=`${e}__grid-bg`,i.setAttribute("width","100%"),i.setAttribute("height","100%"),t.append(i),this.gridBgEl=t,this.gridBgInner=i}return this.gridBgEl}clearBackdrop(t){"gradient"!==t&&this.gradientEl&&(this.gradientEl.remove(),this.gradientEl=void 0),"animation"!==t&&this.animBgEl&&(this.animBgEl.remove(),this.animBgEl=void 0,this.animBgInner=void 0),"grid"!==t&&this.gridBgEl&&(this.gridBgEl.remove(),this.gridBgEl=void 0,this.gridBgInner=void 0)}renderBackground(t,i){if(!this.rootEl||!this.contentEl)return;if(this.clearBackdrop(t),"gradient"===t){this.gradientEl||(this.gradientEl=document.createElement("db-random-gradient"),this.gradientEl.className=`${e}__gradient-bg`,this.gradientEl.setAttribute("height","100%"),this.gradientEl.setAttribute("width","100%"));const t=this.getAttribute("gradient-tone")||"vivid",s=!this.hasAttribute("gradient-animated")||"false"!==this.getAttribute("gradient-animated");return this.gradientEl.setAttribute("scheme",this.getAttribute("gradient-scheme")||a[i]),this.gradientEl.setAttribute("tone",t),this.gradientEl.setAttribute("animated",s?"true":"false"),this.gradientEl.parentElement!==this.rootEl&&this.rootEl.replaceChildren(this.gradientEl),void(this.contentEl.parentElement!==this.gradientEl&&this.gradientEl.append(this.contentEl))}const s=[];if("animation"===t){const t=this.ensureAnimBg();this.animBgInner?.setAttribute("type",this.getAttribute("animation-type")||"graphite"),this.animBgInner?.setAttribute("theme","dark"),s.push(t)}else if("grid"===t){const t=this.ensureGridBg();this.gridBgInner?.setAttribute("type",this.getAttribute("grid-type")||"lines"),this.gridBgInner?.setAttribute("color","var(--db-text-inverse-primary)"),this.gridBgInner?.setAttribute("opacity","0.18"),this.gridBgInner?.setAttribute("fade","vignette"),this.gridBgInner?.setAttribute("animated",""),s.push(t)}const n=[...s,this.contentEl],r=Array.from(this.rootEl.children);r.length===n.length&&n.every((t,e)=>r[e]===t)||this.rootEl.replaceChildren(...n)}syncIcon(e){this.mainEl&&this.textEl&&this.iconEl&&("card"===e?(this.iconEl.replaceChildren(t(r,32)),this.iconEl.parentElement!==this.mainEl&&this.mainEl.insertBefore(this.iconEl,this.textEl)):this.iconEl.remove())}syncBadge(t){this.textEl&&this.badgeEl&&("floating"===t?this.badgeEl.parentElement!==this.textEl&&this.textEl.insertBefore(this.badgeEl,this.textEl.firstChild):this.badgeEl.remove())}syncImage(t,e){this.contentEl&&this.imageEl&&this.mainEl&&("floating"===t&&e?(this.imageEl.src=e,this.imageEl.alt=this.getAttribute("image-alt")||"",this.imageEl.parentElement!==this.contentEl&&this.contentEl.insertBefore(this.imageEl,this.mainEl)):this.imageEl.remove())}syncLink(t,i){if(!this.contentEl)return;if("topbar"!==t||!i)return void this.linkEl?.remove();this.linkEl||(this.linkEl=document.createElement("a"),this.linkEl.className=`${e}__link`),this.linkEl.setAttribute("href",i);const s=this.getAttribute("target");s?this.linkEl.setAttribute("target",s):this.linkEl.removeAttribute("target"),this.linkEl.setAttribute("aria-label",this.titleEl?.textContent||"배너 링크"),this.linkEl.parentElement!==this.contentEl&&this.contentEl.append(this.linkEl)}syncCountdown(t,e){this.textEl&&this.countdownWrapEl&&(t&&e?(this.countdownEl||(this.countdownEl=document.createElement("db-countdown"),this.countdownEl.setAttribute("size","s"),this.countdownEl.setAttribute("variant","compact"),this.countdownEl.setAttribute("show-labels","false"),this.countdownWrapEl.replaceChildren(this.countdownEl)),this.countdownEl.setAttribute("end-date",e),this.countdownWrapEl.parentElement!==this.textEl&&this.textEl.append(this.countdownWrapEl)):this.countdownWrapEl.remove())}updateUI(){if(!this.visible||"false"===this.getAttribute("open"))return void(this.style.display="none");this.style.display="block";const t=this.getType(),r=this.getVariant(),a=this.getSize(),l=this.getAttribute("title")||i[t],o=this.getAttribute("subtitle")||s[t],h=this.getAttribute("cta-text")||n[t],c=this.getBool("auto-close"),d=Math.max(Number(this.getAttribute("close-delay")||5e3),1e3),g=this.getBackground(),E=this.getAttribute("gradient-tone")||"vivid",u=this.getBool("show-countdown"),m=this.getAttribute("countdown-end-date");this.rootEl&&(this.rootEl.className=[e,`${e}--type-${t}`,`${e}--variant-${r}`,`${e}--size-${a}`,`${e}--bg-${g}`,c&&`${e}--auto-close`,"gradient"===g&&`${e}--with-gradient`,"gradient"===g&&"light"===E&&`${e}--gradient-light`].filter(Boolean).join(" ")),this.renderBackground(g,r),this.syncIcon(t),this.syncBadge(t),this.syncImage(t,this.getAttribute("image")),this.syncLink(t,this.getAttribute("href")),this.titleEl&&(this.titleEl.textContent=l),this.subtitleEl&&(this.subtitleEl.textContent=o),this.syncCountdown(u,m),this.actionsEl&&(this.actionsEl.hidden="topbar"===t),this.ctaEl&&(this.ctaEl.textContent=h,this.ctaEl.setAttribute("size",this.ctaButtonSize(t,a)),"floating"===t?this.ctaEl.setAttribute("full-width",""):this.ctaEl.removeAttribute("full-width")),this.progressEl&&(this.progressEl.hidden=!c),this.progressBarEl&&c&&(this.progressBarEl.style.width=`${this.progress}%`),this.stopAutoClose(),c&&this.startAutoClose(d)}}customElements.get("db-ad-banner")||customElements.define("db-ad-banner",DbAdBanner);export{DbAdBanner};
1
+ import { createDbIcon } from './db-icons.js';
2
+
3
+ const CLASS = 'designbase-wc-ad-banner';
4
+ const DEFAULT_TITLES = {
5
+ hero: '지금 바로 시작하세요',
6
+ topbar: '🎉 신규 가입 시 10,000원 적립금 증정!',
7
+ card: '프리미엄 멤버십',
8
+ floating: '오늘만 특가!',
9
+ };
10
+ const DEFAULT_SUBTITLES = {
11
+ hero: '최대 50% 할인된 가격으로 프리미엄 서비스를 경험해보세요. 기간 한정 특별 혜택!',
12
+ topbar: '오늘 하루만 특별 혜택',
13
+ card: '무제한 서비스 이용권을 특별가에 만나보세요',
14
+ floating: '장바구니에 담긴 상품 추가 20% 할인',
15
+ };
16
+ const DEFAULT_CTA = {
17
+ hero: '자세히 보기',
18
+ topbar: '지금 가입하기',
19
+ card: '알아보기',
20
+ floating: '할인받기',
21
+ };
22
+ const TYPE_ICONS = {
23
+ hero: 'star',
24
+ topbar: 'trending-up',
25
+ card: 'star-filled',
26
+ floating: 'cart',
27
+ };
28
+ const VARIANT_SCHEMES = {
29
+ primary: 'primary',
30
+ secondary: 'secondary',
31
+ success: 'success',
32
+ warning: 'warning',
33
+ error: 'error',
34
+ };
35
+ class DbAdBanner extends HTMLElement {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.built = false;
39
+ this.visible = true;
40
+ this.progress = 100;
41
+ }
42
+ static get observedAttributes() {
43
+ return [
44
+ 'type',
45
+ 'variant',
46
+ 'size',
47
+ 'title',
48
+ 'subtitle',
49
+ 'cta-text',
50
+ 'image',
51
+ 'image-alt',
52
+ 'href',
53
+ 'target',
54
+ 'auto-close',
55
+ 'close-delay',
56
+ 'background',
57
+ 'animation-type',
58
+ 'grid-type',
59
+ 'use-random-gradient',
60
+ 'gradient-scheme',
61
+ 'gradient-tone',
62
+ 'gradient-animated',
63
+ 'countdown-end-date',
64
+ 'show-countdown',
65
+ 'open',
66
+ ];
67
+ }
68
+ connectedCallback() {
69
+ this.style.display = 'block';
70
+ if (!this.built) {
71
+ this.built = true;
72
+ this.build();
73
+ }
74
+ this.updateUI();
75
+ }
76
+ disconnectedCallback() {
77
+ this.stopAutoClose();
78
+ }
79
+ attributeChangedCallback(name) {
80
+ if (!this.built)
81
+ return;
82
+ if (name === 'open') {
83
+ this.visible = this.getAttribute('open') !== 'false';
84
+ }
85
+ this.updateUI();
86
+ }
87
+ getBool(name, fallback = false) {
88
+ if (!this.hasAttribute(name))
89
+ return fallback;
90
+ const value = this.getAttribute(name);
91
+ return value === '' || value === 'true';
92
+ }
93
+ getType() {
94
+ const type = this.getAttribute('type') || 'hero';
95
+ return ['hero', 'topbar', 'card', 'floating'].includes(type) ? type : 'hero';
96
+ }
97
+ getVariant() {
98
+ const variant = this.getAttribute('variant') || 'primary';
99
+ return ['primary', 'secondary', 'success', 'warning', 'error'].includes(variant)
100
+ ? variant
101
+ : 'primary';
102
+ }
103
+ getSize() {
104
+ const size = this.getAttribute('size') || 'm';
105
+ return ['s', 'm', 'l'].includes(size) ? size : 'm';
106
+ }
107
+ ctaButtonSize(type, size) {
108
+ if (type === 'card')
109
+ return 's';
110
+ if (type === 'floating')
111
+ return size === 's' ? 's' : 'm';
112
+ return size;
113
+ }
114
+ build() {
115
+ this.rootEl = document.createElement('div');
116
+ this.contentEl = document.createElement('div');
117
+ this.contentEl.className = `${CLASS}__content`;
118
+ this.closeBtn = document.createElement('button');
119
+ this.closeBtn.type = 'button';
120
+ this.closeBtn.className = `${CLASS}__close`;
121
+ this.closeBtn.setAttribute('aria-label', '닫기');
122
+ this.closeBtn.append(createDbIcon('close', 16));
123
+ this.closeBtn.addEventListener('click', (event) => {
124
+ event.stopPropagation();
125
+ this.handleClose();
126
+ });
127
+ this.imageEl = document.createElement('img');
128
+ this.imageEl.className = `${CLASS}__image`;
129
+ this.imageEl.loading = 'lazy';
130
+ const mainEl = document.createElement('div');
131
+ mainEl.className = `${CLASS}__main`;
132
+ this.mainEl = mainEl;
133
+ this.iconEl = document.createElement('div');
134
+ this.iconEl.className = `${CLASS}__icon`;
135
+ this.labelEl = document.createElement('span');
136
+ this.labelEl.className = `${CLASS}__label`;
137
+ this.labelEl.textContent = '특별 이벤트';
138
+ this.badgeEl = document.createElement('span');
139
+ this.badgeEl.className = `${CLASS}__badge`;
140
+ this.badgeEl.textContent = 'HOT DEAL';
141
+ this.titleEl = document.createElement('h2');
142
+ this.titleEl.className = `${CLASS}__title`;
143
+ this.subtitleEl = document.createElement('p');
144
+ this.subtitleEl.className = `${CLASS}__subtitle`;
145
+ const textEl = document.createElement('div');
146
+ textEl.className = `${CLASS}__text`;
147
+ this.textEl = textEl;
148
+ this.countdownWrapEl = document.createElement('div');
149
+ this.countdownWrapEl.className = `${CLASS}__countdown`;
150
+ textEl.append(this.titleEl, this.subtitleEl);
151
+ this.actionsEl = document.createElement('div');
152
+ this.actionsEl.className = `${CLASS}__actions`;
153
+ this.ctaEl = document.createElement('db-button');
154
+ this.ctaEl.className = `${CLASS}__cta`;
155
+ this.ctaEl.setAttribute('variant', 'primary');
156
+ this.ctaEl.setAttribute('end-icon', 'arrow-right');
157
+ this.ctaEl.addEventListener('click', (event) => {
158
+ event.stopPropagation();
159
+ this.dispatchEvent(new CustomEvent('db-cta-click', { bubbles: true, composed: true }));
160
+ });
161
+ this.actionsEl.append(this.ctaEl);
162
+ mainEl.append(textEl, this.actionsEl);
163
+ this.progressEl = document.createElement('div');
164
+ this.progressEl.className = `${CLASS}__progress`;
165
+ this.progressBarEl = document.createElement('div');
166
+ this.progressBarEl.className = `${CLASS}__progress-bar`;
167
+ this.progressEl.append(this.progressBarEl);
168
+ this.contentEl.append(this.closeBtn, mainEl, this.progressEl);
169
+ this.rootEl.append(this.contentEl);
170
+ this.append(this.rootEl);
171
+ // topbar 는 전체가 링크처럼 동작 (href 없을 때도 db-cta-click 발행)
172
+ this.contentEl.addEventListener('click', (event) => {
173
+ if (this.getType() !== 'topbar')
174
+ return;
175
+ if (event.target?.closest(`.${CLASS}__close`))
176
+ return;
177
+ this.dispatchEvent(new CustomEvent('db-cta-click', { bubbles: true, composed: true }));
178
+ });
179
+ }
180
+ handleClose() {
181
+ this.visible = false;
182
+ this.style.display = 'none';
183
+ this.setAttribute('open', 'false');
184
+ this.stopAutoClose();
185
+ this.dispatchEvent(new CustomEvent('db-close', { bubbles: true, composed: true }));
186
+ }
187
+ stopAutoClose() {
188
+ if (this.autoCloseTimer) {
189
+ window.clearInterval(this.autoCloseTimer);
190
+ this.autoCloseTimer = undefined;
191
+ }
192
+ }
193
+ startAutoClose(delay) {
194
+ this.stopAutoClose();
195
+ this.progress = 100;
196
+ this.autoCloseTimer = window.setInterval(() => {
197
+ this.progress -= 100 / (delay / 100);
198
+ if (this.progressBarEl) {
199
+ this.progressBarEl.style.width = `${Math.max(this.progress, 0)}%`;
200
+ }
201
+ if (this.progress <= 0) {
202
+ this.handleClose();
203
+ }
204
+ }, 100);
205
+ }
206
+ getBackground() {
207
+ const explicit = this.getAttribute('background');
208
+ if (explicit && ['solid', 'gradient', 'animation', 'grid'].includes(explicit)) {
209
+ return explicit;
210
+ }
211
+ return this.getBool('use-random-gradient') ? 'gradient' : 'solid';
212
+ }
213
+ ensureAnimBg() {
214
+ if (!this.animBgEl) {
215
+ const wrap = document.createElement('div');
216
+ wrap.className = `${CLASS}__backdrop`;
217
+ const inner = document.createElement('db-animation-background');
218
+ inner.className = `${CLASS}__anim-bg`;
219
+ inner.setAttribute('width', '100%');
220
+ inner.setAttribute('height', '100%');
221
+ wrap.append(inner);
222
+ this.animBgEl = wrap;
223
+ this.animBgInner = inner;
224
+ }
225
+ return this.animBgEl;
226
+ }
227
+ ensureGridBg() {
228
+ if (!this.gridBgEl) {
229
+ const wrap = document.createElement('div');
230
+ wrap.className = `${CLASS}__backdrop`;
231
+ const inner = document.createElement('db-grid-background');
232
+ inner.className = `${CLASS}__grid-bg`;
233
+ inner.setAttribute('width', '100%');
234
+ inner.setAttribute('height', '100%');
235
+ wrap.append(inner);
236
+ this.gridBgEl = wrap;
237
+ this.gridBgInner = inner;
238
+ }
239
+ return this.gridBgEl;
240
+ }
241
+ /** 이전 배경 모드의 백드롭 엘리먼트를 정리한다. */
242
+ clearBackdrop(keep) {
243
+ if (keep !== 'gradient' && this.gradientEl) {
244
+ this.gradientEl.remove();
245
+ this.gradientEl = undefined;
246
+ }
247
+ if (keep !== 'animation' && this.animBgEl) {
248
+ this.animBgEl.remove();
249
+ this.animBgEl = undefined;
250
+ this.animBgInner = undefined;
251
+ }
252
+ if (keep !== 'grid' && this.gridBgEl) {
253
+ this.gridBgEl.remove();
254
+ this.gridBgEl = undefined;
255
+ this.gridBgInner = undefined;
256
+ }
257
+ }
258
+ renderBackground(background, variant) {
259
+ if (!this.rootEl || !this.contentEl)
260
+ return;
261
+ this.clearBackdrop(background);
262
+ if (background === 'gradient') {
263
+ if (!this.gradientEl) {
264
+ this.gradientEl = document.createElement('db-random-gradient');
265
+ this.gradientEl.className = `${CLASS}__gradient-bg`;
266
+ this.gradientEl.setAttribute('height', '100%');
267
+ this.gradientEl.setAttribute('width', '100%');
268
+ }
269
+ const gradientTone = this.getAttribute('gradient-tone') || 'vivid';
270
+ const gradientAnimated = !this.hasAttribute('gradient-animated') || this.getAttribute('gradient-animated') !== 'false';
271
+ this.gradientEl.setAttribute('scheme', this.getAttribute('gradient-scheme') || VARIANT_SCHEMES[variant]);
272
+ this.gradientEl.setAttribute('tone', gradientTone);
273
+ this.gradientEl.setAttribute('animated', gradientAnimated ? 'true' : 'false');
274
+ if (this.gradientEl.parentElement !== this.rootEl) {
275
+ this.rootEl.replaceChildren(this.gradientEl);
276
+ }
277
+ if (this.contentEl.parentElement !== this.gradientEl) {
278
+ this.gradientEl.append(this.contentEl);
279
+ }
280
+ return;
281
+ }
282
+ // solid / animation / grid → 백드롭은 절대 위치 형제, 콘텐츠는 그 위에
283
+ const layers = [];
284
+ if (background === 'animation') {
285
+ const wrap = this.ensureAnimBg();
286
+ this.animBgInner?.setAttribute('type', this.getAttribute('animation-type') || 'graphite');
287
+ this.animBgInner?.setAttribute('theme', 'dark');
288
+ layers.push(wrap);
289
+ }
290
+ else if (background === 'grid') {
291
+ const wrap = this.ensureGridBg();
292
+ this.gridBgInner?.setAttribute('type', this.getAttribute('grid-type') || 'lines');
293
+ this.gridBgInner?.setAttribute('color', 'var(--db-text-inverse-primary)');
294
+ this.gridBgInner?.setAttribute('opacity', '0.18');
295
+ this.gridBgInner?.setAttribute('fade', 'vignette');
296
+ this.gridBgInner?.setAttribute('animated', '');
297
+ layers.push(wrap);
298
+ }
299
+ // 구조가 이미 올바르면 재삽입하지 않는다 (백드롭 캔버스 애니메이션 재시작 방지)
300
+ const desired = [...layers, this.contentEl];
301
+ const current = Array.from(this.rootEl.children);
302
+ const same = current.length === desired.length && desired.every((node, i) => current[i] === node);
303
+ if (!same) {
304
+ this.rootEl.replaceChildren(...desired);
305
+ }
306
+ }
307
+ /** 장식 아이콘은 card 타입에서만 사용한다. */
308
+ syncIcon(type) {
309
+ if (!this.mainEl || !this.textEl || !this.iconEl)
310
+ return;
311
+ if (type !== 'card') {
312
+ this.iconEl.remove();
313
+ return;
314
+ }
315
+ this.iconEl.replaceChildren(createDbIcon(TYPE_ICONS.card, 32));
316
+ if (this.iconEl.parentElement !== this.mainEl) {
317
+ this.mainEl.insertBefore(this.iconEl, this.textEl);
318
+ }
319
+ }
320
+ /** floating 타입에서만 텍스트 상단에 배지 칩을 노출한다. */
321
+ syncBadge(type) {
322
+ if (!this.textEl || !this.badgeEl)
323
+ return;
324
+ if (type !== 'floating') {
325
+ this.badgeEl.remove();
326
+ return;
327
+ }
328
+ if (this.badgeEl.parentElement !== this.textEl) {
329
+ this.textEl.insertBefore(this.badgeEl, this.textEl.firstChild);
330
+ }
331
+ }
332
+ /** floating 타입에서 배너 이미지를 콘텐츠 상단(패딩 밖)에 렌더한다. */
333
+ syncImage(type, src) {
334
+ if (!this.contentEl || !this.imageEl || !this.mainEl)
335
+ return;
336
+ if (type !== 'floating' || !src) {
337
+ this.imageEl.remove();
338
+ return;
339
+ }
340
+ this.imageEl.src = src;
341
+ this.imageEl.alt = this.getAttribute('image-alt') || '';
342
+ if (this.imageEl.parentElement !== this.contentEl) {
343
+ this.contentEl.insertBefore(this.imageEl, this.mainEl);
344
+ }
345
+ }
346
+ /** topbar 타입에서 href 가 있으면 전체를 덮는 링크 오버레이를 렌더한다. */
347
+ syncLink(type, href) {
348
+ if (!this.contentEl)
349
+ return;
350
+ if (type !== 'topbar' || !href) {
351
+ this.linkEl?.remove();
352
+ return;
353
+ }
354
+ if (!this.linkEl) {
355
+ this.linkEl = document.createElement('a');
356
+ this.linkEl.className = `${CLASS}__link`;
357
+ }
358
+ this.linkEl.setAttribute('href', href);
359
+ const target = this.getAttribute('target');
360
+ if (target)
361
+ this.linkEl.setAttribute('target', target);
362
+ else
363
+ this.linkEl.removeAttribute('target');
364
+ this.linkEl.setAttribute('aria-label', this.titleEl?.textContent || '배너 링크');
365
+ if (this.linkEl.parentElement !== this.contentEl) {
366
+ this.contentEl.append(this.linkEl);
367
+ }
368
+ }
369
+ /** show-countdown + end-date 가 있을 때만 카운트다운을 마운트한다. */
370
+ syncCountdown(show, endDate) {
371
+ if (!this.textEl || !this.countdownWrapEl)
372
+ return;
373
+ if (!show || !endDate) {
374
+ this.countdownWrapEl.remove();
375
+ return;
376
+ }
377
+ if (!this.countdownEl) {
378
+ this.countdownEl = document.createElement('db-countdown');
379
+ this.countdownEl.setAttribute('size', 's');
380
+ this.countdownEl.setAttribute('variant', 'compact');
381
+ this.countdownEl.setAttribute('show-labels', 'false');
382
+ this.countdownWrapEl.replaceChildren(this.countdownEl);
383
+ }
384
+ this.countdownEl.setAttribute('end-date', endDate);
385
+ if (this.countdownWrapEl.parentElement !== this.textEl) {
386
+ this.textEl.append(this.countdownWrapEl);
387
+ }
388
+ }
389
+ updateUI() {
390
+ if (!this.visible || this.getAttribute('open') === 'false') {
391
+ this.style.display = 'none';
392
+ return;
393
+ }
394
+ this.style.display = 'block';
395
+ const type = this.getType();
396
+ const variant = this.getVariant();
397
+ const size = this.getSize();
398
+ const title = this.getAttribute('title') || DEFAULT_TITLES[type];
399
+ const subtitle = this.getAttribute('subtitle') || DEFAULT_SUBTITLES[type];
400
+ const ctaText = this.getAttribute('cta-text') || DEFAULT_CTA[type];
401
+ const autoClose = this.getBool('auto-close');
402
+ const closeDelay = Math.max(Number(this.getAttribute('close-delay') || 5000), 1000);
403
+ const background = this.getBackground();
404
+ const gradientTone = this.getAttribute('gradient-tone') || 'vivid';
405
+ const showCountdown = this.getBool('show-countdown');
406
+ const countdownEndDate = this.getAttribute('countdown-end-date');
407
+ if (this.rootEl) {
408
+ this.rootEl.className = [
409
+ CLASS,
410
+ `${CLASS}--type-${type}`,
411
+ `${CLASS}--variant-${variant}`,
412
+ `${CLASS}--size-${size}`,
413
+ `${CLASS}--bg-${background}`,
414
+ autoClose && `${CLASS}--auto-close`,
415
+ background === 'gradient' && `${CLASS}--with-gradient`,
416
+ background === 'gradient' && gradientTone === 'light' && `${CLASS}--gradient-light`,
417
+ ]
418
+ .filter(Boolean)
419
+ .join(' ');
420
+ }
421
+ this.renderBackground(background, variant);
422
+ this.syncIcon(type);
423
+ this.syncBadge(type);
424
+ this.syncImage(type, this.getAttribute('image'));
425
+ this.syncLink(type, this.getAttribute('href'));
426
+ if (this.titleEl)
427
+ this.titleEl.textContent = title;
428
+ if (this.subtitleEl)
429
+ this.subtitleEl.textContent = subtitle;
430
+ this.syncCountdown(showCountdown, countdownEndDate);
431
+ // topbar 는 전체가 링크이므로 CTA 버튼을 숨긴다.
432
+ if (this.actionsEl)
433
+ this.actionsEl.hidden = type === 'topbar';
434
+ if (this.ctaEl) {
435
+ this.ctaEl.textContent = ctaText;
436
+ this.ctaEl.setAttribute('size', this.ctaButtonSize(type, size));
437
+ if (type === 'floating')
438
+ this.ctaEl.setAttribute('full-width', '');
439
+ else
440
+ this.ctaEl.removeAttribute('full-width');
441
+ }
442
+ if (this.progressEl)
443
+ this.progressEl.hidden = !autoClose;
444
+ if (this.progressBarEl && autoClose) {
445
+ this.progressBarEl.style.width = `${this.progress}%`;
446
+ }
447
+ this.stopAutoClose();
448
+ if (autoClose)
449
+ this.startAutoClose(closeDelay);
450
+ }
451
+ }
452
+ if (!customElements.get('db-ad-banner'))
453
+ customElements.define('db-ad-banner', DbAdBanner);
454
+
455
+ export { DbAdBanner };
@@ -1 +1,149 @@
1
- import"./db-button.js";import{createDbIcon as t}from"./db-icons.js";const e="designbase-wc-alert";class DbAlert extends HTMLElement{static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const n=this.getAttribute("variant")||"default",s=this.getAttribute("size")||"m",a="false"!==this.getAttribute("show-icon"),i="false"!==this.getAttribute("closable"),r=this.getAttribute("title")?.trim()||"",o=this.getAttribute("message")?.trim()||"",c=this.getAttribute("action-label"),l=this.getAttribute("action-variant")||"tertiary",d=this.parseActionButtons(),b=Boolean(o),m=Boolean(r),u=m&&!b||!m&&b,h=d.length>0?d:c?[{label:c,variant:l}]:[];this.className=[e,`${e}--${n}`,`${e}--${s}`,a&&`${e}--with-icon`,i&&`${e}--closable`,u&&`${e}--text-single`,h.length>0&&`${e}--has-actions`].filter(Boolean).join(" "),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite"),this.querySelector(`.${e}__content`)?.remove(),this.querySelector(`.${e}__actions`)?.remove(),Array.from(this.childNodes).forEach(t=>{t.nodeType===Node.TEXT_NODE&&t.remove()});const p=document.createElement("div");if(p.className=`${e}__content`,a){const a=document.createElement("div");a.className=`${e}__icon`,a.append(t(this.getIconName(n),"s"===s?16:"l"===s?24:20)),p.append(a)}const g=document.createElement("div");if(g.className=`${e}__body`,m){const t=document.createElement("div");t.className=`${e}__title`,t.textContent=r,g.append(t)}if(b){const t=document.createElement("div");t.className=`${e}__message`,t.textContent=o,g.append(t)}if(p.append(g),h.length>0){const t=document.createElement("div");t.className=`${e}__actions`;const n=document.createElement("div");n.className=`${e}__action-buttons`,h.forEach((t,e)=>{const a=document.createElement("db-button");a.setAttribute("variant",t.variant||"tertiary"),a.setAttribute("size",t.size||s),a.textContent=t.label,t.disabled&&a.setAttribute("disabled",""),a.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:e,label:t.label}}))}),n.append(a)}),t.append(n),p.append(t)}if(i){const n=document.createElement("button");n.type="button",n.className=`${e}__close`,n.setAttribute("aria-label","알림 닫기"),n.append(t("close",20)),n.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),p.append(n)}this.replaceChildren(p)}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
1
+ import './db-button.js';
2
+ import { createDbIcon } from './db-icons.js';
3
+
4
+ const CLASS = 'designbase-wc-alert';
5
+ class DbAlert extends HTMLElement {
6
+ static get observedAttributes() {
7
+ return [
8
+ 'title',
9
+ 'message',
10
+ 'variant',
11
+ 'size',
12
+ 'show-icon',
13
+ 'closable',
14
+ 'action-label',
15
+ 'action-variant',
16
+ 'action-buttons',
17
+ ];
18
+ }
19
+ connectedCallback() {
20
+ this.render();
21
+ }
22
+ attributeChangedCallback() {
23
+ this.render();
24
+ }
25
+ getIconName(variant) {
26
+ if (variant === 'success')
27
+ return 'circle-checked';
28
+ if (variant === 'warning')
29
+ return 'warning-filled';
30
+ if (variant === 'danger')
31
+ return 'error-filled';
32
+ return 'info-filled';
33
+ }
34
+ parseActionButtons() {
35
+ const raw = this.getAttribute('action-buttons');
36
+ if (!raw)
37
+ return [];
38
+ try {
39
+ const parsed = JSON.parse(raw);
40
+ return Array.isArray(parsed) ? parsed : [];
41
+ }
42
+ catch {
43
+ return [];
44
+ }
45
+ }
46
+ render() {
47
+ const variant = this.getAttribute('variant') || 'default';
48
+ const size = this.getAttribute('size') || 'm';
49
+ const showIcon = this.getAttribute('show-icon') !== 'false';
50
+ const closable = this.getAttribute('closable') !== 'false';
51
+ const title = this.getAttribute('title')?.trim() || '';
52
+ const messageAttr = this.getAttribute('message')?.trim() || '';
53
+ const actionLabel = this.getAttribute('action-label');
54
+ const actionVariant = this.getAttribute('action-variant') || 'tertiary';
55
+ const actionButtons = this.parseActionButtons();
56
+ const hasMessage = Boolean(messageAttr);
57
+ const hasTitle = Boolean(title);
58
+ const isSingleLine = (hasTitle && !hasMessage) || (!hasTitle && hasMessage);
59
+ const actions = actionButtons.length > 0
60
+ ? actionButtons
61
+ : actionLabel
62
+ ? [{ label: actionLabel, variant: actionVariant }]
63
+ : [];
64
+ this.className = [
65
+ CLASS,
66
+ `${CLASS}--${variant}`,
67
+ `${CLASS}--${size}`,
68
+ showIcon && `${CLASS}--with-icon`,
69
+ closable && `${CLASS}--closable`,
70
+ isSingleLine && `${CLASS}--text-single`,
71
+ actions.length > 0 && `${CLASS}--has-actions`,
72
+ ]
73
+ .filter(Boolean)
74
+ .join(' ');
75
+ this.setAttribute('role', 'alert');
76
+ this.setAttribute('aria-live', 'polite');
77
+ this.querySelector(`.${CLASS}__content`)?.remove();
78
+ this.querySelector(`.${CLASS}__actions`)?.remove();
79
+ Array.from(this.childNodes).forEach((node) => {
80
+ if (node.nodeType === Node.TEXT_NODE) {
81
+ node.remove();
82
+ }
83
+ });
84
+ const content = document.createElement('div');
85
+ content.className = `${CLASS}__content`;
86
+ if (showIcon) {
87
+ const icon = document.createElement('div');
88
+ icon.className = `${CLASS}__icon`;
89
+ icon.append(createDbIcon(this.getIconName(variant), size === 's' ? 16 : size === 'l' ? 24 : 20));
90
+ content.append(icon);
91
+ }
92
+ const body = document.createElement('div');
93
+ body.className = `${CLASS}__body`;
94
+ if (hasTitle) {
95
+ const heading = document.createElement('div');
96
+ heading.className = `${CLASS}__title`;
97
+ heading.textContent = title;
98
+ body.append(heading);
99
+ }
100
+ if (hasMessage) {
101
+ const text = document.createElement('div');
102
+ text.className = `${CLASS}__message`;
103
+ text.textContent = messageAttr;
104
+ body.append(text);
105
+ }
106
+ content.append(body);
107
+ if (actions.length > 0) {
108
+ const actionsEl = document.createElement('div');
109
+ actionsEl.className = `${CLASS}__actions`;
110
+ const buttonsWrap = document.createElement('div');
111
+ buttonsWrap.className = `${CLASS}__action-buttons`;
112
+ actions.forEach((action, index) => {
113
+ const button = document.createElement('db-button');
114
+ button.setAttribute('variant', action.variant || 'tertiary');
115
+ button.setAttribute('size', action.size || size);
116
+ button.textContent = action.label;
117
+ if (action.disabled)
118
+ button.setAttribute('disabled', '');
119
+ button.addEventListener('db-click', () => {
120
+ this.dispatchEvent(new CustomEvent('db-action', {
121
+ bubbles: true,
122
+ composed: true,
123
+ detail: { index, label: action.label },
124
+ }));
125
+ });
126
+ buttonsWrap.append(button);
127
+ });
128
+ actionsEl.append(buttonsWrap);
129
+ content.append(actionsEl);
130
+ }
131
+ if (closable) {
132
+ const close = document.createElement('button');
133
+ close.type = 'button';
134
+ close.className = `${CLASS}__close`;
135
+ close.setAttribute('aria-label', '알림 닫기');
136
+ close.append(createDbIcon('close', 20));
137
+ close.addEventListener('click', () => {
138
+ this.hidden = true;
139
+ this.dispatchEvent(new CustomEvent('db-close', { bubbles: true, composed: true }));
140
+ });
141
+ content.append(close);
142
+ }
143
+ this.replaceChildren(content);
144
+ }
145
+ }
146
+ if (!customElements.get('db-alert'))
147
+ customElements.define('db-alert', DbAlert);
148
+
149
+ export { DbAlert };