@designbasekorea/ui-wc 0.5.5 → 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 (155) 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.esm.js +39373 -1
  153. package/package.json +1 -1
  154. package/dist/chunks/lottie-2637aa0f.js +0 -1
  155. package/dist/react/chunks/lottie-14e7addb.js +0 -1
@@ -1 +1,266 @@
1
- import{createDbIcon as e}from"./db-icons.js";const t=["s","m","l"],i=["default","outlined","filled"];class DbDropzone extends HTMLElement{constructor(){super(...arguments),this.internalDragOver=!1,this.handleFileInputChange=()=>{this.emitFiles(this.fileInput?.files??null),this.fileInput&&(this.fileInput.value="")},this.handleDragOver=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!0,this.syncClasses(),this.dispatchEvent(new CustomEvent("db-drag-over",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleDragLeave=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!1,this.syncClasses(),this.dispatchEvent(new CustomEvent("db-drag-leave",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleDrop=e=>{e.preventDefault(),e.stopPropagation(),this.isDisabled()||(this.internalDragOver=!1,this.syncClasses(),this.emitFiles(e.dataTransfer?.files??null),this.dispatchEvent(new CustomEvent("db-drop",{bubbles:!0,composed:!0,detail:{event:e}})))},this.handleClick=e=>{this.isDisabled()||e.target.closest(".designbase-wc-dropzone__button")||(this.fileInput?.click(),this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0,detail:{event:e}})))}}static get observedAttributes(){return["size","variant","show-icon","icon","image","title","description","button-text","show-button","accept","max-size","multiple","drag-over","disabled","readonly"]}connectedCallback(){this.ensureInput(),this.sync(),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop),this.addEventListener("click",this.handleClick)}disconnectedCallback(){this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this.removeEventListener("click",this.handleClick)}attributeChangedCallback(){this.isConnected&&this.sync()}ensureInput(){this.fileInput||(this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.style.display="none",this.fileInput.setAttribute("data-wc-internal",""),this.fileInput.addEventListener("change",this.handleFileInputChange),this.append(this.fileInput))}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}isDragOver(){return this.hasAttribute("drag-over")?"false"!==this.getAttribute("drag-over"):this.internalDragOver}validateFile(e){const t=this.getAttribute("accept");if(t){const i=t.split(",").map(e=>e.trim()),s=e.type,n=`.${e.name.split(".").pop()?.toLowerCase()}`;if(!i.some(e=>e.startsWith(".")?n===e.toLowerCase():s===e||s.startsWith(e.replace("*",""))))return!1}const i=Number(this.getAttribute("max-size")||0);return!(i>0&&e.size>i)}emitFiles(e){if(!e||0===e.length)return;const t=Array.from(e).filter(e=>this.validateFile(e));t.length&&this.dispatchEvent(new CustomEvent("db-file-select",{bubbles:!0,composed:!0,detail:{files:t}}))}getDescriptionText(){const e=this.getAttribute("description");if(e)return e;const t=this.getAttribute("accept");if(!t)return"모든 파일 형식 지원";let i=t.split(",").map(e=>{const t=e.trim();return t.startsWith(".")?t.toUpperCase():t.includes("*")?t.replace("*","").toUpperCase():t}).join(", ");const s=Number(this.getAttribute("max-size")||0);if(s>0){const e=1024,t=["Bytes","KB","MB","GB"],n=Math.floor(Math.log(s)/Math.log(e));i+=` (최대 ${`${parseFloat((s/e**n).toFixed(2))} ${t[n]}`})`}return i}collectChildren(){return Array.from(this.children).filter(e=>e!==this.fileInput&&!e.hasAttribute("data-wc-internal"))}syncClasses(){const e=this.getAttribute("size")||"m",s=this.getAttribute("variant")||"default",n=t.includes(e)?e:"m",a=i.includes(s)?s:"default";this.className=["designbase-wc-dropzone",`designbase-wc-dropzone--size-${n}`,`designbase-wc-dropzone--variant-${a}`,this.isDragOver()&&"designbase-wc-dropzone--drag-over",this.hasAttribute("disabled")&&"designbase-wc-dropzone--disabled",this.hasAttribute("readonly")&&"designbase-wc-dropzone--readonly"].filter(Boolean).join(" ")}sync(){this.ensureInput(),this.syncClasses();const i=this.getAttribute("accept"),s=this.hasAttribute("multiple");this.fileInput&&(i?this.fileInput.setAttribute("accept",i):this.fileInput.removeAttribute("accept"),this.fileInput.toggleAttribute("multiple",s),this.fileInput.disabled=this.isDisabled());const n=this.collectChildren(),a=this.querySelector(":scope > .designbase-wc-dropzone__content[data-wc-internal]");if(n.length)return void a?.remove();let r=a;r||(r=document.createElement("div"),r.className="designbase-wc-dropzone__content",r.setAttribute("data-wc-internal",""),this.append(r)),r.replaceChildren();const l=this.getAttribute("size")||"m",o=t.includes(l)?l:"m",d=this.getAttribute("image"),c="false"!==this.getAttribute("show-icon"),h=this.getAttribute("icon")||"gallery",p=this.getAttribute("title")||"파일을 드래그하여 업로드하거나 클릭하여 선택하세요",u=this.getDescriptionText(),b=this.hasAttribute("show-button"),g=this.getAttribute("button-text")||"파일 선택";if(d){const e=document.createElement("div");e.className="designbase-wc-dropzone__image";const t=document.createElement("img");t.src=d,t.alt="Upload illustration",e.append(t),r.append(e)}else if(c){const t=document.createElement("div");t.className="designbase-wc-dropzone__icon";const i="s"===o?32:"l"===o?56:48;t.append(e(h,i)),r.append(t)}if(p){const e=document.createElement("div");e.className="designbase-wc-dropzone__title",e.textContent=p,r.append(e)}if(u){const e=document.createElement("div");e.className="designbase-wc-dropzone__description",e.textContent=u,r.append(e)}if(b){const e=document.createElement("button");e.type="button",e.className="designbase-wc-dropzone__button",e.textContent=g,e.disabled=this.isDisabled(),e.addEventListener("click",e=>{e.stopPropagation(),this.isDisabled()||this.fileInput?.click()}),r.append(e)}}}customElements.get("db-dropzone")||customElements.define("db-dropzone",DbDropzone);export{DbDropzone};
1
+ import { createDbIcon } from './db-icons.js';
2
+
3
+ const SIZES = ['s', 'm', 'l'];
4
+ const VARIANTS = ['default', 'outlined', 'filled'];
5
+ class DbDropzone extends HTMLElement {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.internalDragOver = false;
9
+ this.handleFileInputChange = () => {
10
+ this.emitFiles(this.fileInput?.files ?? null);
11
+ if (this.fileInput)
12
+ this.fileInput.value = '';
13
+ };
14
+ this.handleDragOver = (event) => {
15
+ event.preventDefault();
16
+ event.stopPropagation();
17
+ if (this.isDisabled())
18
+ return;
19
+ this.internalDragOver = true;
20
+ this.syncClasses();
21
+ this.dispatchEvent(new CustomEvent('db-drag-over', { bubbles: true, composed: true, detail: { event } }));
22
+ };
23
+ this.handleDragLeave = (event) => {
24
+ event.preventDefault();
25
+ event.stopPropagation();
26
+ if (this.isDisabled())
27
+ return;
28
+ this.internalDragOver = false;
29
+ this.syncClasses();
30
+ this.dispatchEvent(new CustomEvent('db-drag-leave', { bubbles: true, composed: true, detail: { event } }));
31
+ };
32
+ this.handleDrop = (event) => {
33
+ event.preventDefault();
34
+ event.stopPropagation();
35
+ if (this.isDisabled())
36
+ return;
37
+ this.internalDragOver = false;
38
+ this.syncClasses();
39
+ this.emitFiles(event.dataTransfer?.files ?? null);
40
+ this.dispatchEvent(new CustomEvent('db-drop', { bubbles: true, composed: true, detail: { event } }));
41
+ };
42
+ this.handleClick = (event) => {
43
+ if (this.isDisabled())
44
+ return;
45
+ if (event.target.closest('.designbase-wc-dropzone__button'))
46
+ return;
47
+ this.fileInput?.click();
48
+ this.dispatchEvent(new CustomEvent('db-click', { bubbles: true, composed: true, detail: { event } }));
49
+ };
50
+ }
51
+ static get observedAttributes() {
52
+ return [
53
+ 'size',
54
+ 'variant',
55
+ 'show-icon',
56
+ 'icon',
57
+ 'image',
58
+ 'title',
59
+ 'description',
60
+ 'button-text',
61
+ 'show-button',
62
+ 'accept',
63
+ 'max-size',
64
+ 'multiple',
65
+ 'drag-over',
66
+ 'disabled',
67
+ 'readonly',
68
+ ];
69
+ }
70
+ connectedCallback() {
71
+ this.ensureInput();
72
+ this.sync();
73
+ this.addEventListener('dragover', this.handleDragOver);
74
+ this.addEventListener('dragleave', this.handleDragLeave);
75
+ this.addEventListener('drop', this.handleDrop);
76
+ this.addEventListener('click', this.handleClick);
77
+ }
78
+ disconnectedCallback() {
79
+ this.removeEventListener('dragover', this.handleDragOver);
80
+ this.removeEventListener('dragleave', this.handleDragLeave);
81
+ this.removeEventListener('drop', this.handleDrop);
82
+ this.removeEventListener('click', this.handleClick);
83
+ }
84
+ attributeChangedCallback() {
85
+ if (this.isConnected)
86
+ this.sync();
87
+ }
88
+ ensureInput() {
89
+ if (this.fileInput)
90
+ return;
91
+ this.fileInput = document.createElement('input');
92
+ this.fileInput.type = 'file';
93
+ this.fileInput.style.display = 'none';
94
+ this.fileInput.setAttribute('data-wc-internal', '');
95
+ this.fileInput.addEventListener('change', this.handleFileInputChange);
96
+ this.append(this.fileInput);
97
+ }
98
+ isDisabled() {
99
+ return this.hasAttribute('disabled') || this.hasAttribute('readonly');
100
+ }
101
+ isDragOver() {
102
+ if (this.hasAttribute('drag-over')) {
103
+ return this.getAttribute('drag-over') !== 'false';
104
+ }
105
+ return this.internalDragOver;
106
+ }
107
+ validateFile(file) {
108
+ const accept = this.getAttribute('accept');
109
+ if (accept) {
110
+ const acceptedTypes = accept.split(',').map((type) => type.trim());
111
+ const fileType = file.type;
112
+ const fileExtension = `.${file.name.split('.').pop()?.toLowerCase()}`;
113
+ const isValidType = acceptedTypes.some((type) => {
114
+ if (type.startsWith('.'))
115
+ return fileExtension === type.toLowerCase();
116
+ return fileType === type || fileType.startsWith(type.replace('*', ''));
117
+ });
118
+ if (!isValidType)
119
+ return false;
120
+ }
121
+ const maxSize = Number(this.getAttribute('max-size') || 0);
122
+ if (maxSize > 0 && file.size > maxSize)
123
+ return false;
124
+ return true;
125
+ }
126
+ emitFiles(files) {
127
+ if (!files || files.length === 0)
128
+ return;
129
+ const validFiles = Array.from(files).filter((file) => this.validateFile(file));
130
+ if (!validFiles.length)
131
+ return;
132
+ this.dispatchEvent(new CustomEvent('db-file-select', {
133
+ bubbles: true,
134
+ composed: true,
135
+ detail: { files: validFiles },
136
+ }));
137
+ }
138
+ getDescriptionText() {
139
+ const description = this.getAttribute('description');
140
+ if (description)
141
+ return description;
142
+ const accept = this.getAttribute('accept');
143
+ if (!accept)
144
+ return '모든 파일 형식 지원';
145
+ const types = accept.split(',').map((type) => {
146
+ const trimmed = type.trim();
147
+ if (trimmed.startsWith('.'))
148
+ return trimmed.toUpperCase();
149
+ if (trimmed.includes('*'))
150
+ return trimmed.replace('*', '').toUpperCase();
151
+ return trimmed;
152
+ });
153
+ let desc = types.join(', ');
154
+ const maxSize = Number(this.getAttribute('max-size') || 0);
155
+ if (maxSize > 0) {
156
+ const k = 1024;
157
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
158
+ const i = Math.floor(Math.log(maxSize) / Math.log(k));
159
+ const sizeText = `${parseFloat((maxSize / k ** i).toFixed(2))} ${sizes[i]}`;
160
+ desc += ` (최대 ${sizeText})`;
161
+ }
162
+ return desc;
163
+ }
164
+ collectChildren() {
165
+ return Array.from(this.children).filter((child) => child !== this.fileInput && !child.hasAttribute('data-wc-internal'));
166
+ }
167
+ syncClasses() {
168
+ const size = this.getAttribute('size') || 'm';
169
+ const variant = this.getAttribute('variant') || 'default';
170
+ const safeSize = SIZES.includes(size) ? size : 'm';
171
+ const safeVariant = VARIANTS.includes(variant) ? variant : 'default';
172
+ this.className = [
173
+ 'designbase-wc-dropzone',
174
+ `designbase-wc-dropzone--size-${safeSize}`,
175
+ `designbase-wc-dropzone--variant-${safeVariant}`,
176
+ this.isDragOver() && 'designbase-wc-dropzone--drag-over',
177
+ this.hasAttribute('disabled') && 'designbase-wc-dropzone--disabled',
178
+ this.hasAttribute('readonly') && 'designbase-wc-dropzone--readonly',
179
+ ]
180
+ .filter(Boolean)
181
+ .join(' ');
182
+ }
183
+ sync() {
184
+ this.ensureInput();
185
+ this.syncClasses();
186
+ const accept = this.getAttribute('accept');
187
+ const multiple = this.hasAttribute('multiple');
188
+ if (this.fileInput) {
189
+ if (accept)
190
+ this.fileInput.setAttribute('accept', accept);
191
+ else
192
+ this.fileInput.removeAttribute('accept');
193
+ this.fileInput.toggleAttribute('multiple', multiple);
194
+ this.fileInput.disabled = this.isDisabled();
195
+ }
196
+ const userChildren = this.collectChildren();
197
+ const defaultContent = this.querySelector(':scope > .designbase-wc-dropzone__content[data-wc-internal]');
198
+ if (userChildren.length) {
199
+ defaultContent?.remove();
200
+ return;
201
+ }
202
+ let content = defaultContent;
203
+ if (!content) {
204
+ content = document.createElement('div');
205
+ content.className = 'designbase-wc-dropzone__content';
206
+ content.setAttribute('data-wc-internal', '');
207
+ this.append(content);
208
+ }
209
+ content.replaceChildren();
210
+ const size = this.getAttribute('size') || 'm';
211
+ const safeSize = SIZES.includes(size) ? size : 'm';
212
+ const image = this.getAttribute('image');
213
+ const showIcon = this.getAttribute('show-icon') !== 'false';
214
+ const iconName = this.getAttribute('icon') || 'gallery';
215
+ const title = this.getAttribute('title') || '파일을 드래그하여 업로드하거나 클릭하여 선택하세요';
216
+ const description = this.getDescriptionText();
217
+ const showButton = this.hasAttribute('show-button');
218
+ const buttonText = this.getAttribute('button-text') || '파일 선택';
219
+ if (image) {
220
+ const imageWrap = document.createElement('div');
221
+ imageWrap.className = 'designbase-wc-dropzone__image';
222
+ const img = document.createElement('img');
223
+ img.src = image;
224
+ img.alt = 'Upload illustration';
225
+ imageWrap.append(img);
226
+ content.append(imageWrap);
227
+ }
228
+ else if (showIcon) {
229
+ const iconWrap = document.createElement('div');
230
+ iconWrap.className = 'designbase-wc-dropzone__icon';
231
+ const iconSize = safeSize === 's' ? 32 : safeSize === 'l' ? 56 : 48;
232
+ iconWrap.append(createDbIcon(iconName, iconSize));
233
+ content.append(iconWrap);
234
+ }
235
+ if (title) {
236
+ const titleEl = document.createElement('div');
237
+ titleEl.className = 'designbase-wc-dropzone__title';
238
+ titleEl.textContent = title;
239
+ content.append(titleEl);
240
+ }
241
+ if (description) {
242
+ const descriptionEl = document.createElement('div');
243
+ descriptionEl.className = 'designbase-wc-dropzone__description';
244
+ descriptionEl.textContent = description;
245
+ content.append(descriptionEl);
246
+ }
247
+ if (showButton) {
248
+ const button = document.createElement('button');
249
+ button.type = 'button';
250
+ button.className = 'designbase-wc-dropzone__button';
251
+ button.textContent = buttonText;
252
+ button.disabled = this.isDisabled();
253
+ button.addEventListener('click', (event) => {
254
+ event.stopPropagation();
255
+ if (!this.isDisabled())
256
+ this.fileInput?.click();
257
+ });
258
+ content.append(button);
259
+ }
260
+ }
261
+ }
262
+ if (!customElements.get('db-dropzone')) {
263
+ customElements.define('db-dropzone', DbDropzone);
264
+ }
265
+
266
+ export { DbDropzone };
@@ -1 +1,97 @@
1
- import{createDbIcon as t}from"./db-icons.js";class DbEmptyState extends HTMLElement{static get observedAttributes(){return["variant","size","title","description","action-text","secondary-action-text","image","image-alt"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}getIconName(t){return"no-results"===t?"search":"no-access"===t?"user":"error"===t?"cloud-close":"onboarding"===t?"bulb":"plus"}render(){const e=this.getAttribute("variant")||"no-data",s=this.getAttribute("size")||"m",a=this.getAttribute("title")||"",n=this.getAttribute("description")||"",i=this.getAttribute("action-text"),c=this.getAttribute("secondary-action-text"),d=this.getAttribute("image"),o=this.getAttribute("image-alt")||a,r="s"===s?24:"l"===s?48:32;this.className=`designbase-wc-empty-state designbase-wc-empty-state--${e} designbase-wc-empty-state--${s}`,this.setAttribute("role","status"),this.setAttribute("aria-live","polite"),this.replaceChildren();const m=document.createElement("div");if(m.className="designbase-wc-empty-state__content",d){const t=document.createElement("div");t.className="designbase-wc-empty-state__image";const e=document.createElement("img");e.className="designbase-wc-empty-state__image-element",e.src=d,e.alt=o,t.append(e),m.append(t)}else{const s=document.createElement("div");s.className="designbase-wc-empty-state__icon",s.append(t(this.getIconName(e),r)),m.append(s)}const b=document.createElement("h3");if(b.className="designbase-wc-empty-state__title",b.textContent=a,m.append(b),n){const t=document.createElement("p");t.className="designbase-wc-empty-state__description",t.textContent=n,m.append(t)}if(i||c){const t=document.createElement("div");if(t.className="designbase-wc-empty-state__actions",i){const a=document.createElement("db-button");a.setAttribute("variant","onboarding"===e?"primary":"secondary"),a.setAttribute("size",s),a.textContent=i,a.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-action",{bubbles:!0,composed:!0}))}),t.append(a)}if(c){const e=document.createElement("db-button");e.setAttribute("variant","tertiary"),e.setAttribute("size",s),e.textContent=c,e.addEventListener("db-click",()=>{this.dispatchEvent(new CustomEvent("db-secondary-action",{bubbles:!0,composed:!0}))}),t.append(e)}m.append(t)}this.append(m)}}customElements.get("db-empty-state")||customElements.define("db-empty-state",DbEmptyState);export{DbEmptyState};
1
+ import { createDbIcon } from './db-icons.js';
2
+
3
+ class DbEmptyState extends HTMLElement {
4
+ static get observedAttributes() {
5
+ return ['variant', 'size', 'title', 'description', 'action-text', 'secondary-action-text', 'image', 'image-alt'];
6
+ }
7
+ connectedCallback() {
8
+ this.render();
9
+ }
10
+ attributeChangedCallback() {
11
+ this.render();
12
+ }
13
+ getIconName(variant) {
14
+ if (variant === 'no-results')
15
+ return 'search';
16
+ if (variant === 'no-access')
17
+ return 'user';
18
+ if (variant === 'error')
19
+ return 'cloud-close';
20
+ if (variant === 'onboarding')
21
+ return 'bulb';
22
+ return 'plus';
23
+ }
24
+ render() {
25
+ const variant = this.getAttribute('variant') || 'no-data';
26
+ const size = this.getAttribute('size') || 'm';
27
+ const title = this.getAttribute('title') || '';
28
+ const description = this.getAttribute('description') || '';
29
+ const actionText = this.getAttribute('action-text');
30
+ const secondaryActionText = this.getAttribute('secondary-action-text');
31
+ const image = this.getAttribute('image');
32
+ const imageAlt = this.getAttribute('image-alt') || title;
33
+ const iconSize = size === 's' ? 24 : size === 'l' ? 48 : 32;
34
+ this.className = `designbase-wc-empty-state designbase-wc-empty-state--${variant} designbase-wc-empty-state--${size}`;
35
+ this.setAttribute('role', 'status');
36
+ this.setAttribute('aria-live', 'polite');
37
+ this.replaceChildren();
38
+ const content = document.createElement('div');
39
+ content.className = 'designbase-wc-empty-state__content';
40
+ if (image) {
41
+ const imageWrap = document.createElement('div');
42
+ imageWrap.className = 'designbase-wc-empty-state__image';
43
+ const imageElement = document.createElement('img');
44
+ imageElement.className = 'designbase-wc-empty-state__image-element';
45
+ imageElement.src = image;
46
+ imageElement.alt = imageAlt;
47
+ imageWrap.append(imageElement);
48
+ content.append(imageWrap);
49
+ }
50
+ else {
51
+ const icon = document.createElement('div');
52
+ icon.className = 'designbase-wc-empty-state__icon';
53
+ icon.append(createDbIcon(this.getIconName(variant), iconSize));
54
+ content.append(icon);
55
+ }
56
+ const heading = document.createElement('h3');
57
+ heading.className = 'designbase-wc-empty-state__title';
58
+ heading.textContent = title;
59
+ content.append(heading);
60
+ if (description) {
61
+ const body = document.createElement('p');
62
+ body.className = 'designbase-wc-empty-state__description';
63
+ body.textContent = description;
64
+ content.append(body);
65
+ }
66
+ if (actionText || secondaryActionText) {
67
+ const actions = document.createElement('div');
68
+ actions.className = 'designbase-wc-empty-state__actions';
69
+ if (actionText) {
70
+ const action = document.createElement('db-button');
71
+ action.setAttribute('variant', variant === 'onboarding' ? 'primary' : 'secondary');
72
+ action.setAttribute('size', size);
73
+ action.textContent = actionText;
74
+ action.addEventListener('db-click', () => {
75
+ this.dispatchEvent(new CustomEvent('db-action', { bubbles: true, composed: true }));
76
+ });
77
+ actions.append(action);
78
+ }
79
+ if (secondaryActionText) {
80
+ const action = document.createElement('db-button');
81
+ action.setAttribute('variant', 'tertiary');
82
+ action.setAttribute('size', size);
83
+ action.textContent = secondaryActionText;
84
+ action.addEventListener('db-click', () => {
85
+ this.dispatchEvent(new CustomEvent('db-secondary-action', { bubbles: true, composed: true }));
86
+ });
87
+ actions.append(action);
88
+ }
89
+ content.append(actions);
90
+ }
91
+ this.append(content);
92
+ }
93
+ }
94
+ if (!customElements.get('db-empty-state'))
95
+ customElements.define('db-empty-state', DbEmptyState);
96
+
97
+ export { DbEmptyState };
@@ -1 +1,256 @@
1
- import{createDbIcon as e}from"./db-icons.js";const t=["s","m","l"],s=["default","outlined","filled"];class DbFileUploader extends HTMLElement{constructor(){super(...arguments),this.uploadedFiles=[],this.uploadIntervals=new Map,this.handleFileSelect=e=>{if(this.isDisabled())return;const t=e.detail,s=t?.files??[];if(!s.length)return;const i=s.map(e=>({file:e,id:`${Date.now()}-${Math.random()}`,status:"pending",progress:0}));this.hasAttribute("multiple")?this.uploadedFiles=[...this.uploadedFiles,...i]:this.uploadedFiles=i,this.dispatchEvent(new CustomEvent("db-upload",{bubbles:!0,composed:!0,detail:{files:i}})),this.simulateUpload(i),this.renderFileList()},this.handleRemove=e=>{if(this.isDisabled())return;const t=this.uploadIntervals.get(e);t&&(clearInterval(t),this.uploadIntervals.delete(e)),this.uploadedFiles=this.uploadedFiles.filter(t=>t.id!==e),this.dispatchEvent(new CustomEvent("db-remove",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.renderFileList()},this.handleRetry=e=>{if(this.isDisabled())return;const t=this.uploadedFiles.find(t=>t.id===e);t&&(this.updateFile(e,{status:"pending",progress:0,error:void 0}),this.dispatchEvent(new CustomEvent("db-retry",{bubbles:!0,composed:!0,detail:{fileId:e}})),this.simulateUpload([t]),this.renderFileList())}}static get observedAttributes(){return["size","variant","accept","max-size","multiple","show-file-list","show-progress","disabled","readonly"]}connectedCallback(){this.ensureDropzone(),this.sync(),this.dropzone?.addEventListener("db-file-select",this.handleFileSelect)}disconnectedCallback(){this.dropzone?.removeEventListener("db-file-select",this.handleFileSelect),this.uploadIntervals.forEach(e=>clearInterval(e)),this.uploadIntervals.clear()}attributeChangedCallback(){this.isConnected&&this.sync()}isDisabled(){return this.hasAttribute("disabled")||this.hasAttribute("readonly")}ensureDropzone(){this.dropzone||(this.dropzone=document.createElement("db-dropzone"),this.dropzone.setAttribute("data-wc-internal",""),this.prepend(this.dropzone))}formatFileSize(e){if(0===e)return"0 Bytes";const t=Math.floor(Math.log(e)/Math.log(1024));return`${parseFloat((e/1024**t).toFixed(2))} ${["Bytes","KB","MB","GB"][t]}`}simulateUpload(e){e.forEach((e,t)=>{this.updateFile(e.id,{status:"uploading",progress:0});let s=0;const i=setInterval(()=>{if(s+=20*Math.random(),s>=100)return s=100,clearInterval(i),this.uploadIntervals.delete(e.id),this.updateFile(e.id,{status:"success",progress:100}),void this.renderFileList();this.updateFile(e.id,{progress:s}),this.renderFileList()},100+50*t);this.uploadIntervals.set(e.id,i)})}updateFile(e,t){this.uploadedFiles=this.uploadedFiles.map(s=>s.id===e?{...s,...t}:s)}sync(){if(this.ensureDropzone(),!this.dropzone)return;const e=this.getAttribute("size")||"m",i=this.getAttribute("variant")||"default",l=t.includes(e)?e:"m",a=s.includes(i)?i:"default";this.className=["designbase-wc-file-uploader",`designbase-wc-file-uploader--size-${l}`,`designbase-wc-file-uploader--variant-${a}`,this.hasAttribute("disabled")&&"designbase-wc-file-uploader--disabled",this.hasAttribute("readonly")&&"designbase-wc-file-uploader--readonly"].filter(Boolean).join(" "),this.dropzone.setAttribute("size",l),this.dropzone.setAttribute("variant",a),this.getAttribute("accept")?this.dropzone.setAttribute("accept",this.getAttribute("accept")):this.dropzone.removeAttribute("accept"),this.getAttribute("max-size")?this.dropzone.setAttribute("max-size",this.getAttribute("max-size")):this.dropzone.removeAttribute("max-size"),this.dropzone.toggleAttribute("multiple",this.hasAttribute("multiple")),this.dropzone.toggleAttribute("disabled",this.hasAttribute("disabled")),this.dropzone.toggleAttribute("readonly",this.hasAttribute("readonly")),this.renderFileList()}renderStatusIcon(t){if("uploading"===t){const e=document.createElement("db-spinner");return e.setAttribute("type","circular"),e.setAttribute("size","s"),e}return e("success"===t?"done":"error"===t?"error-filled":"gallery",20)}renderFileList(){const e=!this.hasAttribute("show-file-list")||"false"!==this.getAttribute("show-file-list"),t=!this.hasAttribute("show-progress")||"false"!==this.getAttribute("show-progress");if(this.querySelector(":scope > .designbase-wc-file-uploader__file-list")?.remove(),!e||!this.uploadedFiles.length)return;const s=document.createElement("div");s.className="designbase-wc-file-uploader__file-list";const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-list-title",i.textContent=`업로드된 파일들 (${this.uploadedFiles.length}개)`,s.append(i);const l=document.createElement("div");l.className="designbase-wc-file-uploader__file-items",this.uploadedFiles.forEach(e=>{const s=document.createElement("div");s.className=`designbase-wc-file-uploader__file-item designbase-wc-file-uploader__file-item--${e.status}`;const i=document.createElement("div");i.className="designbase-wc-file-uploader__file-info";const a=document.createElement("div");a.className="designbase-wc-file-uploader__file-icon",a.append(this.renderStatusIcon(e.status));const d=document.createElement("div");d.className="designbase-wc-file-uploader__file-details";const r=document.createElement("div");r.className="designbase-wc-file-uploader__file-name",r.textContent=e.file.name;const n=document.createElement("div");if(n.className="designbase-wc-file-uploader__file-size",n.textContent=this.formatFileSize(e.file.size),d.append(r,n),e.error){const t=document.createElement("div");t.className="designbase-wc-file-uploader__file-error",t.textContent=e.error,d.append(t)}if(i.append(a,d),s.append(i),t&&"uploading"===e.status){const t=document.createElement("div");t.className="designbase-wc-file-uploader__progress";const i=document.createElement("db-progressbar");i.setAttribute("value",String(Math.round(e.progress||0))),i.setAttribute("size","s"),i.setAttribute("variant","primary"),i.setAttribute("bar-style","solid"),i.setAttribute("show-label",""),i.setAttribute("label-position","inside"),i.setAttribute("full-width",""),t.append(i),s.append(t)}const o=document.createElement("div");if(o.className="designbase-wc-file-uploader__file-actions","error"===e.status){const t=document.createElement("button");t.type="button",t.className="designbase-wc-file-uploader__retry-button",t.textContent="재시도",t.disabled=this.isDisabled(),t.addEventListener("click",()=>this.handleRetry(e.id)),o.append(t)}const u=document.createElement("button");u.type="button",u.className="designbase-wc-file-uploader__remove-button",u.textContent="삭제",u.disabled=this.isDisabled(),u.addEventListener("click",()=>this.handleRemove(e.id)),o.append(u),s.append(o),l.append(s)}),s.append(l),this.append(s)}}customElements.get("db-file-uploader")||customElements.define("db-file-uploader",DbFileUploader);export{DbFileUploader};
1
+ import { createDbIcon } from './db-icons.js';
2
+
3
+ const SIZES = ['s', 'm', 'l'];
4
+ const VARIANTS = ['default', 'outlined', 'filled'];
5
+ class DbFileUploader extends HTMLElement {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.uploadedFiles = [];
9
+ this.uploadIntervals = new Map();
10
+ this.handleFileSelect = (event) => {
11
+ if (this.isDisabled())
12
+ return;
13
+ const detail = event.detail;
14
+ const files = detail?.files ?? [];
15
+ if (!files.length)
16
+ return;
17
+ const newUploadFiles = files.map((file) => ({
18
+ file,
19
+ id: `${Date.now()}-${Math.random()}`,
20
+ status: 'pending',
21
+ progress: 0,
22
+ }));
23
+ if (this.hasAttribute('multiple')) {
24
+ this.uploadedFiles = [...this.uploadedFiles, ...newUploadFiles];
25
+ }
26
+ else {
27
+ this.uploadedFiles = newUploadFiles;
28
+ }
29
+ this.dispatchEvent(new CustomEvent('db-upload', {
30
+ bubbles: true,
31
+ composed: true,
32
+ detail: { files: newUploadFiles },
33
+ }));
34
+ this.simulateUpload(newUploadFiles);
35
+ this.renderFileList();
36
+ };
37
+ this.handleRemove = (fileId) => {
38
+ if (this.isDisabled())
39
+ return;
40
+ const interval = this.uploadIntervals.get(fileId);
41
+ if (interval) {
42
+ clearInterval(interval);
43
+ this.uploadIntervals.delete(fileId);
44
+ }
45
+ this.uploadedFiles = this.uploadedFiles.filter((file) => file.id !== fileId);
46
+ this.dispatchEvent(new CustomEvent('db-remove', { bubbles: true, composed: true, detail: { fileId } }));
47
+ this.renderFileList();
48
+ };
49
+ this.handleRetry = (fileId) => {
50
+ if (this.isDisabled())
51
+ return;
52
+ const file = this.uploadedFiles.find((item) => item.id === fileId);
53
+ if (!file)
54
+ return;
55
+ this.updateFile(fileId, { status: 'pending', progress: 0, error: undefined });
56
+ this.dispatchEvent(new CustomEvent('db-retry', { bubbles: true, composed: true, detail: { fileId } }));
57
+ this.simulateUpload([file]);
58
+ this.renderFileList();
59
+ };
60
+ }
61
+ static get observedAttributes() {
62
+ return [
63
+ 'size',
64
+ 'variant',
65
+ 'accept',
66
+ 'max-size',
67
+ 'multiple',
68
+ 'show-file-list',
69
+ 'show-progress',
70
+ 'disabled',
71
+ 'readonly',
72
+ ];
73
+ }
74
+ connectedCallback() {
75
+ this.ensureDropzone();
76
+ this.sync();
77
+ this.dropzone?.addEventListener('db-file-select', this.handleFileSelect);
78
+ }
79
+ disconnectedCallback() {
80
+ this.dropzone?.removeEventListener('db-file-select', this.handleFileSelect);
81
+ this.uploadIntervals.forEach((interval) => clearInterval(interval));
82
+ this.uploadIntervals.clear();
83
+ }
84
+ attributeChangedCallback() {
85
+ if (this.isConnected)
86
+ this.sync();
87
+ }
88
+ isDisabled() {
89
+ return this.hasAttribute('disabled') || this.hasAttribute('readonly');
90
+ }
91
+ ensureDropzone() {
92
+ if (this.dropzone)
93
+ return;
94
+ this.dropzone = document.createElement('db-dropzone');
95
+ this.dropzone.setAttribute('data-wc-internal', '');
96
+ this.prepend(this.dropzone);
97
+ }
98
+ formatFileSize(bytes) {
99
+ if (bytes === 0)
100
+ return '0 Bytes';
101
+ const k = 1024;
102
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
103
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
104
+ return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
105
+ }
106
+ simulateUpload(files) {
107
+ files.forEach((uploadFile, index) => {
108
+ this.updateFile(uploadFile.id, { status: 'uploading', progress: 0 });
109
+ let progress = 0;
110
+ const interval = setInterval(() => {
111
+ progress += Math.random() * 20;
112
+ if (progress >= 100) {
113
+ progress = 100;
114
+ clearInterval(interval);
115
+ this.uploadIntervals.delete(uploadFile.id);
116
+ this.updateFile(uploadFile.id, { status: 'success', progress: 100 });
117
+ this.renderFileList();
118
+ return;
119
+ }
120
+ this.updateFile(uploadFile.id, { progress });
121
+ this.renderFileList();
122
+ }, 100 + index * 50);
123
+ this.uploadIntervals.set(uploadFile.id, interval);
124
+ });
125
+ }
126
+ updateFile(id, patch) {
127
+ this.uploadedFiles = this.uploadedFiles.map((file) => (file.id === id ? { ...file, ...patch } : file));
128
+ }
129
+ sync() {
130
+ this.ensureDropzone();
131
+ if (!this.dropzone)
132
+ return;
133
+ const size = this.getAttribute('size') || 'm';
134
+ const variant = this.getAttribute('variant') || 'default';
135
+ const safeSize = SIZES.includes(size) ? size : 'm';
136
+ const safeVariant = VARIANTS.includes(variant) ? variant : 'default';
137
+ this.className = [
138
+ 'designbase-wc-file-uploader',
139
+ `designbase-wc-file-uploader--size-${safeSize}`,
140
+ `designbase-wc-file-uploader--variant-${safeVariant}`,
141
+ this.hasAttribute('disabled') && 'designbase-wc-file-uploader--disabled',
142
+ this.hasAttribute('readonly') && 'designbase-wc-file-uploader--readonly',
143
+ ]
144
+ .filter(Boolean)
145
+ .join(' ');
146
+ this.dropzone.setAttribute('size', safeSize);
147
+ this.dropzone.setAttribute('variant', safeVariant);
148
+ if (this.getAttribute('accept'))
149
+ this.dropzone.setAttribute('accept', this.getAttribute('accept'));
150
+ else
151
+ this.dropzone.removeAttribute('accept');
152
+ if (this.getAttribute('max-size'))
153
+ this.dropzone.setAttribute('max-size', this.getAttribute('max-size'));
154
+ else
155
+ this.dropzone.removeAttribute('max-size');
156
+ this.dropzone.toggleAttribute('multiple', this.hasAttribute('multiple'));
157
+ this.dropzone.toggleAttribute('disabled', this.hasAttribute('disabled'));
158
+ this.dropzone.toggleAttribute('readonly', this.hasAttribute('readonly'));
159
+ this.renderFileList();
160
+ }
161
+ renderStatusIcon(status) {
162
+ if (status === 'uploading') {
163
+ const spinner = document.createElement('db-spinner');
164
+ spinner.setAttribute('type', 'circular');
165
+ spinner.setAttribute('size', 's');
166
+ return spinner;
167
+ }
168
+ if (status === 'success')
169
+ return createDbIcon('done', 20);
170
+ if (status === 'error')
171
+ return createDbIcon('error-filled', 20);
172
+ return createDbIcon('gallery', 20);
173
+ }
174
+ renderFileList() {
175
+ const showFileList = !this.hasAttribute('show-file-list') || this.getAttribute('show-file-list') !== 'false';
176
+ const showProgress = !this.hasAttribute('show-progress') || this.getAttribute('show-progress') !== 'false';
177
+ this.querySelector(':scope > .designbase-wc-file-uploader__file-list')?.remove();
178
+ if (!showFileList || !this.uploadedFiles.length)
179
+ return;
180
+ const list = document.createElement('div');
181
+ list.className = 'designbase-wc-file-uploader__file-list';
182
+ const title = document.createElement('div');
183
+ title.className = 'designbase-wc-file-uploader__file-list-title';
184
+ title.textContent = `업로드된 파일들 (${this.uploadedFiles.length}개)`;
185
+ list.append(title);
186
+ const items = document.createElement('div');
187
+ items.className = 'designbase-wc-file-uploader__file-items';
188
+ this.uploadedFiles.forEach((uploadFile) => {
189
+ const item = document.createElement('div');
190
+ item.className = `designbase-wc-file-uploader__file-item designbase-wc-file-uploader__file-item--${uploadFile.status}`;
191
+ const info = document.createElement('div');
192
+ info.className = 'designbase-wc-file-uploader__file-info';
193
+ const iconWrap = document.createElement('div');
194
+ iconWrap.className = 'designbase-wc-file-uploader__file-icon';
195
+ iconWrap.append(this.renderStatusIcon(uploadFile.status));
196
+ const details = document.createElement('div');
197
+ details.className = 'designbase-wc-file-uploader__file-details';
198
+ const name = document.createElement('div');
199
+ name.className = 'designbase-wc-file-uploader__file-name';
200
+ name.textContent = uploadFile.file.name;
201
+ const size = document.createElement('div');
202
+ size.className = 'designbase-wc-file-uploader__file-size';
203
+ size.textContent = this.formatFileSize(uploadFile.file.size);
204
+ details.append(name, size);
205
+ if (uploadFile.error) {
206
+ const error = document.createElement('div');
207
+ error.className = 'designbase-wc-file-uploader__file-error';
208
+ error.textContent = uploadFile.error;
209
+ details.append(error);
210
+ }
211
+ info.append(iconWrap, details);
212
+ item.append(info);
213
+ if (showProgress && uploadFile.status === 'uploading') {
214
+ const progress = document.createElement('div');
215
+ progress.className = 'designbase-wc-file-uploader__progress';
216
+ const bar = document.createElement('db-progressbar');
217
+ bar.setAttribute('value', String(Math.round(uploadFile.progress || 0)));
218
+ bar.setAttribute('size', 's');
219
+ bar.setAttribute('variant', 'primary');
220
+ bar.setAttribute('bar-style', 'solid');
221
+ bar.setAttribute('show-label', '');
222
+ bar.setAttribute('label-position', 'inside');
223
+ bar.setAttribute('full-width', '');
224
+ progress.append(bar);
225
+ item.append(progress);
226
+ }
227
+ const actions = document.createElement('div');
228
+ actions.className = 'designbase-wc-file-uploader__file-actions';
229
+ if (uploadFile.status === 'error') {
230
+ const retry = document.createElement('button');
231
+ retry.type = 'button';
232
+ retry.className = 'designbase-wc-file-uploader__retry-button';
233
+ retry.textContent = '재시도';
234
+ retry.disabled = this.isDisabled();
235
+ retry.addEventListener('click', () => this.handleRetry(uploadFile.id));
236
+ actions.append(retry);
237
+ }
238
+ const remove = document.createElement('button');
239
+ remove.type = 'button';
240
+ remove.className = 'designbase-wc-file-uploader__remove-button';
241
+ remove.textContent = '삭제';
242
+ remove.disabled = this.isDisabled();
243
+ remove.addEventListener('click', () => this.handleRemove(uploadFile.id));
244
+ actions.append(remove);
245
+ item.append(actions);
246
+ items.append(item);
247
+ });
248
+ list.append(items);
249
+ this.append(list);
250
+ }
251
+ }
252
+ if (!customElements.get('db-file-uploader')) {
253
+ customElements.define('db-file-uploader', DbFileUploader);
254
+ }
255
+
256
+ export { DbFileUploader };