@designbasekorea/ui-wc 0.9.0 → 0.9.3

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 (118) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +18 -2
  3. package/dist/esm/components/date-picker-utils.js +1 -1
  4. package/dist/esm/components/db-accordion.js +1 -1
  5. package/dist/esm/components/db-achievement-list.js +1 -1
  6. package/dist/esm/components/db-achievement-modal.js +1 -1
  7. package/dist/esm/components/db-activity-heatmap.js +1 -1
  8. package/dist/esm/components/db-ad-banner.js +1 -1
  9. package/dist/esm/components/db-ai-chat-list.js +1 -1
  10. package/dist/esm/components/db-ai-chat.js +1 -1
  11. package/dist/esm/components/db-alert.d.ts +12 -0
  12. package/dist/esm/components/db-alert.js +1 -1
  13. package/dist/esm/components/db-app-badge.js +1 -1
  14. package/dist/esm/components/db-audio-player.js +1 -1
  15. package/dist/esm/components/db-backdrop.js +1 -1
  16. package/dist/esm/components/db-boarding-pass-stack.js +1 -1
  17. package/dist/esm/components/db-boarding-pass.js +1 -1
  18. package/dist/esm/components/db-bottom-navigation.js +1 -1
  19. package/dist/esm/components/db-bottom-sheet.js +1 -1
  20. package/dist/esm/components/db-breadcrumbs.js +1 -1
  21. package/dist/esm/components/db-calendar.js +1 -1
  22. package/dist/esm/components/db-card.js +1 -1
  23. package/dist/esm/components/db-carousel.d.ts +3 -3
  24. package/dist/esm/components/db-carousel.js +1 -1
  25. package/dist/esm/components/db-chat-composer.js +1 -1
  26. package/dist/esm/components/db-chat-room.js +1 -1
  27. package/dist/esm/components/db-chat-widget.js +1 -1
  28. package/dist/esm/components/db-chip.js +1 -1
  29. package/dist/esm/components/db-code-block.js +1 -1
  30. package/dist/esm/components/db-color-picker.js +1 -1
  31. package/dist/esm/components/db-confirm.js +1 -1
  32. package/dist/esm/components/db-context-bar.js +1 -1
  33. package/dist/esm/components/db-context-menu.js +1 -1
  34. package/dist/esm/components/db-credit-card.js +1 -1
  35. package/dist/esm/components/db-cursor-follower.js +1 -1
  36. package/dist/esm/components/db-date-picker.js +1 -1
  37. package/dist/esm/components/db-design-canvas.js +1 -1
  38. package/dist/esm/components/db-design-toolbar.js +1 -1
  39. package/dist/esm/components/db-download-progress.js +1 -1
  40. package/dist/esm/components/db-drawer.d.ts +1 -0
  41. package/dist/esm/components/db-drawer.js +1 -1
  42. package/dist/esm/components/db-dropdown.js +1 -1
  43. package/dist/esm/components/db-dropzone.js +1 -1
  44. package/dist/esm/components/db-email-verify.d.ts +0 -6
  45. package/dist/esm/components/db-email-verify.js +1 -1
  46. package/dist/esm/components/db-file-uploader.js +1 -1
  47. package/dist/esm/components/db-flight-status.js +1 -1
  48. package/dist/esm/components/db-footer.js +1 -1
  49. package/dist/esm/components/db-gantt.js +1 -1
  50. package/dist/esm/components/db-image-list.d.ts +2 -0
  51. package/dist/esm/components/db-image-list.js +1 -1
  52. package/dist/esm/components/db-indicator.js +1 -1
  53. package/dist/esm/components/db-input.js +1 -1
  54. package/dist/esm/components/db-kanban.js +1 -1
  55. package/dist/esm/components/db-lightbox.d.ts +4 -0
  56. package/dist/esm/components/db-lightbox.js +1 -1
  57. package/dist/esm/components/db-markdown-editor.js +1 -1
  58. package/dist/esm/components/db-marquee.d.ts +2 -10
  59. package/dist/esm/components/db-marquee.js +1 -1
  60. package/dist/esm/components/db-modal.js +1 -1
  61. package/dist/esm/components/db-navbar.js +1 -1
  62. package/dist/esm/components/db-node.js +1 -1
  63. package/dist/esm/components/db-onboarding-modal.js +1 -1
  64. package/dist/esm/components/db-otp-input.js +1 -1
  65. package/dist/esm/components/db-page-header.d.ts +8 -0
  66. package/dist/esm/components/db-page-header.js +1 -1
  67. package/dist/esm/components/db-pagination.js +1 -1
  68. package/dist/esm/components/db-phone-verify.js +1 -1
  69. package/dist/esm/components/db-popover.js +1 -1
  70. package/dist/esm/components/db-progress-step.js +1 -1
  71. package/dist/esm/components/db-receipt.js +1 -1
  72. package/dist/esm/components/db-resizable-panels.js +1 -1
  73. package/dist/esm/components/db-search-bar.js +1 -1
  74. package/dist/esm/components/db-section-testimonials.d.ts +1 -4
  75. package/dist/esm/components/db-section-testimonials.js +1 -1
  76. package/dist/esm/components/db-segment-control.d.ts +0 -4
  77. package/dist/esm/components/db-segment-control.js +1 -1
  78. package/dist/esm/components/db-select.js +1 -1
  79. package/dist/esm/components/db-share.js +1 -1
  80. package/dist/esm/components/db-sidebar.js +1 -1
  81. package/dist/esm/components/db-split-view.js +1 -1
  82. package/dist/esm/components/db-stepper.d.ts +0 -3
  83. package/dist/esm/components/db-stepper.js +1 -1
  84. package/dist/esm/components/db-table.js +1 -1
  85. package/dist/esm/components/db-testimonial.js +1 -1
  86. package/dist/esm/components/db-time-picker.js +1 -1
  87. package/dist/esm/components/db-tooltip.js +1 -1
  88. package/dist/esm/components/db-top-banner.js +1 -1
  89. package/dist/esm/components/db-tutorial.js +1 -1
  90. package/dist/esm/components/db-two-factor.d.ts +4 -10
  91. package/dist/esm/components/db-two-factor.js +1 -1
  92. package/dist/esm/components/db-video-player.js +1 -1
  93. package/dist/esm/components/db-voice-control.js +1 -1
  94. package/dist/esm/components/db-youtube-player.js +1 -1
  95. package/dist/esm/components/input-validation.js +1 -1
  96. package/dist/esm/components/paper-card.js +1 -1
  97. package/dist/esm/core/focus-trap.js +1 -1
  98. package/dist/esm/core/host-class.js +1 -0
  99. package/dist/esm/core/i18n-copy.js +1 -0
  100. package/dist/esm/core/i18n-en.js +1 -0
  101. package/dist/esm/core/i18n.d.ts +65 -1
  102. package/dist/esm/core/i18n.js +1 -1
  103. package/dist/esm/core/theme-scope.js +1 -0
  104. package/dist/esm/index.d.ts +1 -1
  105. package/dist/esm/index.js +1 -1
  106. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js +1 -0
  107. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-GM4TCAP5.js +1 -0
  108. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-GSN4JZN7.js +1 -0
  109. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-VJJVQGV4.js +1 -0
  110. package/dist/esm/node_modules/@designbasekorea/carousel/dist/chunks/chunk-YWLMJGDH.js +1 -0
  111. package/dist/index.cjs +1 -1
  112. package/dist/index.css +1 -1
  113. package/dist/index.d.ts +100 -41
  114. package/dist/index.esm.js +1 -1
  115. package/dist/react/index.cjs +1 -1
  116. package/dist/react/index.d.ts +12 -0
  117. package/dist/react/index.esm.js +1 -1
  118. package/package.json +5 -3
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{createFocusTrap as e}from"../core/focus-trap.js";import{lockScroll as s,unlockScroll as i}from"../core/scroll-lock.js";import{dbUid as n}from"../core/uid.js";import{LIGHTBOX_SIZES as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbLightbox extends HTMLElement{constructor(){super(...arguments),this.portalEl=null,this.scrollLocked=!1,this.titleId=n("db-lightbox-title"),this.imageEl=null,this.loadingEl=null,this.errorEl=null,this.counterBadge=null,this.prevNav=null,this.nextNav=null,this.currentIndex=0,this.imageLoaded=!1,this.imageError=!1,this.keydownHandler=null,this.boundSrc="",this.thumbnailSignature="",this.handleImageLoad=()=>{this.imageLoaded=!0,this.imageError=!1,this.syncImageLayers()},this.handleImageError=()=>{this.imageLoaded=!1,this.imageError=!0,this.syncImageLayers()}}static get observedAttributes(){return["images","current-index","size","open","enable-keyboard","show-thumbnails","show-counter","show-close-button","show-navigation-buttons","show-toolbar","close-on-backdrop-click","close-on-escape"]}connectedCallback(){this.classList.add("designbase-wc-lightbox-host"),this.syncOpenState()}disconnectedCallback(){this.unmount()}attributeChangedCallback(t,e,s){if("current-index"===t)return this.currentIndex=Number(s||0),this.resetImageState(),void(this.open&&this.refreshView());"open"!==t?"images"===t&&this.open&&this.refreshView():this.syncOpenState()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}parseImages(){const t=this.getAttribute("images");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}getCurrentImage(){return this.parseImages()[this.currentIndex]||null}resetImageState(){this.imageLoaded=!1,this.imageError=!1,this.boundSrc=""}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}goTo(t){const e=this.parseImages();if(!e.length)return;const s=(t%e.length+e.length)%e.length;s!==this.currentIndex&&(this.currentIndex=s,this.setAttribute("current-index",String(s)),this.resetImageState(),this.refreshView(),this.dispatchEvent(new CustomEvent("db-image-change",{bubbles:!0,composed:!0,detail:{index:s}})))}createIconButton(t,e,s,i,n={}){const a=document.createElement("db-button");return a.className=t,a.setAttribute("variant",n.variant||"ghost"),a.setAttribute("size",n.size||"m"),a.setAttribute("icon-only",""),a.setAttribute("start-icon",e),a.setAttribute("aria-label",s),n.radius&&a.setAttribute("radius",n.radius),a.addEventListener("db-click",i),a}buildPortal(){const e=this.getAttribute("size")||"l",s=a.includes(e)?e:"l",i=document.createElement("div");i.className=`designbase-wc-lightbox designbase-wc-lightbox--size-${s}`,i.setAttribute("data-wc-internal","");const n=document.createElement("div");n.className="designbase-wc-lightbox__overlay";const r=document.createElement("div");r.className="designbase-wc-lightbox__modal",r.setAttribute("role","dialog"),r.setAttribute("aria-modal","true"),r.setAttribute("aria-labelledby",this.titleId);const o=document.createElement("div");o.className="designbase-wc-lightbox__header";const l=document.createElement("div");l.className="designbase-wc-lightbox__title";const c=document.createElement("h3");c.className="designbase-wc-lightbox__title-text",c.id=this.titleId;const h=document.createElement("db-badge");h.className="designbase-wc-lightbox__counter",h.setAttribute("size","s"),h.setAttribute("variant","secondary"),h.setAttribute("type","text"),l.append(c,h);const d=document.createElement("div");d.className="designbase-wc-lightbox__header-actions","false"!==this.getAttribute("show-close-button")&&d.append(this.createIconButton("designbase-wc-lightbox__close-button","close","닫기",()=>this.close())),o.append(l,d);const g=document.createElement("div");g.className="designbase-wc-lightbox__content",this.prevNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--prev","chevron-left","이전 이미지",()=>this.goTo(this.currentIndex-1),{radius:"pill",size:"l"}),this.nextNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--next","chevron-right","다음 이미지",()=>this.goTo(this.currentIndex+1),{radius:"pill",size:"l"});const u=document.createElement("div");u.className="designbase-wc-lightbox__image-container",this.errorEl=document.createElement("div"),this.errorEl.className="designbase-wc-lightbox__error",this.errorEl.hidden=!0;const b=t("gallery",24);b.classList.add("designbase-wc-lightbox__error-icon"),this.errorEl.append(b);const m=document.createElement("p");m.className="designbase-wc-lightbox__error-text",m.textContent="이미지를 불러올 수 없습니다",this.errorEl.append(m),this.loadingEl=document.createElement("div"),this.loadingEl.className="designbase-wc-lightbox__loading";const p=document.createElement("db-spinner");p.setAttribute("type","circular"),p.setAttribute("size","m"),p.setAttribute("show-label",""),p.setAttribute("label","이미지 로딩 중..."),this.loadingEl.append(p),this.imageEl=document.createElement("img"),this.imageEl.className="designbase-wc-lightbox__image",this.imageEl.draggable=!1,this.imageEl.addEventListener("load",this.handleImageLoad),this.imageEl.addEventListener("error",this.handleImageError),u.append(this.errorEl,this.loadingEl,this.imageEl);const E=document.createElement("div");E.className="designbase-wc-lightbox__description";const x=document.createElement("p");x.className="designbase-wc-lightbox__description-text",E.append(x),"false"!==this.getAttribute("show-navigation-buttons")&&g.append(this.prevNav,this.nextNav),g.append(u,E);const _=document.createElement("div");_.className="designbase-wc-lightbox__thumbnails";const v=document.createElement("div");return v.className="designbase-wc-lightbox__thumbnails-container",_.append(v),r.append(o,g,_),n.append(r),i.append(n),n.addEventListener("click",t=>{t.target===n&&"false"!==this.getAttribute("close-on-backdrop-click")&&this.close()}),this.portalEl=i,this.counterBadge=h,i}syncImageLayers(){this.imageEl&&this.loadingEl&&this.errorEl&&(this.imageEl.classList.toggle("designbase-wc-lightbox__image--loaded",this.imageLoaded),this.loadingEl.hidden=this.imageLoaded||this.imageError,this.errorEl.hidden=!this.imageError,this.imageEl.hidden=this.imageError)}updateThumbnails(){if(!this.portalEl)return;const t=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails-container"),e=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails");if(!t||!e)return;const s=this.parseImages(),i="false"!==this.getAttribute("show-thumbnails")&&s.length>1;if(e.hidden=!i,!i)return t.replaceChildren(),void(this.thumbnailSignature="");const n=s.map(t=>t.thumbnail||t.src).join("|");n!==this.thumbnailSignature||t.childElementCount!==s.length?(this.thumbnailSignature=n,t.replaceChildren(),s.forEach((e,s)=>{const i=document.createElement("button");i.type="button",i.className=["designbase-wc-lightbox__thumbnail",s===this.currentIndex&&"designbase-wc-lightbox__thumbnail--active"].filter(Boolean).join(" "),i.title=e.title||`이미지 ${s+1}`,i.setAttribute("aria-label",e.alt||e.title||`이미지 ${s+1}`),i.setAttribute("aria-current",s===this.currentIndex?"true":"false");const n=document.createElement("img");n.className="designbase-wc-lightbox__thumbnail-image",n.src=e.thumbnail||e.src,n.alt="",n.draggable=!1,n.loading="lazy",n.decoding="async",i.append(n),i.addEventListener("click",()=>this.goTo(s)),t.append(i)})):Array.from(t.children).forEach((t,e)=>{const s=t,i=e===this.currentIndex;s.classList.toggle("designbase-wc-lightbox__thumbnail--active",i),s.setAttribute("aria-current",i?"true":"false")})}loadCurrentImage(){if(!this.imageEl)return;const t=this.getCurrentImage();if(!t?.src)return this.imageEl.removeAttribute("src"),this.resetImageState(),void this.syncImageLayers();this.boundSrc!==t.src&&(this.boundSrc=t.src,this.resetImageState(),this.imageEl.src=t.src,this.imageEl.alt=t.alt||t.title||`이미지 ${this.currentIndex+1}`,this.syncImageLayers(),this.imageEl.complete&&this.imageEl.naturalWidth>0&&this.handleImageLoad())}refreshView(){if(!this.portalEl)return;const t=this.getCurrentImage(),e=this.parseImages(),s=this.portalEl.querySelector(".designbase-wc-lightbox__title-text"),i=this.portalEl.querySelector(".designbase-wc-lightbox__description-text"),n=this.portalEl.querySelector(".designbase-wc-lightbox__description");if(s&&(s.textContent=t?.title||"",s.hidden=!t?.title),this.counterBadge){const t="false"!==this.getAttribute("show-counter")&&e.length>1?`${this.currentIndex+1} / ${e.length}`:"";this.counterBadge.textContent=t,this.counterBadge.hidden=!t}n&&i&&(i.textContent=t?.description||"",n.hidden=!t?.description);const a="false"!==this.getAttribute("show-navigation-buttons")&&e.length>1;this.prevNav&&(this.prevNav.hidden=!a),this.nextNav&&(this.nextNav.hidden=!a),this.loadCurrentImage(),this.updateThumbnails()}mount(){this.portalEl||(this.portalEl=this.buildPortal()),this.portalEl.isConnected||document.body.append(this.portalEl),this.scrollLocked||(s(),this.scrollLocked=!0);const t=this.portalEl.querySelector(".designbase-wc-lightbox__modal");t&&!this.focusTrap&&(this.focusTrap=e(t),requestAnimationFrame(()=>this.focusTrap?.activate())),this.keydownHandler||(this.keydownHandler=t=>{this.open&&"false"!==this.getAttribute("enable-keyboard")&&("Escape"===t.key&&"false"!==this.getAttribute("close-on-escape")&&(t.preventDefault(),this.close()),"ArrowLeft"===t.key&&this.goTo(this.currentIndex-1),"ArrowRight"===t.key&&this.goTo(this.currentIndex+1))},document.addEventListener("keydown",this.keydownHandler)),this.currentIndex=Number(this.getAttribute("current-index")||0),this.refreshView()}unmount(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.portalEl?.remove(),this.scrollLocked&&(this.scrollLocked=!1,i()),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null)}syncOpenState(){this.open?this.mount():this.unmount()}}customElements.get("db-lightbox")||customElements.define("db-lightbox",DbLightbox);export{DbLightbox};
1
+ import{inheritThemeScope as e}from"../core/theme-scope.js";import{dbText as t,dbFormat as s}from"../core/i18n.js";import{b as i}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-AGE5BHQ4.js";import{createDbIcon as n}from"./db-icons.js";import{createFocusTrap as r}from"../core/focus-trap.js";import{lockScroll as a,unlockScroll as o}from"../core/scroll-lock.js";import{dbUid as l}from"../core/uid.js";import{LIGHTBOX_SIZES as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbLightbox extends HTMLElement{constructor(){super(...arguments),this.portalEl=null,this.scrollLocked=!1,this.titleId=l("db-lightbox-title"),this.imageEl=null,this.carouselViewport=null,this.slideSignature="",this.loadingEl=null,this.errorEl=null,this.counterBadge=null,this.prevNav=null,this.nextNav=null,this.currentIndex=0,this.imageLoaded=!1,this.imageError=!1,this.keydownHandler=null,this.boundSrc="",this.thumbnailSignature="",this.handleImageLoad=()=>{this.imageLoaded=!0,this.imageError=!1,this.syncImageLayers()},this.handleImageError=()=>{this.imageLoaded=!1,this.imageError=!0,this.syncImageLayers()}}static get observedAttributes(){return["images","current-index","size","open","enable-keyboard","show-thumbnails","show-counter","show-close-button","show-navigation-buttons","show-toolbar","close-on-backdrop-click","close-on-escape"]}connectedCallback(){this.classList.add("designbase-wc-lightbox-host"),this.syncOpenState()}disconnectedCallback(){this.unmount()}attributeChangedCallback(e,t,s){if("current-index"===e)return this.currentIndex=Number(s||0),this.resetImageState(),void(this.open&&(this.carouselEngine&&this.carouselEngine.getState().index!==this.currentIndex&&this.carouselEngine.goTo(this.currentIndex,"instant"),this.refreshView()));"open"!==e?"images"===e&&this.open&&this.refreshView():this.syncOpenState()}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(e){e?this.setAttribute("open",""):this.removeAttribute("open")}parseImages(){const e=this.getAttribute("images");if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}getCurrentImage(){return this.parseImages()[this.currentIndex]||null}resetImageState(){this.imageLoaded=!1,this.imageError=!1,this.boundSrc=""}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}goTo(e){this.carouselEngine?.goTo(e)}ensureCarousel(e){const s=this.carouselViewport;if(!s||!this.portalEl)return;const n=JSON.stringify(e.map(e=>[e.id,e.src]));if(this.carouselEngine&&n===this.slideSignature)return;this.carouselEngine?.destroy(),this.slideSignature=n,this.currentIndex=Math.max(0,Math.min(this.currentIndex,e.length-1)),this.resetImageState(),s.replaceChildren(),e.forEach((e,t)=>{const i=document.createElement("div");i.className="designbase-wc-lightbox__slide";const n=document.createElement("img");n.className="designbase-wc-lightbox__image",n.src=e.src,n.alt=e.alt||e.title||`이미지 ${t+1}`,n.draggable=!1,n.loading=t===this.currentIndex?"eager":"lazy",n.addEventListener("load",()=>{n.classList.add("designbase-wc-lightbox__image--loaded"),t===this.currentIndex&&this.handleImageLoad()}),n.addEventListener("error",()=>{t===this.currentIndex&&this.handleImageError()}),i.append(n),s.append(i)}),this.carouselEngine=i(s.parentElement,{startIndex:this.currentIndex,slidesPerView:1,gap:0,rewind:!0,keyboard:!1,label:t("이미지 갤러리")});const sync=()=>{const e=this.carouselEngine.getState().index;e!==this.currentIndex&&(this.currentIndex=e,this.setAttribute("current-index",String(e)),this.dispatchEvent(new CustomEvent("db-image-change",{detail:{index:e},bubbles:!0,composed:!0})))};this.carouselEngine.on("change",sync),this.carouselEngine.on("refresh",sync)}createIconButton(e,t,s,i,n={}){const r=document.createElement("db-button");return r.className=e,r.setAttribute("variant",n.variant||"ghost"),r.setAttribute("size",n.size||"m"),r.setAttribute("icon-only",""),r.setAttribute("start-icon",t),r.setAttribute("aria-label",s),n.radius&&r.setAttribute("radius",n.radius),r.addEventListener("db-click",i),r}buildPortal(){const e=this.getAttribute("size")||"l",s=c.includes(e)?e:"l",i=document.createElement("div");i.className=`designbase-wc-lightbox designbase-wc-lightbox--size-${s}`,i.setAttribute("data-wc-internal","");const r=document.createElement("div");r.className="designbase-wc-lightbox__overlay";const a=document.createElement("div");a.className="designbase-wc-lightbox__modal",a.setAttribute("role","dialog"),a.setAttribute("aria-modal","true"),a.setAttribute("aria-labelledby",this.titleId);const o=document.createElement("div");o.className="designbase-wc-lightbox__header";const l=document.createElement("div");l.className="designbase-wc-lightbox__title";const h=document.createElement("h3");h.className="designbase-wc-lightbox__title-text",h.id=this.titleId;const d=document.createElement("db-badge");d.className="designbase-wc-lightbox__counter",d.setAttribute("size","s"),d.setAttribute("variant","secondary"),d.setAttribute("type","text"),l.append(h,d);const u=document.createElement("div");u.className="designbase-wc-lightbox__header-actions","false"!==this.getAttribute("show-close-button")&&u.append(this.createIconButton("designbase-wc-lightbox__close-button","close","닫기",()=>this.close())),o.append(l,u);const g=document.createElement("div");g.className="designbase-wc-lightbox__content",this.prevNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--prev","chevron-left","이전 이미지",()=>this.carouselEngine?.prev(),{radius:"pill",size:"l"}),this.nextNav=this.createIconButton("designbase-wc-lightbox__nav-button designbase-wc-lightbox__nav-button--next","chevron-right","다음 이미지",()=>this.carouselEngine?.next(),{radius:"pill",size:"l"});const b=document.createElement("div");b.className="designbase-wc-lightbox__image-container",this.errorEl=document.createElement("div"),this.errorEl.className="designbase-wc-lightbox__error",this.errorEl.hidden=!0;const m=n("gallery",24);m.classList.add("designbase-wc-lightbox__error-icon"),this.errorEl.append(m);const p=document.createElement("p");p.className="designbase-wc-lightbox__error-text",p.textContent=t("이미지를 불러올 수 없습니다"),this.errorEl.append(p),this.loadingEl=document.createElement("div"),this.loadingEl.className="designbase-wc-lightbox__loading";const E=document.createElement("db-spinner");E.setAttribute("type","circular"),E.setAttribute("size","m"),E.setAttribute("show-label",""),E.setAttribute("label","이미지 로딩 중..."),this.loadingEl.append(E),this.carouselViewport=document.createElement("div"),this.carouselViewport.className="designbase-wc-lightbox__viewport db-slide__viewport",b.append(this.carouselViewport,this.errorEl,this.loadingEl);const x=document.createElement("div");x.className="designbase-wc-lightbox__description";const w=document.createElement("p");w.className="designbase-wc-lightbox__description-text",x.append(w),"false"!==this.getAttribute("show-navigation-buttons")&&g.append(this.prevNav,this.nextNav),g.append(b,x);const _=document.createElement("div");_.className="designbase-wc-lightbox__thumbnails";const v=document.createElement("div");return v.className="designbase-wc-lightbox__thumbnails-container",_.append(v),a.append(o,g,_),r.append(a),i.append(r),r.addEventListener("click",e=>{e.target===r&&"false"!==this.getAttribute("close-on-backdrop-click")&&this.close()}),this.portalEl=i,this.counterBadge=d,i}syncImageLayers(){this.imageEl&&this.loadingEl&&this.errorEl&&(this.imageEl.classList.toggle("designbase-wc-lightbox__image--loaded",this.imageLoaded),this.loadingEl.hidden=this.imageLoaded||this.imageError,this.errorEl.hidden=!this.imageError,this.imageEl.hidden=this.imageError)}updateThumbnails(){if(!this.portalEl)return;const e=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails-container"),t=this.portalEl.querySelector(".designbase-wc-lightbox__thumbnails");if(!e||!t)return;const i=this.parseImages(),n="false"!==this.getAttribute("show-thumbnails")&&i.length>1;if(t.hidden=!n,!n)return e.replaceChildren(),void(this.thumbnailSignature="");const r=i.map(e=>e.thumbnail||e.src).join("|");r!==this.thumbnailSignature||e.childElementCount!==i.length?(this.thumbnailSignature=r,e.replaceChildren(),i.forEach((t,i)=>{const n=document.createElement("button");n.type="button",n.className=["designbase-wc-lightbox__thumbnail",i===this.currentIndex&&"designbase-wc-lightbox__thumbnail--active"].filter(Boolean).join(" "),n.title=t.title||s("이미지 {0}",[i+1]),n.setAttribute("aria-label",t.alt||t.title||`이미지 ${i+1}`),n.setAttribute("aria-current",i===this.currentIndex?"true":"false");const r=document.createElement("img");r.className="designbase-wc-lightbox__thumbnail-image",r.src=t.thumbnail||t.src,r.alt="",r.draggable=!1,r.loading="lazy",r.decoding="async",n.append(r),n.addEventListener("click",()=>this.goTo(i)),e.append(n)})):Array.from(e.children).forEach((e,t)=>{const s=e,i=t===this.currentIndex;s.classList.toggle("designbase-wc-lightbox__thumbnail--active",i),s.setAttribute("aria-current",i?"true":"false")})}loadCurrentImage(){if(this.imageEl=this.carouselViewport?.children[this.currentIndex]?.querySelector("img")||null,!this.imageEl)return;const e=this.getCurrentImage();if(!e?.src)return this.imageEl.removeAttribute("src"),this.resetImageState(),void this.syncImageLayers();this.boundSrc!==e.src&&(this.resetImageState(),this.boundSrc=e.src,this.imageEl.src=e.src,this.imageEl.alt=e.alt||e.title||`이미지 ${this.currentIndex+1}`,this.syncImageLayers(),this.imageEl.complete&&this.imageEl.naturalWidth>0&&this.handleImageLoad())}refreshView(){if(!this.portalEl)return;const e=this.parseImages();this.ensureCarousel(e);const t=this.getCurrentImage(),s=this.portalEl.querySelector(".designbase-wc-lightbox__title-text"),i=this.portalEl.querySelector(".designbase-wc-lightbox__description-text"),n=this.portalEl.querySelector(".designbase-wc-lightbox__description");if(s&&(s.textContent=t?.title||"",s.hidden=!t?.title),this.counterBadge){const t="false"!==this.getAttribute("show-counter")&&e.length>1?`${this.currentIndex+1} / ${e.length}`:"";this.counterBadge.textContent=t,this.counterBadge.hidden=!t}n&&i&&(i.textContent=t?.description||"",n.hidden=!t?.description);const r="false"!==this.getAttribute("show-navigation-buttons")&&e.length>1;this.prevNav&&(this.prevNav.hidden=!r),this.nextNav&&(this.nextNav.hidden=!r),this.loadCurrentImage(),this.updateThumbnails()}mount(){this.portalEl||(this.portalEl=this.buildPortal()),this.portalEl.isConnected||(e(this,this.portalEl),document.body.append(this.portalEl)),this.scrollLocked||(a(),this.scrollLocked=!0);const t=this.portalEl.querySelector(".designbase-wc-lightbox__modal");t&&!this.focusTrap&&(this.focusTrap=r(t),requestAnimationFrame(()=>this.focusTrap?.activate())),this.keydownHandler||(this.keydownHandler=e=>{this.open&&"false"!==this.getAttribute("enable-keyboard")&&("Escape"===e.key&&"false"!==this.getAttribute("close-on-escape")&&(e.preventDefault(),this.close()),"ArrowLeft"===e.key&&(e.preventDefault(),this.carouselEngine?.prev()),"ArrowRight"===e.key&&(e.preventDefault(),this.carouselEngine?.next()))},document.addEventListener("keydown",this.keydownHandler)),this.currentIndex=Number(this.getAttribute("current-index")||0),this.refreshView()}unmount(){this.carouselEngine?.destroy(),this.carouselEngine=void 0,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.portalEl?.remove(),this.scrollLocked&&(this.scrollLocked=!1,o()),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null)}syncOpenState(){this.open?this.mount():this.unmount()}}customElements.get("db-lightbox")||customElements.define("db-lightbox",DbLightbox);export{DbLightbox};
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{sanitizeHtmlFragment as e}from"../core/safe-html.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARKDOWN_EDITOR_SIZES as s,MARKDOWN_EDITOR_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const l="designbase-wc-markdown-editor";class DbMarkdownEditor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.internalValue="",this.currentMode="preview",this.isFocused=!1,this.wordCount=0,this.lineCount=0,this.lastSaved=null,this.isSaving=!1,this.handleKeyDown=t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;const{ctrlKey:e,shiftKey:i,key:s}=t;e&&"b"===s?(t.preventDefault(),this.insertText("**","**","**")):e&&"i"===s?(t.preventDefault(),this.insertText("*","*","*")):e&&"k"===s?(t.preventDefault(),this.insertText("[","](",")")):e&&"`"===s?(t.preventDefault(),this.insertText("`","`","`")):e&&i&&"S"===s?(t.preventDefault(),this.insertText("~~","~~","~~")):"Tab"===s&&(t.preventDefault(),this.insertText(" ","",""))}}static get observedAttributes(){return["size","variant","mode","theme","value","placeholder","min-height","max-height","auto-height","readonly","disabled","show-toolbar","show-status","show-word-count","show-line-count","auto-save","auto-save-interval","file-upload"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.syncFromAttributes(),this.renderMode(),this.updateCounts(),this.updateStatus(),this.setupAutoSave()}disconnectedCallback(){this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer)}attributeChangedCallback(t){if(this.built){if("value"===t&&this.textareaEl)return this.internalValue=this.getAttribute("value")||"",this.textareaEl.value=this.internalValue,this.updatePreview(),this.updateCodeView(),void this.updateCounts();if("mode"===t)return this.currentMode=this.getAttribute("mode")||"preview",void this.renderMode();"auto-save"!==t&&"auto-save-interval"!==t||this.setupAutoSave(),this.updateRootClasses()}}get value(){return this.internalValue}set value(t){this.internalValue=t,this.setAttribute("value",t),this.textareaEl&&(this.textareaEl.value=t),this.updatePreview(),this.updateCodeView(),this.updateCounts()}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}syncFromAttributes(){if(this.internalValue=this.getAttribute("value")||"",this.currentMode=this.getAttribute("mode")||"preview",this.textareaEl){this.textareaEl.value=this.internalValue,this.textareaEl.placeholder=this.getAttribute("placeholder")||"마크다운을 입력하세요...",this.textareaEl.readOnly=this.getBool("readonly"),this.textareaEl.disabled=this.getBool("disabled");const t=Number(this.getAttribute("min-height")||200),e=Number(this.getAttribute("max-height")||600),i=this.getBool("auto-height");this.textareaEl.style.minHeight=i?"auto":`${t}px`,this.textareaEl.style.maxHeight=i?"none":`${e}px`}this.updateRootClasses(),this.updatePreview(),this.updateCodeView()}updateRootClasses(){const t=i(this.getAttribute("size"),s,"m"),e=i(this.getAttribute("variant"),a,"default"),n=this.getAttribute("theme")||"light";this.className=[l,`${l}--size-${t}`,`${l}--variant-${e}`,`${l}--mode-${this.currentMode}`,`${l}--theme-${n}`,this.isFocused&&`${l}--focused`,this.getBool("disabled")&&`${l}--disabled`,this.getBool("readonly")&&`${l}--readonly`].filter(Boolean).join(" ")}markdownToHtml(t){return t.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/~~(.*)~~/gim,"<del>$1</del>").replace(/`(.*)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/!\[([^\]]*)\]\(([^)]+)\)/gim,'<img alt="$1" src="$2" />').replace(/^> (.*$)/gim,"<blockquote>$1</blockquote>").replace(/^- (.*$)/gim,"<ul><li>$1</li></ul>").replace(/^(\d+)\. (.*$)/gim,"<ol><li>$2</li></ol>").replace(/\n/gim,"<br />")}updatePreview(){this.previewEl&&this.previewEl.replaceChildren(e(this.markdownToHtml(this.internalValue)))}updateCodeView(){if(this.codeViewEl){const t=this.codeViewEl.querySelector("code");t&&(t.textContent=this.internalValue)}}updateCounts(){this.wordCount=this.internalValue.trim()?this.internalValue.trim().split(/\s+/).length:0,this.lineCount=this.internalValue?this.internalValue.split("\n").length:0,this.wordCountEl&&(this.wordCountEl.textContent=`단어: ${this.wordCount}`),this.lineCountEl&&(this.lineCountEl.textContent=`라인: ${this.lineCount}`)}updateStatus(){if(!this.statusEl)return;const t=this.getBool("show-status",!0);this.statusEl.hidden=!t,this.wordCountEl&&(this.wordCountEl.hidden=!this.getBool("show-word-count",!0)),this.lineCountEl&&(this.lineCountEl.hidden=!this.getBool("show-line-count",!0)),this.lastSavedEl&&(this.lastSavedEl.hidden=!this.lastSaved,this.lastSaved&&(this.lastSavedEl.textContent=`저장됨: ${this.lastSaved.toLocaleTimeString()}`)),this.savingEl&&(this.savingEl.hidden=!this.isSaving)}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.internalValue},bubbles:!0,composed:!0}))}insertText(t,e="",i=""){if(!this.textareaEl||this.getBool("disabled")||this.getBool("readonly"))return;const{selectionStart:s,selectionEnd:a}=this.textareaEl,l=this.internalValue.substring(s,a),n=e+(l||t)+i,o=this.internalValue.substring(0,s)+n+this.internalValue.substring(a);this.internalValue=o,this.textareaEl.value=o,this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts();const r=s+e.length+(l?l.length:t.length);window.setTimeout(()=>{this.textareaEl&&(this.textareaEl.setSelectionRange(r,r),this.textareaEl.focus())},0)}getDefaultToolbarActions(){return[{id:"bold",label:"B",tooltip:"굵게 (Ctrl+B)",shortcut:"Ctrl+B",action:()=>this.insertText("**","**","**")},{id:"italic",label:"I",tooltip:"기울임 (Ctrl+I)",shortcut:"Ctrl+I",action:()=>this.insertText("*","*","*")},{id:"strikethrough",label:"S",tooltip:"취소선 (Ctrl+Shift+S)",shortcut:"Ctrl+Shift+S",action:()=>this.insertText("~~","~~","~~")},{id:"separator1",label:"|",separator:!0,action:()=>{}},{id:"heading1",label:"H1",tooltip:"제목 1",action:()=>this.insertText("# ","","")},{id:"heading2",label:"H2",tooltip:"제목 2",action:()=>this.insertText("## ","","")},{id:"heading3",label:"H3",tooltip:"제목 3",action:()=>this.insertText("### ","","")},{id:"separator2",label:"|",separator:!0,action:()=>{}},{id:"link",label:"",icon:"share-alt",tooltip:"링크 (Ctrl+K)",shortcut:"Ctrl+K",action:()=>this.insertText("[","](",")")},{id:"image",label:"",icon:"video",tooltip:"이미지",action:()=>this.insertText("![","](",")")},{id:"code",label:"",icon:"code",tooltip:"인라인 코드 (Ctrl+`)",shortcut:"Ctrl+`",action:()=>this.insertText("`","`","`")},{id:"codeBlock",label:"```",tooltip:"코드 블록",action:()=>this.insertText("\n```\n","","\n```\n")},{id:"separator3",label:"|",separator:!0,action:()=>{}},{id:"list",label:"•",tooltip:"순서 없는 목록",action:()=>this.insertText("- ","","")},{id:"orderedList",label:"1.",tooltip:"순서 있는 목록",action:()=>this.insertText("1. ","","")},{id:"quote",label:'"',tooltip:"인용구",action:()=>this.insertText("> ","","")},{id:"separator4",label:"|",separator:!0,action:()=>{}},{id:"table",label:"⊞",tooltip:"테이블",action:()=>this.insertText("\n| 헤더1 | 헤더2 | 헤더3 |\n|-------|-------|-------|\n| 셀1 | 셀2 | 셀3 |\n","","")},{id:"horizontalRule",label:"—",tooltip:"수평선",action:()=>this.insertText("\n---\n","","")}]}renderToolbar(){if(!this.toolbarEl)return;const e=this.getBool("show-toolbar",!0);this.toolbarEl.hidden=!e,this.toolbarEl.replaceChildren();const i=document.createElement("div");i.className=`${l}__mode-buttons`;[{mode:"edit",icon:"write",title:"편집 모드"},{mode:"preview",icon:"show",title:"미리보기 모드"},{mode:"split",icon:"hide",title:"분할 모드"},{mode:"code",icon:"code",title:"코드 보기"}].forEach(({mode:e,icon:s,title:a})=>{const n=document.createElement("button");n.type="button",n.className=`${l}__mode-button${this.currentMode===e?` ${l}__mode-button--active`:""}`,n.title=a,n.append(t(s,16)),n.addEventListener("click",()=>{this.currentMode=e,this.updateRootClasses(),this.renderMode(),this.renderToolbar()}),i.append(n)}),this.toolbarEl.append(i);const s=document.createElement("div");if(s.className=`${l}__toolbar-separator`,this.toolbarEl.append(s),"code"!==this.currentMode&&(this.getDefaultToolbarActions().forEach(e=>{const i=document.createElement("button");if(i.type="button",i.className=`${l}__toolbar-item`,i.disabled=this.getBool("disabled"),e.tooltip&&(i.title=e.tooltip),e.icon)i.append(t(e.icon,16));else if("bold"===e.id){const t=document.createElement("strong");t.textContent=e.label,i.append(t)}else if("italic"===e.id){const t=document.createElement("em");t.textContent=e.label,i.append(t)}else if("strikethrough"===e.id){const t=document.createElement("span");t.style.textDecoration="line-through",t.textContent=e.label,i.append(t)}else i.textContent=e.label;if(e.shortcut){const t=document.createElement("span");t.className=`${l}__toolbar-shortcut`,t.textContent=e.shortcut,i.append(t)}i.addEventListener("click",e.action),this.toolbarEl?.append(i)}),this.getBool("file-upload"))){const e=document.createElement("label");e.className=`${l}__file-upload`;const i=document.createElement("input");i.type="file",i.accept="image/*",i.hidden=!0,i.addEventListener("change",async()=>{const t=i.files?.[0];if(!t)return;const e=new CustomEvent("db-file-upload",{detail:{file:t},bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(e),!e.defaultPrevented){const e=URL.createObjectURL(t);this.insertText(`![${t.name}](${e})`)}i.value=""}),e.append(i,t("upload",16)),this.toolbarEl.append(e)}}renderMode(){if(!this.editPanelEl||!this.previewPanelEl||!this.codePanelEl)return;const t="edit"===this.currentMode||"split"===this.currentMode,e="preview"===this.currentMode||"split"===this.currentMode,i="code"===this.currentMode;this.editPanelEl.hidden=!t,this.previewPanelEl.hidden=!e,this.codePanelEl.hidden=!i,this.updateRootClasses(),this.renderToolbar()}setupAutoSave(){if(this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer),!this.getBool("auto-save"))return;const t=Number(this.getAttribute("auto-save-interval")||3e4);this.autoSaveTimer=window.setInterval(()=>{const t=this.getAttribute("value")||"";this.internalValue&&this.internalValue!==t&&(this.isSaving=!0,this.updateStatus(),this.dispatchEvent(new CustomEvent("db-save",{detail:{value:this.internalValue},bubbles:!0,composed:!0})),this.isSaving=!1,this.lastSaved=new Date,this.updateStatus())},t)}build(){this.toolbarEl=document.createElement("div"),this.toolbarEl.className=`${l}__toolbar`,this.contentEl=document.createElement("div"),this.contentEl.className=`${l}__content`,this.editPanelEl=document.createElement("div"),this.editPanelEl.className=`${l}__edit-panel`,this.textareaEl=document.createElement("textarea"),this.textareaEl.className=`${l}__textarea`,this.textareaEl.addEventListener("input",()=>{this.internalValue=this.textareaEl?.value||"",this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts()}),this.textareaEl.addEventListener("focus",()=>{this.isFocused=!0,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("blur",()=>{this.isFocused=!1,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("keydown",this.handleKeyDown),this.editPanelEl.append(this.textareaEl),this.previewPanelEl=document.createElement("div"),this.previewPanelEl.className=`${l}__preview-panel`,this.previewEl=document.createElement("div"),this.previewEl.className=`${l}__preview`,this.previewPanelEl.append(this.previewEl),this.codePanelEl=document.createElement("div"),this.codePanelEl.className=`${l}__code-panel`,this.codeViewEl=document.createElement("pre"),this.codeViewEl.className=`${l}__code-view`;const t=document.createElement("code");this.codeViewEl.append(t),this.codePanelEl.append(this.codeViewEl),this.contentEl.append(this.editPanelEl,this.previewPanelEl,this.codePanelEl),this.statusEl=document.createElement("div"),this.statusEl.className=`${l}__status`,this.wordCountEl=document.createElement("span"),this.wordCountEl.className=`${l}__word-count`,this.lineCountEl=document.createElement("span"),this.lineCountEl.className=`${l}__line-count`,this.lastSavedEl=document.createElement("span"),this.lastSavedEl.className=`${l}__last-saved`,this.savingEl=document.createElement("span"),this.savingEl.className=`${l}__saving`,this.savingEl.textContent="저장 중...",this.statusEl.append(this.wordCountEl,this.lineCountEl,this.lastSavedEl,this.savingEl),this.append(this.toolbarEl,this.contentEl,this.statusEl)}}customElements.get("db-markdown-editor")||customElements.define("db-markdown-editor",DbMarkdownEditor);export{DbMarkdownEditor};
1
+ import{dbFormat as t,dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{sanitizeHtmlFragment as s}from"../core/safe-html.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARKDOWN_EDITOR_SIZES as l,MARKDOWN_EDITOR_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const o="designbase-wc-markdown-editor";class DbMarkdownEditor extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.internalValue="",this.currentMode="preview",this.isFocused=!1,this.wordCount=0,this.lineCount=0,this.lastSaved=null,this.isSaving=!1,this.handleKeyDown=t=>{if(this.getBool("disabled")||this.getBool("readonly"))return;const{ctrlKey:e,shiftKey:i,key:s}=t;e&&"b"===s?(t.preventDefault(),this.insertText("**","**","**")):e&&"i"===s?(t.preventDefault(),this.insertText("*","*","*")):e&&"k"===s?(t.preventDefault(),this.insertText("[","](",")")):e&&"`"===s?(t.preventDefault(),this.insertText("`","`","`")):e&&i&&"S"===s?(t.preventDefault(),this.insertText("~~","~~","~~")):"Tab"===s&&(t.preventDefault(),this.insertText(" ","",""))}}static get observedAttributes(){return["size","variant","mode","theme","value","placeholder","min-height","max-height","auto-height","readonly","disabled","show-toolbar","show-status","show-word-count","show-line-count","auto-save","auto-save-interval","file-upload"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.syncFromAttributes(),this.renderMode(),this.updateCounts(),this.updateStatus(),this.setupAutoSave()}disconnectedCallback(){this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer)}attributeChangedCallback(t){if(this.built){if("value"===t&&this.textareaEl)return this.internalValue=this.getAttribute("value")||"",this.textareaEl.value=this.internalValue,this.updatePreview(),this.updateCodeView(),void this.updateCounts();if("mode"===t)return this.currentMode=this.getAttribute("mode")||"preview",void this.renderMode();"auto-save"!==t&&"auto-save-interval"!==t||this.setupAutoSave(),this.updateRootClasses()}}get value(){return this.internalValue}set value(t){this.internalValue=t,this.setAttribute("value",t),this.textareaEl&&(this.textareaEl.value=t),this.updatePreview(),this.updateCodeView(),this.updateCounts()}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}syncFromAttributes(){if(this.internalValue=this.getAttribute("value")||"",this.currentMode=this.getAttribute("mode")||"preview",this.textareaEl){this.textareaEl.value=this.internalValue,this.textareaEl.placeholder=this.getAttribute("placeholder")||"마크다운을 입력하세요...",this.textareaEl.readOnly=this.getBool("readonly"),this.textareaEl.disabled=this.getBool("disabled");const t=Number(this.getAttribute("min-height")||200),e=Number(this.getAttribute("max-height")||600),i=this.getBool("auto-height");this.textareaEl.style.minHeight=i?"auto":`${t}px`,this.textareaEl.style.maxHeight=i?"none":`${e}px`}this.updateRootClasses(),this.updatePreview(),this.updateCodeView()}updateRootClasses(){const t=a(this.getAttribute("size"),l,"m"),e=a(this.getAttribute("variant"),n,"default"),i=this.getAttribute("theme")||"light";this.className=[o,`${o}--size-${t}`,`${o}--variant-${e}`,`${o}--mode-${this.currentMode}`,`${o}--theme-${i}`,this.isFocused&&`${o}--focused`,this.getBool("disabled")&&`${o}--disabled`,this.getBool("readonly")&&`${o}--readonly`].filter(Boolean).join(" ")}markdownToHtml(t){return t.replace(/^### (.*$)/gim,"<h3>$1</h3>").replace(/^## (.*$)/gim,"<h2>$1</h2>").replace(/^# (.*$)/gim,"<h1>$1</h1>").replace(/\*\*(.*)\*\*/gim,"<strong>$1</strong>").replace(/\*(.*)\*/gim,"<em>$1</em>").replace(/~~(.*)~~/gim,"<del>$1</del>").replace(/`(.*)`/gim,"<code>$1</code>").replace(/\[([^\]]+)\]\(([^)]+)\)/gim,'<a href="$2">$1</a>').replace(/!\[([^\]]*)\]\(([^)]+)\)/gim,'<img alt="$1" src="$2" />').replace(/^> (.*$)/gim,"<blockquote>$1</blockquote>").replace(/^- (.*$)/gim,"<ul><li>$1</li></ul>").replace(/^(\d+)\. (.*$)/gim,"<ol><li>$2</li></ol>").replace(/\n/gim,"<br />")}updatePreview(){this.previewEl&&this.previewEl.replaceChildren(s(this.markdownToHtml(this.internalValue)))}updateCodeView(){if(this.codeViewEl){const t=this.codeViewEl.querySelector("code");t&&(t.textContent=this.internalValue)}}updateCounts(){this.wordCount=this.internalValue.trim()?this.internalValue.trim().split(/\s+/).length:0,this.lineCount=this.internalValue?this.internalValue.split("\n").length:0,this.wordCountEl&&(this.wordCountEl.textContent=t("단어: {0}",[this.wordCount])),this.lineCountEl&&(this.lineCountEl.textContent=t("라인: {0}",[this.lineCount]))}updateStatus(){if(!this.statusEl)return;const e=this.getBool("show-status",!0);this.statusEl.hidden=!e,this.wordCountEl&&(this.wordCountEl.hidden=!this.getBool("show-word-count",!0)),this.lineCountEl&&(this.lineCountEl.hidden=!this.getBool("show-line-count",!0)),this.lastSavedEl&&(this.lastSavedEl.hidden=!this.lastSaved,this.lastSaved&&(this.lastSavedEl.textContent=t("저장됨: {0}",[this.lastSaved.toLocaleTimeString()]))),this.savingEl&&(this.savingEl.hidden=!this.isSaving)}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{detail:{value:this.internalValue},bubbles:!0,composed:!0}))}insertText(t,e="",i=""){if(!this.textareaEl||this.getBool("disabled")||this.getBool("readonly"))return;const{selectionStart:s,selectionEnd:a}=this.textareaEl,l=this.internalValue.substring(s,a),n=e+(l||t)+i,o=this.internalValue.substring(0,s)+n+this.internalValue.substring(a);this.internalValue=o,this.textareaEl.value=o,this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts();const r=s+e.length+(l?l.length:t.length);window.setTimeout(()=>{this.textareaEl&&(this.textareaEl.setSelectionRange(r,r),this.textareaEl.focus())},0)}getDefaultToolbarActions(){return[{id:"bold",label:"B",tooltip:"굵게 (Ctrl+B)",shortcut:"Ctrl+B",action:()=>this.insertText("**","**","**")},{id:"italic",label:"I",tooltip:"기울임 (Ctrl+I)",shortcut:"Ctrl+I",action:()=>this.insertText("*","*","*")},{id:"strikethrough",label:"S",tooltip:"취소선 (Ctrl+Shift+S)",shortcut:"Ctrl+Shift+S",action:()=>this.insertText("~~","~~","~~")},{id:"separator1",label:"|",separator:!0,action:()=>{}},{id:"heading1",label:"H1",tooltip:"제목 1",action:()=>this.insertText("# ","","")},{id:"heading2",label:"H2",tooltip:"제목 2",action:()=>this.insertText("## ","","")},{id:"heading3",label:"H3",tooltip:"제목 3",action:()=>this.insertText("### ","","")},{id:"separator2",label:"|",separator:!0,action:()=>{}},{id:"link",label:"",icon:"share-alt",tooltip:"링크 (Ctrl+K)",shortcut:"Ctrl+K",action:()=>this.insertText("[","](",")")},{id:"image",label:"",icon:"video",tooltip:"이미지",action:()=>this.insertText("![","](",")")},{id:"code",label:"",icon:"code",tooltip:"인라인 코드 (Ctrl+`)",shortcut:"Ctrl+`",action:()=>this.insertText("`","`","`")},{id:"codeBlock",label:"```",tooltip:"코드 블록",action:()=>this.insertText("\n```\n","","\n```\n")},{id:"separator3",label:"|",separator:!0,action:()=>{}},{id:"list",label:"•",tooltip:"순서 없는 목록",action:()=>this.insertText("- ","","")},{id:"orderedList",label:"1.",tooltip:"순서 있는 목록",action:()=>this.insertText("1. ","","")},{id:"quote",label:'"',tooltip:"인용구",action:()=>this.insertText("> ","","")},{id:"separator4",label:"|",separator:!0,action:()=>{}},{id:"table",label:"⊞",tooltip:"테이블",action:()=>this.insertText("\n| 헤더1 | 헤더2 | 헤더3 |\n|-------|-------|-------|\n| 셀1 | 셀2 | 셀3 |\n","","")},{id:"horizontalRule",label:"—",tooltip:"수평선",action:()=>this.insertText("\n---\n","","")}]}renderToolbar(){if(!this.toolbarEl)return;const t=this.getBool("show-toolbar",!0);this.toolbarEl.hidden=!t,this.toolbarEl.replaceChildren();const s=document.createElement("div");s.className=`${o}__mode-buttons`;[{mode:"edit",icon:"write",title:e("편집 모드")},{mode:"preview",icon:"show",title:e("미리보기 모드")},{mode:"split",icon:"hide",title:e("분할 모드")},{mode:"code",icon:"code",title:e("코드 보기")}].forEach(({mode:t,icon:e,title:a})=>{const l=document.createElement("button");l.type="button",l.className=`${o}__mode-button${this.currentMode===t?` ${o}__mode-button--active`:""}`,l.title=a,l.append(i(e,16)),l.addEventListener("click",()=>{this.currentMode=t,this.updateRootClasses(),this.renderMode(),this.renderToolbar()}),s.append(l)}),this.toolbarEl.append(s);const a=document.createElement("div");if(a.className=`${o}__toolbar-separator`,this.toolbarEl.append(a),"code"!==this.currentMode&&(this.getDefaultToolbarActions().forEach(t=>{const e=document.createElement("button");if(e.type="button",e.className=`${o}__toolbar-item`,e.disabled=this.getBool("disabled"),t.tooltip&&(e.title=t.tooltip),t.icon)e.append(i(t.icon,16));else if("bold"===t.id){const i=document.createElement("strong");i.textContent=t.label,e.append(i)}else if("italic"===t.id){const i=document.createElement("em");i.textContent=t.label,e.append(i)}else if("strikethrough"===t.id){const i=document.createElement("span");i.style.textDecoration="line-through",i.textContent=t.label,e.append(i)}else e.textContent=t.label;if(t.shortcut){const i=document.createElement("span");i.className=`${o}__toolbar-shortcut`,i.textContent=t.shortcut,e.append(i)}e.addEventListener("click",t.action),this.toolbarEl?.append(e)}),this.getBool("file-upload"))){const t=document.createElement("label");t.className=`${o}__file-upload`;const e=document.createElement("input");e.type="file",e.accept="image/*",e.hidden=!0,e.addEventListener("change",async()=>{const t=e.files?.[0];if(!t)return;const i=new CustomEvent("db-file-upload",{detail:{file:t},bubbles:!0,composed:!0,cancelable:!0});if(this.dispatchEvent(i),!i.defaultPrevented){const e=URL.createObjectURL(t);this.insertText(`![${t.name}](${e})`)}e.value=""}),t.append(e,i("upload",16)),this.toolbarEl.append(t)}}renderMode(){if(!this.editPanelEl||!this.previewPanelEl||!this.codePanelEl)return;const t="edit"===this.currentMode||"split"===this.currentMode,e="preview"===this.currentMode||"split"===this.currentMode,i="code"===this.currentMode;this.editPanelEl.hidden=!t,this.previewPanelEl.hidden=!e,this.codePanelEl.hidden=!i,this.updateRootClasses(),this.renderToolbar()}setupAutoSave(){if(this.autoSaveTimer&&window.clearInterval(this.autoSaveTimer),!this.getBool("auto-save"))return;const t=Number(this.getAttribute("auto-save-interval")||3e4);this.autoSaveTimer=window.setInterval(()=>{const t=this.getAttribute("value")||"";this.internalValue&&this.internalValue!==t&&(this.isSaving=!0,this.updateStatus(),this.dispatchEvent(new CustomEvent("db-save",{detail:{value:this.internalValue},bubbles:!0,composed:!0})),this.isSaving=!1,this.lastSaved=new Date,this.updateStatus())},t)}build(){this.toolbarEl=document.createElement("div"),this.toolbarEl.className=`${o}__toolbar`,this.contentEl=document.createElement("div"),this.contentEl.className=`${o}__content`,this.editPanelEl=document.createElement("div"),this.editPanelEl.className=`${o}__edit-panel`,this.textareaEl=document.createElement("textarea"),this.textareaEl.className=`${o}__textarea`,this.textareaEl.addEventListener("input",()=>{this.internalValue=this.textareaEl?.value||"",this.emitChange(),this.updatePreview(),this.updateCodeView(),this.updateCounts()}),this.textareaEl.addEventListener("focus",()=>{this.isFocused=!0,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-focus",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("blur",()=>{this.isFocused=!1,this.updateRootClasses(),this.dispatchEvent(new CustomEvent("db-blur",{bubbles:!0,composed:!0}))}),this.textareaEl.addEventListener("keydown",this.handleKeyDown),this.editPanelEl.append(this.textareaEl),this.previewPanelEl=document.createElement("div"),this.previewPanelEl.className=`${o}__preview-panel`,this.previewEl=document.createElement("div"),this.previewEl.className=`${o}__preview`,this.previewPanelEl.append(this.previewEl),this.codePanelEl=document.createElement("div"),this.codePanelEl.className=`${o}__code-panel`,this.codeViewEl=document.createElement("pre"),this.codeViewEl.className=`${o}__code-view`;const t=document.createElement("code");this.codeViewEl.append(t),this.codePanelEl.append(this.codeViewEl),this.contentEl.append(this.editPanelEl,this.previewPanelEl,this.codePanelEl),this.statusEl=document.createElement("div"),this.statusEl.className=`${o}__status`,this.wordCountEl=document.createElement("span"),this.wordCountEl.className=`${o}__word-count`,this.lineCountEl=document.createElement("span"),this.lineCountEl.className=`${o}__line-count`,this.lastSavedEl=document.createElement("span"),this.lastSavedEl.className=`${o}__last-saved`,this.savingEl=document.createElement("span"),this.savingEl.className=`${o}__saving`,this.savingEl.textContent=e("저장 중..."),this.statusEl.append(this.wordCountEl,this.lineCountEl,this.lastSavedEl,this.savingEl),this.append(this.toolbarEl,this.contentEl,this.statusEl)}}customElements.get("db-markdown-editor")||customElements.define("db-markdown-editor",DbMarkdownEditor);export{DbMarkdownEditor};
@@ -9,15 +9,8 @@ declare class DbMarquee extends HTMLElement {
9
9
  private resizeObserver?;
10
10
  private containerWidth;
11
11
  private gap;
12
- private scrollVelocityEnabled;
13
- private rafId;
14
- private lastFrameTime;
15
- private lastScrollY;
16
- private smoothedScrollV;
17
12
  private baseDurationSec;
18
- private reduceMotion;
19
13
  private boundMeasure;
20
- private boundFrame;
21
14
  connectedCallback(): void;
22
15
  disconnectedCallback(): void;
23
16
  attributeChangedCallback(): void;
@@ -42,9 +35,8 @@ declare class DbMarquee extends HTMLElement {
42
35
  /** 트랙을 채울 만큼의 복제 그룹 개수를 델타만 조정한다. */
43
36
  private reconcileDuplicates;
44
37
  private syncReadyState;
45
- private startScrollEngine;
46
- private stopScrollEngine;
47
- private frame;
38
+ private stopEngines;
39
+ private syncEngines;
48
40
  private updateUI;
49
41
  }
50
42
  declare global {
@@ -1 +1 @@
1
- import{sanitizeHref as t}from"../core/safe-url.js";import{coerceToContract as e}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARQUEE_SIZES as s,MARQUEE_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const i="designbase-wc-marquee";function isImageItem(t){return"object"==typeof t&&null!==t&&"string"==typeof t.src}class DbMarquee extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.rows=[],this.rowCount=0,this.containerWidth=0,this.gap=24,this.scrollVelocityEnabled=!1,this.rafId=0,this.lastFrameTime=0,this.lastScrollY=0,this.smoothedScrollV=0,this.baseDurationSec=12,this.reduceMotion=!1,this.boundMeasure=()=>this.measure(),this.boundFrame=t=>this.frame(t)}static get observedAttributes(){return["items","direction","duration","speed","size","variant","bordered","pause-on-hover","fade-edges","fade-width","edge-padding","gap","align-y","row-count","row-gap","scroll-velocity","scroll-boost","aria-label"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.reduceMotion="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,this.build(),this.bindResize()),this.updateUI()}disconnectedCallback(){this.resizeObserver?.disconnect(),this.stopScrollEngine(),this.unbindImageListeners()}attributeChangedCallback(){this.built&&this.updateUI()}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const s=this.getAttribute(t);return""===s||"true"===s}parseItems(){try{const t=this.getAttribute("items"),e=t?JSON.parse(t):[];if(Array.isArray(e)&&e.length>0)return e.filter(t=>"string"==typeof t||isImageItem(t))}catch{}const t=Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"));return t.length>0?t.map(t=>t.textContent?.trim()||""):[]}itemToText(t){return isImageItem(t)?t.alt||"":t}build(){this.containerEl=document.createElement("div"),this.srOnlyEl=document.createElement("span"),this.srOnlyEl.className=`${i}__sr-only`,this.rowsEl=document.createElement("div"),this.rowsEl.className=`${i}__rows`,this.containerEl.append(this.srOnlyEl,this.rowsEl),this.append(this.containerEl)}bindResize(){this.resizeObserver=new ResizeObserver(()=>this.measure()),this.containerEl&&this.resizeObserver.observe(this.containerEl)}reconcileRows(t,e){if(this.rowsEl){for(this.rowCount=t;this.rows.length<t;){const t=document.createElement("div");t.className=`${i}__row`;const e=document.createElement("div");e.className=`${i}__track`;const s=document.createElement("div");s.className=`${i}__group`,s.setAttribute("aria-hidden","true"),e.append(s),t.append(e),this.rowsEl.append(t),this.rows.push({rowEl:t,trackEl:e,baseGroupEl:s,baseGroupWidth:0,duplicateCount:0,baseDir:1,x:0,dirState:1})}for(;this.rows.length>t;){const t=this.rows.pop();t?.rowEl.remove()}this.rows.forEach((t,s)=>{t.baseDir=s%2==0?e:-e;const r=t.baseDir<0;t.rowEl.classList.toggle(`${i}__row--right`,r),t.rowEl.style.setProperty("--db-marquee-row-index",String(s))}),this.resizeObserver&&this.rows.forEach(t=>this.resizeObserver?.observe(t.baseGroupEl))}}measure(){this.containerWidth=Math.ceil(this.containerEl?.clientWidth??0),this.rows.forEach(t=>{t.baseGroupWidth=Math.ceil(t.baseGroupEl.scrollWidth??0),t.rowEl.style.setProperty("--db-marquee-shift",`${t.baseGroupWidth+this.gap}px`),this.reconcileDuplicates(t)}),this.syncReadyState()}unbindImageListeners(){this.rows.forEach(t=>{t.baseGroupEl.querySelectorAll("img").forEach(t=>{t.removeEventListener("load",this.boundMeasure),t.removeEventListener("error",this.boundMeasure)})})}bindImageListeners(){this.rows.forEach(t=>{t.baseGroupEl.querySelectorAll("img").forEach(t=>{t.complete||(t.addEventListener("load",this.boundMeasure),t.addEventListener("error",this.boundMeasure))})})}renderItem(e){const s=document.createElement("div");if(s.className=`${i}__item`,isImageItem(e)){s.classList.add(`${i}__item--image`);const r=document.createElement("img");r.className=`${i}__image`,r.src=e.src,r.alt=e.alt||"",r.loading="lazy",r.decoding="async",e.height&&(r.style.height=`${e.height}px`);const a=t(e.href,"");if(a){const t=document.createElement("a");t.className=`${i}__link`,t.href=a,t.setAttribute("tabindex","-1"),t.append(r),s.append(t)}else s.append(r);return s}return s.textContent=e,s}renderGroup(t,e){const s=e??document.createElement("div");return s.className=`${i}__group`,s.setAttribute("aria-hidden","true"),s.replaceChildren(...t.map(t=>this.renderItem(t))),s}buildBase(t){this.rows.forEach(e=>{for(this.renderGroup(t,e.baseGroupEl);e.trackEl.children.length>1;)e.trackEl.lastElementChild?.remove();e.duplicateCount=0})}baseImagesReady(t){return Array.from(t.baseGroupEl.querySelectorAll("img")).every(t=>t.complete)}reconcileDuplicates(t){const e=t.baseGroupWidth>0&&this.baseImagesReady(t)?Math.max(1,Math.ceil(2*this.containerWidth/t.baseGroupWidth)):1;let s=t.trackEl.children.length-1;if(s===e)return void(t.duplicateCount=e);const r=this.parseItems();for(;s<e;)t.trackEl.append(this.renderGroup(r)),s+=1;for(;s>e;)t.trackEl.lastElementChild?.remove(),s-=1;t.duplicateCount=e}syncReadyState(){if(!this.containerEl)return;const t=this.rows.length>0&&this.rows.every(t=>t.baseGroupWidth>0);this.containerEl.classList.toggle(`${i}--ready`,t)}startScrollEngine(){this.rafId||this.reduceMotion||(this.lastScrollY="undefined"!=typeof window?window.scrollY:0,this.lastFrameTime=0,this.smoothedScrollV=0,this.rows.forEach(t=>{t.x=0,t.dirState=1}),this.rafId=requestAnimationFrame(this.boundFrame))}stopScrollEngine(){this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=0),this.rows.forEach(t=>{t.trackEl.style.transform=""})}frame(t){if(!this.scrollVelocityEnabled)return void(this.rafId=0);this.lastFrameTime||(this.lastFrameTime=t);const e=Math.min((t-this.lastFrameTime)/1e3,.05);this.lastFrameTime=t;const s="undefined"!=typeof window?window.scrollY:0,r=e>0?(s-this.lastScrollY)/e:0;this.lastScrollY=s;const i=1-Math.exp(-e/.12);this.smoothedScrollV+=(r-this.smoothedScrollV)*i;const a=Math.max(Number(this.getAttribute("scroll-boost")||6),0),o=this.smoothedScrollV/800*(a/6);this.rows.forEach(t=>{const s=t.baseGroupWidth+this.gap;if(s<=0)return;const r=s/this.baseDurationSec;let i=-t.baseDir*r*e;o<0?t.dirState=-1:o>0&&(t.dirState=1),i*=t.dirState,i+=i*Math.abs(o);let a=(t.x+i)%s;a>0&&(a-=s),t.x=a,t.trackEl.style.transform=`translate3d(${a}px, 0, 0)`}),this.rafId=requestAnimationFrame(this.boundFrame)}updateUI(){const t=this.parseItems();if(0===t.length)return this.stopScrollEngine(),void(this.hidden=!0);this.hidden=!1;const a=this.getAttribute("direction")||"left",o="right"===a?-1:1,n=Math.max(Number(this.getAttribute("duration")||12),1),l=Number(this.getAttribute("speed")||1),h=n/(Number.isFinite(l)&&l>0?l:1);this.baseDurationSec=h;const c=e(this.getAttribute("size"),s,"m"),d=e(this.getAttribute("variant"),r,"default"),u=this.getAttribute("align-y")||"center",m=this.getBool("fade-edges"),b=Math.max(Number(this.getAttribute("fade-width")||48),0),p=this.getAttribute("edge-padding"),g=null!==p&&""!==p?Math.max(Number(p),0):m?b:0,E=Math.max(Number(this.getAttribute("gap")||24),0);this.gap=E;const f=Math.round(Number(this.getAttribute("row-count")||1)),w=Number.isFinite(f)?Math.min(Math.max(f,1),8):1,y=Math.max(Number(this.getAttribute("row-gap")||12),0),v=this.getBool("scroll-velocity");this.scrollVelocityEnabled=v;const A=this.getBool("pause-on-hover",!0),$=this.hasAttribute("bordered")?this.getBool("bordered"):"outlined"===d,S=this.getAttribute("aria-label")||"Scrolling content";if(this.containerEl&&(this.containerEl.className=[i,`${i}--size-${c}`,`${i}--variant-${d}`,`${i}--align-${u}`,A&&!v&&`${i}--pause-on-hover`,m&&`${i}--fade-edges`,"right"===a&&`${i}--right`,w>1&&`${i}--multi-row`,v&&`${i}--scroll-velocity`,$&&`${i}--bordered`].filter(Boolean).join(" "),this.containerEl.style.setProperty("--db-marquee-duration",`${h}s`),this.containerEl.style.setProperty("--db-marquee-gap",`${E}px`),this.containerEl.style.setProperty("--db-marquee-row-gap",`${y}px`),this.containerEl.style.setProperty("--db-marquee-fade-width",`${b}px`),this.containerEl.style.setProperty("--db-marquee-edge-padding",`${g}px`),this.containerEl.setAttribute("role","region"),this.containerEl.setAttribute("aria-label",S)),this.srOnlyEl){const e=t.map(t=>this.itemToText(t)).filter(Boolean).join(" • ");this.srOnlyEl.textContent=e||S}this.reconcileRows(w,o),this.buildBase(t),this.bindImageListeners(),this.measure(),v?this.startScrollEngine():this.stopScrollEngine()}}customElements.get("db-marquee")||customElements.define("db-marquee",DbMarquee);export{DbMarquee};
1
+ import{a as e}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-GSN4JZN7.js";import{a as t}from"../node_modules/@designbasekorea/carousel/dist/chunks/chunk-YWLMJGDH.js";import{sanitizeHref as s}from"../core/safe-url.js";import{coerceToContract as r}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{MARQUEE_SIZES as i,MARQUEE_VARIANTS as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a="designbase-wc-marquee";function isImageItem(e){return"object"==typeof e&&null!==e&&"string"==typeof e.src}class DbMarquee extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.rows=[],this.rowCount=0,this.containerWidth=0,this.gap=24,this.baseDurationSec=12,this.boundMeasure=()=>this.measure()}static get observedAttributes(){return["items","direction","duration","speed","size","variant","bordered","pause-on-hover","fade-edges","fade-width","edge-padding","gap","align-y","row-count","row-gap","scroll-velocity","scroll-boost","aria-label"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.bindResize(),this.updateUI()}disconnectedCallback(){this.resizeObserver?.disconnect(),this.resizeObserver=void 0,this.stopEngines(),this.unbindImageListeners()}attributeChangedCallback(){this.built&&this.updateUI()}getBool(e,t=!1){if(!this.hasAttribute(e))return t;const s=this.getAttribute(e);return""===s||"true"===s}parseItems(){try{const e=this.getAttribute("items"),t=e?JSON.parse(e):[];if(Array.isArray(t)&&t.length>0)return t.filter(e=>"string"==typeof e||isImageItem(e))}catch{}const e=Array.from(this.children).filter(e=>!e.hasAttribute("data-wc-internal"));return e.length>0?e.map(e=>e.textContent?.trim()||""):[]}itemToText(e){return isImageItem(e)?e.alt||"":e}build(){this.containerEl=document.createElement("div"),this.srOnlyEl=document.createElement("span"),this.srOnlyEl.className=`${a}__sr-only`,this.rowsEl=document.createElement("div"),this.rowsEl.className=`${a}__rows`,this.containerEl.append(this.srOnlyEl,this.rowsEl),this.append(this.containerEl)}bindResize(){this.resizeObserver?.disconnect(),this.resizeObserver=new ResizeObserver(()=>this.measure()),this.containerEl&&this.resizeObserver.observe(this.containerEl)}reconcileRows(e,t){if(this.rowsEl){for(this.rowCount=e;this.rows.length<e;){const e=document.createElement("div");e.className=`${a}__row`,e.setAttribute("aria-hidden","true");const t=document.createElement("div");t.className=`${a}__track db-slide__viewport`;const s=document.createElement("div");s.className=`${a}__group`,s.setAttribute("aria-hidden","true"),t.append(s),e.append(t),this.rowsEl.append(e),this.rows.push({rowEl:e,trackEl:t,baseGroupEl:s,baseGroupWidth:0,duplicateCount:0,baseDir:1})}for(;this.rows.length>e;){const e=this.rows.pop();e?.ticker?.destroy(),e?.engine?.destroy(),e?.rowEl.remove()}this.rows.forEach((e,s)=>{e.baseDir=s%2==0?t:-t;const r=e.baseDir<0;e.rowEl.classList.toggle(`${a}__row--right`,r),e.rowEl.style.setProperty("--db-marquee-row-index",String(s))}),this.resizeObserver&&this.rows.forEach(e=>this.resizeObserver?.observe(e.baseGroupEl))}}measure(){this.containerWidth=Math.ceil(this.containerEl?.clientWidth??0),this.rows.forEach(e=>{e.baseGroupWidth=Math.ceil(e.baseGroupEl.scrollWidth??0),e.rowEl.style.setProperty("--db-marquee-shift",`${e.baseGroupWidth+this.gap}px`),this.reconcileDuplicates(e)}),this.syncReadyState(),this.syncEngines()}unbindImageListeners(){this.rows.forEach(e=>{e.baseGroupEl.querySelectorAll("img").forEach(e=>{e.removeEventListener("load",this.boundMeasure),e.removeEventListener("error",this.boundMeasure)})})}bindImageListeners(){this.rows.forEach(e=>{e.baseGroupEl.querySelectorAll("img").forEach(e=>{e.complete||(e.addEventListener("load",this.boundMeasure),e.addEventListener("error",this.boundMeasure))})})}renderItem(e){const t=document.createElement("div");if(t.className=`${a}__item`,isImageItem(e)){t.classList.add(`${a}__item--image`);const r=document.createElement("img");r.className=`${a}__image`,r.src=e.src,r.alt=e.alt||"",r.loading="lazy",r.decoding="async",e.height&&(r.style.height=`${e.height}px`);const i=s(e.href,"");if(i){const e=document.createElement("a");e.className=`${a}__link`,e.href=i,e.setAttribute("tabindex","-1"),e.append(r),t.append(e)}else t.append(r);return t}return t.textContent=e,t}renderGroup(e,t){const s=t??document.createElement("div");return s.className=`${a}__group`,s.setAttribute("aria-hidden","true"),s.replaceChildren(...e.map(e=>this.renderItem(e))),s}buildBase(e){this.rows.forEach(t=>{for(this.renderGroup(e,t.baseGroupEl);t.trackEl.children.length>1;)t.trackEl.lastElementChild?.remove();t.duplicateCount=0})}baseImagesReady(e){return Array.from(e.baseGroupEl.querySelectorAll("img")).every(e=>e.complete)}reconcileDuplicates(e){const t=e.baseGroupWidth>0&&this.baseImagesReady(e)?Math.max(1,Math.ceil(2*this.containerWidth/e.baseGroupWidth)):1;let s=e.trackEl.children.length-1;if(s===t)return void(e.duplicateCount=t);const r=this.parseItems();for(;s<t;)e.trackEl.append(this.renderGroup(r)),s+=1;for(;s>t;)e.trackEl.lastElementChild?.remove(),s-=1;e.duplicateCount=t}syncReadyState(){if(!this.containerEl)return;const e=this.rows.length>0&&this.rows.every(e=>e.baseGroupWidth>0);this.containerEl.classList.toggle(`${a}--ready`,e)}stopEngines(){this.rows.forEach(e=>{e.ticker?.destroy(),e.engine?.destroy(),e.ticker=void 0,e.engine=void 0})}syncEngines(){this.isConnected&&this.rows.forEach(s=>{if(!s.baseGroupWidth||!this.baseImagesReady(s))return;s.engine?s.engine.update({slideSize:s.baseGroupWidth,gap:this.gap}):s.engine=e(s.rowEl,{slidesPerView:"auto",slideSize:s.baseGroupWidth,gap:this.gap,effect:"slide",loop:!0,mode:"free",drag:!1,keyboard:!1});const r={speed:(s.baseGroupWidth+this.gap)/this.baseDurationSec,direction:s.baseDir<0?"backward":"forward",pauseOnHover:this.getBool("pause-on-hover",!0)&&!this.getBool("scroll-velocity"),scrollVelocity:this.getBool("scroll-velocity"),scrollBoost:Number(this.getAttribute("scroll-boost")||6)};s.ticker?s.ticker.update(r):s.ticker=t(s.engine,r)})}updateUI(){this.stopEngines();const e=this.parseItems();if(0===e.length)return void(this.hidden=!0);this.hidden=!1;const t=this.getAttribute("direction")||"left",s="right"===t?-1:1,n=Math.max(Number(this.getAttribute("duration")||12),1),l=Number(this.getAttribute("speed")||1),h=n/(Number.isFinite(l)&&l>0?l:1);this.baseDurationSec=h;const d=r(this.getAttribute("size"),i,"m"),c=r(this.getAttribute("variant"),o,"default"),u=this.getAttribute("align-y")||"center",m=this.getBool("fade-edges"),b=Math.max(Number(this.getAttribute("fade-width")||48),0),p=this.getAttribute("edge-padding"),g=null!==p&&""!==p?Math.max(Number(p),0):m?b:0,E=Math.max(Number(this.getAttribute("gap")||24),0);this.gap=E;const y=Math.round(Number(this.getAttribute("row-count")||1)),f=Number.isFinite(y)?Math.min(Math.max(y,1),8):1,w=Math.max(Number(this.getAttribute("row-gap")||12),0),v=this.getBool("scroll-velocity"),A=this.getBool("pause-on-hover",!0),$=this.hasAttribute("bordered")?this.getBool("bordered"):"outlined"===c,k=this.getAttribute("aria-label")||"Scrolling content";if(this.containerEl&&(this.containerEl.className=[a,`${a}--size-${d}`,`${a}--variant-${c}`,`${a}--align-${u}`,A&&!v&&`${a}--pause-on-hover`,m&&`${a}--fade-edges`,"right"===t&&`${a}--right`,f>1&&`${a}--multi-row`,v&&`${a}--scroll-velocity`,$&&`${a}--bordered`].filter(Boolean).join(" "),this.containerEl.style.setProperty("--db-marquee-duration",`${h}s`),this.containerEl.style.setProperty("--db-marquee-gap",`${E}px`),this.containerEl.style.setProperty("--db-marquee-row-gap",`${w}px`),this.containerEl.style.setProperty("--db-marquee-fade-width",`${b}px`),this.containerEl.style.setProperty("--db-marquee-edge-padding",`${g}px`),this.containerEl.setAttribute("role","region"),this.containerEl.setAttribute("aria-label",k)),this.srOnlyEl){const t=e.map(e=>this.itemToText(e)).filter(Boolean).join(" • ");this.srOnlyEl.textContent=t||k}this.reconcileRows(f,s),this.buildBase(e),this.bindImageListeners(),this.measure()}}customElements.get("db-marquee")||customElements.define("db-marquee",DbMarquee);export{DbMarquee};
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{dbUid as e}from"../core/uid.js";import{createFocusTrap as s}from"../core/focus-trap.js";import{lockScroll as i,unlockScroll as n}from"../core/scroll-lock.js";import{labelFrom as r}from"../core/i18n.js";import{MODAL_SIZES as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";const l=["default","tabs","segment"],d=["s","m","l"];class DbModal extends HTMLElement{constructor(){super(...arguments),this.titleId=e("db-modal-title"),this.isMounted=!1,this.internalTabId="",this.internalSegment="",this.exitTimerId=null,this.handleDocumentKeyDown=t=>{"Escape"===t.key&&this.open&&"false"!==this.getAttribute("close-on-escape")&&(t.preventDefault(),this.close())}}static get observedAttributes(){return["open","title","size","header-variant","tabs","segments","selected-tab-id","default-selected-tab-id","segment-value","default-segment-value","nav-size","segment-full-width","close-on-outside-click","close-on-escape","show-close-button","role","describedby","label-close"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open","true"):this.removeAttribute("open")}connectedCallback(){this.classList.add("designbase-wc-modal-host"),document.addEventListener("keydown",this.handleDocumentKeyDown),this.childObserver=new MutationObserver(()=>{this.open&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.exitTimerId&&clearTimeout(this.exitTimerId),this.teardown()}attributeChangedCallback(t,e,s){if(e!==s&&this.isConnected)if("open"!==t){if("selected-tab-id"===t||"segment-value"===t){const t=this.getClassifiedChildren();return this.renderBodyContent(t.body),void this.renderHeader(t.header)}this.render(),this.isMounted&&this.syncVisibility()}else this.syncOpenState()}resolvedSize(){return a.includes(this.size)?this.size:"m"}get size(){return o(this.getAttribute("size"),a,"m")}set size(t){t?this.setAttribute("size",t):this.removeAttribute("size")}resolvedHeaderVariant(){const t=this.getAttribute("header-variant")||"default";return l.includes(t)?t:"default"}parsedTabs(){const t=this.getAttribute("tabs");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}parsedSegments(){const t=this.getAttribute("segments");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}usesIntegratedNav(){const t=this.resolvedHeaderVariant();return"tabs"===t&&this.parsedTabs().length>0||"segment"===t&&this.parsedSegments().length>0}closeIconSize(){const t=this.resolvedSize();return"s"===t?16:"l"===t?20:"xl"===t?24:18}activeTabId(){return this.getAttribute("selected-tab-id")||this.internalTabId||this.getAttribute("default-selected-tab-id")||this.parsedTabs()[0]?.id||""}activeSegmentValue(){return this.getAttribute("segment-value")||this.internalSegment||this.getAttribute("default-segment-value")||this.parsedSegments()[0]?.value||""}collectUserChildren(){return Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"))}classifyChildren(t){const e=t.filter(t=>this.isHeaderPart(t)),s=t.filter(t=>this.isFooterPart(t)),i=t.filter(t=>this.isBodyPart(t)),n=t.filter(t=>!e.includes(t)&&!s.includes(t)&&!i.includes(t));return{header:e,body:[...i,...n],footer:s}}getClassifiedChildren(){const t=this.classifyChildren(this.collectUserChildren());if(t.header.length||t.body.length||t.footer.length)return t;return{header:Array.from(this.headerEl?.children||[]).filter(t=>t!==this.closeButton&&!t.classList.contains("designbase-wc-modal__header-row")&&("header"===t.getAttribute("data-modal-part")||t.classList.contains("designbase-wc-modal__header"))),body:this.collectContentParts("body"),footer:this.collectContentParts("footer")}}isHeaderPart(t){return t.classList.contains("designbase-wc-modal__header")||"header"===t.getAttribute("data-modal-part")}isBodyPart(t){return t.classList.contains("designbase-wc-modal__body")||"body"===t.getAttribute("data-modal-part")}isFooterContainer(t){return!(!t.classList.contains("designbase-wc-modal__footer")&&"footer"!==t.getAttribute("data-modal-part"))||"footer"===t.getAttribute("slot")&&("div"===t.localName||"footer"===t.localName)}isFooterPart(t){return this.isFooterContainer(t)||"footer"===t.getAttribute("slot")}collectContentParts(t){if(!this.contentEl)return[];const e=Array.from(this.contentEl.children).filter(e=>"body"===t?this.isBodyPart(e):this.isFooterPart(e));if(e.length>0)return e;const s="footer"===t?Array.from(this.contentEl.querySelectorAll(':scope > [data-wc-part="footer"] > [slot="footer"]')):[];return s.length>0?s:Array.from(this.children).filter(e=>"body"===t?this.isBodyPart(e):this.isFooterPart(e))}footerAnchor(){return this.contentEl?.querySelector(':scope > .designbase-wc-modal__footer, :scope > [data-modal-part="footer"], :scope > [data-wc-part="footer"]')||null}ensurePartShell(t){if(!this.contentEl)return null;const e=this.contentEl.querySelector(`:scope > [data-wc-part="${t}"]`);if(e)return e;const s=document.createElement("div");return s.className=`designbase-wc-modal__${t}`,s.setAttribute("data-modal-part",t),s.setAttribute("data-wc-part",t),s.setAttribute("data-wc-internal",""),"footer"===t?this.contentEl.append(s):this.contentEl.insertBefore(s,this.footerAnchor()),s}placeBodyParts(t){const e=this.contentEl;if(!e)return;const s=t.filter(t=>this.isBodyPart(t)),i=t.filter(t=>!this.isBodyPart(t)&&!this.isFooterPart(t));if(s.length>0){const t=e.querySelector(':scope > [data-wc-part="body"]');return s.forEach(t=>{t.parentElement!==e&&e.insertBefore(t,this.footerAnchor())}),void(t&&!s.includes(t)&&t.remove())}if(0===i.length)return;const n=this.ensurePartShell("body");n&&i.forEach(t=>{t.parentElement!==n&&n.append(t)})}placeFooterParts(t){const e=this.contentEl;if(!e)return;const s=t.filter(t=>this.isFooterContainer(t)),i=t.filter(t=>!this.isFooterContainer(t)&&"footer"===t.getAttribute("slot"));if(s.length>0){const t=e.querySelector(':scope > [data-wc-part="footer"]');return s.forEach(t=>{t.classList.add("designbase-wc-modal__footer"),t.hasAttribute("data-modal-part")||t.setAttribute("data-modal-part","footer"),t.parentElement!==e&&e.append(t)}),void(t&&!s.includes(t)&&t.remove())}if(0===i.length)return;const n=this.ensurePartShell("footer");n&&i.forEach(t=>{t.parentElement!==n&&n.append(t)})}restorePartsToHost(){this.contentEl&&(this.contentEl.querySelectorAll("[data-wc-part]").forEach(t=>{for(;t.firstChild;)this.append(t.firstChild)}),Array.from(this.contentEl.children).filter(t=>!t.classList.contains("designbase-wc-modal__integrated-content")&&!t.hasAttribute("data-wc-internal")).forEach(t=>{t.parentElement!==this&&this.append(t)}))}bindFooterActions(){if(!this.contentEl||"true"===this.contentEl.dataset.modalActionsBound)return;this.contentEl.dataset.modalActionsBound="true";const handleClose=t=>{const e=t.target?.closest("[data-modal-close]");e&&this.contentEl?.contains(e)&&this.close()};this.contentEl.addEventListener("click",handleClose),this.contentEl.addEventListener("db-click",handleClose)}ensureStructure(){this.root||(this.root=document.createElement("div"),this.root.className="designbase-wc-modal__overlay",this.root.setAttribute("data-wc-internal",""),this.root.addEventListener("click",t=>{t.target===this.root&&"false"!==this.getAttribute("close-on-outside-click")&&this.close()}),this.panel=document.createElement("div"),this.panel.className="designbase-wc-modal",this.panel.setAttribute("role",this.dialogRole()),this.panel.setAttribute("aria-modal","true"),this.panel.addEventListener("click",t=>t.stopPropagation()),this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-modal__header",this.headerContentEl=document.createElement("div"),this.headerContentEl.className="designbase-wc-modal__header-content",this.titleEl=document.createElement("h2"),this.titleEl.className="designbase-wc-modal__title",this.titleEl.id=this.titleId,this.closeButton=document.createElement("button"),this.closeButton.type="button",this.closeButton.className="designbase-wc-modal__close-button",this.closeButton.setAttribute("aria-label",r(this,"label-close","modal.close")),this.closeButton.addEventListener("click",()=>this.close()),this.navEl=document.createElement("div"),this.navEl.className="designbase-wc-modal__header-nav",this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-modal__content",this.panel.append(this.headerEl,this.contentEl),this.root.append(this.panel))}renderCloseButton(){if(!this.closeButton)return;const e=this.closeIconSize(),s=t("close",e);s.setAttribute("aria-hidden","true"),this.closeButton.replaceChildren(s),this.closeButton.setAttribute("aria-label",r(this,"label-close","modal.close")),this.closeButton.hidden="false"===this.getAttribute("show-close-button")}renderDefaultHeader(t){if(!(this.headerEl&&this.headerContentEl&&this.titleEl&&this.closeButton))return;if(this.headerEl.className="designbase-wc-modal__header",this.headerEl.replaceChildren(),t.length>0)return t.forEach(t=>this.headerEl.append(t)),void("false"!==this.getAttribute("show-close-button")&&this.headerEl.append(this.closeButton));const e=this.getAttribute("title")||"";this.titleEl.textContent=e,this.titleEl.hidden=!e,this.headerContentEl.replaceChildren(),e&&this.headerContentEl.append(this.titleEl),this.renderCloseButton(),this.headerEl.append(this.headerContentEl),"false"!==this.getAttribute("show-close-button")&&this.headerEl.append(this.closeButton),this.panel&&(e?this.panel.setAttribute("aria-labelledby",this.titleId):this.panel.removeAttribute("aria-labelledby"),this.panel.setAttribute("role",this.dialogRole()),this.syncDescribedBy())}renderNavHeader(){if(!(this.headerEl&&this.headerContentEl&&this.titleEl&&this.closeButton&&this.navEl))return;const t=this.resolvedHeaderVariant(),e=this.parsedTabs(),s=this.parsedSegments(),i=d.includes(this.getAttribute("nav-size")||"m")?this.getAttribute("nav-size")||"m":"s";this.headerEl.className=["designbase-wc-modal__header","tabs"===t&&"designbase-wc-modal__header--tabs","segment"===t&&"designbase-wc-modal__header--segment"].filter(Boolean).join(" ");const n=this.getAttribute("title")||"";this.titleEl.textContent=n,this.titleEl.hidden=!n,this.headerContentEl.replaceChildren(),n&&this.headerContentEl.append(this.titleEl),this.renderCloseButton();const r=document.createElement("div");if(r.className="designbase-wc-modal__header-row",r.append(this.headerContentEl),"false"!==this.getAttribute("show-close-button")&&r.append(this.closeButton),this.headerEl.replaceChildren(r),this.navEl.replaceChildren(),"tabs"===t&&e.length>0){const t=document.createElement("db-tabs");t.setAttribute("size",i),t.setAttribute("items",JSON.stringify(e.map(t=>({id:t.id,label:t.label,disabled:t.disabled})))),t.setAttribute("selected-id",this.activeTabId()),t.addEventListener("db-change",t=>{const e=t.detail?.id;e&&(this.hasAttribute("selected-tab-id")||(this.internalTabId=e),this.dispatchEvent(new CustomEvent("db-tab-change",{detail:{tabId:e},bubbles:!0,composed:!0})),this.renderBodyContent(this.getClassifiedChildren().body))}),this.tabsEl=t,this.navEl.append(t),this.headerEl.append(this.navEl)}if("segment"===t&&s.length>0){const t=document.createElement("db-segment-control");t.setAttribute("size",i),t.setAttribute("options",JSON.stringify(s.map(t=>({value:t.value,label:t.label,disabled:t.disabled})))),t.setAttribute("value",this.activeSegmentValue()),"false"!==this.getAttribute("segment-full-width")&&t.setAttribute("full-width",""),t.addEventListener("db-change",t=>{const e=t.detail?.value;e&&(this.hasAttribute("segment-value")||(this.internalSegment=e),this.dispatchEvent(new CustomEvent("db-segment-change",{detail:{value:e},bubbles:!0,composed:!0})),this.renderBodyContent(this.getClassifiedChildren().body))}),this.segmentEl=t,this.navEl.append(t),this.headerEl.append(this.navEl)}this.panel&&(n?this.panel.setAttribute("aria-labelledby",this.titleId):this.panel.removeAttribute("aria-labelledby"))}renderHeader(t){if(!this.headerEl)return;if(t.length>0)return this.headerEl.hidden=!1,void this.renderDefaultHeader(t);if(this.usesIntegratedNav())return this.headerEl.hidden=!1,void this.renderNavHeader();this.getAttribute("title")||""?(this.headerEl.hidden=!1,this.renderDefaultHeader([])):this.headerEl.hidden=!0}renderBodyContent(t=[]){if(!this.contentEl)return;let e=this.contentEl.querySelector(":scope > .designbase-wc-modal__integrated-content"),s="";if(this.usesIntegratedNav()){const t=this.resolvedHeaderVariant();if("tabs"===t){const t=this.parsedTabs().find(t=>t.id===this.activeTabId());s=t?.content||""}if("segment"===t){const t=this.parsedSegments().find(t=>t.value===this.activeSegmentValue());s=t?.content||""}}s?(e||(e=document.createElement("div"),e.className="designbase-wc-modal__integrated-content designbase-wc-modal__body",this.contentEl.insertBefore(e,this.contentEl.firstChild)),e.textContent=s):e?.remove(),this.placeBodyParts(t)}renderFooter(t){this.contentEl&&(this.placeFooterParts(t),t.forEach(t=>{t instanceof HTMLElement&&(t.hidden=!1)}),this.bindFooterActions())}render(){this.ensureStructure();const{header:t,body:e,footer:s}=this.getClassifiedChildren();a.forEach(t=>this.panel?.classList.remove(`designbase-wc-modal--${t}`)),this.panel?.classList.add(`designbase-wc-modal--${this.resolvedSize()}`),this.renderHeader(t),this.renderBodyContent(e),this.renderFooter(s)}syncVisibility(){if(this.root&&this.panel){if(this.open){if(["entering","entered"].includes(this.root.getAttribute("data-state")||""))return;return this.root.setAttribute("data-state","entering"),this.panel.setAttribute("data-state","entering"),void requestAnimationFrame(()=>{this.panel,requestAnimationFrame(()=>{this.open&&this.root&&this.panel&&(this.root.setAttribute("data-state","entered"),this.panel.setAttribute("data-state","entered"))})})}this.root.setAttribute("data-state","exiting"),this.panel.setAttribute("data-state","exiting")}}syncOpenState(){if(this.open){if(this.render(),this.root&&!this.root.isConnected){(this.closest(".designbase-wp-admin")||document.body).append(this.root)}return this.isMounted||i(),this.isMounted=!0,this.syncVisibility(),void this.activateFocusTrap()}this.isMounted&&(this.syncVisibility(),this.focusTrap?.deactivate(),this.focusTrap=void 0,this.exitTimerId&&clearTimeout(this.exitTimerId),this.exitTimerId=window.setTimeout(()=>{this.open||this.teardown()},200))}activateFocusTrap(){this.panel&&!this.focusTrap&&(this.focusTrap=s(this.panel,{initialFocus:()=>this.panel?.querySelector("[autofocus]")||null}),this.focusTrap.activate())}teardown(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.restorePartsToHost(),this.root?.remove(),this.isMounted&&n(),this.isMounted=!1}dialogRole(){return"alertdialog"===this.getAttribute("role")?"alertdialog":"dialog"}syncDescribedBy(){if(!this.panel)return;const t=this.getAttribute("describedby");t?this.panel.setAttribute("aria-describedby",t):this.contentEl&&(this.contentEl.textContent||"").trim()?(this.contentEl.id||(this.contentEl.id=e("db-modal-desc")),this.panel.setAttribute("aria-describedby",this.contentEl.id)):this.panel.removeAttribute("aria-describedby")}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}}customElements.get("db-modal")||customElements.define("db-modal",DbModal);export{DbModal};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{createDbIcon as e}from"./db-icons.js";import{dbUid as s}from"../core/uid.js";import{createFocusTrap as i}from"../core/focus-trap.js";import{lockScroll as r,unlockScroll as n}from"../core/scroll-lock.js";import{labelFrom as a}from"../core/i18n.js";import{MODAL_SIZES as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as l}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";const d=["default","tabs","segment"],h=["s","m","l"];class DbModal extends HTMLElement{constructor(){super(...arguments),this.titleId=s("db-modal-title"),this.isMounted=!1,this.internalTabId="",this.internalSegment="",this.exitTimerId=null,this.handleDocumentKeyDown=t=>{"Escape"===t.key&&this.open&&"false"!==this.getAttribute("close-on-escape")&&(t.preventDefault(),this.close())}}static get observedAttributes(){return["open","title","size","header-variant","tabs","segments","selected-tab-id","default-selected-tab-id","segment-value","default-segment-value","nav-size","segment-full-width","close-on-outside-click","close-on-escape","show-close-button","role","describedby","label-close"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open","true"):this.removeAttribute("open")}connectedCallback(){this.classList.add("designbase-wc-modal-host"),document.addEventListener("keydown",this.handleDocumentKeyDown),this.childObserver=new MutationObserver(()=>{this.open&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.exitTimerId&&clearTimeout(this.exitTimerId),this.teardown()}attributeChangedCallback(t,e,s){if(e!==s&&this.isConnected)if("open"!==t){if("selected-tab-id"===t||"segment-value"===t){const t=this.getClassifiedChildren();return this.renderBodyContent(t.body),void this.renderHeader(t.header)}this.render(),this.isMounted&&this.syncVisibility()}else this.syncOpenState()}resolvedSize(){return o.includes(this.size)?this.size:"m"}get size(){return l(this.getAttribute("size"),o,"m")}set size(t){t?this.setAttribute("size",t):this.removeAttribute("size")}resolvedHeaderVariant(){const t=this.getAttribute("header-variant")||"default";return d.includes(t)?t:"default"}parsedTabs(){const t=this.getAttribute("tabs");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}parsedSegments(){const t=this.getAttribute("segments");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}usesIntegratedNav(){const t=this.resolvedHeaderVariant();return"tabs"===t&&this.parsedTabs().length>0||"segment"===t&&this.parsedSegments().length>0}closeIconSize(){const t=this.resolvedSize();return"s"===t?16:"l"===t?20:"xl"===t?24:18}activeTabId(){return this.getAttribute("selected-tab-id")||this.internalTabId||this.getAttribute("default-selected-tab-id")||this.parsedTabs()[0]?.id||""}activeSegmentValue(){return this.getAttribute("segment-value")||this.internalSegment||this.getAttribute("default-segment-value")||this.parsedSegments()[0]?.value||""}collectUserChildren(){return Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"))}classifyChildren(t){const e=t.filter(t=>this.isHeaderPart(t)),s=t.filter(t=>this.isFooterPart(t)),i=t.filter(t=>this.isBodyPart(t)),r=t.filter(t=>!e.includes(t)&&!s.includes(t)&&!i.includes(t));return{header:e,body:[...i,...r],footer:s}}getClassifiedChildren(){const t=this.classifyChildren(this.collectUserChildren());if(t.header.length||t.body.length||t.footer.length)return t;return{header:Array.from(this.headerEl?.children||[]).filter(t=>t!==this.closeButton&&!t.classList.contains("designbase-wc-modal__header-row")&&("header"===t.getAttribute("data-modal-part")||t.classList.contains("designbase-wc-modal__header"))),body:this.collectContentParts("body"),footer:this.collectContentParts("footer")}}isHeaderPart(t){return t.classList.contains("designbase-wc-modal__header")||"header"===t.getAttribute("data-modal-part")}isBodyPart(t){return t.classList.contains("designbase-wc-modal__body")||"body"===t.getAttribute("data-modal-part")}isFooterContainer(t){return!(!t.classList.contains("designbase-wc-modal__footer")&&"footer"!==t.getAttribute("data-modal-part"))||"footer"===t.getAttribute("slot")&&("div"===t.localName||"footer"===t.localName)}isFooterPart(t){return this.isFooterContainer(t)||"footer"===t.getAttribute("slot")}collectContentParts(t){if(!this.contentEl)return[];const e=Array.from(this.contentEl.children).filter(e=>"body"===t?this.isBodyPart(e):this.isFooterPart(e));if(e.length>0)return e;const s="footer"===t?Array.from(this.contentEl.querySelectorAll(':scope > [data-wc-part="footer"] > [slot="footer"]')):[];return s.length>0?s:Array.from(this.children).filter(e=>"body"===t?this.isBodyPart(e):this.isFooterPart(e))}footerAnchor(){return this.contentEl?.querySelector(':scope > .designbase-wc-modal__footer, :scope > [data-modal-part="footer"], :scope > [data-wc-part="footer"]')||null}ensurePartShell(t){if(!this.contentEl)return null;const e=this.contentEl.querySelector(`:scope > [data-wc-part="${t}"]`);if(e)return e;const s=document.createElement("div");return s.className=`designbase-wc-modal__${t}`,s.setAttribute("data-modal-part",t),s.setAttribute("data-wc-part",t),s.setAttribute("data-wc-internal",""),"footer"===t?this.contentEl.append(s):this.contentEl.insertBefore(s,this.footerAnchor()),s}placeBodyParts(t){const e=this.contentEl;if(!e)return;const s=t.filter(t=>this.isBodyPart(t)),i=t.filter(t=>!this.isBodyPart(t)&&!this.isFooterPart(t));if(s.length>0){const t=e.querySelector(':scope > [data-wc-part="body"]');return s.forEach(t=>{t.parentElement!==e&&e.insertBefore(t,this.footerAnchor())}),void(t&&!s.includes(t)&&t.remove())}if(0===i.length)return;const r=this.ensurePartShell("body");r&&i.forEach(t=>{t.parentElement!==r&&r.append(t)})}placeFooterParts(t){const e=this.contentEl;if(!e)return;const s=t.filter(t=>this.isFooterContainer(t)),i=t.filter(t=>!this.isFooterContainer(t)&&"footer"===t.getAttribute("slot"));if(s.length>0){const t=e.querySelector(':scope > [data-wc-part="footer"]');return s.forEach(t=>{t.classList.add("designbase-wc-modal__footer"),t.hasAttribute("data-modal-part")||t.setAttribute("data-modal-part","footer"),t.parentElement!==e&&e.append(t)}),void(t&&!s.includes(t)&&t.remove())}if(0===i.length)return;const r=this.ensurePartShell("footer");r&&i.forEach(t=>{t.parentElement!==r&&r.append(t)})}restorePartsToHost(){this.contentEl&&(this.contentEl.querySelectorAll("[data-wc-part]").forEach(t=>{for(;t.firstChild;)this.append(t.firstChild)}),Array.from(this.contentEl.children).filter(t=>!t.classList.contains("designbase-wc-modal__integrated-content")&&!t.hasAttribute("data-wc-internal")).forEach(t=>{t.parentElement!==this&&this.append(t)}))}bindFooterActions(){if(!this.contentEl||"true"===this.contentEl.dataset.modalActionsBound)return;this.contentEl.dataset.modalActionsBound="true";const handleClose=t=>{const e=t.target?.closest("[data-modal-close]");e&&this.contentEl?.contains(e)&&this.close()};this.contentEl.addEventListener("click",handleClose),this.contentEl.addEventListener("db-click",handleClose)}ensureStructure(){this.root||(this.root=document.createElement("div"),this.root.className="designbase-wc-modal__overlay",this.root.setAttribute("data-wc-internal",""),this.root.addEventListener("click",t=>{t.target===this.root&&"false"!==this.getAttribute("close-on-outside-click")&&this.close()}),this.panel=document.createElement("div"),this.panel.className="designbase-wc-modal",this.panel.setAttribute("role",this.dialogRole()),this.panel.setAttribute("aria-modal","true"),this.panel.addEventListener("click",t=>t.stopPropagation()),this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-modal__header",this.headerContentEl=document.createElement("div"),this.headerContentEl.className="designbase-wc-modal__header-content",this.titleEl=document.createElement("h2"),this.titleEl.className="designbase-wc-modal__title",this.titleEl.id=this.titleId,this.closeButton=document.createElement("button"),this.closeButton.type="button",this.closeButton.className="designbase-wc-modal__close-button",this.closeButton.setAttribute("aria-label",a(this,"label-close","modal.close")),this.closeButton.addEventListener("click",()=>this.close()),this.navEl=document.createElement("div"),this.navEl.className="designbase-wc-modal__header-nav",this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-modal__content",this.panel.append(this.headerEl,this.contentEl),this.root.append(this.panel))}renderCloseButton(){if(!this.closeButton)return;const t=this.closeIconSize(),s=e("close",t);s.setAttribute("aria-hidden","true"),this.closeButton.replaceChildren(s),this.closeButton.setAttribute("aria-label",a(this,"label-close","modal.close")),this.closeButton.hidden="false"===this.getAttribute("show-close-button")}renderDefaultHeader(t){if(!(this.headerEl&&this.headerContentEl&&this.titleEl&&this.closeButton))return;if(this.headerEl.className="designbase-wc-modal__header",this.headerEl.replaceChildren(),t.length>0)return t.forEach(t=>this.headerEl.append(t)),void("false"!==this.getAttribute("show-close-button")&&this.headerEl.append(this.closeButton));const e=this.getAttribute("title")||"";this.titleEl.textContent=e,this.titleEl.hidden=!e,this.headerContentEl.replaceChildren(),e&&this.headerContentEl.append(this.titleEl),this.renderCloseButton(),this.headerEl.append(this.headerContentEl),"false"!==this.getAttribute("show-close-button")&&this.headerEl.append(this.closeButton),this.panel&&(e?this.panel.setAttribute("aria-labelledby",this.titleId):this.panel.removeAttribute("aria-labelledby"),this.panel.setAttribute("role",this.dialogRole()),this.syncDescribedBy())}renderNavHeader(){if(!(this.headerEl&&this.headerContentEl&&this.titleEl&&this.closeButton&&this.navEl))return;const t=this.resolvedHeaderVariant(),e=this.parsedTabs(),s=this.parsedSegments(),i=h.includes(this.getAttribute("nav-size")||"m")?this.getAttribute("nav-size")||"m":"s";this.headerEl.className=["designbase-wc-modal__header","tabs"===t&&"designbase-wc-modal__header--tabs","segment"===t&&"designbase-wc-modal__header--segment"].filter(Boolean).join(" ");const r=this.getAttribute("title")||"";this.titleEl.textContent=r,this.titleEl.hidden=!r,this.headerContentEl.replaceChildren(),r&&this.headerContentEl.append(this.titleEl),this.renderCloseButton();const n=document.createElement("div");if(n.className="designbase-wc-modal__header-row",n.append(this.headerContentEl),"false"!==this.getAttribute("show-close-button")&&n.append(this.closeButton),this.headerEl.replaceChildren(n),this.navEl.replaceChildren(),"tabs"===t&&e.length>0){const t=document.createElement("db-tabs");t.setAttribute("size",i),t.setAttribute("items",JSON.stringify(e.map(t=>({id:t.id,label:t.label,disabled:t.disabled})))),t.setAttribute("selected-id",this.activeTabId()),t.addEventListener("db-change",t=>{const e=t.detail?.id;e&&(this.hasAttribute("selected-tab-id")||(this.internalTabId=e),this.dispatchEvent(new CustomEvent("db-tab-change",{detail:{tabId:e},bubbles:!0,composed:!0})),this.renderBodyContent(this.getClassifiedChildren().body))}),this.tabsEl=t,this.navEl.append(t),this.headerEl.append(this.navEl)}if("segment"===t&&s.length>0){const t=document.createElement("db-segment-control");t.setAttribute("size",i),t.setAttribute("options",JSON.stringify(s.map(t=>({value:t.value,label:t.label,disabled:t.disabled})))),t.setAttribute("value",this.activeSegmentValue()),"false"!==this.getAttribute("segment-full-width")&&t.setAttribute("full-width",""),t.addEventListener("db-change",t=>{const e=t.detail?.value;e&&(this.hasAttribute("segment-value")||(this.internalSegment=e),this.dispatchEvent(new CustomEvent("db-segment-change",{detail:{value:e},bubbles:!0,composed:!0})),this.renderBodyContent(this.getClassifiedChildren().body))}),this.segmentEl=t,this.navEl.append(t),this.headerEl.append(this.navEl)}this.panel&&(r?this.panel.setAttribute("aria-labelledby",this.titleId):this.panel.removeAttribute("aria-labelledby"))}renderHeader(t){if(!this.headerEl)return;if(t.length>0)return this.headerEl.hidden=!1,void this.renderDefaultHeader(t);if(this.usesIntegratedNav())return this.headerEl.hidden=!1,void this.renderNavHeader();this.getAttribute("title")||""?(this.headerEl.hidden=!1,this.renderDefaultHeader([])):this.headerEl.hidden=!0}renderBodyContent(t=[]){if(!this.contentEl)return;let e=this.contentEl.querySelector(":scope > .designbase-wc-modal__integrated-content"),s="";if(this.usesIntegratedNav()){const t=this.resolvedHeaderVariant();if("tabs"===t){const t=this.parsedTabs().find(t=>t.id===this.activeTabId());s=t?.content||""}if("segment"===t){const t=this.parsedSegments().find(t=>t.value===this.activeSegmentValue());s=t?.content||""}}s?(e||(e=document.createElement("div"),e.className="designbase-wc-modal__integrated-content designbase-wc-modal__body",this.contentEl.insertBefore(e,this.contentEl.firstChild)),e.textContent=s):e?.remove(),this.placeBodyParts(t)}renderFooter(t){this.contentEl&&(this.placeFooterParts(t),t.forEach(t=>{t instanceof HTMLElement&&(t.hidden=!1)}),this.bindFooterActions())}render(){this.ensureStructure();const{header:t,body:e,footer:s}=this.getClassifiedChildren();o.forEach(t=>this.panel?.classList.remove(`designbase-wc-modal--${t}`)),this.panel?.classList.add(`designbase-wc-modal--${this.resolvedSize()}`),this.renderHeader(t),this.renderBodyContent(e),this.renderFooter(s)}syncVisibility(){if(this.root&&this.panel){if(this.open){if(["entering","entered"].includes(this.root.getAttribute("data-state")||""))return;return this.root.setAttribute("data-state","entering"),this.panel.setAttribute("data-state","entering"),void requestAnimationFrame(()=>{this.panel,requestAnimationFrame(()=>{this.open&&this.root&&this.panel&&(this.root.setAttribute("data-state","entered"),this.panel.setAttribute("data-state","entered"))})})}this.root.setAttribute("data-state","exiting"),this.panel.setAttribute("data-state","exiting")}}syncOpenState(){if(this.open){if(this.render(),this.root&&!this.root.isConnected){const e=this.closest(".designbase-wp-admin")||document.body;t(this,this.root),e.append(this.root)}return this.isMounted||r(),this.isMounted=!0,this.syncVisibility(),void this.activateFocusTrap()}this.isMounted&&(this.syncVisibility(),this.focusTrap?.deactivate(),this.focusTrap=void 0,this.exitTimerId&&clearTimeout(this.exitTimerId),this.exitTimerId=window.setTimeout(()=>{this.open||this.teardown()},200))}activateFocusTrap(){this.panel&&!this.focusTrap&&(this.focusTrap=i(this.panel,{initialFocus:()=>this.panel?.querySelector("[autofocus]")||null}),this.focusTrap.activate())}teardown(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.restorePartsToHost(),this.root?.remove(),this.isMounted&&n(),this.isMounted=!1}dialogRole(){return"alertdialog"===this.getAttribute("role")?"alertdialog":"dialog"}syncDescribedBy(){if(!this.panel)return;const t=this.getAttribute("describedby");t?this.panel.setAttribute("aria-describedby",t):this.contentEl&&(this.contentEl.textContent||"").trim()?(this.contentEl.id||(this.contentEl.id=s("db-modal-desc")),this.panel.setAttribute("aria-describedby",this.contentEl.id)):this.panel.removeAttribute("aria-describedby")}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}}customElements.get("db-modal")||customElements.define("db-modal",DbModal);export{DbModal};
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{sanitizeHref as t}from"../core/safe-url.js";import{NAVBAR_SIZES as a,NAVBAR_VARIANTS as n,NAVBAR_POSITIONS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function resolveIcon(e){if(e)return e}class DbNavbar extends HTMLElement{constructor(){super(...arguments),this.mobileMenuId="db-navbar-menu-"+ ++DbNavbar.nextId,this.mobileOpen=!1,this.userMenuOpen=!1,this.expandedMobile={},this.outsideHandler=null}static get observedAttributes(){return["logo-src","logo-alt","items","user-menu-items","user-profile","size","variant","position","is-authenticated","show-search","search-placeholder","full-width","shadow"]}connectedCallback(){this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick()}attributeChangedCallback(){this.isConnected&&this.render()}get items(){return this.parseItems("items")}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseItems("user-menu-items")}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}parseItems(e="items"){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}iconSize(e){return"s"===e?16:"l"===e?24:20}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{this.contains(e.target)||(this.userMenuOpen=!1,this.updateUserMenuVisibility())},document.addEventListener("mousedown",this.outsideHandler))}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}dispatchItemClick(e,t){this.dispatchEvent(new CustomEvent("user"===t?"db-user-menu-item-click":"db-item-click",{bubbles:!0,composed:!0,detail:{item:e,source:t}}))}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",i=this.getAttribute("position")||"static";this.className=["designbase-wc-navbar",`designbase-wc-navbar--${a.includes(e)?e:"m"}`,`designbase-wc-navbar--${n.includes(t)?t:"default"}`,`designbase-wc-navbar--${s.includes(i)?i:"static"}`,this.hasAttribute("full-width")&&"designbase-wc-navbar--full-width",this.hasAttribute("shadow")&&"designbase-wc-navbar--shadow",this.mobileOpen&&"designbase-wc-navbar--mobile-open"].filter(Boolean).join(" ")}isMegaMenu(e){return Boolean(e.megaMenu&&e.columns?.length)}createNavToggleButton(t,a){const n=document.createElement("button");n.type="button",n.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",t.active&&"designbase-wc-navbar__nav-link--active",t.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),n.disabled=Boolean(t.disabled);const s=resolveIcon(t.icon);s&&n.append(e(s,a)),n.append(document.createTextNode(t.label));const i=e("chevron-down",12);return i.classList.add("designbase-wc-navbar__chevron"),n.append(i),n}createMegaLink(a,n){const s=document.createElement("a");s.href=t(a.href,"#"),s.className=["designbase-wc-navbar__mega-link",a.active&&"designbase-wc-navbar__mega-link--active",a.disabled&&"designbase-wc-navbar__mega-link--disabled"].filter(Boolean).join(" ");const i=resolveIcon(a.icon);if(i){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-link-icon",t.append(e(i,n)),s.append(t)}const r=document.createElement("span");r.className="designbase-wc-navbar__mega-link-body";const c=document.createElement("span");if(c.className="designbase-wc-navbar__mega-link-label",c.textContent=a.label,r.append(c),a.description){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-link-desc",e.textContent=a.description,r.append(e)}return s.append(r),s.addEventListener("click",e=>{e.preventDefault(),a.disabled||this.dispatchItemClick(a,"nav")}),s}createMegaMenu(e,t){const a=document.createElement("li");a.className="designbase-wc-navbar__nav-item designbase-wc-navbar__nav-item--mega";const n=this.createNavToggleButton(e,t),s=document.createElement("div");s.className="designbase-wc-navbar__mega";const i=document.createElement("div");i.className="designbase-wc-navbar__mega-inner";const r=document.createElement("div");return r.className="designbase-wc-navbar__mega-columns",r.style.setProperty("--db-navbar-mega-columns",String(e.columns.length)),e.columns.forEach(e=>{const a=document.createElement("div");if(a.className="designbase-wc-navbar__mega-column",e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-column-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-navbar__mega-list",e.items.forEach(e=>{const a=document.createElement("li");a.append(this.createMegaLink(e,t)),n.append(a)}),a.append(n),r.append(a)}),i.append(r),e.featured&&i.append(this.createMegaFeatured(e.featured,t)),s.append(i),a.append(n,s),a}createMegaFeatured(a,n){const s=document.createElement("a");s.href=t(a.href,"#"),s.className="designbase-wc-navbar__mega-featured",a.image&&(s.style.setProperty("--db-navbar-mega-featured-image",`url("${a.image}")`),s.classList.add("designbase-wc-navbar__mega-featured--image"));const i=resolveIcon(a.icon);if(i){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-icon",t.append(e(i,n+4)),s.append(t)}if(a.title){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-featured-title",e.textContent=a.title,s.append(e)}if(a.description){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-featured-desc",e.textContent=a.description,s.append(e)}if(a.ctaLabel){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-cta",t.append(document.createTextNode(a.ctaLabel)),t.append(e("chevron-right",14)),s.append(t)}return s.addEventListener("click",e=>{e.preventDefault(),this.dispatchItemClick({id:`${a.href||"featured"}`,label:a.title||"featured",href:a.href},"nav")}),s}createDesktopNavItem(a,n){if(this.isMegaMenu(a))return this.createMegaMenu(a,n);const s=document.createElement("li");s.className="designbase-wc-navbar__nav-item";if(Boolean(a.children?.length)){const i=document.createElement("div");i.className="designbase-wc-navbar__dropdown";const r=document.createElement("button");r.type="button",r.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",a.active&&"designbase-wc-navbar__nav-link--active",a.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),r.disabled=Boolean(a.disabled);const c=resolveIcon(a.icon);c&&r.append(e(c,n)),r.append(document.createTextNode(a.label));const d=e("chevron-down",12);d.classList.add("designbase-wc-navbar__chevron"),r.append(d);const l=document.createElement("ul");return l.className="designbase-wc-navbar__dropdown-menu",a.children.forEach(a=>{const s=document.createElement("li"),i=document.createElement("a");i.href=t(a.href,"#"),i.className=["designbase-wc-navbar__dropdown-item",a.active&&"designbase-wc-navbar__dropdown-item--active",a.disabled&&"designbase-wc-navbar__dropdown-item--disabled"].filter(Boolean).join(" ");const r=resolveIcon(a.icon);r&&i.append(e(r,n)),i.append(document.createTextNode(a.label)),i.addEventListener("click",e=>{a.disabled?e.preventDefault():(e.preventDefault(),this.dispatchItemClick(a,"nav"))}),s.append(i),l.append(s)}),i.append(r,l),s.append(i),s}const i=document.createElement("a");i.href=t(a.href,"#"),i.className=["designbase-wc-navbar__nav-link",a.active&&"designbase-wc-navbar__nav-link--active",a.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" ");const r=resolveIcon(a.icon);return r&&i.append(e(r,n)),i.append(document.createTextNode(a.label)),i.addEventListener("click",e=>{a.disabled?e.preventDefault():(e.preventDefault(),this.dispatchItemClick(a,"nav"))}),s.append(i),s}createUserMenuItemElement(e,a,n){const s=document.createElement("db-menu-item");s.setAttribute("label",e.label),s.setAttribute("type","block"),s.setAttribute("menu-style","dropdown"),s.setAttribute("size",a);const i=t(e.href,"");return i&&s.setAttribute("href",i),e.icon&&s.setAttribute("icon",e.icon),e.disabled&&s.setAttribute("disabled",""),s.addEventListener("db-click",()=>{e.disabled||(n(),this.dispatchItemClick(e,"user"))}),s}bindSearchEvents(e){e.addEventListener("db-search",e=>{const t=e.detail,a=t.query??t.value??"";this.dispatchEvent(new CustomEvent("db-search",{bubbles:!0,composed:!0,detail:{query:a,value:a}}))})}applyAvatarProfile(e,t,a){e.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),e.setAttribute("initials",t.name),e.setAttribute("alt",t.name),t.avatar&&e.setAttribute("src",t.avatar),void 0!==t.badge&&e.setAttribute("badge",String(t.badge)),t.badgeVariant&&e.setAttribute("badge-variant",t.badgeVariant),t.badgeType&&e.setAttribute("badge-type",t.badgeType),t.badgeText&&e.setAttribute("badge-text",t.badgeText)}getMobileChildren(e){if(this.isMegaMenu(e)){const t=(e.columns||[]).flatMap(e=>e.items);return e.featured?.href&&t.push({id:`${e.id}-featured`,label:e.featured.title||e.featured.ctaLabel||e.label,href:e.featured.href,icon:e.featured.icon}),t}return e.children||[]}createMobileMenuItem(e,a){const n=this.getMobileChildren(e),s=n.length>0,i=Boolean(this.expandedMobile[e.id]),r=document.createElement("db-menu-item");r.setAttribute("label",e.label),r.setAttribute("type","block"),r.setAttribute("menu-style","accordion"),r.setAttribute("size",a);const c=t(e.href,"");return c&&r.setAttribute("href",c),e.icon&&r.setAttribute("icon",e.icon),e.active&&r.setAttribute("active",""),e.disabled&&r.setAttribute("disabled",""),s&&(r.setAttribute("expandable",""),r.subItems=n.map(e=>({id:e.id,label:e.label,href:e.href,icon:e.icon,active:e.active,disabled:e.disabled})),i&&r.setAttribute("expanded","")),r.addEventListener("db-click",()=>{e.disabled||(s?this.expandedMobile[e.id]=r.hasAttribute("expanded"):(this.mobileOpen=!1,this.dispatchItemClick(e,"mobile"),this.render()))}),r.addEventListener("db-child-click",e=>{const t=e.detail;this.mobileOpen=!1,this.dispatchItemClick(t.child,"mobile"),this.render()}),r}updateUserMenuVisibility(){const e=this.querySelector(".designbase-wc-navbar__user-dropdown-menu");e&&(e.hidden=!this.userMenuOpen)}renderMobileMenu(){const e=this.querySelector(".designbase-wc-navbar__mobile-nav-list");if(!e)return;const t=this.getAttribute("size")||"m",a=this.parseItems();e.replaceChildren(...a.map(e=>this.createMobileMenuItem(e,t)))}render(){this.syncHostClasses(),this.setAttribute("role","navigation"),this.setAttribute("aria-label","메인 네비게이션");const t=this.getAttribute("size")||"m",a=this.iconSize(t),n=this.parseItems(),s=this.parseItems("user-menu-items"),i=this.parseUserProfile(),r=this.hasAttribute("is-authenticated"),c=this.hasAttribute("show-search");this.replaceChildren();const d=document.createElement("div");d.className=["designbase-wc-navbar__container",this.hasAttribute("full-width")&&"designbase-wc-navbar__container--full-width"].filter(Boolean).join(" ");const l=document.createElement("div");l.className="designbase-wc-navbar__left";const o=document.createElement("div");o.className="designbase-wc-navbar__brand";const b=document.createElement("div");b.className="designbase-wc-navbar__logo";const u=document.createElement("db-logo"),m=this.getAttribute("logo-src");u.setAttribute("type",m?"custom":"designbase"),m&&u.setAttribute("src",m),u.setAttribute("alt",this.getAttribute("logo-alt")||"홈"),u.setAttribute("size","s"),u.setAttribute("clickable",""),u.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),b.append(u),o.append(b),l.append(o);const p=document.createElement("div");p.className="designbase-wc-navbar__right";const h=document.createElement("div");h.className="designbase-wc-navbar__nav designbase-wc-navbar__nav--desktop";const v=document.createElement("ul");if(v.className="designbase-wc-navbar__nav-list",n.forEach(e=>v.append(this.createDesktopNavItem(e,a))),h.append(v),p.append(h),c){const e=document.createElement("div");e.className="designbase-wc-navbar__search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"===t?"s":"l"===t?"l":"m"),a.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(a),e.append(a),p.append(e)}const g=document.createElement("div");if(g.className="designbase-wc-navbar__user-menu",r&&i){const a=document.createElement("div");a.className="designbase-wc-navbar__user-dropdown";const n=document.createElement("button");n.type="button",n.className="designbase-wc-navbar__user-toggle",n.setAttribute("aria-expanded",String(this.userMenuOpen));const r=document.createElement("db-avatar");this.applyAvatarProfile(r,i,t);const c=document.createElement("span");c.className="designbase-wc-navbar__user-name",c.textContent=i.name,n.append(r,c,e("chevron-down",12)),n.addEventListener("click",()=>{this.userMenuOpen=!this.userMenuOpen,n.setAttribute("aria-expanded",String(this.userMenuOpen)),this.updateUserMenuVisibility()});const d=document.createElement("ul");if(d.className="designbase-wc-navbar__user-dropdown-menu",d.hidden=!this.userMenuOpen,i.email){const e=document.createElement("li");e.className="designbase-wc-navbar__user-info";const t=document.createElement("span");t.className="designbase-wc-navbar__user-email",t.textContent=i.email,e.append(t),d.append(e)}s.forEach(e=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(e,t,()=>{this.userMenuOpen=!1,this.updateUserMenuVisibility()})),d.append(a)}),a.append(n,d),g.append(a)}else{const e=document.createElement("db-button");e.setAttribute("variant","primary"),e.setAttribute("size","s"===t?"s":"l"===t?"l":"m"),e.textContent="로그인",e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),g.append(e)}p.append(g);const _=document.createElement("button");_.type="button",_.className="designbase-wc-navbar__mobile-toggle",_.setAttribute("aria-expanded",String(this.mobileOpen)),this.mobileOpen&&_.setAttribute("aria-controls",this.mobileMenuId),_.setAttribute("aria-label",this.mobileOpen?"메뉴 닫기":"메뉴 열기");for(let e=0;e<3;e+=1){const e=document.createElement("span");e.className="designbase-wc-navbar__mobile-toggle-line",_.append(e)}if(_.addEventListener("click",()=>{this.mobileOpen=!this.mobileOpen,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus()}),d.append(l,p,_),this.append(d),this.mobileOpen){const e=document.createElement("div");if(e.className="designbase-wc-navbar__mobile-menu",e.id=this.mobileMenuId,e.addEventListener("keydown",e=>{"Escape"===e.key&&(this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())}),c){const t=document.createElement("div");t.className="designbase-wc-navbar__mobile-search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"),a.setAttribute("full-width",""),a.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(a),t.append(a),e.append(t)}const t=document.createElement("div");t.className="designbase-wc-navbar__mobile-nav-list",e.append(t);const a=document.createElement("div");if(a.className="designbase-wc-navbar__mobile-user",r&&i){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-info";const t=document.createElement("db-avatar");this.applyAvatarProfile(t,i,"m");const n=document.createElement("div"),r=document.createElement("div");if(r.className="designbase-wc-navbar__mobile-user-name",r.textContent=i.name,n.append(r),i.email){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-email",e.textContent=i.email,n.append(e)}if(e.append(t,n),a.append(e),s.length){const e=document.createElement("ul");e.className="designbase-wc-navbar__mobile-user-menu",s.forEach(t=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(t,"m",()=>{this.mobileOpen=!1,this.render()})),e.append(a)}),a.append(e)}}else{const e=document.createElement("db-button");e.setAttribute("variant","primary"),e.setAttribute("size","m"),e.setAttribute("full-width",""),e.textContent="로그인",e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),a.append(e)}e.append(a),this.append(e),this.renderMobileMenu()}}}DbNavbar.nextId=0,customElements.get("db-navbar")||customElements.define("db-navbar",DbNavbar);export{DbNavbar};
1
+ import{dbText as e}from"../core/i18n.js";import{createDbIcon as t}from"./db-icons.js";import{sanitizeHref as a}from"../core/safe-url.js";import{NAVBAR_SIZES as n,NAVBAR_VARIANTS as s,NAVBAR_POSITIONS as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";function resolveIcon(e){if(e)return e}class DbNavbar extends HTMLElement{constructor(){super(...arguments),this.mobileMenuId="db-navbar-menu-"+ ++DbNavbar.nextId,this.mobileOpen=!1,this.userMenuOpen=!1,this.expandedMobile={},this.outsideHandler=null}static get observedAttributes(){return["logo-src","logo-alt","items","user-menu-items","user-profile","size","variant","position","is-authenticated","show-search","search-placeholder","full-width","shadow"]}connectedCallback(){this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick()}attributeChangedCallback(){this.isConnected&&this.render()}get items(){return this.parseItems("items")}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseItems("user-menu-items")}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}parseItems(e="items"){try{const t=JSON.parse(this.getAttribute(e)||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}iconSize(e){return"s"===e?16:"l"===e?24:20}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{this.contains(e.target)||(this.userMenuOpen=!1,this.updateUserMenuVisibility())},document.addEventListener("mousedown",this.outsideHandler))}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}dispatchItemClick(e,t){this.dispatchEvent(new CustomEvent("user"===t?"db-user-menu-item-click":"db-item-click",{bubbles:!0,composed:!0,detail:{item:e,source:t}}))}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",a=this.getAttribute("position")||"static";this.className=["designbase-wc-navbar",`designbase-wc-navbar--${n.includes(e)?e:"m"}`,`designbase-wc-navbar--${s.includes(t)?t:"default"}`,`designbase-wc-navbar--${i.includes(a)?a:"static"}`,this.hasAttribute("full-width")&&"designbase-wc-navbar--full-width",this.hasAttribute("shadow")&&"designbase-wc-navbar--shadow",this.mobileOpen&&"designbase-wc-navbar--mobile-open"].filter(Boolean).join(" ")}isMegaMenu(e){return Boolean(e.megaMenu&&e.columns?.length)}createNavToggleButton(e,a){const n=document.createElement("button");n.type="button",n.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),n.disabled=Boolean(e.disabled);const s=resolveIcon(e.icon);s&&n.append(t(s,a)),n.append(document.createTextNode(e.label));const i=t("chevron-down",12);return i.classList.add("designbase-wc-navbar__chevron"),n.append(i),n}createMegaLink(e,n){const s=document.createElement("a");s.href=a(e.href,"#"),s.className=["designbase-wc-navbar__mega-link",e.active&&"designbase-wc-navbar__mega-link--active",e.disabled&&"designbase-wc-navbar__mega-link--disabled"].filter(Boolean).join(" ");const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-link-icon",e.append(t(i,n)),s.append(e)}const r=document.createElement("span");r.className="designbase-wc-navbar__mega-link-body";const c=document.createElement("span");if(c.className="designbase-wc-navbar__mega-link-label",c.textContent=e.label,r.append(c),e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-link-desc",t.textContent=e.description,r.append(t)}return s.append(r),s.addEventListener("click",t=>{t.preventDefault(),e.disabled||this.dispatchItemClick(e,"nav")}),s}createMegaMenu(e,t){const a=document.createElement("li");a.className="designbase-wc-navbar__nav-item designbase-wc-navbar__nav-item--mega";const n=this.createNavToggleButton(e,t),s=document.createElement("div");s.className="designbase-wc-navbar__mega";const i=document.createElement("div");i.className="designbase-wc-navbar__mega-inner";const r=document.createElement("div");return r.className="designbase-wc-navbar__mega-columns",r.style.setProperty("--db-navbar-mega-columns",String(e.columns.length)),e.columns.forEach(e=>{const a=document.createElement("div");if(a.className="designbase-wc-navbar__mega-column",e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-column-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-navbar__mega-list",e.items.forEach(e=>{const a=document.createElement("li");a.append(this.createMegaLink(e,t)),n.append(a)}),a.append(n),r.append(a)}),i.append(r),e.featured&&i.append(this.createMegaFeatured(e.featured,t)),s.append(i),a.append(n,s),a}createMegaFeatured(e,n){const s=document.createElement("a");s.href=a(e.href,"#"),s.className="designbase-wc-navbar__mega-featured",e.image&&(s.style.setProperty("--db-navbar-mega-featured-image",`url("${e.image}")`),s.classList.add("designbase-wc-navbar__mega-featured--image"));const i=resolveIcon(e.icon);if(i){const e=document.createElement("span");e.className="designbase-wc-navbar__mega-featured-icon",e.append(t(i,n+4)),s.append(e)}if(e.title){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-title",t.textContent=e.title,s.append(t)}if(e.description){const t=document.createElement("span");t.className="designbase-wc-navbar__mega-featured-desc",t.textContent=e.description,s.append(t)}if(e.ctaLabel){const a=document.createElement("span");a.className="designbase-wc-navbar__mega-featured-cta",a.append(document.createTextNode(e.ctaLabel)),a.append(t("chevron-right",14)),s.append(a)}return s.addEventListener("click",t=>{t.preventDefault(),this.dispatchItemClick({id:`${e.href||"featured"}`,label:e.title||"featured",href:e.href},"nav")}),s}createDesktopNavItem(e,n){if(this.isMegaMenu(e))return this.createMegaMenu(e,n);const s=document.createElement("li");s.className="designbase-wc-navbar__nav-item";if(Boolean(e.children?.length)){const i=document.createElement("div");i.className="designbase-wc-navbar__dropdown";const r=document.createElement("button");r.type="button",r.className=["designbase-wc-navbar__nav-link","designbase-wc-navbar__nav-link--has-children",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" "),r.disabled=Boolean(e.disabled);const c=resolveIcon(e.icon);c&&r.append(t(c,n)),r.append(document.createTextNode(e.label));const d=t("chevron-down",12);d.classList.add("designbase-wc-navbar__chevron"),r.append(d);const l=document.createElement("ul");return l.className="designbase-wc-navbar__dropdown-menu",e.children.forEach(e=>{const s=document.createElement("li"),i=document.createElement("a");i.href=a(e.href,"#"),i.className=["designbase-wc-navbar__dropdown-item",e.active&&"designbase-wc-navbar__dropdown-item--active",e.disabled&&"designbase-wc-navbar__dropdown-item--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);r&&i.append(t(r,n)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),s.append(i),l.append(s)}),i.append(r,l),s.append(i),s}const i=document.createElement("a");i.href=a(e.href,"#"),i.className=["designbase-wc-navbar__nav-link",e.active&&"designbase-wc-navbar__nav-link--active",e.disabled&&"designbase-wc-navbar__nav-link--disabled"].filter(Boolean).join(" ");const r=resolveIcon(e.icon);return r&&i.append(t(r,n)),i.append(document.createTextNode(e.label)),i.addEventListener("click",t=>{e.disabled?t.preventDefault():(t.preventDefault(),this.dispatchItemClick(e,"nav"))}),s.append(i),s}createUserMenuItemElement(e,t,n){const s=document.createElement("db-menu-item");s.setAttribute("label",e.label),s.setAttribute("type","block"),s.setAttribute("menu-style","dropdown"),s.setAttribute("size",t);const i=a(e.href,"");return i&&s.setAttribute("href",i),e.icon&&s.setAttribute("icon",e.icon),e.disabled&&s.setAttribute("disabled",""),s.addEventListener("db-click",()=>{e.disabled||(n(),this.dispatchItemClick(e,"user"))}),s}bindSearchEvents(e){e.addEventListener("db-search",e=>{const t=e.detail,a=t.query??t.value??"";this.dispatchEvent(new CustomEvent("db-search",{bubbles:!0,composed:!0,detail:{query:a,value:a}}))})}applyAvatarProfile(e,t,a){e.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),e.setAttribute("initials",t.name),e.setAttribute("alt",t.name),t.avatar&&e.setAttribute("src",t.avatar),void 0!==t.badge&&e.setAttribute("badge",String(t.badge)),t.badgeVariant&&e.setAttribute("badge-variant",t.badgeVariant),t.badgeType&&e.setAttribute("badge-type",t.badgeType),t.badgeText&&e.setAttribute("badge-text",t.badgeText)}getMobileChildren(e){if(this.isMegaMenu(e)){const t=(e.columns||[]).flatMap(e=>e.items);return e.featured?.href&&t.push({id:`${e.id}-featured`,label:e.featured.title||e.featured.ctaLabel||e.label,href:e.featured.href,icon:e.featured.icon}),t}return e.children||[]}createMobileMenuItem(e,t){const n=this.getMobileChildren(e),s=n.length>0,i=Boolean(this.expandedMobile[e.id]),r=document.createElement("db-menu-item");r.setAttribute("label",e.label),r.setAttribute("type","block"),r.setAttribute("menu-style","accordion"),r.setAttribute("size",t);const c=a(e.href,"");return c&&r.setAttribute("href",c),e.icon&&r.setAttribute("icon",e.icon),e.active&&r.setAttribute("active",""),e.disabled&&r.setAttribute("disabled",""),s&&(r.setAttribute("expandable",""),r.subItems=n.map(e=>({id:e.id,label:e.label,href:e.href,icon:e.icon,active:e.active,disabled:e.disabled})),i&&r.setAttribute("expanded","")),r.addEventListener("db-click",()=>{e.disabled||(s?this.expandedMobile[e.id]=r.hasAttribute("expanded"):(this.mobileOpen=!1,this.dispatchItemClick(e,"mobile"),this.render()))}),r.addEventListener("db-child-click",e=>{const t=e.detail;this.mobileOpen=!1,this.dispatchItemClick(t.child,"mobile"),this.render()}),r}updateUserMenuVisibility(){const e=this.querySelector(".designbase-wc-navbar__user-dropdown-menu");e&&(e.hidden=!this.userMenuOpen)}renderMobileMenu(){const e=this.querySelector(".designbase-wc-navbar__mobile-nav-list");if(!e)return;const t=this.getAttribute("size")||"m",a=this.parseItems();e.replaceChildren(...a.map(e=>this.createMobileMenuItem(e,t)))}render(){this.syncHostClasses(),this.setAttribute("role","navigation"),this.setAttribute("aria-label",e("메인 네비게이션"));const a=this.getAttribute("size")||"m",n=this.iconSize(a),s=this.parseItems(),i=this.parseItems("user-menu-items"),r=this.parseUserProfile(),c=this.hasAttribute("is-authenticated"),d=this.hasAttribute("show-search");this.replaceChildren();const l=document.createElement("div");l.className=["designbase-wc-navbar__container",this.hasAttribute("full-width")&&"designbase-wc-navbar__container--full-width"].filter(Boolean).join(" ");const o=document.createElement("div");o.className="designbase-wc-navbar__left";const b=document.createElement("div");b.className="designbase-wc-navbar__brand";const u=document.createElement("div");u.className="designbase-wc-navbar__logo";const m=document.createElement("db-logo"),p=this.getAttribute("logo-src");m.setAttribute("type",p?"custom":"designbase"),p&&m.setAttribute("src",p),m.setAttribute("alt",this.getAttribute("logo-alt")||"홈"),m.setAttribute("size","s"),m.setAttribute("clickable",""),m.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),u.append(m),b.append(u),o.append(b);const h=document.createElement("div");h.className="designbase-wc-navbar__right";const v=document.createElement("div");v.className="designbase-wc-navbar__nav designbase-wc-navbar__nav--desktop";const g=document.createElement("ul");if(g.className="designbase-wc-navbar__nav-list",s.forEach(e=>g.append(this.createDesktopNavItem(e,n))),v.append(g),h.append(v),d){const e=document.createElement("div");e.className="designbase-wc-navbar__search";const t=document.createElement("db-search-bar");t.setAttribute("variant","outlined"),t.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),t.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(t),e.append(t),h.append(e)}const _=document.createElement("div");if(_.className="designbase-wc-navbar__user-menu",c&&r){const e=document.createElement("div");e.className="designbase-wc-navbar__user-dropdown";const n=document.createElement("button");n.type="button",n.className="designbase-wc-navbar__user-toggle",n.setAttribute("aria-expanded",String(this.userMenuOpen));const s=document.createElement("db-avatar");this.applyAvatarProfile(s,r,a);const c=document.createElement("span");c.className="designbase-wc-navbar__user-name",c.textContent=r.name,n.append(s,c,t("chevron-down",12)),n.addEventListener("click",()=>{this.userMenuOpen=!this.userMenuOpen,n.setAttribute("aria-expanded",String(this.userMenuOpen)),this.updateUserMenuVisibility()});const d=document.createElement("ul");if(d.className="designbase-wc-navbar__user-dropdown-menu",d.hidden=!this.userMenuOpen,r.email){const e=document.createElement("li");e.className="designbase-wc-navbar__user-info";const t=document.createElement("span");t.className="designbase-wc-navbar__user-email",t.textContent=r.email,e.append(t),d.append(e)}i.forEach(e=>{const t=document.createElement("li");t.append(this.createUserMenuItemElement(e,a,()=>{this.userMenuOpen=!1,this.updateUserMenuVisibility()})),d.append(t)}),e.append(n,d),_.append(e)}else{const t=document.createElement("db-button");t.setAttribute("variant","primary"),t.setAttribute("size","s"===a?"s":"l"===a?"l":"m"),t.textContent=e("로그인"),t.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),_.append(t)}h.append(_);const f=document.createElement("button");f.type="button",f.className="designbase-wc-navbar__mobile-toggle",f.setAttribute("aria-expanded",String(this.mobileOpen)),this.mobileOpen&&f.setAttribute("aria-controls",this.mobileMenuId),f.setAttribute("aria-label",this.mobileOpen?"메뉴 닫기":"메뉴 열기");for(let e=0;e<3;e+=1){const e=document.createElement("span");e.className="designbase-wc-navbar__mobile-toggle-line",f.append(e)}if(f.addEventListener("click",()=>{this.mobileOpen=!this.mobileOpen,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus()}),l.append(o,h,f),this.append(l),this.mobileOpen){const t=document.createElement("div");if(t.className="designbase-wc-navbar__mobile-menu",t.id=this.mobileMenuId,t.addEventListener("keydown",e=>{"Escape"===e.key&&(this.mobileOpen=!1,this.render(),this.querySelector(".designbase-wc-navbar__mobile-toggle")?.focus())}),d){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-search";const a=document.createElement("db-search-bar");a.setAttribute("variant","outlined"),a.setAttribute("size","s"),a.setAttribute("full-width",""),a.setAttribute("placeholder",this.getAttribute("search-placeholder")||"검색..."),this.bindSearchEvents(a),e.append(a),t.append(e)}const a=document.createElement("div");a.className="designbase-wc-navbar__mobile-nav-list",t.append(a);const n=document.createElement("div");if(n.className="designbase-wc-navbar__mobile-user",c&&r){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-info";const t=document.createElement("db-avatar");this.applyAvatarProfile(t,r,"m");const a=document.createElement("div"),s=document.createElement("div");if(s.className="designbase-wc-navbar__mobile-user-name",s.textContent=r.name,a.append(s),r.email){const e=document.createElement("div");e.className="designbase-wc-navbar__mobile-user-email",e.textContent=r.email,a.append(e)}if(e.append(t,a),n.append(e),i.length){const e=document.createElement("ul");e.className="designbase-wc-navbar__mobile-user-menu",i.forEach(t=>{const a=document.createElement("li");a.append(this.createUserMenuItemElement(t,"m",()=>{this.mobileOpen=!1,this.render()})),e.append(a)}),n.append(e)}}else{const t=document.createElement("db-button");t.setAttribute("variant","primary"),t.setAttribute("size","m"),t.setAttribute("full-width",""),t.textContent=e("로그인"),t.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-login-click",{bubbles:!0,composed:!0}))}),n.append(t)}t.append(n),this.append(t),this.renderMobileMenu()}}}DbNavbar.nextId=0,customElements.get("db-navbar")||customElements.define("db-navbar",DbNavbar);export{DbNavbar};
@@ -1 +1 @@
1
- import{DbElement as t}from"../core/base-element.js";import{createDbIcon as e}from"./db-icons.js";import"./db-badge.js";import{nodeStyle as i}from"./node-style.js";const s=["default","compact"],n=["idle","running","success","error"],o=new Set(["any","text","image","number","boolean"]),r={any:"일반",text:"텍스트",image:"이미지",number:"숫자",boolean:"조건"},a={idle:"대기",running:"실행 중",success:"완료",error:"오류"};class DbNode extends t{constructor(){super(...arguments),this.root=this.attachShadow({mode:"open"}),this.inputPorts=[],this.outputPorts=[],this.portsDirty=!0,this.drag=null,this.portDrag=null,this.suppressPortClick=!1}static get observedAttributes(){return["node-id","heading","description","icon","variant","status","selected","collapsed","disabled","movable","runnable","collapsible","inputs","outputs","detail","deletable"]}get inputs(){return this.inputPorts.map(t=>({...t}))}set inputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.inputPorts)&&(this.inputPorts=e,this.portsDirty=!0,this.sync())}get outputs(){return this.outputPorts.map(t=>({...t}))}set outputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.outputPorts)&&(this.outputPorts=e,this.portsDirty=!0,this.sync())}getPortElement(t,e){const i="input"===e?this.inputList:this.outputList;return[...i?.querySelectorAll("button")||[]].find(e=>e.dataset.portId===t)||null}connectedCallback(){this.root.childElementCount||this.build(),this.upgradeProperties(["inputs","outputs"]);for(const t of["inputs","outputs"])this.hasAttribute(t)&&this.readPorts(t);this.sync()}disconnectedCallback(){this.finishDrag("end"),this.cancelPortDrag(),super.disconnectedCallback()}attributeChangedCallback(t){"inputs"!==t&&"outputs"!==t||this.readPorts(t),"disabled"===t&&this.hasAttribute("disabled")&&(this.finishDrag("end"),this.cancelPortDrag()),this.sync()}normalizePorts(t){if(!Array.isArray(t))return[];const e=new Set;return t.filter(t=>t&&"string"==typeof t.id&&t.id&&"string"==typeof t.label&&!e.has(t.id)&&e.add(t.id)).map(t=>({id:t.id,label:t.label,type:o.has(t.type)?t.type:"any",connected:!!t.connected,disabled:!!t.disabled}))}readPorts(t){let e=[];try{e=JSON.parse(this.getAttribute(t)||"[]")}catch{}"inputs"===t?this.inputPorts=this.normalizePorts(e):this.outputPorts=this.normalizePorts(e),this.portsDirty=!0}nodeId(){return this.getAttribute("node-id")||this.id}el(t,e){const i=document.createElement(t);return i.className=e,i}action(t,i){const s=this.el("button","action");return s.type="button",s.setAttribute("aria-label",t),s.title=t,s.append(e(i,16)),s}build(){const t=document.createElement("style");t.textContent=i;const e=this.el("article","frame");e.part.add("frame");const s=this.el("header","header");s.part.add("header"),this.headingButton=this.el("button","heading"),this.headingButton.type="button",this.iconBox=this.el("span","icon"),this.iconBox.setAttribute("aria-hidden","true"),this.titleEl=this.el("span","title"),this.headingButton.append(this.iconBox,this.titleEl),this.statusEl=this.el("span","status"),this.statusEl.setAttribute("role","status"),this.statusBadge=document.createElement("db-badge"),this.statusBadge.setAttribute("size","s"),this.statusBadge.setAttribute("type","outlined"),this.statusEl.append(this.statusBadge);const n=this.el("div","actions"),o=document.createElement("slot");o.name="actions",this.runButton=this.action("노드 실행","play-outline"),this.runButton.classList.add("action--run"),this.collapseButton=this.action("노드 접기","chevron-up"),this.deleteButton=this.action("노드 삭제","close"),this.deleteButton.addEventListener("click",()=>this.dbEmit("delete",{nodeId:this.nodeId()},{cancelable:!0})),n.append(o,this.runButton,this.collapseButton,this.deleteButton),s.append(this.headingButton,this.statusEl,n),this.descriptionEl=this.el("p","description"),this.inputList=this.el("div","ports ports--input"),this.inputList.part.add("inputs"),this.outputList=this.el("div","ports ports--output"),this.outputList.part.add("outputs"),this.body=this.el("div","body"),this.body.part.add("body"),this.body.append(document.createElement("slot")),this.footer=this.el("footer","footer");const r=document.createElement("slot");r.name="footer",this.footer.append(r);this.root.addEventListener("slotchange",()=>{this.body.hidden=this.hasAttribute("collapsed")||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=this.hasAttribute("collapsed")||!r.assignedNodes({flatten:!0}).length}),e.append(s,this.descriptionEl,this.inputList,this.body,this.outputList,this.footer),this.root.append(t,e);const isEditor=t=>t.composedPath().some(t=>t instanceof HTMLElement&&(t.isContentEditable||t.matches("input, textarea, db-input, db-textarea, db-markdown-editor")));this.addEventListener("selectstart",t=>{isEditor(t)||t.preventDefault()}),this.addEventListener("dragstart",t=>{isEditor(t)||t.preventDefault()}),this.headingButton.addEventListener("click",()=>{this.hasAttribute("disabled")||this.dbEmit("select",{nodeId:this.nodeId()})}),this.collapseButton.addEventListener("click",()=>{const t=!this.hasAttribute("collapsed");this.toggleAttribute("collapsed",t),this.dbEmit("collapse",{nodeId:this.nodeId(),collapsed:t})}),this.runButton.addEventListener("click",()=>this.dbEmit("run",{nodeId:this.nodeId()},{cancelable:!0})),this.headingButton.addEventListener("pointerdown",t=>{this.hasAttribute("movable")&&!this.hasAttribute("disabled")&&0===t.button&&(this.drag={id:t.pointerId,x:t.clientX,y:t.clientY,lastX:t.clientX,lastY:t.clientY},this.headingButton.setPointerCapture(t.pointerId),this.emitMove("start",0,0))}),this.headingButton.addEventListener("pointermove",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.emitMove("move",t.clientX-this.drag.x,t.clientY-this.drag.y))}),this.headingButton.addEventListener("pointerup",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.finishDrag("end"))}),this.headingButton.addEventListener("pointercancel",()=>this.finishDrag("end")),this.headingButton.addEventListener("lostpointercapture",()=>this.finishDrag("end")),this.headingButton.addEventListener("keydown",t=>{if("Escape"===t.key&&this.drag)return void this.finishDrag("cancel");if(!this.hasAttribute("movable")||this.hasAttribute("disabled"))return;const e={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};if(e[t.key]){t.preventDefault();const[i,s]=e[t.key],n=t.shiftKey?4:16;this.emitMove("keyboard",i*n,s*n)}})}emitMove(t,e,i){this.dbEmit("move",{nodeId:this.nodeId(),deltaX:e,deltaY:i,phase:t})}finishDrag(t){const e=this.drag;e&&(this.drag=null,this.emitMove(t,"cancel"===t?0:e.lastX-e.x,"cancel"===t?0:e.lastY-e.y),this.headingButton.hasPointerCapture(e.id)&&this.headingButton.releasePointerCapture(e.id))}renderPorts(t,e,i){const s=this.root.activeElement,n=s&&t.contains(s)?s.dataset.portId:void 0;this.cancelPortDrag(),t.replaceChildren(),t.hidden=!e.length;for(const s of e){const e=this.el("div","port-row");e.dataset.type=s.type||"any";const n=this.el("button","port");n.type="button",n.part.add("port"),n.dataset.portId=s.id,n.dataset.direction=i,n.disabled=this.hasAttribute("disabled")||!!s.disabled,n.dataset.connected=String(!!s.connected),n.setAttribute("aria-label",`${"input"===i?"입력":"출력"} · ${s.label} · ${r[s.type||"any"]}`),n.setAttribute("aria-pressed",String(!!s.connected));const o=this.el("span","port-dot");n.append(o);const a=this.el("span","port-label");a.textContent=s.label;const d=this.el("span","port-type");d.textContent=r[s.type||"any"];const h={nodeId:this.nodeId(),portId:s.id,direction:i,type:s.type||"any"};n.addEventListener("click",()=>{this.suppressPortClick||this.dbEmit("port-select",h)}),n.addEventListener("pointerdown",t=>{0!==t.button||n.disabled||(this.portDrag={id:t.pointerId,button:n,port:h,x:t.clientX,y:t.clientY,moved:!1},this.suppressPortClick=!1,n.setPointerCapture(t.pointerId))}),n.addEventListener("pointermove",t=>{const e=this.portDrag;e&&e.id===t.pointerId&&(!e.moved&&Math.hypot(t.clientX-e.x,t.clientY-e.y)>=4&&(e.moved=!0,this.suppressPortClick=!0,this.emitPortDrag("start",e.x,e.y)),e.moved&&this.emitPortDrag("move",t.clientX,t.clientY))}),n.addEventListener("pointerup",t=>{this.portDrag?.id===t.pointerId&&(this.portDrag.moved&&this.emitPortDrag("end",t.clientX,t.clientY),this.portDrag=null,n.hasPointerCapture(t.pointerId)&&n.releasePointerCapture(t.pointerId),setTimeout(()=>{this.suppressPortClick=!1},0))}),n.addEventListener("pointercancel",()=>this.cancelPortDrag()),n.addEventListener("lostpointercapture",()=>this.cancelPortDrag()),n.addEventListener("keydown",t=>{"Escape"===t.key&&this.cancelPortDrag()}),e.append(n,a,d),t.append(e)}n&&this.getPortElement(n,i)?.focus({preventScroll:!0})}emitPortDrag(t,e,i){this.portDrag&&this.dbEmit("port-drag",{...this.portDrag.port,phase:t,clientX:e,clientY:i})}cancelPortDrag(){const t=this.portDrag;t&&(t.moved&&this.emitPortDrag("cancel",t.x,t.y),this.portDrag=null,t.button.hasPointerCapture(t.id)&&t.button.releasePointerCapture(t.id))}sync(){if(!this.headingButton)return;const t=this.hasAttribute("disabled"),i=this.hasAttribute("collapsed");this.setAttribute("aria-disabled",String(t)),this.root.querySelector(".frame").inert=t,this.dataset.variant=s.includes(this.getAttribute("variant"))?this.getAttribute("variant"):"default";const o=n.find(t=>t===this.getAttribute("status"))||"idle";this.dataset.status=o,this.titleEl.textContent=this.getAttribute("heading")||"새 노드",this.headingButton.disabled=t,this.headingButton.setAttribute("aria-pressed",String(this.hasAttribute("selected"))),this.headingButton.title=this.hasAttribute("movable")?"드래그 또는 방향키로 이동":"노드 선택";const r=this.getAttribute("icon");if(this.iconBox.hidden=!r,r?this.iconBox.replaceChildren(e(r,16)):this.iconBox.replaceChildren(),this.descriptionEl.textContent=this.getAttribute("description")||"",this.descriptionEl.hidden=i||!this.descriptionEl.textContent,this.statusBadge.textContent=a[o],this.statusBadge.setAttribute("variant","error"===o?"danger":"success"===o?"success":"info"),this.statusEl.hidden="idle"===o,this.collapseButton.hidden=!this.hasAttribute("collapsible"),this.collapseButton.disabled=t,this.collapseButton.setAttribute("aria-expanded",String(!i)),this.collapseButton.setAttribute("aria-label",i?"노드 펼치기":"노드 접기"),this.collapseButton.title=i?"노드 펼치기":"노드 접기",this.collapseButton.replaceChildren(e(i?"chevron-down":"chevron-up",16)),this.deleteButton.hidden=!this.hasAttribute("deletable"),this.deleteButton.disabled=t,this.runButton.hidden=!this.hasAttribute("runnable"),this.runButton.disabled=t||"running"===o,this.body.hidden=i||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=i||!this.footer.querySelector("slot").assignedNodes({flatten:!0}).length,this.portsDirty)this.renderPorts(this.inputList,this.inputPorts,"input"),this.renderPorts(this.outputList,this.outputPorts,"output"),this.portsDirty=!1;else for(const e of[this.inputList,this.outputList])for(const i of e.querySelectorAll("button")){const s=e===this.inputList?this.inputPorts:this.outputPorts;i.disabled=t||!!s.find(t=>t.id===i.dataset.portId)?.disabled}}}customElements.get("db-node")||customElements.define("db-node",DbNode);export{DbNode,n as NODE_STATUSES,s as NODE_VARIANTS};
1
+ import{dbFormat as t,dbText as e}from"../core/i18n.js";import{DbElement as i}from"../core/base-element.js";import{createDbIcon as s}from"./db-icons.js";import"./db-badge.js";import{nodeStyle as n}from"./node-style.js";const o=["default","compact"],r=["idle","running","success","error"],a=new Set(["any","text","image","number","boolean"]),typeLabels=()=>({any:e("일반"),text:e("텍스트"),image:e("이미지"),number:e("숫자"),boolean:e("조건")}),d={idle:"대기",running:"실행 중",success:"완료",error:"오류"};class DbNode extends i{constructor(){super(...arguments),this.root=this.attachShadow({mode:"open"}),this.inputPorts=[],this.outputPorts=[],this.portsDirty=!0,this.drag=null,this.portDrag=null,this.suppressPortClick=!1}static get observedAttributes(){return["node-id","heading","description","icon","variant","status","selected","collapsed","disabled","movable","runnable","collapsible","inputs","outputs","detail","deletable"]}get inputs(){return this.inputPorts.map(t=>({...t}))}set inputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.inputPorts)&&(this.inputPorts=e,this.portsDirty=!0,this.sync())}get outputs(){return this.outputPorts.map(t=>({...t}))}set outputs(t){const e=this.normalizePorts(t);JSON.stringify(e)!==JSON.stringify(this.outputPorts)&&(this.outputPorts=e,this.portsDirty=!0,this.sync())}getPortElement(t,e){const i="input"===e?this.inputList:this.outputList;return[...i?.querySelectorAll("button")||[]].find(e=>e.dataset.portId===t)||null}connectedCallback(){this.root.childElementCount||this.build(),this.upgradeProperties(["inputs","outputs"]);for(const t of["inputs","outputs"])this.hasAttribute(t)&&this.readPorts(t);this.sync()}disconnectedCallback(){this.finishDrag("end"),this.cancelPortDrag(),super.disconnectedCallback()}attributeChangedCallback(t){"inputs"!==t&&"outputs"!==t||this.readPorts(t),"disabled"===t&&this.hasAttribute("disabled")&&(this.finishDrag("end"),this.cancelPortDrag()),this.sync()}normalizePorts(t){if(!Array.isArray(t))return[];const e=new Set;return t.filter(t=>t&&"string"==typeof t.id&&t.id&&"string"==typeof t.label&&!e.has(t.id)&&e.add(t.id)).map(t=>({id:t.id,label:t.label,type:a.has(t.type)?t.type:"any",connected:!!t.connected,disabled:!!t.disabled}))}readPorts(t){let e=[];try{e=JSON.parse(this.getAttribute(t)||"[]")}catch{}"inputs"===t?this.inputPorts=this.normalizePorts(e):this.outputPorts=this.normalizePorts(e),this.portsDirty=!0}nodeId(){return this.getAttribute("node-id")||this.id}el(t,e){const i=document.createElement(t);return i.className=e,i}action(t,e){const i=this.el("button","action");return i.type="button",i.setAttribute("aria-label",t),i.title=t,i.append(s(e,16)),i}build(){const t=document.createElement("style");t.textContent=n;const e=this.el("article","frame");e.part.add("frame");const i=this.el("header","header");i.part.add("header"),this.headingButton=this.el("button","heading"),this.headingButton.type="button",this.iconBox=this.el("span","icon"),this.iconBox.setAttribute("aria-hidden","true"),this.titleEl=this.el("span","title"),this.headingButton.append(this.iconBox,this.titleEl),this.statusEl=this.el("span","status"),this.statusEl.setAttribute("role","status"),this.statusBadge=document.createElement("db-badge"),this.statusBadge.setAttribute("size","s"),this.statusBadge.setAttribute("type","outlined"),this.statusEl.append(this.statusBadge);const s=this.el("div","actions"),o=document.createElement("slot");o.name="actions",this.runButton=this.action("노드 실행","play-outline"),this.runButton.classList.add("action--run"),this.collapseButton=this.action("노드 접기","chevron-up"),this.deleteButton=this.action("노드 삭제","close"),this.deleteButton.addEventListener("click",()=>this.dbEmit("delete",{nodeId:this.nodeId()},{cancelable:!0})),s.append(o,this.runButton,this.collapseButton,this.deleteButton),i.append(this.headingButton,this.statusEl,s),this.descriptionEl=this.el("p","description"),this.inputList=this.el("div","ports ports--input"),this.inputList.part.add("inputs"),this.outputList=this.el("div","ports ports--output"),this.outputList.part.add("outputs"),this.body=this.el("div","body"),this.body.part.add("body"),this.body.append(document.createElement("slot")),this.footer=this.el("footer","footer");const r=document.createElement("slot");r.name="footer",this.footer.append(r);this.root.addEventListener("slotchange",()=>{this.body.hidden=this.hasAttribute("collapsed")||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=this.hasAttribute("collapsed")||!r.assignedNodes({flatten:!0}).length}),e.append(i,this.descriptionEl,this.inputList,this.body,this.outputList,this.footer),this.root.append(t,e);const isEditor=t=>t.composedPath().some(t=>t instanceof HTMLElement&&(t.isContentEditable||t.matches("input, textarea, db-input, db-textarea, db-markdown-editor")));this.addEventListener("selectstart",t=>{isEditor(t)||t.preventDefault()}),this.addEventListener("dragstart",t=>{isEditor(t)||t.preventDefault()}),this.headingButton.addEventListener("click",()=>{this.hasAttribute("disabled")||this.dbEmit("select",{nodeId:this.nodeId()})}),this.collapseButton.addEventListener("click",()=>{const t=!this.hasAttribute("collapsed");this.toggleAttribute("collapsed",t),this.dbEmit("collapse",{nodeId:this.nodeId(),collapsed:t})}),this.runButton.addEventListener("click",()=>this.dbEmit("run",{nodeId:this.nodeId()},{cancelable:!0})),this.headingButton.addEventListener("pointerdown",t=>{this.hasAttribute("movable")&&!this.hasAttribute("disabled")&&0===t.button&&(this.drag={id:t.pointerId,x:t.clientX,y:t.clientY,lastX:t.clientX,lastY:t.clientY},this.headingButton.setPointerCapture(t.pointerId),this.emitMove("start",0,0))}),this.headingButton.addEventListener("pointermove",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.emitMove("move",t.clientX-this.drag.x,t.clientY-this.drag.y))}),this.headingButton.addEventListener("pointerup",t=>{this.drag?.id===t.pointerId&&(this.drag.lastX=t.clientX,this.drag.lastY=t.clientY,this.finishDrag("end"))}),this.headingButton.addEventListener("pointercancel",()=>this.finishDrag("end")),this.headingButton.addEventListener("lostpointercapture",()=>this.finishDrag("end")),this.headingButton.addEventListener("keydown",t=>{if("Escape"===t.key&&this.drag)return void this.finishDrag("cancel");if(!this.hasAttribute("movable")||this.hasAttribute("disabled"))return;const e={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]};if(e[t.key]){t.preventDefault();const[i,s]=e[t.key],n=t.shiftKey?4:16;this.emitMove("keyboard",i*n,s*n)}})}emitMove(t,e,i){this.dbEmit("move",{nodeId:this.nodeId(),deltaX:e,deltaY:i,phase:t})}finishDrag(t){const e=this.drag;e&&(this.drag=null,this.emitMove(t,"cancel"===t?0:e.lastX-e.x,"cancel"===t?0:e.lastY-e.y),this.headingButton.hasPointerCapture(e.id)&&this.headingButton.releasePointerCapture(e.id))}renderPorts(i,s,n){const o=this.root.activeElement,r=o&&i.contains(o)?o.dataset.portId:void 0;this.cancelPortDrag(),i.replaceChildren(),i.hidden=!s.length;for(const o of s){const s=this.el("div","port-row");s.dataset.type=o.type||"any";const r=this.el("button","port");r.type="button",r.part.add("port"),r.dataset.portId=o.id,r.dataset.direction=n,r.disabled=this.hasAttribute("disabled")||!!o.disabled,r.dataset.connected=String(!!o.connected),r.setAttribute("aria-label",t("{0} · {1} · {2}",[e("input"===n?"입력":"출력"),o.label,typeLabels()[o.type||"any"]])),r.setAttribute("aria-pressed",String(!!o.connected));const a=this.el("span","port-dot");r.append(a);const d=this.el("span","port-label");d.textContent=o.label;const h=this.el("span","port-type");h.textContent=typeLabels()[o.type||"any"];const l={nodeId:this.nodeId(),portId:o.id,direction:n,type:o.type||"any"};r.addEventListener("click",()=>{this.suppressPortClick||this.dbEmit("port-select",l)}),r.addEventListener("pointerdown",t=>{0!==t.button||r.disabled||(this.portDrag={id:t.pointerId,button:r,port:l,x:t.clientX,y:t.clientY,moved:!1},this.suppressPortClick=!1,r.setPointerCapture(t.pointerId))}),r.addEventListener("pointermove",t=>{const e=this.portDrag;e&&e.id===t.pointerId&&(!e.moved&&Math.hypot(t.clientX-e.x,t.clientY-e.y)>=4&&(e.moved=!0,this.suppressPortClick=!0,this.emitPortDrag("start",e.x,e.y)),e.moved&&this.emitPortDrag("move",t.clientX,t.clientY))}),r.addEventListener("pointerup",t=>{this.portDrag?.id===t.pointerId&&(this.portDrag.moved&&this.emitPortDrag("end",t.clientX,t.clientY),this.portDrag=null,r.hasPointerCapture(t.pointerId)&&r.releasePointerCapture(t.pointerId),setTimeout(()=>{this.suppressPortClick=!1},0))}),r.addEventListener("pointercancel",()=>this.cancelPortDrag()),r.addEventListener("lostpointercapture",()=>this.cancelPortDrag()),r.addEventListener("keydown",t=>{"Escape"===t.key&&this.cancelPortDrag()}),s.append(r,d,h),i.append(s)}r&&this.getPortElement(r,n)?.focus({preventScroll:!0})}emitPortDrag(t,e,i){this.portDrag&&this.dbEmit("port-drag",{...this.portDrag.port,phase:t,clientX:e,clientY:i})}cancelPortDrag(){const t=this.portDrag;t&&(t.moved&&this.emitPortDrag("cancel",t.x,t.y),this.portDrag=null,t.button.hasPointerCapture(t.id)&&t.button.releasePointerCapture(t.id))}sync(){if(!this.headingButton)return;const t=this.hasAttribute("disabled"),e=this.hasAttribute("collapsed");this.setAttribute("aria-disabled",String(t)),this.root.querySelector(".frame").inert=t,this.dataset.variant=o.includes(this.getAttribute("variant"))?this.getAttribute("variant"):"default";const i=r.find(t=>t===this.getAttribute("status"))||"idle";this.dataset.status=i,this.titleEl.textContent=this.getAttribute("heading")||"새 노드",this.headingButton.disabled=t,this.headingButton.setAttribute("aria-pressed",String(this.hasAttribute("selected"))),this.headingButton.title=this.hasAttribute("movable")?"드래그 또는 방향키로 이동":"노드 선택";const n=this.getAttribute("icon");if(this.iconBox.hidden=!n,n?this.iconBox.replaceChildren(s(n,16)):this.iconBox.replaceChildren(),this.descriptionEl.textContent=this.getAttribute("description")||"",this.descriptionEl.hidden=e||!this.descriptionEl.textContent,this.statusBadge.textContent=d[i],this.statusBadge.setAttribute("variant","error"===i?"danger":"success"===i?"success":"info"),this.statusEl.hidden="idle"===i,this.collapseButton.hidden=!this.hasAttribute("collapsible"),this.collapseButton.disabled=t,this.collapseButton.setAttribute("aria-expanded",String(!e)),this.collapseButton.setAttribute("aria-label",e?"노드 펼치기":"노드 접기"),this.collapseButton.title=e?"노드 펼치기":"노드 접기",this.collapseButton.replaceChildren(s(e?"chevron-down":"chevron-up",16)),this.deleteButton.hidden=!this.hasAttribute("deletable"),this.deleteButton.disabled=t,this.runButton.hidden=!this.hasAttribute("runnable"),this.runButton.disabled=t||"running"===i,this.body.hidden=e||!this.body.querySelector("slot").assignedNodes({flatten:!0}).some(t=>1===t.nodeType||!!t.textContent?.trim()),this.footer.hidden=e||!this.footer.querySelector("slot").assignedNodes({flatten:!0}).length,this.portsDirty)this.renderPorts(this.inputList,this.inputPorts,"input"),this.renderPorts(this.outputList,this.outputPorts,"output"),this.portsDirty=!1;else for(const e of[this.inputList,this.outputList])for(const i of e.querySelectorAll("button")){const s=e===this.inputList?this.inputPorts:this.outputPorts;i.disabled=t||!!s.find(t=>t.id===i.dataset.portId)?.disabled}}}customElements.get("db-node")||customElements.define("db-node",DbNode);export{DbNode,r as NODE_STATUSES,o as NODE_VARIANTS};
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{createFocusTrap as e}from"../core/focus-trap.js";import{lockScroll as i,unlockScroll as s}from"../core/scroll-lock.js";class DbOnboardingModal extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.internalStep=0,this.keyHandler=null,this.isMounted=!1,this.handlePrev=()=>{this.getCurrentStep()>0&&this.goToStep(this.getCurrentStep()-1)},this.handleNext=()=>{const t=this.getSteps(),e=this.getCurrentStep();e>=t.length-1?this.dispatchEvent(new CustomEvent("db-complete",{bubbles:!0,composed:!0})):this.goToStep(e+1)}}static get observedAttributes(){return["open","steps","current-step","show-close-button","show-indicator","indicator-type","indicator-size"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}get steps(){return this.parseSteps()}set steps(t){const e="string"==typeof t?t:JSON.stringify(t);this.getAttribute("steps")!==e&&this.setAttribute("steps",e)}connectedCallback(){this.style.display="contents",this.syncStepFromAttribute(),this.syncOpenState()}disconnectedCallback(){this.detachKeyHandler(),this.unmount()}attributeChangedCallback(t){this.isConnected&&("open"!==t?("current-step"===t&&this.syncStepFromAttribute(),"steps"!==t?this.isMounted&&this.render():this.isOpenRequested()&&(this.isMounted?this.render():this.syncOpenState())):this.syncOpenState())}isOpenRequested(){return this.open}parseSteps(){const t=this.getAttribute("steps");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}syncStepFromAttribute(){if(!this.hasAttribute("current-step"))return;const t=Number(this.getAttribute("current-step")||0);Number.isFinite(t)&&(this.internalStep=Math.max(0,t))}getSteps(){return this.parseSteps()}getCurrentStep(){const t=this.getSteps();return t.length?Math.min(Math.max(this.internalStep,0),t.length-1):0}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}emitStepChange(t){this.dispatchEvent(new CustomEvent("db-step-change",{bubbles:!0,composed:!0,detail:{step:t}}))}goToStep(t){const e=this.getSteps();if(!e.length)return;const i=Math.min(Math.max(t,0),e.length-1);this.internalStep=i,this.emitStepChange(i),this.render()}attachKeyHandler(){this.keyHandler||(this.keyHandler=t=>{"Escape"!==t.key?"ArrowLeft"===t.key&&this.getCurrentStep()>0?this.handlePrev():"ArrowRight"===t.key&&this.getCurrentStep()<this.getSteps().length-1&&this.handleNext():this.close()},document.addEventListener("keydown",this.keyHandler))}detachKeyHandler(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}syncOpenState(){if(this.isOpenRequested())return this.mount(),void this.attachKeyHandler();this.detachKeyHandler(),this.unmount()}mount(){this.root||(this.root=document.createElement("div"),this.root.className="designbase-wc-onboarding-modal",this.root.setAttribute("role","dialog"),this.root.setAttribute("aria-modal","true"),this.root.tabIndex=-1,this.ensureStructure()),this.root.isConnected||document.body.append(this.root),this.isMounted=!0,this.render(),this.scrollLocked||(i(),this.scrollLocked=!0),this.root&&!this.focusTrap&&(this.focusTrap=e(this.root),requestAnimationFrame(()=>this.focusTrap?.activate()))}unmount(){this.isMounted=!1,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.root?.remove(),this.scrollLocked&&(this.scrollLocked=!1,s())}ensureStructure(){this.root&&(this.contentEl&&this.root.contains(this.contentEl)||(this.overlayEl=void 0,this.contentEl=void 0,this.closeButtonEl=void 0,this.mainEl=void 0,this.imageWrapEl=void 0,this.imageEl=void 0,this.textEl=void 0,this.titleEl=void 0,this.descriptionEl=void 0,this.navigationEl=void 0,this.prevButtonEl=void 0,this.nextButtonEl=void 0,this.indicatorEl=void 0,this.root.replaceChildren(),this.overlayEl=document.createElement("div"),this.overlayEl.className="designbase-wc-onboarding-modal__overlay",this.overlayEl.addEventListener("click",()=>this.close()),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-onboarding-modal__content",this.closeButtonEl=document.createElement("button"),this.closeButtonEl.type="button",this.closeButtonEl.className="designbase-wc-onboarding-modal__close-button",this.closeButtonEl.setAttribute("aria-label","닫기"),this.closeButtonEl.append(t("close",20)),this.closeButtonEl.addEventListener("click",()=>this.close()),this.mainEl=document.createElement("div"),this.mainEl.className="designbase-wc-onboarding-modal__main",this.imageWrapEl=document.createElement("div"),this.imageWrapEl.className="designbase-wc-onboarding-modal__image",this.imageEl=document.createElement("img"),this.imageWrapEl.append(this.imageEl),this.textEl=document.createElement("div"),this.textEl.className="designbase-wc-onboarding-modal__text",this.titleEl=document.createElement("h2"),this.titleEl.id="onboarding-title",this.titleEl.className="designbase-wc-onboarding-modal__title",this.descriptionEl=document.createElement("p"),this.descriptionEl.id="onboarding-description",this.descriptionEl.className="designbase-wc-onboarding-modal__description",this.textEl.append(this.titleEl,this.descriptionEl),this.mainEl.append(this.imageWrapEl,this.textEl),this.navigationEl=document.createElement("div"),this.navigationEl.className="designbase-wc-onboarding-modal__navigation",this.prevButtonEl=document.createElement("db-button"),this.prevButtonEl.setAttribute("variant","secondary"),this.prevButtonEl.setAttribute("size","m"),this.prevButtonEl.setAttribute("start-icon","chevron-left"),this.prevButtonEl.setAttribute("aria-label","이전"),this.prevButtonEl.addEventListener("db-click",this.handlePrev),this.indicatorEl=document.createElement("db-indicator"),this.indicatorEl.addEventListener("db-step-click",t=>{const e=t.detail;this.goToStep(e.index??e.current)}),this.nextButtonEl=document.createElement("db-button"),this.nextButtonEl.setAttribute("variant","primary"),this.nextButtonEl.setAttribute("size","m"),this.nextButtonEl.addEventListener("db-click",this.handleNext),this.navigationEl.append(this.prevButtonEl,this.indicatorEl,this.nextButtonEl),this.contentEl.append(this.closeButtonEl,this.mainEl,this.navigationEl),this.root.append(this.overlayEl,this.contentEl)))}render(){if(!this.root||!this.isMounted)return;this.ensureStructure();const t=this.getSteps(),e=this.getCurrentStep(),i=t[e];if(!i)return;const s=!this.hasAttribute("show-close-button")||"false"!==this.getAttribute("show-close-button"),n=!this.hasAttribute("show-indicator")||"false"!==this.getAttribute("show-indicator"),o=this.getAttribute("indicator-type")||"dots",r=this.getAttribute("indicator-size")||"m",a=0===e,l=e===t.length-1;if(this.root.setAttribute("aria-labelledby","onboarding-title"),this.root.setAttribute("aria-describedby","onboarding-description"),this.closeButtonEl&&(this.closeButtonEl.style.display=s?"":"none"),this.imageWrapEl&&this.imageEl&&(i.image?(this.imageEl.src=i.image,this.imageEl.alt=i.title||"온보딩 이미지",this.imageWrapEl.style.display=""):this.imageWrapEl.style.display="none"),this.titleEl&&(this.titleEl.textContent=i.title||"",this.titleEl.style.display=i.title?"":"none"),this.descriptionEl&&(this.descriptionEl.textContent=i.description||"",this.descriptionEl.style.display=i.description?"":"none"),this.prevButtonEl&&(this.prevButtonEl.textContent="이전",a?this.prevButtonEl.setAttribute("disabled",""):this.prevButtonEl.removeAttribute("disabled")),this.nextButtonEl&&(this.nextButtonEl.textContent=l?"완료":"다음",this.nextButtonEl.setAttribute("aria-label",l?"완료":"다음"),l?this.nextButtonEl.removeAttribute("end-icon"):this.nextButtonEl.setAttribute("end-icon","chevron-right")),this.indicatorEl){const i=n&&t.length>1;this.indicatorEl.style.display=i?"":"none",i&&(this.indicatorEl.setAttribute("total",String(t.length)),this.indicatorEl.setAttribute("current",String(e)),this.indicatorEl.setAttribute("indicator-type",o),this.indicatorEl.setAttribute("size",r),this.indicatorEl.setAttribute("clickable",""))}}}customElements.get("db-onboarding-modal")||customElements.define("db-onboarding-modal",DbOnboardingModal);export{DbOnboardingModal};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as e}from"../core/i18n.js";import{createDbIcon as i}from"./db-icons.js";import{createFocusTrap as s}from"../core/focus-trap.js";import{lockScroll as n,unlockScroll as o}from"../core/scroll-lock.js";class DbOnboardingModal extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.internalStep=0,this.keyHandler=null,this.isMounted=!1,this.handlePrev=()=>{this.getCurrentStep()>0&&this.goToStep(this.getCurrentStep()-1)},this.handleNext=()=>{const t=this.getSteps(),e=this.getCurrentStep();e>=t.length-1?this.dispatchEvent(new CustomEvent("db-complete",{bubbles:!0,composed:!0})):this.goToStep(e+1)}}static get observedAttributes(){return["open","steps","current-step","show-close-button","show-indicator","indicator-type","indicator-size"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}get steps(){return this.parseSteps()}set steps(t){const e="string"==typeof t?t:JSON.stringify(t);this.getAttribute("steps")!==e&&this.setAttribute("steps",e)}connectedCallback(){this.style.display="contents",this.syncStepFromAttribute(),this.syncOpenState()}disconnectedCallback(){this.detachKeyHandler(),this.unmount()}attributeChangedCallback(t){this.isConnected&&("open"!==t?("current-step"===t&&this.syncStepFromAttribute(),"steps"!==t?this.isMounted&&this.render():this.isOpenRequested()&&(this.isMounted?this.render():this.syncOpenState())):this.syncOpenState())}isOpenRequested(){return this.open}parseSteps(){const t=this.getAttribute("steps");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}syncStepFromAttribute(){if(!this.hasAttribute("current-step"))return;const t=Number(this.getAttribute("current-step")||0);Number.isFinite(t)&&(this.internalStep=Math.max(0,t))}getSteps(){return this.parseSteps()}getCurrentStep(){const t=this.getSteps();return t.length?Math.min(Math.max(this.internalStep,0),t.length-1):0}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}emitStepChange(t){this.dispatchEvent(new CustomEvent("db-step-change",{bubbles:!0,composed:!0,detail:{step:t}}))}goToStep(t){const e=this.getSteps();if(!e.length)return;const i=Math.min(Math.max(t,0),e.length-1);this.internalStep=i,this.emitStepChange(i),this.render()}attachKeyHandler(){this.keyHandler||(this.keyHandler=t=>{"Escape"!==t.key?"ArrowLeft"===t.key&&this.getCurrentStep()>0?this.handlePrev():"ArrowRight"===t.key&&this.getCurrentStep()<this.getSteps().length-1&&this.handleNext():this.close()},document.addEventListener("keydown",this.keyHandler))}detachKeyHandler(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}syncOpenState(){if(this.isOpenRequested())return this.mount(),void this.attachKeyHandler();this.detachKeyHandler(),this.unmount()}mount(){this.root||(this.root=document.createElement("div"),this.root.className="designbase-wc-onboarding-modal",this.root.setAttribute("role","dialog"),this.root.setAttribute("aria-modal","true"),this.root.tabIndex=-1,this.ensureStructure()),this.root.isConnected||(t(this,this.root),document.body.append(this.root)),this.isMounted=!0,this.render(),this.scrollLocked||(n(),this.scrollLocked=!0),this.root&&!this.focusTrap&&(this.focusTrap=s(this.root),requestAnimationFrame(()=>this.focusTrap?.activate()))}unmount(){this.isMounted=!1,this.focusTrap?.deactivate(),this.focusTrap=void 0,this.root?.remove(),this.scrollLocked&&(this.scrollLocked=!1,o())}ensureStructure(){this.root&&(this.contentEl&&this.root.contains(this.contentEl)||(this.overlayEl=void 0,this.contentEl=void 0,this.closeButtonEl=void 0,this.mainEl=void 0,this.imageWrapEl=void 0,this.imageEl=void 0,this.textEl=void 0,this.titleEl=void 0,this.descriptionEl=void 0,this.navigationEl=void 0,this.prevButtonEl=void 0,this.nextButtonEl=void 0,this.indicatorEl=void 0,this.root.replaceChildren(),this.overlayEl=document.createElement("div"),this.overlayEl.className="designbase-wc-onboarding-modal__overlay",this.overlayEl.addEventListener("click",()=>this.close()),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-onboarding-modal__content",this.closeButtonEl=document.createElement("button"),this.closeButtonEl.type="button",this.closeButtonEl.className="designbase-wc-onboarding-modal__close-button",this.closeButtonEl.setAttribute("aria-label",e("닫기")),this.closeButtonEl.append(i("close",20)),this.closeButtonEl.addEventListener("click",()=>this.close()),this.mainEl=document.createElement("div"),this.mainEl.className="designbase-wc-onboarding-modal__main",this.imageWrapEl=document.createElement("div"),this.imageWrapEl.className="designbase-wc-onboarding-modal__image",this.imageEl=document.createElement("img"),this.imageWrapEl.append(this.imageEl),this.textEl=document.createElement("div"),this.textEl.className="designbase-wc-onboarding-modal__text",this.titleEl=document.createElement("h2"),this.titleEl.id="onboarding-title",this.titleEl.className="designbase-wc-onboarding-modal__title",this.descriptionEl=document.createElement("p"),this.descriptionEl.id="onboarding-description",this.descriptionEl.className="designbase-wc-onboarding-modal__description",this.textEl.append(this.titleEl,this.descriptionEl),this.mainEl.append(this.imageWrapEl,this.textEl),this.navigationEl=document.createElement("div"),this.navigationEl.className="designbase-wc-onboarding-modal__navigation",this.prevButtonEl=document.createElement("db-button"),this.prevButtonEl.setAttribute("variant","secondary"),this.prevButtonEl.setAttribute("size","m"),this.prevButtonEl.setAttribute("start-icon","chevron-left"),this.prevButtonEl.setAttribute("aria-label",e("이전")),this.prevButtonEl.addEventListener("db-click",this.handlePrev),this.indicatorEl=document.createElement("db-indicator"),this.indicatorEl.addEventListener("db-step-click",t=>{const e=t.detail;this.goToStep(e.index??e.current)}),this.nextButtonEl=document.createElement("db-button"),this.nextButtonEl.setAttribute("variant","primary"),this.nextButtonEl.setAttribute("size","m"),this.nextButtonEl.addEventListener("db-click",this.handleNext),this.navigationEl.append(this.prevButtonEl,this.indicatorEl,this.nextButtonEl),this.contentEl.append(this.closeButtonEl,this.mainEl,this.navigationEl),this.root.append(this.overlayEl,this.contentEl)))}render(){if(!this.root||!this.isMounted)return;this.ensureStructure();const t=this.getSteps(),i=this.getCurrentStep(),s=t[i];if(!s)return;const n=!this.hasAttribute("show-close-button")||"false"!==this.getAttribute("show-close-button"),o=!this.hasAttribute("show-indicator")||"false"!==this.getAttribute("show-indicator"),r=this.getAttribute("indicator-type")||"dots",a=this.getAttribute("indicator-size")||"m",l=0===i,h=i===t.length-1;if(this.root.setAttribute("aria-labelledby","onboarding-title"),this.root.setAttribute("aria-describedby","onboarding-description"),this.closeButtonEl&&(this.closeButtonEl.style.display=n?"":"none"),this.imageWrapEl&&this.imageEl&&(s.image?(this.imageEl.src=s.image,this.imageEl.alt=s.title||"온보딩 이미지",this.imageWrapEl.style.display=""):this.imageWrapEl.style.display="none"),this.titleEl&&(this.titleEl.textContent=s.title||"",this.titleEl.style.display=s.title?"":"none"),this.descriptionEl&&(this.descriptionEl.textContent=s.description||"",this.descriptionEl.style.display=s.description?"":"none"),this.prevButtonEl&&(this.prevButtonEl.textContent=e("이전"),l?this.prevButtonEl.setAttribute("disabled",""):this.prevButtonEl.removeAttribute("disabled")),this.nextButtonEl&&(this.nextButtonEl.textContent=h?"완료":"다음",this.nextButtonEl.setAttribute("aria-label",h?"완료":"다음"),h?this.nextButtonEl.removeAttribute("end-icon"):this.nextButtonEl.setAttribute("end-icon","chevron-right")),this.indicatorEl){const e=o&&t.length>1;this.indicatorEl.style.display=e?"":"none",e&&(this.indicatorEl.setAttribute("total",String(t.length)),this.indicatorEl.setAttribute("current",String(i)),this.indicatorEl.setAttribute("indicator-type",r),this.indicatorEl.setAttribute("size",a),this.indicatorEl.setAttribute("clickable",""))}}}customElements.get("db-onboarding-modal")||customElements.define("db-onboarding-modal",DbOnboardingModal);export{DbOnboardingModal};
@@ -1 +1 @@
1
- import{dbUid as t}from"../core/uid.js";import{coerceToContract as e}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{OTP_INPUT_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 DbOtpInput extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals?.(),this.built=!1,this.digits=[],this.suppressSync=!1,this.initialValue="",this.lastCompleteValue="",this.onDigitFocus=t=>{const e=t.currentTarget;requestAnimationFrame(()=>e.select())},this.onDigitInput=t=>{if(this.suppressSync)return;const e=t.currentTarget,i=Number(e.dataset.index||0),s=e.value.replace(/\D/g,"");if(s.length>1){const t=this.digits.slice(0,i).map(t=>t.value).join("");return void this.applyValue(t+s,Math.min(this.length-1,t.length+s.length))}e.value=s.slice(-1),e.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(e.value));const a=this.digits.map(t=>t.value).join("");this.setAttribute("value",a),this.emit("db-input"),this.emit("db-change"),e.value&&i<this.digits.length-1&&this.focusAt(i+1)},this.onDigitKeydown=t=>{const e=t.currentTarget,i=Number(e.dataset.index||0);if("Backspace"!==t.key)return"ArrowLeft"===t.key?(t.preventDefault(),void this.focusAt(i-1)):"ArrowRight"===t.key?(t.preventDefault(),void this.focusAt(i+1)):void("Delete"===t.key&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change")));if(e.value)e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change");else if(i>0){t.preventDefault(),this.focusAt(i-1);const e=this.digits[i-1];e&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change"))}},this.onPaste=t=>{t.preventDefault();const e=t.clipboardData?.getData("text")||"",i=Number(t.currentTarget.dataset.index||0),s=this.digits.slice(0,i).map(t=>t.value).join("");this.applyValue(s+e,Math.min(this.length-1,s.length+e.replace(/\D/g,"").length))}}static get observedAttributes(){return["length","value","size","disabled","readonly","error","error-message","label","auto-focus","masked","name","required"]}get length(){const t=Number(this.getAttribute("length")||6);return Number.isFinite(t)?Math.min(8,Math.max(4,Math.round(t))):6}set length(t){this.setAttribute("length",String(t))}get value(){return this.digits.map(t=>t.value).join("")||this.getAttribute("value")||""}set value(t){this.setAttribute("value",t)}get size(){return e(this.getAttribute("size"),i,"m")}set size(t){this.setAttribute("size",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t)}connectedCallback(){this.built||(this.initialValue=this.getAttribute("value")||""),this.build(),this.sync(),this.hasAttribute("auto-focus")&&!this.disabled&&requestAnimationFrame(()=>this.focusFirstEmpty())}attributeChangedCallback(t){this.built&&("length"===t&&(this.built=!1,this.build()),this.sync())}focus(){this.disabled||this.focusFirstEmpty()}clear(){this.suppressSync=!0,this.digits.forEach(t=>{t.value=""}),this.suppressSync=!1,this.lastCompleteValue="",this.setValueAttribute(""),this.emit("db-input"),this.emit("db-change"),this.focusFirstEmpty()}formResetCallback(){this.lastCompleteValue="",this.value=this.initialValue}formDisabledCallback(t){this.toggleAttribute("disabled",t)}build(){this.replaceChildren(),this.digits=[];const e=this.length,i="designbase-wc-otp-input",s=this.getAttribute("label");if(s){const t=el("div",`${i}__label`);t.textContent=s,this.append(t)}const a=el("div",`${i}__row`);a.setAttribute("role","group"),a.setAttribute("aria-label",s||"인증 코드");for(let t=0;t<e;t+=1){const e=el("div",`${i}__cell`),s=document.createElement("input");s.className=`${i}__digit`,s.type=this.hasAttribute("masked")?"password":"text",s.inputMode="numeric",s.autocomplete=0===t?"one-time-code":"off",s.maxLength=1,s.pattern="[0-9]*",s.setAttribute("aria-label",`${t+1}번째 자리`),s.dataset.index=String(t),s.addEventListener("input",this.onDigitInput),s.addEventListener("keydown",this.onDigitKeydown),s.addEventListener("paste",this.onPaste),s.addEventListener("focus",this.onDigitFocus),e.append(s),a.append(e),this.digits.push(s)}this.append(a),this.errorEl=el("p",`${i}__error`),this.errorEl.id=`${this.id||t("db-otp")}-error`,this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,this.append(this.errorEl),this.built=!0}sync(){const t="designbase-wc-otp-input",e=this.size,i=this.hasAttribute("error"),s=this.disabled,a=this.readOnly,r=this.getAttribute("error-message")||"";this.className=[t,`${t}--${e}`,i&&`${t}--error`,s&&`${t}--disabled`].filter(Boolean).join(" ");const l=(this.getAttribute("value")||"").replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((e,n)=>{e.value=l[n]||"",e.disabled=s,e.readOnly=a,e.type=this.hasAttribute("masked")?"password":"text",e.classList.toggle(`${t}__digit--filled`,Boolean(e.value)),e.setAttribute("aria-invalid",String(i)),i&&r?e.setAttribute("aria-describedby",this.errorEl?.id||""):e.removeAttribute("aria-describedby")}),this.suppressSync=!1,this.errorEl&&(this.errorEl.textContent=r,this.errorEl.hidden=!i||!r),this.setAttribute("role","group"),this.setAttribute("aria-disabled",String(s)),this.setAttribute("aria-invalid",String(i)),this.syncFormValue(l)}emit(t){const e=this.digits.map(t=>t.value).join("");if(this.setValueAttribute(e),this.dispatchEvent(new CustomEvent(t,{detail:{value:e},bubbles:!0,composed:!0})),"db-change"===t&&e.length===this.length&&/^\d+$/.test(e)){if(e===this.lastCompleteValue)return;this.lastCompleteValue=e,this.dispatchEvent(new CustomEvent("db-complete",{detail:{value:e},bubbles:!0,composed:!0}))}else e.length!==this.length&&(this.lastCompleteValue="")}setValueAttribute(t){this.getAttribute("value")!==t&&this.setAttribute("value",t),this.syncFormValue(t)}syncFormValue(t){this.internals?.setFormValue(t||null),this.internals&&(this.hasAttribute("error")?this.internals.setValidity({customError:!0},this.getAttribute("error-message")||"인증 코드가 올바르지 않습니다.",this.digits[0]):this.hasAttribute("required")&&t.length!==this.length?this.internals.setValidity({valueMissing:!0},"인증 코드를 모두 입력해 주세요.",this.digits.find(t=>!t.value)||this.digits[0]):this.internals.setValidity({}))}focusFirstEmpty(){const t=this.digits.find(t=>!t.value)||this.digits[this.digits.length-1];t?.focus(),t?.select()}focusAt(t){const e=this.digits[Math.max(0,Math.min(this.digits.length-1,t))];e?.focus(),e?.select()}applyValue(t,e){const i=t.replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((t,e)=>{t.value=i[e]||"",t.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(t.value))}),this.suppressSync=!1,this.emit("db-input"),this.emit("db-change"),void 0!==e?this.focusAt(e):i.length<this.length?this.focusAt(i.length):this.focusAt(this.length-1)}}DbOtpInput.formAssociated=!0,customElements.get("db-otp-input")||customElements.define("db-otp-input",DbOtpInput);export{DbOtpInput};
1
+ import{dbFormat as t}from"../core/i18n.js";import{dbUid as e}from"../core/uid.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{OTP_INPUT_SIZES as s}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 DbOtpInput extends HTMLElement{constructor(){super(...arguments),this.internals=this.attachInternals?.(),this.built=!1,this.digits=[],this.suppressSync=!1,this.initialValue="",this.lastCompleteValue="",this.onDigitFocus=t=>{const e=t.currentTarget;requestAnimationFrame(()=>e.select())},this.onDigitInput=t=>{if(this.suppressSync)return;const e=t.currentTarget,i=Number(e.dataset.index||0),s=e.value.replace(/\D/g,"");if(s.length>1){const t=this.digits.slice(0,i).map(t=>t.value).join("");return void this.applyValue(t+s,Math.min(this.length-1,t.length+s.length))}e.value=s.slice(-1),e.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(e.value));const a=this.digits.map(t=>t.value).join("");this.setAttribute("value",a),this.emit("db-input"),this.emit("db-change"),e.value&&i<this.digits.length-1&&this.focusAt(i+1)},this.onDigitKeydown=t=>{const e=t.currentTarget,i=Number(e.dataset.index||0);if("Backspace"!==t.key)return"ArrowLeft"===t.key?(t.preventDefault(),void this.focusAt(i-1)):"ArrowRight"===t.key?(t.preventDefault(),void this.focusAt(i+1)):void("Delete"===t.key&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change")));if(e.value)e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change");else if(i>0){t.preventDefault(),this.focusAt(i-1);const e=this.digits[i-1];e&&(e.value="",e.classList.remove("designbase-wc-otp-input__digit--filled"),this.emit("db-input"),this.emit("db-change"))}},this.onPaste=t=>{t.preventDefault();const e=t.clipboardData?.getData("text")||"",i=Number(t.currentTarget.dataset.index||0),s=this.digits.slice(0,i).map(t=>t.value).join("");this.applyValue(s+e,Math.min(this.length-1,s.length+e.replace(/\D/g,"").length))}}static get observedAttributes(){return["length","value","size","disabled","readonly","error","error-message","label","auto-focus","masked","name","required"]}get length(){const t=Number(this.getAttribute("length")||6);return Number.isFinite(t)?Math.min(8,Math.max(4,Math.round(t))):6}set length(t){this.setAttribute("length",String(t))}get value(){return this.digits.map(t=>t.value).join("")||this.getAttribute("value")||""}set value(t){this.setAttribute("value",t)}get size(){return i(this.getAttribute("size"),s,"m")}set size(t){this.setAttribute("size",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t)}connectedCallback(){this.built||(this.initialValue=this.getAttribute("value")||""),this.build(),this.sync(),this.hasAttribute("auto-focus")&&!this.disabled&&requestAnimationFrame(()=>this.focusFirstEmpty())}attributeChangedCallback(t){this.built&&("length"===t&&(this.built=!1,this.build()),this.sync())}focus(){this.disabled||this.focusFirstEmpty()}clear(){this.suppressSync=!0,this.digits.forEach(t=>{t.value=""}),this.suppressSync=!1,this.lastCompleteValue="",this.setValueAttribute(""),this.emit("db-input"),this.emit("db-change"),this.focusFirstEmpty()}formResetCallback(){this.lastCompleteValue="",this.value=this.initialValue}formDisabledCallback(t){this.toggleAttribute("disabled",t)}build(){this.replaceChildren(),this.digits=[];const i=this.length,s="designbase-wc-otp-input",a=this.getAttribute("label");if(a){const t=el("div",`${s}__label`);t.textContent=a,this.append(t)}const r=el("div",`${s}__row`);r.setAttribute("role","group"),r.setAttribute("aria-label",a||"인증 코드");for(let e=0;e<i;e+=1){const i=el("div",`${s}__cell`),a=document.createElement("input");a.className=`${s}__digit`,a.type=this.hasAttribute("masked")?"password":"text",a.inputMode="numeric",a.autocomplete=0===e?"one-time-code":"off",a.maxLength=1,a.pattern="[0-9]*",a.setAttribute("aria-label",t("{0}번째 자리",[e+1])),a.dataset.index=String(e),a.addEventListener("input",this.onDigitInput),a.addEventListener("keydown",this.onDigitKeydown),a.addEventListener("paste",this.onPaste),a.addEventListener("focus",this.onDigitFocus),i.append(a),r.append(i),this.digits.push(a)}this.append(r),this.errorEl=el("p",`${s}__error`),this.errorEl.id=`${this.id||e("db-otp")}-error`,this.errorEl.setAttribute("role","alert"),this.errorEl.hidden=!0,this.append(this.errorEl),this.built=!0}sync(){const t="designbase-wc-otp-input",e=this.size,i=this.hasAttribute("error"),s=this.disabled,a=this.readOnly,r=this.getAttribute("error-message")||"";this.className=[t,`${t}--${e}`,i&&`${t}--error`,s&&`${t}--disabled`].filter(Boolean).join(" ");const l=(this.getAttribute("value")||"").replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((e,n)=>{e.value=l[n]||"",e.disabled=s,e.readOnly=a,e.type=this.hasAttribute("masked")?"password":"text",e.classList.toggle(`${t}__digit--filled`,Boolean(e.value)),e.setAttribute("aria-invalid",String(i)),i&&r?e.setAttribute("aria-describedby",this.errorEl?.id||""):e.removeAttribute("aria-describedby")}),this.suppressSync=!1,this.errorEl&&(this.errorEl.textContent=r,this.errorEl.hidden=!i||!r),this.setAttribute("role","group"),this.setAttribute("aria-disabled",String(s)),this.setAttribute("aria-invalid",String(i)),this.syncFormValue(l)}emit(t){const e=this.digits.map(t=>t.value).join("");if(this.setValueAttribute(e),this.dispatchEvent(new CustomEvent(t,{detail:{value:e},bubbles:!0,composed:!0})),"db-change"===t&&e.length===this.length&&/^\d+$/.test(e)){if(e===this.lastCompleteValue)return;this.lastCompleteValue=e,this.dispatchEvent(new CustomEvent("db-complete",{detail:{value:e},bubbles:!0,composed:!0}))}else e.length!==this.length&&(this.lastCompleteValue="")}setValueAttribute(t){this.getAttribute("value")!==t&&this.setAttribute("value",t),this.syncFormValue(t)}syncFormValue(t){this.internals?.setFormValue(t||null),this.internals&&(this.hasAttribute("error")?this.internals.setValidity({customError:!0},this.getAttribute("error-message")||"인증 코드가 올바르지 않습니다.",this.digits[0]):this.hasAttribute("required")&&t.length!==this.length?this.internals.setValidity({valueMissing:!0},"인증 코드를 모두 입력해 주세요.",this.digits.find(t=>!t.value)||this.digits[0]):this.internals.setValidity({}))}focusFirstEmpty(){const t=this.digits.find(t=>!t.value)||this.digits[this.digits.length-1];t?.focus(),t?.select()}focusAt(t){const e=this.digits[Math.max(0,Math.min(this.digits.length-1,t))];e?.focus(),e?.select()}applyValue(t,e){const i=t.replace(/\D/g,"").slice(0,this.length);this.suppressSync=!0,this.digits.forEach((t,e)=>{t.value=i[e]||"",t.classList.toggle("designbase-wc-otp-input__digit--filled",Boolean(t.value))}),this.suppressSync=!1,this.emit("db-input"),this.emit("db-change"),void 0!==e?this.focusAt(e):i.length<this.length?this.focusAt(i.length):this.focusAt(this.length-1)}}DbOtpInput.formAssociated=!0,customElements.get("db-otp-input")||customElements.define("db-otp-input",DbOtpInput);export{DbOtpInput};