@designbasekorea/ui-wc 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # 변경 이력
2
+
3
+ ## 0.7.0 - 2026-07-17
4
+
5
+ ### 추가
6
+
7
+ - AI Chat, Chat List, Chat Room, Chat Widget 및 메시지 작성·추천·타이핑 컴포넌트
8
+ - CookieBanner, Signature, DownloadProgress
9
+ - OtpInput, PhoneVerify, EmailVerify, TwoFactor
10
+ - React wrapper와 Web Component 공개 API
11
+
12
+ ### 개선
13
+
14
+ - SectionHero의 showcase·split 레이아웃
15
+ - Testimonial 및 SectionTestimonials 변형과 미디어 처리
16
+ - SectionFaq 아코디언 표현
17
+ - Sidebar 설정 패널 전환과 메뉴·프로필 인터랙션
18
+ - 컴포넌트 갤러리, API 레퍼런스, 검색 키워드 및 다국어 문서
19
+
20
+ ### 수정
21
+
22
+ - 오류 페이지 템플릿의 상태 표현과 반응형 레이아웃
23
+ - Web Component 슬롯·숨김 상태·기본값 동기화
package/README.md CHANGED
@@ -4,6 +4,15 @@ Designbase **Web Components** — Vue 3, Angular, React, vanilla HTML에서 공
4
4
 
5
5
  100여 개의 커스텀 엘리먼트를 제공하며, React 전용 wrapper(`@designbasekorea/ui-wc/react`)도 포함합니다.
6
6
 
7
+ ## v0.7.0 업데이트
8
+
9
+ - AI 채팅·채팅방·채팅 위젯을 위한 Chat 컴포넌트 모음 추가
10
+ - CookieBanner, Signature, DownloadProgress 추가
11
+ - OTP·이메일·전화번호·2단계 인증 컴포넌트 추가
12
+ - SectionHero, Testimonial, SectionTestimonials, SectionFaq 레이아웃과 변형 개선
13
+ - Sidebar 설정 패널 전환과 메뉴·프로필 인터랙션 개선
14
+ - React wrapper, Web Component 속성·이벤트 타입 및 예제 문서 최신화
15
+
7
16
  ## 설치
8
17
 
9
18
  ```bash
@@ -0,0 +1,15 @@
1
+ declare class DbCookieBanner extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ connectedCallback(): void;
4
+ attributeChangedCallback(): void;
5
+ private isEnabled;
6
+ private createButton;
7
+ private render;
8
+ }
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ 'db-cookie-banner': DbCookieBanner;
12
+ }
13
+ }
14
+
15
+ export { DbCookieBanner };
@@ -0,0 +1 @@
1
+ class DbCookieBanner extends HTMLElement{static get observedAttributes(){return["title","description","policy-label","policy-href","accept-label","reject-label","settings-label","show-reject","show-settings","fixed","dismissed"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}isEnabled(e,t){const s=this.getAttribute(e);return null===s?t:"false"!==s}createButton(e,t,s,i){const n=document.createElement("db-button");return n.setAttribute("variant",t),n.setAttribute("size","s"),n.textContent=e,n.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0})),i&&(this.setAttribute("dismissed",""),this.render())}),n}render(){if(this.hasAttribute("dismissed"))return this.replaceChildren(),this.className="designbase-wc-cookie-banner designbase-wc-cookie-banner--dismissed",this.style.display="none",void this.removeAttribute("role");this.style.display="";const e=this.getAttribute("title")||"쿠키 사용 안내",t=this.getAttribute("description")||"더 나은 서비스 제공을 위해 쿠키를 사용합니다. 계속 이용하시면 쿠키 사용에 동의하는 것으로 간주됩니다.",s=this.getAttribute("policy-label")||"쿠키 정책",i=this.getAttribute("policy-href")||"",n=this.getAttribute("accept-label")||"모두 허용",a=this.getAttribute("reject-label")||"필수만 허용",c=this.getAttribute("settings-label")||"설정",r=this.isEnabled("show-reject",!0),o=this.isEnabled("show-settings",!1),d=this.isEnabled("fixed",!0);this.className=["designbase-wc-cookie-banner",d&&"designbase-wc-cookie-banner--fixed"].filter(Boolean).join(" "),this.setAttribute("role","dialog"),this.setAttribute("aria-label",e),this.setAttribute("aria-live","polite");const l=document.createElement("div");l.className="designbase-wc-cookie-banner__inner";const b=document.createElement("div");if(b.className="designbase-wc-cookie-banner__copy",e){const t=document.createElement("p");t.className="designbase-wc-cookie-banner__title",t.textContent=e,b.append(t)}const h=document.createElement("p");if(h.className="designbase-wc-cookie-banner__description",h.append(document.createTextNode(t)),i){h.append(document.createTextNode(" "));const e=document.createElement("a");e.className="designbase-wc-cookie-banner__policy",e.href=i,e.target="_blank",e.rel="noopener noreferrer",e.textContent=s,e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-policy",{bubbles:!0,composed:!0}))}),h.append(e)}b.append(h);const p=document.createElement("div");p.className="designbase-wc-cookie-banner__actions",o&&p.append(this.createButton(c,"ghost","db-settings",!1)),r&&p.append(this.createButton(a,"tertiary","db-reject",!0)),p.append(this.createButton(n,"primary","db-accept",!0)),l.append(b,p),this.replaceChildren(l)}}customElements.get("db-cookie-banner")||customElements.define("db-cookie-banner",DbCookieBanner);export{DbCookieBanner};
@@ -1 +1 @@
1
- import{applySectionBlockHeader as t}from"./section-block-header-utils.js";import{syncMarketingBlockHost as e}from"./marketing-block-host-utils.js";const i="designbase-wc-section-faq";class DbSectionFaq extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["headline","subtitle","description","badge","items","allow-multiple","align","content-padding","size","full-width","full-height","overflow-visible"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}parseItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseBadge(){try{const t=this.getAttribute("badge");return t?JSON.parse(t):null}catch{return null}}build(){this.innerEl=document.createElement("div"),this.innerEl.className=`${i}__inner`,this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-section-block-header",this.headerEl.innerHTML='\n <db-badge class="designbase-wc-section-block-header__badge" hidden></db-badge>\n <h2 class="designbase-wc-section-block-header__headline"></h2>\n <p class="designbase-wc-section-block-header__subtitle"></p>\n <p class="designbase-wc-section-block-header__description"></p>\n ',this.accordionEl=document.createElement("db-accordion"),this.accordionEl.className=`${i}__accordion`,this.innerEl.append(this.headerEl,this.accordionEl),this.append(this.innerEl)}updateUI(){const s=this.getAttribute("headline")||"자주 묻는 질문",n=this.getAttribute("subtitle")||"",a=this.getAttribute("description")||"",l=this.getAttribute("content-padding")||"l",r=this.getAttribute("align")||"center",c=this.hasAttribute("allow-multiple"),d=this.parseBadge(),o=this.parseItems();if(this.className=[i,`${i}--padding-${l}`].join(" "),e(this,i),this.headerEl&&t(this.headerEl,{headline:s,subtitle:n,description:a,badge:d,align:r}),!this.accordionEl)return;const h=o.map(t=>({id:t.id,title:t.question,content:t.answer,itemType:"question"}));this.accordionEl.setAttribute("items",JSON.stringify(h)),this.accordionEl.setAttribute("variant","separated"),this.accordionEl.setAttribute("size","m"),this.accordionEl.setAttribute("default-item-type","question"),c?(this.accordionEl.setAttribute("allow-multiple",""),this.accordionEl.setAttribute("expand-mode","multiple")):(this.accordionEl.removeAttribute("allow-multiple"),this.accordionEl.setAttribute("expand-mode","single"))}}customElements.get("db-section-faq")||customElements.define("db-section-faq",DbSectionFaq);export{DbSectionFaq};
1
+ import{applySectionBlockHeader as t}from"./section-block-header-utils.js";import{syncMarketingBlockHost as e}from"./marketing-block-host-utils.js";const i="designbase-wc-section-faq";class DbSectionFaq extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["headline","subtitle","description","badge","items","allow-multiple","align","content-padding","size","full-width","full-height","overflow-visible"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}parseItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t:[]}catch{return[]}}parseBadge(){try{const t=this.getAttribute("badge");return t?JSON.parse(t):null}catch{return null}}build(){this.innerEl=document.createElement("div"),this.innerEl.className=`${i}__inner`,this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-section-block-header",this.headerEl.innerHTML='\n <db-badge class="designbase-wc-section-block-header__badge" hidden></db-badge>\n <h2 class="designbase-wc-section-block-header__headline"></h2>\n <p class="designbase-wc-section-block-header__subtitle"></p>\n <p class="designbase-wc-section-block-header__description"></p>\n ',this.accordionEl=document.createElement("db-accordion"),this.accordionEl.className=`${i}__accordion`,this.innerEl.append(this.headerEl,this.accordionEl),this.append(this.innerEl)}updateUI(){const s=this.getAttribute("headline")||"자주 묻는 질문",n=this.getAttribute("subtitle")||"",a=this.getAttribute("description")||"",l=this.getAttribute("content-padding")||"l",r=this.getAttribute("align")||"center",c=this.hasAttribute("allow-multiple"),d=this.parseBadge(),o=this.parseItems();if(this.className=[i,`${i}--padding-${l}`].join(" "),e(this,i),this.headerEl&&t(this.headerEl,{headline:s,subtitle:n,description:a,badge:d,align:r}),!this.accordionEl)return;const h=o.map(t=>({id:t.id,title:t.question,content:t.answer,itemType:"question"}));this.accordionEl.setAttribute("items",JSON.stringify(h)),this.accordionEl.setAttribute("variant","default"),this.accordionEl.setAttribute("size","m"),this.accordionEl.setAttribute("default-item-type","question"),c?(this.accordionEl.setAttribute("allow-multiple",""),this.accordionEl.setAttribute("expand-mode","multiple")):(this.accordionEl.removeAttribute("allow-multiple"),this.accordionEl.setAttribute("expand-mode","single"))}}customElements.get("db-section-faq")||customElements.define("db-section-faq",DbSectionFaq);export{DbSectionFaq};
@@ -13,16 +13,29 @@ declare class DbSectionHero extends HTMLElement {
13
13
  private backgroundVideoEl?;
14
14
  private backgroundImageEl?;
15
15
  private overlayEl?;
16
+ private defaultContainerEl?;
17
+ private splitContainerEl?;
18
+ private stageEl?;
19
+ private floatsEl?;
20
+ private contentEl?;
21
+ private badgeEl?;
16
22
  private titleEl?;
17
23
  private subtitleEl?;
18
24
  private descriptionEl?;
19
25
  private buttonsEl?;
26
+ private visualMainEl?;
27
+ private visualSideEl?;
28
+ private visualTlEl?;
29
+ private visualTrEl?;
20
30
  connectedCallback(): void;
21
31
  attributeChangedCallback(): void;
22
32
  get buttons(): HeroButton[];
23
33
  set buttons(value: HeroButton[] | string);
24
34
  private parseButtons;
35
+ private createContent;
36
+ private createVisual;
25
37
  private build;
38
+ private mountLayout;
26
39
  private updateUI;
27
40
  }
28
41
  declare global {
@@ -1 +1 @@
1
- const t="designbase-wc-section-hero";class DbSectionHero extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["title","subtitle","description","background-image","background-video","overlay-color","overlay-opacity","buttons","variant","theme","alignment","animated","full-height","min-height","max-height","content-max-width"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}get buttons(){return this.parseButtons()}set buttons(t){this.setAttribute("buttons","string"==typeof t?t:JSON.stringify(t))}parseButtons(){try{const t=JSON.parse(this.getAttribute("buttons")||"[]");return Array.isArray(t)?t:[]}catch{return[]}}build(){this.backgroundVideoEl=document.createElement("video"),this.backgroundVideoEl.className=`${t}__background-video`,this.backgroundVideoEl.autoplay=!0,this.backgroundVideoEl.muted=!0,this.backgroundVideoEl.loop=!0,this.backgroundVideoEl.playsInline=!0,this.backgroundVideoEl.hidden=!0,this.backgroundImageEl=document.createElement("div"),this.backgroundImageEl.className=`${t}__background-image`,this.backgroundImageEl.hidden=!0,this.overlayEl=document.createElement("div"),this.overlayEl.className=`${t}__overlay`,this.overlayEl.hidden=!0;const e=document.createElement("div");e.className=`${t}__container`;const i=document.createElement("div");i.className=`${t}__content`,this.titleEl=document.createElement("h1"),this.titleEl.className=`${t}__title`,this.subtitleEl=document.createElement("p"),this.subtitleEl.className=`${t}__subtitle`,this.descriptionEl=document.createElement("p"),this.descriptionEl.className=`${t}__description`,this.buttonsEl=document.createElement("div"),this.buttonsEl.className=`${t}__buttons`,i.append(this.titleEl,this.subtitleEl,this.descriptionEl,this.buttonsEl),e.append(i),this.append(this.backgroundVideoEl,this.backgroundImageEl,this.overlayEl,e)}updateUI(){const e=this.getAttribute("title")||"",i=this.getAttribute("subtitle")||"",s=this.getAttribute("description")||"",n=this.getAttribute("background-image")||"",a=this.getAttribute("background-video")||"",o=this.getAttribute("overlay-color")||"",r=Number(this.getAttribute("overlay-opacity")||.5),l=this.getAttribute("variant")||"default",d=this.getAttribute("theme")||"light",c=this.getAttribute("alignment")||"left",h=this.hasAttribute("animated"),u=this.hasAttribute("full-height"),b=this.getAttribute("min-height"),g=this.getAttribute("max-height"),m=this.getAttribute("content-max-width"),E=this.parseButtons(),p=Boolean(n||a),y="dark"===d||"gradient"===d||p&&("overlay"===l||"image"===d);this.className=[t,`${t}--variant-${l}`,`${t}--theme-${d}`,`${t}--alignment-${c}`,h&&`${t}--animated`,u&&`${t}--full-height`,y&&`${t}--on-media`].filter(Boolean).join(" "),this.style.minHeight=b||"",this.style.maxHeight=g||"",this.titleEl&&(this.titleEl.textContent=e),this.subtitleEl&&(this.subtitleEl.textContent=i,this.subtitleEl.hidden=!i),this.descriptionEl&&(this.descriptionEl.textContent=s,this.descriptionEl.hidden=!s);const k=this.querySelector(`.${t}__content`);if(k&&(m?k.style.maxWidth=/^\d+$/.test(m)?`${m}px`:m:k.style.removeProperty("max-width")),this.backgroundVideoEl)if(a){this.backgroundVideoEl.hidden=!1,this.backgroundVideoEl.replaceChildren();const t=document.createElement("source");t.src=a,t.type="video/mp4",this.backgroundVideoEl.append(t)}else this.backgroundVideoEl.hidden=!0;this.backgroundImageEl&&(n?(this.backgroundImageEl.hidden=!1,this.backgroundImageEl.style.backgroundImage=`url(${n})`,this.backgroundImageEl.style.backgroundSize="cover",this.backgroundImageEl.style.backgroundPosition="center",this.backgroundImageEl.style.backgroundRepeat="no-repeat"):this.backgroundImageEl.hidden=!0),this.overlayEl&&(p?(this.overlayEl.hidden=!1,o?(this.overlayEl.style.background=o,this.overlayEl.style.opacity=String(r)):(this.overlayEl.style.background=`linear-gradient(180deg, rgba(0, 0, 0, ${.35*r}) 0%, rgba(0, 0, 0, ${r}) 100%)`,this.overlayEl.style.opacity="1")):this.overlayEl.hidden=!0),this.buttonsEl&&(this.buttonsEl.replaceChildren(),E.length>0?(E.forEach(e=>{const i=document.createElement("db-button");if(i.setAttribute("variant",function mapButtonVariant(t){return"outline"===t?"tertiary":"ghost"===t?"ghost":"secondary"===t?"secondary":"tertiary"===t?"tertiary":"primary"}(e.variant)),i.setAttribute("size",e.size||"m"),e.href&&i.setAttribute("href",e.href),e.external&&(i.setAttribute("target","_blank"),i.setAttribute("rel","noopener noreferrer")),e.startIcon)i.setAttribute("start-icon",e.startIcon),i.textContent=e.text;else if(e.icon){const s=document.createElement("span");s.className=`${t}__button-content`;const n=document.createElement("span");n.className=`${t}__button-icon`,n.setAttribute("aria-hidden","true"),n.textContent=e.icon;const a=document.createElement("span");a.textContent=e.text,s.append(n,a),i.append(s)}else i.textContent=e.text;i.addEventListener("click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-button-click",{detail:{button:e},bubbles:!0,composed:!0}))}),this.buttonsEl.append(i)}),this.buttonsEl.hidden=!1):this.buttonsEl.hidden=!0)}}customElements.get("db-section-hero")||customElements.define("db-section-hero",DbSectionHero);export{DbSectionHero};
1
+ const t="designbase-wc-section-hero";function fillVisualSlot(e,i,s,l){if(e.replaceChildren(),i){const l=document.createElement("img");return l.className=`${t}__visual-image`,l.src=i,l.alt=s,void e.append(l)}const a=document.createElement("div");a.className=`${t}__visual-placeholder`,a.setAttribute("aria-hidden","true"),a.textContent=l,e.append(a)}class DbSectionHero extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["title","subtitle","description","badge","background-image","background-video","overlay-color","overlay-opacity","buttons","variant","theme","alignment","visual-image","visual-alt","visual-top-left","visual-top-right","animated","full-height","min-height","max-height","content-max-width"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}get buttons(){return this.parseButtons()}set buttons(t){this.setAttribute("buttons","string"==typeof t?t:JSON.stringify(t))}parseButtons(){try{const t=JSON.parse(this.getAttribute("buttons")||"[]");return Array.isArray(t)?t:[]}catch{return[]}}createContent(){return this.contentEl=document.createElement("div"),this.contentEl.className=`${t}__content`,this.badgeEl=document.createElement("p"),this.badgeEl.className=`${t}__badge`,this.badgeEl.hidden=!0,this.titleEl=document.createElement("h1"),this.titleEl.className=`${t}__title`,this.subtitleEl=document.createElement("p"),this.subtitleEl.className=`${t}__subtitle`,this.descriptionEl=document.createElement("p"),this.descriptionEl.className=`${t}__description`,this.buttonsEl=document.createElement("div"),this.buttonsEl.className=`${t}__buttons`,this.contentEl.append(this.badgeEl,this.titleEl,this.subtitleEl,this.descriptionEl,this.buttonsEl),this.contentEl}createVisual(e){const i=document.createElement("div");return i.className=`${t}__visual ${e}`,i}build(){this.backgroundVideoEl=document.createElement("video"),this.backgroundVideoEl.className=`${t}__background-video`,this.backgroundVideoEl.autoplay=!0,this.backgroundVideoEl.muted=!0,this.backgroundVideoEl.loop=!0,this.backgroundVideoEl.playsInline=!0,this.backgroundVideoEl.hidden=!0,this.backgroundImageEl=document.createElement("div"),this.backgroundImageEl.className=`${t}__background-image`,this.backgroundImageEl.hidden=!0,this.overlayEl=document.createElement("div"),this.overlayEl.className=`${t}__overlay`,this.overlayEl.hidden=!0,this.createContent(),this.defaultContainerEl=document.createElement("div"),this.defaultContainerEl.className=`${t}__container`,this.splitContainerEl=document.createElement("div"),this.splitContainerEl.className=`${t}__container ${t}__container--split`,this.splitContainerEl.hidden=!0,this.stageEl=document.createElement("div"),this.stageEl.className=`${t}__stage`,this.stageEl.hidden=!0,this.floatsEl=document.createElement("div"),this.floatsEl.className=`${t}__floats`,this.visualTlEl=this.createVisual(`${t}__visual--float ${t}__visual--tl`),this.visualTrEl=this.createVisual(`${t}__visual--float ${t}__visual--tr`),this.floatsEl.append(this.visualTlEl,this.visualTrEl),this.visualMainEl=this.createVisual(`${t}__visual--main`),this.visualSideEl=this.createVisual(`${t}__visual--side`),this.defaultContainerEl.append(this.contentEl),this.append(this.backgroundVideoEl,this.backgroundImageEl,this.overlayEl,this.defaultContainerEl,this.splitContainerEl,this.stageEl)}mountLayout(e){if(this.contentEl&&this.defaultContainerEl&&this.splitContainerEl&&this.stageEl){if(this.defaultContainerEl.hidden=!0,this.splitContainerEl.hidden=!0,this.stageEl.hidden=!0,"showcase"===e){this.stageEl.hidden=!1;const e=document.createElement("div");return e.className=`${t}__cluster`,e.append(this.floatsEl,this.contentEl),void this.stageEl.replaceChildren(e,this.visualMainEl)}if("split"===e)return this.splitContainerEl.hidden=!1,void this.splitContainerEl.replaceChildren(this.contentEl,this.visualSideEl);this.defaultContainerEl.hidden=!1,this.defaultContainerEl.replaceChildren(this.contentEl)}}updateUI(){const e=this.getAttribute("title")||"",i=this.getAttribute("subtitle")||"",s=this.getAttribute("description")||"",l=this.getAttribute("badge")||"",a=this.getAttribute("background-image")||"",n=this.getAttribute("background-video")||"",o=this.getAttribute("overlay-color")||"",r=Number(this.getAttribute("overlay-opacity")||.5),h=this.getAttribute("variant")||"default",d=this.getAttribute("theme")||"light",u=this.getAttribute("alignment")||"left",c=this.getAttribute("visual-image")||"",E=this.getAttribute("visual-alt")||"",b=this.getAttribute("visual-top-left")||"",g=this.getAttribute("visual-top-right")||"",m=this.hasAttribute("animated"),p=this.hasAttribute("full-height"),v=this.getAttribute("min-height"),_=this.getAttribute("max-height"),y=this.getAttribute("content-max-width"),f=this.parseButtons(),k=Boolean(a||n),$="dark"===d||"gradient"===d||k&&("overlay"===h||"image"===d),C="showcase"===h?"center":"split"===h?"left":u;if(this.className=[t,`${t}--variant-${h}`,`${t}--theme-${d}`,`${t}--alignment-${C}`,m&&`${t}--animated`,p&&`${t}--full-height`,$&&`${t}--on-media`].filter(Boolean).join(" "),this.style.minHeight=v||"",this.style.maxHeight=_||"",this.mountLayout(h),this.badgeEl&&(this.badgeEl.textContent=l,this.badgeEl.hidden=!l),this.titleEl&&(this.titleEl.textContent=e),this.subtitleEl&&(this.subtitleEl.textContent=i,this.subtitleEl.hidden=!i),this.descriptionEl&&(this.descriptionEl.textContent=s,this.descriptionEl.hidden=!s),this.contentEl&&(y?this.contentEl.style.maxWidth=/^\d+$/.test(y)?`${y}px`:y:this.contentEl.style.removeProperty("max-width")),this.backgroundVideoEl)if(n){this.backgroundVideoEl.hidden=!1,this.backgroundVideoEl.replaceChildren();const t=document.createElement("source");t.src=n,t.type="video/mp4",this.backgroundVideoEl.append(t)}else this.backgroundVideoEl.hidden=!0;this.backgroundImageEl&&(a?(this.backgroundImageEl.hidden=!1,this.backgroundImageEl.style.backgroundImage=`url(${a})`,this.backgroundImageEl.style.backgroundSize="cover",this.backgroundImageEl.style.backgroundPosition="center",this.backgroundImageEl.style.backgroundRepeat="no-repeat"):this.backgroundImageEl.hidden=!0),this.overlayEl&&(k?(this.overlayEl.hidden=!1,o?(this.overlayEl.style.background=o,this.overlayEl.style.opacity=String(r)):(this.overlayEl.style.background=`linear-gradient(180deg, rgba(0, 0, 0, ${.35*r}) 0%, rgba(0, 0, 0, ${r}) 100%)`,this.overlayEl.style.opacity="1")):this.overlayEl.hidden=!0),"showcase"===h?(this.visualTlEl&&fillVisualSlot(this.visualTlEl,b,"","Visual"),this.visualTrEl&&fillVisualSlot(this.visualTrEl,g,"","Visual"),this.visualMainEl&&fillVisualSlot(this.visualMainEl,c,E,"Hero visual")):"split"===h&&this.visualSideEl&&fillVisualSlot(this.visualSideEl,c,E,"Hero visual"),this.buttonsEl&&(this.buttonsEl.replaceChildren(),f.length>0?(f.forEach(e=>{const i=document.createElement("db-button");if(i.setAttribute("variant",function mapButtonVariant(t){return"outline"===t?"tertiary":"ghost"===t?"ghost":"secondary"===t?"secondary":"tertiary"===t?"tertiary":"primary"}(e.variant)),i.setAttribute("size",e.size||"m"),e.href&&i.setAttribute("href",e.href),e.external&&(i.setAttribute("target","_blank"),i.setAttribute("rel","noopener noreferrer")),e.startIcon)i.setAttribute("start-icon",e.startIcon),i.textContent=e.text;else if(e.icon){const s=document.createElement("span");s.className=`${t}__button-content`;const l=document.createElement("span");l.className=`${t}__button-icon`,l.setAttribute("aria-hidden","true"),l.textContent=e.icon;const a=document.createElement("span");a.textContent=e.text,s.append(l,a),i.append(s)}else i.textContent=e.text;i.addEventListener("click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-button-click",{detail:{button:e},bubbles:!0,composed:!0}))}),this.buttonsEl.append(i)}),this.buttonsEl.hidden=!1):this.buttonsEl.hidden=!0)}}customElements.get("db-section-hero")||customElements.define("db-section-hero",DbSectionHero);export{DbSectionHero};
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{applySectionBlockHeader as t}from"./section-block-header-utils.js";import{syncMarketingBlockHost as s}from"./marketing-block-host-utils.js";const i="designbase-wc-section-testimonials";class DbSectionTestimonials extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.carouselIndex=0}static get observedAttributes(){return["headline","subtitle","description","badge","items","variant","columns","align","content-padding","size","full-width","full-height","overflow-visible"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}disconnectedCallback(){this.resizeObserver?.disconnect(),this.resizeObserver=void 0}attributeChangedCallback(){this.built&&(this.carouselIndex=0,this.updateUI())}parseItems(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBadge(){try{const e=this.getAttribute("badge");return e?JSON.parse(e):null}catch{return null}}buildHeader(e){this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-section-block-header";const t=document.createElement("db-badge");t.className="designbase-wc-section-block-header__badge",t.hidden=!0,t.dataset.role="badge";const s=document.createElement("h2");s.className="designbase-wc-section-block-header__headline",s.dataset.role="headline";const i=document.createElement("p");i.className="designbase-wc-section-block-header__subtitle",i.dataset.role="subtitle";const a=document.createElement("p");a.className="designbase-wc-section-block-header__description",a.dataset.role="description",this.headerEl.append(t,s,i,a),e.append(this.headerEl)}build(){this.innerEl=document.createElement("div"),this.innerEl.className=`${i}__inner`,this.buildHeader(this.innerEl),this.contentEl=document.createElement("div"),this.contentEl.className=`${i}__grid`,this.innerEl.append(this.contentEl),this.append(this.innerEl)}createTestimonialEl(e){const t=document.createElement("db-testimonial");return t.setAttribute("variant","card"),t.setAttribute("quote",e.quote),t.setAttribute("author",e.author),e.role&&t.setAttribute("role",e.role),e.company&&t.setAttribute("company",e.company),e.avatar&&t.setAttribute("avatar",e.avatar),null!=e.rating&&t.setAttribute("rating",String(e.rating)),t.setAttribute("align","center"),t}updateHeader(){this.headerEl&&t(this.headerEl,{headline:this.getAttribute("headline")||"고객 후기",subtitle:this.getAttribute("subtitle")||"",description:this.getAttribute("description")||"",badge:this.parseBadge(),align:this.getAttribute("align")||"center"})}clampCarouselIndex(e){e<=0?this.carouselIndex=0:(this.carouselIndex>=e&&(this.carouselIndex=0),this.carouselIndex<0&&(this.carouselIndex=0))}updateCarouselTransform(){if(!this.carouselViewport||!this.carouselTrack)return;const e=this.carouselViewport.clientWidth;this.carouselTrack.style.transform=`translate3d(-${this.carouselIndex*e}px, 0, 0)`,this.carouselIndicator&&this.carouselIndicator.setAttribute("current",String(this.carouselIndex))}goToCarouselSlide(e,t){t<=0||(this.carouselIndex=Math.max(0,Math.min(e,t-1)),this.updateCarouselTransform())}renderGrid(e){this.contentEl&&(this.resizeObserver?.disconnect(),this.resizeObserver=void 0,this.carouselViewport=void 0,this.carouselTrack=void 0,this.carouselIndicator=void 0,this.contentEl.className=`${i}__grid`,this.contentEl.replaceChildren(),e.forEach(e=>{this.contentEl.append(this.createTestimonialEl(e))}))}renderCarousel(t){if(!this.contentEl)return;if(this.contentEl.replaceChildren(),this.contentEl.className=`${i}__carousel`,this.clampCarouselIndex(t.length),0===t.length)return;const s=document.createElement("div");s.className=`${i}__carousel-viewport`;const a=document.createElement("div");if(a.className=`${i}__carousel-track`,t.forEach(e=>{const t=document.createElement("div");t.className=`${i}__carousel-slide`,t.append(this.createTestimonialEl(e)),a.append(t)}),s.append(a),this.carouselViewport=s,this.carouselTrack=a,t.length>1){const a=document.createElement("button");a.type="button",a.className=`${i}__carousel-nav ${i}__carousel-nav--prev`,a.setAttribute("aria-label","이전 후기"),a.append(e("chevron-left",20)),a.addEventListener("click",()=>{const e=this.carouselIndex-1;this.goToCarouselSlide(e<0?t.length-1:e,t.length)});const r=document.createElement("button");r.type="button",r.className=`${i}__carousel-nav ${i}__carousel-nav--next`,r.setAttribute("aria-label","다음 후기"),r.append(e("chevron-right",20)),r.addEventListener("click",()=>{const e=this.carouselIndex+1;this.goToCarouselSlide(e>=t.length?0:e,t.length)}),s.append(a,r);const n=document.createElement("div");n.className=`${i}__carousel-controls`;const l=document.createElement("db-indicator");l.className=`${i}__carousel-indicator`,l.setAttribute("current",String(this.carouselIndex)),l.setAttribute("total",String(t.length)),l.setAttribute("type","dots"),l.setAttribute("size","s"),l.setAttribute("clickable",""),l.addEventListener("db-step-click",e=>{const s=e;this.goToCarouselSlide(s.detail.index,t.length)}),this.carouselIndicator=l,n.append(l),this.contentEl.append(s,n)}else this.contentEl.append(s);this.resizeObserver?.disconnect(),this.resizeObserver=new ResizeObserver(()=>this.updateCarouselTransform()),this.resizeObserver.observe(s),requestAnimationFrame(()=>this.updateCarouselTransform())}updateUI(){const e=this.getAttribute("variant")||"grid",t=this.getAttribute("columns")||"3",a=this.getAttribute("content-padding")||"l",r=this.parseItems();this.className=[i,`${i}--${e}`,`${i}--cols-${t}`,`${i}--padding-${a}`].join(" "),s(this,i),this.updateHeader(),"carousel"===e?this.renderCarousel(r):this.renderGrid(r)}}customElements.get("db-section-testimonials")||customElements.define("db-section-testimonials",DbSectionTestimonials);export{DbSectionTestimonials};
1
+ import{createDbIcon as e}from"./db-icons.js";import{applySectionBlockHeader as t}from"./section-block-header-utils.js";import{syncMarketingBlockHost as s}from"./marketing-block-host-utils.js";const i="designbase-wc-section-testimonials";class DbSectionTestimonials extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.carouselIndex=0}static get observedAttributes(){return["headline","subtitle","description","badge","items","variant","columns","align","content-padding","size","full-width","full-height","overflow-visible"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}disconnectedCallback(){this.resizeObserver?.disconnect(),this.resizeObserver=void 0}attributeChangedCallback(){this.built&&(this.carouselIndex=0,this.updateUI())}parseItems(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBadge(){try{const e=this.getAttribute("badge");return e?JSON.parse(e):null}catch{return null}}buildHeader(e){this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-section-block-header";const t=document.createElement("db-badge");t.className="designbase-wc-section-block-header__badge",t.hidden=!0,t.dataset.role="badge";const s=document.createElement("h2");s.className="designbase-wc-section-block-header__headline",s.dataset.role="headline";const i=document.createElement("p");i.className="designbase-wc-section-block-header__subtitle",i.dataset.role="subtitle";const a=document.createElement("p");a.className="designbase-wc-section-block-header__description",a.dataset.role="description",this.headerEl.append(t,s,i,a),e.append(this.headerEl)}build(){this.innerEl=document.createElement("div"),this.innerEl.className=`${i}__inner`,this.buildHeader(this.innerEl),this.contentEl=document.createElement("div"),this.contentEl.className=`${i}__grid`,this.innerEl.append(this.contentEl),this.append(this.innerEl)}createTestimonialEl(e){const t=document.createElement("db-testimonial");return t.setAttribute("variant","card"),t.setAttribute("quote",e.quote),t.setAttribute("author",e.author),e.role&&t.setAttribute("role",e.role),e.company&&t.setAttribute("company",e.company),e.avatar&&t.setAttribute("avatar",e.avatar),null!=e.rating&&t.setAttribute("rating",String(e.rating)),t}updateHeader(){this.headerEl&&t(this.headerEl,{headline:this.getAttribute("headline")||"고객 후기",subtitle:this.getAttribute("subtitle")||"",description:this.getAttribute("description")||"",badge:this.parseBadge(),align:this.getAttribute("align")||"center"})}clampCarouselIndex(e){e<=0?this.carouselIndex=0:(this.carouselIndex>=e&&(this.carouselIndex=0),this.carouselIndex<0&&(this.carouselIndex=0))}updateCarouselTransform(){if(!this.carouselViewport||!this.carouselTrack)return;const e=this.carouselViewport.clientWidth;this.carouselTrack.style.transform=`translate3d(-${this.carouselIndex*e}px, 0, 0)`,this.carouselIndicator&&this.carouselIndicator.setAttribute("current",String(this.carouselIndex))}goToCarouselSlide(e,t){t<=0||(this.carouselIndex=Math.max(0,Math.min(e,t-1)),this.updateCarouselTransform())}renderGrid(e){this.contentEl&&(this.resizeObserver?.disconnect(),this.resizeObserver=void 0,this.carouselViewport=void 0,this.carouselTrack=void 0,this.carouselIndicator=void 0,this.contentEl.className=`${i}__grid`,this.contentEl.replaceChildren(),e.forEach(e=>{this.contentEl.append(this.createTestimonialEl(e))}))}renderCarousel(t){if(!this.contentEl)return;if(this.contentEl.replaceChildren(),this.contentEl.className=`${i}__carousel`,this.clampCarouselIndex(t.length),0===t.length)return;const s=document.createElement("div");s.className=`${i}__carousel-viewport`;const a=document.createElement("div");if(a.className=`${i}__carousel-track`,t.forEach(e=>{const t=document.createElement("div");t.className=`${i}__carousel-slide`,t.append(this.createTestimonialEl(e)),a.append(t)}),s.append(a),this.carouselViewport=s,this.carouselTrack=a,t.length>1){const a=document.createElement("button");a.type="button",a.className=`${i}__carousel-nav ${i}__carousel-nav--prev`,a.setAttribute("aria-label","이전 후기"),a.append(e("chevron-left",20)),a.addEventListener("click",()=>{const e=this.carouselIndex-1;this.goToCarouselSlide(e<0?t.length-1:e,t.length)});const r=document.createElement("button");r.type="button",r.className=`${i}__carousel-nav ${i}__carousel-nav--next`,r.setAttribute("aria-label","다음 후기"),r.append(e("chevron-right",20)),r.addEventListener("click",()=>{const e=this.carouselIndex+1;this.goToCarouselSlide(e>=t.length?0:e,t.length)}),s.append(a,r);const n=document.createElement("div");n.className=`${i}__carousel-controls`;const l=document.createElement("db-indicator");l.className=`${i}__carousel-indicator`,l.setAttribute("current",String(this.carouselIndex)),l.setAttribute("total",String(t.length)),l.setAttribute("type","dots"),l.setAttribute("size","s"),l.setAttribute("clickable",""),l.addEventListener("db-step-click",e=>{const s=e;this.goToCarouselSlide(s.detail.index,t.length)}),this.carouselIndicator=l,n.append(l),this.contentEl.append(s,n)}else this.contentEl.append(s);this.resizeObserver?.disconnect(),this.resizeObserver=new ResizeObserver(()=>this.updateCarouselTransform()),this.resizeObserver.observe(s),requestAnimationFrame(()=>this.updateCarouselTransform())}updateUI(){const e=this.getAttribute("variant")||"grid",t=this.getAttribute("columns")||"3",a=this.getAttribute("content-padding")||"l",r=this.parseItems();this.className=[i,`${i}--${e}`,`${i}--cols-${t}`,`${i}--padding-${a}`].join(" "),s(this,i),this.updateHeader(),"carousel"===e?this.renderCarousel(r):this.renderGrid(r)}}customElements.get("db-section-testimonials")||customElements.define("db-section-testimonials",DbSectionTestimonials);export{DbSectionTestimonials};
@@ -13,6 +13,8 @@ interface DbSidebarItem {
13
13
  selected?: boolean;
14
14
  /** 프로필 메뉴에서 이 항목 앞에 구분선을 표시합니다. */
15
15
  dividerBefore?: boolean;
16
+ /** 클릭 시 이동할 사이드바 패널 id (예: settings) */
17
+ openPanel?: string;
16
18
  children?: DbSidebarItem[];
17
19
  }
18
20
  interface DbSidebarSection {
@@ -93,6 +95,12 @@ declare class DbSidebar extends HTMLElement {
93
95
  set backLabel(value: string);
94
96
  get backHref(): string;
95
97
  set backHref(value: string);
98
+ get settingsSections(): DbSidebarSection[];
99
+ set settingsSections(value: DbSidebarSection[] | string);
100
+ get activePanel(): string;
101
+ set activePanel(value: string);
102
+ private parseSettingsSections;
103
+ private hasSettingsPanel;
96
104
  private parseSections;
97
105
  private parseUserMenuItems;
98
106
  private parseUserProfile;
@@ -112,6 +120,8 @@ declare class DbSidebar extends HTMLElement {
112
120
  private setUserFlyout;
113
121
  private scheduleUserFlyoutClose;
114
122
  private syncHostClasses;
123
+ private syncActivePanelTrack;
124
+ private navigateToPanel;
115
125
  private dispatchItemClick;
116
126
  private dispatchUserMenuItemClick;
117
127
  private dispatchBackClick;
@@ -129,6 +139,8 @@ declare class DbSidebar extends HTMLElement {
129
139
  private renderBottomNav;
130
140
  private createUserDropdown;
131
141
  private createPromoBanner;
142
+ private createHeader;
143
+ private createNavWrapper;
132
144
  private render;
133
145
  }
134
146
  declare global {
@@ -1 +1 @@
1
- import{createDbIcon as e,isDbIconName as t}from"./db-icons.js";const s=["s","m","l"],i=["default","dark","light"],r=["left","right"];class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.flyoutCloseTimer=null,this.userFlyoutCloseTimer=null,this.outsideHandler=null}static get observedAttributes(){return["items","sections","user-menu-items","user-profile","default-expanded-ids","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","header-type","back-label","back-href","size","variant","position","collapsed","collapsible","show-logo","full-height","shadow"]}connectedCallback(){this.seedExpanded(),this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick(),this.cancelFlyoutClose(),this.cancelUserFlyoutClose()}attributeChangedCallback(e){this.isConnected&&("default-expanded-ids"===e&&this.seedExpanded(),"collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.cancelFlyoutClose(),this.cancelUserFlyoutClose()),this.render())}seedExpanded(){try{const e=JSON.parse(this.getAttribute("default-expanded-ids")||"[]");Array.isArray(e)&&(this.expandedItems=new Set(e))}catch{this.expandedItems=new Set}}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||"프로젝트 관리"}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||"프로젝트"}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||"프로젝트를 추가해 주세요"}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||"프로젝트 추가"}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}get headerType(){return"back"===this.getAttribute("header-type")?"back":"default"}set headerType(e){this.setAttribute("header-type",e)}get backLabel(){return this.getAttribute("back-label")||"뒤로가기"}set backLabel(e){this.setAttribute("back-label",e)}get backHref(){return this.getAttribute("back-href")||""}set backHref(e){e?this.setAttribute("back-href",e):this.removeAttribute("back-href")}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,this.userFlyoutItemId=null,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.classList.remove("designbase-wc-sidebar--user-menu-open"),this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncExclusiveAccordion(e){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(t=>{const s=t.getAttribute("data-item-id");s&&(e&&s===e?t.setAttribute("expanded",""):t.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}cancelUserFlyoutClose(){this.userFlyoutCloseTimer&&(clearTimeout(this.userFlyoutCloseTimer),this.userFlyoutCloseTimer=null)}setUserFlyout(e){this.cancelUserFlyoutClose(),this.userFlyoutItemId=e,this.querySelectorAll(".designbase-wc-sidebar__user-menu-item").forEach(t=>{const s=Boolean(e&&t.dataset.itemId===e);t.classList.toggle("designbase-wc-sidebar__user-menu-item--flyout-active",s),t.querySelector(".designbase-wc-sidebar__user-menu-trigger")?.setAttribute("aria-expanded",String(s));const i=t.querySelector(".designbase-wc-sidebar__user-flyout");i&&(i.hidden=!s)})}scheduleUserFlyoutClose(){this.cancelUserFlyoutClose(),this.userFlyoutCloseTimer=setTimeout(()=>{this.userFlyoutCloseTimer=null,this.setUserFlyout(null)},120)}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",a=this.getAttribute("position")||"left";this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--${s.includes(e)?e:"m"}`,`designbase-wc-sidebar--${i.includes(t)?t:"default"}`,`designbase-wc-sidebar--${r.includes(a)?a:"left"}`,this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow",this.userMenuOpen&&"designbase-wc-sidebar--user-menu-open","back"===this.headerType&&"designbase-wc-sidebar--header-back"].filter(Boolean).join(" ")}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchBackClick(){const e=new CustomEvent("db-back-click",{bubbles:!0,composed:!0,cancelable:!0,detail:{label:this.backLabel,href:this.backHref}});this.dispatchEvent(e),!e.defaultPrevented&&this.backHref&&window.location.assign(this.backHref)}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(t="s"){const s=document.createElement("span");return s.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${t}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),s.setAttribute("aria-hidden","true"),s.append(e("plus","m"===t?16:14)),s}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("badge-style","text"),t.textContent=e.badge,t}createProjectSelector(t){if(!this.hasAttribute("projects"))return null;const s=this.parseProjects(),i=0===s.length,r=this.getSelectedProject(),a=document.createElement("div");a.className=["designbase-wc-sidebar__project-selector",t&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",i&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const n=this.getAttribute("project-section-label");if(!t&&n&&n.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=n.trim(),a.append(e)}const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__project-trigger",c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.projectMenuOpen)),i||!r){if(c.setAttribute("aria-label",this.projectEmptyTriggerLabel),c.append(this.createProjectEmptyMark(t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,c.append(e)}}else if(c.setAttribute("aria-label",r.label),c.append(this.createProjectAvatar(r,t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=r.label,c.append(e)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__project-chevron",o.setAttribute("aria-hidden","true"),o.append(e("chevron-down",14)),c.append(o),c.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),a.append(c),this.projectMenuOpen){const t=document.createElement("div");if(t.className="designbase-wc-sidebar__project-dropdown",t.setAttribute("role","menu"),t.setAttribute("aria-label",this.projectSectionLabel),i){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-empty",e.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,e.append(s),t.append(e)}else{const e=document.createElement("ul");e.className="designbase-wc-sidebar__project-list",s.forEach(t=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",r&&t.id===r.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(t,"s"));const a=document.createElement("span");a.className="designbase-wc-sidebar__project-option-label",a.textContent=t.label,i.append(a);const n=this.createProjectBadge(t);n&&i.append(n),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",t.id),this.dispatchProjectChange(t),this.render()}),s.append(i),e.append(s)}),t.append(e)}const n=document.createElement("button");n.type="button",n.className="designbase-wc-sidebar__project-manage",n.setAttribute("role","menuitem"),n.append(e("plus",14));const c=document.createElement("span");c.textContent=this.projectManageLabel,n.append(c),n.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref;e&&window.location.assign(e),this.dispatchProjectManage(),this.render()}),t.append(n),a.append(t)}return a}createFlyout(e,t){const s=this.getAttribute("position")||"left",i=document.createElement("div");i.className=["designbase-wc-sidebar__flyout","right"===s&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),i.setAttribute("role","menu"),i.setAttribute("aria-label",`${e.label} 하위 메뉴`),i.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),i.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const r=document.createElement("div");r.className="designbase-wc-sidebar__flyout-title",r.textContent=e.label,i.append(r);const a=document.createElement("ul");return a.className="designbase-wc-sidebar__flyout-list",(e.children||[]).forEach(e=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",t),e.href&&i.setAttribute("href",e.href),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),s.append(i),a.append(s)}),i.append(a),i}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),r=this.expandedItems.has(e.id),a=this.hasAttribute("collapsed"),n=a&&i,c=document.createElement("li");c.className=["designbase-wc-sidebar__item",n&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),n&&(c.addEventListener("mouseenter",()=>this.showFlyout(e.id)),c.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const o=document.createElement("db-menu-item");if(o.setAttribute("data-item-id",e.id),o.setAttribute("label",e.label),o.setAttribute("type","block"),o.setAttribute("menu-style","accordion"),o.setAttribute("size",t),o.setAttribute("depth",String(s)),e.href&&o.setAttribute("href",e.href),e.icon&&o.setAttribute("icon",e.icon),e.active&&o.setAttribute("active",""),e.disabled&&o.setAttribute("disabled",""),void 0!==e.badge&&o.setAttribute("badge",String(e.badge)),e.badgeColor&&o.setAttribute("badge-color",e.badgeColor),i&&!n&&(o.setAttribute("expandable",""),o.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor})),r&&!a&&o.setAttribute("expanded","")),o.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!a){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),void(s?(this.expandedItems.clear(),this.expandedItems.add(e.id),this.syncExclusiveAccordion(e.id)):(this.expandedItems.delete(e.id),this.syncExclusiveAccordion(null)))}if(n)return this.closeOverlayMenus(),void this.showFlyout(e.id);this.closeOverlayMenus(),this.dispatchItemClick(e)}}),o.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),c.append(o),a&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),c.append(s)}if(a&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),c.append(t)}return n&&this.flyoutItemId===e.id&&c.append(this.createFlyout(e,t)),c}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const r=document.createElement("div");if(r.className=["designbase-wc-sidebar__section",e.gap&&`designbase-wc-sidebar__section--gap-${e.gap}`].filter(Boolean).join(" "),!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,r.append(t)}const a=document.createElement("ul");a.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>a.append(this.createSidebarMenuItem(e,t))),r.append(a),i.append(r)}),i}renderNav(){const e=this.querySelector(".designbase-wc-sidebar__nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseSections(),t,s))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(s,i=!1){if(!s.length)return null;const r=this.getAttribute("position")||"left",a=document.createElement("div");a.className=["designbase-wc-sidebar__user-dropdown",i&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),a.setAttribute("role","menu"),a.setAttribute("aria-label","사용자 메뉴"),a.hidden=!this.userMenuOpen,a.addEventListener("keydown",e=>{"Escape"===e.key&&(e.stopPropagation(),this.userFlyoutItemId?this.setUserFlyout(null):(this.userMenuOpen=!1,this.render()))});const n=document.createElement("ul");return n.className="designbase-wc-sidebar__user-menu",s.forEach(s=>{const i=Boolean(s.children?.length),a=document.createElement("li");a.dataset.itemId=s.id,a.className=["designbase-wc-sidebar__user-menu-item",s.dividerBefore&&"designbase-wc-sidebar__user-menu-item--divider",s.disabled&&"designbase-wc-sidebar__user-menu-item--disabled",i&&"designbase-wc-sidebar__user-menu-item--has-children"].filter(Boolean).join(" ");const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__user-menu-trigger",c.setAttribute("role","menuitem"),c.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),c.append(t)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__user-menu-label",o.textContent=s.label,c.append(o),s.value){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-value",e.textContent=s.value,c.append(e)}if(i){const i=document.createElement("span");i.className="designbase-wc-sidebar__user-menu-chevron",i.setAttribute("aria-hidden","true"),i.append(e("right"===r?"chevron-left":"chevron-right",16)),c.append(i),c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.userFlyoutItemId===s.id));const openFlyout=()=>this.setUserFlyout(s.id);a.addEventListener("mouseenter",openFlyout),a.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose()),a.addEventListener("focusin",openFlyout),a.addEventListener("focusout",e=>{const t=e.relatedTarget;t&&a.contains(t)||this.scheduleUserFlyoutClose()}),c.addEventListener("click",openFlyout);const n=document.createElement("div");n.className=["designbase-wc-sidebar__user-flyout","right"===r&&"designbase-wc-sidebar__user-flyout--align-left"].filter(Boolean).join(" "),n.setAttribute("role","menu"),n.setAttribute("aria-label",`${s.label} 하위 메뉴`),n.hidden=this.userFlyoutItemId!==s.id,n.addEventListener("mouseenter",()=>this.cancelUserFlyoutClose()),n.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose());const o=document.createElement("ul");o.className="designbase-wc-sidebar__user-flyout-list",(s.children||[]).forEach(s=>{const i=document.createElement("li");i.className="designbase-wc-sidebar__user-flyout-item";const r=document.createElement("button");if(r.type="button",r.className=["designbase-wc-sidebar__user-menu-trigger","designbase-wc-sidebar__user-flyout-trigger",s.selected&&"designbase-wc-sidebar__user-flyout-trigger--selected"].filter(Boolean).join(" "),r.setAttribute("role","menuitemradio"),r.setAttribute("aria-checked",String(Boolean(s.selected))),r.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),r.append(t)}const a=document.createElement("span");if(a.className="designbase-wc-sidebar__user-menu-label",a.textContent=s.label,r.append(a),s.selected){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-check",t.setAttribute("aria-hidden","true"),t.append(e("done",16)),r.append(t)}r.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),i.append(r),o.append(i)}),n.append(o),a.append(c,n)}else c.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),a.append(c);n.append(a)}),a.append(n),a}createPromoBanner(s){if("back"===this.headerType)return null;const i=this.parsePromoBanner();if(!i)return null;if(s){const s=document.createElement("button");s.type="button",s.className="designbase-wc-sidebar__promo-collapsed",s.setAttribute("aria-label",i.ctaLabel||i.title);const r=document.createElement("db-animation-background");r.className="designbase-wc-sidebar__promo-bg",r.setAttribute("type","aurora"),r.setAttribute("theme","light"),r.setAttribute("intensity","subtle"),r.setAttribute("blur","40"),r.setAttribute("speed","4000"),r.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),s.append(r),s.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",18)),s.addEventListener("click",()=>this.dispatchPromoCtaClick(i));const a=document.createElement("span");a.className="designbase-wc-sidebar__item-tooltip",a.textContent=i.title,a.setAttribute("role","tooltip");const n=document.createElement("div");return n.className="designbase-wc-sidebar__promo-collapsed-wrap",n.append(s,a),n}const r=document.createElement("div");r.className="designbase-wc-sidebar__promo";const a=document.createElement("db-animation-background");a.className="designbase-wc-sidebar__promo-bg",a.setAttribute("type","aurora"),a.setAttribute("theme","light"),a.setAttribute("intensity","subtle"),a.setAttribute("blur","60"),a.setAttribute("speed","5000"),a.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),r.append(a);const n=document.createElement("div");n.className="designbase-wc-sidebar__promo-content";const c=document.createElement("div");c.className="designbase-wc-sidebar__promo-title-row";const o=document.createElement("span");o.className="designbase-wc-sidebar__promo-icon",o.setAttribute("aria-hidden","true"),o.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",16));const d=document.createElement("div");if(d.className="designbase-wc-sidebar__promo-title",d.textContent=i.title,c.append(o,d),n.append(c),i.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=i.description,n.append(e)}if(i.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=i.ctaLabel,e.addEventListener("db-click",()=>{i.ctaHref&&window.location.assign(i.ctaHref),this.dispatchPromoCtaClick(i)}),n.append(e)}return r.append(n),r}render(){this.syncHostClasses(),this.setAttribute("role","complementary"),this.setAttribute("aria-label","사이드바 네비게이션");const t=this.getAttribute("size")||"m",s="false"!==this.getAttribute("collapsible"),i="false"!==this.getAttribute("show-logo"),r=this.hasAttribute("collapsed"),a=this.parseUserProfile(),n=this.parseUserMenuItems(),c=this.parseBottomSections(),o="l"===t?"m":"s"===t?"xs":"s";this.replaceChildren();const d=document.createElement("div");if(d.className="designbase-wc-sidebar__container","back"===this.headerType||s||i&&!r){const t=document.createElement("div");if(t.className=["designbase-wc-sidebar__header",(r||!i)&&"designbase-wc-sidebar__header--collapsed-only","back"===this.headerType&&"designbase-wc-sidebar__header--back"].filter(Boolean).join(" "),"back"===this.headerType){const s=document.createElement("button");if(s.type="button",s.className=["designbase-wc-sidebar__back",r&&"designbase-wc-sidebar__back--collapsed"].filter(Boolean).join(" "),s.setAttribute("aria-label",this.backLabel),s.append(e("chevron-left",18)),!r){const e=document.createElement("span");e.textContent=this.backLabel,s.append(e)}s.addEventListener("click",()=>this.dispatchBackClick()),t.append(s)}else if(!r&&i){const e=document.createElement("div");e.className="designbase-wc-sidebar__logo";const s=document.createElement("db-logo");s.setAttribute("type","designbase"),s.setAttribute("size",o),e.append(s),e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),t.append(e)}if(s){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__toggle",e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("icon-only",""),e.setAttribute("start-icon",r?"arrow-bar-right":"arrow-bar-left"),e.setAttribute("aria-label",r?"사이드바 펼치기":"사이드바 접기"),e.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),t.append(e)}d.append(t)}const l=document.createElement("div");l.className="designbase-wc-sidebar__nav-wrapper";const u=this.createProjectSelector(r);u&&l.append(u);const b=document.createElement("nav");if(b.className="designbase-wc-sidebar__nav",b.setAttribute("aria-label","주 메뉴"),l.append(b),c.length>0){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label","하단 메뉴"),l.append(e)}d.append(l);const p=document.createElement("div");p.className="designbase-wc-sidebar__footer";const m=this.createPromoBanner(r);if(m&&p.append(m),a&&!r){const t=document.createElement("div");t.className="designbase-wc-sidebar__user";const s=this.createUserDropdown(n);s&&t.append(s);const i=document.createElement("div");i.className="designbase-wc-sidebar__user-info",i.setAttribute("role","button"),i.setAttribute("tabindex","0"),i.setAttribute("aria-expanded",String(this.userMenuOpen));const r=document.createElement("db-avatar");r.className="designbase-wc-sidebar__user-avatar",r.setAttribute("size","s"),r.setAttribute("initials",a.name),r.setAttribute("alt",a.name),a.avatar&&r.setAttribute("src",a.avatar);const c=document.createElement("div");c.className="designbase-wc-sidebar__user-details";const o=document.createElement("div");if(o.className="designbase-wc-sidebar__user-name",o.textContent=a.name,c.append(o),a.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=a.email,c.append(e)}if(i.append(r,c),n.length){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-more",t.setAttribute("aria-hidden","true"),t.append(e("more-vertical",16)),i.append(t),i.setAttribute("aria-haspopup","menu")}i.addEventListener("click",()=>{n.length&&(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render())}),i.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),i.click())}),t.append(i),p.append(t)}else if(a&&r){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",a.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),n.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",a.name),t.setAttribute("alt",a.name),a.avatar&&t.setAttribute("src",a.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=a.name,t.setAttribute("role","tooltip"),e.append(t)}const s=this.createUserDropdown(n,!0);s&&e.append(s),e.addEventListener("click",e=>{n.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render()))}),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}),p.append(e)}d.append(p),this.append(d),this.renderNav(),this.renderBottomNav()}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
1
+ import{createDbIcon as e,isDbIconName as t}from"./db-icons.js";const s=["s","m","l"],i=["default","dark","light"],a=["left","right"];class DbSidebar extends HTMLElement{constructor(){super(...arguments),this.expandedItems=new Set,this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.flyoutCloseTimer=null,this.userFlyoutCloseTimer=null,this.outsideHandler=null}static get observedAttributes(){return["items","sections","user-menu-items","user-profile","default-expanded-ids","projects","selected-project-id","project-manage-label","project-manage-href","project-section-label","project-empty-label","project-empty-trigger-label","bottom-items","bottom-sections","promo-banner","header-type","back-label","back-href","settings-sections","active-panel","size","variant","position","collapsed","collapsible","show-logo","full-height","shadow"]}connectedCallback(){this.seedExpanded(),this.render(),this.bindOutsideClick()}disconnectedCallback(){this.unbindOutsideClick(),this.cancelFlyoutClose(),this.cancelUserFlyoutClose()}attributeChangedCallback(e){if(this.isConnected){if("default-expanded-ids"===e&&this.seedExpanded(),"collapsed"===e&&this.hasAttribute("collapsed")&&(this.userMenuOpen=!1,this.projectMenuOpen=!1,this.flyoutItemId=null,this.userFlyoutItemId=null,this.cancelFlyoutClose(),this.cancelUserFlyoutClose()),"active-panel"===e&&this.querySelector(".designbase-wc-sidebar__panel-track"))return this.syncActivePanelTrack(),void this.dispatchEvent(new CustomEvent("db-panel-change",{bubbles:!0,composed:!0,detail:{panel:this.activePanel}}));this.render()}}seedExpanded(){try{const e=JSON.parse(this.getAttribute("default-expanded-ids")||"[]");Array.isArray(e)&&(this.expandedItems=new Set(e))}catch{this.expandedItems=new Set}}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get sections(){return this.parseSections()}set sections(e){this.setAttribute("sections","string"==typeof e?e:JSON.stringify(e))}get userMenuItems(){return this.parseUserMenuItems()}set userMenuItems(e){this.setAttribute("user-menu-items","string"==typeof e?e:JSON.stringify(e))}get userProfile(){return this.parseUserProfile()}set userProfile(e){null==e?this.removeAttribute("user-profile"):this.setAttribute("user-profile","string"==typeof e?e:JSON.stringify(e))}get projects(){return this.parseProjects()}set projects(e){this.setAttribute("projects","string"==typeof e?e:JSON.stringify(e))}get selectedProjectId(){return this.getAttribute("selected-project-id")||""}set selectedProjectId(e){e?this.setAttribute("selected-project-id",e):this.removeAttribute("selected-project-id")}get projectManageLabel(){return this.getAttribute("project-manage-label")||"프로젝트 관리"}set projectManageLabel(e){this.setAttribute("project-manage-label",e)}get projectManageHref(){return this.getAttribute("project-manage-href")||""}set projectManageHref(e){e?this.setAttribute("project-manage-href",e):this.removeAttribute("project-manage-href")}get projectSectionLabel(){return this.getAttribute("project-section-label")||"프로젝트"}set projectSectionLabel(e){this.setAttribute("project-section-label",e)}get projectEmptyLabel(){return this.getAttribute("project-empty-label")||"프로젝트를 추가해 주세요"}set projectEmptyLabel(e){this.setAttribute("project-empty-label",e)}get projectEmptyTriggerLabel(){return this.getAttribute("project-empty-trigger-label")||"프로젝트 추가"}set projectEmptyTriggerLabel(e){this.setAttribute("project-empty-trigger-label",e)}get bottomItems(){return this.parseBottomItems()}set bottomItems(e){this.setAttribute("bottom-items","string"==typeof e?e:JSON.stringify(e))}get bottomSections(){return this.parseBottomSections()}set bottomSections(e){this.setAttribute("bottom-sections","string"==typeof e?e:JSON.stringify(e))}get promoBanner(){return this.parsePromoBanner()}set promoBanner(e){null==e?this.removeAttribute("promo-banner"):this.setAttribute("promo-banner","string"==typeof e?e:JSON.stringify(e))}get headerType(){return"back"===this.getAttribute("header-type")?"back":"default"}set headerType(e){this.setAttribute("header-type",e)}get backLabel(){return this.getAttribute("back-label")||"뒤로가기"}set backLabel(e){this.setAttribute("back-label",e)}get backHref(){return this.getAttribute("back-href")||""}set backHref(e){e?this.setAttribute("back-href",e):this.removeAttribute("back-href")}get settingsSections(){return this.parseSettingsSections()}set settingsSections(e){this.setAttribute("settings-sections","string"==typeof e?e:JSON.stringify(e))}get activePanel(){return this.getAttribute("active-panel")||"main"}set activePanel(e){this.setAttribute("active-panel",e||"main")}parseSettingsSections(){try{const e=JSON.parse(this.getAttribute("settings-sections")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}hasSettingsPanel(){return this.parseSettingsSections().length>0}parseSections(){const e=this.getAttribute("sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}try{const e=JSON.parse(this.getAttribute("items")||"[]");return[{id:"main",items:Array.isArray(e)?e:[]}]}catch{return[{id:"main",items:[]}]}}parseUserMenuItems(){try{const e=JSON.parse(this.getAttribute("user-menu-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseUserProfile(){const e=this.getAttribute("user-profile");if(!e)return null;try{return JSON.parse(e)}catch{return null}}parseProjects(){try{const e=JSON.parse(this.getAttribute("projects")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomItems(){try{const e=JSON.parse(this.getAttribute("bottom-items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}parseBottomSections(){const e=this.getAttribute("bottom-sections");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length)return t}catch{}const t=this.parseBottomItems();return t.length?[{id:"bottom",items:t}]:[]}parsePromoBanner(){const e=this.getAttribute("promo-banner");if(!e)return null;try{return JSON.parse(e)}catch{return null}}getSelectedProject(){const e=this.parseProjects();if(!e.length)return null;const t=this.selectedProjectId;return e.find(e=>e.id===t)||e[0]}bindOutsideClick(){this.outsideHandler||(this.outsideHandler=e=>{const t=e.target;if(this.contains(t))return;let s=!1;this.userMenuOpen&&(this.userMenuOpen=!1,this.userFlyoutItemId=null,s=!0),this.projectMenuOpen&&(this.projectMenuOpen=!1,s=!0),s&&this.render()},document.addEventListener("mousedown",this.outsideHandler))}closeOverlayMenus(){const e=this.projectMenuOpen,t=this.userMenuOpen;if(!e&&!t)return!1;this.projectMenuOpen=!1,this.userMenuOpen=!1,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.classList.remove("designbase-wc-sidebar--user-menu-open"),this.querySelector(".designbase-wc-sidebar__project-dropdown")?.remove(),this.querySelector(".designbase-wc-sidebar__project-selector")?.classList.remove("designbase-wc-sidebar__project-selector--open");const s=this.querySelector(".designbase-wc-sidebar__project-trigger");s?.setAttribute("aria-expanded","false");const i=this.querySelector(".designbase-wc-sidebar__user-dropdown");return i&&(i.hidden=!0),this.querySelector(".designbase-wc-sidebar__user-info")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.setAttribute("aria-expanded","false"),this.querySelector(".designbase-wc-sidebar__user-collapsed")?.classList.remove("designbase-wc-sidebar__user-collapsed--open"),!0}syncExclusiveAccordion(e){[...Array.from(this.querySelectorAll(".designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item")),...Array.from(this.querySelectorAll(".designbase-wc-sidebar__bottom-nav .designbase-wc-sidebar__nav-list > .designbase-wc-sidebar__item > db-menu-item"))].forEach(t=>{const s=t.getAttribute("data-item-id");s&&(e&&s===e?t.setAttribute("expanded",""):t.removeAttribute("expanded"))})}unbindOutsideClick(){this.outsideHandler&&(document.removeEventListener("mousedown",this.outsideHandler),this.outsideHandler=null)}cancelFlyoutClose(){this.flyoutCloseTimer&&(clearTimeout(this.flyoutCloseTimer),this.flyoutCloseTimer=null)}showFlyout(e){this.cancelFlyoutClose(),this.flyoutItemId!==e&&(this.flyoutItemId=e,this.renderNav(),this.renderBottomNav())}scheduleFlyoutClose(){this.cancelFlyoutClose(),this.flyoutCloseTimer=setTimeout(()=>{this.flyoutCloseTimer=null,this.flyoutItemId=null,this.renderNav(),this.renderBottomNav()},120)}cancelUserFlyoutClose(){this.userFlyoutCloseTimer&&(clearTimeout(this.userFlyoutCloseTimer),this.userFlyoutCloseTimer=null)}setUserFlyout(e){this.cancelUserFlyoutClose(),this.userFlyoutItemId=e,this.querySelectorAll(".designbase-wc-sidebar__user-menu-item").forEach(t=>{const s=Boolean(e&&t.dataset.itemId===e);t.classList.toggle("designbase-wc-sidebar__user-menu-item--flyout-active",s),t.querySelector(".designbase-wc-sidebar__user-menu-trigger")?.setAttribute("aria-expanded",String(s));const i=t.querySelector(".designbase-wc-sidebar__user-flyout");i&&(i.hidden=!s)})}scheduleUserFlyoutClose(){this.cancelUserFlyoutClose(),this.userFlyoutCloseTimer=setTimeout(()=>{this.userFlyoutCloseTimer=null,this.setUserFlyout(null)},120)}syncHostClasses(){const e=this.getAttribute("size")||"m",t=this.getAttribute("variant")||"default",n=this.getAttribute("position")||"left";this.className=["designbase-wc-sidebar",`designbase-wc-sidebar--${s.includes(e)?e:"m"}`,`designbase-wc-sidebar--${i.includes(t)?t:"default"}`,`designbase-wc-sidebar--${a.includes(n)?n:"left"}`,this.hasAttribute("collapsed")&&"designbase-wc-sidebar--collapsed",this.hasAttribute("full-height")&&"designbase-wc-sidebar--full-height",this.hasAttribute("shadow")&&"designbase-wc-sidebar--shadow",this.userMenuOpen&&"designbase-wc-sidebar--user-menu-open",("back"===this.headerType||"main"!==this.activePanel)&&"designbase-wc-sidebar--header-back","main"!==this.activePanel&&"designbase-wc-sidebar--panel-settings",this.hasSettingsPanel()&&"designbase-wc-sidebar--has-panels"].filter(Boolean).join(" ")}syncActivePanelTrack(){const e=this.querySelector(".designbase-wc-sidebar__panel-track");if(!e)return;const t=this.activePanel;e.setAttribute("data-active",t),this.syncHostClasses(),this.querySelectorAll(".designbase-wc-sidebar__panel-slide").forEach(e=>{const s=e.dataset.panel===t;e.toggleAttribute("inert",!s),e.setAttribute("aria-hidden",String(!s))})}navigateToPanel(e){const t=e||"main";if(this.activePanel!==t)return this.hasAttribute("collapsed")?(this.setAttribute("active-panel",t),void this.removeAttribute("collapsed")):void this.setAttribute("active-panel",t)}dispatchItemClick(e){this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchUserMenuItemClick(e){this.dispatchEvent(new CustomEvent("db-user-menu-item-click",{bubbles:!0,composed:!0,detail:{item:e}}))}dispatchBackClick(){this.hasSettingsPanel()&&"main"!==this.activePanel&&this.navigateToPanel("main");const e=new CustomEvent("db-back-click",{bubbles:!0,composed:!0,cancelable:!0,detail:{label:this.backLabel,href:this.backHref}});this.dispatchEvent(e),!e.defaultPrevented&&this.backHref&&"main"===this.activePanel&&"back"===this.headerType&&window.location.assign(this.backHref)}dispatchProjectChange(e){this.dispatchEvent(new CustomEvent("db-project-change",{bubbles:!0,composed:!0,detail:{project:e}}))}dispatchProjectManage(){this.dispatchEvent(new CustomEvent("db-project-manage",{bubbles:!0,composed:!0,detail:{}}))}dispatchPromoCtaClick(e){this.dispatchEvent(new CustomEvent("db-promo-cta-click",{bubbles:!0,composed:!0,detail:{banner:e}}))}createProjectAvatar(e,t="s"){const s=document.createElement("db-avatar");if(s.className="designbase-wc-sidebar__project-avatar",s.setAttribute("size",t),s.setAttribute("initials",(e.label||"?").trim()),s.setAttribute("alt",e.label),e.color){const applyColor=()=>{const t=s.querySelector(".designbase-wc-avatar__initials");return!!t&&(t.style.backgroundColor=e.color,t.style.color="#fff",!0)},t=new MutationObserver(()=>{applyColor()&&t.disconnect()});t.observe(s,{childList:!0,subtree:!0}),queueMicrotask(()=>{applyColor()&&t.disconnect()})}return s}createProjectEmptyMark(t="s"){const s=document.createElement("span");return s.className=["designbase-wc-sidebar__project-mark",`designbase-wc-sidebar__project-mark--${t}`,"designbase-wc-sidebar__project-mark--empty"].join(" "),s.setAttribute("aria-hidden","true"),s.append(e("plus","m"===t?16:14)),s}createProjectBadge(e){if(!e.badge)return null;const t=document.createElement("db-badge");return t.className="designbase-wc-sidebar__project-badge",t.setAttribute("size","s"),t.setAttribute("variant",e.badgeColor||"warning"),t.setAttribute("badge-style","text"),t.textContent=e.badge,t}createProjectSelector(t){if(!this.hasAttribute("projects"))return null;const s=this.parseProjects(),i=0===s.length,a=this.getSelectedProject(),n=document.createElement("div");n.className=["designbase-wc-sidebar__project-selector",t&&"designbase-wc-sidebar__project-selector--collapsed",this.projectMenuOpen&&"designbase-wc-sidebar__project-selector--open",i&&"designbase-wc-sidebar__project-selector--empty"].filter(Boolean).join(" ");const r=this.getAttribute("project-section-label");if(!t&&r&&r.trim()){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-section-label",e.textContent=r.trim(),n.append(e)}const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__project-trigger",c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.projectMenuOpen)),i||!a){if(c.setAttribute("aria-label",this.projectEmptyTriggerLabel),c.append(this.createProjectEmptyMark(t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=this.projectEmptyTriggerLabel,c.append(e)}}else if(c.setAttribute("aria-label",a.label),c.append(this.createProjectAvatar(a,t?"m":"s")),!t){const e=document.createElement("span");e.className="designbase-wc-sidebar__project-label",e.textContent=a.label,c.append(e)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__project-chevron",o.setAttribute("aria-hidden","true"),o.append(e("chevron-down",14)),c.append(o),c.addEventListener("click",()=>{this.projectMenuOpen=!this.projectMenuOpen,this.userMenuOpen=!1,this.render()}),n.append(c),this.projectMenuOpen){const t=document.createElement("div");if(t.className="designbase-wc-sidebar__project-dropdown",t.setAttribute("role","menu"),t.setAttribute("aria-label",this.projectSectionLabel),i){const e=document.createElement("div");e.className="designbase-wc-sidebar__project-empty",e.setAttribute("role","presentation");const s=document.createElement("p");s.className="designbase-wc-sidebar__project-empty-text",s.textContent=this.projectEmptyLabel,e.append(s),t.append(e)}else{const e=document.createElement("ul");e.className="designbase-wc-sidebar__project-list",s.forEach(t=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__project-option";const i=document.createElement("button");i.type="button",i.className=["designbase-wc-sidebar__project-option-btn",a&&t.id===a.id&&"designbase-wc-sidebar__project-option-btn--active"].filter(Boolean).join(" "),i.setAttribute("role","menuitem"),i.append(this.createProjectAvatar(t,"s"));const n=document.createElement("span");n.className="designbase-wc-sidebar__project-option-label",n.textContent=t.label,i.append(n);const r=this.createProjectBadge(t);r&&i.append(r),i.addEventListener("click",()=>{this.projectMenuOpen=!1,this.setAttribute("selected-project-id",t.id),this.dispatchProjectChange(t),this.render()}),s.append(i),e.append(s)}),t.append(e)}const r=document.createElement("button");r.type="button",r.className="designbase-wc-sidebar__project-manage",r.setAttribute("role","menuitem"),r.append(e("plus",14));const c=document.createElement("span");c.textContent=this.projectManageLabel,r.append(c),r.addEventListener("click",()=>{this.projectMenuOpen=!1;const e=this.projectManageHref;e&&window.location.assign(e),this.dispatchProjectManage(),this.render()}),t.append(r),n.append(t)}return n}createFlyout(e,t){const s=this.getAttribute("position")||"left",i=document.createElement("div");i.className=["designbase-wc-sidebar__flyout","right"===s&&"designbase-wc-sidebar__flyout--align-left"].filter(Boolean).join(" "),i.setAttribute("role","menu"),i.setAttribute("aria-label",`${e.label} 하위 메뉴`),i.addEventListener("mouseenter",()=>this.cancelFlyoutClose()),i.addEventListener("mouseleave",()=>this.scheduleFlyoutClose());const a=document.createElement("div");a.className="designbase-wc-sidebar__flyout-title",a.textContent=e.label,i.append(a);const n=document.createElement("ul");return n.className="designbase-wc-sidebar__flyout-list",(e.children||[]).forEach(e=>{const s=document.createElement("li");s.className="designbase-wc-sidebar__flyout-item";const i=document.createElement("db-menu-item");i.setAttribute("label",e.label),i.setAttribute("type","block"),i.setAttribute("menu-style","dropdown"),i.setAttribute("size",t),e.href&&i.setAttribute("href",e.href),e.active&&i.setAttribute("active",""),e.disabled&&i.setAttribute("disabled",""),void 0!==e.badge&&i.setAttribute("badge",String(e.badge)),e.badgeColor&&i.setAttribute("badge-color",e.badgeColor),i.addEventListener("db-click",()=>{e.disabled||(this.flyoutItemId=null,this.dispatchItemClick(e),this.renderNav(),this.renderBottomNav())}),s.append(i),n.append(s)}),i.append(n),i}createSidebarMenuItem(e,t,s=0){const i=Boolean(e.children?.length),a=this.expandedItems.has(e.id),n=this.hasAttribute("collapsed"),r=n&&i,c=document.createElement("li");c.className=["designbase-wc-sidebar__item",r&&this.flyoutItemId===e.id&&"designbase-wc-sidebar__item--flyout-active"].filter(Boolean).join(" "),r&&(c.addEventListener("mouseenter",()=>this.showFlyout(e.id)),c.addEventListener("mouseleave",()=>this.scheduleFlyoutClose()));const o=document.createElement("db-menu-item");if(o.setAttribute("data-item-id",e.id),o.setAttribute("label",e.label),o.setAttribute("type","block"),o.setAttribute("menu-style","accordion"),o.setAttribute("size",t),o.setAttribute("depth",String(s)),e.href&&o.setAttribute("href",e.href),e.icon&&o.setAttribute("icon",e.icon),e.active&&o.setAttribute("active",""),e.disabled&&o.setAttribute("disabled",""),void 0!==e.badge&&o.setAttribute("badge",String(e.badge)),e.badgeColor&&o.setAttribute("badge-color",e.badgeColor),i&&!r&&(o.setAttribute("expandable",""),o.subItems=(e.children||[]).map(e=>({id:e.id,label:e.label,href:e.href,active:e.active,disabled:e.disabled,badge:e.badge,badgeColor:e.badgeColor})),a&&!n&&o.setAttribute("expanded","")),o.addEventListener("db-click",t=>{if(!e.disabled){if(i&&!n){const s=t.detail?.expanded??!this.expandedItems.has(e.id);return this.closeOverlayMenus(),void(s?(this.expandedItems.clear(),this.expandedItems.add(e.id),this.syncExclusiveAccordion(e.id)):(this.expandedItems.delete(e.id),this.syncExclusiveAccordion(null)))}if(r)return this.closeOverlayMenus(),void this.showFlyout(e.id);if(this.closeOverlayMenus(),e.openPanel&&this.hasSettingsPanel())return this.dispatchItemClick(e),void this.navigateToPanel(e.openPanel);this.dispatchItemClick(e)}}),o.addEventListener("db-child-click",e=>{const t=e.detail;this.dispatchItemClick(t.child)}),c.append(o),n&&void 0!==e.badge&&null!==e.badge&&""!==e.badge){const t=e.badgeColor||"primary",s=document.createElement("span");s.className=["designbase-wc-sidebar__collapsed-badge-dot",`designbase-wc-sidebar__collapsed-badge-dot--${t}`].join(" "),s.setAttribute("aria-hidden","true"),c.append(s)}if(n&&!i){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=e.label,t.setAttribute("role","tooltip"),c.append(t)}return r&&this.flyoutItemId===e.id&&c.append(this.createFlyout(e,t)),c}renderSectionList(e,t,s){const i=document.createDocumentFragment();return e.forEach(e=>{const a=document.createElement("div");if(a.className=["designbase-wc-sidebar__section",e.gap&&`designbase-wc-sidebar__section--gap-${e.gap}`].filter(Boolean).join(" "),!s&&e.title){const t=document.createElement("div");t.className="designbase-wc-sidebar__section-title",t.textContent=e.title,a.append(t)}const n=document.createElement("ul");n.className="designbase-wc-sidebar__nav-list",e.items.forEach(e=>n.append(this.createSidebarMenuItem(e,t))),a.append(n),i.append(a)}),i}renderNav(){const e=this.getAttribute("size")||"m",t=this.hasAttribute("collapsed"),s=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="main"]')||(this.hasSettingsPanel()?null:this.querySelector(".designbase-wc-sidebar__nav"));s&&s.replaceChildren(this.renderSectionList(this.parseSections(),e,t));const i=this.querySelector('.designbase-wc-sidebar__nav[data-panel-nav="settings"]');i&&i.replaceChildren(this.renderSectionList(this.parseSettingsSections(),e,!1))}renderBottomNav(){const e=this.querySelector(".designbase-wc-sidebar__bottom-nav");if(!e)return;const t=this.getAttribute("size")||"m",s=this.hasAttribute("collapsed");e.replaceChildren(this.renderSectionList(this.parseBottomSections(),t,s))}createUserDropdown(s,i=!1){if(!s.length)return null;const a=this.getAttribute("position")||"left",n=document.createElement("div");n.className=["designbase-wc-sidebar__user-dropdown",i&&"designbase-wc-sidebar__user-dropdown--collapsed"].filter(Boolean).join(" "),n.setAttribute("role","menu"),n.setAttribute("aria-label","사용자 메뉴"),n.hidden=!this.userMenuOpen,n.addEventListener("keydown",e=>{"Escape"===e.key&&(e.stopPropagation(),this.userFlyoutItemId?this.setUserFlyout(null):(this.userMenuOpen=!1,this.render()))});const r=document.createElement("ul");return r.className="designbase-wc-sidebar__user-menu",s.forEach(s=>{const i=Boolean(s.children?.length),n=document.createElement("li");n.dataset.itemId=s.id,n.className=["designbase-wc-sidebar__user-menu-item",s.dividerBefore&&"designbase-wc-sidebar__user-menu-item--divider",s.disabled&&"designbase-wc-sidebar__user-menu-item--disabled",i&&"designbase-wc-sidebar__user-menu-item--has-children"].filter(Boolean).join(" ");const c=document.createElement("button");if(c.type="button",c.className="designbase-wc-sidebar__user-menu-trigger",c.setAttribute("role","menuitem"),c.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),c.append(t)}const o=document.createElement("span");if(o.className="designbase-wc-sidebar__user-menu-label",o.textContent=s.label,c.append(o),s.value){const e=document.createElement("span");e.className="designbase-wc-sidebar__user-menu-value",e.textContent=s.value,c.append(e)}if(i){const i=document.createElement("span");i.className="designbase-wc-sidebar__user-menu-chevron",i.setAttribute("aria-hidden","true"),i.append(e("right"===a?"chevron-left":"chevron-right",16)),c.append(i),c.setAttribute("aria-haspopup","menu"),c.setAttribute("aria-expanded",String(this.userFlyoutItemId===s.id));const openFlyout=()=>this.setUserFlyout(s.id);n.addEventListener("mouseenter",openFlyout),n.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose()),n.addEventListener("focusin",openFlyout),n.addEventListener("focusout",e=>{const t=e.relatedTarget;t&&n.contains(t)||this.scheduleUserFlyoutClose()}),c.addEventListener("click",openFlyout);const r=document.createElement("div");r.className=["designbase-wc-sidebar__user-flyout","right"===a&&"designbase-wc-sidebar__user-flyout--align-left"].filter(Boolean).join(" "),r.setAttribute("role","menu"),r.setAttribute("aria-label",`${s.label} 하위 메뉴`),r.hidden=this.userFlyoutItemId!==s.id,r.addEventListener("mouseenter",()=>this.cancelUserFlyoutClose()),r.addEventListener("mouseleave",()=>this.scheduleUserFlyoutClose());const o=document.createElement("ul");o.className="designbase-wc-sidebar__user-flyout-list",(s.children||[]).forEach(s=>{const i=document.createElement("li");i.className="designbase-wc-sidebar__user-flyout-item";const a=document.createElement("button");if(a.type="button",a.className=["designbase-wc-sidebar__user-menu-trigger","designbase-wc-sidebar__user-flyout-trigger",s.selected&&"designbase-wc-sidebar__user-flyout-trigger--selected"].filter(Boolean).join(" "),a.setAttribute("role","menuitemradio"),a.setAttribute("aria-checked",String(Boolean(s.selected))),a.disabled=Boolean(s.disabled),s.icon&&t(s.icon)){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-icon",t.setAttribute("aria-hidden","true"),t.append(e(s.icon,16)),a.append(t)}const n=document.createElement("span");if(n.className="designbase-wc-sidebar__user-menu-label",n.textContent=s.label,a.append(n),s.selected){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-menu-check",t.setAttribute("aria-hidden","true"),t.append(e("done",16)),a.append(t)}a.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),i.append(a),o.append(i)}),r.append(o),n.append(c,r)}else c.addEventListener("click",()=>{s.disabled||(this.userFlyoutItemId=null,this.userMenuOpen=!1,this.dispatchUserMenuItemClick(s),s.href&&window.location.assign(s.href),this.render())}),n.append(c);r.append(n)}),n.append(r),n}createPromoBanner(s){if("back"===this.headerType)return null;const i=this.parsePromoBanner();if(!i)return null;if(s){const s=document.createElement("button");s.type="button",s.className="designbase-wc-sidebar__promo-collapsed",s.setAttribute("aria-label",i.ctaLabel||i.title);const a=document.createElement("db-animation-background");a.className="designbase-wc-sidebar__promo-bg",a.setAttribute("type","aurora"),a.setAttribute("theme","light"),a.setAttribute("intensity","subtle"),a.setAttribute("blur","40"),a.setAttribute("speed","4000"),a.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8"])),s.append(a),s.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",18)),s.addEventListener("click",()=>this.dispatchPromoCtaClick(i));const n=document.createElement("span");n.className="designbase-wc-sidebar__item-tooltip",n.textContent=i.title,n.setAttribute("role","tooltip");const r=document.createElement("div");return r.className="designbase-wc-sidebar__promo-collapsed-wrap",r.append(s,n),r}const a=document.createElement("div");a.className="designbase-wc-sidebar__promo";const n=document.createElement("db-animation-background");n.className="designbase-wc-sidebar__promo-bg",n.setAttribute("type","aurora"),n.setAttribute("theme","light"),n.setAttribute("intensity","subtle"),n.setAttribute("blur","60"),n.setAttribute("speed","5000"),n.setAttribute("colors",JSON.stringify(["#c7d2fe","#ddd6fe","#fbcfe8","#bfdbfe"])),a.append(n);const r=document.createElement("div");r.className="designbase-wc-sidebar__promo-content";const c=document.createElement("div");c.className="designbase-wc-sidebar__promo-title-row";const o=document.createElement("span");o.className="designbase-wc-sidebar__promo-icon",o.setAttribute("aria-hidden","true"),o.append(e(i.icon&&t(i.icon)?i.icon:"sparkle",16));const d=document.createElement("div");if(d.className="designbase-wc-sidebar__promo-title",d.textContent=i.title,c.append(o,d),r.append(c),i.description){const e=document.createElement("div");e.className="designbase-wc-sidebar__promo-desc",e.textContent=i.description,r.append(e)}if(i.ctaLabel){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__promo-action",e.setAttribute("variant","secondary"),e.setAttribute("size","s"),e.setAttribute("full-width",""),e.textContent=i.ctaLabel,e.addEventListener("db-click",()=>{i.ctaHref&&window.location.assign(i.ctaHref),this.dispatchPromoCtaClick(i)}),r.append(e)}return a.append(r),a}createHeader(t){const{mode:s,size:i,collapsible:a,showLogo:n,collapsed:r}=t,c="settings"===s||"back"===this.headerType,o="l"===i?"m":"s"===i?"xs":"s";if(!c&&!a&&(!n||r))return null;const d=document.createElement("div");if(d.className=["designbase-wc-sidebar__header",(r||!n)&&!c&&"designbase-wc-sidebar__header--collapsed-only",c&&"designbase-wc-sidebar__header--back"].filter(Boolean).join(" "),c){const t=document.createElement("button");if(t.type="button",t.className=["designbase-wc-sidebar__back",r&&"designbase-wc-sidebar__back--collapsed"].filter(Boolean).join(" "),t.setAttribute("aria-label",this.backLabel),t.append(e("chevron-left",18)),!r){const e=document.createElement("span");e.textContent=this.backLabel,t.append(e)}t.addEventListener("click",()=>this.dispatchBackClick()),d.append(t)}else if(!r&&n){const e=document.createElement("div");e.className="designbase-wc-sidebar__logo";const t=document.createElement("db-logo");t.setAttribute("type","designbase"),t.setAttribute("size",o),e.append(t),e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-logo-click",{bubbles:!0,composed:!0}))}),d.append(e)}if(a&&"main"===s){const e=document.createElement("db-button");e.className="designbase-wc-sidebar__toggle",e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("icon-only",""),e.setAttribute("start-icon",r?"arrow-bar-right":"arrow-bar-left"),e.setAttribute("aria-label",r?"사이드바 펼치기":"사이드바 접기"),e.addEventListener("db-click",()=>{const e=!this.hasAttribute("collapsed");e?this.setAttribute("collapsed",""):this.removeAttribute("collapsed"),this.dispatchEvent(new CustomEvent("db-toggle",{bubbles:!0,composed:!0,detail:{collapsed:e}}))}),d.append(e)}return d}createNavWrapper(e){const{mode:t,collapsed:s,includeProjects:i,includeBottom:a}=e,n=document.createElement("div");if(n.className="designbase-wc-sidebar__nav-wrapper",i){const e=this.createProjectSelector(s);e&&n.append(e)}const r=document.createElement("nav");if(r.className="designbase-wc-sidebar__nav",r.setAttribute("data-panel-nav",t),r.setAttribute("aria-label","settings"===t?"설정 메뉴":"주 메뉴"),n.append(r),a){const e=document.createElement("nav");e.className="designbase-wc-sidebar__bottom-nav",e.setAttribute("aria-label","하단 메뉴"),n.append(e)}return n}render(){this.syncHostClasses(),this.setAttribute("role","complementary"),this.setAttribute("aria-label","사이드바 네비게이션");const t=this.getAttribute("size")||"m",s="false"!==this.getAttribute("collapsible"),i="false"!==this.getAttribute("show-logo"),a=this.hasAttribute("collapsed"),n=this.parseUserProfile(),r=this.parseUserMenuItems(),c=this.parseBottomSections(),o=this.hasSettingsPanel(),d=this.activePanel;this.replaceChildren();const l=document.createElement("div");if(l.className="designbase-wc-sidebar__container",o){const e=document.createElement("div");e.className="designbase-wc-sidebar__panel-viewport";const n=document.createElement("div");n.className="designbase-wc-sidebar__panel-track",n.setAttribute("data-active",d);const r=document.createElement("div");r.className="designbase-wc-sidebar__panel-slide",r.dataset.panel="main",r.toggleAttribute("inert","main"!==d),r.setAttribute("aria-hidden",String("main"!==d));const o=this.createHeader({mode:"main",size:t,collapsible:s,showLogo:i,collapsed:a});o&&r.append(o),r.append(this.createNavWrapper({mode:"main",collapsed:a,includeProjects:!0,includeBottom:c.length>0}));const u=this.createPromoBanner(a);u&&r.append(u);const b=document.createElement("div");b.className="designbase-wc-sidebar__panel-slide",b.dataset.panel="settings",b.toggleAttribute("inert","settings"!==d),b.setAttribute("aria-hidden",String("settings"!==d));const p=this.createHeader({mode:"settings",size:t,collapsible:!1,showLogo:!1,collapsed:!1});p&&b.append(p),b.append(this.createNavWrapper({mode:"settings",collapsed:!1,includeProjects:!1,includeBottom:!1})),n.append(r,b),e.append(n),l.append(e)}else{const e=this.createHeader({mode:"back"===this.headerType?"settings":"main",size:t,collapsible:"back"!==this.headerType&&s,showLogo:"back"!==this.headerType&&i,collapsed:a});e&&l.append(e),l.append(this.createNavWrapper({mode:"main",collapsed:a,includeProjects:"back"!==this.headerType,includeBottom:c.length>0}))}const u=document.createElement("div");if(u.className="designbase-wc-sidebar__footer",!o){const e=this.createPromoBanner(a);e&&u.append(e)}if(n&&!a){const t=document.createElement("div");t.className="designbase-wc-sidebar__user";const s=this.createUserDropdown(r);s&&t.append(s);const i=document.createElement("div");i.className="designbase-wc-sidebar__user-info",i.setAttribute("role","button"),i.setAttribute("tabindex","0"),i.setAttribute("aria-expanded",String(this.userMenuOpen));const a=document.createElement("db-avatar");a.className="designbase-wc-sidebar__user-avatar",a.setAttribute("size","s"),a.setAttribute("initials",n.name),a.setAttribute("alt",n.name),n.avatar&&a.setAttribute("src",n.avatar);const c=document.createElement("div");c.className="designbase-wc-sidebar__user-details";const o=document.createElement("div");if(o.className="designbase-wc-sidebar__user-name",o.textContent=n.name,c.append(o),n.email){const e=document.createElement("div");e.className="designbase-wc-sidebar__user-email",e.textContent=n.email,c.append(e)}if(i.append(a,c),r.length){const t=document.createElement("span");t.className="designbase-wc-sidebar__user-more",t.setAttribute("aria-hidden","true"),t.append(e("more-vertical",16)),i.append(t),i.setAttribute("aria-haspopup","menu")}i.addEventListener("click",()=>{r.length&&(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render())}),i.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),i.click())}),t.append(i),u.append(t)}else if(n&&a){const e=document.createElement("div");e.className=["designbase-wc-sidebar__user-collapsed",this.userMenuOpen&&"designbase-wc-sidebar__user-collapsed--open"].filter(Boolean).join(" "),e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.setAttribute("aria-label",n.name),e.setAttribute("aria-expanded",String(this.userMenuOpen)),r.length&&e.setAttribute("aria-haspopup","menu");const t=document.createElement("db-avatar");if(t.className="designbase-wc-sidebar__user-avatar-collapsed",t.setAttribute("size","s"),t.setAttribute("initials",n.name),t.setAttribute("alt",n.name),n.avatar&&t.setAttribute("src",n.avatar),e.append(t),!this.userMenuOpen){const t=document.createElement("span");t.className="designbase-wc-sidebar__item-tooltip",t.textContent=n.name,t.setAttribute("role","tooltip"),e.append(t)}const s=this.createUserDropdown(r,!0);s&&e.append(s),e.addEventListener("click",e=>{r.length&&(e.target.closest(".designbase-wc-sidebar__user-dropdown")||(this.userMenuOpen=!this.userMenuOpen,this.userFlyoutItemId=null,this.cancelUserFlyoutClose(),this.projectMenuOpen=!1,this.render()))}),e.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}),u.append(e)}l.append(u),this.append(l),this.renderNav(),this.renderBottomNav()}}customElements.get("db-sidebar")||customElements.define("db-sidebar",DbSidebar);export{DbSidebar};
@@ -0,0 +1,79 @@
1
+ type DbSignatureVariant = 'dashed' | 'outlined';
2
+ interface DbSignaturePoint {
3
+ x: number;
4
+ y: number;
5
+ t: number;
6
+ }
7
+ /**
8
+ * db-signature — 마우스·터치·펜으로 서명을 그리는 컴포넌트
9
+ *
10
+ * 중점 이차 곡선 + coalesced pointer 로 자연스럽게 이어지며,
11
+ * ⌘Z / ⌘⇧Z (Ctrl+Z / Ctrl+⇧Z) 로 되돌리기·다시 실행을 지원합니다.
12
+ *
13
+ * 속성: height, variant, pen-color, background-color, min-width, max-width,
14
+ * placeholder, show-clear, clear-label, disabled, readonly, value
15
+ * 메서드: clear(), undo(), redo(), isEmpty(), toDataURL(), fromDataURL()
16
+ * 이벤트: db-begin, db-end, db-change(detail.value), db-clear
17
+ */
18
+ declare class DbSignature extends HTMLElement {
19
+ private canvas;
20
+ private placeholderEl;
21
+ private clearButton;
22
+ private resizeObserver;
23
+ private themeObserver;
24
+ private strokes;
25
+ private redoStack;
26
+ private currentStroke;
27
+ private lastMid;
28
+ private lastWidth;
29
+ private lastVelocity;
30
+ private backgroundImage;
31
+ private activePointerId;
32
+ static get observedAttributes(): string[];
33
+ connectedCallback(): void;
34
+ disconnectedCallback(): void;
35
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
36
+ get value(): string | null;
37
+ set value(next: string | null);
38
+ private getNumberAttr;
39
+ private getBooleanAttr;
40
+ private getVariant;
41
+ private get minWidth();
42
+ private get maxWidth();
43
+ private get interactive();
44
+ private getPenColor;
45
+ private render;
46
+ private updateState;
47
+ private syncCanvasSize;
48
+ private resetCanvas;
49
+ private resolveWidth;
50
+ private drawCurveSegment;
51
+ private drawDot;
52
+ private drawStroke;
53
+ private redraw;
54
+ private getPoint;
55
+ private appendPoint;
56
+ private handlePointerDown;
57
+ private handlePointerMove;
58
+ private handlePointerUp;
59
+ private handleClearClick;
60
+ private handleKeyDown;
61
+ private emitChange;
62
+ isEmpty(): boolean;
63
+ clear(): void;
64
+ /** 마지막 획을 되돌립니다 */
65
+ undo(): void;
66
+ /** 되돌린 획을 다시 적용합니다 */
67
+ redo(): void;
68
+ toDataURL(type?: string, quality?: number): string | null;
69
+ fromDataURL(dataUrl: string): void;
70
+ getCanvas(): HTMLCanvasElement | null;
71
+ }
72
+ declare global {
73
+ interface HTMLElementTagNameMap {
74
+ 'db-signature': DbSignature;
75
+ }
76
+ }
77
+
78
+ export { DbSignature };
79
+ export type { DbSignaturePoint, DbSignatureVariant };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t}from"./db-icons.js";const e=["dashed","outlined"];class DbSignature extends HTMLElement{constructor(){super(...arguments),this.canvas=null,this.placeholderEl=null,this.clearButton=null,this.resizeObserver=null,this.themeObserver=null,this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.lastWidth=0,this.lastVelocity=0,this.backgroundImage=null,this.activePointerId=null,this.handlePointerDown=t=>{if(!this.interactive||0!==t.button)return;t.preventDefault(),this.focus({preventScroll:!0}),this.activePointerId=t.pointerId;try{this.canvas?.setPointerCapture(t.pointerId)}catch{}this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2;const e=this.getPoint(t);this.currentStroke=[e],this.lastMid=e,this.dispatchEvent(new CustomEvent("db-begin",{bubbles:!0,composed:!0}))},this.handlePointerMove=t=>{if(!this.currentStroke||this.activePointerId!==t.pointerId)return;t.preventDefault();const e="function"==typeof t.getCoalescedEvents?t.getCoalescedEvents():[t];for(const t of e){const e=this.canvas.getBoundingClientRect();this.appendPoint({x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()})}},this.handlePointerUp=t=>{const e=this.currentStroke;if(!e||this.activePointerId!==t.pointerId)return;this.activePointerId=null,this.currentStroke=null;const i=this.canvas?.getContext("2d");if(i)if(1===e.length)this.drawDot(i,e[0],this.getPenColor());else{const t=e[e.length-1],s=this.lastMid??t,n=this.lastWidth||(this.minWidth+this.maxWidth)/2;this.drawCurveSegment(i,s,t,t,this.getPenColor(),n)}this.lastMid=null,this.strokes.push(e),this.redoStack=[],this.updateState(),this.dispatchEvent(new CustomEvent("db-end",{bubbles:!0,composed:!0})),this.emitChange()},this.handleClearClick=()=>{this.interactive&&(this.clear(),this.dispatchEvent(new CustomEvent("db-clear",{bubbles:!0,composed:!0})),this.emitChange())},this.handleKeyDown=t=>{if(!this.interactive)return;if(!(t.metaKey||t.ctrlKey))return;const e=t.key.toLowerCase();return"z"===e&&t.shiftKey?(t.preventDefault(),void this.redo()):"z"===e?(t.preventDefault(),void this.undo()):void("y"===e&&(t.preventDefault(),this.redo()))}}static get observedAttributes(){return["height","variant","pen-color","background-color","min-width","max-width","placeholder","show-clear","clear-label","disabled","readonly","value"]}connectedCallback(){this.render(),this.syncCanvasSize(),this.addEventListener("keydown",this.handleKeyDown),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>this.syncCanvasSize()),this.resizeObserver.observe(this)),"undefined"!=typeof MutationObserver&&(this.themeObserver=new MutationObserver(()=>{this.getAttribute("pen-color")||this.redraw()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme","data-color-mode","class"]}));const t=this.getAttribute("value");t&&this.fromDataURL(t)}disconnectedCallback(){this.removeEventListener("keydown",this.handleKeyDown),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.themeObserver?.disconnect(),this.themeObserver=null}attributeChangedCallback(t,e,i){this.isConnected&&e!==i&&("value"!==t?(this.render(),this.syncCanvasSize(),this.redraw()):i?this.fromDataURL(i):this.clear())}get value(){return this.toDataURL()}set value(t){t?this.fromDataURL(t):this.clear()}getNumberAttr(t,e){const i=this.getAttribute(t);if(null===i||""===i)return e;const s=Number(i);return Number.isFinite(s)?s:e}getBooleanAttr(t,e=!1){if(!this.hasAttribute(t))return e;const i=this.getAttribute(t);return""===i||"true"===i}getVariant(){const t=this.getAttribute("variant");return t&&e.includes(t)?t:"dashed"}get minWidth(){return this.getNumberAttr("min-width",1)}get maxWidth(){return this.getNumberAttr("max-width",3.2)}get interactive(){return!this.getBooleanAttr("disabled")&&!this.getBooleanAttr("readonly")}getPenColor(){const t=this.getAttribute("pen-color");if(t)return t;return getComputedStyle(this).getPropertyValue("--db-text-primary").trim()||"#2c3542"}render(){const e=this.getVariant(),i=this.getAttribute("placeholder")??"",s=this.getBooleanAttr("show-clear",!0);if(this.className=["designbase-wc-signature",`designbase-wc-signature--${e}`,this.getBooleanAttr("disabled")&&"designbase-wc-signature--disabled",this.getBooleanAttr("readonly")&&"designbase-wc-signature--readonly",this.isEmpty()&&"designbase-wc-signature--empty"].filter(Boolean).join(" "),this.style.height=`${this.getNumberAttr("height",220)}px`,this.interactive?this.tabIndex=0:this.removeAttribute("tabindex"),this.canvas||(this.canvas=document.createElement("canvas"),this.canvas.className="designbase-wc-signature__canvas",this.canvas.setAttribute("role","img"),this.canvas.addEventListener("pointerdown",this.handlePointerDown),this.canvas.addEventListener("pointermove",this.handlePointerMove),this.canvas.addEventListener("pointerup",this.handlePointerUp),this.canvas.addEventListener("pointercancel",this.handlePointerUp),this.append(this.canvas)),this.canvas.setAttribute("aria-label",i||"서명 입력 영역"),i?(this.placeholderEl||(this.placeholderEl=document.createElement("span"),this.placeholderEl.className="designbase-wc-signature__placeholder",this.append(this.placeholderEl)),this.placeholderEl.textContent=i,this.placeholderEl.hidden=!this.isEmpty()):(this.placeholderEl?.remove(),this.placeholderEl=null),s){this.clearButton||(this.clearButton=document.createElement("button"),this.clearButton.type="button",this.clearButton.className="designbase-wc-signature__clear",this.clearButton.addEventListener("click",this.handleClearClick),this.clearButton.append(t("trash",20)),this.append(this.clearButton));const e=this.getAttribute("clear-label")||"서명 지우기";this.clearButton.setAttribute("aria-label",e),this.clearButton.title=e,this.clearButton.disabled=!this.interactive||this.isEmpty()}else this.clearButton?.remove(),this.clearButton=null}updateState(){const t=this.isEmpty();this.classList.toggle("designbase-wc-signature--empty",t),this.placeholderEl&&(this.placeholderEl.hidden=!t),this.clearButton&&(this.clearButton.disabled=!this.interactive||t)}syncCanvasSize(){const t=this.canvas;if(!t)return;const e=window.devicePixelRatio||1,i=t.getBoundingClientRect();if(0===i.width||0===i.height)return;const s=Math.round(i.width*e),n=Math.round(i.height*e);t.width===s&&t.height===n||(t.width=s,t.height=n,t.getContext("2d")?.scale(e,e),this.redraw())}resetCanvas(t,e,i){t.clearRect(0,0,e,i);const s=this.getAttribute("background-color");s&&"transparent"!==s&&(t.fillStyle=s,t.fillRect(0,0,e,i)),this.backgroundImage&&t.drawImage(this.backgroundImage,0,0,e,i)}resolveWidth(t,e){const i=e.x-t.x,s=e.y-t.y,n=.55*(Math.sqrt(i*i+s*s)/Math.max(e.t-t.t,1))+(1-.55)*this.lastVelocity;this.lastVelocity=n;const{minWidth:r,maxWidth:a}=this,h=Math.min(Math.max(a/(.85*n+1),r),a),o=(this.lastWidth+h)/2;return this.lastWidth=h,o}drawCurveSegment(t,e,i,s,n,r){t.strokeStyle=n,t.lineWidth=r,t.lineCap="round",t.lineJoin="round",t.beginPath(),t.moveTo(e.x,e.y),t.quadraticCurveTo(i.x,i.y,s.x,s.y),t.stroke()}drawDot(t,e,i){t.fillStyle=i,t.beginPath(),t.arc(e.x,e.y,(this.minWidth+this.maxWidth)/4,0,2*Math.PI),t.fill()}drawStroke(t,e,i){if(this.lastVelocity=0,this.lastWidth=(this.minWidth+this.maxWidth)/2,0===e.length)return;if(1===e.length)return void this.drawDot(t,e[0],i);if(2===e.length){const s=this.resolveWidth(e[0],e[1]);return void this.drawCurveSegment(t,e[0],e[0],e[1],i,s)}let s=e[0];for(let n=1;n<e.length-1;n+=1){const r=e[n],a=e[n+1],h={x:(r.x+a.x)/2,y:(r.y+a.y)/2,t:r.t},o=this.resolveWidth(e[n-1],r);this.drawCurveSegment(t,s,r,h,i,o),s=h}const n=e[e.length-1],r=e[e.length-2],a=this.resolveWidth(r,n);this.drawCurveSegment(t,s,n,n,i,a)}redraw(){const t=this.canvas,e=t?.getContext("2d");if(!t||!e)return;const i=window.devicePixelRatio||1;this.resetCanvas(e,t.width/i,t.height/i);const s=this.getPenColor();for(const t of this.strokes)this.drawStroke(e,t,s)}getPoint(t){const e=t.currentTarget.getBoundingClientRect();return{x:t.clientX-e.left,y:t.clientY-e.top,t:t.timeStamp||Date.now()}}appendPoint(t){const e=this.currentStroke,i=this.canvas?.getContext("2d");if(!e||!i)return;const s=e[e.length-1],n=t.x-s.x,r=t.y-s.y;if(Math.sqrt(n*n+r*r)<1.5)return;e.push(t);const a=this.getPenColor(),h=this.lastMid??s,o={x:(s.x+t.x)/2,y:(s.y+t.y)/2,t:t.t},l=this.resolveWidth(s,t);this.drawCurveSegment(i,h,s,o,a,l),this.lastMid=o}emitChange(){this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{value:this.toDataURL()}}))}isEmpty(){return 0===this.strokes.length&&!this.backgroundImage}clear(){this.strokes=[],this.redoStack=[],this.currentStroke=null,this.lastMid=null,this.backgroundImage=null,this.redraw(),this.updateState()}undo(){if(this.currentStroke)return;if(0===this.strokes.length)return;const t=this.strokes[this.strokes.length-1];this.strokes=this.strokes.slice(0,-1),this.redoStack=[...this.redoStack,t],this.redraw(),this.updateState(),this.emitChange()}redo(){if(this.currentStroke)return;if(0===this.redoStack.length)return;const t=this.redoStack[this.redoStack.length-1];this.redoStack=this.redoStack.slice(0,-1),this.strokes=[...this.strokes,t],this.redraw(),this.updateState(),this.emitChange()}toDataURL(t="image/png",e){return!this.canvas||this.isEmpty()?null:this.canvas.toDataURL(t,e)}fromDataURL(t){const e=new Image;e.crossOrigin="anonymous",e.onload=()=>{this.backgroundImage=e,this.strokes=[],this.redoStack=[],this.redraw(),this.updateState()},e.src=t}getCanvas(){return this.canvas}}customElements.get("db-signature")||customElements.define("db-signature",DbSignature);export{DbSignature};
@@ -4,6 +4,7 @@ declare class DbTestimonial extends HTMLElement {
4
4
  private innerEl?;
5
5
  private quoteEl?;
6
6
  private backgroundEl?;
7
+ private logoWrapEl?;
7
8
  private logoEl?;
8
9
  private footerEl?;
9
10
  private extraEl?;
@@ -1 +1 @@
1
- const t="designbase-wc-testimonial",e=["list","card","logo","image","text"];class DbTestimonial extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["quote","author","role","company","avatar","avatar-initials","rating","max-rating","variant","logo","logo-alt","image","image-alt","tone","align"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}build(){this.innerEl=document.createElement("div"),this.quoteEl=document.createElement("p"),this.quoteEl.className=`${t}__quote`,this.backgroundEl=document.createElement("img"),this.backgroundEl.className=`${t}__background`,this.backgroundEl.hidden=!0,this.logoEl=document.createElement("img"),this.logoEl.className=`${t}__logo`,this.logoEl.hidden=!0,this.footerEl=document.createElement("div"),this.footerEl.className=`${t}__footer`,this.avatarWrapEl=document.createElement("div"),this.avatarWrapEl.className=`${t}__avatar`,this.avatarEl=document.createElement("db-avatar"),this.avatarEl.className=`${t}__avatar-image`,this.avatarWrapEl.append(this.avatarEl);const e=document.createElement("div");e.className=`${t}__meta`,this.authorEl=document.createElement("span"),this.authorEl.className=`${t}__author`,this.roleEl=document.createElement("span"),this.roleEl.className=`${t}__role`,this.ratingEl=document.createElement("db-rating"),this.ratingEl.className=`${t}__rating`,this.ratingEl.setAttribute("display","stars"),this.ratingEl.setAttribute("variant","inline"),this.ratingEl.setAttribute("allow-half",""),this.ratingEl.setAttribute("readonly",""),this.ratingEl.setAttribute("hover-effect","false"),this.ratingEl.setAttribute("color","primary"),this.ratingEl.hidden=!0,e.append(this.authorEl,this.roleEl,this.ratingEl),this.footerEl.append(this.avatarWrapEl,e),this.extraEl=document.createElement("div"),this.extraEl.className=`${t}__extra`,this.extraEl.hidden=!0,this.innerEl.append(this.logoEl,this.quoteEl,this.footerEl,this.extraEl),this.append(this.backgroundEl,this.innerEl)}getVariant(){const t=this.getAttribute("variant")||"card";return e.includes(t)?t:"card"}getAvatarSize(){return"list"===this.getVariant()?"s":"m"}syncExtraContent(){if(!this.extraEl)return;const t=Array.from(this.childNodes).filter(t=>t!==this.innerEl&&(t.nodeType===Node.ELEMENT_NODE||t.nodeType===Node.TEXT_NODE&&t.textContent?.trim()));if(0===t.length)return this.extraEl.hidden=!0,void this.extraEl.replaceChildren();this.extraEl.hidden=!1,this.extraEl.replaceChildren(...t.map(t=>t.cloneNode(!0)))}updateUI(){const e=this.getAttribute("quote")||"",i=this.getAttribute("author")||"",a=this.getAttribute("role")||"",r=this.getAttribute("company")||"",s=this.getAttribute("avatar")||"",l=this.getAttribute("avatar-initials")||"",n=this.getAttribute("rating"),o=Number(this.getAttribute("max-rating")||5),h=null!==n&&""!==n?function clampRating(t,e){if("number"==typeof t&&!Number.isNaN(t))return t<0?0:t>e?e:Math.round(10*t)/10}(Number(n),o):void 0,E=this.getVariant(),u=this.getAttribute("logo")||"",d=this.getAttribute("logo-alt")||"",g=this.getAttribute("image")||"",c=this.getAttribute("image-alt")||"",m=this.getAttribute("tone")||"violet",b=this.getAttribute("align")||"left",v=[t,`${t}--variant-${E}`,`${t}--tone-${m}`,"left"!==b?`${t}--align-${b}`:""].filter(Boolean).join(" ");this.className=v,this.innerEl&&(this.innerEl.className=`${t}__inner`),this.quoteEl&&(this.quoteEl.textContent=e?`“${e}”`:""),this.backgroundEl&&(this.backgroundEl.hidden="image"!==E||!g,g&&(this.backgroundEl.src=g,this.backgroundEl.alt=c)),this.logoEl&&(this.logoEl.hidden="logo"!==E||!u,u&&(this.logoEl.src=u,this.logoEl.alt=d)),this.authorEl&&(this.authorEl.textContent=i);const p=[a,r].filter(Boolean).join(" · ");this.roleEl&&(this.roleEl.textContent=p,this.roleEl.hidden=!p);const A=Boolean(s||l);this.avatarWrapEl&&(this.avatarWrapEl.hidden=!A),this.avatarEl&&A&&(this.avatarEl.setAttribute("size",this.getAvatarSize()),s?this.avatarEl.setAttribute("src",s):this.avatarEl.removeAttribute("src"),l?this.avatarEl.setAttribute("initials",l):this.avatarEl.removeAttribute("initials"),this.avatarEl.setAttribute("alt",`${i} 프로필 이미지`)),this.ratingEl&&("number"==typeof h?(this.ratingEl.hidden=!1,this.ratingEl.setAttribute("value",String(h)),this.ratingEl.setAttribute("max-value",String(o)),this.ratingEl.setAttribute("size","s")):this.ratingEl.hidden=!0),this.syncExtraContent()}}customElements.get("db-testimonial")||customElements.define("db-testimonial",DbTestimonial);export{DbTestimonial};
1
+ const t="designbase-wc-testimonial",e=["list","card","logo","image","text"];class DbTestimonial extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["quote","author","role","company","avatar","avatar-initials","rating","max-rating","variant","logo","logo-alt","image","image-alt","tone","align"]}connectedCallback(){this.built||(this.built=!0,this.build()),this.updateUI()}attributeChangedCallback(){this.built&&this.updateUI()}build(){this.innerEl=document.createElement("div"),this.quoteEl=document.createElement("p"),this.quoteEl.className=`${t}__quote`,this.backgroundEl=document.createElement("div"),this.backgroundEl.className=`${t}__background`,this.backgroundEl.hidden=!0,this.backgroundEl.setAttribute("aria-hidden","true"),this.logoWrapEl=document.createElement("div"),this.logoWrapEl.className=`${t}__logo`,this.logoWrapEl.hidden=!0,this.logoEl=document.createElement("img"),this.logoEl.alt="",this.logoWrapEl.append(this.logoEl),this.footerEl=document.createElement("div"),this.footerEl.className=`${t}__footer`,this.avatarWrapEl=document.createElement("div"),this.avatarWrapEl.className=`${t}__avatar`,this.avatarEl=document.createElement("db-avatar"),this.avatarEl.className=`${t}__avatar-image`,this.avatarWrapEl.append(this.avatarEl);const e=document.createElement("div");e.className=`${t}__meta`,this.authorEl=document.createElement("span"),this.authorEl.className=`${t}__author`,this.roleEl=document.createElement("span"),this.roleEl.className=`${t}__role`,this.ratingEl=document.createElement("db-rating"),this.ratingEl.className=`${t}__rating`,this.ratingEl.setAttribute("display","stars"),this.ratingEl.setAttribute("variant","inline"),this.ratingEl.setAttribute("allow-half",""),this.ratingEl.setAttribute("readonly",""),this.ratingEl.setAttribute("hover-effect","false"),this.ratingEl.setAttribute("color","primary"),this.ratingEl.hidden=!0,e.append(this.authorEl,this.roleEl,this.ratingEl),this.footerEl.append(this.avatarWrapEl,e),this.extraEl=document.createElement("div"),this.extraEl.className=`${t}__extra`,this.extraEl.hidden=!0,this.innerEl.append(this.logoWrapEl,this.quoteEl,this.footerEl,this.extraEl),this.append(this.backgroundEl,this.innerEl)}getVariant(){const t=this.getAttribute("variant")||"card";return e.includes(t)?t:"card"}getAvatarSize(){return"list"===this.getVariant()?"s":"m"}syncExtraContent(){if(!this.extraEl)return;const t=Array.from(this.childNodes).filter(t=>t!==this.innerEl&&t!==this.backgroundEl&&(t.nodeType===Node.ELEMENT_NODE||t.nodeType===Node.TEXT_NODE&&Boolean(t.textContent?.trim())));if(0===t.length)return this.extraEl.hidden=!0,void this.extraEl.replaceChildren();this.extraEl.hidden=!1,this.extraEl.replaceChildren(...t.map(t=>t.cloneNode(!0)))}updateUI(){const e=this.getAttribute("quote")||"",i=this.getAttribute("author")||"",a=this.getAttribute("role")||"",r=this.getAttribute("company")||"",l=this.getAttribute("avatar")||"",s=this.getAttribute("avatar-initials")||"",n=this.getAttribute("rating"),o=Number(this.getAttribute("max-rating")||5),h=null!==n&&""!==n?function clampRating(t,e){if("number"==typeof t&&!Number.isNaN(t))return t<0?0:t>e?e:Math.round(10*t)/10}(Number(n),o):void 0,E=this.getVariant(),u=this.getAttribute("logo")||"",d=this.getAttribute("logo-alt")||"",g=this.getAttribute("image")||"",c=this.getAttribute("image-alt")||"",m=this.getAttribute("tone")||"violet",b=this.getAttribute("align")||"left",v=[t,`${t}--variant-${E}`,`${t}--tone-${m}`,"left"!==b?`${t}--align-${b}`:""].filter(Boolean).join(" ");if(this.className=v,this.innerEl&&(this.innerEl.className=`${t}__inner`),this.quoteEl&&(this.quoteEl.textContent=e?`“${e}”`:""),this.backgroundEl){const t="image"===E&&Boolean(g);this.backgroundEl.hidden=!t,t?(this.backgroundEl.style.backgroundImage=`url("${g}")`,this.backgroundEl.setAttribute("role","img"),this.backgroundEl.setAttribute("aria-label",c||"Testimonial background"),this.backgroundEl.removeAttribute("aria-hidden")):(this.backgroundEl.style.removeProperty("background-image"),this.backgroundEl.removeAttribute("role"),this.backgroundEl.removeAttribute("aria-label"),this.backgroundEl.setAttribute("aria-hidden","true"))}if(this.logoWrapEl&&this.logoEl){const t="logo"===E&&Boolean(u);this.logoWrapEl.hidden=!t,t?(this.logoEl.src=u,this.logoEl.alt=d||"logo"):(this.logoEl.removeAttribute("src"),this.logoEl.alt="")}this.authorEl&&(this.authorEl.textContent=i);const p=[a,r].filter(Boolean).join(" · ");this.roleEl&&(this.roleEl.textContent=p,this.roleEl.hidden=!p);const A=Boolean(l||s);this.avatarWrapEl&&(this.avatarWrapEl.hidden=!A),this.avatarEl&&A&&(this.avatarEl.setAttribute("size",this.getAvatarSize()),l?this.avatarEl.setAttribute("src",l):this.avatarEl.removeAttribute("src"),s?this.avatarEl.setAttribute("initials",s):this.avatarEl.removeAttribute("initials"),this.avatarEl.setAttribute("alt",`${i} 프로필 이미지`)),this.ratingEl&&("number"==typeof h?(this.ratingEl.hidden=!1,this.ratingEl.removeAttribute("hidden"),this.ratingEl.style.removeProperty("display"),this.ratingEl.setAttribute("value",String(h)),this.ratingEl.setAttribute("max-value",String(o)),this.ratingEl.setAttribute("size","s")):(this.ratingEl.hidden=!0,this.ratingEl.setAttribute("hidden",""),this.ratingEl.style.display="none",this.ratingEl.removeAttribute("value"))),this.syncExtraContent()}}customElements.get("db-testimonial")||customElements.define("db-testimonial",DbTestimonial);export{DbTestimonial};
@@ -37,6 +37,7 @@ export { DbMenuItem } from './components/db-menu-item.js';
37
37
  export { DbSearchBar } from './components/db-search-bar.js';
38
38
  export { DbShare, DbSharePlatform, DbShareVariant } from './components/db-share.js';
39
39
  export { DbTopBanner } from './components/db-top-banner.js';
40
+ export { DbCookieBanner } from './components/db-cookie-banner.js';
40
41
  export { DbStat, DbStatChange } from './components/db-stat.js';
41
42
  export { DbImage } from './components/db-image.js';
42
43
  export { DbImagePlaceholder } from './components/db-image-placeholder.js';
@@ -70,6 +71,7 @@ export { DbDatePicker } from './components/db-date-picker.js';
70
71
  export { DbTimePicker } from './components/db-time-picker.js';
71
72
  export { CalendarEventData, CalendarEventType, DbCalendar } from './components/db-calendar.js';
72
73
  export { DbRating } from './components/db-rating.js';
74
+ export { DbSignature, DbSignaturePoint, DbSignatureVariant } from './components/db-signature.js';
73
75
  export { DbCountdown } from './components/db-countdown.js';
74
76
  export { DbMasonry } from './components/db-masonry.js';
75
77
  export { DbCarousel } from './components/db-carousel.js';