@designbasekorea/ui-wc 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE-WORLD-MAP.md +10 -0
  3. package/README.md +58 -0
  4. package/dist/esm/components/db-achievement-list.d.ts +2 -0
  5. package/dist/esm/components/db-achievement-list.js +1 -1
  6. package/dist/esm/components/db-activity-heatmap.d.ts +1 -0
  7. package/dist/esm/components/db-activity-heatmap.js +1 -1
  8. package/dist/esm/components/db-ad-banner.d.ts +2 -0
  9. package/dist/esm/components/db-ad-banner.js +1 -1
  10. package/dist/esm/components/db-ai-chat-list.d.ts +5 -1
  11. package/dist/esm/components/db-ai-chat-list.js +1 -1
  12. package/dist/esm/components/db-ai-chat.d.ts +2 -0
  13. package/dist/esm/components/db-ai-chat.js +1 -1
  14. package/dist/esm/components/db-ai-file-tree.js +1 -1
  15. package/dist/esm/components/db-alert.d.ts +1 -0
  16. package/dist/esm/components/db-alert.js +1 -1
  17. package/dist/esm/components/db-audio-player.d.ts +2 -0
  18. package/dist/esm/components/db-audio-player.js +1 -1
  19. package/dist/esm/components/db-avatar.d.ts +1 -0
  20. package/dist/esm/components/db-avatar.js +1 -1
  21. package/dist/esm/components/db-banner.d.ts +2 -0
  22. package/dist/esm/components/db-banner.js +1 -1
  23. package/dist/esm/components/db-button.d.ts +7 -1
  24. package/dist/esm/components/db-button.js +1 -1
  25. package/dist/esm/components/db-calendar.d.ts +5 -0
  26. package/dist/esm/components/db-calendar.js +1 -1
  27. package/dist/esm/components/db-card.d.ts +1 -0
  28. package/dist/esm/components/db-card.js +1 -1
  29. package/dist/esm/components/db-chat-composer.d.ts +3 -0
  30. package/dist/esm/components/db-chat-composer.js +1 -1
  31. package/dist/esm/components/db-chat-message.d.ts +2 -0
  32. package/dist/esm/components/db-chat-message.js +1 -1
  33. package/dist/esm/components/db-chat-room.d.ts +1 -0
  34. package/dist/esm/components/db-chat-room.js +1 -1
  35. package/dist/esm/components/db-chat-typing.d.ts +2 -0
  36. package/dist/esm/components/db-chat-typing.js +1 -1
  37. package/dist/esm/components/db-chat-widget.d.ts +9 -0
  38. package/dist/esm/components/db-chat-widget.js +1 -1
  39. package/dist/esm/components/db-chip.d.ts +2 -0
  40. package/dist/esm/components/db-chip.js +1 -1
  41. package/dist/esm/components/db-code-block.d.ts +1 -0
  42. package/dist/esm/components/db-code-block.js +1 -1
  43. package/dist/esm/components/db-color-picker.d.ts +4 -0
  44. package/dist/esm/components/db-color-picker.js +1 -1
  45. package/dist/esm/components/db-color-swatch.d.ts +3 -0
  46. package/dist/esm/components/db-color-swatch.js +1 -1
  47. package/dist/esm/components/db-cookie-banner.d.ts +3 -0
  48. package/dist/esm/components/db-cookie-banner.js +1 -1
  49. package/dist/esm/components/db-countdown.d.ts +2 -1
  50. package/dist/esm/components/db-countdown.js +1 -1
  51. package/dist/esm/components/db-date-picker.d.ts +3 -0
  52. package/dist/esm/components/db-date-picker.js +1 -1
  53. package/dist/esm/components/db-dropdown.d.ts +1 -0
  54. package/dist/esm/components/db-dropdown.js +1 -1
  55. package/dist/esm/components/db-dropzone.d.ts +2 -0
  56. package/dist/esm/components/db-dropzone.js +1 -1
  57. package/dist/esm/components/db-email-verify.d.ts +1 -0
  58. package/dist/esm/components/db-email-verify.js +1 -1
  59. package/dist/esm/components/db-file-uploader.d.ts +2 -0
  60. package/dist/esm/components/db-file-uploader.js +1 -1
  61. package/dist/esm/components/db-form.d.ts +2 -0
  62. package/dist/esm/components/db-form.js +1 -1
  63. package/dist/esm/components/db-gantt.d.ts +2 -0
  64. package/dist/esm/components/db-gantt.js +1 -1
  65. package/dist/esm/components/db-image-list.d.ts +3 -0
  66. package/dist/esm/components/db-image-list.js +1 -1
  67. package/dist/esm/components/db-image.d.ts +1 -0
  68. package/dist/esm/components/db-image.js +1 -1
  69. package/dist/esm/components/db-input-group.d.ts +30 -0
  70. package/dist/esm/components/db-input-group.js +1 -0
  71. package/dist/esm/components/db-input.d.ts +1 -0
  72. package/dist/esm/components/db-input.js +1 -1
  73. package/dist/esm/components/db-kanban.d.ts +3 -0
  74. package/dist/esm/components/db-kanban.js +1 -1
  75. package/dist/esm/components/db-lightbox.d.ts +2 -0
  76. package/dist/esm/components/db-lightbox.js +1 -1
  77. package/dist/esm/components/db-list.d.ts +2 -0
  78. package/dist/esm/components/db-list.js +1 -1
  79. package/dist/esm/components/db-markdown-editor.d.ts +2 -0
  80. package/dist/esm/components/db-markdown-editor.js +1 -1
  81. package/dist/esm/components/db-menu-item.js +1 -1
  82. package/dist/esm/components/db-navbar.d.ts +3 -0
  83. package/dist/esm/components/db-navbar.js +1 -1
  84. package/dist/esm/components/db-node.d.ts +1 -0
  85. package/dist/esm/components/db-node.js +1 -1
  86. package/dist/esm/components/db-onboarding-modal.d.ts +2 -0
  87. package/dist/esm/components/db-onboarding-modal.js +1 -1
  88. package/dist/esm/components/db-otp-input.d.ts +4 -1
  89. package/dist/esm/components/db-otp-input.js +1 -1
  90. package/dist/esm/components/db-page-header.js +1 -1
  91. package/dist/esm/components/db-popover.d.ts +1 -0
  92. package/dist/esm/components/db-popover.js +1 -1
  93. package/dist/esm/components/db-progress-step.d.ts +2 -0
  94. package/dist/esm/components/db-progress-step.js +1 -1
  95. package/dist/esm/components/db-range-slider.d.ts +1 -0
  96. package/dist/esm/components/db-range-slider.js +1 -1
  97. package/dist/esm/components/db-rating.d.ts +1 -0
  98. package/dist/esm/components/db-rating.js +1 -1
  99. package/dist/esm/components/db-search-bar.d.ts +2 -0
  100. package/dist/esm/components/db-search-bar.js +1 -1
  101. package/dist/esm/components/db-section-logo-cloud.js +1 -1
  102. package/dist/esm/components/db-share.d.ts +5 -0
  103. package/dist/esm/components/db-share.js +1 -1
  104. package/dist/esm/components/db-sidebar.d.ts +3 -0
  105. package/dist/esm/components/db-sidebar.js +1 -1
  106. package/dist/esm/components/db-signature.d.ts +2 -0
  107. package/dist/esm/components/db-signature.js +1 -1
  108. package/dist/esm/components/db-spinner.d.ts +2 -0
  109. package/dist/esm/components/db-spinner.js +1 -1
  110. package/dist/esm/components/db-stepper.d.ts +2 -0
  111. package/dist/esm/components/db-stepper.js +1 -1
  112. package/dist/esm/components/db-table.d.ts +2 -0
  113. package/dist/esm/components/db-table.js +1 -1
  114. package/dist/esm/components/db-tabs.d.ts +1 -0
  115. package/dist/esm/components/db-tabs.js +1 -1
  116. package/dist/esm/components/db-ticket.js +1 -1
  117. package/dist/esm/components/db-time-picker.d.ts +2 -0
  118. package/dist/esm/components/db-time-picker.js +1 -1
  119. package/dist/esm/components/db-timeline.d.ts +4 -0
  120. package/dist/esm/components/db-timeline.js +1 -1
  121. package/dist/esm/components/db-toast.d.ts +2 -0
  122. package/dist/esm/components/db-toast.js +1 -1
  123. package/dist/esm/components/db-tool-layout.d.ts +92 -0
  124. package/dist/esm/components/db-tool-layout.js +1 -0
  125. package/dist/esm/components/db-tool-panel.d.ts +50 -0
  126. package/dist/esm/components/db-tool-panel.js +1 -0
  127. package/dist/esm/components/db-top-banner.d.ts +2 -0
  128. package/dist/esm/components/db-top-banner.js +1 -1
  129. package/dist/esm/components/db-video-player.d.ts +3 -0
  130. package/dist/esm/components/db-video-player.js +1 -1
  131. package/dist/esm/components/db-world-map.d.ts +60 -0
  132. package/dist/esm/components/db-world-map.js +1 -0
  133. package/dist/esm/components/db-youtube-player.d.ts +2 -0
  134. package/dist/esm/components/db-youtube-player.js +1 -1
  135. package/dist/esm/components/db-zoom-control.d.ts +52 -0
  136. package/dist/esm/components/db-zoom-control.js +1 -0
  137. package/dist/esm/components/input-validation.js +1 -1
  138. package/dist/esm/components/paper-card.d.ts +2 -0
  139. package/dist/esm/components/paper-card.js +1 -1
  140. package/dist/esm/core/i18n-copy.js +1 -1
  141. package/dist/esm/core/i18n-en.js +1 -1
  142. package/dist/esm/core/i18n.d.ts +31 -1
  143. package/dist/esm/core/i18n.js +1 -1
  144. package/dist/esm/helpers/world-countries.js +1 -0
  145. package/dist/esm/helpers/world-land.js +1 -0
  146. package/dist/esm/index.d.ts +6 -1
  147. package/dist/esm/index.js +1 -1
  148. package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
  149. package/dist/index.cjs +1 -1
  150. package/dist/index.css +1 -1
  151. package/dist/index.d.ts +442 -6
  152. package/dist/index.esm.js +1 -1
  153. package/dist/react/index.cjs +1 -1
  154. package/dist/react/index.d.ts +837 -71
  155. package/dist/react/index.esm.js +1 -1
  156. package/package.json +4 -3
@@ -1 +1 @@
1
- import{dbText as e}from"../core/i18n.js";import{createDbIcon as t}from"./db-icons.js";import{TABLE_SIZES as s,TABLE_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTable extends HTMLElement{constructor(){super(...arguments),this.internalSelectedRows=[],this.internalSortDirection=null,this.internalPage=1}static get observedAttributes(){return["columns","data","title","size","variant","empty-message","sortable","sort-column","sort-direction","selectable","multi-select","selected-rows","row-key","loading","pagination","page","page-size","total-items","show-count-badge","clickable"]}get columns(){try{return JSON.parse(this.getAttribute("columns")||"[]")}catch{return[]}}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}get data(){try{return JSON.parse(this.getAttribute("data")||"[]")}catch{return[]}}set data(e){this.setAttribute("data","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.render()}attributeChangedCallback(e){"selected-rows"===e&&this.syncSelectedRowsFromAttribute(),"sort-column"!==e&&"sort-direction"!==e||this.syncSortFromAttributes(),"page"===e&&(this.internalPage=Number(this.getAttribute("page")||1)),this.render()}syncSelectedRowsFromAttribute(){try{this.internalSelectedRows=JSON.parse(this.getAttribute("selected-rows")||"[]")}catch{this.internalSelectedRows=[]}}syncSortFromAttributes(){const e=this.getAttribute("sort-column"),t=this.getAttribute("sort-direction");this.internalSortColumn=e||void 0,this.internalSortDirection="asc"===t||"desc"===t?t:null}getRowKey(e,t){const s=e[this.getAttribute("row-key")||"id"];return String(null!=s?s:t)}getSortedData(){const e=this.data,t=this.getAttribute("sort-column")||this.internalSortColumn,s=this.getAttribute("sort-direction")||this.internalSortDirection;if(!t||!s)return e;const n=this.columns.find(e=>e.key===t);return n?.sortable?[...e].sort((e,n)=>{const a=e[t],i=n[t];return a===i?0:null==a?1:null==i?-1:a<i?"asc"===s?-1:1:"asc"===s?1:-1}):e}handleSort(e){if(!this.hasAttribute("sortable")||!e.sortable)return;let t="asc";this.internalSortColumn===e.key&&("asc"===this.internalSortDirection?t="desc":"desc"===this.internalSortDirection&&(t=null)),this.internalSortColumn=t?e.key:void 0,this.internalSortDirection=t,this.dispatchEvent(new CustomEvent("db-sort-change",{bubbles:!0,composed:!0,detail:{column:e.key,direction:t}})),this.render()}handleRowSelect(e,t,s){s?.stopPropagation();let n;n=this.hasAttribute("multi-select")?t?[...this.internalSelectedRows,e]:this.internalSelectedRows.filter(t=>t!==e):t?[e]:[],this.internalSelectedRows=n,this.dispatchEvent(new CustomEvent("db-selection-change",{bubbles:!0,composed:!0,detail:{selectedRows:n}})),this.render()}handleSelectAll(e){const t=e?this.data.map((e,t)=>this.getRowKey(e,t)):[];this.internalSelectedRows=t,this.dispatchEvent(new CustomEvent("db-selection-change",{bubbles:!0,composed:!0,detail:{selectedRows:t}})),this.render()}getPaginatedData(){const e=this.getSortedData();if(!this.hasAttribute("pagination"))return e;const t=Number(this.getAttribute("page-size")||10),s=Number(this.getAttribute("total-items")||e.length),n=Math.max(1,Math.ceil(s/t)),a=(Math.min(this.internalPage,n)-1)*t;return e.slice(a,a+t)}createSortIcon(e){const s=document.createElement("span");s.className="designbase-wc-table__sort-icon";if(!(this.internalSortColumn===e.key&&Boolean(this.internalSortDirection))){s.classList.add("designbase-wc-table__sort-icon--idle");const e=document.createElement("span");return e.className="designbase-wc-table__sort-icon-stack",e.append(t("chevron-up",10),t("chevron-down",10)),s.append(e),s}return s.classList.add("asc"===this.internalSortDirection?"designbase-wc-table__sort-icon--asc":"designbase-wc-table__sort-icon--desc"),s.append(t("asc"===this.internalSortDirection?"chevron-up":"chevron-down",14)),s}createCheckbox(e){const t=document.createElement("db-checkbox");return t.setAttribute("size","s"),t.setAttribute("has-label","false"),e.checked&&t.setAttribute("checked",""),e.indeterminate&&t.setAttribute("indeterminate",""),e.stopPropagation&&t.addEventListener("click",e=>e.stopPropagation()),t.addEventListener("db-change",t=>{const s=t.detail;e.onChange?.(s.checked)}),t}render(){const t=this.getAttribute("size")||"m",a=this.getAttribute("variant")||"default",i=s.includes(t)?t:"m",c=n.includes(a)?a:"default",r=this.columns,o=this.getPaginatedData(),l=this.getSortedData(),d=this.hasAttribute("loading");d?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy");const b=this.hasAttribute("selectable"),h=this.hasAttribute("sortable"),u=this.getAttribute("empty-message")||"데이터가 없습니다.";if(this.className=["designbase-wc-table",`designbase-wc-table--${i}`,`designbase-wc-table--${c}`,b&&"designbase-wc-table--selectable",h&&"designbase-wc-table--sortable",d&&"designbase-wc-table--loading"].filter(Boolean).join(" "),this.replaceChildren(),d){const t=document.createElement("div");t.className="designbase-wc-table__loading";const s=document.createElement("div");s.className="designbase-wc-table__loading-spinner";const n=document.createElement("span");return n.textContent=e("로딩 중..."),t.append(s,n),void this.append(t)}const m=this.getAttribute("title"),g=this.hasAttribute("show-count-badge");if(m||g){const e=document.createElement("div");e.className="designbase-wc-table__header";const t=document.createElement("div");if(t.className="designbase-wc-table__header-left",m){const e=document.createElement("h3");e.className="designbase-wc-table__title",e.textContent=m,t.append(e)}if(g){const e=document.createElement("db-badge");e.setAttribute("count",String(this.data.length)),e.setAttribute("type","number"),e.setAttribute("variant","primary"),e.setAttribute("size","s"),t.append(e)}e.append(t),this.append(e)}const p=document.createElement("div");p.className="designbase-wc-table__container";const w=document.createElement("table");w.className="designbase-wc-table__table";const _=document.createElement("thead");_.className="designbase-wc-table__thead";const A=document.createElement("tr");A.className="designbase-wc-table__tr";const S=o.map((e,t)=>this.getRowKey(e,t)),E=S.filter(e=>this.internalSelectedRows.includes(e)),f=this.hasAttribute("clickable");if(b){const e=document.createElement("th");e.className="designbase-wc-table__th designbase-wc-table__th--checkbox";const t=this.createCheckbox({checked:S.length>0&&E.length===S.length,indeterminate:E.length>0&&E.length<S.length,onChange:e=>this.handleSelectAll(e)});e.append(t),A.append(e)}r.forEach(e=>{const t=document.createElement("th");t.className=["designbase-wc-table__th",`designbase-wc-table__th--${e.align||"left"}`,h&&e.sortable&&"designbase-wc-table__th--sortable",this.internalSortColumn===e.key&&this.internalSortDirection&&"designbase-wc-table__th--sorted"].filter(Boolean).join(" "),e.width&&(t.style.width="number"==typeof e.width?`${e.width}px`:e.width);const s=document.createElement("div");s.className="designbase-wc-table__th-content";const n=document.createElement("span");n.className="designbase-wc-table__th-text",n.textContent=e.header,s.append(n),h&&e.sortable&&s.append(this.createSortIcon(e)),t.append(s),h&&e.sortable&&t.addEventListener("click",()=>this.handleSort(e)),A.append(t)}),_.append(A);const y=document.createElement("tbody");if(y.className="designbase-wc-table__tbody",0===l.length){const t=document.createElement("tr");t.className="designbase-wc-table__tr";const s=document.createElement("td");s.className="designbase-wc-table__td designbase-wc-table__td--empty",s.colSpan=Math.max(r.length+(b?1:0),1);const n=document.createElement("db-empty-state");n.setAttribute("title",e("데이터가 없습니다")),n.setAttribute("description",u),n.setAttribute("variant","no-data"),n.setAttribute("size","m"),s.append(n),t.append(s),y.append(t)}else o.forEach((e,t)=>{const s=this.getRowKey(e,t),n=this.internalSelectedRows.includes(s),a=document.createElement("tr");if(a.className=["designbase-wc-table__tr",f&&"designbase-wc-table__tr--clickable",n&&"designbase-wc-table__tr--selected"].filter(Boolean).join(" "),f&&a.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-row-click",{detail:{item:e,index:t},bubbles:!0,composed:!0}))}),b){const e=document.createElement("td");e.className="designbase-wc-table__td designbase-wc-table__td--checkbox";const t=this.createCheckbox({checked:n,stopPropagation:!0,onChange:e=>this.handleRowSelect(s,e)});e.append(t),a.append(e)}r.forEach(t=>{const s=document.createElement("td");s.className=["designbase-wc-table__td",`designbase-wc-table__td--${t.align||"left"}`].join(" "),s.textContent=String(e[t.key]??""),a.append(s)}),y.append(a)});if(w.append(_,y),p.append(w),this.append(p),this.hasAttribute("pagination")){const e=Number(this.getAttribute("page-size")||10),t=Number(this.getAttribute("total-items")||l.length),s=Math.max(1,Math.ceil(t/e)),n=document.createElement("div");n.className="designbase-wc-table__footer";const a=document.createElement("db-pagination");a.setAttribute("current-page",String(this.internalPage)),a.setAttribute("total-pages",String(s)),a.setAttribute("size",i),a.setAttribute("show-first-last",""),a.addEventListener("db-change",e=>{const t=Number(e.detail?.page||1);this.internalPage=t,this.dispatchEvent(new CustomEvent("db-page-change",{bubbles:!0,composed:!0,detail:{page:t}})),this.render()}),n.append(a),this.append(n)}}}customElements.get("db-table")||customElements.define("db-table",DbTable);export{DbTable};
1
+ import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{TABLE_SIZES as n,TABLE_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTable extends HTMLElement{constructor(){super(...arguments),this.internalSelectedRows=[],this.internalSortDirection=null,this.internalPage=1}static get observedAttributes(){return["columns","data","title","size","variant","empty-message","sortable","sort-column","sort-direction","selectable","multi-select","selected-rows","row-key","loading","pagination","page","page-size","total-items","show-count-badge","clickable"]}get columns(){try{return JSON.parse(this.getAttribute("columns")||"[]")}catch{return[]}}set columns(e){this.setAttribute("columns","string"==typeof e?e:JSON.stringify(e))}get data(){try{return JSON.parse(this.getAttribute("data")||"[]")}catch{return[]}}set data(e){this.setAttribute("data","string"==typeof e?e:JSON.stringify(e))}connectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>{const e=this.querySelector(".designbase-wc-table__loading span");e&&(e.textContent=t("로딩 중..."));const s=this.querySelector(".designbase-wc-table__td--empty db-empty-state");s&&(s.setAttribute("title",t("데이터가 없습니다")),s.setAttribute("description",this.getAttribute("empty-message")||t("데이터가 없습니다.")))}),this.render()}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(e){"selected-rows"===e&&this.syncSelectedRowsFromAttribute(),"sort-column"!==e&&"sort-direction"!==e||this.syncSortFromAttributes(),"page"===e&&(this.internalPage=Number(this.getAttribute("page")||1)),this.render()}syncSelectedRowsFromAttribute(){try{this.internalSelectedRows=JSON.parse(this.getAttribute("selected-rows")||"[]")}catch{this.internalSelectedRows=[]}}syncSortFromAttributes(){const e=this.getAttribute("sort-column"),t=this.getAttribute("sort-direction");this.internalSortColumn=e||void 0,this.internalSortDirection="asc"===t||"desc"===t?t:null}getRowKey(e,t){const s=e[this.getAttribute("row-key")||"id"];return String(null!=s?s:t)}getSortedData(){const e=this.data,t=this.getAttribute("sort-column")||this.internalSortColumn,s=this.getAttribute("sort-direction")||this.internalSortDirection;if(!t||!s)return e;const n=this.columns.find(e=>e.key===t);return n?.sortable?[...e].sort((e,n)=>{const a=e[t],i=n[t];return a===i?0:null==a?1:null==i?-1:a<i?"asc"===s?-1:1:"asc"===s?1:-1}):e}handleSort(e){if(!this.hasAttribute("sortable")||!e.sortable)return;let t="asc";this.internalSortColumn===e.key&&("asc"===this.internalSortDirection?t="desc":"desc"===this.internalSortDirection&&(t=null)),this.internalSortColumn=t?e.key:void 0,this.internalSortDirection=t,this.dispatchEvent(new CustomEvent("db-sort-change",{bubbles:!0,composed:!0,detail:{column:e.key,direction:t}})),this.render()}handleRowSelect(e,t,s){s?.stopPropagation();let n;n=this.hasAttribute("multi-select")?t?[...this.internalSelectedRows,e]:this.internalSelectedRows.filter(t=>t!==e):t?[e]:[],this.internalSelectedRows=n,this.dispatchEvent(new CustomEvent("db-selection-change",{bubbles:!0,composed:!0,detail:{selectedRows:n}})),this.render()}handleSelectAll(e){const t=e?this.data.map((e,t)=>this.getRowKey(e,t)):[];this.internalSelectedRows=t,this.dispatchEvent(new CustomEvent("db-selection-change",{bubbles:!0,composed:!0,detail:{selectedRows:t}})),this.render()}getPaginatedData(){const e=this.getSortedData();if(!this.hasAttribute("pagination"))return e;const t=Number(this.getAttribute("page-size")||10),s=Number(this.getAttribute("total-items")||e.length),n=Math.max(1,Math.ceil(s/t)),a=(Math.min(this.internalPage,n)-1)*t;return e.slice(a,a+t)}createSortIcon(e){const t=document.createElement("span");t.className="designbase-wc-table__sort-icon";if(!(this.internalSortColumn===e.key&&Boolean(this.internalSortDirection))){t.classList.add("designbase-wc-table__sort-icon--idle");const e=document.createElement("span");return e.className="designbase-wc-table__sort-icon-stack",e.append(s("chevron-up",10),s("chevron-down",10)),t.append(e),t}return t.classList.add("asc"===this.internalSortDirection?"designbase-wc-table__sort-icon--asc":"designbase-wc-table__sort-icon--desc"),t.append(s("asc"===this.internalSortDirection?"chevron-up":"chevron-down",14)),t}createCheckbox(e){const t=document.createElement("db-checkbox");return t.setAttribute("size","s"),t.setAttribute("has-label","false"),e.checked&&t.setAttribute("checked",""),e.indeterminate&&t.setAttribute("indeterminate",""),e.stopPropagation&&t.addEventListener("click",e=>e.stopPropagation()),t.addEventListener("db-change",t=>{const s=t.detail;e.onChange?.(s.checked)}),t}render(){const e=this.getAttribute("size")||"m",s=this.getAttribute("variant")||"default",i=n.includes(e)?e:"m",c=a.includes(s)?s:"default",r=this.columns,o=this.getPaginatedData(),l=this.getSortedData(),d=this.hasAttribute("loading");d?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy");const b=this.hasAttribute("selectable"),h=this.hasAttribute("sortable"),u=this.getAttribute("empty-message")||t("데이터가 없습니다.");if(this.className=["designbase-wc-table",`designbase-wc-table--${i}`,`designbase-wc-table--${c}`,b&&"designbase-wc-table--selectable",h&&"designbase-wc-table--sortable",d&&"designbase-wc-table--loading"].filter(Boolean).join(" "),this.replaceChildren(),d){const e=document.createElement("div");e.className="designbase-wc-table__loading";const s=document.createElement("div");s.className="designbase-wc-table__loading-spinner";const n=document.createElement("span");return n.textContent=t("로딩 중..."),e.append(s,n),void this.append(e)}const m=this.getAttribute("title"),g=this.hasAttribute("show-count-badge");if(m||g){const e=document.createElement("div");e.className="designbase-wc-table__header";const t=document.createElement("div");if(t.className="designbase-wc-table__header-left",m){const e=document.createElement("h3");e.className="designbase-wc-table__title",e.textContent=m,t.append(e)}if(g){const e=document.createElement("db-badge");e.setAttribute("count",String(this.data.length)),e.setAttribute("type","number"),e.setAttribute("variant","primary"),e.setAttribute("size","s"),t.append(e)}e.append(t),this.append(e)}const p=document.createElement("div");p.className="designbase-wc-table__container";const w=document.createElement("table");w.className="designbase-wc-table__table";const _=document.createElement("thead");_.className="designbase-wc-table__thead";const A=document.createElement("tr");A.className="designbase-wc-table__tr";const S=o.map((e,t)=>this.getRowKey(e,t)),E=S.filter(e=>this.internalSelectedRows.includes(e)),y=this.hasAttribute("clickable");if(b){const e=document.createElement("th");e.className="designbase-wc-table__th designbase-wc-table__th--checkbox";const t=this.createCheckbox({checked:S.length>0&&E.length===S.length,indeterminate:E.length>0&&E.length<S.length,onChange:e=>this.handleSelectAll(e)});e.append(t),A.append(e)}r.forEach(e=>{const t=document.createElement("th");t.className=["designbase-wc-table__th",`designbase-wc-table__th--${e.align||"left"}`,h&&e.sortable&&"designbase-wc-table__th--sortable",this.internalSortColumn===e.key&&this.internalSortDirection&&"designbase-wc-table__th--sorted"].filter(Boolean).join(" "),e.width&&(t.style.width="number"==typeof e.width?`${e.width}px`:e.width);const s=document.createElement("div");s.className="designbase-wc-table__th-content";const n=document.createElement("span");n.className="designbase-wc-table__th-text",n.textContent=e.header,s.append(n),h&&e.sortable&&s.append(this.createSortIcon(e)),t.append(s),h&&e.sortable&&t.addEventListener("click",()=>this.handleSort(e)),A.append(t)}),_.append(A);const f=document.createElement("tbody");if(f.className="designbase-wc-table__tbody",0===l.length){const e=document.createElement("tr");e.className="designbase-wc-table__tr";const s=document.createElement("td");s.className="designbase-wc-table__td designbase-wc-table__td--empty",s.colSpan=Math.max(r.length+(b?1:0),1);const n=document.createElement("db-empty-state");n.setAttribute("title",t("데이터가 없습니다")),n.setAttribute("description",u),n.setAttribute("variant","no-data"),n.setAttribute("size","m"),s.append(n),e.append(s),f.append(e)}else o.forEach((e,t)=>{const s=this.getRowKey(e,t),n=this.internalSelectedRows.includes(s),a=document.createElement("tr");if(a.className=["designbase-wc-table__tr",y&&"designbase-wc-table__tr--clickable",n&&"designbase-wc-table__tr--selected"].filter(Boolean).join(" "),y&&a.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-row-click",{detail:{item:e,index:t},bubbles:!0,composed:!0}))}),b){const e=document.createElement("td");e.className="designbase-wc-table__td designbase-wc-table__td--checkbox";const t=this.createCheckbox({checked:n,stopPropagation:!0,onChange:e=>this.handleRowSelect(s,e)});e.append(t),a.append(e)}r.forEach(t=>{const s=document.createElement("td");s.className=["designbase-wc-table__td",`designbase-wc-table__td--${t.align||"left"}`].join(" "),s.textContent=String(e[t.key]??""),a.append(s)}),f.append(a)});if(w.append(_,f),p.append(w),this.append(p),this.hasAttribute("pagination")){const e=Number(this.getAttribute("page-size")||10),t=Number(this.getAttribute("total-items")||l.length),s=Math.max(1,Math.ceil(t/e)),n=document.createElement("div");n.className="designbase-wc-table__footer";const a=document.createElement("db-pagination");a.setAttribute("current-page",String(this.internalPage)),a.setAttribute("total-pages",String(s)),a.setAttribute("size",i),a.setAttribute("show-first-last",""),a.addEventListener("db-change",e=>{const t=Number(e.detail?.page||1);this.internalPage=t,this.dispatchEvent(new CustomEvent("db-page-change",{bubbles:!0,composed:!0,detail:{page:t}})),this.render()}),n.append(a),this.append(n)}}}customElements.get("db-table")||customElements.define("db-table",DbTable);export{DbTable};
@@ -5,6 +5,7 @@ interface TabItemConfig {
5
5
  icon?: string;
6
6
  }
7
7
  declare class DbTabs extends HTMLElement {
8
+ private unsubscribeLocale?;
8
9
  static get observedAttributes(): string[];
9
10
  private readonly uid;
10
11
  private readonly records;
@@ -1 +1 @@
1
- import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{labelFrom as i}from"../core/i18n.js";import{dbUid as s}from"../core/uid.js";import{setHostClasses as n}from"../core/host-class.js";import{coerceToContract as r}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TABS_ORIENTATIONS as a,TABS_SIZES as o,TABS_VARIANTS as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTabs extends HTMLElement{constructor(){super(...arguments),this.uid=s("db-tabs"),this.records=new Map,this.slotNodes=new Set,this.rendering=!1,this.reflecting=!1,this.suppressClick=!1,this.beginDrag=t=>{if(!this.list||"touch"===t.pointerType||!t.isPrimary||0!==t.button||this.drag)return;if(!("horizontal"===this.orientation?this.list.scrollWidth>this.list.clientWidth+1:this.list.scrollHeight>this.list.clientHeight+1))return;const e=t.target instanceof Element&&t.target.closest("button")||this.list;this.drag={id:t.pointerId,target:e,x:t.clientX,y:t.clientY,left:this.list.scrollLeft,top:this.list.scrollTop,moved:!1};try{e.setPointerCapture(t.pointerId)}catch{}},this.moveDrag=t=>{const e=this.drag;if(!e||!this.list||e.id!==t.pointerId)return;const i="horizontal"===this.orientation?t.clientX-e.x:t.clientY-e.y;!e.moved&&Math.abs(i)<6||(e.moved=!0,this.list.classList.add("designbase-wc-tabs__list--dragging"),t.cancelable&&t.preventDefault(),"horizontal"===this.orientation?this.list.scrollLeft=e.left-i:this.list.scrollTop=e.top-i)},this.finishDrag=t=>{t.pointerId===this.drag?.id&&(this.moveDrag(t),this.endDrag(!1))},this.cancelDrag=t=>{t.pointerId===this.drag?.id&&this.endDrag(!0)},this.captureClick=t=>{this.suppressClick&&(t.preventDefault(),t.stopImmediatePropagation())},this.handleResize=()=>{this.isConnected&&(void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=requestAnimationFrame(()=>{this.resizeRaf=void 0,this.handleListScroll(),this.updateIndicator()}))},this.handleListScroll=()=>{if(!this.list)return;const t="rtl"===getComputedStyle(this).direction,e=[...this.records.values()],i=e[e.length-1]?.button.getBoundingClientRect(),s=this.list.getBoundingClientRect(),n="horizontal"===this.orientation&&!!i&&(t?i.left<s.left-1:i.right>s.right+1);this.list.classList.toggle("designbase-wc-tabs__list--show-gradient",n)}}static get observedAttributes(){return["labels","items","active-index","selected-id","orientation","size","variant","full-width","aria-label","aria-labelledby","aria-describedby","label-tablist","dir"]}get tabItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t.filter(t=>!!t&&"object"==typeof t&&"string"==typeof t.label&&t.label.trim().length>0):[]}catch{return[]}}set tabItems(t){this.items=t}get items(){return this.tabItems}set items(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}get labels(){const t=this.tabItems;if(t.length)return t.map(t=>t.label);const e=this.getAttribute("labels")||"";try{const t=JSON.parse(e);if(Array.isArray(t))return t.filter(t=>"string"==typeof t&&!!t.trim())}catch{}return e.split(",").map(t=>t.trim()).filter(Boolean)}set labels(t){this.setAttribute("labels",Array.isArray(t)?JSON.stringify(t):t)}entries(){const t=this.tabItems,e=new Set;return this.labels.map((i,s)=>{const n=t[s]||{label:i},r="string"==typeof n.id&&n.id?n.id:String(s);let a=r,o=1;for(;e.has(a);)a=`${r}#${++o}`;return e.add(a),{key:a,item:n,index:s}})}get activeIndex(){const t=this.entries(),e=this.getAttribute("selected-id");let i=e?t.findIndex(t=>t.key===e):-1;if(i<0){const t=Number(this.getAttribute("active-index")||0);i=Number.isFinite(t)?Math.trunc(t):0}if(i=Math.max(0,Math.min(i,t.length-1)),t[i]&&!t[i].item.disabled)return i;const s=t.find(t=>t.index>=i&&!t.item.disabled);return s?.index??t.find(t=>!t.item.disabled)?.index??-1}set activeIndex(t){this.reflecting=!0;try{this.removeAttribute("selected-id"),this.setAttribute("active-index",String(t))}finally{this.reflecting=!1}this.isConnected&&this.render()}get selectedId(){return this.entries()[this.activeIndex]?.key||""}set selectedId(t){this.setAttribute("selected-id",t)}get orientation(){return r(this.getAttribute("orientation"),a,"horizontal")}set orientation(t){this.setAttribute("orientation",t)}get size(){return r(this.getAttribute("size"),o,"m")}set size(t){this.setAttribute("size",t)}get variant(){return r(this.getAttribute("variant"),l,"default")}set variant(t){this.setAttribute("variant",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){for(const t of["items","tabItems","labels","activeIndex","selectedId","orientation","size","variant","fullWidth"])if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}this.resizeObserver??(this.resizeObserver=new ResizeObserver(this.handleResize)),this.resizeObserver.observe(this),this.render(),this.resizeObserver.observe(this.list);for(const t of this.records.values())this.resizeObserver.observe(t.button);window.addEventListener("resize",this.handleResize),document.fonts?.addEventListener("loadingdone",this.handleResize),this.childObserver??(this.childObserver=new MutationObserver(t=>{if(this.rendering)return;t.some(t=>"attributes"===t.type||Array.from(t.addedNodes).some(t=>t instanceof HTMLElement&&t.parentElement===this&&void 0!==this.slotIndex(t))||Array.from(t.removedNodes).some(t=>t instanceof HTMLElement&&(this.slotNodes.has(t)&&!this.contains(t)||[...this.records.values()].some(e=>e.panel===t)&&t.parentElement!==this)))&&this.render()})),this.childObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["slot","data-panel-index"]})}disconnectedCallback(){this.endDrag(!0),void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.suppressClick=!1,this.clickTimer=void 0,window.removeEventListener("resize",this.handleResize),document.fonts?.removeEventListener("loadingdone",this.handleResize),this.resizeObserver?.disconnect(),this.childObserver?.disconnect(),void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=void 0}attributeChangedCallback(t,e,i){if(!this.reflecting&&e!==i){if("active-index"===t&&this.isConnected){this.reflecting=!0;try{this.removeAttribute("selected-id")}finally{this.reflecting=!1}}this.isConnected&&this.render()}}refresh(){this.isConnected&&this.render()}focus(t){this.records.get(this.selectedId)?.button.focus(t)}slotIndex(t){const e=t.getAttribute("slot")?.match(/^panel-(\d+)$/),i=e?.[1]??t.dataset.panelIndex;if(void 0===i||""===i.trim())return;const s=Number(i);return Number.isInteger(s)&&s>=0?s:void 0}collectSlots(){for(const t of Array.from(this.children))t instanceof HTMLElement&&void 0!==this.slotIndex(t)&&this.slotNodes.add(t);const t=new Map;for(const e of this.slotNodes){if(!this.contains(e)){this.slotNodes.delete(e);continue}const i=this.slotIndex(e);if(void 0===i)continue;const s=t.get(i)||[];s.push(e),t.set(i,s)}return t}createRecord(t){const e=document.createElement("button");e.type="button",e.setAttribute("role","tab");const i=s(this.uid);e.id=`${i}-tab`;const n=document.createElement("span");n.className="designbase-wc-tabs__tab-icon",n.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className="designbase-wc-tabs__tab-label",e.append(n,r);const a=document.createElement("div");a.id=`${i}-panel`,a.className="designbase-wc-tabs__panel",a.setAttribute("role","tabpanel"),a.setAttribute("aria-labelledby",e.id),a.tabIndex=0;const o=document.createElement("div");return o.id=`${i}-inner`,o.className="designbase-wc-tabs__panel-inner",a.append(o),e.addEventListener("click",()=>this.select(t)),e.addEventListener("focus",()=>{this.focusedKey=t,this.syncRoving()}),e.addEventListener("keydown",e=>this.navigate(e,t)),this.resizeObserver?.observe(e),{button:e,icon:n,label:r,panel:a,inner:o}}hideUnassigned(t){this.stash??(this.stash=Object.assign(document.createElement("div"),{hidden:!0,inert:!0})),this.stash.parentElement||this.append(this.stash),t.parentElement!==this.stash&&this.stash.append(t)}render(){if(!this.rendering){this.drag&&this.endDrag(!0),this.rendering=!0;try{const s=this.entries(),r=this.activeIndex,a=s[r]?.key||"",o=document.activeElement,l=[...this.records.values()].findIndex(t=>t.button===o||t.panel.contains(o)),d=this.collectSlots(),h=new Set;this.list??(this.list=document.createElement("div")),this.list.parentElement||(this.list.addEventListener("scroll",this.handleListScroll,{passive:!0}),this.list.addEventListener("pointerdown",this.beginDrag),this.list.addEventListener("pointermove",this.moveDrag),this.list.addEventListener("pointerup",this.finishDrag),this.list.addEventListener("pointercancel",this.cancelDrag),this.list.addEventListener("lostpointercapture",this.cancelDrag),this.list.addEventListener("click",this.captureClick,!0),this.prepend(this.list)),this.list.className=`designbase-wc-tabs__list designbase-wc-tabs__list--${this.orientation}${this.fullWidth?" designbase-wc-tabs__list--full-width":""}`,this.list.setAttribute("role","tablist"),this.list.setAttribute("aria-orientation",this.orientation),this.list.setAttribute("aria-label",this.getAttribute("aria-label")||i(this,"label-tablist","tabs.label"));for(const t of["aria-labelledby","aria-describedby"])this.hasAttribute(t)?this.list.setAttribute(t,this.getAttribute(t)):this.list.removeAttribute(t);const c=[];let b=null,u=this.list;for(const{key:i,item:n,index:a}of s){const s=this.records.get(i)||this.createRecord(i);c.push([i,s]),s.button.className=`designbase-wc-tabs__tab${a===r?" designbase-wc-tabs__tab--selected":""}${n.disabled?" designbase-wc-tabs__tab--disabled":""}`,s.button.disabled=Boolean(n.disabled),s.button.setAttribute("aria-selected",String(a===r)),s.label.textContent=n.label;const o=`${n.icon}:${this.size}`;if(s.iconSignature!==o){s.icon.replaceChildren();const i=n.icon,r="string"==typeof i&&t(i);s.icon.hidden=!r,r&&s.icon.append(e(i,"s"===this.size?16:"l"===this.size?20:18)),s.iconSignature=o}if(s.inner.dataset.dbTabsContentIndex=String(a),!s.inner.hasAttribute("data-db-react-content")){const t=d.get(a)||[];for(const e of Array.from(s.inner.children))t.includes(e)||this.hideUnassigned(e);for(const e of t)h.add(e),e.parentElement!==s.inner&&s.inner.append(e)}const l=b?b.nextElementSibling:this.list.firstElementChild;l!==s.button&&this.list.insertBefore(s.button,l),b=s.button;const g=u.nextElementSibling;g!==s.panel&&this.insertBefore(s.panel,g),u=s.panel}const g=new Set(s.map(t=>t.key));for(const[t,e]of this.records)if(!g.has(t)){for(const t of this.slotNodes)e.panel.contains(t)&&!h.has(t)&&this.hideUnassigned(t);this.resizeObserver?.unobserve(e.button),e.button.remove(),e.panel.remove()}for(const t of this.slotNodes)h.has(t)||this.hideUnassigned(t);this.records.clear();for(const[t,e]of c)this.records.set(t,e);const f=c.some(([,t])=>t.inner.childNodes.length>0||t.inner.hasAttribute("data-db-react-content"));n(this,["designbase-wc-tabs",`designbase-wc-tabs--${this.orientation}`,`designbase-wc-tabs--${this.size}`,`designbase-wc-tabs--${this.variant}`,this.fullWidth&&"designbase-wc-tabs--full-width",!f&&"designbase-wc-tabs--nav-only"]);for(const[t,e]of c){const i=f&&t===a;e.panel.hidden=!i,e.panel.inert=!i,e.panel.setAttribute("aria-hidden",String(!i)),f?e.button.setAttribute("aria-controls",e.panel.id):e.button.removeAttribute("aria-controls")}this.focusedKey&&this.records.has(this.focusedKey)&&!this.records.get(this.focusedKey)?.button.disabled||(this.focusedKey=a),this.list.contains(o)||(this.focusedKey=a),this.syncRoving(),this.reflecting=!0;try{this.setAttribute("active-index",String(r)),a?this.setAttribute("selected-id",a):this.removeAttribute("selected-id")}finally{this.reflecting=!1}"default"===this.variant&&a?(this.indicator??(this.indicator=document.createElement("span")),this.indicator.className="designbase-wc-tabs__indicator designbase-wc-tabs__indicator--no-transition",this.indicator.setAttribute("aria-hidden","true"),this.indicator.parentElement!==this.list&&this.list.append(this.indicator)):this.indicator?.remove(),o instanceof HTMLElement&&l>=0&&(document.activeElement!==o||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled)&&(!o.isConnected||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled?this.records.get(a)?.button.focus({preventScroll:!0}):o.focus({preventScroll:!0})),this.handleResize()}finally{this.rendering=!1}this.dispatchEvent(new Event("db-content-targets-change"))}}syncRoving(){for(const[t,e]of this.records)e.button.tabIndex=e.button.disabled||t!==this.focusedKey?-1:0}select(t){if(this.suppressClick)return;const e=this.entries().find(e=>e.key===t);e&&!e.item.disabled&&(this.focusedKey=t,this.syncRoving(),t!==this.selectedId&&(this.selectedId=t,this.dispatchEvent(new CustomEvent("db-change",{detail:{index:e.index,label:e.item.label,id:t},bubbles:!0,composed:!0})),this.ensureVisible(this.records.get(t).button)))}navigate(t,e){if(t.altKey||t.ctrlKey||t.metaKey)return;const i=this.entries().filter(t=>!t.item.disabled),s=i.findIndex(t=>t.key===e);if(s<0)return;let n=s;const r="vertical"===this.orientation,a="rtl"===getComputedStyle(this).direction;if("Home"===t.key)n=0;else if("End"===t.key)n=i.length-1;else if(!r||"ArrowDown"!==t.key&&"ArrowUp"!==t.key){if(r||"ArrowRight"!==t.key&&"ArrowLeft"!==t.key)return;n=(s+("ArrowRight"===t.key!==a?1:-1)+i.length)%i.length}else n=(s+("ArrowDown"===t.key?1:-1)+i.length)%i.length;t.preventDefault();const o=this.records.get(i[n].key).button;o.focus({preventScroll:!0}),this.ensureVisible(o)}ensureVisible(t){if(!this.list)return;const e=t.getBoundingClientRect(),i=this.list.getBoundingClientRect();"horizontal"===this.orientation?this.list.scrollBy({left:e.left<i.left?e.left-i.left:e.right>i.right?e.right-i.right:0,behavior:"auto"}):this.list.scrollBy({top:e.top<i.top?e.top-i.top:e.bottom>i.bottom?e.bottom-i.bottom:0,behavior:"auto"})}endDrag(t){const e=this.drag;if(this.drag=void 0,e){this.list?.classList.remove("designbase-wc-tabs__list--dragging"),e.moved&&(this.suppressClick=!0,void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.clickTimer=window.setTimeout(()=>{this.suppressClick=!1,this.clickTimer=void 0},0));try{e.target.hasPointerCapture(e.id)&&e.target.releasePointerCapture(e.id)}catch{}t&&this.handleListScroll()}}updateIndicator(){const t=this.records.get(this.selectedId)?.button;if(!t||!this.indicator?.isConnected)return;const e="vertical"===this.orientation;this.indicator.classList.toggle("designbase-wc-tabs__indicator--vertical",e),this.indicator.classList.toggle("designbase-wc-tabs__indicator--horizontal",!e),this.indicator.classList.add("designbase-wc-tabs__indicator--ready"),this.indicator.style.width=e?"2px":`${t.offsetWidth}px`,this.indicator.style.height=e?`${t.offsetHeight}px`:"2px",this.indicator.style.transform=e?`translate3d(0, ${t.offsetTop}px, 0)`:`translate3d(${t.offsetLeft}px, 0, 0)`}}customElements.get("db-tabs")||customElements.define("db-tabs",DbTabs);export{DbTabs};
1
+ import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{subscribeDbLocale as i,labelFrom as s}from"../core/i18n.js";import{dbUid as n}from"../core/uid.js";import{setHostClasses as r}from"../core/host-class.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TABS_ORIENTATIONS as o,TABS_SIZES as l,TABS_VARIANTS as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTabs extends HTMLElement{constructor(){super(...arguments),this.uid=n("db-tabs"),this.records=new Map,this.slotNodes=new Set,this.rendering=!1,this.reflecting=!1,this.suppressClick=!1,this.beginDrag=t=>{if(!this.list||"touch"===t.pointerType||!t.isPrimary||0!==t.button||this.drag)return;if(!("horizontal"===this.orientation?this.list.scrollWidth>this.list.clientWidth+1:this.list.scrollHeight>this.list.clientHeight+1))return;const e=t.target instanceof Element&&t.target.closest("button")||this.list;this.drag={id:t.pointerId,target:e,x:t.clientX,y:t.clientY,left:this.list.scrollLeft,top:this.list.scrollTop,moved:!1};try{e.setPointerCapture(t.pointerId)}catch{}},this.moveDrag=t=>{const e=this.drag;if(!e||!this.list||e.id!==t.pointerId)return;const i="horizontal"===this.orientation?t.clientX-e.x:t.clientY-e.y;!e.moved&&Math.abs(i)<6||(e.moved=!0,this.list.classList.add("designbase-wc-tabs__list--dragging"),t.cancelable&&t.preventDefault(),"horizontal"===this.orientation?this.list.scrollLeft=e.left-i:this.list.scrollTop=e.top-i)},this.finishDrag=t=>{t.pointerId===this.drag?.id&&(this.moveDrag(t),this.endDrag(!1))},this.cancelDrag=t=>{t.pointerId===this.drag?.id&&this.endDrag(!0)},this.captureClick=t=>{this.suppressClick&&(t.preventDefault(),t.stopImmediatePropagation())},this.handleResize=()=>{this.isConnected&&(void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=requestAnimationFrame(()=>{this.resizeRaf=void 0,this.handleListScroll(),this.updateIndicator()}))},this.handleListScroll=()=>{if(!this.list)return;const t="rtl"===getComputedStyle(this).direction,e=[...this.records.values()],i=e[e.length-1]?.button.getBoundingClientRect(),s=this.list.getBoundingClientRect(),n="horizontal"===this.orientation&&!!i&&(t?i.left<s.left-1:i.right>s.right+1);this.list.classList.toggle("designbase-wc-tabs__list--show-gradient",n)}}static get observedAttributes(){return["labels","items","active-index","selected-id","orientation","size","variant","full-width","aria-label","aria-labelledby","aria-describedby","label-tablist","dir"]}get tabItems(){try{const t=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(t)?t.filter(t=>!!t&&"object"==typeof t&&"string"==typeof t.label&&t.label.trim().length>0):[]}catch{return[]}}set tabItems(t){this.items=t}get items(){return this.tabItems}set items(t){this.setAttribute("items","string"==typeof t?t:JSON.stringify(t))}get labels(){const t=this.tabItems;if(t.length)return t.map(t=>t.label);const e=this.getAttribute("labels")||"";try{const t=JSON.parse(e);if(Array.isArray(t))return t.filter(t=>"string"==typeof t&&!!t.trim())}catch{}return e.split(",").map(t=>t.trim()).filter(Boolean)}set labels(t){this.setAttribute("labels",Array.isArray(t)?JSON.stringify(t):t)}entries(){const t=this.tabItems,e=new Set;return this.labels.map((i,s)=>{const n=t[s]||{label:i},r="string"==typeof n.id&&n.id?n.id:String(s);let a=r,o=1;for(;e.has(a);)a=`${r}#${++o}`;return e.add(a),{key:a,item:n,index:s}})}get activeIndex(){const t=this.entries(),e=this.getAttribute("selected-id");let i=e?t.findIndex(t=>t.key===e):-1;if(i<0){const t=Number(this.getAttribute("active-index")||0);i=Number.isFinite(t)?Math.trunc(t):0}if(i=Math.max(0,Math.min(i,t.length-1)),t[i]&&!t[i].item.disabled)return i;const s=t.find(t=>t.index>=i&&!t.item.disabled);return s?.index??t.find(t=>!t.item.disabled)?.index??-1}set activeIndex(t){this.reflecting=!0;try{this.removeAttribute("selected-id"),this.setAttribute("active-index",String(t))}finally{this.reflecting=!1}this.isConnected&&this.render()}get selectedId(){return this.entries()[this.activeIndex]?.key||""}set selectedId(t){this.setAttribute("selected-id",t)}get orientation(){return a(this.getAttribute("orientation"),o,"horizontal")}set orientation(t){this.setAttribute("orientation",t)}get size(){return a(this.getAttribute("size"),l,"m")}set size(t){this.setAttribute("size",t)}get variant(){return a(this.getAttribute("variant"),d,"default")}set variant(t){this.setAttribute("variant",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){for(const t of["items","tabItems","labels","activeIndex","selectedId","orientation","size","variant","fullWidth"])if(Object.prototype.hasOwnProperty.call(this,t)){const e=this[t];delete this[t],this[t]=e}this.resizeObserver??(this.resizeObserver=new ResizeObserver(this.handleResize)),this.resizeObserver.observe(this),this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=i(()=>{this.list?.setAttribute("aria-label",this.getAttribute("aria-label")||s(this,"label-tablist","tabs.label"))}),this.resizeObserver.observe(this.list);for(const t of this.records.values())this.resizeObserver.observe(t.button);window.addEventListener("resize",this.handleResize),document.fonts?.addEventListener("loadingdone",this.handleResize),this.childObserver??(this.childObserver=new MutationObserver(t=>{if(this.rendering)return;t.some(t=>"attributes"===t.type||Array.from(t.addedNodes).some(t=>t instanceof HTMLElement&&t.parentElement===this&&void 0!==this.slotIndex(t))||Array.from(t.removedNodes).some(t=>t instanceof HTMLElement&&(this.slotNodes.has(t)&&!this.contains(t)||[...this.records.values()].some(e=>e.panel===t)&&t.parentElement!==this)))&&this.render()})),this.childObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["slot","data-panel-index"]})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.endDrag(!0),void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.suppressClick=!1,this.clickTimer=void 0,window.removeEventListener("resize",this.handleResize),document.fonts?.removeEventListener("loadingdone",this.handleResize),this.resizeObserver?.disconnect(),this.childObserver?.disconnect(),void 0!==this.resizeRaf&&cancelAnimationFrame(this.resizeRaf),this.resizeRaf=void 0}attributeChangedCallback(t,e,i){if(!this.reflecting&&e!==i){if("active-index"===t&&this.isConnected){this.reflecting=!0;try{this.removeAttribute("selected-id")}finally{this.reflecting=!1}}this.isConnected&&this.render()}}refresh(){this.isConnected&&this.render()}focus(t){this.records.get(this.selectedId)?.button.focus(t)}slotIndex(t){const e=t.getAttribute("slot")?.match(/^panel-(\d+)$/),i=e?.[1]??t.dataset.panelIndex;if(void 0===i||""===i.trim())return;const s=Number(i);return Number.isInteger(s)&&s>=0?s:void 0}collectSlots(){for(const t of Array.from(this.children))t instanceof HTMLElement&&void 0!==this.slotIndex(t)&&this.slotNodes.add(t);const t=new Map;for(const e of this.slotNodes){if(!this.contains(e)){this.slotNodes.delete(e);continue}const i=this.slotIndex(e);if(void 0===i)continue;const s=t.get(i)||[];s.push(e),t.set(i,s)}return t}createRecord(t){const e=document.createElement("button");e.type="button",e.setAttribute("role","tab");const i=n(this.uid);e.id=`${i}-tab`;const s=document.createElement("span");s.className="designbase-wc-tabs__tab-icon",s.setAttribute("aria-hidden","true");const r=document.createElement("span");r.className="designbase-wc-tabs__tab-label",e.append(s,r);const a=document.createElement("div");a.id=`${i}-panel`,a.className="designbase-wc-tabs__panel",a.setAttribute("role","tabpanel"),a.setAttribute("aria-labelledby",e.id),a.tabIndex=0;const o=document.createElement("div");return o.id=`${i}-inner`,o.className="designbase-wc-tabs__panel-inner",a.append(o),e.addEventListener("click",()=>this.select(t)),e.addEventListener("focus",()=>{this.focusedKey=t,this.syncRoving()}),e.addEventListener("keydown",e=>this.navigate(e,t)),this.resizeObserver?.observe(e),{button:e,icon:s,label:r,panel:a,inner:o}}hideUnassigned(t){this.stash??(this.stash=Object.assign(document.createElement("div"),{hidden:!0,inert:!0})),this.stash.parentElement||this.append(this.stash),t.parentElement!==this.stash&&this.stash.append(t)}render(){if(!this.rendering){this.drag&&this.endDrag(!0),this.rendering=!0;try{const i=this.entries(),n=this.activeIndex,a=i[n]?.key||"",o=document.activeElement,l=[...this.records.values()].findIndex(t=>t.button===o||t.panel.contains(o)),d=this.collectSlots(),h=new Set;this.list??(this.list=document.createElement("div")),this.list.parentElement||(this.list.addEventListener("scroll",this.handleListScroll,{passive:!0}),this.list.addEventListener("pointerdown",this.beginDrag),this.list.addEventListener("pointermove",this.moveDrag),this.list.addEventListener("pointerup",this.finishDrag),this.list.addEventListener("pointercancel",this.cancelDrag),this.list.addEventListener("lostpointercapture",this.cancelDrag),this.list.addEventListener("click",this.captureClick,!0),this.prepend(this.list)),this.list.className=`designbase-wc-tabs__list designbase-wc-tabs__list--${this.orientation}${this.fullWidth?" designbase-wc-tabs__list--full-width":""}`,this.list.setAttribute("role","tablist"),this.list.setAttribute("aria-orientation",this.orientation),this.list.setAttribute("aria-label",this.getAttribute("aria-label")||s(this,"label-tablist","tabs.label"));for(const t of["aria-labelledby","aria-describedby"])this.hasAttribute(t)?this.list.setAttribute(t,this.getAttribute(t)):this.list.removeAttribute(t);const c=[];let b=null,u=this.list;for(const{key:s,item:r,index:a}of i){const i=this.records.get(s)||this.createRecord(s);c.push([s,i]),i.button.className=`designbase-wc-tabs__tab${a===n?" designbase-wc-tabs__tab--selected":""}${r.disabled?" designbase-wc-tabs__tab--disabled":""}`,i.button.disabled=Boolean(r.disabled),i.button.setAttribute("aria-selected",String(a===n)),i.label.textContent=r.label;const o=`${r.icon}:${this.size}`;if(i.iconSignature!==o){i.icon.replaceChildren();const s=r.icon,n="string"==typeof s&&t(s);i.icon.hidden=!n,n&&i.icon.append(e(s,"s"===this.size?16:"l"===this.size?20:18)),i.iconSignature=o}if(i.inner.dataset.dbTabsContentIndex=String(a),!i.inner.hasAttribute("data-db-react-content")){const t=d.get(a)||[];for(const e of Array.from(i.inner.children))t.includes(e)||this.hideUnassigned(e);for(const e of t)h.add(e),e.parentElement!==i.inner&&i.inner.append(e)}const l=b?b.nextElementSibling:this.list.firstElementChild;l!==i.button&&this.list.insertBefore(i.button,l),b=i.button;const g=u.nextElementSibling;g!==i.panel&&this.insertBefore(i.panel,g),u=i.panel}const g=new Set(i.map(t=>t.key));for(const[t,e]of this.records)if(!g.has(t)){for(const t of this.slotNodes)e.panel.contains(t)&&!h.has(t)&&this.hideUnassigned(t);this.resizeObserver?.unobserve(e.button),e.button.remove(),e.panel.remove()}for(const t of this.slotNodes)h.has(t)||this.hideUnassigned(t);this.records.clear();for(const[t,e]of c)this.records.set(t,e);const f=c.some(([,t])=>t.inner.childNodes.length>0||t.inner.hasAttribute("data-db-react-content"));r(this,["designbase-wc-tabs",`designbase-wc-tabs--${this.orientation}`,`designbase-wc-tabs--${this.size}`,`designbase-wc-tabs--${this.variant}`,this.fullWidth&&"designbase-wc-tabs--full-width",!f&&"designbase-wc-tabs--nav-only"]);for(const[t,e]of c){const i=f&&t===a;e.panel.hidden=!i,e.panel.inert=!i,e.panel.setAttribute("aria-hidden",String(!i)),f?e.button.setAttribute("aria-controls",e.panel.id):e.button.removeAttribute("aria-controls")}this.focusedKey&&this.records.has(this.focusedKey)&&!this.records.get(this.focusedKey)?.button.disabled||(this.focusedKey=a),this.list.contains(o)||(this.focusedKey=a),this.syncRoving(),this.reflecting=!0;try{this.setAttribute("active-index",String(n)),a?this.setAttribute("selected-id",a):this.removeAttribute("selected-id")}finally{this.reflecting=!1}"default"===this.variant&&a?(this.indicator??(this.indicator=document.createElement("span")),this.indicator.className="designbase-wc-tabs__indicator designbase-wc-tabs__indicator--no-transition",this.indicator.setAttribute("aria-hidden","true"),this.indicator.parentElement!==this.list&&this.list.append(this.indicator)):this.indicator?.remove(),o instanceof HTMLElement&&l>=0&&(document.activeElement!==o||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled)&&(!o.isConnected||o.closest("[inert]")||o instanceof HTMLButtonElement&&o.disabled?this.records.get(a)?.button.focus({preventScroll:!0}):o.focus({preventScroll:!0})),this.handleResize()}finally{this.rendering=!1}this.dispatchEvent(new Event("db-content-targets-change"))}}syncRoving(){for(const[t,e]of this.records)e.button.tabIndex=e.button.disabled||t!==this.focusedKey?-1:0}select(t){if(this.suppressClick)return;const e=this.entries().find(e=>e.key===t);e&&!e.item.disabled&&(this.focusedKey=t,this.syncRoving(),t!==this.selectedId&&(this.selectedId=t,this.dispatchEvent(new CustomEvent("db-change",{detail:{index:e.index,label:e.item.label,id:t},bubbles:!0,composed:!0})),this.ensureVisible(this.records.get(t).button)))}navigate(t,e){if(t.altKey||t.ctrlKey||t.metaKey)return;const i=this.entries().filter(t=>!t.item.disabled),s=i.findIndex(t=>t.key===e);if(s<0)return;let n=s;const r="vertical"===this.orientation,a="rtl"===getComputedStyle(this).direction;if("Home"===t.key)n=0;else if("End"===t.key)n=i.length-1;else if(!r||"ArrowDown"!==t.key&&"ArrowUp"!==t.key){if(r||"ArrowRight"!==t.key&&"ArrowLeft"!==t.key)return;n=(s+("ArrowRight"===t.key!==a?1:-1)+i.length)%i.length}else n=(s+("ArrowDown"===t.key?1:-1)+i.length)%i.length;t.preventDefault();const o=this.records.get(i[n].key).button;o.focus({preventScroll:!0}),this.ensureVisible(o)}ensureVisible(t){if(!this.list)return;const e=t.getBoundingClientRect(),i=this.list.getBoundingClientRect();"horizontal"===this.orientation?this.list.scrollBy({left:e.left<i.left?e.left-i.left:e.right>i.right?e.right-i.right:0,behavior:"auto"}):this.list.scrollBy({top:e.top<i.top?e.top-i.top:e.bottom>i.bottom?e.bottom-i.bottom:0,behavior:"auto"})}endDrag(t){const e=this.drag;if(this.drag=void 0,e){this.list?.classList.remove("designbase-wc-tabs__list--dragging"),e.moved&&(this.suppressClick=!0,void 0!==this.clickTimer&&clearTimeout(this.clickTimer),this.clickTimer=window.setTimeout(()=>{this.suppressClick=!1,this.clickTimer=void 0},0));try{e.target.hasPointerCapture(e.id)&&e.target.releasePointerCapture(e.id)}catch{}t&&this.handleListScroll()}}updateIndicator(){const t=this.records.get(this.selectedId)?.button;if(!t||!this.indicator?.isConnected)return;const e="vertical"===this.orientation;this.indicator.classList.toggle("designbase-wc-tabs__indicator--vertical",e),this.indicator.classList.toggle("designbase-wc-tabs__indicator--horizontal",!e),this.indicator.classList.add("designbase-wc-tabs__indicator--ready"),this.indicator.style.width=e?"2px":`${t.offsetWidth}px`,this.indicator.style.height=e?`${t.offsetHeight}px`:"2px",this.indicator.style.transform=e?`translate3d(0, ${t.offsetTop}px, 0)`:`translate3d(${t.offsetLeft}px, 0, 0)`}}customElements.get("db-tabs")||customElements.define("db-tabs",DbTabs);export{DbTabs};
@@ -1 +1 @@
1
- import{DbPaperCard as e,paperFields as t,paperJson as i,paperNode as s,paperDetails as r}from"./paper-card.js";class DbTicket extends e{static get observedAttributes(){return["layout","issuer","heading","description","reference","fields","edge","note","code-image-src","code-alt","action-label","disabled"]}upgradeNames(){return["fields"]}get fields(){return t(this.data??i(this.attr("fields")))}set fields(e){this.data=null==e?void 0:t(e),this.isConnected&&this.render()}render(){const e=s("section","db-paper__main");this.attr("issuer")&&e.append(s("div","db-paper__issuer",this.attr("issuer"))),e.append(s("h3","db-paper__title",this.attr("heading")||"티켓")),this.attr("description")&&e.append(s("p","db-paper__description",this.attr("description"))),this.fields.length&&e.append(r(this.fields));const t=s("div","db-paper__stub");t.append(this.code(this.attr("reference"))),this.attr("note")&&t.append(s("p","db-paper__note",this.attr("note")));const i=this.action(this.attr("reference"));i&&t.append(i),this.replace(e,t)}}customElements.get("db-ticket")||customElements.define("db-ticket",DbTicket);export{DbTicket};
1
+ import{DbPaperCard as e,paperFields as t,paperJson as i,paperNode as s,paperDetails as r}from"./paper-card.js";import{t as d}from"../core/i18n.js";class DbTicket extends e{static get observedAttributes(){return["layout","issuer","heading","description","reference","fields","edge","note","code-image-src","code-alt","action-label","disabled"]}upgradeNames(){return["fields"]}get fields(){return t(this.data??i(this.attr("fields")))}set fields(e){this.data=null==e?void 0:t(e),this.isConnected&&this.render()}render(){const e=s("section","db-paper__main");this.attr("issuer")&&e.append(s("div","db-paper__issuer",this.attr("issuer"))),e.append(s("h3","db-paper__title",this.attr("heading")||d("ticket.title"))),this.attr("description")&&e.append(s("p","db-paper__description",this.attr("description"))),this.fields.length&&e.append(r(this.fields));const t=s("div","db-paper__stub");t.append(this.code(this.attr("reference"))),this.attr("note")&&t.append(s("p","db-paper__note",this.attr("note")));const i=this.action(this.attr("reference"));i&&t.append(i),this.replace(e,t)}}customElements.get("db-ticket")||customElements.define("db-ticket",DbTicket);export{DbTicket};
@@ -15,6 +15,7 @@ declare class DbTimePicker extends HTMLElement {
15
15
  private seconds;
16
16
  private period;
17
17
  private inputText;
18
+ private unsubscribeLocale?;
18
19
  private tempHours;
19
20
  private tempMinutes;
20
21
  private tempSeconds;
@@ -24,6 +25,7 @@ declare class DbTimePicker extends HTMLElement {
24
25
  private viewportChangeFrame;
25
26
  connectedCallback(): void;
26
27
  disconnectedCallback(): void;
28
+ private syncLocale;
27
29
  /** 열린 드롭다운은 Escape 로 닫히고 포커스는 트리거로 돌아간다 (A11Y-ESCAPE) */
28
30
  private handleDocumentKeyDown;
29
31
  private boundDocumentKeyDown;
@@ -1 +1 @@
1
- import{inheritThemeScope as t}from"../core/theme-scope.js";import{dbText as e}from"../core/i18n.js";import{createDbIcon as i,getDbComponentIconSize as s}from"./db-icons.js";import"./db-button.js";import{TIME_PICKER_FORMATS as n,TIME_PICKER_SIZES as o,TIME_PICKER_DROPDOWN_POSITIONS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as h}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";const d="designbase-wc-time-picker";class DbTimePicker extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.isOpen=!1,this.hours=12,this.minutes=0,this.seconds=0,this.period="PM",this.inputText="",this.tempHours=12,this.tempMinutes=0,this.tempSeconds=0,this.tempPeriod="PM",this.boundDocumentMouseDown=t=>this.handleDocumentMouseDown(t),this.boundViewportChange=()=>this.handleViewportChange(),this.viewportChangeFrame=null,this.handleDocumentKeyDown=t=>{"Escape"===t.key&&this.isOpen&&(t.preventDefault(),this.closePicker(),this.inputEl?.focus())},this.boundDocumentKeyDown=t=>this.handleDocumentKeyDown(t)}static get observedAttributes(){return["value","default-value","type","format","minute-step","size","disabled","readonly","label","full-width","error","dropdown-position","open"]}connectedCallback(){this.built||this.build(),this.parseTimeString(this.getAttribute("value")??this.getAttribute("default-value")??"12:00"),this.syncInputText(),this.render(),document.addEventListener("mousedown",this.boundDocumentMouseDown),document.addEventListener("keydown",this.boundDocumentKeyDown),window.addEventListener("resize",this.boundViewportChange),window.addEventListener("scroll",this.boundViewportChange,{capture:!0,passive:!0})}disconnectedCallback(){document.removeEventListener("mousedown",this.boundDocumentMouseDown),document.removeEventListener("keydown",this.boundDocumentKeyDown),window.removeEventListener("resize",this.boundViewportChange),window.removeEventListener("scroll",this.boundViewportChange,{capture:!0}),null!==this.viewportChangeFrame&&cancelAnimationFrame(this.viewportChangeFrame),this.viewportChangeFrame=null,this.dropdownEl?.remove()}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value");t&&(this.parseTimeString(t),this.syncInputText())}if("open"===t)return this.isOpen=this.hasAttribute("open"),void this.render();this.render()}}get value(){return this.getAttribute("value")||""}set value(t){t?this.setAttribute("value",t):this.removeAttribute("value")}get format(){const t=this.getAttribute("format")||"24h";return n.includes(t)?t:"24h"}set format(t){this.setAttribute("format",t)}get type(){return"modal"===this.getAttribute("type")?"modal":"dropdown"}get is12h(){return"12h"===this.format||"12h-with-seconds"===this.format}get showSeconds(){return"12h-with-seconds"===this.format||"24h-with-seconds"===this.format}get minuteStep(){const t=Number(this.getAttribute("minute-step")||"1");return Number.isFinite(t)&&t>0?t:1}get normalizedSize(){return h(this.getAttribute("size"),o,"m")}get dropdownPosition(){return h(this.getAttribute("dropdown-position"),r,"auto")}get itemHeight(){return"s"===this.normalizedSize?32:"l"===this.normalizedSize?40:28}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",Boolean(t))}get readonly(){return this.hasAttribute("readonly")}set readonly(t){this.toggleAttribute("readonly",Boolean(t))}build(){this.built=!0,this.labelEl=document.createElement("label"),this.labelEl.className=`${d}__label`,this.triggerEl=document.createElement("div"),this.triggerEl.className=`${d}__trigger`;const t=document.createElement("button");t.type="button",t.className=`${d}__icon-display`,t.setAttribute("aria-label",e("시간 선택 열기")),t.addEventListener("click",()=>this.toggleOpen()),this.inputEl=document.createElement("input"),this.inputEl.type="text",this.inputEl.className=`${d}__input`,this.inputEl.setAttribute("aria-label",e("시간 입력")),this.inputEl.addEventListener("click",()=>this.openPicker()),this.inputEl.addEventListener("blur",()=>this.handleInputBlur()),this.inputEl.addEventListener("input",()=>{this.inputText=this.inputEl?.value||""});const i=document.createElement("button");i.type="button",i.className=`${d}__toggle`,i.setAttribute("aria-label",e("시간 선택 열기")),i.addEventListener("click",()=>this.toggleOpen()),this.triggerEl.append(t,this.inputEl,i),this.dropdownEl=document.createElement("div"),this.dropdownEl.className=`${d}__dropdown`,this.dropdownEl.setAttribute("role","dialog"),this.dropdownEl.setAttribute("aria-modal","false")}pad2(t){return String(t).padStart(2,"0")}to24Hour(t,e){return"AM"===e?12===t?0:t:12===t?12:t+12}formatTimeString(t,e,i,s){const n="AM"===(s||this.period)?"오전":"오후";return this.is12h?`${n} ${this.pad2(t)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(i)}`:""}`:`${this.pad2(t)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(i)}`:""}`}toValue24(t,e,i,s){const n=this.is12h?this.to24Hour(t,s||this.period):t;return`${this.pad2(n)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(i)}`:""}`}parseTimeString(t){const e=t.trim();if(this.is12h){const t=this.showSeconds?/^(오전|오후|AM|PM)?\s*(0?[1-9]|1[0-2]):([0-5]\d):([0-5]\d)\s*(AM|PM|오전|오후)?$/i:/^(오전|오후|AM|PM)?\s*(0?[1-9]|1[0-2]):([0-5]\d)\s*(AM|PM|오전|오후)?$/i,i=e.match(t);if(i){const t=i[1],e=this.showSeconds?i[5]:i[4],s=(t||e||"AM").toUpperCase();return this.hours=parseInt(i[2],10),this.minutes=parseInt(i[3],10),this.seconds=this.showSeconds?parseInt(i[4],10):0,void(this.period="오후"===s||"PM"===s?"PM":"AM")}}else{const t=this.showSeconds?/^([01]?\d|2[0-3]):([0-5]\d):([0-5]\d)$/:/^([01]?\d|2[0-3]):([0-5]\d)$/,i=e.match(t);i&&(this.hours=parseInt(i[1],10),this.minutes=parseInt(i[2],10),this.seconds=this.showSeconds?parseInt(i[3],10):0)}}syncInputText(){this.inputText=this.formatTimeString(this.hours,this.minutes,this.seconds),this.inputEl&&(this.inputEl.value=this.inputText)}emitChange(t){this.setAttribute("value",t),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:t},bubbles:!0,composed:!0}))}handleTimeChange(t,e,i=this.seconds,s){this.hours=t,this.minutes=e,this.seconds=i,s&&(this.period=s);const n=this.formatTimeString(t,e,i,s);this.inputText=n,this.inputEl&&(this.inputEl.value=n),this.emitChange(this.toValue24(t,e,i,s))}handleInputBlur(){if(!this.inputEl)return;const t=this.inputText;this.parseTimeString(this.inputEl.value);this.formatTimeString(this.hours,this.minutes,this.seconds)!==t||this.inputEl.value.trim()?this.handleTimeChange(this.hours,this.minutes,this.seconds,this.period):this.syncInputText()}openPicker(){this.disabled||this.readonly||(this.isOpen=!0,"modal"===this.type&&(this.tempHours=this.hours,this.tempMinutes=this.minutes,this.tempSeconds=this.seconds,this.tempPeriod=this.period),this.render())}closePicker(){this.isOpen=!1,this.render()}toggleOpen(){this.isOpen?this.closePicker():this.openPicker()}handleDocumentMouseDown(t){if(!this.isOpen)return;const e=t.target;this.contains(e)||this.dropdownEl?.contains(e)||this.closePicker()}handleViewportChange(){this.isOpen&&"dropdown"===this.type&&null===this.viewportChangeFrame&&(this.viewportChangeFrame=requestAnimationFrame(()=>{this.viewportChangeFrame=null,this.isOpen&&"dropdown"===this.type&&this.positionDropdown()}))}positionDropdown(){if(!this.isOpen||"dropdown"!==this.type||!this.triggerEl||!this.dropdownEl||this.dropdownEl.hidden)return;const t=this.dropdownEl,e=this.triggerEl.getBoundingClientRect();t.style.width="";const i=t.getBoundingClientRect(),s=Math.max(0,window.innerWidth-16),n=Math.min(i.width,s);t.style.width=`${Math.round(n)}px`;const o=this.dropdownPosition,r=e.bottom+4+i.height<=window.innerHeight-8,h=e.top-4-i.height>=8,d="auto"===o?r||!h?"bottom":"top":o.startsWith("top")?"top":"bottom",a="auto"===o?e.left+n>window.innerWidth-8?"end":"start":o.endsWith("end")?"end":"start",l="end"===a?e.right-n:e.left,u=Math.max(8,Math.min(l,window.innerWidth-n-8)),p="top"===d?e.top-i.height-4:e.bottom+4,c=Math.max(8,Math.min(p,window.innerHeight-i.height-8));t.style.left=`${Math.round(u)}px`,t.style.top=`${Math.round(c)}px`,t.dataset.placement=`${d}-${a}`}createWheel(t){const{label:e,items:i,value:s,onChange:n,formatter:o}=t,r=document.createElement("div");r.className=`${d}__wheel-container`;const h=document.createElement("div");h.className=`${d}__wheel-label`,h.textContent=e,r.appendChild(h);const a=document.createElement("div");a.className=`${d}__wheel-viewport`;const l=document.createElement("div");l.className=`${d}__wheel`,l.setAttribute("role","listbox"),l.setAttribute("aria-label",e);let u=null,p=!1,c=!1,m=0,b=0;const indexOfValue=t=>i.findIndex(e=>e===t),scrollToIndex=(t,e=!0)=>{const i=t*this.itemHeight;p=!0,l.scrollTo({top:i,behavior:e?"smooth":"auto"}),window.setTimeout(()=>{p=!1},150)},fmt=t=>o?o(t):"number"==typeof t?this.pad2(t):String(t);i.forEach(t=>{const e=document.createElement("div");e.className=[`${d}__wheel-item`,t===s&&`${d}__wheel-item--selected`].filter(Boolean).join(" "),e.setAttribute("role","option"),e.setAttribute("aria-selected",String(t===s)),e.textContent=fmt(t),e.addEventListener("click",()=>{const e=indexOfValue(t);scrollToIndex(e,!0),t!==s&&n(t)}),l.appendChild(e)});const handleScroll=()=>{p||(u&&window.clearTimeout(u),u=window.setTimeout(()=>{const t=l.scrollTop,e=Math.round(t/this.itemHeight),o=Math.max(0,Math.min(i.length-1,e)),r=i[o];scrollToIndex(o,!0),r!==s&&n(r)},120))};l.addEventListener("scroll",handleScroll,{passive:!0}),l.addEventListener("pointerdown",t=>{c=!0,m=t.clientY,b=l.scrollTop,l.setPointerCapture(t.pointerId),l.style.cursor="grabbing"}),l.addEventListener("pointermove",t=>{c&&(l.scrollTop=b-(t.clientY-m))});const endDrag=t=>{c&&(c=!1,l.releasePointerCapture(t.pointerId),l.style.cursor="grab",handleScroll())};l.addEventListener("pointerup",endDrag),l.addEventListener("pointercancel",endDrag);const w=indexOfValue(s);w>=0&&requestAnimationFrame(()=>scrollToIndex(w,!1));const g=document.createElement("div");g.className=`${d}__wheel-center-indicator`,g.setAttribute("aria-hidden","true");const E=document.createElement("div");E.className=`${d}__wheel-fade wheel-fade--top`,E.setAttribute("aria-hidden","true");const v=document.createElement("div");return v.className=`${d}__wheel-fade wheel-fade--bottom`,v.setAttribute("aria-hidden","true"),a.append(l,g,E,v),r.appendChild(a),r}renderSelector(t=!1){const s=document.createElement("div");s.className=`${d}__selector`;const n=document.createElement("div");n.className=`${d}__picker-wheels`;const o=this.is12h?Array.from({length:12},(t,e)=>e+1):Array.from({length:24},(t,e)=>e),r=Array.from({length:Math.floor(60/this.minuteStep)},(t,e)=>e*this.minuteStep),h=Array.from({length:60},(t,e)=>e),a=t?this.tempHours:this.hours,l=t?this.tempMinutes:this.minutes,u=t?this.tempSeconds:this.seconds,p=t?this.tempPeriod:this.period,onChange=(e,i,s,n)=>{if(t)return this.tempHours=e,this.tempMinutes=i,this.tempSeconds=s,void(this.tempPeriod=n);this.handleTimeChange(e,i,s,n)};if(n.appendChild(this.createWheel({label:e("시간"),items:o,value:a,onChange:t=>onChange(t,l,u,p)})),n.appendChild(this.createWheel({label:e("분"),items:r,value:r.includes(l)?l:r[0],onChange:t=>onChange(a,t,u,p)})),this.showSeconds&&n.appendChild(this.createWheel({label:e("초"),items:h,value:u,onChange:t=>onChange(a,l,t,p)})),this.is12h&&n.appendChild(this.createWheel({label:e("오전/오후"),items:["AM","PM"],value:p,onChange:t=>onChange(a,l,u,t),formatter:t=>"AM"===t?"오전":"오후"})),s.appendChild(n),t)return s;const c=document.createElement("div");c.className=`${d}__dropdown-actions`;const m=document.createElement("div");m.className=`${d}__preview`,m.setAttribute("aria-live","polite"),m.appendChild(i("clock",16));const b=document.createElement("div");b.className=`${d}__preview-time`,b.textContent=this.formatTimeString(a,l,u,p),m.appendChild(b);const w=document.createElement("db-button");return w.setAttribute("variant","primary"),w.setAttribute("size","m"),w.textContent=e("선택"),w.addEventListener("click",()=>{this.handleTimeChange(a,l,u,p),this.closePicker()}),c.append(m,w),s.appendChild(c),s}render(){const n=this.normalizedSize,o=this.dropdownPosition,r=s(n);if(this.className=[d,`${d}--${n}`,this.hasAttribute("full-width")&&`${d}--full-width`,this.disabled&&`${d}--disabled`,this.readonly&&`${d}--readonly`,this.isOpen&&`${d}--open`,this.hasAttribute("error")&&`${d}--error`].filter(Boolean).join(" "),this.inputEl?.setAttribute("aria-invalid",String(this.hasAttribute("error"))),this.dropdownEl?.parentElement===document.body&&this.dropdownEl.remove(),this.replaceChildren(),!(this.labelEl&&this.triggerEl&&this.inputEl&&this.dropdownEl))return;const h=this.getAttribute("label")||"";this.labelEl.textContent=h,this.labelEl.hidden=!h,this.inputEl.value=this.inputText,this.inputEl.placeholder=this.is12h?this.showSeconds?"12:00:00 PM":"12:00 PM":this.showSeconds?"12:00:00":"12:00",this.inputEl.disabled=this.disabled,this.inputEl.readOnly=this.readonly;const a=this.triggerEl.querySelector(`.${d}__icon-display`);a&&(a.innerHTML="",a.appendChild(i("clock",r)),a.disabled=this.disabled);const l=this.triggerEl.querySelector(`.${d}__toggle`);if(l&&(l.innerHTML="",l.appendChild(i("chevron-down",r)),l.disabled=this.disabled),this.dropdownEl.className=[`${d}__dropdown`,`${d}__dropdown--${n}`,`${d}__dropdown--${o}`].filter(Boolean).join(" "),this.dropdownEl.setAttribute("aria-label",e("시간 선택")),this.dropdownEl.hidden=!this.isOpen,this.isOpen&&"dropdown"===this.type&&(this.dropdownEl.replaceChildren(this.renderSelector(!1)),t(this,this.dropdownEl),document.body.appendChild(this.dropdownEl),this.dropdownEl.hidden=!1,this.positionDropdown(),requestAnimationFrame(()=>this.positionDropdown())),this.append(this.labelEl,this.triggerEl),this.isOpen&&"modal"===this.type){const t=document.createElement("db-modal");t.setAttribute("open","true"),t.setAttribute("title",e("시간 선택")),t.setAttribute("size","s"),t.addEventListener("db-close",()=>this.closePicker());const i=this.renderSelector(!0),s=document.createElement("div");s.className=`${d}__modal-footer`;const n=document.createElement("db-button");n.setAttribute("variant","secondary"),n.setAttribute("size","m"),n.textContent=e("취소"),n.addEventListener("click",()=>this.closePicker());const o=document.createElement("db-button");o.setAttribute("variant","primary"),o.setAttribute("size","m"),o.textContent=e("적용"),o.addEventListener("click",()=>{this.handleTimeChange(this.tempHours,this.tempMinutes,this.tempSeconds,this.tempPeriod),this.closePicker()}),s.append(n,o),t.append(i,s),this.appendChild(t)}}}customElements.get("db-time-picker")||customElements.define("db-time-picker",DbTimePicker);export{DbTimePicker};
1
+ import{inheritThemeScope as t}from"../core/theme-scope.js";import{subscribeDbLocale as e,dbText as i}from"../core/i18n.js";import{createDbIcon as s,getDbComponentIconSize as n}from"./db-icons.js";import"./db-button.js";import{TIME_PICKER_FORMATS as o,TIME_PICKER_SIZES as r,TIME_PICKER_DROPDOWN_POSITIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";import{coerceToContract as d}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";const a="designbase-wc-time-picker";class DbTimePicker extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.isOpen=!1,this.hours=12,this.minutes=0,this.seconds=0,this.period="PM",this.inputText="",this.tempHours=12,this.tempMinutes=0,this.tempSeconds=0,this.tempPeriod="PM",this.boundDocumentMouseDown=t=>this.handleDocumentMouseDown(t),this.boundViewportChange=()=>this.handleViewportChange(),this.viewportChangeFrame=null,this.handleDocumentKeyDown=t=>{"Escape"===t.key&&this.isOpen&&(t.preventDefault(),this.closePicker(),this.inputEl?.focus())},this.boundDocumentKeyDown=t=>this.handleDocumentKeyDown(t)}static get observedAttributes(){return["value","default-value","type","format","minute-step","size","disabled","readonly","label","full-width","error","dropdown-position","open"]}connectedCallback(){this.built||this.build(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale()),this.parseTimeString(this.getAttribute("value")??this.getAttribute("default-value")??"12:00"),this.syncInputText(),this.render(),document.addEventListener("mousedown",this.boundDocumentMouseDown),document.addEventListener("keydown",this.boundDocumentKeyDown),window.addEventListener("resize",this.boundViewportChange),window.addEventListener("scroll",this.boundViewportChange,{capture:!0,passive:!0})}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,document.removeEventListener("mousedown",this.boundDocumentMouseDown),document.removeEventListener("keydown",this.boundDocumentKeyDown),window.removeEventListener("resize",this.boundViewportChange),window.removeEventListener("scroll",this.boundViewportChange,{capture:!0}),null!==this.viewportChangeFrame&&cancelAnimationFrame(this.viewportChangeFrame),this.viewportChangeFrame=null,this.dropdownEl?.remove()}syncLocale(){if(!this.built)return;if(this.inputEl?.setAttribute("aria-label",i("시간 입력")),this.triggerEl?.querySelectorAll(`.${a}__icon-display, .${a}__toggle`).forEach(t=>t.setAttribute("aria-label",i("시간 선택 열기"))),this.is12h&&this.inputEl&&document.activeElement!==this.inputEl){const t=`${this.pad2(this.hours)}:${this.pad2(this.minutes)}${this.showSeconds?`:${this.pad2(this.seconds)}`:""}`;("AM"===this.period?["오전","AM"]:["오후","PM"]).some(e=>this.inputText===`${e} ${t}`)&&this.syncInputText()}this.dropdownEl?.setAttribute("aria-label",i("시간 선택"));const t=this.querySelector("db-modal");t&&t.setAttribute("title",i("시간 선택"));const e=[this.dropdownEl,t].filter(t=>!!t);for(const t of e){const e=["시간","분",...this.showSeconds?["초"]:[],...this.is12h?["오전/오후"]:[]];t.querySelectorAll(`.${a}__wheel-container`).forEach((t,s)=>{const n=e[s];if(!n)return;const o=t.querySelector(`.${a}__wheel-label`);o&&(o.textContent=i(n)),t.querySelector('[role="listbox"]')?.setAttribute("aria-label",i(n)),"오전/오후"===n&&t.querySelectorAll('[role="option"]').forEach((t,e)=>{t.textContent=i(0===e?"오전":"오후")})});const s=t.querySelector(`.${a}__preview-time`);s&&(s.textContent=this.formatTimeString(this.hours,this.minutes,this.seconds,this.period));const n=t.querySelector(`.${a}__dropdown-actions db-button`);n&&(n.textContent=i("선택"));const o=t.querySelectorAll(`.${a}__modal-footer db-button`);o[0]&&(o[0].textContent=i("취소")),o[1]&&(o[1].textContent=i("적용"))}}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value");t&&(this.parseTimeString(t),this.syncInputText())}if("open"===t)return this.isOpen=this.hasAttribute("open"),void this.render();this.render()}}get value(){return this.getAttribute("value")||""}set value(t){t?this.setAttribute("value",t):this.removeAttribute("value")}get format(){const t=this.getAttribute("format")||"24h";return o.includes(t)?t:"24h"}set format(t){this.setAttribute("format",t)}get type(){return"modal"===this.getAttribute("type")?"modal":"dropdown"}get is12h(){return"12h"===this.format||"12h-with-seconds"===this.format}get showSeconds(){return"12h-with-seconds"===this.format||"24h-with-seconds"===this.format}get minuteStep(){const t=Number(this.getAttribute("minute-step")||"1");return Number.isFinite(t)&&t>0?t:1}get normalizedSize(){return d(this.getAttribute("size"),r,"m")}get dropdownPosition(){return d(this.getAttribute("dropdown-position"),h,"auto")}get itemHeight(){return"s"===this.normalizedSize?32:"l"===this.normalizedSize?40:28}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",Boolean(t))}get readonly(){return this.hasAttribute("readonly")}set readonly(t){this.toggleAttribute("readonly",Boolean(t))}build(){this.built=!0,this.labelEl=document.createElement("label"),this.labelEl.className=`${a}__label`,this.triggerEl=document.createElement("div"),this.triggerEl.className=`${a}__trigger`;const t=document.createElement("button");t.type="button",t.className=`${a}__icon-display`,t.setAttribute("aria-label",i("시간 선택 열기")),t.addEventListener("click",()=>this.toggleOpen()),this.inputEl=document.createElement("input"),this.inputEl.type="text",this.inputEl.className=`${a}__input`,this.inputEl.setAttribute("aria-label",i("시간 입력")),this.inputEl.addEventListener("click",()=>this.openPicker()),this.inputEl.addEventListener("blur",()=>this.handleInputBlur()),this.inputEl.addEventListener("input",()=>{this.inputText=this.inputEl?.value||""});const e=document.createElement("button");e.type="button",e.className=`${a}__toggle`,e.setAttribute("aria-label",i("시간 선택 열기")),e.addEventListener("click",()=>this.toggleOpen()),this.triggerEl.append(t,this.inputEl,e),this.dropdownEl=document.createElement("div"),this.dropdownEl.className=`${a}__dropdown`,this.dropdownEl.setAttribute("role","dialog"),this.dropdownEl.setAttribute("aria-modal","false")}pad2(t){return String(t).padStart(2,"0")}to24Hour(t,e){return"AM"===e?12===t?0:t:12===t?12:t+12}formatTimeString(t,e,s,n){const o=n||this.period,r=i("AM"===o?"오전":"오후");return this.is12h?`${r} ${this.pad2(t)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(s)}`:""}`:`${this.pad2(t)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(s)}`:""}`}toValue24(t,e,i,s){const n=this.is12h?this.to24Hour(t,s||this.period):t;return`${this.pad2(n)}:${this.pad2(e)}${this.showSeconds?`:${this.pad2(i)}`:""}`}parseTimeString(t){const e=t.trim();if(this.is12h){const t=this.showSeconds?/^(오전|오후|AM|PM)?\s*(0?[1-9]|1[0-2]):([0-5]\d):([0-5]\d)\s*(AM|PM|오전|오후)?$/i:/^(오전|오후|AM|PM)?\s*(0?[1-9]|1[0-2]):([0-5]\d)\s*(AM|PM|오전|오후)?$/i,i=e.match(t);if(i){const t=i[1],e=this.showSeconds?i[5]:i[4],s=(t||e||"AM").toUpperCase();return this.hours=parseInt(i[2],10),this.minutes=parseInt(i[3],10),this.seconds=this.showSeconds?parseInt(i[4],10):0,void(this.period="오후"===s||"PM"===s?"PM":"AM")}}else{const t=this.showSeconds?/^([01]?\d|2[0-3]):([0-5]\d):([0-5]\d)$/:/^([01]?\d|2[0-3]):([0-5]\d)$/,i=e.match(t);i&&(this.hours=parseInt(i[1],10),this.minutes=parseInt(i[2],10),this.seconds=this.showSeconds?parseInt(i[3],10):0)}}syncInputText(){this.inputText=this.formatTimeString(this.hours,this.minutes,this.seconds),this.inputEl&&(this.inputEl.value=this.inputText)}emitChange(t){this.setAttribute("value",t),this.dispatchEvent(new CustomEvent("db-change",{detail:{value:t},bubbles:!0,composed:!0}))}handleTimeChange(t,e,i=this.seconds,s){this.hours=t,this.minutes=e,this.seconds=i,s&&(this.period=s);const n=this.formatTimeString(t,e,i,s);this.inputText=n,this.inputEl&&(this.inputEl.value=n),this.emitChange(this.toValue24(t,e,i,s))}handleInputBlur(){if(!this.inputEl)return;const t=this.inputText;this.parseTimeString(this.inputEl.value);this.formatTimeString(this.hours,this.minutes,this.seconds)!==t||this.inputEl.value.trim()?this.handleTimeChange(this.hours,this.minutes,this.seconds,this.period):this.syncInputText()}openPicker(){this.disabled||this.readonly||(this.isOpen=!0,"modal"===this.type&&(this.tempHours=this.hours,this.tempMinutes=this.minutes,this.tempSeconds=this.seconds,this.tempPeriod=this.period),this.render())}closePicker(){this.isOpen=!1,this.render()}toggleOpen(){this.isOpen?this.closePicker():this.openPicker()}handleDocumentMouseDown(t){if(!this.isOpen)return;const e=t.target;this.contains(e)||this.dropdownEl?.contains(e)||this.closePicker()}handleViewportChange(){this.isOpen&&"dropdown"===this.type&&null===this.viewportChangeFrame&&(this.viewportChangeFrame=requestAnimationFrame(()=>{this.viewportChangeFrame=null,this.isOpen&&"dropdown"===this.type&&this.positionDropdown()}))}positionDropdown(){if(!this.isOpen||"dropdown"!==this.type||!this.triggerEl||!this.dropdownEl||this.dropdownEl.hidden)return;const t=this.dropdownEl,e=this.triggerEl.getBoundingClientRect();t.style.width="";const i=t.getBoundingClientRect(),s=Math.max(0,window.innerWidth-16),n=Math.min(i.width,s);t.style.width=`${Math.round(n)}px`;const o=this.dropdownPosition,r=e.bottom+4+i.height<=window.innerHeight-8,h=e.top-4-i.height>=8,d="auto"===o?r||!h?"bottom":"top":o.startsWith("top")?"top":"bottom",a="auto"===o?e.left+n>window.innerWidth-8?"end":"start":o.endsWith("end")?"end":"start",l="end"===a?e.right-n:e.left,u=Math.max(8,Math.min(l,window.innerWidth-n-8)),c="top"===d?e.top-i.height-4:e.bottom+4,p=Math.max(8,Math.min(c,window.innerHeight-i.height-8));t.style.left=`${Math.round(u)}px`,t.style.top=`${Math.round(p)}px`,t.dataset.placement=`${d}-${a}`}createWheel(t){const{label:e,items:i,value:s,onChange:n,formatter:o}=t,r=document.createElement("div");r.className=`${a}__wheel-container`;const h=document.createElement("div");h.className=`${a}__wheel-label`,h.textContent=e,r.appendChild(h);const d=document.createElement("div");d.className=`${a}__wheel-viewport`;const l=document.createElement("div");l.className=`${a}__wheel`,l.setAttribute("role","listbox"),l.setAttribute("aria-label",e);let u=null,c=!1,p=!1,m=0,b=0;const indexOfValue=t=>i.findIndex(e=>e===t),scrollToIndex=(t,e=!0)=>{const i=t*this.itemHeight;c=!0,l.scrollTo({top:i,behavior:e?"smooth":"auto"}),window.setTimeout(()=>{c=!1},150)},fmt=t=>o?o(t):"number"==typeof t?this.pad2(t):String(t);i.forEach(t=>{const e=document.createElement("div");e.className=[`${a}__wheel-item`,t===s&&`${a}__wheel-item--selected`].filter(Boolean).join(" "),e.setAttribute("role","option"),e.setAttribute("aria-selected",String(t===s)),e.textContent=fmt(t),e.addEventListener("click",()=>{const e=indexOfValue(t);scrollToIndex(e,!0),t!==s&&n(t)}),l.appendChild(e)});const handleScroll=()=>{c||(u&&window.clearTimeout(u),u=window.setTimeout(()=>{const t=l.scrollTop,e=Math.round(t/this.itemHeight),o=Math.max(0,Math.min(i.length-1,e)),r=i[o];scrollToIndex(o,!0),r!==s&&n(r)},120))};l.addEventListener("scroll",handleScroll,{passive:!0}),l.addEventListener("pointerdown",t=>{p=!0,m=t.clientY,b=l.scrollTop,l.setPointerCapture(t.pointerId),l.style.cursor="grabbing"}),l.addEventListener("pointermove",t=>{p&&(l.scrollTop=b-(t.clientY-m))});const endDrag=t=>{p&&(p=!1,l.releasePointerCapture(t.pointerId),l.style.cursor="grab",handleScroll())};l.addEventListener("pointerup",endDrag),l.addEventListener("pointercancel",endDrag);const w=indexOfValue(s);w>=0&&requestAnimationFrame(()=>scrollToIndex(w,!1));const g=document.createElement("div");g.className=`${a}__wheel-center-indicator`,g.setAttribute("aria-hidden","true");const E=document.createElement("div");E.className=`${a}__wheel-fade wheel-fade--top`,E.setAttribute("aria-hidden","true");const v=document.createElement("div");return v.className=`${a}__wheel-fade wheel-fade--bottom`,v.setAttribute("aria-hidden","true"),d.append(l,g,E,v),r.appendChild(d),r}renderSelector(t=!1){const e=document.createElement("div");e.className=`${a}__selector`;const n=document.createElement("div");n.className=`${a}__picker-wheels`;const o=this.is12h?Array.from({length:12},(t,e)=>e+1):Array.from({length:24},(t,e)=>e),r=Array.from({length:Math.floor(60/this.minuteStep)},(t,e)=>e*this.minuteStep),h=Array.from({length:60},(t,e)=>e),d=t?this.tempHours:this.hours,l=t?this.tempMinutes:this.minutes,u=t?this.tempSeconds:this.seconds,c=t?this.tempPeriod:this.period,onChange=(e,i,s,n)=>{if(t)return this.tempHours=e,this.tempMinutes=i,this.tempSeconds=s,void(this.tempPeriod=n);this.handleTimeChange(e,i,s,n)};if(n.appendChild(this.createWheel({label:i("시간"),items:o,value:d,onChange:t=>onChange(t,l,u,c)})),n.appendChild(this.createWheel({label:i("분"),items:r,value:r.includes(l)?l:r[0],onChange:t=>onChange(d,t,u,c)})),this.showSeconds&&n.appendChild(this.createWheel({label:i("초"),items:h,value:u,onChange:t=>onChange(d,l,t,c)})),this.is12h&&n.appendChild(this.createWheel({label:i("오전/오후"),items:["AM","PM"],value:c,onChange:t=>onChange(d,l,u,t),formatter:t=>i("AM"===t?"오전":"오후")})),e.appendChild(n),t)return e;const p=document.createElement("div");p.className=`${a}__dropdown-actions`;const m=document.createElement("div");m.className=`${a}__preview`,m.setAttribute("aria-live","polite"),m.appendChild(s("clock",16));const b=document.createElement("div");b.className=`${a}__preview-time`,b.textContent=this.formatTimeString(d,l,u,c),m.appendChild(b);const w=document.createElement("db-button");return w.setAttribute("variant","primary"),w.setAttribute("size","m"),w.textContent=i("선택"),w.addEventListener("click",()=>{this.handleTimeChange(d,l,u,c),this.closePicker()}),p.append(m,w),e.appendChild(p),e}render(){const e=this.normalizedSize,o=this.dropdownPosition,r=n(e);if(this.className=[a,`${a}--${e}`,this.hasAttribute("full-width")&&`${a}--full-width`,this.disabled&&`${a}--disabled`,this.readonly&&`${a}--readonly`,this.isOpen&&`${a}--open`,this.hasAttribute("error")&&`${a}--error`].filter(Boolean).join(" "),this.inputEl?.setAttribute("aria-invalid",String(this.hasAttribute("error"))),this.dropdownEl?.parentElement===document.body&&this.dropdownEl.remove(),this.replaceChildren(),!(this.labelEl&&this.triggerEl&&this.inputEl&&this.dropdownEl))return;const h=this.getAttribute("label")||"";this.labelEl.textContent=h,this.labelEl.hidden=!h,this.inputEl.value=this.inputText,this.inputEl.placeholder=this.is12h?this.showSeconds?"12:00:00 PM":"12:00 PM":this.showSeconds?"12:00:00":"12:00",this.inputEl.disabled=this.disabled,this.inputEl.readOnly=this.readonly;const d=this.triggerEl.querySelector(`.${a}__icon-display`);d&&(d.innerHTML="",d.appendChild(s("clock",r)),d.disabled=this.disabled);const l=this.triggerEl.querySelector(`.${a}__toggle`);if(l&&(l.innerHTML="",l.appendChild(s("chevron-down",r)),l.disabled=this.disabled),this.dropdownEl.className=[`${a}__dropdown`,`${a}__dropdown--${e}`,`${a}__dropdown--${o}`].filter(Boolean).join(" "),this.dropdownEl.setAttribute("aria-label",i("시간 선택")),this.dropdownEl.hidden=!this.isOpen,this.isOpen&&"dropdown"===this.type&&(this.dropdownEl.replaceChildren(this.renderSelector(!1)),t(this,this.dropdownEl),document.body.appendChild(this.dropdownEl),this.dropdownEl.hidden=!1,this.positionDropdown(),requestAnimationFrame(()=>this.positionDropdown())),this.append(this.labelEl,this.triggerEl),this.isOpen&&"modal"===this.type){const t=document.createElement("db-modal");t.setAttribute("open","true"),t.setAttribute("title",i("시간 선택")),t.setAttribute("size","s"),t.addEventListener("db-close",()=>this.closePicker());const e=this.renderSelector(!0),s=document.createElement("div");s.className=`${a}__modal-footer`;const n=document.createElement("db-button");n.setAttribute("variant","secondary"),n.setAttribute("size","m"),n.textContent=i("취소"),n.addEventListener("click",()=>this.closePicker());const o=document.createElement("db-button");o.setAttribute("variant","primary"),o.setAttribute("size","m"),o.textContent=i("적용"),o.addEventListener("click",()=>{this.handleTimeChange(this.tempHours,this.tempMinutes,this.tempSeconds,this.tempPeriod),this.closePicker()}),s.append(n,o),t.append(e,s),this.appendChild(t)}}}customElements.get("db-time-picker")||customElements.define("db-time-picker",DbTimePicker);export{DbTimePicker};
@@ -10,13 +10,17 @@ type DbTimelineItem = {
10
10
  disabled?: boolean;
11
11
  };
12
12
  declare class DbTimeline extends HTMLElement {
13
+ private unsubscribeLocale?;
13
14
  static get observedAttributes(): string[];
14
15
  connectedCallback(): void;
16
+ disconnectedCallback(): void;
15
17
  attributeChangedCallback(): void;
16
18
  get items(): DbTimelineItem[];
17
19
  set items(value: DbTimelineItem[] | string);
18
20
  private getItemPosition;
19
21
  private handleItemClick;
22
+ private itemLabel;
23
+ private syncLocale;
20
24
  private render;
21
25
  }
22
26
  declare global {
@@ -1 +1 @@
1
- import{isDbIconName as e,createDbIcon as t}from"./db-icons.js";import{coerceToContract as i}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TIMELINE_VARIANTS as n,TIMELINE_SIZES as s}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const a="designbase-wc-timeline";class DbTimeline extends HTMLElement{static get observedAttributes(){return["items","type","variant","size","color","clickable","full-width","disabled"]}connectedCallback(){this.style.display="block",this.render()}attributeChangedCallback(){this.isConnected&&this.render()}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}getItemPosition(e){return"left"===(this.getAttribute("type")||"alternate")||e%2==0?"left":"right"}handleItemClick(e,t){this.hasAttribute("disabled")||e.disabled||!this.hasAttribute("clickable")||this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e,index:t}}))}render(){const l=this.getAttribute("type")||"alternate",c=i(this.getAttribute("variant"),n,"default"),d=i(this.getAttribute("size"),s,"m"),o=this.getAttribute("color")||"primary",r=this.hasAttribute("clickable"),m=this.hasAttribute("disabled"),b=this.items;this.className=[a,`${a}--${l}`,`${a}--${c}`,`${a}--${d}`,r&&`${a}--clickable`,this.hasAttribute("full-width")&&`${a}--full-width`,m&&`${a}--disabled`].filter(Boolean).join(" "),this.replaceChildren();const u=document.createElement("div");u.className=`${a}__container`,b.forEach((i,n)=>{const s=this.getItemPosition(n),l=n===b.length-1,p=r&&!m&&!i.disabled,_=r&&(m||Boolean(i.disabled)),h=i.color||o,$=i.status||"pending",v=document.createElement("div");v.className=[`${a}__item`,`${a}__item--${s}`,`${a}__item--${h}`,p&&`${a}__item--clickable`,i.disabled&&`${a}__item--disabled`].filter(Boolean).join(" ");const f=document.createElement("div");if(f.className=`${a}__indicator-container`,"active"===$&&!i.icon&&void 0===i.number){const e=document.createElement("div");e.className=`${a}__pulse`,f.append(e)}const k=document.createElement("div");if(k.className=[`${a}__dot`,`${a}__dot--${h}`,`${a}__dot--${c}`,`${a}__dot--${$}`,p&&`${a}__dot--clickable`,i.icon&&`${a}__dot--with-icon`,void 0!==i.number&&!i.icon&&`${a}__dot--with-number`].filter(Boolean).join(" "),_&&(k.setAttribute("role","button"),k.setAttribute("aria-disabled","true")),p&&(k.tabIndex=0,k.setAttribute("role","button"),k.setAttribute("aria-label",i.title?`${i.title} 타임라인 점`:`타임라인 점 ${n+1}`),k.addEventListener("click",()=>this.handleItemClick(i,n)),k.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.handleItemClick(i,n))})),i.icon&&e(i.icon)){const e=document.createElement("div");e.className=`${a}__icon`,e.append(t(i.icon,"s"===d?14:"l"===d?20:16)),k.append(e)}else if(void 0!==i.number){const e=document.createElement("span");e.className=`${a}__number`,e.textContent=String(i.number),k.append(e)}if(f.append(k),!l){const e=document.createElement("div");e.className=`${a}__connector`,f.append(e)}const E=document.createElement("div");if(E.className=[`${a}__content`,`${a}__content--${s}`].join(" "),i.timestamp){const e=document.createElement("div");e.className=`${a}__timestamp`,e.textContent=i.timestamp,E.append(e)}const g=document.createElement("div");if(g.className=`${a}__content-inner`,_&&(g.setAttribute("role","button"),g.setAttribute("aria-disabled","true")),p&&(g.tabIndex=0,g.setAttribute("role","button"),g.setAttribute("aria-label",i.title?`${i.title} 타임라인 아이템`:`타임라인 아이템 ${n+1}`),g.addEventListener("click",()=>this.handleItemClick(i,n)),g.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.handleItemClick(i,n))})),i.title){const e=document.createElement("h3");e.className=`${a}__title`,e.textContent=i.title,g.append(e)}if(i.description){const e=document.createElement("p");e.className=`${a}__description`,e.textContent=i.description,g.append(e)}E.append(g),v.append(f,E),u.append(v)}),this.append(u)}}customElements.get("db-timeline")||customElements.define("db-timeline",DbTimeline);export{DbTimeline};
1
+ import{subscribeDbLocale as e,dbFormat as t}from"../core/i18n.js";import{isDbIconName as i,createDbIcon as n}from"./db-icons.js";import{coerceToContract as s}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TIMELINE_VARIANTS as a,TIMELINE_SIZES as l}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const c="designbase-wc-timeline";class DbTimeline extends HTMLElement{static get observedAttributes(){return["items","type","variant","size","color","clickable","full-width","disabled"]}connectedCallback(){this.style.display="block",this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.syncLocale())}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(){this.isConnected&&this.render()}get items(){try{return JSON.parse(this.getAttribute("items")||"[]")}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}getItemPosition(e){return"left"===(this.getAttribute("type")||"alternate")||e%2==0?"left":"right"}handleItemClick(e,t){this.hasAttribute("disabled")||e.disabled||!this.hasAttribute("clickable")||this.dispatchEvent(new CustomEvent("db-item-click",{bubbles:!0,composed:!0,detail:{item:e,index:t}}))}itemLabel(e,i,n){const s="dot"===n?e.title?"{0} 타임라인 점":"타임라인 점 {0}":e.title?"{0} 타임라인 아이템":"타임라인 아이템 {0}";return t(s,[e.title||i+1])}syncLocale(){const e=this.items;this.querySelectorAll("[data-locale-timeline-index]").forEach(t=>{const i=Number(t.dataset.localeTimelineIndex);e[i]&&t.setAttribute("aria-label",this.itemLabel(e[i],i,"dot"===t.dataset.localeTimelineKind?"dot":"item"))})}render(){const e=this.getAttribute("type")||"alternate",t=s(this.getAttribute("variant"),a,"default"),o=s(this.getAttribute("size"),l,"m"),d=this.getAttribute("color")||"primary",r=this.hasAttribute("clickable"),m=this.hasAttribute("disabled"),b=this.items;this.className=[c,`${c}--${e}`,`${c}--${t}`,`${c}--${o}`,r&&`${c}--clickable`,this.hasAttribute("full-width")&&`${c}--full-width`,m&&`${c}--disabled`].filter(Boolean).join(" "),this.replaceChildren();const u=document.createElement("div");u.className=`${c}__container`,b.forEach((e,s)=>{const a=this.getItemPosition(s),l=s===b.length-1,h=r&&!m&&!e.disabled,p=r&&(m||Boolean(e.disabled)),_=e.color||d,$=e.status||"pending",f=document.createElement("div");f.className=[`${c}__item`,`${c}__item--${a}`,`${c}__item--${_}`,h&&`${c}__item--clickable`,e.disabled&&`${c}__item--disabled`].filter(Boolean).join(" ");const v=document.createElement("div");if(v.className=`${c}__indicator-container`,"active"===$&&!e.icon&&void 0===e.number){const e=document.createElement("div");e.className=`${c}__pulse`,v.append(e)}const k=document.createElement("div");if(k.className=[`${c}__dot`,`${c}__dot--${_}`,`${c}__dot--${t}`,`${c}__dot--${$}`,h&&`${c}__dot--clickable`,e.icon&&`${c}__dot--with-icon`,void 0!==e.number&&!e.icon&&`${c}__dot--with-number`].filter(Boolean).join(" "),p&&(k.setAttribute("role","button"),k.setAttribute("aria-disabled","true")),h&&(k.tabIndex=0,k.setAttribute("role","button"),k.dataset.localeTimelineIndex=String(s),k.dataset.localeTimelineKind="dot",k.setAttribute("aria-label",this.itemLabel(e,s,"dot")),k.addEventListener("click",()=>this.handleItemClick(e,s)),k.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleItemClick(e,s))})),e.icon&&i(e.icon)){const t=document.createElement("div");t.className=`${c}__icon`,t.append(n(e.icon,"s"===o?14:"l"===o?20:16)),k.append(t)}else if(void 0!==e.number){const t=document.createElement("span");t.className=`${c}__number`,t.textContent=String(e.number),k.append(t)}if(v.append(k),!l){const e=document.createElement("div");e.className=`${c}__connector`,v.append(e)}const E=document.createElement("div");if(E.className=[`${c}__content`,`${c}__content--${a}`].join(" "),e.timestamp){const t=document.createElement("div");t.className=`${c}__timestamp`,t.textContent=e.timestamp,E.append(t)}const g=document.createElement("div");if(g.className=`${c}__content-inner`,p&&(g.setAttribute("role","button"),g.setAttribute("aria-disabled","true")),h&&(g.dataset.localeTimelineIndex=String(s),g.dataset.localeTimelineKind="item",g.tabIndex=0,g.setAttribute("role","button"),g.setAttribute("aria-label",this.itemLabel(e,s,"item")),g.addEventListener("click",()=>this.handleItemClick(e,s)),g.addEventListener("keydown",t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.handleItemClick(e,s))})),e.title){const t=document.createElement("h3");t.className=`${c}__title`,t.textContent=e.title,g.append(t)}if(e.description){const t=document.createElement("p");t.className=`${c}__description`,t.textContent=e.description,g.append(t)}E.append(g),f.append(v,E),u.append(f)}),this.append(u)}}customElements.get("db-timeline")||customElements.define("db-timeline",DbTimeline);export{DbTimeline};
@@ -4,6 +4,7 @@ declare class DbToast extends HTMLElement {
4
4
  private progressInterval;
5
5
  private closeTimerId;
6
6
  private closed;
7
+ private unsubscribeLocale?;
7
8
  private readonly cleanups;
8
9
  /** 일시정지 시점까지 소비한 시간 (ms) */
9
10
  private elapsedBeforePause;
@@ -14,6 +15,7 @@ declare class DbToast extends HTMLElement {
14
15
  private pauseTimers;
15
16
  private resumeTimers;
16
17
  attributeChangedCallback(name: string): void;
18
+ private syncCloseLabel;
17
19
  private clearTimers;
18
20
  private startTimers;
19
21
  /** 토스트를 닫고(애니메이션 포함) auto-remove 설정 시 DOM에서 제거합니다. */
@@ -1 +1 @@
1
- import{createDbIcon as t}from"./db-icons.js";import{politenessForTone as e}from"../core/a11y.js";import{labelFrom as s}from"../core/i18n.js";import{CleanupBag as i}from"../core/dom.js";import{coerceToContract as r}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TOAST_VARIANTS as a}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbToast extends HTMLElement{constructor(){super(...arguments),this.timeoutId=null,this.progressInterval=null,this.closeTimerId=null,this.closed=!1,this.cleanups=new i,this.elapsedBeforePause=0,this.runStartedAt=0,this.paused=!1,this.pauseTimers=()=>{this.paused||this.closed||(this.paused=!0,this.elapsedBeforePause+=Date.now()-this.runStartedAt,this.clearTimers())},this.resumeTimers=()=>{this.paused&&!this.closed&&(this.paused=!1,this.startTimers())}}static get observedAttributes(){return["toast-id","variant","title","description","duration","show-close","show-progress","auto-remove"]}connectedCallback(){this.closed=!1,this.elapsedBeforePause=0,this.render(),this.startTimers(),requestAnimationFrame(()=>this.classList.add("designbase-wc-toast--visible")),this.cleanups.listen(this,"pointerenter",this.pauseTimers),this.cleanups.listen(this,"pointerleave",this.resumeTimers),this.cleanups.listen(this,"focusin",this.pauseTimers),this.cleanups.listen(this,"focusout",this.resumeTimers)}disconnectedCallback(){this.cleanups.run(),this.clearTimers(),this.closeTimerId&&clearTimeout(this.closeTimerId),this.closeTimerId=null}attributeChangedCallback(t){if(!this.isConnected||this.closed)return;const e=this.classList.contains("designbase-wc-toast--visible");this.render(),e&&requestAnimationFrame(()=>this.classList.add("designbase-wc-toast--visible")),"duration"!==t&&"show-progress"!==t||(this.clearTimers(),this.startTimers())}clearTimers(){this.timeoutId&&clearTimeout(this.timeoutId),this.progressInterval&&clearInterval(this.progressInterval),this.timeoutId=null,this.progressInterval=null}startTimers(){const t=Number(this.getAttribute("duration")??"5000");if(!Number.isFinite(t)||t<=0)return;const e=Math.max(0,t-this.elapsedBeforePause);if(this.runStartedAt=Date.now(),0===e)return void this.close();if("false"!==this.getAttribute("show-progress")&&this.hasAttribute("show-progress")){const e=this.querySelector(".designbase-wc-toast__progress-bar");e&&(e.style.width="0%");const s=Date.now();return void(this.progressInterval=setInterval(()=>{const i=this.elapsedBeforePause+(Date.now()-s),r=Math.min(100,i/t*100);e&&(e.style.width=`${r}%`),r>=100&&this.close()},16))}this.timeoutId=setTimeout(()=>this.close(),e)}close(){this.closed||(this.closed=!0,this.clearTimers(),this.classList.remove("designbase-wc-toast--visible"),this.classList.add("designbase-wc-toast--closing"),this.closeTimerId&&clearTimeout(this.closeTimerId),this.closeTimerId=setTimeout(()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0,detail:{id:this.getAttribute("toast-id")||""}}));("true"===this.getAttribute("auto-remove")||this.hasAttribute("auto-remove")&&"false"!==this.getAttribute("auto-remove"))&&this.remove()},300))}iconForVariant(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}render(){const i=r(this.getAttribute("variant"),a,"info"),o=this.getAttribute("title")||"",n=this.getAttribute("description")||"",c="false"!==this.getAttribute("show-close"),l="false"!==this.getAttribute("show-progress")&&this.hasAttribute("show-progress");this.className=["designbase-wc-toast",`designbase-wc-toast--${i}`,this.closed&&"designbase-wc-toast--closing"].filter(Boolean).join(" ");const d=e(i);if(this.setAttribute("role","assertive"===d?"alert":"status"),this.setAttribute("aria-live",d),this.setAttribute("aria-atomic","true"),this.replaceChildren(),l){const t=document.createElement("div");t.className="designbase-wc-toast__progress";const e=document.createElement("div");e.className="designbase-wc-toast__progress-bar",e.style.width="0%",t.append(e),this.append(t)}const h=document.createElement("div");h.className=`designbase-wc-toast__icon designbase-wc-toast__icon--${i}`,h.setAttribute("aria-hidden","true"),h.append(t(this.iconForVariant(i),20));const u=document.createElement("div");u.className="designbase-wc-toast__content";const m=document.createElement("div");if(m.className="designbase-wc-toast__title",m.textContent=o,u.append(m),n){const t=document.createElement("div");t.className="designbase-wc-toast__description",t.textContent=n,u.append(t)}if(this.append(h,u),c){const e=document.createElement("button");e.type="button",e.className="designbase-wc-toast__close-button",e.setAttribute("aria-label",s(this,"label-close","toast.close"));const i=t("close",20);i.setAttribute("aria-hidden","true"),e.append(i),e.addEventListener("click",()=>this.close()),this.append(e)}}}customElements.get("db-toast")||customElements.define("db-toast",DbToast);export{DbToast};
1
+ import{createDbIcon as t}from"./db-icons.js";import{politenessForTone as e}from"../core/a11y.js";import{subscribeDbLocale as s,labelFrom as i}from"../core/i18n.js";import{CleanupBag as a}from"../core/dom.js";import{coerceToContract as o}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{TOAST_VARIANTS as r}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbToast extends HTMLElement{constructor(){super(...arguments),this.timeoutId=null,this.progressInterval=null,this.closeTimerId=null,this.closed=!1,this.cleanups=new a,this.elapsedBeforePause=0,this.runStartedAt=0,this.paused=!1,this.pauseTimers=()=>{this.paused||this.closed||(this.paused=!0,this.elapsedBeforePause+=Date.now()-this.runStartedAt,this.clearTimers())},this.resumeTimers=()=>{this.paused&&!this.closed&&(this.paused=!1,this.startTimers())}}static get observedAttributes(){return["toast-id","variant","title","description","duration","show-close","show-progress","auto-remove","label-close"]}connectedCallback(){this.closed=!1,this.elapsedBeforePause=0,this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=s(()=>this.syncCloseLabel()),this.startTimers(),requestAnimationFrame(()=>this.classList.add("designbase-wc-toast--visible")),this.cleanups.listen(this,"pointerenter",this.pauseTimers),this.cleanups.listen(this,"pointerleave",this.resumeTimers),this.cleanups.listen(this,"focusin",this.pauseTimers),this.cleanups.listen(this,"focusout",this.resumeTimers)}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0,this.cleanups.run(),this.clearTimers(),this.closeTimerId&&clearTimeout(this.closeTimerId),this.closeTimerId=null}attributeChangedCallback(t){if(!this.isConnected||this.closed)return;if("label-close"===t)return void this.syncCloseLabel();const e=this.classList.contains("designbase-wc-toast--visible");this.render(),e&&requestAnimationFrame(()=>this.classList.add("designbase-wc-toast--visible")),"duration"!==t&&"show-progress"!==t||(this.clearTimers(),this.startTimers())}syncCloseLabel(){this.querySelector(".designbase-wc-toast__close-button")?.setAttribute("aria-label",i(this,"label-close","toast.close"))}clearTimers(){this.timeoutId&&clearTimeout(this.timeoutId),this.progressInterval&&clearInterval(this.progressInterval),this.timeoutId=null,this.progressInterval=null}startTimers(){const t=Number(this.getAttribute("duration")??"5000");if(!Number.isFinite(t)||t<=0)return;const e=Math.max(0,t-this.elapsedBeforePause);if(this.runStartedAt=Date.now(),0===e)return void this.close();if("false"!==this.getAttribute("show-progress")&&this.hasAttribute("show-progress")){const e=this.querySelector(".designbase-wc-toast__progress-bar");e&&(e.style.width="0%");const s=Date.now();return void(this.progressInterval=setInterval(()=>{const i=this.elapsedBeforePause+(Date.now()-s),a=Math.min(100,i/t*100);e&&(e.style.width=`${a}%`),a>=100&&this.close()},16))}this.timeoutId=setTimeout(()=>this.close(),e)}close(){this.closed||(this.closed=!0,this.clearTimers(),this.classList.remove("designbase-wc-toast--visible"),this.classList.add("designbase-wc-toast--closing"),this.closeTimerId&&clearTimeout(this.closeTimerId),this.closeTimerId=setTimeout(()=>{this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0,detail:{id:this.getAttribute("toast-id")||""}}));("true"===this.getAttribute("auto-remove")||this.hasAttribute("auto-remove")&&"false"!==this.getAttribute("auto-remove"))&&this.remove()},300))}iconForVariant(t){return"success"===t?"circle-checked":"warning"===t?"warning-filled":"danger"===t?"error-filled":"info-filled"}render(){const s=o(this.getAttribute("variant"),r,"info"),a=this.getAttribute("title")||"",n=this.getAttribute("description")||"",c="false"!==this.getAttribute("show-close"),l="false"!==this.getAttribute("show-progress")&&this.hasAttribute("show-progress");this.className=["designbase-wc-toast",`designbase-wc-toast--${s}`,this.closed&&"designbase-wc-toast--closing"].filter(Boolean).join(" ");const d=e(s);if(this.setAttribute("role","assertive"===d?"alert":"status"),this.setAttribute("aria-live",d),this.setAttribute("aria-atomic","true"),this.replaceChildren(),l){const t=document.createElement("div");t.className="designbase-wc-toast__progress";const e=document.createElement("div");e.className="designbase-wc-toast__progress-bar",e.style.width="0%",t.append(e),this.append(t)}const h=document.createElement("div");h.className=`designbase-wc-toast__icon designbase-wc-toast__icon--${s}`,h.setAttribute("aria-hidden","true"),h.append(t(this.iconForVariant(s),20));const u=document.createElement("div");u.className="designbase-wc-toast__content";const m=document.createElement("div");if(m.className="designbase-wc-toast__title",m.textContent=a,u.append(m),n){const t=document.createElement("div");t.className="designbase-wc-toast__description",t.textContent=n,u.append(t)}if(this.append(h,u),c){const e=document.createElement("button");e.type="button",e.className="designbase-wc-toast__close-button",e.setAttribute("aria-label",i(this,"label-close","toast.close"));const s=t("close",20);s.setAttribute("aria-hidden","true"),e.append(s),e.addEventListener("click",()=>this.close()),this.append(e)}}}customElements.get("db-toast")||customElements.define("db-toast",DbToast);export{DbToast};
@@ -0,0 +1,92 @@
1
+ declare const TOOL_LAYOUT_VARIANTS: readonly ["floating", "flush", "inset"];
2
+ type ToolLayoutVariant = (typeof TOOL_LAYOUT_VARIANTS)[number];
3
+ type ToolLayoutPanel = 'sidebar' | 'inspector' | 'bottom';
4
+ interface ToolLayoutSizes {
5
+ sidebar?: number;
6
+ inspector?: number;
7
+ bottom?: number;
8
+ }
9
+ interface ToolLayoutResizeDetail {
10
+ panel: ToolLayoutPanel;
11
+ size: number;
12
+ sizes: ToolLayoutSizes;
13
+ phase: 'change' | 'end' | 'cancel';
14
+ }
15
+ /** Content-free desktop utility shell. One direct child per named slot; main is required.
16
+ * Children stay in place so framework state, focus and event listeners survive layout changes.
17
+ * CSS sizing hooks: --db-tool-rail-width, --db-tool-sidebar-width,
18
+ * --db-tool-inspector-width, --db-tool-bottom-height, --db-tool-gap, --db-tool-radius.
19
+ */
20
+ declare class DbToolLayout extends HTMLElement {
21
+ static get observedAttributes(): string[];
22
+ private mutations?;
23
+ private resize?;
24
+ private width;
25
+ private height;
26
+ private effective;
27
+ private handles;
28
+ private frame;
29
+ private lateralBudget;
30
+ private bottomCapacity;
31
+ private unsubscribe?;
32
+ private drag?;
33
+ get resizable(): boolean;
34
+ set resizable(value: boolean);
35
+ get sidebarHidden(): boolean;
36
+ set sidebarHidden(value: boolean);
37
+ get inspectorHidden(): boolean;
38
+ set inspectorHidden(value: boolean);
39
+ get bottomHidden(): boolean;
40
+ set bottomHidden(value: boolean);
41
+ get sidebarMin(): number;
42
+ set sidebarMin(value: number);
43
+ get sidebarMax(): number;
44
+ set sidebarMax(value: number);
45
+ get inspectorMin(): number;
46
+ set inspectorMin(value: number);
47
+ get inspectorMax(): number;
48
+ set inspectorMax(value: number);
49
+ get bottomMin(): number;
50
+ set bottomMin(value: number);
51
+ get bottomMax(): number;
52
+ set bottomMax(value: number);
53
+ get mainMinSize(): number;
54
+ set mainMinSize(value: number);
55
+ get panelSizes(): ToolLayoutSizes;
56
+ set panelSizes(value: ToolLayoutSizes | string);
57
+ get sizes(): Required<ToolLayoutSizes>;
58
+ setPanelOpen(panel: ToolLayoutPanel, open: boolean): void;
59
+ togglePanel(panel: ToolLayoutPanel): void;
60
+ private number;
61
+ private bounds;
62
+ private panelElement;
63
+ private onClose;
64
+ private scheduleHandles;
65
+ private computeSizes;
66
+ private limit;
67
+ private resizePanel;
68
+ private startResize;
69
+ private moveResize;
70
+ private endResize;
71
+ private cancelResize;
72
+ private finishResize;
73
+ private keyResize;
74
+ private ensureHandles;
75
+ private positionHandles;
76
+ get variant(): ToolLayoutVariant;
77
+ set variant(value: ToolLayoutVariant);
78
+ get fullHeight(): boolean;
79
+ set fullHeight(value: boolean);
80
+ connectedCallback(): void;
81
+ disconnectedCallback(): void;
82
+ attributeChangedCallback(): void;
83
+ private sync;
84
+ }
85
+ declare global {
86
+ interface HTMLElementTagNameMap {
87
+ 'db-tool-layout': DbToolLayout;
88
+ }
89
+ }
90
+
91
+ export { DbToolLayout, TOOL_LAYOUT_VARIANTS };
92
+ export type { ToolLayoutPanel, ToolLayoutResizeDetail, ToolLayoutSizes, ToolLayoutVariant };
@@ -0,0 +1 @@
1
+ import{t,subscribeDbLocale as e}from"../core/i18n.js";const i=["floating","flush","inset"],s=["sidebar","inspector","bottom"],n={sidebar:{min:160,max:320},inspector:{min:200,max:360},bottom:{min:96,max:280}},a=["header","rail","sidebar","main","inspector","bottom","status"];class DbToolLayout extends HTMLElement{constructor(){super(...arguments),this.width=1280,this.height=0,this.effective={sidebar:320,inspector:360,bottom:280},this.handles=new Map,this.frame=0,this.lateralBudget=1/0,this.bottomCapacity=1/0,this.onClose=t=>{const e=t.target,i=e.getAttribute("slot");e.parentElement===this&&s.includes(i)&&(t.stopPropagation(),this.setPanelOpen(i,!1))},this.scheduleHandles=()=>{cancelAnimationFrame(this.frame),this.frame=requestAnimationFrame(()=>this.positionHandles())},this.moveResize=t=>{const e=this.drag;if(!e||t.pointerId!==e.pointer)return;const i=("bottom"===e.panel?t.clientY:t.clientX)-e.origin;this.resizePanel(e.panel,e.size+i*("sidebar"===e.panel?1:-1))},this.endResize=t=>{this.drag&&t.pointerId===this.drag.pointer&&this.finishResize(!1)},this.cancelResize=t=>{this.drag?.pointer===t.pointerId&&this.finishResize(!0)}}static get observedAttributes(){return["variant","full-height","resizable","panel-sizes","sidebar-hidden","inspector-hidden","bottom-hidden","sidebar-min","sidebar-max","inspector-min","inspector-max","bottom-min","bottom-max","main-min-size"]}get resizable(){return"false"!==this.getAttribute("resizable")}set resizable(t){this.setAttribute("resizable",String(t))}get sidebarHidden(){return this.hasAttribute("sidebar-hidden")}set sidebarHidden(t){this.toggleAttribute("sidebar-hidden",t)}get inspectorHidden(){return this.hasAttribute("inspector-hidden")}set inspectorHidden(t){this.toggleAttribute("inspector-hidden",t)}get bottomHidden(){return this.hasAttribute("bottom-hidden")}set bottomHidden(t){this.toggleAttribute("bottom-hidden",t)}get sidebarMin(){return this.bounds("sidebar").min}set sidebarMin(t){this.setAttribute("sidebar-min",String(t))}get sidebarMax(){return this.bounds("sidebar").max}set sidebarMax(t){this.setAttribute("sidebar-max",String(t))}get inspectorMin(){return this.bounds("inspector").min}set inspectorMin(t){this.setAttribute("inspector-min",String(t))}get inspectorMax(){return this.bounds("inspector").max}set inspectorMax(t){this.setAttribute("inspector-max",String(t))}get bottomMin(){return this.bounds("bottom").min}set bottomMin(t){this.setAttribute("bottom-min",String(t))}get bottomMax(){return this.bounds("bottom").max}set bottomMax(t){this.setAttribute("bottom-max",String(t))}get mainMinSize(){return this.number("main-min-size",280)}set mainMinSize(t){this.setAttribute("main-min-size",String(t))}get panelSizes(){try{const t=JSON.parse(this.getAttribute("panel-sizes")||"{}");return t&&"object"==typeof t?Object.fromEntries(s.filter(e=>"number"==typeof t[e]&&Number.isFinite(t[e])).map(e=>[e,t[e]])):{}}catch{return{}}}set panelSizes(t){this.setAttribute("panel-sizes","string"==typeof t?t:JSON.stringify(t))}get sizes(){return{...this.effective}}setPanelOpen(t,e){if(!s.includes(t))return;const i=this.panelElement(t),n=!e&&i?.contains(document.activeElement);if(this.toggleAttribute(`${t}-hidden`,!e),n){const e=this.querySelector(`[data-tool-toggle="${t}"]`),i=e||this.panelElement("main");i&&(e||i.hasAttribute("tabindex")||(i.tabIndex=-1),i.focus({preventScroll:!0}))}this.dispatchEvent(new CustomEvent("db-panel-toggle",{bubbles:!0,composed:!0,detail:{panel:t,open:e}}))}togglePanel(t){this.setPanelOpen(t,this.hasAttribute(`${t}-hidden`))}number(t,e){const i=Number(this.getAttribute(t));return this.hasAttribute(t)&&Number.isFinite(i)?Math.max(0,Math.min(4096,i)):e}bounds(t){const e=this.number(`${t}-min`,n[t].min);return{min:e,max:Math.max(e,this.number(`${t}-max`,n[t].max))}}panelElement(t){return Array.from(this.children).find(e=>e.getAttribute("slot")===t)}computeSizes(t,e){const i=this.panelSizes;for(const t of s){const e=this.bounds(t),s=this.style.getPropertyValue("--db-tool-"+("bottom"===t?"bottom-height":t+"-width")).trim().match(/^(\d+(?:\.\d+)?)(?:px)?$/),n=s?Number(s[1]):e.max;this.effective[t]=Math.max(e.min,Math.min(e.max,i[t]??n))}const n=getComputedStyle(this),a=1+(t("rail")?1:0)+(t("sidebar")&&"mobile"!==e?1:0)+(t("inspector")&&"desktop"===e?1:0),o=Math.max(0,this.width-parseFloat(n.paddingLeft||"0")-parseFloat(n.paddingRight||"0")-(parseFloat(n.columnGap)||0)*(a-1)-(t("rail")?parseFloat(n.getPropertyValue("--db-tool-rail-width"))||56:0)),r=s.filter(i=>"bottom"!==i&&t(i)&&("sidebar"===i?"mobile"!==e:"desktop"===e)),h=Math.max(0,o-Math.min(this.mainMinSize,o));this.lateralBudget=h,this.bottomCapacity=1/0;let l=r.reduce((t,e)=>t+this.effective[e],0)-h;for(const t of r){const e=Math.min(Math.max(0,l),Math.max(0,this.effective[t]-this.bounds(t).min));this.effective[t]-=e,l-=e}if(l>0){const t=r.reduce((t,e)=>t+this.effective[e],0);for(const e of r)this.effective[e]*=h/(t||1)}if(this.fullHeight&&t("bottom")){const t=["header","status"].reduce((t,e)=>t+(this.panelElement(e)?.getBoundingClientRect().height||0),0),e=Math.max(0,this.clientHeight-t-220-parseFloat(n.paddingTop||"0")-parseFloat(n.paddingBottom||"0")-3*(parseFloat(n.rowGap)||0));this.bottomCapacity=e,this.effective.bottom=Math.min(this.effective.bottom,e)}}limit(t){const e=this.bounds(t),i="sidebar"===t?"inspector":"sidebar",s=this.hasAttribute(`data-has-${i}`)&&("sidebar"===i?"mobile"!==this.dataset.size:"desktop"===this.dataset.size),n="bottom"===t?this.bottomCapacity:Math.max(0,this.lateralBudget-(s?this.effective[i]:0)),a=Math.min(e.max,n);return{min:Math.min(e.min,a),max:a}}resizePanel(t,e,i="change"){const{min:s,max:n}=this.limit(t);this.panelSizes={...this.panelSizes,[t]:Math.round(Math.max(s,Math.min(n,e)))},this.dispatchEvent(new CustomEvent("db-panel-resize",{bubbles:!0,composed:!0,detail:{panel:t,size:this.effective[t],sizes:this.sizes,phase:i}}))}startResize(t,e,i){0!==t.button||this.drag||(t.preventDefault(),i.focus({preventScroll:!0}),this.drag={panel:e,handle:i,pointer:t.pointerId,origin:"bottom"===e?t.clientY:t.clientX,size:this.effective[e],before:this.panelSizes},i.setPointerCapture(t.pointerId),this.dataset.resizing=e)}finishResize(t){const e=this.drag;e&&(this.drag=void 0,delete this.dataset.resizing,t&&(this.panelSizes=e.before),e.handle.hasPointerCapture(e.pointer)&&e.handle.releasePointerCapture(e.pointer),this.dispatchEvent(new CustomEvent("db-panel-resize",{bubbles:!0,composed:!0,detail:{panel:e.panel,size:this.effective[e.panel],sizes:this.sizes,phase:t?"cancel":"end"}})))}keyResize(t,e){if("Escape"===t.key&&this.drag)return void this.finishResize(!0);const i=this.limit(e);let s;"Home"===t.key&&(s=i.min),"End"===t.key&&(s=i.max);const n=t.shiftKey?32:8;if("bottom"===e)"ArrowUp"===t.key&&(s=this.effective[e]+n),"ArrowDown"===t.key&&(s=this.effective[e]-n);else{const i="sidebar"===e?1:-1;"ArrowRight"===t.key&&(s=this.effective[e]+n*i),"ArrowLeft"===t.key&&(s=this.effective[e]-n*i)}void 0!==s&&(t.preventDefault(),this.resizePanel(e,s,"end"))}ensureHandles(){for(const t of s){if(this.handles.has(t))continue;const e=document.createElement("div");e.className="designbase-wc-tool-layout__handle",e.dataset.panel=t,e.setAttribute("role","separator"),e.tabIndex=0,e.setAttribute("aria-orientation","bottom"===t?"horizontal":"vertical"),e.addEventListener("pointerdown",i=>this.startResize(i,t,e)),e.addEventListener("pointermove",this.moveResize),e.addEventListener("pointerup",this.endResize),e.addEventListener("pointercancel",this.cancelResize),e.addEventListener("lostpointercapture",this.cancelResize),e.addEventListener("keydown",e=>this.keyResize(e,t)),e.addEventListener("dblclick",()=>this.resizePanel(t,this.limit(t).max,"end")),this.handles.set(t,e),this.append(e)}}positionHandles(){const e=this.getBoundingClientRect(),i=parseFloat(getComputedStyle(this).columnGap)||0;for(const n of s){const s=this.handles.get(n),a=this.panelElement(n),o=!!a&&!a.hidden&&!this.hasAttribute(`${n}-hidden`)&&this.resizable&&("bottom"===n||("sidebar"===n?"mobile"!==this.dataset.size:"desktop"===this.dataset.size));if(s.hidden=!o,!o)continue;const r=a.getBoundingClientRect();s.setAttribute("aria-label",t(`toolLayout.resize.${n}`));const h=this.limit(n);s.setAttribute("aria-valuemin",String(Math.min(h.min,this.effective[n]))),s.setAttribute("aria-valuemax",String(h.max)),s.setAttribute("aria-valuenow",String(Math.round(this.effective[n]))),a.id&&s.setAttribute("aria-controls",a.id),Object.assign(s.style,"bottom"===n?{left:`${r.left-e.left+this.scrollLeft}px`,top:r.top-e.top+this.scrollTop-i/2-4+"px",width:`${r.width}px`,height:"8px"}:{left:("sidebar"===n?r.right+i/2:r.left-i/2)-e.left+this.scrollLeft-4+"px",top:`${r.top-e.top+this.scrollTop}px`,width:"8px",height:`${r.height}px`})}}get variant(){const t=this.getAttribute("variant");return i.includes(t)?t:"floating"}set variant(t){this.setAttribute("variant",t)}get fullHeight(){return this.hasAttribute("full-height")}set fullHeight(t){this.toggleAttribute("full-height",t)}connectedCallback(){this.classList.add("designbase-wc-tool-layout"),this.ensureHandles(),this.addEventListener("db-close",this.onClose),this.addEventListener("scroll",this.scheduleHandles),this.unsubscribe=e(this.scheduleHandles),this.width=this.getBoundingClientRect().width||1280,this.sync(),this.mutations=new MutationObserver(t=>{t.some(t=>t.target===this||t.target.parentElement===this)&&this.sync()}),this.mutations.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["slot","hidden"]}),this.resize=new ResizeObserver(t=>{const e=t.find(t=>t.target===this),i=e?.borderBoxSize?.[0]?.inlineSize??this.getBoundingClientRect().width,s=e?.borderBoxSize?.[0]?.blockSize??this.getBoundingClientRect().height;i!==this.width||this.fullHeight&&s!==this.height?(this.width=i,this.height=s,this.sync()):this.scheduleHandles()}),this.resize.observe(this);for(const t of this.children)t.hasAttribute("slot")&&this.resize.observe(t)}disconnectedCallback(){this.mutations?.disconnect(),this.resize?.disconnect(),this.unsubscribe?.(),cancelAnimationFrame(this.frame),this.finishResize(!0),this.removeEventListener("db-close",this.onClose),this.removeEventListener("scroll",this.scheduleHandles)}attributeChangedCallback(){this.isConnected&&this.sync()}sync(){this.dataset.variant=this.variant,!this.drag||this.resizable&&this.panelElement(this.drag.panel)&&!this.hasAttribute(`${this.drag.panel}-hidden`)&&!this.panelElement(this.drag.panel)?.hidden||this.finishResize(!0);for(const t of s)this.panelElement(t)?.toggleAttribute("data-tool-hidden",this.hasAttribute(`${t}-hidden`));const t=new Set(Array.from(this.children).filter(t=>!t.hasAttribute("hidden")&&!t.hasAttribute("data-tool-hidden")).map(t=>t.getAttribute("slot"))),has=e=>t.has(e),e=this.width<768?"mobile":this.width<1024?"tablet":"desktop";this.computeSizes(has,e);const i=[...has("rail")?["var(--db-tool-rail-width, 56px)"]:[],...has("sidebar")&&"mobile"!==e?[`minmax(0, ${this.effective.sidebar}px)`]:[],"minmax(0, 1fr)",...has("inspector")&&"desktop"===e?[`minmax(0, ${this.effective.inspector}px)`]:[]],n=[...has("rail")?["rail"]:[],...has("sidebar")&&"mobile"!==e?["sidebar"]:[],"main",...has("inspector")&&"desktop"===e?["inspector"]:[]],o=[],r=[],row=(t,e,s=!1)=>{o.push(i.map((e,i)=>s&&has("rail")&&0===i?"rail":t)),r.push(e)};has("header")&&row("header","auto"),o.push(n),r.push("minmax(220px, 1fr)"),has("sidebar")&&"mobile"===e&&row("sidebar","auto",!0),has("inspector")&&"desktop"!==e&&row("inspector","auto",!0),has("bottom")&&row("bottom",`${this.effective.bottom}px`,!0),has("status")&&row("status","auto"),this.style.setProperty("--db-tool-columns",i.join(" ")),this.style.setProperty("--db-tool-areas",o.map(t=>`"${t.join(" ")}"`).join(" ")),this.style.setProperty("--db-tool-rows",r.join(" "));const h=o.filter(t=>!t.includes("header")&&!t.includes("status")),l=h[0].filter(t=>"rail"!==t),d=h[h.length-1].filter(t=>"rail"!==t);for(const t of Array.from(this.children)){const e=t.getAttribute("slot");if(!e||"rail"===e||"header"===e||"status"===e)continue;const i=[l[0]===e&&"top-left",l[l.length-1]===e&&"top-right",d[0]===e&&"bottom-left",d[d.length-1]===e&&"bottom-right"].filter(Boolean).join(" ");t.getAttribute("data-tool-corners")!==i&&t.setAttribute("data-tool-corners",i)}this.dataset.size=e,this.dataset.variant=this.variant;for(const t of a)this.toggleAttribute(`data-has-${t}`,has(t));this.scheduleHandles()}}customElements.get("db-tool-layout")||customElements.define("db-tool-layout",DbToolLayout);export{DbToolLayout,i as TOOL_LAYOUT_VARIANTS};
@@ -0,0 +1,50 @@
1
+ interface ToolPanelTab {
2
+ id: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ }
6
+ /** Content stays in its original DOM across collapse and tab changes. Nest appearance="section"
7
+ * panels inside a body for independent disclosure groups, or appearance="card" for inset cards. */
8
+ declare class DbToolPanel extends HTMLElement {
9
+ static get observedAttributes(): string[];
10
+ private headingElement?;
11
+ private titleButton?;
12
+ private closeButton?;
13
+ private tabsElement?;
14
+ private observer?;
15
+ private unsubscribe?;
16
+ private uid;
17
+ get heading(): string;
18
+ set heading(value: string);
19
+ get padding(): 'none' | 's' | 'm';
20
+ set padding(value: 'none' | 's' | 'm');
21
+ get collapsible(): boolean;
22
+ set collapsible(value: boolean);
23
+ get collapsed(): boolean;
24
+ set collapsed(value: boolean);
25
+ get closable(): boolean;
26
+ set closable(value: boolean);
27
+ get divider(): boolean;
28
+ set divider(value: boolean);
29
+ get appearance(): 'default' | 'section' | 'card';
30
+ set appearance(value: 'default' | 'section' | 'card');
31
+ get tabs(): ToolPanelTab[];
32
+ set tabs(value: ToolPanelTab[] | string);
33
+ get selectedTab(): string;
34
+ set selectedTab(value: string);
35
+ connectedCallback(): void;
36
+ disconnectedCallback(): void;
37
+ attributeChangedCallback(): void;
38
+ toggle(): void;
39
+ private ensureChrome;
40
+ private makeTitle;
41
+ private sync;
42
+ }
43
+ declare global {
44
+ interface HTMLElementTagNameMap {
45
+ 'db-tool-panel': DbToolPanel;
46
+ }
47
+ }
48
+
49
+ export { DbToolPanel };
50
+ export type { ToolPanelTab };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t}from"./db-icons.js";import{dbUid as e}from"../core/uid.js";import{subscribeDbLocale as s,t as i}from"../core/i18n.js";class DbToolPanel extends HTMLElement{constructor(){super(...arguments),this.uid=e("tool-panel")}static get observedAttributes(){return["heading","padding","collapsible","collapsed","closable","divider","appearance","tabs","selected-tab"]}get heading(){return this.getAttribute("heading")||""}set heading(t){this.setAttribute("heading",t)}get padding(){const t=this.getAttribute("padding");return"none"===t||"s"===t?t:"m"}set padding(t){this.setAttribute("padding",t)}get collapsible(){return this.hasAttribute("collapsible")}set collapsible(t){this.toggleAttribute("collapsible",t)}get collapsed(){return this.hasAttribute("collapsed")}set collapsed(t){this.toggleAttribute("collapsed",t)}get closable(){return this.hasAttribute("closable")}set closable(t){this.toggleAttribute("closable",t)}get divider(){return this.hasAttribute("divider")}set divider(t){this.toggleAttribute("divider",t)}get appearance(){const t=this.getAttribute("appearance");return"section"===t||"card"===t?t:"default"}set appearance(t){this.setAttribute("appearance",t)}get tabs(){try{const t=JSON.parse(this.getAttribute("tabs")||"[]"),e=new Set;return Array.isArray(t)?t.filter(t=>t&&"string"==typeof t.id&&!!t.id&&"string"==typeof t.label&&!!t.label&&!e.has(t.id)&&!!e.add(t.id)):[]}catch{return[]}}set tabs(t){this.setAttribute("tabs","string"==typeof t?t:JSON.stringify(t))}get selectedTab(){const t=this.tabs;return t.find(t=>t.id===this.getAttribute("selected-tab")&&!t.disabled)?.id||t.find(t=>!t.disabled)?.id||""}set selectedTab(t){this.setAttribute("selected-tab",t)}connectedCallback(){this.classList.add("designbase-wc-tool-panel"),this.id||(this.id=this.uid),this.ensureChrome(),this.sync(),this.observer=new MutationObserver(t=>{t.some(t=>t.target===this||t.target.parentElement===this)&&this.sync()}),this.observer.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["slot"]}),this.unsubscribe=s(()=>this.sync())}disconnectedCallback(){this.observer?.disconnect(),this.unsubscribe?.()}attributeChangedCallback(){this.isConnected&&this.sync()}toggle(){this.collapsible&&(this.collapsed=!this.collapsed,this.dispatchEvent(new CustomEvent("db-collapse-change",{bubbles:!0,composed:!0,detail:{collapsed:this.collapsed}})))}ensureChrome(){this.headingElement?.parentElement!==this&&(this.headingElement=document.createElement("div"),this.headingElement.className="designbase-wc-tool-panel__heading",this.headingElement.setAttribute("data-tool-heading",""),this.headingElement.setAttribute("data-tool-chrome",""),this.titleButton=this.makeTitle(),this.headingElement.append(this.titleButton),this.closeButton=document.createElement("button"),this.closeButton.type="button",this.closeButton.className="designbase-wc-tool-panel__close",this.closeButton.setAttribute("data-tool-chrome",""),this.closeButton.append(t("close",14)),this.closeButton.addEventListener("click",()=>this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))),this.tabsElement=document.createElement("db-tabs"),this.tabsElement.className="designbase-wc-tool-panel__tabs",this.tabsElement.setAttribute("data-tool-chrome",""),this.tabsElement.size="s",this.tabsElement.addEventListener("db-change",t=>{t.target===this.tabsElement&&(t.stopPropagation(),this.selectedTab=t.detail.id,this.dispatchEvent(new CustomEvent("db-tab-change",{bubbles:!0,composed:!0,detail:{id:this.selectedTab}})))}),this.prepend(this.headingElement,this.closeButton,this.tabsElement))}makeTitle(){const t=document.createElement(this.collapsible?"button":"span");return t.className="designbase-wc-tool-panel__title",t instanceof HTMLButtonElement&&(t.type="button",t.addEventListener("click",()=>this.toggle())),t}sync(){if(!(this.titleButton&&this.headingElement&&this.tabsElement&&this.closeButton))return;if(this.titleButton instanceof HTMLButtonElement!==this.collapsible){const t=this.makeTitle();this.titleButton.replaceWith(t),this.titleButton=t}const s=this.heading;if(this.titleButton.dataset.heading!==s||this.titleButton.dataset.collapsible!==String(this.collapsible)){if(this.titleButton.replaceChildren(),this.collapsible){const e=t("chevron-down",12);e.classList.add("designbase-wc-tool-panel__chevron"),this.titleButton.append(e)}const e=document.createElement("span");e.textContent=s,this.titleButton.append(e),this.titleButton.dataset.heading=s,this.titleButton.dataset.collapsible=String(this.collapsible)}this.headingElement.hidden=!s,this.collapsible?this.titleButton.tabIndex=0:this.titleButton.removeAttribute("tabindex"),this.collapsible?this.titleButton.setAttribute("aria-expanded",String(!this.collapsed)):this.titleButton.removeAttribute("aria-expanded"),this.closeButton.hidden=!this.closable,this.closeButton.setAttribute("aria-label",i("toolPanel.close")),this.closeButton.title=i("toolPanel.close");const a=this.tabs;this.tabsElement.hidden=!a.length;const l=JSON.stringify(a);this.tabsElement.getAttribute("items")!==l&&(this.tabsElement.items=a),this.tabsElement.selectedId!==this.selectedTab&&(this.tabsElement.selectedId=this.selectedTab),this.tabsElement.setAttribute("aria-label",s||i("toolPanel.tabs"));const n=[];for(const t of Array.from(this.children)){if(t.hasAttribute("data-tool-chrome")||"actions"===t.getAttribute("slot"))continue;const s=t.getAttribute("slot")||"body";t.id||(t.id=e(`${this.uid}-content`)),n.push(t.id);const i=s.startsWith("tab-");if(t.toggleAttribute("data-tool-tab-hidden",i&&s.slice(4)!==this.selectedTab),i){const e=a.findIndex(t=>`tab-${t.id}`===s),i=this.tabsElement.querySelectorAll('[role="tab"]')[e];t.setAttribute("role","tabpanel"),i&&(t.setAttribute("aria-labelledby",i.id),i.setAttribute("aria-controls",t.id))}}this.titleButton.setAttribute("aria-controls",n.join(" ")),this.dataset.padding=this.padding,this.dataset.appearance=this.appearance,this.dataset.collapsed=String(this.collapsible&&this.collapsed)}}customElements.get("db-tool-panel")||customElements.define("db-tool-panel",DbToolPanel);export{DbToolPanel};
@@ -1,6 +1,8 @@
1
1
  declare class DbTopBanner extends HTMLElement {
2
+ private unsubscribeLocale?;
2
3
  static get observedAttributes(): string[];
3
4
  connectedCallback(): void;
5
+ disconnectedCallback(): void;
4
6
  attributeChangedCallback(): void;
5
7
  private isDarkBg;
6
8
  private createLinkButton;
@@ -1 +1 @@
1
- import{dbText as e}from"../core/i18n.js";import{createDbIcon as t}from"./db-icons.js";import{TOP_BANNER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTopBanner extends HTMLElement{static get observedAttributes(){return["badge-text","content","image","link-text","variant","fixed","dismissed"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}isDarkBg(e){return"primary"===e||"dark"===e}createLinkButton(e,n){const s=this.isDarkBg(e),a=document.createElement("db-button");a.setAttribute("variant",s?"secondary":"ghost"),a.setAttribute("size","s"),a.classList.add("designbase-wc-top-banner__link");const i=document.createElement("span");i.textContent=n;const r=document.createElement("span");return r.className="designbase-wc-button__end-icon",r.append(t("chevron-right",16)),a.append(i,r),a.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-link",{bubbles:!0,composed:!0}))}),a}createCloseButton(){const n=document.createElement("db-button");return n.setAttribute("variant","ghost"),n.setAttribute("size","m"),n.setAttribute("icon-only",""),n.setAttribute("aria-label",e("닫기")),n.classList.add("designbase-wc-top-banner__close"),n.append(t("close",20)),n.addEventListener("db-click",()=>{this.setAttribute("dismissed",""),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})),this.render()}),n}createBadge(e,t){const n=document.createElement("db-badge");return n.setAttribute("size","s"),n.setAttribute("variant",t?"secondary":"primary"),n.setAttribute("type","text"),n.textContent=e,n.classList.add("designbase-wc-top-banner__badge"),n}render(){if(this.hasAttribute("dismissed"))return this.replaceChildren(),this.className="designbase-wc-top-banner designbase-wc-top-banner--dismissed",void(this.style.display="none");this.style.display="";const e=this.getAttribute("badge-text")||"",t=this.getAttribute("content")||"",s=this.getAttribute("image")||"",a=this.getAttribute("link-text")||"",i=this.getAttribute("variant")||"primary",r=n.includes(i)?i:"primary",d=this.hasAttribute("fixed"),o=this.isDarkBg(r);if(this.className=["designbase-wc-top-banner",`designbase-wc-top-banner--${r}`,d&&"designbase-wc-top-banner--fixed",s&&"designbase-wc-top-banner--has-image"].filter(Boolean).join(" "),this.setAttribute("role","alert"),s?this.style.setProperty("--db-top-banner-bg-image",`url("${s}")`):this.style.removeProperty("--db-top-banner-bg-image"),this.replaceChildren(),s){const e=document.createElement("div");e.className="designbase-wc-top-banner__background",e.setAttribute("aria-hidden","true");const t=document.createElement("div");t.className="designbase-wc-top-banner__overlay",t.setAttribute("aria-hidden","true"),this.append(e,t)}const c=document.createElement("div");c.className="designbase-wc-top-banner__container";const b=document.createElement("div");b.className="designbase-wc-top-banner__content",e&&b.append(this.createBadge(e,o));const p=document.createElement("span");p.className="designbase-wc-top-banner__text",p.textContent=t,b.append(p),a&&b.append(this.createLinkButton(r,a)),c.append(b),c.append(this.createCloseButton()),this.append(c)}}customElements.get("db-top-banner")||customElements.define("db-top-banner",DbTopBanner);export{DbTopBanner};
1
+ import{subscribeDbLocale as e,dbText as t}from"../core/i18n.js";import{createDbIcon as s}from"./db-icons.js";import{TOP_BANNER_VARIANTS as n}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";class DbTopBanner extends HTMLElement{static get observedAttributes(){return["badge-text","content","image","link-text","variant","fixed","dismissed"]}connectedCallback(){this.render(),this.unsubscribeLocale?.(),this.unsubscribeLocale=e(()=>this.querySelector(".designbase-wc-top-banner__close")?.setAttribute("aria-label",t("닫기")))}disconnectedCallback(){this.unsubscribeLocale?.(),this.unsubscribeLocale=void 0}attributeChangedCallback(){this.render()}isDarkBg(e){return"primary"===e||"dark"===e}createLinkButton(e,t){const n=this.isDarkBg(e),a=document.createElement("db-button");a.setAttribute("variant",n?"secondary":"ghost"),a.setAttribute("size","s"),a.classList.add("designbase-wc-top-banner__link");const i=document.createElement("span");i.textContent=t;const r=document.createElement("span");return r.className="designbase-wc-button__end-icon",r.append(s("chevron-right",16)),a.append(i,r),a.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-link",{bubbles:!0,composed:!0}))}),a}createCloseButton(){const e=document.createElement("db-button");return e.setAttribute("variant","ghost"),e.setAttribute("size","m"),e.setAttribute("icon-only",""),e.setAttribute("aria-label",t("닫기")),e.classList.add("designbase-wc-top-banner__close"),e.append(s("close",20)),e.addEventListener("db-click",()=>{this.setAttribute("dismissed",""),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0})),this.render()}),e}createBadge(e,t){const s=document.createElement("db-badge");return s.setAttribute("size","s"),s.setAttribute("variant",t?"secondary":"primary"),s.setAttribute("type","text"),s.textContent=e,s.classList.add("designbase-wc-top-banner__badge"),s}render(){if(this.hasAttribute("dismissed"))return this.replaceChildren(),this.className="designbase-wc-top-banner designbase-wc-top-banner--dismissed",void(this.style.display="none");this.style.display="";const e=this.getAttribute("badge-text")||"",t=this.getAttribute("content")||"",s=this.getAttribute("image")||"",a=this.getAttribute("link-text")||"",i=this.getAttribute("variant")||"primary",r=n.includes(i)?i:"primary",c=this.hasAttribute("fixed"),d=this.isDarkBg(r);if(this.className=["designbase-wc-top-banner",`designbase-wc-top-banner--${r}`,c&&"designbase-wc-top-banner--fixed",s&&"designbase-wc-top-banner--has-image"].filter(Boolean).join(" "),this.setAttribute("role","alert"),s?this.style.setProperty("--db-top-banner-bg-image",`url("${s}")`):this.style.removeProperty("--db-top-banner-bg-image"),this.replaceChildren(),s){const e=document.createElement("div");e.className="designbase-wc-top-banner__background",e.setAttribute("aria-hidden","true");const t=document.createElement("div");t.className="designbase-wc-top-banner__overlay",t.setAttribute("aria-hidden","true"),this.append(e,t)}const o=document.createElement("div");o.className="designbase-wc-top-banner__container";const b=document.createElement("div");b.className="designbase-wc-top-banner__content",e&&b.append(this.createBadge(e,d));const l=document.createElement("span");l.className="designbase-wc-top-banner__text",l.textContent=t,b.append(l),a&&b.append(this.createLinkButton(r,a)),o.append(b),o.append(this.createCloseButton()),this.append(o)}}customElements.get("db-top-banner")||customElements.define("db-top-banner",DbTopBanner);export{DbTopBanner};