@designbasekorea/ui-wc 0.5.3 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/chunks/lottie-e273b936.js +17032 -0
  2. package/dist/esm/components/animation-background/canvas-controller.js +121 -1
  3. package/dist/esm/components/animation-background/controls.js +180 -1
  4. package/dist/esm/components/animation-background/graphite-controller.js +196 -1
  5. package/dist/esm/components/animation-background/graphite-presets.js +42 -1
  6. package/dist/esm/components/animation-background/graphite-shader.js +111 -1
  7. package/dist/esm/components/animation-background/layers.js +369 -1
  8. package/dist/esm/components/animation-background/lumina-presets.js +53 -1
  9. package/dist/esm/components/animation-background/lumina-shaders.js +181 -1
  10. package/dist/esm/components/animation-background/lumina-utils.js +60 -1
  11. package/dist/esm/components/animation-background/particle-defaults.js +36 -1
  12. package/dist/esm/components/animation-background/renderers.js +167 -1
  13. package/dist/esm/components/animation-background/shader-controller.js +154 -1
  14. package/dist/esm/components/color-picker-utils.js +134 -1
  15. package/dist/esm/components/date-picker-utils.js +140 -1
  16. package/dist/esm/components/db-accordion.js +304 -1
  17. package/dist/esm/components/db-ad-banner.js +455 -1
  18. package/dist/esm/components/db-alert.js +149 -1
  19. package/dist/esm/components/db-animation-background.js +486 -1
  20. package/dist/esm/components/db-animation-text.js +601 -1
  21. package/dist/esm/components/db-app-badge.js +88 -1
  22. package/dist/esm/components/db-audio-player.js +752 -1
  23. package/dist/esm/components/db-avatar.js +188 -1
  24. package/dist/esm/components/db-backdrop.js +139 -1
  25. package/dist/esm/components/db-badge.js +91 -1
  26. package/dist/esm/components/db-banner.js +188 -1
  27. package/dist/esm/components/db-bottom-navigation.js +146 -1
  28. package/dist/esm/components/db-bottom-sheet.js +481 -1
  29. package/dist/esm/components/db-breadcrumbs.js +329 -1
  30. package/dist/esm/components/db-button.js +316 -1
  31. package/dist/esm/components/db-calendar.js +675 -1
  32. package/dist/esm/components/db-card.js +265 -1
  33. package/dist/esm/components/db-carousel.js +264 -1
  34. package/dist/esm/components/db-checkbox.js +202 -1
  35. package/dist/esm/components/db-chip.js +104 -1
  36. package/dist/esm/components/db-code-block.js +304 -1
  37. package/dist/esm/components/db-color-picker.js +746 -1
  38. package/dist/esm/components/db-confirm.js +191 -1
  39. package/dist/esm/components/db-container.js +39 -1
  40. package/dist/esm/components/db-context-menu.js +265 -1
  41. package/dist/esm/components/db-countdown.js +146 -1
  42. package/dist/esm/components/db-cursor-follower.js +173 -1
  43. package/dist/esm/components/db-date-picker.js +837 -1
  44. package/dist/esm/components/db-divider.js +66 -1
  45. package/dist/esm/components/db-drawer.js +245 -1
  46. package/dist/esm/components/db-dropdown.js +493 -1
  47. package/dist/esm/components/db-dropzone.js +266 -1
  48. package/dist/esm/components/db-empty-state.js +97 -1
  49. package/dist/esm/components/db-file-uploader.js +256 -1
  50. package/dist/esm/components/db-floating-action-button.js +139 -1
  51. package/dist/esm/components/db-footer.js +385 -1
  52. package/dist/esm/components/db-form.js +566 -1
  53. package/dist/esm/components/db-gantt.js +882 -1
  54. package/dist/esm/components/db-gradient.js +133 -1
  55. package/dist/esm/components/db-grid-background.js +909 -1
  56. package/dist/esm/components/db-grid.js +73 -1
  57. package/dist/esm/components/db-icons.js +82 -1
  58. package/dist/esm/components/db-image-list.js +214 -1
  59. package/dist/esm/components/db-image-placeholder.js +96 -1
  60. package/dist/esm/components/db-image.js +289 -1
  61. package/dist/esm/components/db-indicator.js +517 -1
  62. package/dist/esm/components/db-input.js +420 -1
  63. package/dist/esm/components/db-kanban.js +538 -1
  64. package/dist/esm/components/db-label.js +66 -1
  65. package/dist/esm/components/db-lightbox.js +372 -1
  66. package/dist/esm/components/db-list.js +340 -1
  67. package/dist/esm/components/db-logo-svg.js +72 -1
  68. package/dist/esm/components/db-logo.js +106 -1
  69. package/dist/esm/components/db-lottie.js +109 -1
  70. package/dist/esm/components/db-markdown-editor.js +458 -1
  71. package/dist/esm/components/db-marquee.js +402 -1
  72. package/dist/esm/components/db-masonry.js +94 -1
  73. package/dist/esm/components/db-menu-item.js +211 -1
  74. package/dist/esm/components/db-modal.js +522 -1
  75. package/dist/esm/components/db-navbar.js +680 -1
  76. package/dist/esm/components/db-onboarding-modal.js +322 -1
  77. package/dist/esm/components/db-page-header.js +312 -1
  78. package/dist/esm/components/db-pagination.js +271 -1
  79. package/dist/esm/components/db-popover.js +580 -1
  80. package/dist/esm/components/db-progress-step.js +166 -1
  81. package/dist/esm/components/db-progress.js +171 -1
  82. package/dist/esm/components/db-progressbar.js +72 -1
  83. package/dist/esm/components/db-radio.js +172 -1
  84. package/dist/esm/components/db-random-gradient.js +121 -1
  85. package/dist/esm/components/db-range-slider.js +811 -1
  86. package/dist/esm/components/db-rating.js +325 -1
  87. package/dist/esm/components/db-reorder.js +286 -1
  88. package/dist/esm/components/db-resizable-panels.js +282 -1
  89. package/dist/esm/components/db-scroll-area.js +126 -1
  90. package/dist/esm/components/db-search-bar.js +668 -1
  91. package/dist/esm/components/db-section-app-download.js +101 -1
  92. package/dist/esm/components/db-section-contact.js +102 -1
  93. package/dist/esm/components/db-section-cta.js +150 -1
  94. package/dist/esm/components/db-section-faq.js +120 -1
  95. package/dist/esm/components/db-section-feature-grid.js +137 -1
  96. package/dist/esm/components/db-section-feature.js +179 -1
  97. package/dist/esm/components/db-section-hero.js +243 -1
  98. package/dist/esm/components/db-section-logo-cloud.js +138 -1
  99. package/dist/esm/components/db-section-pricing.js +166 -1
  100. package/dist/esm/components/db-section-stats.js +129 -1
  101. package/dist/esm/components/db-section-testimonials.js +252 -1
  102. package/dist/esm/components/db-section.js +385 -1
  103. package/dist/esm/components/db-segment-control.js +231 -1
  104. package/dist/esm/components/db-select.js +571 -1
  105. package/dist/esm/components/db-share-icons.js +40 -1
  106. package/dist/esm/components/db-share.js +489 -1
  107. package/dist/esm/components/db-sidebar.js +1068 -1
  108. package/dist/esm/components/db-skeleton.js +94 -1
  109. package/dist/esm/components/db-spinner.js +102 -1
  110. package/dist/esm/components/db-split-view.js +297 -1
  111. package/dist/esm/components/db-stack.js +46 -1
  112. package/dist/esm/components/db-stat.js +218 -1
  113. package/dist/esm/components/db-stepper.js +398 -1
  114. package/dist/esm/components/db-table.js +412 -1
  115. package/dist/esm/components/db-tabs.js +335 -1
  116. package/dist/esm/components/db-testimonial.js +162 -1
  117. package/dist/esm/components/db-textarea.js +233 -1
  118. package/dist/esm/components/db-time-picker.js +523 -1
  119. package/dist/esm/components/db-timeline.js +174 -1
  120. package/dist/esm/components/db-toast.js +158 -1
  121. package/dist/esm/components/db-toggle.js +162 -1
  122. package/dist/esm/components/db-toolbar.js +94 -1
  123. package/dist/esm/components/db-tooltip.js +440 -1
  124. package/dist/esm/components/db-top-banner.js +121 -1
  125. package/dist/esm/components/db-tutorial.js +324 -1
  126. package/dist/esm/components/db-video-player.js +503 -1
  127. package/dist/esm/components/db-youtube-player.js +194 -1
  128. package/dist/esm/components/highlight-code.js +65 -1
  129. package/dist/esm/components/input-validation.js +50 -1
  130. package/dist/esm/components/marketing-block-host-utils.js +9 -1
  131. package/dist/esm/components/number-scrub.js +117 -1
  132. package/dist/esm/components/random-gradient-palettes.js +67 -1
  133. package/dist/esm/components/section-block-header-utils.js +48 -1
  134. package/dist/esm/helpers/confirm.js +52 -1
  135. package/dist/esm/helpers/toast.js +73 -1
  136. package/dist/esm/index.js +111 -1
  137. package/dist/esm/node_modules/prismjs/components/prism-bash.js +235 -1
  138. package/dist/esm/node_modules/prismjs/components/prism-clike.js +31 -1
  139. package/dist/esm/node_modules/prismjs/components/prism-css.js +64 -1
  140. package/dist/esm/node_modules/prismjs/components/prism-javascript.js +172 -1
  141. package/dist/esm/node_modules/prismjs/components/prism-json.js +27 -1
  142. package/dist/esm/node_modules/prismjs/components/prism-jsx.js +143 -1
  143. package/dist/esm/node_modules/prismjs/components/prism-markup.js +186 -1
  144. package/dist/esm/node_modules/prismjs/components/prism-scss.js +81 -1
  145. package/dist/esm/node_modules/prismjs/components/prism-tsx.js +15 -1
  146. package/dist/esm/node_modules/prismjs/components/prism-typescript.js +60 -1
  147. package/dist/index.cjs +55414 -1
  148. package/dist/index.css +1 -1
  149. package/dist/index.esm.js +38284 -1
  150. package/dist/react/chunks/lottie-72a4c6d4.js +17032 -0
  151. package/dist/react/index.cjs +56503 -1
  152. package/dist/react/index.d.ts +1 -1
  153. package/dist/react/index.esm.js +39373 -1
  154. package/package.json +1 -1
  155. package/dist/chunks/lottie-2d1f6278.js +0 -1
  156. package/dist/react/chunks/lottie-14e7addb.js +0 -1
@@ -1 +1,412 @@
1
- import{createDbIcon as e}from"./db-icons.js";const t=["s","m","l"],s=["default","striped","hoverable"];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(t){const s=document.createElement("span");s.className="designbase-wc-table__sort-icon";if(!(this.internalSortColumn===t.key&&Boolean(this.internalSortDirection))){s.classList.add("designbase-wc-table__sort-icon--idle");const t=document.createElement("span");return t.className="designbase-wc-table__sort-icon-stack",t.append(e("chevron-up",10),e("chevron-down",10)),s.append(t),s}return s.classList.add("asc"===this.internalSortDirection?"designbase-wc-table__sort-icon--asc":"designbase-wc-table__sort-icon--desc"),s.append(e("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 e=this.getAttribute("size")||"m",n=this.getAttribute("variant")||"default",a=t.includes(e)?e:"m",i=s.includes(n)?n:"default",c=this.columns,r=this.getPaginatedData(),l=this.getSortedData(),o=this.hasAttribute("loading"),d=this.hasAttribute("selectable"),b=this.hasAttribute("sortable"),h=this.getAttribute("empty-message")||"데이터가 없습니다.";if(this.className=["designbase-wc-table",`designbase-wc-table--${a}`,`designbase-wc-table--${i}`,d&&"designbase-wc-table--selectable",b&&"designbase-wc-table--sortable",o&&"designbase-wc-table--loading"].filter(Boolean).join(" "),this.replaceChildren(),o){const e=document.createElement("div");e.className="designbase-wc-table__loading";const t=document.createElement("div");t.className="designbase-wc-table__loading-spinner";const s=document.createElement("span");return s.textContent="로딩 중...",e.append(t,s),void this.append(e)}const u=this.getAttribute("title"),m=this.hasAttribute("show-count-badge");if(u||m){const e=document.createElement("div");e.className="designbase-wc-table__header";const t=document.createElement("div");if(t.className="designbase-wc-table__header-left",u){const e=document.createElement("h3");e.className="designbase-wc-table__title",e.textContent=u,t.append(e)}if(m){const e=document.createElement("db-badge");e.setAttribute("count",String(this.data.length)),e.setAttribute("badge-style","number"),e.setAttribute("variant","primary"),e.setAttribute("size","s"),t.append(e)}e.append(t),this.append(e)}const g=document.createElement("div");g.className="designbase-wc-table__container";const p=document.createElement("table");p.className="designbase-wc-table__table";const w=document.createElement("thead");w.className="designbase-wc-table__thead";const _=document.createElement("tr");_.className="designbase-wc-table__tr";const A=r.map((e,t)=>this.getRowKey(e,t)),S=A.filter(e=>this.internalSelectedRows.includes(e)),E=this.hasAttribute("clickable");if(d){const e=document.createElement("th");e.className="designbase-wc-table__th designbase-wc-table__th--checkbox";const t=this.createCheckbox({checked:A.length>0&&S.length===A.length,indeterminate:S.length>0&&S.length<A.length,onChange:e=>this.handleSelectAll(e)});e.append(t),_.append(e)}c.forEach(e=>{const t=document.createElement("th");t.className=["designbase-wc-table__th",`designbase-wc-table__th--${e.align||"left"}`,b&&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),b&&e.sortable&&s.append(this.createSortIcon(e)),t.append(s),b&&e.sortable&&t.addEventListener("click",()=>this.handleSort(e)),_.append(t)}),w.append(_);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 t=document.createElement("td");t.className="designbase-wc-table__td designbase-wc-table__td--empty",t.colSpan=Math.max(c.length+(d?1:0),1);const s=document.createElement("db-empty-state");s.setAttribute("title","데이터가 없습니다"),s.setAttribute("description",h),s.setAttribute("variant","no-data"),s.setAttribute("size","m"),t.append(s),e.append(t),f.append(e)}else r.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",E&&"designbase-wc-table__tr--clickable",n&&"designbase-wc-table__tr--selected"].filter(Boolean).join(" "),E&&a.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-row-click",{detail:{item:e,index:t},bubbles:!0,composed:!0}))}),d){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)}c.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(p.append(w,f),g.append(p),this.append(g),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 i=document.createElement("db-pagination");i.setAttribute("current-page",String(this.internalPage)),i.setAttribute("total-pages",String(s)),i.setAttribute("size",a),i.setAttribute("show-first-last",""),i.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(i),this.append(n)}}}customElements.get("db-table")||customElements.define("db-table",DbTable);export{DbTable};
1
+ import { createDbIcon } from './db-icons.js';
2
+
3
+ const SIZES = ['s', 'm', 'l'];
4
+ const VARIANTS = ['default', 'striped', 'hoverable'];
5
+ class DbTable extends HTMLElement {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.internalSelectedRows = [];
9
+ this.internalSortDirection = null;
10
+ this.internalPage = 1;
11
+ }
12
+ static get observedAttributes() {
13
+ return [
14
+ 'columns',
15
+ 'data',
16
+ 'title',
17
+ 'size',
18
+ 'variant',
19
+ 'empty-message',
20
+ 'sortable',
21
+ 'sort-column',
22
+ 'sort-direction',
23
+ 'selectable',
24
+ 'multi-select',
25
+ 'selected-rows',
26
+ 'row-key',
27
+ 'loading',
28
+ 'pagination',
29
+ 'page',
30
+ 'page-size',
31
+ 'total-items',
32
+ 'show-count-badge',
33
+ 'clickable',
34
+ ];
35
+ }
36
+ get columns() {
37
+ try {
38
+ return JSON.parse(this.getAttribute('columns') || '[]');
39
+ }
40
+ catch {
41
+ return [];
42
+ }
43
+ }
44
+ set columns(value) {
45
+ this.setAttribute('columns', typeof value === 'string' ? value : JSON.stringify(value));
46
+ }
47
+ get data() {
48
+ try {
49
+ return JSON.parse(this.getAttribute('data') || '[]');
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ }
55
+ set data(value) {
56
+ this.setAttribute('data', typeof value === 'string' ? value : JSON.stringify(value));
57
+ }
58
+ connectedCallback() {
59
+ this.render();
60
+ }
61
+ attributeChangedCallback(name) {
62
+ if (name === 'selected-rows') {
63
+ this.syncSelectedRowsFromAttribute();
64
+ }
65
+ if (name === 'sort-column' || name === 'sort-direction') {
66
+ this.syncSortFromAttributes();
67
+ }
68
+ if (name === 'page') {
69
+ this.internalPage = Number(this.getAttribute('page') || 1);
70
+ }
71
+ this.render();
72
+ }
73
+ syncSelectedRowsFromAttribute() {
74
+ try {
75
+ this.internalSelectedRows = JSON.parse(this.getAttribute('selected-rows') || '[]');
76
+ }
77
+ catch {
78
+ this.internalSelectedRows = [];
79
+ }
80
+ }
81
+ syncSortFromAttributes() {
82
+ const column = this.getAttribute('sort-column');
83
+ const direction = this.getAttribute('sort-direction');
84
+ this.internalSortColumn = column || undefined;
85
+ this.internalSortDirection = direction === 'asc' || direction === 'desc' ? direction : null;
86
+ }
87
+ getRowKey(item, index) {
88
+ const rowKey = this.getAttribute('row-key') || 'id';
89
+ const value = item[rowKey];
90
+ return value !== undefined && value !== null ? String(value) : String(index);
91
+ }
92
+ getSortedData() {
93
+ const data = this.data;
94
+ const columnKey = this.getAttribute('sort-column') || this.internalSortColumn;
95
+ const direction = this.getAttribute('sort-direction') || this.internalSortDirection;
96
+ if (!columnKey || !direction)
97
+ return data;
98
+ const column = this.columns.find((col) => col.key === columnKey);
99
+ if (!column?.sortable)
100
+ return data;
101
+ return [...data].sort((a, b) => {
102
+ const aValue = a[columnKey];
103
+ const bValue = b[columnKey];
104
+ if (aValue === bValue)
105
+ return 0;
106
+ if (aValue === undefined || aValue === null)
107
+ return 1;
108
+ if (bValue === undefined || bValue === null)
109
+ return -1;
110
+ if (aValue < bValue)
111
+ return direction === 'asc' ? -1 : 1;
112
+ return direction === 'asc' ? 1 : -1;
113
+ });
114
+ }
115
+ handleSort(column) {
116
+ if (!this.hasAttribute('sortable') || !column.sortable)
117
+ return;
118
+ let nextDirection = 'asc';
119
+ if (this.internalSortColumn === column.key) {
120
+ if (this.internalSortDirection === 'asc')
121
+ nextDirection = 'desc';
122
+ else if (this.internalSortDirection === 'desc')
123
+ nextDirection = null;
124
+ }
125
+ this.internalSortColumn = nextDirection ? column.key : undefined;
126
+ this.internalSortDirection = nextDirection;
127
+ this.dispatchEvent(new CustomEvent('db-sort-change', {
128
+ bubbles: true,
129
+ composed: true,
130
+ detail: { column: column.key, direction: nextDirection },
131
+ }));
132
+ this.render();
133
+ }
134
+ handleRowSelect(rowKey, checked, event) {
135
+ event?.stopPropagation();
136
+ const multiSelect = this.hasAttribute('multi-select');
137
+ let next;
138
+ if (multiSelect) {
139
+ next = checked
140
+ ? [...this.internalSelectedRows, rowKey]
141
+ : this.internalSelectedRows.filter((key) => key !== rowKey);
142
+ }
143
+ else {
144
+ next = checked ? [rowKey] : [];
145
+ }
146
+ this.internalSelectedRows = next;
147
+ this.dispatchEvent(new CustomEvent('db-selection-change', {
148
+ bubbles: true,
149
+ composed: true,
150
+ detail: { selectedRows: next },
151
+ }));
152
+ this.render();
153
+ }
154
+ handleSelectAll(checked) {
155
+ const next = checked ? this.data.map((item, index) => this.getRowKey(item, index)) : [];
156
+ this.internalSelectedRows = next;
157
+ this.dispatchEvent(new CustomEvent('db-selection-change', {
158
+ bubbles: true,
159
+ composed: true,
160
+ detail: { selectedRows: next },
161
+ }));
162
+ this.render();
163
+ }
164
+ getPaginatedData() {
165
+ const sorted = this.getSortedData();
166
+ if (!this.hasAttribute('pagination'))
167
+ return sorted;
168
+ const pageSize = Number(this.getAttribute('page-size') || 10);
169
+ const totalItems = Number(this.getAttribute('total-items') || sorted.length);
170
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
171
+ const page = Math.min(this.internalPage, totalPages);
172
+ const start = (page - 1) * pageSize;
173
+ return sorted.slice(start, start + pageSize);
174
+ }
175
+ createSortIcon(column) {
176
+ const icon = document.createElement('span');
177
+ icon.className = 'designbase-wc-table__sort-icon';
178
+ const isSorted = this.internalSortColumn === column.key && Boolean(this.internalSortDirection);
179
+ if (!isSorted) {
180
+ icon.classList.add('designbase-wc-table__sort-icon--idle');
181
+ const stack = document.createElement('span');
182
+ stack.className = 'designbase-wc-table__sort-icon-stack';
183
+ stack.append(createDbIcon('chevron-up', 10), createDbIcon('chevron-down', 10));
184
+ icon.append(stack);
185
+ return icon;
186
+ }
187
+ icon.classList.add(this.internalSortDirection === 'asc'
188
+ ? 'designbase-wc-table__sort-icon--asc'
189
+ : 'designbase-wc-table__sort-icon--desc');
190
+ icon.append(createDbIcon(this.internalSortDirection === 'asc' ? 'chevron-up' : 'chevron-down', 14));
191
+ return icon;
192
+ }
193
+ createCheckbox(options) {
194
+ const checkbox = document.createElement('db-checkbox');
195
+ checkbox.setAttribute('size', 's');
196
+ checkbox.setAttribute('has-label', 'false');
197
+ if (options.checked)
198
+ checkbox.setAttribute('checked', '');
199
+ if (options.indeterminate)
200
+ checkbox.setAttribute('indeterminate', '');
201
+ if (options.stopPropagation) {
202
+ checkbox.addEventListener('click', (event) => event.stopPropagation());
203
+ }
204
+ checkbox.addEventListener('db-change', (event) => {
205
+ const detail = event.detail;
206
+ options.onChange?.(detail.checked);
207
+ });
208
+ return checkbox;
209
+ }
210
+ render() {
211
+ const size = this.getAttribute('size') || 'm';
212
+ const variant = this.getAttribute('variant') || 'default';
213
+ const resolvedSize = SIZES.includes(size) ? size : 'm';
214
+ const resolvedVariant = VARIANTS.includes(variant) ? variant : 'default';
215
+ const columns = this.columns;
216
+ const paginatedData = this.getPaginatedData();
217
+ const sortedData = this.getSortedData();
218
+ const loading = this.hasAttribute('loading');
219
+ const selectable = this.hasAttribute('selectable');
220
+ const sortable = this.hasAttribute('sortable');
221
+ const emptyMessage = this.getAttribute('empty-message') || '데이터가 없습니다.';
222
+ this.className = [
223
+ 'designbase-wc-table',
224
+ `designbase-wc-table--${resolvedSize}`,
225
+ `designbase-wc-table--${resolvedVariant}`,
226
+ selectable && 'designbase-wc-table--selectable',
227
+ sortable && 'designbase-wc-table--sortable',
228
+ loading && 'designbase-wc-table--loading',
229
+ ]
230
+ .filter(Boolean)
231
+ .join(' ');
232
+ this.replaceChildren();
233
+ if (loading) {
234
+ const loadingWrap = document.createElement('div');
235
+ loadingWrap.className = 'designbase-wc-table__loading';
236
+ const spinner = document.createElement('div');
237
+ spinner.className = 'designbase-wc-table__loading-spinner';
238
+ const text = document.createElement('span');
239
+ text.textContent = '로딩 중...';
240
+ loadingWrap.append(spinner, text);
241
+ this.append(loadingWrap);
242
+ return;
243
+ }
244
+ const title = this.getAttribute('title');
245
+ const showCountBadge = this.hasAttribute('show-count-badge');
246
+ if (title || showCountBadge) {
247
+ const header = document.createElement('div');
248
+ header.className = 'designbase-wc-table__header';
249
+ const left = document.createElement('div');
250
+ left.className = 'designbase-wc-table__header-left';
251
+ if (title) {
252
+ const heading = document.createElement('h3');
253
+ heading.className = 'designbase-wc-table__title';
254
+ heading.textContent = title;
255
+ left.append(heading);
256
+ }
257
+ if (showCountBadge) {
258
+ const badge = document.createElement('db-badge');
259
+ badge.setAttribute('count', String(this.data.length));
260
+ badge.setAttribute('badge-style', 'number');
261
+ badge.setAttribute('variant', 'primary');
262
+ badge.setAttribute('size', 's');
263
+ left.append(badge);
264
+ }
265
+ header.append(left);
266
+ this.append(header);
267
+ }
268
+ const container = document.createElement('div');
269
+ container.className = 'designbase-wc-table__container';
270
+ const table = document.createElement('table');
271
+ table.className = 'designbase-wc-table__table';
272
+ const thead = document.createElement('thead');
273
+ thead.className = 'designbase-wc-table__thead';
274
+ const headRow = document.createElement('tr');
275
+ headRow.className = 'designbase-wc-table__tr';
276
+ const visibleKeys = paginatedData.map((item, index) => this.getRowKey(item, index));
277
+ const selectedVisible = visibleKeys.filter((key) => this.internalSelectedRows.includes(key));
278
+ const rowClickable = this.hasAttribute('clickable');
279
+ if (selectable) {
280
+ const th = document.createElement('th');
281
+ th.className = 'designbase-wc-table__th designbase-wc-table__th--checkbox';
282
+ const checkbox = this.createCheckbox({
283
+ checked: visibleKeys.length > 0 && selectedVisible.length === visibleKeys.length,
284
+ indeterminate: selectedVisible.length > 0 && selectedVisible.length < visibleKeys.length,
285
+ onChange: (checked) => this.handleSelectAll(checked),
286
+ });
287
+ th.append(checkbox);
288
+ headRow.append(th);
289
+ }
290
+ columns.forEach((column) => {
291
+ const th = document.createElement('th');
292
+ th.className = [
293
+ 'designbase-wc-table__th',
294
+ `designbase-wc-table__th--${column.align || 'left'}`,
295
+ sortable && column.sortable && 'designbase-wc-table__th--sortable',
296
+ this.internalSortColumn === column.key &&
297
+ this.internalSortDirection &&
298
+ 'designbase-wc-table__th--sorted',
299
+ ]
300
+ .filter(Boolean)
301
+ .join(' ');
302
+ if (column.width)
303
+ th.style.width = typeof column.width === 'number' ? `${column.width}px` : column.width;
304
+ const content = document.createElement('div');
305
+ content.className = 'designbase-wc-table__th-content';
306
+ const text = document.createElement('span');
307
+ text.className = 'designbase-wc-table__th-text';
308
+ text.textContent = column.header;
309
+ content.append(text);
310
+ if (sortable && column.sortable)
311
+ content.append(this.createSortIcon(column));
312
+ th.append(content);
313
+ if (sortable && column.sortable) {
314
+ th.addEventListener('click', () => this.handleSort(column));
315
+ }
316
+ headRow.append(th);
317
+ });
318
+ thead.append(headRow);
319
+ const tbody = document.createElement('tbody');
320
+ tbody.className = 'designbase-wc-table__tbody';
321
+ if (sortedData.length === 0) {
322
+ const row = document.createElement('tr');
323
+ row.className = 'designbase-wc-table__tr';
324
+ const cell = document.createElement('td');
325
+ cell.className = 'designbase-wc-table__td designbase-wc-table__td--empty';
326
+ cell.colSpan = Math.max(columns.length + (selectable ? 1 : 0), 1);
327
+ const empty = document.createElement('db-empty-state');
328
+ empty.setAttribute('title', '데이터가 없습니다');
329
+ empty.setAttribute('description', emptyMessage);
330
+ empty.setAttribute('variant', 'no-data');
331
+ empty.setAttribute('size', 'm');
332
+ cell.append(empty);
333
+ row.append(cell);
334
+ tbody.append(row);
335
+ }
336
+ else {
337
+ paginatedData.forEach((item, index) => {
338
+ const rowKey = this.getRowKey(item, index);
339
+ const isSelected = this.internalSelectedRows.includes(rowKey);
340
+ const row = document.createElement('tr');
341
+ row.className = [
342
+ 'designbase-wc-table__tr',
343
+ rowClickable && 'designbase-wc-table__tr--clickable',
344
+ isSelected && 'designbase-wc-table__tr--selected',
345
+ ]
346
+ .filter(Boolean)
347
+ .join(' ');
348
+ if (rowClickable) {
349
+ row.addEventListener('click', () => {
350
+ this.dispatchEvent(new CustomEvent('db-row-click', {
351
+ detail: { item, index },
352
+ bubbles: true,
353
+ composed: true,
354
+ }));
355
+ });
356
+ }
357
+ if (selectable) {
358
+ const cell = document.createElement('td');
359
+ cell.className = 'designbase-wc-table__td designbase-wc-table__td--checkbox';
360
+ const checkbox = this.createCheckbox({
361
+ checked: isSelected,
362
+ stopPropagation: true,
363
+ onChange: (checked) => this.handleRowSelect(rowKey, checked),
364
+ });
365
+ cell.append(checkbox);
366
+ row.append(cell);
367
+ }
368
+ columns.forEach((column) => {
369
+ const cell = document.createElement('td');
370
+ cell.className = [
371
+ 'designbase-wc-table__td',
372
+ `designbase-wc-table__td--${column.align || 'left'}`,
373
+ ].join(' ');
374
+ cell.textContent = String(item[column.key] ?? '');
375
+ row.append(cell);
376
+ });
377
+ tbody.append(row);
378
+ });
379
+ }
380
+ table.append(thead, tbody);
381
+ container.append(table);
382
+ this.append(container);
383
+ if (this.hasAttribute('pagination')) {
384
+ const pageSize = Number(this.getAttribute('page-size') || 10);
385
+ const totalItems = Number(this.getAttribute('total-items') || sortedData.length);
386
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
387
+ const footer = document.createElement('div');
388
+ footer.className = 'designbase-wc-table__footer';
389
+ const pagination = document.createElement('db-pagination');
390
+ pagination.setAttribute('current-page', String(this.internalPage));
391
+ pagination.setAttribute('total-pages', String(totalPages));
392
+ pagination.setAttribute('size', resolvedSize);
393
+ pagination.setAttribute('show-first-last', '');
394
+ pagination.addEventListener('db-change', (event) => {
395
+ const page = Number(event.detail?.page || 1);
396
+ this.internalPage = page;
397
+ this.dispatchEvent(new CustomEvent('db-page-change', {
398
+ bubbles: true,
399
+ composed: true,
400
+ detail: { page },
401
+ }));
402
+ this.render();
403
+ });
404
+ footer.append(pagination);
405
+ this.append(footer);
406
+ }
407
+ }
408
+ }
409
+ if (!customElements.get('db-table'))
410
+ customElements.define('db-table', DbTable);
411
+
412
+ export { DbTable };