@designbasekorea/ui-wc 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/esm/components/db-ai-chat-list.js +1 -1
  3. package/dist/esm/components/db-alert.d.ts +12 -0
  4. package/dist/esm/components/db-alert.js +1 -1
  5. package/dist/esm/components/db-backdrop.js +1 -1
  6. package/dist/esm/components/db-bottom-sheet.js +1 -1
  7. package/dist/esm/components/db-chat-composer.js +1 -1
  8. package/dist/esm/components/db-code-block.js +1 -1
  9. package/dist/esm/components/db-confirm.js +1 -1
  10. package/dist/esm/components/db-context-menu.js +1 -1
  11. package/dist/esm/components/db-cursor-follower.js +1 -1
  12. package/dist/esm/components/db-drawer.d.ts +1 -0
  13. package/dist/esm/components/db-drawer.js +1 -1
  14. package/dist/esm/components/db-dropdown.js +1 -1
  15. package/dist/esm/components/db-lightbox.js +1 -1
  16. package/dist/esm/components/db-modal.js +1 -1
  17. package/dist/esm/components/db-onboarding-modal.js +1 -1
  18. package/dist/esm/components/db-popover.js +1 -1
  19. package/dist/esm/components/db-search-bar.js +1 -1
  20. package/dist/esm/components/db-select.js +1 -1
  21. package/dist/esm/components/db-time-picker.js +1 -1
  22. package/dist/esm/components/db-tooltip.js +1 -1
  23. package/dist/esm/components/db-tutorial.js +1 -1
  24. package/dist/esm/components/db-voice-control.js +1 -1
  25. package/dist/esm/core/focus-trap.js +1 -1
  26. package/dist/esm/core/host-class.js +1 -0
  27. package/dist/esm/core/i18n-copy.js +1 -1
  28. package/dist/esm/core/i18n-en.js +1 -1
  29. package/dist/esm/core/i18n.d.ts +12 -0
  30. package/dist/esm/core/i18n.js +1 -1
  31. package/dist/esm/core/theme-scope.js +1 -0
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.d.ts +25 -0
  34. package/dist/index.esm.js +1 -1
  35. package/dist/react/index.cjs +1 -1
  36. package/dist/react/index.d.ts +4 -0
  37. package/dist/react/index.esm.js +1 -1
  38. package/package.json +2 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # 변경 이력
2
2
 
3
+ ## 0.9.3 - 2026-10-26
4
+
5
+ Pro 템플릿(AI Assistant·Docs) 제작 중 발견한 라이브러리 버그 수정 릴리스입니다.
6
+
7
+ - ChatComposer: 전송·정지·첨부 버튼 접근성 이름과 placeholder 기본값이 `dbUseLocale('en')`을 따르도록 i18n 키(`chatComposer.*`)로 이동. `send-label`이 실제로 전송 버튼에 적용되고, `stop-label`·`attach-label`(React `stopLabel`·`attachLabel`)을 추가. 드롭 오버레이 문구도 번역됩니다.
8
+ - VoiceControl: 시작·완료·취소 라벨과 상태 문구를 i18n 키(`voice.*`)로 이동. `start-label`·`stop-label`·`cancel-label`은 계속 우선합니다.
9
+ - i18n: 영어 로케일에서 `dbText('첨부')`가 "Added"로 나오던 번역 오류를 "Attach"로 수정. "~ 추가" 버튼 문구("Add color" 등)와 첨부 메뉴·음성 입력 문구의 영어 번역도 바로잡음.
10
+ - Select, Dropdown, AiChatList, CodeBlock, ChatComposer, Alert: 렌더할 때 호스트의 `class`를 통째로 덮어써 소비자 클래스(React `className` 포함)가 사라지던 문제 수정. 컴포넌트는 자기 클래스만 추가·제거합니다(`core/host-class`).
11
+ - Alert: 자식 콘텐츠(링크·`code`·텍스트 등)를 본문 아래 슬롯에 렌더합니다. 재렌더해도 유지되고 나중에 추가된 자식도 반영됩니다. React `<Alert>`는 순수 텍스트 자식은 기존처럼 `message`로, 요소가 섞인 자식은 실제 DOM으로 전달합니다.
12
+ - **동작 변경** Alert: 닫기 버튼이 옵트인으로 바뀌었습니다. `closable` 속성(React `closable`)을 줄 때만 표시합니다. 이전처럼 닫기 버튼이 필요하면 `closable`을 추가하세요.
13
+ - 호스트 클래스: React `className`이 나중에 바뀌어 class 속성이 다시 쓰여도 컴포넌트 소유 클래스를 즉시 복원합니다.
14
+ - 회귀 테스트: `npm run test:template-fixes` (`scripts/test-ui-wc-template-fixes.mjs`, 빌드된 dist를 Chromium에서 검증).
15
+
3
16
  ## 0.9.2 - 2026-10-24
4
17
 
5
18
  `@designbasekorea/ui-wc` 컴포넌트 패키지 단독 릴리스입니다. 현재 WC/React 컴포넌트와 스타일·타입 선언을 재빌드하며 examples, blocks, 페이지 템플릿은 배포 대상에 포함하지 않습니다.
@@ -1 +1 @@
1
- import{createDbIcon as t,isDbIconName as e}from"./db-icons.js";class DbAiChatList extends HTMLElement{constructor(){super(...arguments),this._items=[]}static get observedAttributes(){return["selected-id","new-label","title-label"]}get items(){return this._items}set items(t){this._items=Array.isArray(t)?t:[],this.render()}get selectedId(){return this.getAttribute("selected-id")||""}set selectedId(t){t?this.setAttribute("selected-id",t):this.removeAttribute("selected-id")}connectedCallback(){if(!this._items.length&&this.hasAttribute("items"))try{this._items=JSON.parse(this.getAttribute("items")||"[]")}catch{this._items=[]}this.render()}attributeChangedCallback(){this.render()}render(){this.className="designbase-wc-ai-chat-list",this.replaceChildren();const s=document.createElement("button");s.type="button",s.className="designbase-wc-ai-chat-list__new";const i=document.createElement("span");i.className="designbase-wc-ai-chat-list__new-icon",i.append(t("plus",18));const n=document.createElement("span");if(n.textContent=this.getAttribute("new-label")||"새 대화",s.append(i,n),s.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-new",{bubbles:!0,composed:!0}))}),this.append(s),!this._items.length)return;const a=new Map,c=this.getAttribute("title-label")||"최근 항목";for(const t of this._items){const e=t.group||c;a.has(e)||a.set(e,[]),a.get(e).push(t)}const d=this.selectedId,l=document.createElement("div");l.className="designbase-wc-ai-chat-list__scroll";for(const[s,i]of a){const n=document.createElement("div");n.className="designbase-wc-ai-chat-list__group";const a=document.createElement("div");a.className="designbase-wc-ai-chat-list__group-title",a.textContent=s,n.append(a);for(const s of i){const i=document.createElement("button");if(i.type="button",i.className=["designbase-wc-ai-chat-list__item",s.id===d&&"designbase-wc-ai-chat-list__item--selected"].filter(Boolean).join(" "),s.icon&&e(s.icon)){const e=document.createElement("span");e.className="designbase-wc-ai-chat-list__item-icon",e.append(t(s.icon,16)),i.append(e)}const a=document.createElement("span");a.className="designbase-wc-ai-chat-list__item-title",a.textContent=s.title,i.append(a),i.addEventListener("click",()=>{this.selectedId=s.id,this.dispatchEvent(new CustomEvent("db-select",{detail:{id:s.id,title:s.title},bubbles:!0,composed:!0}))}),n.append(i)}l.append(n)}this.append(l)}}customElements.get("db-ai-chat-list")||customElements.define("db-ai-chat-list",DbAiChatList);export{DbAiChatList};
1
+ import{setHostClasses as t}from"../core/host-class.js";import{createDbIcon as e,isDbIconName as s}from"./db-icons.js";class DbAiChatList extends HTMLElement{constructor(){super(...arguments),this._items=[]}static get observedAttributes(){return["selected-id","new-label","title-label"]}get items(){return this._items}set items(t){this._items=Array.isArray(t)?t:[],this.render()}get selectedId(){return this.getAttribute("selected-id")||""}set selectedId(t){t?this.setAttribute("selected-id",t):this.removeAttribute("selected-id")}connectedCallback(){if(!this._items.length&&this.hasAttribute("items"))try{this._items=JSON.parse(this.getAttribute("items")||"[]")}catch{this._items=[]}this.render()}attributeChangedCallback(){this.render()}render(){t(this,["designbase-wc-ai-chat-list"]),this.replaceChildren();const i=document.createElement("button");i.type="button",i.className="designbase-wc-ai-chat-list__new";const n=document.createElement("span");n.className="designbase-wc-ai-chat-list__new-icon",n.append(e("plus",18));const a=document.createElement("span");if(a.textContent=this.getAttribute("new-label")||"새 대화",i.append(n,a),i.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-new",{bubbles:!0,composed:!0}))}),this.append(i),!this._items.length)return;const c=new Map,d=this.getAttribute("title-label")||"최근 항목";for(const t of this._items){const e=t.group||d;c.has(e)||c.set(e,[]),c.get(e).push(t)}const l=this.selectedId,o=document.createElement("div");o.className="designbase-wc-ai-chat-list__scroll";for(const[t,i]of c){const n=document.createElement("div");n.className="designbase-wc-ai-chat-list__group";const a=document.createElement("div");a.className="designbase-wc-ai-chat-list__group-title",a.textContent=t,n.append(a);for(const t of i){const i=document.createElement("button");if(i.type="button",i.className=["designbase-wc-ai-chat-list__item",t.id===l&&"designbase-wc-ai-chat-list__item--selected"].filter(Boolean).join(" "),t.icon&&s(t.icon)){const s=document.createElement("span");s.className="designbase-wc-ai-chat-list__item-icon",s.append(e(t.icon,16)),i.append(s)}const a=document.createElement("span");a.className="designbase-wc-ai-chat-list__item-title",a.textContent=t.title,i.append(a),i.addEventListener("click",()=>{this.selectedId=t.id,this.dispatchEvent(new CustomEvent("db-select",{detail:{id:t.id,title:t.title},bubbles:!0,composed:!0}))}),n.append(i)}o.append(n)}this.append(o)}}customElements.get("db-ai-chat-list")||customElements.define("db-ai-chat-list",DbAiChatList);export{DbAiChatList};
@@ -8,8 +8,20 @@ interface DbAlertAction {
8
8
  }
9
9
  declare class DbAlert extends HTMLElement {
10
10
  static get observedAttributes(): string[];
11
+ /** 소비자가 넣은 자식(링크·코드 등)을 담아 두는 내부 컨테이너. 렌더 사이에 유지된다. */
12
+ private slotEl?;
13
+ private observer?;
14
+ /** 슬롯 내부 변경(React 가 래퍼 안 자식을 바꿀 때)을 감지해 빈 슬롯 여부를 다시 계산한다 */
15
+ private slotObserver?;
16
+ private renderedSlotted;
11
17
  connectedCallback(): void;
18
+ disconnectedCallback(): void;
12
19
  attributeChangedCallback(): void;
20
+ private getSlot;
21
+ /** 호스트에 직접 붙은 소비자 노드를 슬롯으로 옮긴다. 공백 텍스트는 버린다. */
22
+ private moveChildrenToSlot;
23
+ private adoptChildren;
24
+ private hasSlotted;
13
25
  private getIconName;
14
26
  private parseActionButtons;
15
27
  private render;
@@ -1 +1 @@
1
- import{dbText as t}from"../core/i18n.js";import"./db-button.js";import{createDbIcon as e}from"./db-icons.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{ALERT_VARIANTS as s,ALERT_SIZES as i}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a="designbase-wc-alert";class DbAlert extends HTMLElement{static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const o=n(this.getAttribute("variant"),s,"default"),r=n(this.getAttribute("size"),i,"m"),c="false"!==this.getAttribute("show-icon"),l="false"!==this.getAttribute("closable"),d=this.getAttribute("title")?.trim()||"",m=this.getAttribute("message")?.trim()||"",b=this.getAttribute("action-label"),u=this.getAttribute("action-variant")||"tertiary",h=this.parseActionButtons(),p=Boolean(m),g=Boolean(d),v=g&&!p||!g&&p,A=h.length>0?h:b?[{label:b,variant:u}]:[];this.className=[a,`${a}--${o}`,`${a}--${r}`,c&&`${a}--with-icon`,l&&`${a}--closable`,v&&`${a}--text-single`,A.length>0&&`${a}--has-actions`].filter(Boolean).join(" "),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite"),this.querySelector(`.${a}__content`)?.remove(),this.querySelector(`.${a}__actions`)?.remove(),Array.from(this.childNodes).forEach(t=>{t.nodeType===Node.TEXT_NODE&&t.remove()});const _=document.createElement("div");if(_.className=`${a}__content`,c){const t=document.createElement("div");t.className=`${a}__icon`,t.append(e(this.getIconName(o),"s"===r?16:"l"===r?24:20)),_.append(t)}const f=document.createElement("div");if(f.className=`${a}__body`,g){const t=document.createElement("div");t.className=`${a}__title`,t.textContent=d,f.append(t)}if(p){const t=document.createElement("div");t.className=`${a}__message`,t.textContent=m,f.append(t)}if(_.append(f),A.length>0){const t=document.createElement("div");t.className=`${a}__actions`;const e=document.createElement("div");e.className=`${a}__action-buttons`,A.forEach((t,n)=>{const s=document.createElement("db-button");s.setAttribute("variant",t.variant||"tertiary"),s.setAttribute("size",t.size||r),s.textContent=t.label,t.disabled&&s.setAttribute("disabled",""),s.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:n,label:t.label}}))}),e.append(s)}),t.append(e),_.append(t)}if(l){const n=document.createElement("button");n.type="button",n.className=`${a}__close`,n.setAttribute("aria-label",t("알림 닫기")),n.append(e("close",20)),n.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),_.append(n)}this.replaceChildren(_)}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
1
+ import{dbText as t}from"../core/i18n.js";import{setHostClasses as e}from"../core/host-class.js";import"./db-button.js";import{createDbIcon as s}from"./db-icons.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{ALERT_VARIANTS as n,ALERT_SIZES as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-alert";class DbAlert extends HTMLElement{constructor(){super(...arguments),this.renderedSlotted=!1}static get observedAttributes(){return["title","message","variant","size","show-icon","closable","action-label","action-variant","action-buttons"]}connectedCallback(){this.render(),this.observer??(this.observer=new MutationObserver(()=>this.adoptChildren())),this.observer.observe(this,{childList:!0}),this.slotObserver??(this.slotObserver=new MutationObserver(()=>{this.hasSlotted()!==this.renderedSlotted&&this.render()})),this.slotObserver.observe(this.getSlot(),{childList:!0,subtree:!0,characterData:!0})}disconnectedCallback(){this.observer?.disconnect(),this.slotObserver?.disconnect()}attributeChangedCallback(){this.isConnected&&this.render()}getSlot(){return this.slotEl||(this.slotEl=document.createElement("div"),this.slotEl.className=`${r}__slot`,this.slotEl.setAttribute("data-wc-internal","")),this.slotEl}moveChildrenToSlot(){const t=this.getSlot();let e=!1;for(const s of Array.from(this.childNodes))s instanceof Element&&s.hasAttribute("data-wc-internal")||s.nodeType!==Node.COMMENT_NODE&&(s.nodeType!==Node.TEXT_NODE||s.textContent?.trim()?(t.append(s),e=!0):s.remove());return e}adoptChildren(){this.moveChildrenToSlot()&&this.render()}hasSlotted(){const hasContent=t=>t.nodeType===Node.TEXT_NODE?Boolean(t.textContent?.trim()):t instanceof Element&&(!t.hasAttribute("data-db-children")||Array.from(t.childNodes).some(hasContent));return Boolean(this.slotEl&&Array.from(this.slotEl.childNodes).some(hasContent))}getIconName(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}parseActionButtons(){const t=this.getAttribute("action-buttons");if(!t)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}render(){const a=i(this.getAttribute("variant"),n,"default"),l=i(this.getAttribute("size"),o,"m"),c="false"!==this.getAttribute("show-icon"),d=this.hasAttribute("closable")&&"false"!==this.getAttribute("closable"),h=this.getAttribute("title")?.trim()||"",b=this.getAttribute("message")?.trim()||"",m=this.getAttribute("action-label"),u=this.getAttribute("action-variant")||"tertiary",p=this.parseActionButtons(),v=Boolean(b),E=Boolean(h);this.moveChildrenToSlot();const A=this.hasSlotted();this.renderedSlotted=A;const g=1===Number(E)+Number(v)+Number(A),f=p.length>0?p:m?[{label:m,variant:u}]:[];e(this,[r,`${r}--${a}`,`${r}--${l}`,c&&`${r}--with-icon`,d&&`${r}--closable`,g&&`${r}--text-single`,f.length>0&&`${r}--has-actions`]),this.setAttribute("role","alert"),this.setAttribute("aria-live","polite");const N=this.getSlot(),_=document.createElement("div");if(_.className=`${r}__content`,_.setAttribute("data-wc-internal",""),c){const t=document.createElement("div");t.className=`${r}__icon`,t.append(s(this.getIconName(a),"s"===l?16:"l"===l?24:20)),_.append(t)}const C=document.createElement("div");if(C.className=`${r}__body`,E){const t=document.createElement("div");t.className=`${r}__title`,t.textContent=h,C.append(t)}if(v){const t=document.createElement("div");t.className=`${r}__message`,t.textContent=b,C.append(t)}if(A?C.append(N):N.remove(),_.append(C),f.length>0){const t=document.createElement("div");t.className=`${r}__actions`,t.setAttribute("data-wc-internal","");const e=document.createElement("div");e.className=`${r}__action-buttons`,f.forEach((t,s)=>{const i=document.createElement("db-button");i.setAttribute("variant",t.variant||"tertiary"),i.setAttribute("size",t.size||l),i.textContent=t.label,t.disabled&&i.setAttribute("disabled",""),i.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0,detail:{index:s,label:t.label}}))}),e.append(i)}),t.append(e),_.append(t)}if(d){const e=document.createElement("button");e.type="button",e.className=`${r}__close`,e.setAttribute("aria-label",t("알림 닫기")),e.append(s("close",20)),e.addEventListener("click",()=>{this.hidden=!0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}),_.append(e)}this.observer?.disconnect(),this.replaceChildren(_),this.isConnected&&this.observer?.observe(this,{childList:!0})}}customElements.get("db-alert")||customElements.define("db-alert",DbAlert);export{DbAlert};
@@ -1 +1 @@
1
- import{lockScroll as t,unlockScroll as e}from"../core/scroll-lock.js";const s=["fade","slide","zoom","none"];class DbBackdrop extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.keyHandler=null,this.handlePortalClick=t=>{t.target===this.portal&&"true"!==this.getAttribute("disable-backdrop-click")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))}}static get observedAttributes(){return["open","blur","opacity","blur-amount","animation","animation-duration","z-index","background-color","disable-backdrop-click","disable-escape-key-down"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}connectedCallback(){this.style.display="contents",this.syncOpenState()}disconnectedCallback(){this.detachListeners(),this.portal?.remove(),this.portal=void 0,this.releaseScrollLock()}attributeChangedCallback(){this.isConnected&&this.syncOpenState()}isOpen(){return this.open}syncOpenState(){this.isOpen()?this.render():(this.releaseScrollLock(),this.detachListeners(),this.portal?.remove())}collectChildren(){return Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"))}attachListeners(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))},document.addEventListener("keydown",this.keyHandler))}detachListeners(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}render(){if(!this.isOpen())return void this.syncOpenState();const e=this.hasAttribute("blur"),i=this.getAttribute("opacity")||"0.5",r=this.getAttribute("blur-amount")||"4",o=s.includes(this.getAttribute("animation")||"fade")&&this.getAttribute("animation")||"fade",a=this.getAttribute("animation-duration")||"300",n=this.getAttribute("z-index")||"1000",l=this.getAttribute("background-color"),c=this.collectChildren();this.scrollLocked||(t(),this.scrollLocked=!0),this.attachListeners(),this.portal||(this.portal=document.createElement("div"),this.portal.setAttribute("data-wc-internal",""),this.portal.addEventListener("click",this.handlePortalClick)),this.portal.className=["designbase-wc-backdrop",`designbase-wc-backdrop--${o}`,"designbase-wc-backdrop--open",e?"designbase-wc-backdrop--blur":""].filter(Boolean).join(" "),this.portal.setAttribute("role","presentation"),this.portal.setAttribute("aria-hidden","false"),this.portal.style.setProperty("--backdrop-opacity",i),this.portal.style.setProperty("--backdrop-blur-amount",`${r}px`),this.portal.style.setProperty("--backdrop-animation-duration",`${a}ms`),this.portal.style.setProperty("--backdrop-z-index",n),l?this.portal.style.backgroundColor=l:this.portal.style.removeProperty("background-color"),this.portal.replaceChildren(...c),this.portal.isConnected||document.body.append(this.portal)}releaseScrollLock(){this.scrollLocked&&(this.scrollLocked=!1,e())}}customElements.get("db-backdrop")||customElements.define("db-backdrop",DbBackdrop);export{DbBackdrop};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{lockScroll as e,unlockScroll as s}from"../core/scroll-lock.js";const i=["fade","slide","zoom","none"];class DbBackdrop extends HTMLElement{constructor(){super(...arguments),this.scrollLocked=!1,this.keyHandler=null,this.handlePortalClick=t=>{t.target===this.portal&&"true"!==this.getAttribute("disable-backdrop-click")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))}}static get observedAttributes(){return["open","blur","opacity","blur-amount","animation","animation-duration","z-index","background-color","disable-backdrop-click","disable-escape-key-down"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}connectedCallback(){this.style.display="contents",this.syncOpenState()}disconnectedCallback(){this.detachListeners(),this.portal?.remove(),this.portal=void 0,this.releaseScrollLock()}attributeChangedCallback(){this.isConnected&&this.syncOpenState()}isOpen(){return this.open}syncOpenState(){this.isOpen()?this.render():(this.releaseScrollLock(),this.detachListeners(),this.portal?.remove())}collectChildren(){return Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal"))}attachListeners(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&(this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})))},document.addEventListener("keydown",this.keyHandler))}detachListeners(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}render(){if(!this.isOpen())return void this.syncOpenState();const s=this.hasAttribute("blur"),r=this.getAttribute("opacity")||"0.5",o=this.getAttribute("blur-amount")||"4",a=i.includes(this.getAttribute("animation")||"fade")&&this.getAttribute("animation")||"fade",n=this.getAttribute("animation-duration")||"300",l=this.getAttribute("z-index")||"1000",c=this.getAttribute("background-color"),d=this.collectChildren();this.scrollLocked||(e(),this.scrollLocked=!0),this.attachListeners(),this.portal||(this.portal=document.createElement("div"),this.portal.setAttribute("data-wc-internal",""),this.portal.addEventListener("click",this.handlePortalClick)),this.portal.className=["designbase-wc-backdrop",`designbase-wc-backdrop--${a}`,"designbase-wc-backdrop--open",s?"designbase-wc-backdrop--blur":""].filter(Boolean).join(" "),this.portal.setAttribute("role","presentation"),this.portal.setAttribute("aria-hidden","false"),this.portal.style.setProperty("--backdrop-opacity",r),this.portal.style.setProperty("--backdrop-blur-amount",`${o}px`),this.portal.style.setProperty("--backdrop-animation-duration",`${n}ms`),this.portal.style.setProperty("--backdrop-z-index",l),c?this.portal.style.backgroundColor=c:this.portal.style.removeProperty("background-color"),this.portal.replaceChildren(...d),this.portal.isConnected||(t(this,this.portal),document.body.append(this.portal))}releaseScrollLock(){this.scrollLocked&&(this.scrollLocked=!1,s())}}customElements.get("db-backdrop")||customElements.define("db-backdrop",DbBackdrop);export{DbBackdrop};
@@ -1 +1 @@
1
- import{dbText as t}from"../core/i18n.js";import{createDbIcon as e}from"./db-icons.js";import{createFocusTrap as s}from"../core/focus-trap.js";import{unlockScroll as i,lockScroll as r}from"../core/scroll-lock.js";import{BOTTOM_SHEET_VARIANTS as o,BOTTOM_SHEET_ANIMATIONS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={s:40,m:60,l:80,full:100};function resolveHeightPercent(t){if(!t)return a.m;const e=a[t];if(e)return Math.min(100,Math.max(20,e));const s=Number(t);return Number.isFinite(s)?Math.min(100,Math.max(20,s)):a.m}class DbBottomSheet extends HTMLElement{constructor(){super(...arguments),this.sheetHeightPercent=a.m,this.scrollLocked=!1,this.isDragging=!1,this.isVisible=!1,this.isMounted=!1,this.keyHandler=null,this.dragState={active:!1,pointerId:-1,startY:0,startHeight:a.m,lastY:0,lastTime:0},this.handlePointerDown=t=>{"true"!==this.getAttribute("disable-drag")&&0===t.button&&(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),this.dragState={active:!0,pointerId:t.pointerId,startY:t.clientY,startHeight:this.sheetHeightPercent,lastY:t.clientY,lastTime:Date.now()},this.isDragging=!0,this.syncActiveClasses())},this.handlePointerMove=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;t.preventDefault(),e.lastY=t.clientY,e.lastTime=Date.now();const s=window.innerHeight||1,i=(e.startY-t.clientY)/s*100,r=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheetHeightPercent=Math.min(r,Math.max(20,e.startHeight+i)),this.applySheetDimensions()},this.handlePointerUp=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;const s=t.currentTarget;s.hasPointerCapture(t.pointerId)&&s.releasePointerCapture(t.pointerId),this.finishDrag()}}static get observedAttributes(){return["open","title","subtitle","height","max-height","variant","disable-backdrop-click","disable-escape-key-down","disable-drag","show-close-button","animation","animation-duration","z-index","show-backdrop","backdrop-blur","backdrop-opacity","sticky-header","sticky-footer"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}shouldMountPortal(){return this.isOpenRequested()||this.isMounted}connectedCallback(){this.style.display="contents",this.childObserver=new MutationObserver(()=>{this.isOpenRequested()&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),this.childObserver=void 0,this.clearTimers(),this.detachEscape(),this.root?.remove(),this.root=void 0,this.teardownOverlay()}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,i())}attributeChangedCallback(t){this.isConnected&&("open"!==t?("height"===t&&this.isOpenRequested()&&(this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height"))),this.shouldMountPortal()&&(this.render(),this.isMounted&&this.syncActiveClasses())):this.syncOpenState())}isOpenRequested(){return this.open}clearTimers(){this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}scheduleEnterAnimation(){this.enterFrame&&cancelAnimationFrame(this.enterFrame),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isOpenRequested()&&this.sheet&&(this.sheet.offsetHeight,this.isVisible=!0,this.syncActiveClasses())})})}getMaxHeightLimit(t){const e=Number(this.getAttribute("max-height")||0),s=t>=100;return Math.min(100,Math.max(t,e||(s?100:90)))}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}collectSlotted(t){const e=Array.from(this.querySelectorAll(`:scope > [slot="${t}"]`));if(e.length)return e;if("header"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");return t?Array.from(t.children):[]}if("footer"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");return t?Array.from(t.children):[]}return[]}collectContentNodes(){const t=Array.from(this.children).filter(t=>{const e=t.getAttribute("slot");return!e||"default"===e});return t.length?t:this.contentEl?Array.from(this.contentEl.children):[]}finishDrag(){const t=this.dragState;if(!t.active)return;t.active=!1,this.isDragging=!1;const e=t.lastY-t.startY,s=e/Math.max(1,Date.now()-t.lastTime),i=window.innerHeight||1,r=(t.startY-t.lastY)/i*100,o=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height"))),n=Math.min(o,Math.max(20,t.startHeight+r));n<=22||e>72||s>.6?this.close():(this.sheetHeightPercent=n,this.applySheetDimensions(),this.syncActiveClasses())}syncOpenState(){const t=this.isOpenRequested(),e=Number(this.getAttribute("animation-duration")||400);if(this.clearTimers(),t)return this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height")),this.render(),this.isMounted=!0,this.isVisible=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&document.body.append(this.root),this.scheduleEnterAnimation(),this.scrollLocked||(r(),this.scrollLocked=!0),this.sheet&&!this.focusTrap&&(this.focusTrap=s(this.sheet),requestAnimationFrame(()=>this.focusTrap?.activate())),void this.attachEscape();this.isVisible=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.detachContentToHost(),this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.teardownOverlay(),this.detachEscape()},e),this.detachEscape()}syncActiveClasses(){if(!this.sheet)return;const t=resolveHeightPercent(this.getAttribute("height")),e=this.getAttribute("variant")||"default",s=this.getAttribute("animation")||"slide",i=o.includes(e)?e:"default",r=n.includes(s)?s:"slide",a="false"!==this.getAttribute("show-backdrop"),h=this.hasAttribute("sticky-header"),c=this.hasAttribute("sticky-footer");this.sheet.className=["designbase-wc-bottom-sheet",`designbase-wc-bottom-sheet--${i}`,`designbase-wc-bottom-sheet--${r}`,this.isMounted&&this.isVisible&&"designbase-wc-bottom-sheet--open",this.isDragging&&"designbase-wc-bottom-sheet--dragging",h&&"designbase-wc-bottom-sheet--sticky-header",c&&"designbase-wc-bottom-sheet--sticky-footer",!a&&"designbase-wc-bottom-sheet--no-backdrop",(t>=100||this.sheetHeightPercent>=100)&&"designbase-wc-bottom-sheet--full"].filter(Boolean).join(" "),this.backdrop?.classList.toggle("designbase-wc-backdrop--open",this.isMounted&&this.isVisible)}applySheetDimensions(){if(!this.sheet)return;const t=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheet.style.height=`${this.sheetHeightPercent}vh`,this.sheet.style.maxHeight=`${t}vh`}detachContentToHost(){this.contentEl&&Array.from(this.contentEl.children).forEach(t=>this.append(t));const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");t&&Array.from(t.children).forEach(t=>{"bottom-sheet-title"!==t.id&&"bottom-sheet-subtitle"!==t.id&&this.append(t)});const e=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");e&&Array.from(e.children).forEach(t=>this.append(t))}render(){if(!this.shouldMountPortal())return;const s=this.getAttribute("title"),i=this.getAttribute("subtitle"),r="false"!==this.getAttribute("show-close-button"),o="false"!==this.getAttribute("show-backdrop"),n=this.hasAttribute("backdrop-blur"),a=this.getAttribute("backdrop-opacity")||"0.5",h=this.getAttribute("animation-duration")||"400",c=this.getAttribute("z-index")||"1000",d=this.hasAttribute("sticky-header"),l=this.hasAttribute("sticky-footer"),b=this.collectSlotted("header"),m=this.collectSlotted("footer"),u=this.collectContentNodes();if(this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.backdrop=document.createElement("div"),this.backdrop.className="designbase-wc-backdrop designbase-wc-backdrop--bottom-sheet",this.backdrop.setAttribute("role","presentation"),this.backdrop.addEventListener("click",t=>{t.target===this.backdrop&&"true"!==this.getAttribute("disable-backdrop-click")&&this.close()}),this.sheet=document.createElement("div"),this.sheet.setAttribute("role","dialog"),this.sheet.setAttribute("aria-modal","true"),this.grabBar=document.createElement("div"),this.grabBar.className="designbase-wc-bottom-sheet__grab-bar",this.grabBar.addEventListener("pointerdown",this.handlePointerDown),this.grabBar.addEventListener("pointermove",this.handlePointerMove),this.grabBar.addEventListener("pointerup",this.handlePointerUp),this.grabBar.addEventListener("pointercancel",this.handlePointerUp),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-bottom-sheet__content"),this.root.replaceChildren(),o&&this.backdrop&&(this.backdrop.className=["designbase-wc-backdrop","designbase-wc-backdrop--bottom-sheet",n&&"designbase-wc-backdrop--blur"].filter(Boolean).join(" "),this.backdrop.style.setProperty("--backdrop-opacity",a),this.backdrop.style.setProperty("--bottom-sheet-animation-duration",`${h}ms`),this.backdrop.style.zIndex=c,this.backdrop.setAttribute("aria-hidden",String(!this.isOpenRequested())),this.root.append(this.backdrop)),!this.sheet||!this.grabBar||!this.contentEl)return;this.sheet.style.zIndex=String(Number(c)+1),this.sheet.style.setProperty("--bottom-sheet-animation-duration",`${h}ms`),this.applySheetDimensions(),s?this.sheet.setAttribute("aria-labelledby","bottom-sheet-title"):this.sheet.removeAttribute("aria-labelledby"),i?this.sheet.setAttribute("aria-describedby","bottom-sheet-subtitle"):this.sheet.removeAttribute("aria-describedby"),this.sheet.replaceChildren();const p="true"===this.getAttribute("disable-drag");if(this.grabBar.className=["designbase-wc-bottom-sheet__grab-bar",!p&&"designbase-wc-bottom-sheet__grab-bar--draggable"].filter(Boolean).join(" "),this.grabBar.replaceChildren(),!p){const t=document.createElement("div");t.className="designbase-wc-bottom-sheet__handle",t.setAttribute("aria-hidden","true"),this.grabBar.append(t)}this.sheet.append(this.grabBar);if(Boolean(s||i||b.length||r)){const o=document.createElement("div");o.className=["designbase-wc-bottom-sheet__header",d&&"designbase-wc-bottom-sheet__header--sticky"].filter(Boolean).join(" ");const n=document.createElement("div");if(n.className="designbase-wc-bottom-sheet__header-main",b.length)b.forEach(t=>n.append(t));else{if(s){const t=document.createElement("h2");t.id="bottom-sheet-title",t.className="designbase-wc-bottom-sheet__title",t.textContent=s,n.append(t)}if(i){const t=document.createElement("p");t.id="bottom-sheet-subtitle",t.className="designbase-wc-bottom-sheet__subtitle",t.textContent=i,n.append(t)}}if(o.append(n),r){const s=document.createElement("button");s.type="button",s.className="designbase-wc-bottom-sheet__close-button",s.setAttribute("aria-label",t("닫기")),s.append(e("close",20)),s.addEventListener("click",()=>this.close()),o.append(s)}this.sheet.append(o)}if(this.contentEl.replaceChildren(...u),this.sheet.append(this.contentEl),m.length){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__footer",l&&"designbase-wc-bottom-sheet__footer--sticky"].filter(Boolean).join(" "),m.forEach(e=>t.append(e)),this.sheet.append(t)}this.root.append(this.sheet),this.isMounted&&!this.root.isConnected&&document.body.append(this.root),this.syncActiveClasses()}}customElements.get("db-bottom-sheet")||customElements.define("db-bottom-sheet",DbBottomSheet);export{DbBottomSheet};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as e}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{createFocusTrap as i}from"../core/focus-trap.js";import{unlockScroll as r,lockScroll as o}from"../core/scroll-lock.js";import{BOTTOM_SHEET_VARIANTS as n,BOTTOM_SHEET_ANIMATIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a={s:40,m:60,l:80,full:100};function resolveHeightPercent(t){if(!t)return a.m;const e=a[t];if(e)return Math.min(100,Math.max(20,e));const s=Number(t);return Number.isFinite(s)?Math.min(100,Math.max(20,s)):a.m}class DbBottomSheet extends HTMLElement{constructor(){super(...arguments),this.sheetHeightPercent=a.m,this.scrollLocked=!1,this.isDragging=!1,this.isVisible=!1,this.isMounted=!1,this.keyHandler=null,this.dragState={active:!1,pointerId:-1,startY:0,startHeight:a.m,lastY:0,lastTime:0},this.handlePointerDown=t=>{"true"!==this.getAttribute("disable-drag")&&0===t.button&&(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),this.dragState={active:!0,pointerId:t.pointerId,startY:t.clientY,startHeight:this.sheetHeightPercent,lastY:t.clientY,lastTime:Date.now()},this.isDragging=!0,this.syncActiveClasses())},this.handlePointerMove=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;t.preventDefault(),e.lastY=t.clientY,e.lastTime=Date.now();const s=window.innerHeight||1,i=(e.startY-t.clientY)/s*100,r=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheetHeightPercent=Math.min(r,Math.max(20,e.startHeight+i)),this.applySheetDimensions()},this.handlePointerUp=t=>{const e=this.dragState;if(!e.active||t.pointerId!==e.pointerId)return;const s=t.currentTarget;s.hasPointerCapture(t.pointerId)&&s.releasePointerCapture(t.pointerId),this.finishDrag()}}static get observedAttributes(){return["open","title","subtitle","height","max-height","variant","disable-backdrop-click","disable-escape-key-down","disable-drag","show-close-button","animation","animation-duration","z-index","show-backdrop","backdrop-blur","backdrop-opacity","sticky-header","sticky-footer"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open",""):this.removeAttribute("open")}shouldMountPortal(){return this.isOpenRequested()||this.isMounted}connectedCallback(){this.style.display="contents",this.childObserver=new MutationObserver(()=>{this.isOpenRequested()&&this.render()}),this.childObserver.observe(this,{childList:!0}),this.syncOpenState()}disconnectedCallback(){this.childObserver?.disconnect(),this.childObserver=void 0,this.clearTimers(),this.detachEscape(),this.root?.remove(),this.root=void 0,this.teardownOverlay()}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,r())}attributeChangedCallback(t){this.isConnected&&("open"!==t?("height"===t&&this.isOpenRequested()&&(this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height"))),this.shouldMountPortal()&&(this.render(),this.isMounted&&this.syncActiveClasses())):this.syncOpenState())}isOpenRequested(){return this.open}clearTimers(){this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}scheduleEnterAnimation(){this.enterFrame&&cancelAnimationFrame(this.enterFrame),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isOpenRequested()&&this.sheet&&(this.sheet.offsetHeight,this.isVisible=!0,this.syncActiveClasses())})})}getMaxHeightLimit(t){const e=Number(this.getAttribute("max-height")||0),s=t>=100;return Math.min(100,Math.max(t,e||(s?100:90)))}close(){this.open=!1,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"true"!==this.getAttribute("disable-escape-key-down")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}collectSlotted(t){const e=Array.from(this.querySelectorAll(`:scope > [slot="${t}"]`));if(e.length)return e;if("header"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");return t?Array.from(t.children):[]}if("footer"===t){const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");return t?Array.from(t.children):[]}return[]}collectContentNodes(){const t=Array.from(this.children).filter(t=>{const e=t.getAttribute("slot");return!e||"default"===e});return t.length?t:this.contentEl?Array.from(this.contentEl.children):[]}finishDrag(){const t=this.dragState;if(!t.active)return;t.active=!1,this.isDragging=!1;const e=t.lastY-t.startY,s=e/Math.max(1,Date.now()-t.lastTime),i=window.innerHeight||1,r=(t.startY-t.lastY)/i*100,o=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height"))),n=Math.min(o,Math.max(20,t.startHeight+r));n<=22||e>72||s>.6?this.close():(this.sheetHeightPercent=n,this.applySheetDimensions(),this.syncActiveClasses())}syncOpenState(){const e=this.isOpenRequested(),s=Number(this.getAttribute("animation-duration")||400);if(this.clearTimers(),e)return this.sheetHeightPercent=resolveHeightPercent(this.getAttribute("height")),this.render(),this.isMounted=!0,this.isVisible=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root)),this.scheduleEnterAnimation(),this.scrollLocked||(o(),this.scrollLocked=!0),this.sheet&&!this.focusTrap&&(this.focusTrap=i(this.sheet),requestAnimationFrame(()=>this.focusTrap?.activate())),void this.attachEscape();this.isVisible=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.detachContentToHost(),this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.teardownOverlay(),this.detachEscape()},s),this.detachEscape()}syncActiveClasses(){if(!this.sheet)return;const t=resolveHeightPercent(this.getAttribute("height")),e=this.getAttribute("variant")||"default",s=this.getAttribute("animation")||"slide",i=n.includes(e)?e:"default",r=h.includes(s)?s:"slide",o="false"!==this.getAttribute("show-backdrop"),a=this.hasAttribute("sticky-header"),c=this.hasAttribute("sticky-footer");this.sheet.className=["designbase-wc-bottom-sheet",`designbase-wc-bottom-sheet--${i}`,`designbase-wc-bottom-sheet--${r}`,this.isMounted&&this.isVisible&&"designbase-wc-bottom-sheet--open",this.isDragging&&"designbase-wc-bottom-sheet--dragging",a&&"designbase-wc-bottom-sheet--sticky-header",c&&"designbase-wc-bottom-sheet--sticky-footer",!o&&"designbase-wc-bottom-sheet--no-backdrop",(t>=100||this.sheetHeightPercent>=100)&&"designbase-wc-bottom-sheet--full"].filter(Boolean).join(" "),this.backdrop?.classList.toggle("designbase-wc-backdrop--open",this.isMounted&&this.isVisible)}applySheetDimensions(){if(!this.sheet)return;const t=this.getMaxHeightLimit(resolveHeightPercent(this.getAttribute("height")));this.sheet.style.height=`${this.sheetHeightPercent}vh`,this.sheet.style.maxHeight=`${t}vh`}detachContentToHost(){this.contentEl&&Array.from(this.contentEl.children).forEach(t=>this.append(t));const t=this.sheet?.querySelector(".designbase-wc-bottom-sheet__header-main");t&&Array.from(t.children).forEach(t=>{"bottom-sheet-title"!==t.id&&"bottom-sheet-subtitle"!==t.id&&this.append(t)});const e=this.sheet?.querySelector(".designbase-wc-bottom-sheet__footer");e&&Array.from(e.children).forEach(t=>this.append(t))}render(){if(!this.shouldMountPortal())return;const i=this.getAttribute("title"),r=this.getAttribute("subtitle"),o="false"!==this.getAttribute("show-close-button"),n="false"!==this.getAttribute("show-backdrop"),h=this.hasAttribute("backdrop-blur"),a=this.getAttribute("backdrop-opacity")||"0.5",c=this.getAttribute("animation-duration")||"400",d=this.getAttribute("z-index")||"1000",l=this.hasAttribute("sticky-header"),b=this.hasAttribute("sticky-footer"),m=this.collectSlotted("header"),u=this.collectSlotted("footer"),p=this.collectContentNodes();if(this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.backdrop=document.createElement("div"),this.backdrop.className="designbase-wc-backdrop designbase-wc-backdrop--bottom-sheet",this.backdrop.setAttribute("role","presentation"),this.backdrop.addEventListener("click",t=>{t.target===this.backdrop&&"true"!==this.getAttribute("disable-backdrop-click")&&this.close()}),this.sheet=document.createElement("div"),this.sheet.setAttribute("role","dialog"),this.sheet.setAttribute("aria-modal","true"),this.grabBar=document.createElement("div"),this.grabBar.className="designbase-wc-bottom-sheet__grab-bar",this.grabBar.addEventListener("pointerdown",this.handlePointerDown),this.grabBar.addEventListener("pointermove",this.handlePointerMove),this.grabBar.addEventListener("pointerup",this.handlePointerUp),this.grabBar.addEventListener("pointercancel",this.handlePointerUp),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-bottom-sheet__content"),this.root.replaceChildren(),n&&this.backdrop&&(this.backdrop.className=["designbase-wc-backdrop","designbase-wc-backdrop--bottom-sheet",h&&"designbase-wc-backdrop--blur"].filter(Boolean).join(" "),this.backdrop.style.setProperty("--backdrop-opacity",a),this.backdrop.style.setProperty("--bottom-sheet-animation-duration",`${c}ms`),this.backdrop.style.zIndex=d,this.backdrop.setAttribute("aria-hidden",String(!this.isOpenRequested())),this.root.append(this.backdrop)),!this.sheet||!this.grabBar||!this.contentEl)return;this.sheet.style.zIndex=String(Number(d)+1),this.sheet.style.setProperty("--bottom-sheet-animation-duration",`${c}ms`),this.applySheetDimensions(),i?this.sheet.setAttribute("aria-labelledby","bottom-sheet-title"):this.sheet.removeAttribute("aria-labelledby"),r?this.sheet.setAttribute("aria-describedby","bottom-sheet-subtitle"):this.sheet.removeAttribute("aria-describedby"),this.sheet.replaceChildren();const g="true"===this.getAttribute("disable-drag");if(this.grabBar.className=["designbase-wc-bottom-sheet__grab-bar",!g&&"designbase-wc-bottom-sheet__grab-bar--draggable"].filter(Boolean).join(" "),this.grabBar.replaceChildren(),!g){const t=document.createElement("div");t.className="designbase-wc-bottom-sheet__handle",t.setAttribute("aria-hidden","true"),this.grabBar.append(t)}this.sheet.append(this.grabBar);if(Boolean(i||r||m.length||o)){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__header",l&&"designbase-wc-bottom-sheet__header--sticky"].filter(Boolean).join(" ");const n=document.createElement("div");if(n.className="designbase-wc-bottom-sheet__header-main",m.length)m.forEach(t=>n.append(t));else{if(i){const t=document.createElement("h2");t.id="bottom-sheet-title",t.className="designbase-wc-bottom-sheet__title",t.textContent=i,n.append(t)}if(r){const t=document.createElement("p");t.id="bottom-sheet-subtitle",t.className="designbase-wc-bottom-sheet__subtitle",t.textContent=r,n.append(t)}}if(t.append(n),o){const i=document.createElement("button");i.type="button",i.className="designbase-wc-bottom-sheet__close-button",i.setAttribute("aria-label",e("닫기")),i.append(s("close",20)),i.addEventListener("click",()=>this.close()),t.append(i)}this.sheet.append(t)}if(this.contentEl.replaceChildren(...p),this.sheet.append(this.contentEl),u.length){const t=document.createElement("div");t.className=["designbase-wc-bottom-sheet__footer",b&&"designbase-wc-bottom-sheet__footer--sticky"].filter(Boolean).join(" "),u.forEach(e=>t.append(e)),this.sheet.append(t)}this.root.append(this.sheet),this.isMounted&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root)),this.syncActiveClasses()}}customElements.get("db-bottom-sheet")||customElements.define("db-bottom-sheet",DbBottomSheet);export{DbBottomSheet};
@@ -1 +1 @@
1
- import{dbText as t,dbFormat as e}from"../core/i18n.js";import{isDbIconName as s,createDbIcon as i}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";import"./db-voice-control.js";const DEFAULT_ATTACH_OPTIONS=()=>[{id:"image",label:t("사진·이미지"),icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:t("동영상"),icon:"video",accept:"video/*",multiple:!0},{id:"file",label:t("문서·파일"),icon:"file-new",accept:"",multiple:!0},{id:"camera",label:t("카메라 촬영"),icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const a={image:"gallery",video:"video",file:"file-new"};let n=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=DEFAULT_ATTACH_OPTIONS(),this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>"Escape"===t.key&&this.voiceActive?(t.preventDefault(),void this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:"cancel"},bubbles:!0,composed:!0}))):"Escape"===t.key&&this.attachMenuOpen?(t.preventDefault(),void this.closeAttachMenu()):void("Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())),this.handleSendClick=()=>{this.disabled||this.voiceActive||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label","voice-state","voice-message","voice-disabled"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:DEFAULT_ATTACH_OPTIONS(),this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==t?this.sync():this.renderSendButton()}}build(){this.built=!0,this.className="designbase-wc-chat-composer",this.replaceChildren();const e=document.createElement("div");e.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const s=document.createElement("div");s.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),s.append(this.field);const i=document.createElement("div");i.className="designbase-wc-chat-composer__toolbar";const a=document.createElement("div");a.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label",t("첨부")),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",a.append(this.attachWrap,this.toolsEl);const n=document.createElement("div");n.className="designbase-wc-chat-composer__trailing",this.micBtn=document.createElement("db-voice-control"),this.micBtn.setAttribute("compact","");for(const t of["start","stop","cancel"])this.micBtn.addEventListener(`db-${t}`,e=>{e.stopPropagation(),this.disabled||this.streaming||this.hasAttribute("voice-disabled")||this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:t},bubbles:!0,composed:!0}))});this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),n.append(this.micBtn,this.sendBtn),i.append(a,n),e.append(this.attachmentsEl,s,i),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true"),this.dropOverlay.innerHTML='<span class="designbase-wc-chat-composer__drop-label">파일을 놓으면 첨부됩니다</span>',this.append(e,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=this.getAttribute("placeholder")||"메시지를 입력하세요…",this.field.disabled=this.disabled,this.field.readOnly=this.voiceActive;const t=this.getAttribute("max-length");t?this.field.maxLength=Number(t):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.micBtn.setAttribute("state",this.getAttribute("voice-state")||"idle"),this.micBtn.setAttribute("message",this.getAttribute("voice-message")||""),this.micBtn.toggleAttribute("disabled",this.disabled||this.streaming||this.hasAttribute("voice-disabled")),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const t of this._tools){const e=document.createElement("db-chip");e.setAttribute("label",t.label),e.setAttribute("size","s"),e.setAttribute("clickable",""),e.setAttribute("variant",t.active?"primary":"default"),t.icon&&s(t.icon)&&e.setAttribute("start-icon",t.icon),e.setAttribute("aria-pressed",String(!!t.active)),e.addEventListener("db-click",()=>{this.disabled||(t.active=!t.active,e.setAttribute("variant",t.active?"primary":"default"),e.setAttribute("aria-pressed",String(!!t.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:t.id,active:!!t.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(e)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const t of this._attachOptions){const e=document.createElement("button");e.type="button",e.className="designbase-wc-chat-composer__attach-item",e.setAttribute("role","menuitem");const a=document.createElement("span");a.className="designbase-wc-chat-composer__attach-item-icon",t.icon&&s(t.icon)&&a.append(i(t.icon,18));const n=document.createElement("span");n.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=t.label,n.append(h),t.description){const e=document.createElement("span");e.className="designbase-wc-chat-composer__attach-item-desc",e.textContent=t.description,n.append(e)}e.append(a,n),e.addEventListener("click",()=>this.chooseAttachOption(t)),this.attachMenu.append(e)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const s=document.createElement("div");s.className="designbase-wc-chat-composer__thumb";const a=document.createElement("img");a.src=t.preview,a.alt=t.name;const n=document.createElement("button");n.type="button",n.className="designbase-wc-chat-composer__thumb-remove",n.setAttribute("aria-label",e("{0} 제거",[t.name])),n.append(i("close",12)),n.addEventListener("click",()=>this.removeAttachment(t.id)),s.append(a,n),this.attachmentsEl.append(s);continue}const s=document.createElement("db-chip");s.setAttribute("label",t.name),s.setAttribute("size","s"),s.setAttribute("variant","neutral"),s.setAttribute("deletable",""),s.setAttribute("start-icon",a[t.kind]),s.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(s)}this.syncSendState()}renderSendButton(){const t=this.streaming;this.sendBtn.setAttribute("variant",t?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",t?"stop":"send"),this.sendBtn.setAttribute("aria-label",t?"생성 중지":"전송"),this.syncSendState()}get voiceActive(){return this.hasAttribute("voice")&&["starting","listening","stopping"].includes(this.getAttribute("voice-state")||"idle")}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||this.voiceActive||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${n+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming||this.voiceActive)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${n+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
1
+ import{labelFrom as t,dbText as e,dbFormat as s}from"../core/i18n.js";import{setHostClasses as i}from"../core/host-class.js";import{isDbIconName as a,createDbIcon as n}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";import"./db-voice-control.js";const DEFAULT_ATTACH_OPTIONS=()=>[{id:"image",label:e("사진·이미지"),icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:e("동영상"),icon:"video",accept:"video/*",multiple:!0},{id:"file",label:e("문서·파일"),icon:"file-new",accept:"",multiple:!0},{id:"camera",label:e("카메라 촬영"),icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const h={image:"gallery",video:"video",file:"file-new"};let c=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=DEFAULT_ATTACH_OPTIONS(),this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>"Escape"===t.key&&this.voiceActive?(t.preventDefault(),void this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:"cancel"},bubbles:!0,composed:!0}))):"Escape"===t.key&&this.attachMenuOpen?(t.preventDefault(),void this.closeAttachMenu()):void("Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())),this.handleSendClick=()=>{this.disabled||this.voiceActive||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label","stop-label","attach-label","voice-state","voice-message","voice-disabled"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:DEFAULT_ATTACH_OPTIONS(),this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(e){if(this.built){if("value"===e){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==e&&"send-label"!==e&&"stop-label"!==e?"attach-label"!==e?this.sync():this.attachBtn.setAttribute("aria-label",t(this,"attach-label","chatComposer.attach")):this.renderSendButton()}}build(){this.built=!0,i(this,["designbase-wc-chat-composer"]),this.replaceChildren();const s=document.createElement("div");s.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const a=document.createElement("div");a.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),a.append(this.field);const n=document.createElement("div");n.className="designbase-wc-chat-composer__toolbar";const h=document.createElement("div");h.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label",t(this,"attach-label","chatComposer.attach")),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",h.append(this.attachWrap,this.toolsEl);const c=document.createElement("div");c.className="designbase-wc-chat-composer__trailing",this.micBtn=document.createElement("db-voice-control"),this.micBtn.setAttribute("compact","");for(const t of["start","stop","cancel"])this.micBtn.addEventListener(`db-${t}`,e=>{e.stopPropagation(),this.disabled||this.streaming||this.hasAttribute("voice-disabled")||this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:t},bubbles:!0,composed:!0}))});this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),c.append(this.micBtn,this.sendBtn),n.append(h,c),s.append(this.attachmentsEl,a,n),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className="designbase-wc-chat-composer__drop-label",r.textContent=e("파일을 놓으면 첨부됩니다"),this.dropOverlay.append(r),this.append(s,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=t(this,"placeholder","chatComposer.placeholder"),this.field.disabled=this.disabled,this.field.readOnly=this.voiceActive;const e=this.getAttribute("max-length");e?this.field.maxLength=Number(e):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.micBtn.setAttribute("state",this.getAttribute("voice-state")||"idle"),this.micBtn.setAttribute("message",this.getAttribute("voice-message")||""),this.micBtn.toggleAttribute("disabled",this.disabled||this.streaming||this.hasAttribute("voice-disabled")),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const t of this._tools){const e=document.createElement("db-chip");e.setAttribute("label",t.label),e.setAttribute("size","s"),e.setAttribute("clickable",""),e.setAttribute("variant",t.active?"primary":"default"),t.icon&&a(t.icon)&&e.setAttribute("start-icon",t.icon),e.setAttribute("aria-pressed",String(!!t.active)),e.addEventListener("db-click",()=>{this.disabled||(t.active=!t.active,e.setAttribute("variant",t.active?"primary":"default"),e.setAttribute("aria-pressed",String(!!t.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:t.id,active:!!t.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(e)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const t of this._attachOptions){const e=document.createElement("button");e.type="button",e.className="designbase-wc-chat-composer__attach-item",e.setAttribute("role","menuitem");const s=document.createElement("span");s.className="designbase-wc-chat-composer__attach-item-icon",t.icon&&a(t.icon)&&s.append(n(t.icon,18));const i=document.createElement("span");i.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=t.label,i.append(h),t.description){const e=document.createElement("span");e.className="designbase-wc-chat-composer__attach-item-desc",e.textContent=t.description,i.append(e)}e.append(s,i),e.addEventListener("click",()=>this.chooseAttachOption(t)),this.attachMenu.append(e)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const e=document.createElement("div");e.className="designbase-wc-chat-composer__thumb";const i=document.createElement("img");i.src=t.preview,i.alt=t.name;const a=document.createElement("button");a.type="button",a.className="designbase-wc-chat-composer__thumb-remove",a.setAttribute("aria-label",s("{0} 제거",[t.name])),a.append(n("close",12)),a.addEventListener("click",()=>this.removeAttachment(t.id)),e.append(i,a),this.attachmentsEl.append(e);continue}const e=document.createElement("db-chip");e.setAttribute("label",t.name),e.setAttribute("size","s"),e.setAttribute("variant","neutral"),e.setAttribute("deletable",""),e.setAttribute("start-icon",h[t.kind]),e.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(e)}this.syncSendState()}renderSendButton(){const e=this.streaming;this.sendBtn.setAttribute("variant",e?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",e?"stop":"send"),this.sendBtn.setAttribute("aria-label",e?t(this,"stop-label","chatComposer.stop"):t(this,"send-label","chatComposer.send")),this.syncSendState()}get voiceActive(){return this.hasAttribute("voice")&&["starting","listening","stopping"].includes(this.getAttribute("voice-state")||"idle")}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||this.voiceActive||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${c+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming||this.voiceActive)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${c+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
@@ -1 +1 @@
1
- import{dbFormat as e}from"../core/i18n.js";import{ensureHighlightReady as t,highlightCodeSync as i,formatLanguageLabel as s}from"./highlight-code.js";const o="designbase-wc-code-block";class DbCodeBlock extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.renderToken=0,this.internalActiveId="",this.copied=!1,this.editedCodes={},this.handleSegmentChange=e=>{const t=e,i=t.detail?.value;i&&(this.hasAttribute("active-id")||(this.internalActiveId=i),this.dispatchEvent(new CustomEvent("db-active-id-change",{detail:{activeId:i},bubbles:!0,composed:!0})),this.render())}}static get observedAttributes(){return["items","code","language","default-active-id","active-id","show-language","highlight","theme","show-copy","copied-label","copy-label","min-height","max-height","overflow","editable"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.internalActiveId=this.getAttribute("default-active-id")||this.getResolvedItems()[0]?.id||""),this.render(),t().then(()=>{this.isConnected&&this.built&&this.render()}),this.addEventListener("db-change",this.handleSegmentChange)}disconnectedCallback(){this.removeEventListener("db-change",this.handleSegmentChange),this.copyTimeout&&window.clearTimeout(this.copyTimeout)}attributeChangedCallback(e){if(this.built)if("active-id"!==e){if("items"===e||"code"===e||"language"===e){const e=this.getResolvedItems();e.find(e=>e.id===this.getActiveId())||(this.internalActiveId=e[0]?.id||"")}this.render()}else this.render()}getBool(e,t=!0){if(!this.hasAttribute(e))return t;const i=this.getAttribute(e);return""===i||"true"===i}getResolvedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length>0)return t}catch{}const t=this.getAttribute("code");if(t){const e=this.getAttribute("language")||"tsx";return[{id:"default",label:e,code:t,language:e}]}return[]}getActiveId(){return this.getAttribute("active-id")||this.internalActiveId}getActiveItem(){const e=this.getResolvedItems();return e.find(e=>e.id===this.getActiveId())||e[0]}toCssSize(e){if(e)return/^\d+$/.test(e)?`${e}px`:e}async handleCopy(){const e=this.getActiveItem(),t=this.getBool("editable",!1),i=(t?this.editedCodes[e?.id??""]??e?.code:e?.code)?.trim();if(i){try{await navigator.clipboard.writeText(i)}catch{const e=document.createElement("textarea");e.value=i,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select(),document.execCommand("copy"),e.remove()}this.copied=!0,this.render(),this.copyTimeout&&window.clearTimeout(this.copyTimeout),this.copyTimeout=window.setTimeout(()=>{this.copied=!1,this.render()},1600)}}render(){const e=++this.renderToken;this.renderNow(e)}renderNow(t){const n=this.getActiveItem();if(!n)return void this.replaceChildren();const d=this.getResolvedItems(),c=d.length>1,a=this.getAttribute("language")||"tsx",r=n.language??a,l=this.getBool("show-language",!0),h=this.getBool("highlight",!0),u=this.getAttribute("theme")||"auto",m=this.getBool("show-copy",!0),b=this.getAttribute("copied-label")||"복사됨",g=this.getAttribute("copy-label")||"복사",p=this.getAttribute("overflow")||"scroll-x",v=this.getBool("editable",!1),A=v?this.editedCodes[n.id]??n.code:n.code,y=A.trim();let f=null;if(h&&A)try{f=i(A,r)}catch{f=null}if(t!==this.renderToken)return;const C=this.toCssSize(this.getAttribute("min-height")),E=this.toCssSize(this.getAttribute("max-height"));C?this.style.setProperty("--db-code-block-min-height",C):this.style.removeProperty("--db-code-block-min-height"),E?this.style.setProperty("--db-code-block-max-height",E):this.style.removeProperty("--db-code-block-max-height"),this.className=[o,`${o}--overflow-${p}`,"auto"!==u&&`${o}--theme-${u}`,v&&`${o}--editable`].filter(Boolean).join(" ");const _=document.createElement("div");_.className=`${o}__toolbar`;const x=document.createElement("div");if(x.className=`${o}__toolbar-left`,c){const e=document.createElement("db-segment-control");e.setAttribute("size","s"),e.setAttribute("options",JSON.stringify(d.map(e=>({value:e.id,label:e.label})))),e.setAttribute("value",this.getActiveId()),x.append(e)}if(l){const e=document.createElement("span");e.className=`${o}__language`,e.textContent=s(r),x.append(e)}if(_.append(x),m){const e=document.createElement("db-button");e.setAttribute("type","button"),e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("start-icon",this.copied?"done":"copy"),e.textContent=this.copied?b:g,e.addEventListener("db-click",()=>this.handleCopy()),_.append(e)}const $=document.createElement("div");if($.className=`${o}__body`,c&&n.description){const e=document.createElement("p");e.className=`${o}__caption`,e.textContent=n.description,$.append(e)}if(v){void 0===this.editedCodes[n.id]&&(this.editedCodes[n.id]=n.code);const t=document.createElement("div");t.className=`${o}__editor`;const d=document.createElement("pre");d.className=`${o}__pre ${o}__pre--mirror`,d.setAttribute("aria-hidden","true");const c=document.createElement("code");c.className=`${o}__code language-${r}`,f?c.innerHTML=f:c.textContent=A,d.append(c);const a=document.createElement("textarea");a.className=`${o}__textarea`,a.value=A,a.spellcheck=!1,a.setAttribute("autocapitalize","off"),a.setAttribute("autocorrect","off"),a.setAttribute("aria-label",e("{0} 코드 편집",[s(r)])),a.addEventListener("input",()=>{this.editedCodes[n.id]=a.value;const e=h&&a.value?i(a.value,r):null;e?c.innerHTML=e:c.textContent=a.value,this.dispatchEvent(new CustomEvent("db-code-change",{detail:{code:a.value,itemId:n.id},bubbles:!0,composed:!0}))}),t.append(d,a),$.append(t)}else{const e=document.createElement("pre");e.className=`${o}__pre`;const t=document.createElement("code");t.className=`${o}__code language-${r}`,f?t.innerHTML=f:t.textContent=y,e.append(t),$.append(e)}this.replaceChildren(_,$)}}customElements.get("db-code-block")||customElements.define("db-code-block",DbCodeBlock);export{DbCodeBlock};
1
+ import{setHostClasses as e}from"../core/host-class.js";import{dbFormat as t}from"../core/i18n.js";import{ensureHighlightReady as i,highlightCodeSync as s,formatLanguageLabel as o}from"./highlight-code.js";const n="designbase-wc-code-block";class DbCodeBlock extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.renderToken=0,this.internalActiveId="",this.copied=!1,this.editedCodes={},this.handleSegmentChange=e=>{const t=e,i=t.detail?.value;i&&(this.hasAttribute("active-id")||(this.internalActiveId=i),this.dispatchEvent(new CustomEvent("db-active-id-change",{detail:{activeId:i},bubbles:!0,composed:!0})),this.render())}}static get observedAttributes(){return["items","code","language","default-active-id","active-id","show-language","highlight","theme","show-copy","copied-label","copy-label","min-height","max-height","overflow","editable"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.internalActiveId=this.getAttribute("default-active-id")||this.getResolvedItems()[0]?.id||""),this.render(),i().then(()=>{this.isConnected&&this.built&&this.render()}),this.addEventListener("db-change",this.handleSegmentChange)}disconnectedCallback(){this.removeEventListener("db-change",this.handleSegmentChange),this.copyTimeout&&window.clearTimeout(this.copyTimeout)}attributeChangedCallback(e){if(this.built)if("active-id"!==e){if("items"===e||"code"===e||"language"===e){const e=this.getResolvedItems();e.find(e=>e.id===this.getActiveId())||(this.internalActiveId=e[0]?.id||"")}this.render()}else this.render()}getBool(e,t=!0){if(!this.hasAttribute(e))return t;const i=this.getAttribute(e);return""===i||"true"===i}getResolvedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t)&&t.length>0)return t}catch{}const t=this.getAttribute("code");if(t){const e=this.getAttribute("language")||"tsx";return[{id:"default",label:e,code:t,language:e}]}return[]}getActiveId(){return this.getAttribute("active-id")||this.internalActiveId}getActiveItem(){const e=this.getResolvedItems();return e.find(e=>e.id===this.getActiveId())||e[0]}toCssSize(e){if(e)return/^\d+$/.test(e)?`${e}px`:e}async handleCopy(){const e=this.getActiveItem(),t=this.getBool("editable",!1),i=(t?this.editedCodes[e?.id??""]??e?.code:e?.code)?.trim();if(i){try{await navigator.clipboard.writeText(i)}catch{const e=document.createElement("textarea");e.value=i,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select(),document.execCommand("copy"),e.remove()}this.copied=!0,this.render(),this.copyTimeout&&window.clearTimeout(this.copyTimeout),this.copyTimeout=window.setTimeout(()=>{this.copied=!1,this.render()},1600)}}render(){const e=++this.renderToken;this.renderNow(e)}renderNow(i){const d=this.getActiveItem();if(!d)return void this.replaceChildren();const c=this.getResolvedItems(),a=c.length>1,r=this.getAttribute("language")||"tsx",l=d.language??r,h=this.getBool("show-language",!0),u=this.getBool("highlight",!0),m=this.getAttribute("theme")||"auto",b=this.getBool("show-copy",!0),g=this.getAttribute("copied-label")||"복사됨",p=this.getAttribute("copy-label")||"복사",v=this.getAttribute("overflow")||"scroll-x",A=this.getBool("editable",!1),y=A?this.editedCodes[d.id]??d.code:d.code,f=y.trim();let C=null;if(u&&y)try{C=s(y,l)}catch{C=null}if(i!==this.renderToken)return;const E=this.toCssSize(this.getAttribute("min-height")),_=this.toCssSize(this.getAttribute("max-height"));E?this.style.setProperty("--db-code-block-min-height",E):this.style.removeProperty("--db-code-block-min-height"),_?this.style.setProperty("--db-code-block-max-height",_):this.style.removeProperty("--db-code-block-max-height"),e(this,[n,`${n}--overflow-${v}`,"auto"!==m&&`${n}--theme-${m}`,A&&`${n}--editable`]);const x=document.createElement("div");x.className=`${n}__toolbar`;const $=document.createElement("div");if($.className=`${n}__toolbar-left`,a){const e=document.createElement("db-segment-control");e.setAttribute("size","s"),e.setAttribute("options",JSON.stringify(c.map(e=>({value:e.id,label:e.label})))),e.setAttribute("value",this.getActiveId()),$.append(e)}if(h){const e=document.createElement("span");e.className=`${n}__language`,e.textContent=o(l),$.append(e)}if(x.append($),b){const e=document.createElement("db-button");e.setAttribute("type","button"),e.setAttribute("variant","tertiary"),e.setAttribute("size","s"),e.setAttribute("start-icon",this.copied?"done":"copy"),e.textContent=this.copied?g:p,e.addEventListener("db-click",()=>this.handleCopy()),x.append(e)}const w=document.createElement("div");if(w.className=`${n}__body`,a&&d.description){const e=document.createElement("p");e.className=`${n}__caption`,e.textContent=d.description,w.append(e)}if(A){void 0===this.editedCodes[d.id]&&(this.editedCodes[d.id]=d.code);const e=document.createElement("div");e.className=`${n}__editor`;const i=document.createElement("pre");i.className=`${n}__pre ${n}__pre--mirror`,i.setAttribute("aria-hidden","true");const c=document.createElement("code");c.className=`${n}__code language-${l}`,C?c.innerHTML=C:c.textContent=y,i.append(c);const a=document.createElement("textarea");a.className=`${n}__textarea`,a.value=y,a.spellcheck=!1,a.setAttribute("autocapitalize","off"),a.setAttribute("autocorrect","off"),a.setAttribute("aria-label",t("{0} 코드 편집",[o(l)])),a.addEventListener("input",()=>{this.editedCodes[d.id]=a.value;const e=u&&a.value?s(a.value,l):null;e?c.innerHTML=e:c.textContent=a.value,this.dispatchEvent(new CustomEvent("db-code-change",{detail:{code:a.value,itemId:d.id},bubbles:!0,composed:!0}))}),e.append(i,a),w.append(e)}else{const e=document.createElement("pre");e.className=`${n}__pre`;const t=document.createElement("code");t.className=`${n}__code language-${l}`,C?t.innerHTML=C:t.textContent=f,e.append(t),w.append(e)}this.replaceChildren(x,w)}}customElements.get("db-code-block")||customElements.define("db-code-block",DbCodeBlock);export{DbCodeBlock};
@@ -1 +1 @@
1
- import{createDbIcon as e}from"./db-icons.js";import{createFocusTrap as t}from"../core/focus-trap.js";import{unlockScroll as i,lockScroll as s}from"../core/scroll-lock.js";import{coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{CONFIRM_VARIANTS as o,CONFIRM_SIZES as c}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbConfirm extends HTMLElement{constructor(){super(...arguments),this.root=null,this.keyHandler=null,this.scrollLocked=!1}static get observedAttributes(){return["open","title","message","confirm-text","cancel-text","confirm-variant","variant","size","show-icon","initial-focus","confirm-disabled","cancel-disabled","close-on-escape","close-on-backdrop"]}connectedCallback(){this.render()}disconnectedCallback(){this.detachEscape(),this.teardownOverlay(),this.root?.remove(),this.root=null}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,i())}attributeChangedCallback(){this.render()}isOpen(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}attachEscape(){this.keyHandler||(this.keyHandler=e=>{"Escape"===e.key&&"false"!==this.getAttribute("close-on-escape")&&this.dispatchCancel()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}dispatchCancel(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-cancel",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}dispatchConfirm(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-confirm",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}iconForVariant(e){return"success"===e?"award":"warning"===e?"bell-active":"danger"===e?"cloud-close":"bulb"}iconSize(e){return"s"===e?20:"l"===e?32:24}render(){if(this.root?.remove(),this.root=null,this.detachEscape(),this.teardownOverlay(),!this.isOpen())return void this.replaceChildren();this.scrollLocked||(s(),this.scrollLocked=!0),this.attachEscape();const i=this.getAttribute("title")||"",a=this.getAttribute("message")||this.textContent?.trim()||"",r=this.getAttribute("confirm-text")||"확인",d=this.getAttribute("cancel-text")||"취소",l=this.getAttribute("confirm-variant")||"primary",m=n(this.getAttribute("variant"),o,"info"),b=n(this.getAttribute("size"),c,"s"),u="false"!==this.getAttribute("show-icon"),h=this.getAttribute("initial-focus")||"confirm",p="true"===this.getAttribute("confirm-disabled"),f="true"===this.getAttribute("cancel-disabled"),v=document.createElement("div");v.className="designbase-wc-confirm__overlay",v.setAttribute("role","dialog"),v.setAttribute("aria-modal","true"),i&&v.setAttribute("aria-labelledby","confirm-title"),v.setAttribute("aria-describedby","confirm-content"),v.addEventListener("click",e=>{e.target===v&&"false"!==this.getAttribute("close-on-backdrop")&&this.dispatchCancel()});const g=document.createElement("div");g.className=["designbase-wc-confirm__modal",`designbase-wc-confirm__modal--${m}`,`designbase-wc-confirm__modal--${b}`,!u&&"designbase-wc-confirm__modal--no-icon"].filter(Boolean).join(" ");const E=document.createElement("div");if(E.className=["designbase-wc-confirm__header",!u&&"designbase-wc-confirm__header--no-icon"].filter(Boolean).join(" "),u){const t=document.createElement("div");t.className="designbase-wc-confirm__icon",t.append(e(this.iconForVariant(m),this.iconSize(b))),E.append(t)}const A=document.createElement("div");if(A.className="designbase-wc-confirm__title-area",i){const e=document.createElement("h2");e.id="confirm-title",e.className="designbase-wc-confirm__title",e.textContent=i,A.append(e)}E.append(A),g.append(E);const w=document.createElement("div");w.id="confirm-content",w.className="designbase-wc-confirm__content",w.textContent=a,g.append(w);const k=document.createElement("div");k.className="designbase-wc-confirm__footer";const _=document.createElement("db-button");_.setAttribute("variant","tertiary"),_.setAttribute("full-width",""),_.textContent=d,f&&_.setAttribute("disabled",""),_.addEventListener("db-click",()=>this.dispatchCancel());const C=document.createElement("db-button");C.setAttribute("variant",l),C.setAttribute("full-width",""),C.textContent=r,p&&C.setAttribute("disabled",""),C.addEventListener("db-click",()=>this.dispatchConfirm()),k.append(_,C),g.append(k),v.append(g),document.body.append(v),this.root=v,this.focusTrap=t(g,{initialFocus:()=>"cancel"===h?_:C}),requestAnimationFrame(()=>this.focusTrap?.activate())}}customElements.get("db-confirm")||customElements.define("db-confirm",DbConfirm);export{DbConfirm};
1
+ import{inheritThemeScope as e}from"../core/theme-scope.js";import{createDbIcon as t}from"./db-icons.js";import{createFocusTrap as i}from"../core/focus-trap.js";import{unlockScroll as s,lockScroll as n}from"../core/scroll-lock.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{CONFIRM_VARIANTS as c,CONFIRM_SIZES as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbConfirm extends HTMLElement{constructor(){super(...arguments),this.root=null,this.keyHandler=null,this.scrollLocked=!1}static get observedAttributes(){return["open","title","message","confirm-text","cancel-text","confirm-variant","variant","size","show-icon","initial-focus","confirm-disabled","cancel-disabled","close-on-escape","close-on-backdrop"]}connectedCallback(){this.render()}disconnectedCallback(){this.detachEscape(),this.teardownOverlay(),this.root?.remove(),this.root=null}teardownOverlay(){this.focusTrap?.deactivate(),this.focusTrap=void 0,this.scrollLocked&&(this.scrollLocked=!1,s())}attributeChangedCallback(){this.render()}isOpen(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}attachEscape(){this.keyHandler||(this.keyHandler=e=>{"Escape"===e.key&&"false"!==this.getAttribute("close-on-escape")&&this.dispatchCancel()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}dispatchCancel(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-cancel",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}dispatchConfirm(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-confirm",{bubbles:!0,composed:!0})),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}iconForVariant(e){return"success"===e?"award":"warning"===e?"bell-active":"danger"===e?"cloud-close":"bulb"}iconSize(e){return"s"===e?20:"l"===e?32:24}render(){if(this.root?.remove(),this.root=null,this.detachEscape(),this.teardownOverlay(),!this.isOpen())return void this.replaceChildren();this.scrollLocked||(n(),this.scrollLocked=!0),this.attachEscape();const s=this.getAttribute("title")||"",r=this.getAttribute("message")||this.textContent?.trim()||"",d=this.getAttribute("confirm-text")||"확인",l=this.getAttribute("cancel-text")||"취소",m=this.getAttribute("confirm-variant")||"primary",b=o(this.getAttribute("variant"),c,"info"),u=o(this.getAttribute("size"),a,"s"),h="false"!==this.getAttribute("show-icon"),p=this.getAttribute("initial-focus")||"confirm",f="true"===this.getAttribute("confirm-disabled"),v="true"===this.getAttribute("cancel-disabled"),g=document.createElement("div");g.className="designbase-wc-confirm__overlay",g.setAttribute("role","dialog"),g.setAttribute("aria-modal","true"),s&&g.setAttribute("aria-labelledby","confirm-title"),g.setAttribute("aria-describedby","confirm-content"),g.addEventListener("click",e=>{e.target===g&&"false"!==this.getAttribute("close-on-backdrop")&&this.dispatchCancel()});const E=document.createElement("div");E.className=["designbase-wc-confirm__modal",`designbase-wc-confirm__modal--${b}`,`designbase-wc-confirm__modal--${u}`,!h&&"designbase-wc-confirm__modal--no-icon"].filter(Boolean).join(" ");const A=document.createElement("div");if(A.className=["designbase-wc-confirm__header",!h&&"designbase-wc-confirm__header--no-icon"].filter(Boolean).join(" "),h){const e=document.createElement("div");e.className="designbase-wc-confirm__icon",e.append(t(this.iconForVariant(b),this.iconSize(u))),A.append(e)}const w=document.createElement("div");if(w.className="designbase-wc-confirm__title-area",s){const e=document.createElement("h2");e.id="confirm-title",e.className="designbase-wc-confirm__title",e.textContent=s,w.append(e)}A.append(w),E.append(A);const k=document.createElement("div");k.id="confirm-content",k.className="designbase-wc-confirm__content",k.textContent=r,E.append(k);const _=document.createElement("div");_.className="designbase-wc-confirm__footer";const C=document.createElement("db-button");C.setAttribute("variant","tertiary"),C.setAttribute("full-width",""),C.textContent=l,v&&C.setAttribute("disabled",""),C.addEventListener("db-click",()=>this.dispatchCancel());const y=document.createElement("db-button");y.setAttribute("variant",m),y.setAttribute("full-width",""),y.textContent=d,f&&y.setAttribute("disabled",""),y.addEventListener("db-click",()=>this.dispatchConfirm()),_.append(C,y),E.append(_),g.append(E),e(this,g),document.body.append(g),this.root=g,this.focusTrap=i(E,{initialFocus:()=>"cancel"===p?C:y}),requestAnimationFrame(()=>this.focusTrap?.activate())}}customElements.get("db-confirm")||customElements.define("db-confirm",DbConfirm);export{DbConfirm};
@@ -1 +1 @@
1
- class DbContextMenu extends HTMLElement{constructor(){super(...arguments),this.externalTarget=null,this.activeSubMenu=null,this.onExternalContextMenu=null,this.handleDocumentMouseDown=t=>{if(!this.open)return;const e=t.target;this.menuEl?.contains(e)||2===t.button&&(this.targetWrap?.contains(e)||this.externalTarget?.contains(e))||this.close()},this.handleKeyDown=t=>{this.open&&"Escape"===t.key&&this.close()},this.handleContextMenu=t=>{this.hasAttribute("disabled")||(t.preventDefault(),t.stopPropagation(),this.openAt(t.clientX,t.clientY))}}static get observedAttributes(){return["open","x","y","items","target-id","disabled"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(t){t?this.setAttribute("open","true"):this.removeAttribute("open")}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}connectedCallback(){this.style.display="contents",requestAnimationFrame(()=>{this.renderTarget(),this.syncMenu()}),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleKeyDown),this.unbindExternalTarget(),this.menuEl?.remove(),this.menuEl=void 0}attributeChangedCallback(t){if(this.isConnected)return"target-id"===t?(this.unbindExternalTarget(),void this.bindExternalTarget()):void("open"!==t&&"x"!==t&&"y"!==t&&"items"!==t||this.syncMenu())}openAt(t,e){this.setAttribute("x",String(t)),this.setAttribute("y",String(e)),this.setAttribute("open","true"),this.dispatchEvent(new CustomEvent("db-open",{bubbles:!0,composed:!0,detail:{x:t,y:e}})),this.syncMenu()}close(){this.activeSubMenu=null,this.removeAttribute("open"),this.menuEl?.remove(),this.menuEl=void 0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}collectTargetChildren(){const t=Array.from(this.children).filter(t=>!t.hasAttribute("data-wc-internal")&&t!==this.targetWrap);return t.length>0?t:Array.from(this.targetWrap?.children||[])}bindExternalTarget(){const t=this.getAttribute("target-id");t&&(this.externalTarget=document.getElementById(t),this.externalTarget&&(this.onExternalContextMenu=t=>this.handleContextMenu(t),this.externalTarget.addEventListener("contextmenu",this.onExternalContextMenu)))}unbindExternalTarget(){this.externalTarget&&this.onExternalContextMenu&&this.externalTarget.removeEventListener("contextmenu",this.onExternalContextMenu),this.externalTarget=null,this.onExternalContextMenu=null}renderTarget(){const t=this.collectTargetChildren();this.getAttribute("target-id")?(this.replaceChildren(),this.bindExternalTarget()):(this.targetWrap||(this.targetWrap=document.createElement("div"),this.targetWrap.className="designbase-wc-context-menu__target",this.targetWrap.addEventListener("contextmenu",this.handleContextMenu)),this.replaceChildren(),t.forEach(t=>this.targetWrap.append(t)),t.length>0&&this.append(this.targetWrap))}adjustPosition(){if(!this.menuEl)return;const t=Number(this.getAttribute("x")||0),e=Number(this.getAttribute("y")||0),n=this.menuEl.getBoundingClientRect();let i=t,s=e;t+n.width>window.innerWidth&&(i=t-n.width),e+n.height>window.innerHeight&&(s=e-n.height),this.menuEl.style.left=`${Math.max(0,i)}px`,this.menuEl.style.top=`${Math.max(0,s)}px`}createMenuItem(t){const e=document.createElement("db-menu-item");return e.setAttribute("label",t.label||t.id),e.setAttribute("type","block"),e.setAttribute("menu-style","dropdown"),t.icon&&e.setAttribute("icon",t.icon),t.disabled&&e.setAttribute("disabled",""),t.variant&&e.setAttribute("variant",t.variant),t.subItems?.length&&(e.setAttribute("sub-items",JSON.stringify(t.subItems)),e.setAttribute("expandable","")),e.addEventListener("db-click",()=>{t.disabled||t.subItems?.length||(this.dispatchEvent(new CustomEvent("db-select",{detail:{item:t},bubbles:!0,composed:!0})),this.close())}),e.addEventListener("db-child-click",t=>{const e=t.detail?.child;this.dispatchEvent(new CustomEvent("db-select",{detail:{item:e},bubbles:!0,composed:!0})),this.close()}),e}renderItem(t,e){if(t.divider||t.isDivider){const t=document.createElement("db-divider");return t.className="designbase-wc-divider",t}const n=document.createElement("div");n.className="designbase-wc-context-menu__item-wrapper",n.append(this.createMenuItem(t));if(Boolean(t.subItems?.length)){const e=document.createElement("div");e.className=["designbase-wc-context-menu__submenu",this.activeSubMenu===t.id&&"designbase-wc-context-menu__submenu--open"].filter(Boolean).join(" "),t.subItems?.forEach((t,n)=>{const i=this.renderItem(t,n);i&&e.append(i)}),n.addEventListener("mouseenter",()=>{this.activeSubMenu=t.id,e.classList.add("designbase-wc-context-menu__submenu--open")}),n.addEventListener("mouseleave",()=>{this.activeSubMenu=null,e.classList.remove("designbase-wc-context-menu__submenu--open")}),n.append(e)}return n}syncMenu(){if(this.menuEl?.remove(),this.menuEl=void 0,!this.open)return;const t=Number(this.getAttribute("x")||0),e=Number(this.getAttribute("y")||0),n=this.items,i=document.createElement("div");i.className="designbase-wc-context-menu",i.setAttribute("data-wc-internal",""),i.style.position="fixed",i.style.left=`${t}px`,i.style.top=`${e}px`,i.style.zIndex="1000",i.setAttribute("role","menu"),i.setAttribute("aria-orientation","vertical"),n.forEach((t,e)=>{const n=this.renderItem(t,e);n&&i.append(n)}),document.body.append(i),this.menuEl=i,requestAnimationFrame(()=>this.adjustPosition())}}customElements.get("db-context-menu")||customElements.define("db-context-menu",DbContextMenu);export{DbContextMenu};
1
+ import{inheritThemeScope as e}from"../core/theme-scope.js";class DbContextMenu extends HTMLElement{constructor(){super(...arguments),this.externalTarget=null,this.activeSubMenu=null,this.onExternalContextMenu=null,this.handleDocumentMouseDown=e=>{if(!this.open)return;const t=e.target;this.menuEl?.contains(t)||2===e.button&&(this.targetWrap?.contains(t)||this.externalTarget?.contains(t))||this.close()},this.handleKeyDown=e=>{this.open&&"Escape"===e.key&&this.close()},this.handleContextMenu=e=>{this.hasAttribute("disabled")||(e.preventDefault(),e.stopPropagation(),this.openAt(e.clientX,e.clientY))}}static get observedAttributes(){return["open","x","y","items","target-id","disabled"]}get open(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}set open(e){e?this.setAttribute("open","true"):this.removeAttribute("open")}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.style.display="contents",requestAnimationFrame(()=>{this.renderTarget(),this.syncMenu()}),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleKeyDown),this.unbindExternalTarget(),this.menuEl?.remove(),this.menuEl=void 0}attributeChangedCallback(e){if(this.isConnected)return"target-id"===e?(this.unbindExternalTarget(),void this.bindExternalTarget()):void("open"!==e&&"x"!==e&&"y"!==e&&"items"!==e||this.syncMenu())}openAt(e,t){this.setAttribute("x",String(e)),this.setAttribute("y",String(t)),this.setAttribute("open","true"),this.dispatchEvent(new CustomEvent("db-open",{bubbles:!0,composed:!0,detail:{x:e,y:t}})),this.syncMenu()}close(){this.activeSubMenu=null,this.removeAttribute("open"),this.menuEl?.remove(),this.menuEl=void 0,this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}collectTargetChildren(){const e=Array.from(this.children).filter(e=>!e.hasAttribute("data-wc-internal")&&e!==this.targetWrap);return e.length>0?e:Array.from(this.targetWrap?.children||[])}bindExternalTarget(){const e=this.getAttribute("target-id");e&&(this.externalTarget=document.getElementById(e),this.externalTarget&&(this.onExternalContextMenu=e=>this.handleContextMenu(e),this.externalTarget.addEventListener("contextmenu",this.onExternalContextMenu)))}unbindExternalTarget(){this.externalTarget&&this.onExternalContextMenu&&this.externalTarget.removeEventListener("contextmenu",this.onExternalContextMenu),this.externalTarget=null,this.onExternalContextMenu=null}renderTarget(){const e=this.collectTargetChildren();this.getAttribute("target-id")?(this.replaceChildren(),this.bindExternalTarget()):(this.targetWrap||(this.targetWrap=document.createElement("div"),this.targetWrap.className="designbase-wc-context-menu__target",this.targetWrap.addEventListener("contextmenu",this.handleContextMenu)),this.replaceChildren(),e.forEach(e=>this.targetWrap.append(e)),e.length>0&&this.append(this.targetWrap))}adjustPosition(){if(!this.menuEl)return;const e=Number(this.getAttribute("x")||0),t=Number(this.getAttribute("y")||0),n=this.menuEl.getBoundingClientRect();let i=e,s=t;e+n.width>window.innerWidth&&(i=e-n.width),t+n.height>window.innerHeight&&(s=t-n.height),this.menuEl.style.left=`${Math.max(0,i)}px`,this.menuEl.style.top=`${Math.max(0,s)}px`}createMenuItem(e){const t=document.createElement("db-menu-item");return t.setAttribute("label",e.label||e.id),t.setAttribute("type","block"),t.setAttribute("menu-style","dropdown"),e.icon&&t.setAttribute("icon",e.icon),e.disabled&&t.setAttribute("disabled",""),e.variant&&t.setAttribute("variant",e.variant),e.subItems?.length&&(t.setAttribute("sub-items",JSON.stringify(e.subItems)),t.setAttribute("expandable","")),t.addEventListener("db-click",()=>{e.disabled||e.subItems?.length||(this.dispatchEvent(new CustomEvent("db-select",{detail:{item:e},bubbles:!0,composed:!0})),this.close())}),t.addEventListener("db-child-click",e=>{const t=e.detail?.child;this.dispatchEvent(new CustomEvent("db-select",{detail:{item:t},bubbles:!0,composed:!0})),this.close()}),t}renderItem(e,t){if(e.divider||e.isDivider){const e=document.createElement("db-divider");return e.className="designbase-wc-divider",e}const n=document.createElement("div");n.className="designbase-wc-context-menu__item-wrapper",n.append(this.createMenuItem(e));if(Boolean(e.subItems?.length)){const t=document.createElement("div");t.className=["designbase-wc-context-menu__submenu",this.activeSubMenu===e.id&&"designbase-wc-context-menu__submenu--open"].filter(Boolean).join(" "),e.subItems?.forEach((e,n)=>{const i=this.renderItem(e,n);i&&t.append(i)}),n.addEventListener("mouseenter",()=>{this.activeSubMenu=e.id,t.classList.add("designbase-wc-context-menu__submenu--open")}),n.addEventListener("mouseleave",()=>{this.activeSubMenu=null,t.classList.remove("designbase-wc-context-menu__submenu--open")}),n.append(t)}return n}syncMenu(){if(this.menuEl?.remove(),this.menuEl=void 0,!this.open)return;const t=Number(this.getAttribute("x")||0),n=Number(this.getAttribute("y")||0),i=this.items,s=document.createElement("div");s.className="designbase-wc-context-menu",s.setAttribute("data-wc-internal",""),s.style.position="fixed",s.style.left=`${t}px`,s.style.top=`${n}px`,s.style.zIndex="1000",s.setAttribute("role","menu"),s.setAttribute("aria-orientation","vertical"),i.forEach((e,t)=>{const n=this.renderItem(e,t);n&&s.append(n)}),e(this,s),document.body.append(s),this.menuEl=s,requestAnimationFrame(()=>this.adjustPosition())}}customElements.get("db-context-menu")||customElements.define("db-context-menu",DbContextMenu);export{DbContextMenu};
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";const e="designbase-wc-cursor-follower",s="designbase-wc-cursor-follower--hide-native";class DbCursorFollower extends HTMLElement{constructor(){super(...arguments),this.target={x:-9999,y:-9999},this.current={x:-9999,y:-9999},this.raf=0,this.enabled=!1,this.isScoped=!1}static get observedAttributes(){return["default-label","selector","smoothness","offset","hide-native-cursor","show-icon"]}connectedCallback(){this.style.display="contents",this.setupDesktopGate()}disconnectedCallback(){this.teardown()}attributeChangedCallback(){this.isConnected&&this.enabled&&this.mountLayer()}setupDesktopGate(){"undefined"!=typeof window&&(this.desktopMq=window.matchMedia("(pointer: fine) and (hover: hover) and (min-width: 769px)"),this.onDesktopChange=()=>{const t=this.desktopMq?.matches??!1;t!==this.enabled&&(this.enabled=t,t?this.mountLayer():this.teardownLayer())},this.onDesktopChange(),this.desktopMq.addEventListener("change",this.onDesktopChange))}updateScope(){this.isScoped=this.childElementCount>0||!!this.textContent?.trim()}isInScope(t){return!!t&&(!this.isScoped||this.contains(t))}mountLayer(){this.teardownLayer(),this.updateScope();const i=this.getAttribute("default-label")||"See the project",o=this.getAttribute("selector")||'a[href], button:not(:disabled), [role="button"]:not([aria-disabled="true"]), [data-cursor], [data-cursor-label], input[type="submit"], input[type="button"]',n=Math.min(1,Math.max(.05,Number(this.getAttribute("smoothness")||.14))),r=function parseOffset(t){if(!t)return{x:18,y:18};try{const e=JSON.parse(t);return{x:Number(e.x??18),y:Number(e.y??18)}}catch{const[e,s]=t.split(",").map(t=>Number(t.trim()));return{x:Number.isFinite(e)?e:18,y:Number.isFinite(s)?s:18}}}(this.getAttribute("offset")),a=this.hasAttribute("hide-native-cursor")&&"false"!==this.getAttribute("hide-native-cursor"),l=!this.hasAttribute("show-icon")||"false"!==this.getAttribute("show-icon");a&&document.documentElement.classList.add(s),this.portalRoot=document.createElement("div"),this.portalRoot.className=e,this.portalRoot.setAttribute("aria-hidden","true"),this.pillEl=document.createElement("div"),this.pillEl.className=`${e}__pill`,this.labelEl=document.createElement("span"),this.labelEl.textContent=i,this.pillEl.appendChild(this.labelEl),l&&(this.iconEl=document.createElement("span"),this.iconEl.className=`${e}__icon`,this.iconEl.appendChild(t("arrow-right",14)),this.pillEl.appendChild(this.iconEl)),this.portalRoot.appendChild(this.pillEl),document.body.appendChild(this.portalRoot),this.onMouseMove=t=>{this.target={x:t.clientX+r.x,y:t.clientY+r.y};const s=document.elementFromPoint(t.clientX,t.clientY),n=s?.closest(o)??null;this.isInScope(n)&&n?(this.labelEl&&(this.labelEl.textContent=function getLabelFromElement(t,e){return t.getAttribute("data-cursor-label")||t.getAttribute("data-cursor")||t.getAttribute("aria-label")||e}(n,i)),this.pillEl?.classList.add(`${e}__pill--visible`)):this.pillEl?.classList.remove(`${e}__pill--visible`)},window.addEventListener("mousemove",this.onMouseMove,{passive:!0});const tick=()=>{this.current.x+=(this.target.x-this.current.x)*n,this.current.y+=(this.target.y-this.current.y)*n,this.portalRoot&&(this.portalRoot.style.transform=`translate3d(${this.current.x}px, ${this.current.y}px, 0)`),this.raf=requestAnimationFrame(tick)};this.raf=requestAnimationFrame(tick)}teardownLayer(){cancelAnimationFrame(this.raf),this.onMouseMove&&(window.removeEventListener("mousemove",this.onMouseMove),this.onMouseMove=void 0),document.documentElement.classList.remove(s),this.portalRoot?.remove(),this.portalRoot=void 0,this.pillEl=void 0,this.labelEl=void 0,this.iconEl=void 0}teardown(){this.teardownLayer(),this.desktopMq&&this.onDesktopChange&&this.desktopMq.removeEventListener("change",this.onDesktopChange),this.isScoped=!1,this.enabled=!1}}customElements.get("db-cursor-follower")||customElements.define("db-cursor-follower",DbCursorFollower);export{DbCursorFollower};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{createDbIcon as e}from"./db-icons.js";const s="designbase-wc-cursor-follower",i="designbase-wc-cursor-follower--hide-native";class DbCursorFollower extends HTMLElement{constructor(){super(...arguments),this.target={x:-9999,y:-9999},this.current={x:-9999,y:-9999},this.raf=0,this.enabled=!1,this.isScoped=!1}static get observedAttributes(){return["default-label","selector","smoothness","offset","hide-native-cursor","show-icon"]}connectedCallback(){this.style.display="contents",this.setupDesktopGate()}disconnectedCallback(){this.teardown()}attributeChangedCallback(){this.isConnected&&this.enabled&&this.mountLayer()}setupDesktopGate(){"undefined"!=typeof window&&(this.desktopMq=window.matchMedia("(pointer: fine) and (hover: hover) and (min-width: 769px)"),this.onDesktopChange=()=>{const t=this.desktopMq?.matches??!1;t!==this.enabled&&(this.enabled=t,t?this.mountLayer():this.teardownLayer())},this.onDesktopChange(),this.desktopMq.addEventListener("change",this.onDesktopChange))}updateScope(){this.isScoped=this.childElementCount>0||!!this.textContent?.trim()}isInScope(t){return!!t&&(!this.isScoped||this.contains(t))}mountLayer(){this.teardownLayer(),this.updateScope();const o=this.getAttribute("default-label")||"See the project",n=this.getAttribute("selector")||'a[href], button:not(:disabled), [role="button"]:not([aria-disabled="true"]), [data-cursor], [data-cursor-label], input[type="submit"], input[type="button"]',r=Math.min(1,Math.max(.05,Number(this.getAttribute("smoothness")||.14))),a=function parseOffset(t){if(!t)return{x:18,y:18};try{const e=JSON.parse(t);return{x:Number(e.x??18),y:Number(e.y??18)}}catch{const[e,s]=t.split(",").map(t=>Number(t.trim()));return{x:Number.isFinite(e)?e:18,y:Number.isFinite(s)?s:18}}}(this.getAttribute("offset")),l=this.hasAttribute("hide-native-cursor")&&"false"!==this.getAttribute("hide-native-cursor"),h=!this.hasAttribute("show-icon")||"false"!==this.getAttribute("show-icon");l&&document.documentElement.classList.add(i),this.portalRoot=document.createElement("div"),this.portalRoot.className=s,this.portalRoot.setAttribute("aria-hidden","true"),this.pillEl=document.createElement("div"),this.pillEl.className=`${s}__pill`,this.labelEl=document.createElement("span"),this.labelEl.textContent=o,this.pillEl.appendChild(this.labelEl),h&&(this.iconEl=document.createElement("span"),this.iconEl.className=`${s}__icon`,this.iconEl.appendChild(e("arrow-right",14)),this.pillEl.appendChild(this.iconEl)),this.portalRoot.appendChild(this.pillEl),t(this,this.portalRoot),document.body.appendChild(this.portalRoot),this.onMouseMove=t=>{this.target={x:t.clientX+a.x,y:t.clientY+a.y};const e=document.elementFromPoint(t.clientX,t.clientY),i=e?.closest(n)??null;this.isInScope(i)&&i?(this.labelEl&&(this.labelEl.textContent=function getLabelFromElement(t,e){return t.getAttribute("data-cursor-label")||t.getAttribute("data-cursor")||t.getAttribute("aria-label")||e}(i,o)),this.pillEl?.classList.add(`${s}__pill--visible`)):this.pillEl?.classList.remove(`${s}__pill--visible`)},window.addEventListener("mousemove",this.onMouseMove,{passive:!0});const tick=()=>{this.current.x+=(this.target.x-this.current.x)*r,this.current.y+=(this.target.y-this.current.y)*r,this.portalRoot&&(this.portalRoot.style.transform=`translate3d(${this.current.x}px, ${this.current.y}px, 0)`),this.raf=requestAnimationFrame(tick)};this.raf=requestAnimationFrame(tick)}teardownLayer(){cancelAnimationFrame(this.raf),this.onMouseMove&&(window.removeEventListener("mousemove",this.onMouseMove),this.onMouseMove=void 0),document.documentElement.classList.remove(i),this.portalRoot?.remove(),this.portalRoot=void 0,this.pillEl=void 0,this.labelEl=void 0,this.iconEl=void 0}teardown(){this.teardownLayer(),this.desktopMq&&this.onDesktopChange&&this.desktopMq.removeEventListener("change",this.onDesktopChange),this.isScoped=!1,this.enabled=!1}}customElements.get("db-cursor-follower")||customElements.define("db-cursor-follower",DbCursorFollower);export{DbCursorFollower};
@@ -17,6 +17,7 @@ declare class DbDrawer extends HTMLElement {
17
17
  /** 잠근 적이 있을 때만 푼다 — 카운트가 음수로 새지 않도록 */
18
18
  private releaseScrollLock;
19
19
  attributeChangedCallback(name: string): void;
20
+ private syncInteraction;
20
21
  private isOpenRequested;
21
22
  private clearTimers;
22
23
  private attachEscape;
@@ -1 +1 @@
1
- import{dbText as t}from"../core/i18n.js";import{createFocusTrap as e}from"../core/focus-trap.js";import{unlockScroll as s,lockScroll as i}from"../core/scroll-lock.js";import{DRAWER_POSITIONS as r,DRAWER_SIZES as o}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDrawer extends HTMLElement{constructor(){super(...arguments),this.isMounted=!1,this.isActive=!1,this.scrollLocked=!1,this.keyHandler=null}static get observedAttributes(){return["open","title","position","size","show-close-button","close-on-backdrop-click","close-on-escape","animation-duration","show-overlay","overlay-closable","z-index","trap-focus","drawer-id"]}connectedCallback(){this.style.display="contents",this.render(),this.syncOpenState()}disconnectedCallback(){this.clearTimers(),this.detachEscape(),this.focusTrap?.deactivate(),this.focusTrap=void 0,this.root?.remove(),this.root=void 0,this.releaseScrollLock()}releaseScrollLock(){this.scrollLocked&&(this.scrollLocked=!1,s())}attributeChangedCallback(t){this.isConnected&&("open"!==t?(this.render(),this.isMounted&&this.syncActiveClasses()):this.syncOpenState())}isOpenRequested(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}clearTimers(){null!=this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"false"!==this.getAttribute("close-on-escape")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}close(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}collectChildren(){return[...new Set([...Array.from(this.contentEl?.children||[]),...Array.from(this.children)])].filter(t=>!t.hasAttribute("data-wc-internal"))}syncOpenState(){const t=this.isOpenRequested(),s=Number(this.getAttribute("animation-duration")||300);if(this.clearTimers(),t)return this.render(),this.isMounted=!0,this.isActive=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&document.body.append(this.root),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isActive=!0,this.syncActiveClasses(),"false"!==this.getAttribute("trap-focus")&&this.container&&(this.focusTrap=e(this.container),this.focusTrap.activate())})}),this.scrollLocked||(i(),this.scrollLocked=!0),void this.attachEscape();this.isActive=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.releaseScrollLock(),this.detachEscape(),this.focusTrap?.deactivate(),this.focusTrap=void 0},s),this.detachEscape()}syncActiveClasses(){this.root&&(this.root.classList.toggle("designbase-wc-drawer--open",this.isActive),this.root.classList.toggle("designbase-wc-drawer--closing",this.isMounted&&!this.isActive),this.overlay?.classList.toggle("designbase-wc-drawer__overlay--open",this.isActive),this.container?.classList.toggle("designbase-wc-drawer__container--open",this.isActive))}render(){const e=r.includes(this.getAttribute("position")||"right")&&this.getAttribute("position")||"right",s=o.includes(this.getAttribute("size")||"m")&&this.getAttribute("size")||"m",i=this.getAttribute("title"),n="false"!==this.getAttribute("show-close-button"),a="false"!==this.getAttribute("show-overlay"),c=this.getAttribute("animation-duration")||"300",l=this.getAttribute("z-index")||"1000",h=this.getAttribute("drawer-id")||"drawer",d=this.collectChildren();this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.overlay=document.createElement("div"),this.overlay.className="designbase-wc-drawer__overlay",this.overlay.setAttribute("aria-hidden","true"),this.overlay.addEventListener("click",t=>{if(t.target!==this.overlay)return;const e="false"!==this.getAttribute("overlay-closable"),s="false"!==this.getAttribute("close-on-backdrop-click");e&&s&&this.close()}),this.container=document.createElement("div"),this.container.className=`designbase-wc-drawer__container designbase-wc-drawer__container--${e}`,this.container.setAttribute("role","dialog"),this.container.setAttribute("aria-modal","true"),this.container.tabIndex=-1,this.container.addEventListener("click",t=>t.stopPropagation()),this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-drawer__content",this.container.append(this.contentEl)),this.root.className=["designbase-wc-drawer",`designbase-wc-drawer--${e}`,`designbase-wc-drawer--${s}`].join(" "),this.root.style.setProperty("--drawer-animation-duration",`${c}ms`),this.root.style.setProperty("--drawer-z-index",l),this.container.className=`designbase-wc-drawer__container designbase-wc-drawer__container--${e}`,this.container.id=h,i?this.container.setAttribute("aria-labelledby",`${h}-title`):this.container.removeAttribute("aria-labelledby"),this.contentEl.id=`${h}-content`,a&&this.overlay?this.overlay.parentElement!==this.root&&this.root.prepend(this.overlay):this.overlay?.remove(),this.container.querySelector(":scope > .designbase-wc-drawer__header")?.remove();if(Boolean(i)||n){const e=document.createElement("div");if(e.className="designbase-wc-drawer__header",i){const t=document.createElement("h2");t.className="designbase-wc-drawer__title",t.id=`${h}-title`,t.textContent=i,e.append(t)}if(n){const s=document.createElement("db-button");s.className="designbase-wc-drawer__close-button",s.setAttribute("variant","ghost"),s.setAttribute("size","s"),s.setAttribute("icon-only",""),s.setAttribute("start-icon","close"),s.setAttribute("aria-label",t("닫기")),s.addEventListener("db-click",t=>{t.stopPropagation(),this.close()}),e.append(s)}this.container.insertBefore(e,this.contentEl)}const u=Array.from(this.contentEl.children);(u.length!==d.length||u.some((t,e)=>t!==d[e]))&&this.contentEl.replaceChildren(...d),this.container.parentElement!==this.root&&this.root.append(this.container),this.isMounted&&!this.root.isConnected&&document.body.append(this.root)}}customElements.get("db-drawer")||customElements.define("db-drawer",DbDrawer);export{DbDrawer};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as e}from"../core/i18n.js";import{createFocusTrap as s}from"../core/focus-trap.js";import{unlockScroll as i,lockScroll as r}from"../core/scroll-lock.js";import{DRAWER_POSITIONS as o,DRAWER_SIZES as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDrawer extends HTMLElement{constructor(){super(...arguments),this.isMounted=!1,this.isActive=!1,this.scrollLocked=!1,this.keyHandler=null}static get observedAttributes(){return["open","title","position","size","show-close-button","close-on-backdrop-click","close-on-escape","animation-duration","show-overlay","overlay-closable","z-index","trap-focus","drawer-id"]}connectedCallback(){this.style.display="contents",this.render(),this.syncOpenState()}disconnectedCallback(){this.clearTimers(),this.detachEscape(),this.focusTrap?.deactivate(),this.focusTrap=void 0,this.root?.remove(),this.root=void 0,this.releaseScrollLock()}releaseScrollLock(){this.scrollLocked&&(this.scrollLocked=!1,i())}attributeChangedCallback(t){this.isConnected&&("open"!==t?(this.render(),this.isMounted&&(this.syncActiveClasses(),this.syncInteraction())):this.syncOpenState())}syncInteraction(){"false"===this.getAttribute("show-overlay")?this.releaseScrollLock():this.scrollLocked||(r(),this.scrollLocked=!0);"false"!==this.getAttribute("trap-focus")?this.isActive&&this.container&&!this.focusTrap&&(this.focusTrap=s(this.container),this.focusTrap.activate()):(this.focusTrap?.deactivate(),this.focusTrap=void 0)}isOpenRequested(){return this.hasAttribute("open")&&"false"!==this.getAttribute("open")}clearTimers(){null!=this.enterFrame&&(cancelAnimationFrame(this.enterFrame),this.enterFrame=void 0),this.exitTimer&&(clearTimeout(this.exitTimer),this.exitTimer=void 0)}attachEscape(){this.keyHandler||(this.keyHandler=t=>{"Escape"===t.key&&"false"!==this.getAttribute("close-on-escape")&&this.close()},document.addEventListener("keydown",this.keyHandler))}detachEscape(){this.keyHandler&&(document.removeEventListener("keydown",this.keyHandler),this.keyHandler=null)}close(){this.setAttribute("open","false"),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}collectChildren(){return[...new Set([...Array.from(this.contentEl?.children||[]),...Array.from(this.children)])].filter(t=>!t.hasAttribute("data-wc-internal"))}syncOpenState(){const e=this.isOpenRequested(),s=Number(this.getAttribute("animation-duration")||300);if(this.clearTimers(),e)return this.render(),this.isMounted=!0,this.isActive=!1,this.syncActiveClasses(),this.root&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root)),this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=requestAnimationFrame(()=>{this.enterFrame=void 0,this.isActive=!0,this.syncActiveClasses(),this.syncInteraction()})}),this.syncInteraction(),void this.attachEscape();this.isActive=!1,this.syncActiveClasses(),this.exitTimer=setTimeout(()=>{this.exitTimer=void 0,this.isMounted=!1,this.syncActiveClasses(),this.root?.remove(),this.releaseScrollLock(),this.detachEscape(),this.focusTrap?.deactivate(),this.focusTrap=void 0},s),this.detachEscape()}syncActiveClasses(){this.root&&(this.root.classList.toggle("designbase-wc-drawer--open",this.isActive),this.root.classList.toggle("designbase-wc-drawer--closing",this.isMounted&&!this.isActive),this.overlay?.classList.toggle("designbase-wc-drawer__overlay--open",this.isActive),this.container?.classList.toggle("designbase-wc-drawer__container--open",this.isActive))}render(){const s=o.includes(this.getAttribute("position")||"right")&&this.getAttribute("position")||"right",i=n.includes(this.getAttribute("size")||"m")&&this.getAttribute("size")||"m",r=this.getAttribute("title"),a="false"!==this.getAttribute("show-close-button"),c="false"!==this.getAttribute("show-overlay"),h=this.getAttribute("animation-duration")||"300",l=this.getAttribute("z-index")||"1000",d=this.getAttribute("drawer-id")||"drawer",u=this.collectChildren();this.root||(this.root=document.createElement("div"),this.root.setAttribute("data-wc-internal",""),this.overlay=document.createElement("div"),this.overlay.className="designbase-wc-drawer__overlay",this.overlay.setAttribute("aria-hidden","true"),this.overlay.addEventListener("click",t=>{if(t.target!==this.overlay)return;const e="false"!==this.getAttribute("overlay-closable"),s="false"!==this.getAttribute("close-on-backdrop-click");e&&s&&this.close()}),this.container=document.createElement("div"),this.container.className=`designbase-wc-drawer__container designbase-wc-drawer__container--${s}`,this.container.setAttribute("role","dialog"),this.container.setAttribute("aria-modal","true"),this.container.tabIndex=-1,this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-drawer__content",this.container.append(this.contentEl)),this.root.className=["designbase-wc-drawer",`designbase-wc-drawer--${s}`,`designbase-wc-drawer--${i}`].join(" "),this.root.style.setProperty("--drawer-animation-duration",`${h}ms`),this.root.style.setProperty("--drawer-z-index",l),this.container.className=`designbase-wc-drawer__container designbase-wc-drawer__container--${s}`,this.container.id=d,this.container.setAttribute("aria-modal",String(c)),r?this.container.setAttribute("aria-labelledby",`${d}-title`):this.container.removeAttribute("aria-labelledby"),this.contentEl.id=`${d}-content`,c&&this.overlay?this.overlay.parentElement!==this.root&&this.root.prepend(this.overlay):this.overlay?.remove(),this.container.querySelector(":scope > .designbase-wc-drawer__header")?.remove();if(Boolean(r)||a){const t=document.createElement("div");if(t.className="designbase-wc-drawer__header",r){const e=document.createElement("h2");e.className="designbase-wc-drawer__title",e.id=`${d}-title`,e.textContent=r,t.append(e)}if(a){const s=document.createElement("db-button");s.className="designbase-wc-drawer__close-button",s.setAttribute("variant","ghost"),s.setAttribute("size","s"),s.setAttribute("icon-only",""),s.setAttribute("start-icon","close"),s.setAttribute("aria-label",e("닫기")),s.addEventListener("db-click",t=>{t.stopPropagation(),this.close()}),t.append(s)}this.container.insertBefore(t,this.contentEl)}const m=Array.from(this.contentEl.children);(m.length!==u.length||m.some((t,e)=>t!==u[e]))&&this.contentEl.replaceChildren(...u),this.container.parentElement!==this.root&&this.root.append(this.container),this.isMounted&&!this.root.isConnected&&(t(this,this.root),document.body.append(this.root))}}customElements.get("db-drawer")||customElements.define("db-drawer",DbDrawer);export{DbDrawer};
@@ -1 +1 @@
1
- import{isDbIconName as e,createDbIcon as t}from"./db-icons.js";import{DROPDOWN_SIZES as i,DROPDOWN_PLACEMENTS as r,DROPDOWN_TRIGGER_VARIANTS as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDropdown extends HTMLElement{constructor(){super(...arguments),this.focusedIndex=-1,this.onTriggerActivate=null,this.lastTriggerSignature="",this.handleTriggerKeyDown=e=>{if(!this.menu?.contains(e.target))return"Enter"!==e.key&&" "!==e.key&&"ArrowDown"!==e.key||this.open?void("Escape"===e.key&&this.open&&(e.preventDefault(),this.open=!1,this.render())):(e.preventDefault(),this.open=!0,requestAnimationFrame(()=>this.focusItem(0)),void this.render())},this.handleDocumentKeyDown=e=>{if(!this.open)return;if("Escape"===e.key)return e.preventDefault(),this.open=!1,this.render(),void this.triggerWrap?.querySelector("[aria-haspopup]")?.focus();if(this.menu?.querySelector(':scope > [slot="content"]'))return;const t=this.enabledItems();if(!t.length)return;const i=t.findIndex(e=>this.parsedItems.indexOf(e)===this.focusedIndex);switch(e.key){case"ArrowDown":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i+1)%t.length]));break;case"ArrowUp":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i-1+t.length)%t.length]));break;case"Home":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[0]));break;case"End":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[t.length-1]));break;case"Enter":case" ":{e.preventDefault();const t=this.parsedItems[this.focusedIndex];!t||t.divider||t.disabled||this.selectItem(t);break}}},this.handleDocumentMouseDown=e=>{this.open&&(this.contains(e.target)||(this.open=!1,this.render()))}}static get observedAttributes(){return["options","items","placeholder","label","value","size","placement","full-width","disabled","open","trigger-variant","trigger-icon","icon-only","show-chevron"]}get showChevron(){return"false"!==this.getAttribute("show-chevron")}set showChevron(e){this.setAttribute("show-chevron",String(e))}get parsedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return(this.getAttribute("options")||"").split(",").map(e=>e.trim()).filter(Boolean).map((e,t)=>({id:`option-${t}`,label:e}))}get options(){return this.parsedItems.map(e=>e.label||e.id)}set options(e){this.setAttribute("options",Array.isArray(e)?e.join(","):e)}get items(){return this.parsedItems}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get value(){return this.getAttribute("value")||""}set value(e){e?this.setAttribute("value",e):this.removeAttribute("value")}get open(){return this.hasAttribute("open")}set open(e){const t=this.open;this.toggleAttribute("open",e),t!==e&&this.dispatchEvent(new CustomEvent("db-open",{detail:{open:e},bubbles:!0,composed:!0}))}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get placement(){return this.getAttribute("placement")||"bottom-left"}set placement(e){this.setAttribute("placement",e)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(e){e?this.setAttribute("placeholder",e):this.removeAttribute("placeholder")}get label(){return this.getAttribute("label")||""}set label(e){e?this.setAttribute("label",e):this.removeAttribute("label")}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}connectedCallback(){requestAnimationFrame(()=>this.render()),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.unbindTrigger()}attributeChangedCallback(e){this.isConnected&&("open"!==e||this.open||(this.focusedIndex=-1),this.render())}resolvedSize(){return i.includes(this.size)?this.size:"m"}resolvedPlacement(){return r.includes(this.placement)?this.placement:"bottom-left"}menuItemIconSize(){const e=this.resolvedSize();return"s"===e?14:"l"===e?18:16}triggerLabel(){return this.label?this.label:this.placeholder?this.placeholder:this.value?this.value:"메뉴"}enabledItems(){return this.parsedItems.filter(e=>!e.disabled&&!e.divider)}collectTriggerChildren(){const isInternalNode=e=>"content"===e.getAttribute("slot")||e.hasAttribute("data-wc-internal")||e===this.triggerWrap||e===this.menu||e===this.defaultTrigger,e=Array.from(this.children).filter(e=>!isInternalNode(e));return e.length>0?e:Array.from(this.triggerWrap?.children||[]).filter(e=>!isInternalNode(e))}hasCustomTrigger(){return this.collectTriggerChildren().length>0}bindTrigger(){this.triggerWrap&&(this.unbindTrigger(),this.onTriggerActivate=e=>{this.disabled||this.menu?.contains(e.target)||(e.preventDefault(),e.stopPropagation(),this.toggleOpen())},this.triggerWrap.addEventListener("click",this.onTriggerActivate),this.triggerWrap.addEventListener("keydown",this.handleTriggerKeyDown))}unbindTrigger(){this.triggerWrap&&this.onTriggerActivate&&this.triggerWrap.removeEventListener("click",this.onTriggerActivate),this.triggerWrap&&this.triggerWrap.removeEventListener("keydown",this.handleTriggerKeyDown),this.onTriggerActivate=null}toggleOpen(){this.disabled||(this.open=!this.open,this.open&&requestAnimationFrame(()=>this.focusItem(0)),this.render())}triggerSignature(){return[this.resolvedSize(),this.getAttribute("trigger-variant")||"tertiary",this.hasAttribute("icon-only")?"1":"0",this.getAttribute("trigger-icon")||"",this.fullWidth?"1":"0",this.showChevron?"1":"0"].join("|")}renderDefaultTrigger(){const t=this.resolvedSize(),i=this.getAttribute("trigger-variant")||"tertiary",r=s.includes(i)?i:"tertiary",n=this.hasAttribute("icon-only"),o=this.getAttribute("trigger-icon"),a=document.createElement("db-button");if(a.setAttribute("type","button"),a.setAttribute("variant",r),a.setAttribute("size",t),a.className="designbase-wc-dropdown__trigger",a.setAttribute("aria-haspopup","menu"),a.setAttribute("aria-label",this.triggerLabel()),this.fullWidth&&a.setAttribute("full-width",""),n)a.setAttribute("icon-only",""),a.setAttribute("start-icon",o&&e(o)?o:"edit"),a.removeAttribute("end-icon");else{a.removeAttribute("icon-only"),o&&e(o)?a.setAttribute("start-icon",o):a.removeAttribute("start-icon");const t=document.createElement("span");t.className="designbase-wc-dropdown__trigger-label",t.textContent=this.triggerLabel(),a.append(t),this.showChevron&&a.setAttribute("end-icon","chevron-down")}return a}syncDefaultTriggerState(e){e.setAttribute("aria-expanded",String(this.open)),e.setAttribute("aria-label",this.triggerLabel()),e.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),this.disabled?e.setAttribute("disabled",""):e.removeAttribute("disabled");const t=e.querySelector(".designbase-wc-dropdown__trigger-label");t&&(t.textContent=this.triggerLabel())}ensureStructure(){this.triggerWrap||(this.triggerWrap=document.createElement("div"),this.triggerWrap.className="designbase-wc-dropdown__trigger-wrap",this.triggerWrap.setAttribute("data-wc-internal","")),this.menu||(this.menu=document.createElement("div"),this.menu.className="designbase-wc-dropdown__menu",this.menu.setAttribute("data-wc-internal",""),this.menu.setAttribute("role","menu"));const e=this.triggerWrap,t=this.menu;e&&t&&(this.contains(e)||this.append(e),e.contains(t)||e.append(t),Array.from(this.children).forEach(i=>{i===e||i.hasAttribute("data-wc-internal")||("content"===i.getAttribute("slot")?t.append(i):e.insertBefore(i,t))}))}renderTrigger(){const e=this.triggerWrap,t=this.menu;if(!e||!t)return;const i=this.collectTriggerChildren();if(i.length>0){this.defaultTrigger?.remove(),this.defaultTrigger=void 0;Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),i.forEach(i=>{i.setAttribute("aria-haspopup","menu"),i.setAttribute("aria-expanded",String(this.open)),i.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),e.insertBefore(i,t)})}else{Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),this.defaultTrigger&&this.triggerSignature()===this.lastTriggerSignature||(this.defaultTrigger?.remove(),this.defaultTrigger=this.renderDefaultTrigger(),this.lastTriggerSignature=this.triggerSignature(),e.insertBefore(this.defaultTrigger,t)),this.defaultTrigger&&this.syncDefaultTriggerState(this.defaultTrigger)}this.bindTrigger()}renderMenu(){const e=this.resolvedPlacement();this.menu.className=`designbase-wc-dropdown__menu designbase-wc-dropdown__menu--${e}${this.open?" designbase-wc-dropdown__menu--open":""}`,this.menu.setAttribute("aria-hidden",String(!this.open)),this.menu.setAttribute("aria-label",this.triggerLabel());const i=this.menu.querySelector(':scope > [slot="content"]');if(this.menu.setAttribute("role",i?"dialog":"menu"),i)return this.menu.inert=!this.open,this.menu.setAttribute("aria-modal","false"),this.menu.classList.add("designbase-wc-dropdown__menu--custom"),void this.triggerWrap?.querySelector("[aria-haspopup]")?.setAttribute("aria-haspopup","dialog");this.menu.inert=!1,this.menu.removeAttribute("aria-modal"),this.menu.replaceChildren();const r=this.menuItemIconSize();this.parsedItems.forEach((e,i)=>{if(e.divider){const e=document.createElement("div");return e.className="designbase-wc-dropdown__divider",e.setAttribute("role","separator"),void this.menu?.append(e)}e.id||e.label||String(i);const s=e.label||e.id,n=Boolean(e.disabled||this.disabled),o=this.focusedIndex===i,a=document.createElement("button");if(a.type="button",a.className=["designbase-wc-dropdown__item",n&&"designbase-wc-dropdown__item--disabled",o&&"designbase-wc-dropdown__item--focused"].filter(Boolean).join(" "),a.setAttribute("role","menuitem"),a.disabled=n,a.tabIndex=o?0:-1,a.dataset.index=String(i),e.icon){const i=t(e.icon,r);i.classList.add("designbase-wc-dropdown__item-icon"),a.append(i)}const d=document.createElement("span");d.className="designbase-wc-dropdown__item-label",d.textContent=s,a.append(d),a.addEventListener("click",t=>{t.stopPropagation(),this.selectItem(e)}),this.menu?.append(a)})}render(){const e=this.resolvedSize();this.className=["designbase-wc-dropdown",`designbase-wc-dropdown--${e}`,this.open&&"designbase-wc-dropdown--open",this.fullWidth&&"designbase-wc-dropdown--full-width",this.disabled&&"designbase-wc-dropdown--disabled"].filter(Boolean).join(" "),this.ensureStructure(),this.renderTrigger(),this.renderMenu()}selectItem(e){e.disabled||e.divider||(this.open=!1,this.focusedIndex=-1,this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.label||e.id,id:e.id,item:e},bubbles:!0,composed:!0})),this.render(),this.triggerWrap?.querySelector("[aria-haspopup]")?.focus())}focusItem(e){if(this.menu?.querySelector(':scope > [slot="content"]'))return void this.menu.querySelector('input:not([disabled]), button:not([disabled]), [tabindex="0"]')?.focus();const t=this.enabledItems();if(!t.length)return;const i=t[Math.max(0,Math.min(e,t.length-1))],r=this.parsedItems.indexOf(i);this.focusedIndex=r;Array.from(this.menu?.querySelectorAll(".designbase-wc-dropdown__item")||[]).forEach(e=>{const t=Number(e.dataset.index)===r;e.classList.toggle("designbase-wc-dropdown__item--focused",t),e.tabIndex=t?0:-1,t&&e.focus()})}}customElements.get("db-dropdown")||customElements.define("db-dropdown",DbDropdown);export{DbDropdown};
1
+ import{setHostClasses as e}from"../core/host-class.js";import{isDbIconName as t,createDbIcon as i}from"./db-icons.js";import{DROPDOWN_SIZES as r,DROPDOWN_PLACEMENTS as s,DROPDOWN_TRIGGER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbDropdown extends HTMLElement{constructor(){super(...arguments),this.focusedIndex=-1,this.onTriggerActivate=null,this.lastTriggerSignature="",this.handleTriggerKeyDown=e=>{if(!this.menu?.contains(e.target))return"Enter"!==e.key&&" "!==e.key&&"ArrowDown"!==e.key||this.open?void("Escape"===e.key&&this.open&&(e.preventDefault(),this.open=!1,this.render())):(e.preventDefault(),this.open=!0,requestAnimationFrame(()=>this.focusItem(0)),void this.render())},this.handleDocumentKeyDown=e=>{if(!this.open)return;if("Escape"===e.key)return e.preventDefault(),this.open=!1,this.render(),void this.triggerWrap?.querySelector("[aria-haspopup]")?.focus();if(this.menu?.querySelector(':scope > [slot="content"]'))return;const t=this.enabledItems();if(!t.length)return;const i=t.findIndex(e=>this.parsedItems.indexOf(e)===this.focusedIndex);switch(e.key){case"ArrowDown":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i+1)%t.length]));break;case"ArrowUp":e.preventDefault(),this.focusItem(i<0?0:this.parsedItems.indexOf(t[(i-1+t.length)%t.length]));break;case"Home":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[0]));break;case"End":e.preventDefault(),this.focusItem(this.parsedItems.indexOf(t[t.length-1]));break;case"Enter":case" ":{e.preventDefault();const t=this.parsedItems[this.focusedIndex];!t||t.divider||t.disabled||this.selectItem(t);break}}},this.handleDocumentMouseDown=e=>{this.open&&(this.contains(e.target)||(this.open=!1,this.render()))}}static get observedAttributes(){return["options","items","placeholder","label","value","size","placement","full-width","disabled","open","trigger-variant","trigger-icon","icon-only","show-chevron"]}get showChevron(){return"false"!==this.getAttribute("show-chevron")}set showChevron(e){this.setAttribute("show-chevron",String(e))}get parsedItems(){const e=this.getAttribute("items");if(e)try{const t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return(this.getAttribute("options")||"").split(",").map(e=>e.trim()).filter(Boolean).map((e,t)=>({id:`option-${t}`,label:e}))}get options(){return this.parsedItems.map(e=>e.label||e.id)}set options(e){this.setAttribute("options",Array.isArray(e)?e.join(","):e)}get items(){return this.parsedItems}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get value(){return this.getAttribute("value")||""}set value(e){e?this.setAttribute("value",e):this.removeAttribute("value")}get open(){return this.hasAttribute("open")}set open(e){const t=this.open;this.toggleAttribute("open",e),t!==e&&this.dispatchEvent(new CustomEvent("db-open",{detail:{open:e},bubbles:!0,composed:!0}))}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",e)}get size(){return this.getAttribute("size")||"m"}set size(e){this.setAttribute("size",e)}get placement(){return this.getAttribute("placement")||"bottom-left"}set placement(e){this.setAttribute("placement",e)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(e){e?this.setAttribute("placeholder",e):this.removeAttribute("placeholder")}get label(){return this.getAttribute("label")||""}set label(e){e?this.setAttribute("label",e):this.removeAttribute("label")}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(e){this.toggleAttribute("full-width",e)}connectedCallback(){requestAnimationFrame(()=>this.render()),document.addEventListener("mousedown",this.handleDocumentMouseDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}disconnectedCallback(){document.removeEventListener("mousedown",this.handleDocumentMouseDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.unbindTrigger()}attributeChangedCallback(e){this.isConnected&&("open"!==e||this.open||(this.focusedIndex=-1),this.render())}resolvedSize(){return r.includes(this.size)?this.size:"m"}resolvedPlacement(){return s.includes(this.placement)?this.placement:"bottom-left"}menuItemIconSize(){const e=this.resolvedSize();return"s"===e?14:"l"===e?18:16}triggerLabel(){return this.label?this.label:this.placeholder?this.placeholder:this.value?this.value:"메뉴"}enabledItems(){return this.parsedItems.filter(e=>!e.disabled&&!e.divider)}collectTriggerChildren(){const isInternalNode=e=>"content"===e.getAttribute("slot")||e.hasAttribute("data-wc-internal")||e===this.triggerWrap||e===this.menu||e===this.defaultTrigger,e=Array.from(this.children).filter(e=>!isInternalNode(e));return e.length>0?e:Array.from(this.triggerWrap?.children||[]).filter(e=>!isInternalNode(e))}hasCustomTrigger(){return this.collectTriggerChildren().length>0}bindTrigger(){this.triggerWrap&&(this.unbindTrigger(),this.onTriggerActivate=e=>{this.disabled||this.menu?.contains(e.target)||(e.preventDefault(),e.stopPropagation(),this.toggleOpen())},this.triggerWrap.addEventListener("click",this.onTriggerActivate),this.triggerWrap.addEventListener("keydown",this.handleTriggerKeyDown))}unbindTrigger(){this.triggerWrap&&this.onTriggerActivate&&this.triggerWrap.removeEventListener("click",this.onTriggerActivate),this.triggerWrap&&this.triggerWrap.removeEventListener("keydown",this.handleTriggerKeyDown),this.onTriggerActivate=null}toggleOpen(){this.disabled||(this.open=!this.open,this.open&&requestAnimationFrame(()=>this.focusItem(0)),this.render())}triggerSignature(){return[this.resolvedSize(),this.getAttribute("trigger-variant")||"tertiary",this.hasAttribute("icon-only")?"1":"0",this.getAttribute("trigger-icon")||"",this.fullWidth?"1":"0",this.showChevron?"1":"0"].join("|")}renderDefaultTrigger(){const e=this.resolvedSize(),i=this.getAttribute("trigger-variant")||"tertiary",r=n.includes(i)?i:"tertiary",s=this.hasAttribute("icon-only"),o=this.getAttribute("trigger-icon"),a=document.createElement("db-button");if(a.setAttribute("type","button"),a.setAttribute("variant",r),a.setAttribute("size",e),a.className="designbase-wc-dropdown__trigger",a.setAttribute("aria-haspopup","menu"),a.setAttribute("aria-label",this.triggerLabel()),this.fullWidth&&a.setAttribute("full-width",""),s)a.setAttribute("icon-only",""),a.setAttribute("start-icon",o&&t(o)?o:"edit"),a.removeAttribute("end-icon");else{a.removeAttribute("icon-only"),o&&t(o)?a.setAttribute("start-icon",o):a.removeAttribute("start-icon");const e=document.createElement("span");e.className="designbase-wc-dropdown__trigger-label",e.textContent=this.triggerLabel(),a.append(e),this.showChevron&&a.setAttribute("end-icon","chevron-down")}return a}syncDefaultTriggerState(e){e.setAttribute("aria-expanded",String(this.open)),e.setAttribute("aria-label",this.triggerLabel()),e.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),this.disabled?e.setAttribute("disabled",""):e.removeAttribute("disabled");const t=e.querySelector(".designbase-wc-dropdown__trigger-label");t&&(t.textContent=this.triggerLabel())}ensureStructure(){this.triggerWrap||(this.triggerWrap=document.createElement("div"),this.triggerWrap.className="designbase-wc-dropdown__trigger-wrap",this.triggerWrap.setAttribute("data-wc-internal","")),this.menu||(this.menu=document.createElement("div"),this.menu.className="designbase-wc-dropdown__menu",this.menu.setAttribute("data-wc-internal",""),this.menu.setAttribute("role","menu"));const e=this.triggerWrap,t=this.menu;e&&t&&(this.contains(e)||this.append(e),e.contains(t)||e.append(t),Array.from(this.children).forEach(i=>{i===e||i.hasAttribute("data-wc-internal")||("content"===i.getAttribute("slot")?t.append(i):e.insertBefore(i,t))}))}renderTrigger(){const e=this.triggerWrap,t=this.menu;if(!e||!t)return;const i=this.collectTriggerChildren();if(i.length>0){this.defaultTrigger?.remove(),this.defaultTrigger=void 0;Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),i.forEach(i=>{i.setAttribute("aria-haspopup","menu"),i.setAttribute("aria-expanded",String(this.open)),i.classList.toggle("designbase-wc-dropdown__trigger--open",this.open),e.insertBefore(i,t)})}else{Array.from(e.children).filter(e=>e!==t&&e!==this.defaultTrigger).forEach(e=>e.remove()),this.defaultTrigger&&this.triggerSignature()===this.lastTriggerSignature||(this.defaultTrigger?.remove(),this.defaultTrigger=this.renderDefaultTrigger(),this.lastTriggerSignature=this.triggerSignature(),e.insertBefore(this.defaultTrigger,t)),this.defaultTrigger&&this.syncDefaultTriggerState(this.defaultTrigger)}this.bindTrigger()}renderMenu(){const e=this.resolvedPlacement();this.menu.className=`designbase-wc-dropdown__menu designbase-wc-dropdown__menu--${e}${this.open?" designbase-wc-dropdown__menu--open":""}`,this.menu.setAttribute("aria-hidden",String(!this.open)),this.menu.setAttribute("aria-label",this.triggerLabel());const t=this.menu.querySelector(':scope > [slot="content"]');if(this.menu.setAttribute("role",t?"dialog":"menu"),t)return this.menu.inert=!this.open,this.menu.setAttribute("aria-modal","false"),this.menu.classList.add("designbase-wc-dropdown__menu--custom"),void this.triggerWrap?.querySelector("[aria-haspopup]")?.setAttribute("aria-haspopup","dialog");this.menu.inert=!1,this.menu.removeAttribute("aria-modal"),this.menu.replaceChildren();const r=this.menuItemIconSize();this.parsedItems.forEach((e,t)=>{if(e.divider){const e=document.createElement("div");return e.className="designbase-wc-dropdown__divider",e.setAttribute("role","separator"),void this.menu?.append(e)}e.id||e.label||String(t);const s=e.label||e.id,n=Boolean(e.disabled||this.disabled),o=this.focusedIndex===t,a=document.createElement("button");if(a.type="button",a.className=["designbase-wc-dropdown__item",n&&"designbase-wc-dropdown__item--disabled",o&&"designbase-wc-dropdown__item--focused"].filter(Boolean).join(" "),a.setAttribute("role","menuitem"),a.disabled=n,a.tabIndex=o?0:-1,a.dataset.index=String(t),e.icon){const t=i(e.icon,r);t.classList.add("designbase-wc-dropdown__item-icon"),a.append(t)}const d=document.createElement("span");d.className="designbase-wc-dropdown__item-label",d.textContent=s,a.append(d),a.addEventListener("click",t=>{t.stopPropagation(),this.selectItem(e)}),this.menu?.append(a)})}render(){const t=this.resolvedSize();e(this,["designbase-wc-dropdown",`designbase-wc-dropdown--${t}`,this.open&&"designbase-wc-dropdown--open",this.fullWidth&&"designbase-wc-dropdown--full-width",this.disabled&&"designbase-wc-dropdown--disabled"]),this.ensureStructure(),this.renderTrigger(),this.renderMenu()}selectItem(e){e.disabled||e.divider||(this.open=!1,this.focusedIndex=-1,this.dispatchEvent(new CustomEvent("db-change",{detail:{value:e.label||e.id,id:e.id,item:e},bubbles:!0,composed:!0})),this.render(),this.triggerWrap?.querySelector("[aria-haspopup]")?.focus())}focusItem(e){if(this.menu?.querySelector(':scope > [slot="content"]'))return void this.menu.querySelector('input:not([disabled]), button:not([disabled]), [tabindex="0"]')?.focus();const t=this.enabledItems();if(!t.length)return;const i=t[Math.max(0,Math.min(e,t.length-1))],r=this.parsedItems.indexOf(i);this.focusedIndex=r;Array.from(this.menu?.querySelectorAll(".designbase-wc-dropdown__item")||[]).forEach(e=>{const t=Number(e.dataset.index)===r;e.classList.toggle("designbase-wc-dropdown__item--focused",t),e.tabIndex=t?0:-1,t&&e.focus()})}}customElements.get("db-dropdown")||customElements.define("db-dropdown",DbDropdown);export{DbDropdown};