@designbasekorea/ui-wc 0.5.6 → 0.6.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 (202) hide show
  1. package/dist/chunks/lottie-0e23d630.js +1 -0
  2. package/dist/esm/components/animation-background/canvas-controller.js +1 -121
  3. package/dist/esm/components/animation-background/controls.js +1 -180
  4. package/dist/esm/components/animation-background/graphite-controller.js +1 -196
  5. package/dist/esm/components/animation-background/graphite-presets.js +1 -42
  6. package/dist/esm/components/animation-background/graphite-shader.js +1 -111
  7. package/dist/esm/components/animation-background/layers.js +1 -369
  8. package/dist/esm/components/animation-background/lumina-presets.js +1 -53
  9. package/dist/esm/components/animation-background/lumina-shaders.js +1 -181
  10. package/dist/esm/components/animation-background/lumina-utils.js +1 -60
  11. package/dist/esm/components/animation-background/particle-defaults.js +1 -36
  12. package/dist/esm/components/animation-background/renderers.js +1 -167
  13. package/dist/esm/components/animation-background/shader-controller.js +1 -154
  14. package/dist/esm/components/color-picker-utils.js +1 -134
  15. package/dist/esm/components/date-picker-utils.js +1 -140
  16. package/dist/esm/components/db-accordion.js +1 -304
  17. package/dist/esm/components/db-ad-banner.js +1 -455
  18. package/dist/esm/components/db-ai-chat-list.d.ts +43 -0
  19. package/dist/esm/components/db-ai-chat-list.js +1 -0
  20. package/dist/esm/components/db-ai-chat.d.ts +159 -0
  21. package/dist/esm/components/db-ai-chat.js +1 -0
  22. package/dist/esm/components/db-alert.js +1 -149
  23. package/dist/esm/components/db-animation-background.js +1 -486
  24. package/dist/esm/components/db-animation-text.js +1 -601
  25. package/dist/esm/components/db-app-badge.js +1 -88
  26. package/dist/esm/components/db-audio-player.js +1 -752
  27. package/dist/esm/components/db-avatar.js +1 -188
  28. package/dist/esm/components/db-backdrop.js +1 -139
  29. package/dist/esm/components/db-badge.js +1 -91
  30. package/dist/esm/components/db-banner.js +1 -188
  31. package/dist/esm/components/db-bottom-navigation.js +1 -146
  32. package/dist/esm/components/db-bottom-sheet.js +1 -481
  33. package/dist/esm/components/db-breadcrumbs.js +1 -329
  34. package/dist/esm/components/db-button.js +1 -316
  35. package/dist/esm/components/db-calendar.js +1 -675
  36. package/dist/esm/components/db-card.js +1 -265
  37. package/dist/esm/components/db-carousel.js +1 -264
  38. package/dist/esm/components/db-chat-composer.d.ts +134 -0
  39. package/dist/esm/components/db-chat-composer.js +1 -0
  40. package/dist/esm/components/db-chat-list.d.ts +47 -0
  41. package/dist/esm/components/db-chat-list.js +1 -0
  42. package/dist/esm/components/db-chat-message.d.ts +39 -0
  43. package/dist/esm/components/db-chat-message.js +1 -0
  44. package/dist/esm/components/db-chat-orb.d.ts +99 -0
  45. package/dist/esm/components/db-chat-orb.js +1 -0
  46. package/dist/esm/components/db-chat-room.d.ts +71 -0
  47. package/dist/esm/components/db-chat-room.js +1 -0
  48. package/dist/esm/components/db-chat-suggestions.d.ts +44 -0
  49. package/dist/esm/components/db-chat-suggestions.js +1 -0
  50. package/dist/esm/components/db-chat-typing.d.ts +22 -0
  51. package/dist/esm/components/db-chat-typing.js +1 -0
  52. package/dist/esm/components/db-chat-welcome.d.ts +32 -0
  53. package/dist/esm/components/db-chat-welcome.js +1 -0
  54. package/dist/esm/components/db-chat-widget.d.ts +146 -0
  55. package/dist/esm/components/db-chat-widget.js +1 -0
  56. package/dist/esm/components/db-checkbox.js +1 -202
  57. package/dist/esm/components/db-chip.js +1 -104
  58. package/dist/esm/components/db-code-block.js +1 -304
  59. package/dist/esm/components/db-color-picker.js +1 -746
  60. package/dist/esm/components/db-confirm.js +1 -191
  61. package/dist/esm/components/db-container.js +1 -39
  62. package/dist/esm/components/db-context-menu.js +1 -265
  63. package/dist/esm/components/db-countdown.js +1 -146
  64. package/dist/esm/components/db-cursor-follower.js +1 -173
  65. package/dist/esm/components/db-date-picker.js +1 -837
  66. package/dist/esm/components/db-divider.js +1 -66
  67. package/dist/esm/components/db-download-progress.d.ts +89 -0
  68. package/dist/esm/components/db-download-progress.js +1 -0
  69. package/dist/esm/components/db-drawer.js +1 -245
  70. package/dist/esm/components/db-dropdown.js +1 -493
  71. package/dist/esm/components/db-dropzone.js +1 -266
  72. package/dist/esm/components/db-email-verify.d.ts +62 -0
  73. package/dist/esm/components/db-email-verify.js +1 -0
  74. package/dist/esm/components/db-empty-state.js +1 -97
  75. package/dist/esm/components/db-file-uploader.js +1 -256
  76. package/dist/esm/components/db-floating-action-button.js +1 -139
  77. package/dist/esm/components/db-footer.js +1 -385
  78. package/dist/esm/components/db-form.js +1 -566
  79. package/dist/esm/components/db-gantt.js +1 -882
  80. package/dist/esm/components/db-gradient.js +1 -133
  81. package/dist/esm/components/db-grid-background.js +1 -909
  82. package/dist/esm/components/db-grid.js +1 -73
  83. package/dist/esm/components/db-icons.d.ts +3 -0
  84. package/dist/esm/components/db-icons.js +1 -82
  85. package/dist/esm/components/db-image-list.js +1 -214
  86. package/dist/esm/components/db-image-placeholder.js +1 -96
  87. package/dist/esm/components/db-image.js +1 -289
  88. package/dist/esm/components/db-indicator.js +1 -517
  89. package/dist/esm/components/db-input.js +1 -420
  90. package/dist/esm/components/db-kanban.js +1 -538
  91. package/dist/esm/components/db-label.js +1 -66
  92. package/dist/esm/components/db-lightbox.js +1 -372
  93. package/dist/esm/components/db-list.js +1 -340
  94. package/dist/esm/components/db-logo-svg.js +1 -72
  95. package/dist/esm/components/db-logo.js +1 -106
  96. package/dist/esm/components/db-lottie.js +1 -109
  97. package/dist/esm/components/db-markdown-editor.js +1 -458
  98. package/dist/esm/components/db-marquee.js +1 -402
  99. package/dist/esm/components/db-masonry.js +1 -94
  100. package/dist/esm/components/db-menu-item.js +1 -211
  101. package/dist/esm/components/db-modal.js +1 -522
  102. package/dist/esm/components/db-navbar.js +1 -680
  103. package/dist/esm/components/db-onboarding-modal.js +1 -322
  104. package/dist/esm/components/db-otp-input.d.ts +53 -0
  105. package/dist/esm/components/db-otp-input.js +1 -0
  106. package/dist/esm/components/db-page-header.js +1 -312
  107. package/dist/esm/components/db-pagination.js +1 -271
  108. package/dist/esm/components/db-phone-verify.d.ts +61 -0
  109. package/dist/esm/components/db-phone-verify.js +1 -0
  110. package/dist/esm/components/db-popover.js +1 -580
  111. package/dist/esm/components/db-progress-step.js +1 -166
  112. package/dist/esm/components/db-progress.js +1 -171
  113. package/dist/esm/components/db-progressbar.js +1 -72
  114. package/dist/esm/components/db-radio.js +1 -172
  115. package/dist/esm/components/db-random-gradient.js +1 -121
  116. package/dist/esm/components/db-range-slider.js +1 -811
  117. package/dist/esm/components/db-rating.js +1 -325
  118. package/dist/esm/components/db-reorder.js +1 -286
  119. package/dist/esm/components/db-resizable-panels.js +1 -282
  120. package/dist/esm/components/db-scroll-area.js +1 -126
  121. package/dist/esm/components/db-search-bar.js +1 -668
  122. package/dist/esm/components/db-section-app-download.js +1 -101
  123. package/dist/esm/components/db-section-contact.js +1 -102
  124. package/dist/esm/components/db-section-cta.js +1 -150
  125. package/dist/esm/components/db-section-faq.js +1 -120
  126. package/dist/esm/components/db-section-feature-grid.js +1 -137
  127. package/dist/esm/components/db-section-feature.js +1 -179
  128. package/dist/esm/components/db-section-hero.js +1 -243
  129. package/dist/esm/components/db-section-logo-cloud.js +1 -138
  130. package/dist/esm/components/db-section-pricing.js +1 -166
  131. package/dist/esm/components/db-section-stats.js +1 -129
  132. package/dist/esm/components/db-section-testimonials.js +1 -252
  133. package/dist/esm/components/db-section.js +1 -385
  134. package/dist/esm/components/db-segment-control.js +1 -231
  135. package/dist/esm/components/db-select.js +1 -571
  136. package/dist/esm/components/db-share-icons.js +1 -40
  137. package/dist/esm/components/db-share.js +1 -489
  138. package/dist/esm/components/db-sidebar.js +1 -1068
  139. package/dist/esm/components/db-skeleton.js +1 -94
  140. package/dist/esm/components/db-spinner.js +1 -102
  141. package/dist/esm/components/db-split-view.js +1 -297
  142. package/dist/esm/components/db-stack.js +1 -46
  143. package/dist/esm/components/db-stat.js +1 -218
  144. package/dist/esm/components/db-stepper.js +1 -398
  145. package/dist/esm/components/db-table.js +1 -412
  146. package/dist/esm/components/db-tabs.js +1 -335
  147. package/dist/esm/components/db-testimonial.d.ts +2 -0
  148. package/dist/esm/components/db-testimonial.js +1 -162
  149. package/dist/esm/components/db-textarea.js +1 -233
  150. package/dist/esm/components/db-time-picker.js +1 -523
  151. package/dist/esm/components/db-timeline.js +1 -174
  152. package/dist/esm/components/db-toast.js +1 -158
  153. package/dist/esm/components/db-toggle.js +1 -162
  154. package/dist/esm/components/db-toolbar.js +1 -94
  155. package/dist/esm/components/db-tooltip.js +1 -440
  156. package/dist/esm/components/db-top-banner.js +1 -121
  157. package/dist/esm/components/db-tutorial.js +1 -324
  158. package/dist/esm/components/db-two-factor.d.ts +60 -0
  159. package/dist/esm/components/db-two-factor.js +1 -0
  160. package/dist/esm/components/db-video-player.js +1 -503
  161. package/dist/esm/components/db-youtube-player.js +1 -194
  162. package/dist/esm/components/highlight-code.js +1 -65
  163. package/dist/esm/components/input-validation.js +1 -50
  164. package/dist/esm/components/marketing-block-host-utils.js +1 -9
  165. package/dist/esm/components/number-scrub.js +1 -117
  166. package/dist/esm/components/random-gradient-palettes.js +1 -67
  167. package/dist/esm/components/section-block-header-utils.js +1 -48
  168. package/dist/esm/helpers/confirm.js +1 -52
  169. package/dist/esm/helpers/toast.js +1 -73
  170. package/dist/esm/index.d.ts +16 -0
  171. package/dist/esm/index.js +1 -111
  172. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-bash.js +1 -0
  173. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-clike.js +1 -0
  174. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-css.js +1 -0
  175. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-javascript.js +1 -0
  176. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-json.js +1 -0
  177. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-jsx.js +1 -0
  178. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-markup.js +1 -0
  179. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-scss.js +1 -0
  180. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-tsx.js +1 -0
  181. package/dist/esm/node_modules/.pnpm/prismjs@1.30.0/node_modules/prismjs/components/prism-typescript.js +1 -0
  182. package/dist/index.cjs +1 -55414
  183. package/dist/index.css +1 -1
  184. package/dist/index.d.ts +1091 -2
  185. package/dist/index.esm.js +1 -38284
  186. package/dist/react/chunks/lottie-14e7addb.js +1 -0
  187. package/dist/react/index.cjs +1 -56503
  188. package/dist/react/index.d.ts +1620 -54
  189. package/dist/react/index.esm.js +1 -39373
  190. package/package.json +1 -1
  191. package/dist/chunks/lottie-e273b936.js +0 -17032
  192. package/dist/esm/node_modules/prismjs/components/prism-bash.js +0 -235
  193. package/dist/esm/node_modules/prismjs/components/prism-clike.js +0 -31
  194. package/dist/esm/node_modules/prismjs/components/prism-css.js +0 -64
  195. package/dist/esm/node_modules/prismjs/components/prism-javascript.js +0 -172
  196. package/dist/esm/node_modules/prismjs/components/prism-json.js +0 -27
  197. package/dist/esm/node_modules/prismjs/components/prism-jsx.js +0 -143
  198. package/dist/esm/node_modules/prismjs/components/prism-markup.js +0 -186
  199. package/dist/esm/node_modules/prismjs/components/prism-scss.js +0 -81
  200. package/dist/esm/node_modules/prismjs/components/prism-tsx.js +0 -15
  201. package/dist/esm/node_modules/prismjs/components/prism-typescript.js +0 -60
  202. package/dist/react/chunks/lottie-72a4c6d4.js +0 -17032
@@ -1,566 +1 @@
1
- import './db-input.js';
2
- import './db-textarea.js';
3
- import './db-select.js';
4
- import './db-checkbox.js';
5
- import './db-radio.js';
6
- import './db-button.js';
7
-
8
- /**
9
- * Form Web Component
10
- * packages/ui Form.tsx 기준 — ui-wc 폼 필드(db-input, db-select 등) 조합
11
- */
12
- const CLASS = 'designbase-wc-form';
13
- class DbForm extends HTMLElement {
14
- constructor() {
15
- super(...arguments);
16
- this.built = false;
17
- this.formEl = null;
18
- this.headerEl = null;
19
- this.fieldsEl = null;
20
- this.actionsEl = null;
21
- this.submitBtn = null;
22
- this.resetBtn = null;
23
- this.values = {};
24
- this.errors = {};
25
- this.touched = {};
26
- this.initialValues = {};
27
- this.fieldWrappers = new Map();
28
- this.boundSubmit = (e) => this.handleSubmit(e);
29
- this.boundReset = (e) => this.handleReset(e);
30
- }
31
- static get observedAttributes() {
32
- return [
33
- 'fields',
34
- 'columns',
35
- 'size',
36
- 'variant',
37
- 'title',
38
- 'description',
39
- 'submit-text',
40
- 'reset-text',
41
- 'show-reset',
42
- 'submit-loading',
43
- 'submit-disabled',
44
- 'initial-values',
45
- ];
46
- }
47
- connectedCallback() {
48
- if (!this.built) {
49
- this.buildShell();
50
- this.built = true;
51
- }
52
- this.bootstrapValues();
53
- this.syncAll();
54
- }
55
- attributeChangedCallback(name) {
56
- if (!this.built)
57
- return;
58
- if (name === 'initial-values') {
59
- this.bootstrapValues();
60
- }
61
- if (name === 'fields') {
62
- this.bootstrapValues();
63
- }
64
- this.syncAll();
65
- }
66
- get fields() {
67
- return this.parseFields(this.getAttribute('fields'));
68
- }
69
- set fields(value) {
70
- this.setAttribute('fields', typeof value === 'string' ? value : JSON.stringify(value));
71
- }
72
- parseFields(raw) {
73
- if (!raw)
74
- return [];
75
- try {
76
- const parsed = JSON.parse(raw);
77
- return Array.isArray(parsed) ? parsed : [];
78
- }
79
- catch {
80
- return [];
81
- }
82
- }
83
- parseInitialValues() {
84
- const raw = this.getAttribute('initial-values');
85
- if (!raw)
86
- return {};
87
- try {
88
- const parsed = JSON.parse(raw);
89
- return parsed && typeof parsed === 'object' ? parsed : {};
90
- }
91
- catch {
92
- return {};
93
- }
94
- }
95
- bootstrapValues() {
96
- this.initialValues = this.parseInitialValues();
97
- const next = { ...this.initialValues };
98
- this.fields.forEach((field) => {
99
- if (next[field.name] !== undefined)
100
- return;
101
- if (field.value !== undefined) {
102
- next[field.name] = field.value;
103
- return;
104
- }
105
- if (field.defaultValue !== undefined) {
106
- next[field.name] = field.defaultValue;
107
- return;
108
- }
109
- if (field.type === 'checkbox' && field.checkboxGroup) {
110
- next[field.name] = [];
111
- return;
112
- }
113
- if (field.type === 'checkbox') {
114
- next[field.name] = false;
115
- return;
116
- }
117
- next[field.name] = '';
118
- });
119
- this.values = next;
120
- }
121
- buildShell() {
122
- this.formEl = document.createElement('form');
123
- this.formEl.className = `${CLASS}__native`;
124
- this.formEl.noValidate = true;
125
- this.formEl.addEventListener('submit', this.boundSubmit);
126
- this.headerEl = document.createElement('div');
127
- this.headerEl.className = `${CLASS}__header`;
128
- this.fieldsEl = document.createElement('div');
129
- this.fieldsEl.className = `${CLASS}__fields`;
130
- this.actionsEl = document.createElement('div');
131
- this.actionsEl.className = `${CLASS}__actions`;
132
- this.submitBtn = document.createElement('db-button');
133
- this.submitBtn.setAttribute('type', 'submit');
134
- this.submitBtn.setAttribute('variant', 'primary');
135
- this.resetBtn = document.createElement('db-button');
136
- this.resetBtn.setAttribute('type', 'button');
137
- this.resetBtn.setAttribute('variant', 'secondary');
138
- this.resetBtn.addEventListener('click', this.boundReset);
139
- this.actionsEl.append(this.submitBtn, this.resetBtn);
140
- this.formEl.append(this.fieldsEl, this.actionsEl);
141
- this.append(this.headerEl, this.formEl);
142
- }
143
- syncAll() {
144
- this.syncClasses();
145
- this.syncHeader();
146
- this.renderFields();
147
- this.syncActions();
148
- }
149
- syncClasses() {
150
- const columns = this.getAttribute('columns') || '1';
151
- const size = this.getAttribute('size') || 'm';
152
- const variant = this.getAttribute('variant') || 'default';
153
- this.className = [
154
- CLASS,
155
- `${CLASS}--columns-${columns}`,
156
- `${CLASS}--${size}`,
157
- `${CLASS}--${variant}`,
158
- this.hasAttribute('submit-loading') && `${CLASS}--loading`,
159
- ]
160
- .filter(Boolean)
161
- .join(' ');
162
- }
163
- syncHeader() {
164
- if (!this.headerEl)
165
- return;
166
- const title = this.getAttribute('title') || '';
167
- const description = this.getAttribute('description') || '';
168
- this.headerEl.innerHTML = '';
169
- if (!title && !description) {
170
- this.headerEl.hidden = true;
171
- return;
172
- }
173
- this.headerEl.hidden = false;
174
- if (title) {
175
- const heading = document.createElement('h3');
176
- heading.className = `${CLASS}__title`;
177
- heading.textContent = title;
178
- this.headerEl.appendChild(heading);
179
- }
180
- if (description) {
181
- const desc = document.createElement('p');
182
- desc.className = `${CLASS}__description`;
183
- desc.textContent = description;
184
- this.headerEl.appendChild(desc);
185
- }
186
- }
187
- syncActions() {
188
- const submitText = this.getAttribute('submit-text') || '제출';
189
- const resetText = this.getAttribute('reset-text') || '리셋';
190
- const showReset = this.hasAttribute('show-reset');
191
- if (this.submitBtn) {
192
- this.submitBtn.textContent = submitText;
193
- if (this.hasAttribute('submit-loading')) {
194
- this.submitBtn.setAttribute('loading', '');
195
- }
196
- else {
197
- this.submitBtn.removeAttribute('loading');
198
- }
199
- if (this.hasAttribute('submit-disabled')) {
200
- this.submitBtn.setAttribute('disabled', '');
201
- }
202
- else {
203
- this.submitBtn.removeAttribute('disabled');
204
- }
205
- }
206
- if (this.resetBtn) {
207
- this.resetBtn.textContent = resetText;
208
- this.resetBtn.hidden = !showReset;
209
- }
210
- }
211
- renderFields() {
212
- if (!this.fieldsEl)
213
- return;
214
- const size = this.getAttribute('size') || 'm';
215
- this.fieldsEl.innerHTML = '';
216
- this.fieldWrappers.clear();
217
- this.fields.forEach((field) => {
218
- const wrapper = document.createElement('div');
219
- wrapper.className = `${CLASS}__field-wrapper ${CLASS}__field-wrapper--${field.type || 'text'}`;
220
- wrapper.dataset.field = field.name;
221
- if (field.label && !(field.type === 'checkbox' && !field.checkboxGroup)) {
222
- const label = document.createElement('label');
223
- label.className = `${CLASS}__label`;
224
- label.htmlFor = `db-form-${field.name}`;
225
- label.textContent = field.label;
226
- if (field.required || field.validation?.required) {
227
- const req = document.createElement('span');
228
- req.className = `${CLASS}__required`;
229
- req.textContent = '*';
230
- req.setAttribute('aria-hidden', 'true');
231
- label.appendChild(req);
232
- }
233
- wrapper.appendChild(label);
234
- }
235
- wrapper.appendChild(this.createFieldControl(field, size));
236
- this.fieldsEl.appendChild(wrapper);
237
- this.fieldWrappers.set(field.name, wrapper);
238
- this.refreshFieldState(field.name);
239
- });
240
- }
241
- refreshFieldState(fieldName) {
242
- const field = this.fields.find((item) => item.name === fieldName);
243
- const wrapper = this.fieldWrappers.get(fieldName);
244
- if (!field || !wrapper)
245
- return;
246
- const showError = Boolean(this.touched[fieldName] && this.errors[fieldName]);
247
- wrapper.classList.toggle(`${CLASS}__field-wrapper--error`, showError);
248
- wrapper.querySelector(`.${CLASS}__error`)?.remove();
249
- wrapper.querySelector(`.${CLASS}__help`)?.remove();
250
- const control = wrapper.querySelector(`.${CLASS}__field, db-input, db-textarea, db-select, db-checkbox`);
251
- if (control) {
252
- if (showError) {
253
- control.setAttribute('error', '');
254
- control.setAttribute('error-message', this.errors[fieldName]);
255
- }
256
- else {
257
- control.removeAttribute('error');
258
- control.removeAttribute('error-message');
259
- }
260
- }
261
- if (showError) {
262
- const errorEl = document.createElement('div');
263
- errorEl.className = `${CLASS}__error`;
264
- errorEl.textContent = this.errors[fieldName];
265
- wrapper.appendChild(errorEl);
266
- return;
267
- }
268
- if (field.helpText) {
269
- const helpEl = document.createElement('div');
270
- helpEl.className = `${CLASS}__help`;
271
- helpEl.textContent = field.helpText;
272
- wrapper.appendChild(helpEl);
273
- }
274
- }
275
- refreshAllFieldStates() {
276
- this.fields.forEach((field) => this.refreshFieldState(field.name));
277
- }
278
- createFieldControl(field, size) {
279
- const type = field.type || 'text';
280
- const value = this.values[field.name];
281
- const showError = Boolean(this.touched[field.name] && this.errors[field.name]);
282
- const errorMessage = showError ? this.errors[field.name] : '';
283
- if (type === 'textarea') {
284
- const el = document.createElement('db-textarea');
285
- el.className = `${CLASS}__field`;
286
- el.setAttribute('name', field.name);
287
- el.id = `db-form-${field.name}`;
288
- el.setAttribute('size', size);
289
- el.setAttribute('full-width', '');
290
- if (field.placeholder)
291
- el.setAttribute('placeholder', field.placeholder);
292
- if (value !== undefined)
293
- el.setAttribute('value', String(value));
294
- if (field.disabled)
295
- el.setAttribute('disabled', '');
296
- if (field.readOnly)
297
- el.setAttribute('readonly', '');
298
- if (field.required)
299
- el.setAttribute('required', '');
300
- if (field.maxLength)
301
- el.setAttribute('max-length', String(field.maxLength));
302
- if (showError) {
303
- el.setAttribute('error', '');
304
- el.setAttribute('error-message', errorMessage);
305
- }
306
- el.addEventListener('db-change', (e) => {
307
- const detail = e.detail;
308
- this.handleFieldChange(field, detail.value);
309
- });
310
- el.addEventListener('db-input', (e) => {
311
- const detail = e.detail;
312
- this.handleFieldChange(field, detail.value, false);
313
- });
314
- return el;
315
- }
316
- if (type === 'select') {
317
- const el = document.createElement('db-select');
318
- el.className = `${CLASS}__field`;
319
- el.setAttribute('name', field.name);
320
- el.id = `db-form-${field.name}`;
321
- el.setAttribute('size', size);
322
- el.setAttribute('full-width', '');
323
- if (field.placeholder)
324
- el.setAttribute('placeholder', field.placeholder);
325
- if (field.options)
326
- el.setAttribute('options', JSON.stringify(field.options));
327
- if (field.multiple)
328
- el.setAttribute('multiple', '');
329
- if (field.disabled)
330
- el.setAttribute('disabled', '');
331
- if (field.readOnly)
332
- el.setAttribute('readonly', '');
333
- if (field.required)
334
- el.setAttribute('required', '');
335
- if (value !== undefined) {
336
- el.setAttribute('value', Array.isArray(value) ? JSON.stringify(value) : String(value));
337
- }
338
- if (showError) {
339
- el.setAttribute('error', '');
340
- el.setAttribute('error-message', errorMessage);
341
- }
342
- el.addEventListener('db-change', (e) => {
343
- const detail = e.detail;
344
- this.handleFieldChange(field, detail.value);
345
- });
346
- return el;
347
- }
348
- if (type === 'radio' && field.radioGroup) {
349
- const group = document.createElement('div');
350
- group.className = `${CLASS}__radio-group`;
351
- group.setAttribute('role', 'radiogroup');
352
- (field.options || []).forEach((option) => {
353
- const radio = document.createElement('db-radio');
354
- radio.setAttribute('name', field.name);
355
- radio.setAttribute('value', option.value);
356
- radio.setAttribute('size', size);
357
- if (value === option.value)
358
- radio.setAttribute('checked', '');
359
- if (field.disabled || option.disabled)
360
- radio.setAttribute('disabled', '');
361
- radio.textContent = option.label;
362
- radio.addEventListener('db-change', (e) => {
363
- const detail = e.detail;
364
- if (detail.checked) {
365
- this.handleFieldChange(field, option.value);
366
- }
367
- });
368
- group.appendChild(radio);
369
- });
370
- return group;
371
- }
372
- if (type === 'checkbox' && field.checkboxGroup) {
373
- const group = document.createElement('div');
374
- group.className = `${CLASS}__checkbox-group`;
375
- const selected = Array.isArray(value) ? value : [];
376
- (field.options || []).forEach((option) => {
377
- const checkbox = document.createElement('db-checkbox');
378
- checkbox.setAttribute('name', field.name);
379
- checkbox.setAttribute('value', option.value);
380
- checkbox.setAttribute('size', size);
381
- if (selected.includes(option.value))
382
- checkbox.setAttribute('checked', '');
383
- if (field.disabled || option.disabled)
384
- checkbox.setAttribute('disabled', '');
385
- checkbox.textContent = option.label;
386
- checkbox.addEventListener('db-change', (e) => {
387
- const detail = e.detail;
388
- const current = Array.isArray(this.values[field.name])
389
- ? [...this.values[field.name]]
390
- : [];
391
- const next = detail.checked
392
- ? [...new Set([...current, option.value])]
393
- : current.filter((v) => v !== option.value);
394
- this.handleFieldChange(field, next);
395
- });
396
- group.appendChild(checkbox);
397
- });
398
- return group;
399
- }
400
- if (type === 'checkbox') {
401
- const el = document.createElement('db-checkbox');
402
- el.className = `${CLASS}__field`;
403
- el.setAttribute('name', field.name);
404
- el.id = `db-form-${field.name}`;
405
- el.setAttribute('size', size);
406
- if (value)
407
- el.setAttribute('checked', '');
408
- if (field.disabled)
409
- el.setAttribute('disabled', '');
410
- if (field.readOnly)
411
- el.setAttribute('readonly', '');
412
- if (field.required)
413
- el.setAttribute('required', '');
414
- el.textContent = field.label || '';
415
- el.addEventListener('db-change', (e) => {
416
- const detail = e.detail;
417
- this.handleFieldChange(field, detail.checked);
418
- });
419
- return el;
420
- }
421
- const el = document.createElement('db-input');
422
- el.className = `${CLASS}__field`;
423
- el.setAttribute('name', field.name);
424
- el.id = `db-form-${field.name}`;
425
- el.setAttribute('type', type);
426
- el.setAttribute('size', size);
427
- el.setAttribute('full-width', '');
428
- if (field.placeholder)
429
- el.setAttribute('placeholder', field.placeholder);
430
- if (value !== undefined && value !== false)
431
- el.setAttribute('value', String(value));
432
- if (field.disabled)
433
- el.setAttribute('disabled', '');
434
- if (field.readOnly)
435
- el.setAttribute('readonly', '');
436
- if (field.required)
437
- el.setAttribute('required', '');
438
- if (field.min !== undefined)
439
- el.setAttribute('min', String(field.min));
440
- if (field.max !== undefined)
441
- el.setAttribute('max', String(field.max));
442
- if (field.minLength !== undefined)
443
- el.setAttribute('minlength', String(field.minLength));
444
- if (field.maxLength !== undefined)
445
- el.setAttribute('maxlength', String(field.maxLength));
446
- if (field.pattern)
447
- el.setAttribute('pattern', field.pattern);
448
- if (showError) {
449
- el.setAttribute('error', '');
450
- el.setAttribute('error-message', errorMessage);
451
- }
452
- el.addEventListener('db-change', (e) => {
453
- const detail = e.detail;
454
- this.handleFieldChange(field, detail.value);
455
- });
456
- el.addEventListener('db-input', (e) => {
457
- const detail = e.detail;
458
- this.handleFieldChange(field, detail.value, false);
459
- });
460
- return el;
461
- }
462
- handleFieldChange(field, value, touch = true) {
463
- this.values[field.name] = value;
464
- if (touch) {
465
- this.touched[field.name] = true;
466
- }
467
- const error = this.validateField(field, value);
468
- this.errors[field.name] = error || '';
469
- this.refreshFieldState(field.name);
470
- this.dispatchEvent(new CustomEvent('db-change', {
471
- bubbles: true,
472
- composed: true,
473
- detail: { values: { ...this.values } },
474
- }));
475
- }
476
- validateField(field, value) {
477
- const validation = field.validation || {};
478
- const required = validation.required ?? field.required;
479
- if (required) {
480
- if (value === undefined
481
- || value === null
482
- || value === ''
483
- || value === false
484
- || (Array.isArray(value) && value.length === 0)) {
485
- return field.errorMessage || `${field.label || field.name}은(는) 필수입니다.`;
486
- }
487
- }
488
- if (validation.min !== undefined && Number(value) < validation.min) {
489
- return field.errorMessage || `최소값은 ${validation.min}입니다.`;
490
- }
491
- if (validation.max !== undefined && Number(value) > validation.max) {
492
- return field.errorMessage || `최대값은 ${validation.max}입니다.`;
493
- }
494
- if (validation.minLength !== undefined && String(value).length < validation.minLength) {
495
- return field.errorMessage || `최소 ${validation.minLength}자 이상 입력해주세요.`;
496
- }
497
- if (validation.maxLength !== undefined && String(value).length > validation.maxLength) {
498
- return field.errorMessage || `최대 ${validation.maxLength}자까지 입력 가능합니다.`;
499
- }
500
- const patternSource = validation.pattern || field.pattern;
501
- if (patternSource && String(value)) {
502
- try {
503
- const regex = new RegExp(patternSource);
504
- if (!regex.test(String(value))) {
505
- return field.errorMessage || '올바른 형식으로 입력해주세요.';
506
- }
507
- }
508
- catch {
509
- // ignore invalid pattern
510
- }
511
- }
512
- return undefined;
513
- }
514
- validateForm() {
515
- let isValid = true;
516
- this.fields.forEach((field) => {
517
- const error = this.validateField(field, this.values[field.name]);
518
- if (error) {
519
- this.errors[field.name] = error;
520
- isValid = false;
521
- }
522
- else {
523
- this.errors[field.name] = '';
524
- }
525
- });
526
- return isValid;
527
- }
528
- handleSubmit(e) {
529
- e.preventDefault();
530
- this.fields.forEach((field) => {
531
- this.touched[field.name] = true;
532
- });
533
- if (!this.validateForm()) {
534
- this.refreshAllFieldStates();
535
- return;
536
- }
537
- this.dispatchEvent(new CustomEvent('db-submit', {
538
- bubbles: true,
539
- composed: true,
540
- detail: { values: { ...this.values } },
541
- }));
542
- }
543
- handleReset(e) {
544
- e.preventDefault();
545
- this.values = { ...this.initialValues };
546
- this.bootstrapValues();
547
- this.errors = {};
548
- this.touched = {};
549
- this.renderFields();
550
- this.dispatchEvent(new CustomEvent('db-reset', {
551
- bubbles: true,
552
- composed: true,
553
- detail: { values: { ...this.values } },
554
- }));
555
- this.dispatchEvent(new CustomEvent('db-change', {
556
- bubbles: true,
557
- composed: true,
558
- detail: { values: { ...this.values } },
559
- }));
560
- }
561
- }
562
- if (!customElements.get('db-form')) {
563
- customElements.define('db-form', DbForm);
564
- }
565
-
566
- export { DbForm };
1
+ import"./db-input.js";import"./db-textarea.js";import"./db-select.js";import"./db-checkbox.js";import"./db-radio.js";import"./db-button.js";const e="designbase-wc-form";class DbForm extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.formEl=null,this.headerEl=null,this.fieldsEl=null,this.actionsEl=null,this.submitBtn=null,this.resetBtn=null,this.values={},this.errors={},this.touched={},this.initialValues={},this.fieldWrappers=new Map,this.boundSubmit=e=>this.handleSubmit(e),this.boundReset=e=>this.handleReset(e)}static get observedAttributes(){return["fields","columns","size","variant","title","description","submit-text","reset-text","show-reset","submit-loading","submit-disabled","initial-values"]}connectedCallback(){this.built||(this.buildShell(),this.built=!0),this.bootstrapValues(),this.syncAll()}attributeChangedCallback(e){this.built&&("initial-values"===e&&this.bootstrapValues(),"fields"===e&&this.bootstrapValues(),this.syncAll())}get fields(){return this.parseFields(this.getAttribute("fields"))}set fields(e){this.setAttribute("fields","string"==typeof e?e:JSON.stringify(e))}parseFields(e){if(!e)return[];try{const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}parseInitialValues(){const e=this.getAttribute("initial-values");if(!e)return{};try{const t=JSON.parse(e);return t&&"object"==typeof t?t:{}}catch{return{}}}bootstrapValues(){this.initialValues=this.parseInitialValues();const e={...this.initialValues};this.fields.forEach(t=>{void 0===e[t.name]&&(void 0===t.value?void 0===t.defaultValue?"checkbox"===t.type&&t.checkboxGroup?e[t.name]=[]:"checkbox"!==t.type?e[t.name]="":e[t.name]=!1:e[t.name]=t.defaultValue:e[t.name]=t.value)}),this.values=e}buildShell(){this.formEl=document.createElement("form"),this.formEl.className=`${e}__native`,this.formEl.noValidate=!0,this.formEl.addEventListener("submit",this.boundSubmit),this.headerEl=document.createElement("div"),this.headerEl.className=`${e}__header`,this.fieldsEl=document.createElement("div"),this.fieldsEl.className=`${e}__fields`,this.actionsEl=document.createElement("div"),this.actionsEl.className=`${e}__actions`,this.submitBtn=document.createElement("db-button"),this.submitBtn.setAttribute("type","submit"),this.submitBtn.setAttribute("variant","primary"),this.resetBtn=document.createElement("db-button"),this.resetBtn.setAttribute("type","button"),this.resetBtn.setAttribute("variant","secondary"),this.resetBtn.addEventListener("click",this.boundReset),this.actionsEl.append(this.submitBtn,this.resetBtn),this.formEl.append(this.fieldsEl,this.actionsEl),this.append(this.headerEl,this.formEl)}syncAll(){this.syncClasses(),this.syncHeader(),this.renderFields(),this.syncActions()}syncClasses(){const t=this.getAttribute("columns")||"1",i=this.getAttribute("size")||"m",s=this.getAttribute("variant")||"default";this.className=[e,`${e}--columns-${t}`,`${e}--${i}`,`${e}--${s}`,this.hasAttribute("submit-loading")&&`${e}--loading`].filter(Boolean).join(" ")}syncHeader(){if(!this.headerEl)return;const t=this.getAttribute("title")||"",i=this.getAttribute("description")||"";if(this.headerEl.innerHTML="",t||i){if(this.headerEl.hidden=!1,t){const i=document.createElement("h3");i.className=`${e}__title`,i.textContent=t,this.headerEl.appendChild(i)}if(i){const t=document.createElement("p");t.className=`${e}__description`,t.textContent=i,this.headerEl.appendChild(t)}}else this.headerEl.hidden=!0}syncActions(){const e=this.getAttribute("submit-text")||"제출",t=this.getAttribute("reset-text")||"리셋",i=this.hasAttribute("show-reset");this.submitBtn&&(this.submitBtn.textContent=e,this.hasAttribute("submit-loading")?this.submitBtn.setAttribute("loading",""):this.submitBtn.removeAttribute("loading"),this.hasAttribute("submit-disabled")?this.submitBtn.setAttribute("disabled",""):this.submitBtn.removeAttribute("disabled")),this.resetBtn&&(this.resetBtn.textContent=t,this.resetBtn.hidden=!i)}renderFields(){if(!this.fieldsEl)return;const t=this.getAttribute("size")||"m";this.fieldsEl.innerHTML="",this.fieldWrappers.clear(),this.fields.forEach(i=>{const s=document.createElement("div");if(s.className=`${e}__field-wrapper ${e}__field-wrapper--${i.type||"text"}`,s.dataset.field=i.name,i.label&&("checkbox"!==i.type||i.checkboxGroup)){const t=document.createElement("label");if(t.className=`${e}__label`,t.htmlFor=`db-form-${i.name}`,t.textContent=i.label,i.required||i.validation?.required){const i=document.createElement("span");i.className=`${e}__required`,i.textContent="*",i.setAttribute("aria-hidden","true"),t.appendChild(i)}s.appendChild(t)}s.appendChild(this.createFieldControl(i,t)),this.fieldsEl.appendChild(s),this.fieldWrappers.set(i.name,s),this.refreshFieldState(i.name)})}refreshFieldState(t){const i=this.fields.find(e=>e.name===t),s=this.fieldWrappers.get(t);if(!i||!s)return;const r=Boolean(this.touched[t]&&this.errors[t]);s.classList.toggle(`${e}__field-wrapper--error`,r),s.querySelector(`.${e}__error`)?.remove(),s.querySelector(`.${e}__help`)?.remove();const a=s.querySelector(`.${e}__field, db-input, db-textarea, db-select, db-checkbox`);if(a&&(r?(a.setAttribute("error",""),a.setAttribute("error-message",this.errors[t])):(a.removeAttribute("error"),a.removeAttribute("error-message"))),r){const i=document.createElement("div");return i.className=`${e}__error`,i.textContent=this.errors[t],void s.appendChild(i)}if(i.helpText){const t=document.createElement("div");t.className=`${e}__help`,t.textContent=i.helpText,s.appendChild(t)}}refreshAllFieldStates(){this.fields.forEach(e=>this.refreshFieldState(e.name))}createFieldControl(t,i){const s=t.type||"text",r=this.values[t.name],a=Boolean(this.touched[t.name]&&this.errors[t.name]),n=a?this.errors[t.name]:"";if("textarea"===s){const s=document.createElement("db-textarea");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),s.setAttribute("full-width",""),t.placeholder&&s.setAttribute("placeholder",t.placeholder),void 0!==r&&s.setAttribute("value",String(r)),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),t.maxLength&&s.setAttribute("max-length",String(t.maxLength)),a&&(s.setAttribute("error",""),s.setAttribute("error-message",n)),s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),s.addEventListener("db-input",e=>{const i=e.detail;this.handleFieldChange(t,i.value,!1)}),s}if("select"===s){const s=document.createElement("db-select");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),s.setAttribute("full-width",""),t.placeholder&&s.setAttribute("placeholder",t.placeholder),t.options&&s.setAttribute("options",JSON.stringify(t.options)),t.multiple&&s.setAttribute("multiple",""),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),void 0!==r&&s.setAttribute("value",Array.isArray(r)?JSON.stringify(r):String(r)),a&&(s.setAttribute("error",""),s.setAttribute("error-message",n)),s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),s}if("radio"===s&&t.radioGroup){const s=document.createElement("div");return s.className=`${e}__radio-group`,s.setAttribute("role","radiogroup"),(t.options||[]).forEach(e=>{const a=document.createElement("db-radio");a.setAttribute("name",t.name),a.setAttribute("value",e.value),a.setAttribute("size",i),r===e.value&&a.setAttribute("checked",""),(t.disabled||e.disabled)&&a.setAttribute("disabled",""),a.textContent=e.label,a.addEventListener("db-change",i=>{i.detail.checked&&this.handleFieldChange(t,e.value)}),s.appendChild(a)}),s}if("checkbox"===s&&t.checkboxGroup){const s=document.createElement("div");s.className=`${e}__checkbox-group`;const a=Array.isArray(r)?r:[];return(t.options||[]).forEach(e=>{const r=document.createElement("db-checkbox");r.setAttribute("name",t.name),r.setAttribute("value",e.value),r.setAttribute("size",i),a.includes(e.value)&&r.setAttribute("checked",""),(t.disabled||e.disabled)&&r.setAttribute("disabled",""),r.textContent=e.label,r.addEventListener("db-change",i=>{const s=i.detail,r=Array.isArray(this.values[t.name])?[...this.values[t.name]]:[],a=s.checked?[...new Set([...r,e.value])]:r.filter(t=>t!==e.value);this.handleFieldChange(t,a)}),s.appendChild(r)}),s}if("checkbox"===s){const s=document.createElement("db-checkbox");return s.className=`${e}__field`,s.setAttribute("name",t.name),s.id=`db-form-${t.name}`,s.setAttribute("size",i),r&&s.setAttribute("checked",""),t.disabled&&s.setAttribute("disabled",""),t.readOnly&&s.setAttribute("readonly",""),t.required&&s.setAttribute("required",""),s.textContent=t.label||"",s.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.checked)}),s}const l=document.createElement("db-input");return l.className=`${e}__field`,l.setAttribute("name",t.name),l.id=`db-form-${t.name}`,l.setAttribute("type",s),l.setAttribute("size",i),l.setAttribute("full-width",""),t.placeholder&&l.setAttribute("placeholder",t.placeholder),void 0!==r&&!1!==r&&l.setAttribute("value",String(r)),t.disabled&&l.setAttribute("disabled",""),t.readOnly&&l.setAttribute("readonly",""),t.required&&l.setAttribute("required",""),void 0!==t.min&&l.setAttribute("min",String(t.min)),void 0!==t.max&&l.setAttribute("max",String(t.max)),void 0!==t.minLength&&l.setAttribute("minlength",String(t.minLength)),void 0!==t.maxLength&&l.setAttribute("maxlength",String(t.maxLength)),t.pattern&&l.setAttribute("pattern",t.pattern),a&&(l.setAttribute("error",""),l.setAttribute("error-message",n)),l.addEventListener("db-change",e=>{const i=e.detail;this.handleFieldChange(t,i.value)}),l.addEventListener("db-input",e=>{const i=e.detail;this.handleFieldChange(t,i.value,!1)}),l}handleFieldChange(e,t,i=!0){this.values[e.name]=t,i&&(this.touched[e.name]=!0);const s=this.validateField(e,t);this.errors[e.name]=s||"",this.refreshFieldState(e.name),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}validateField(e,t){const i=e.validation||{};if((i.required??e.required)&&(null==t||""===t||!1===t||Array.isArray(t)&&0===t.length))return e.errorMessage||`${e.label||e.name}은(는) 필수입니다.`;if(void 0!==i.min&&Number(t)<i.min)return e.errorMessage||`최소값은 ${i.min}입니다.`;if(void 0!==i.max&&Number(t)>i.max)return e.errorMessage||`최대값은 ${i.max}입니다.`;if(void 0!==i.minLength&&String(t).length<i.minLength)return e.errorMessage||`최소 ${i.minLength}자 이상 입력해주세요.`;if(void 0!==i.maxLength&&String(t).length>i.maxLength)return e.errorMessage||`최대 ${i.maxLength}자까지 입력 가능합니다.`;const s=i.pattern||e.pattern;if(s&&String(t))try{if(!new RegExp(s).test(String(t)))return e.errorMessage||"올바른 형식으로 입력해주세요."}catch{}}validateForm(){let e=!0;return this.fields.forEach(t=>{const i=this.validateField(t,this.values[t.name]);i?(this.errors[t.name]=i,e=!1):this.errors[t.name]=""}),e}handleSubmit(e){e.preventDefault(),this.fields.forEach(e=>{this.touched[e.name]=!0}),this.validateForm()?this.dispatchEvent(new CustomEvent("db-submit",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})):this.refreshAllFieldStates()}handleReset(e){e.preventDefault(),this.values={...this.initialValues},this.bootstrapValues(),this.errors={},this.touched={},this.renderFields(),this.dispatchEvent(new CustomEvent("db-reset",{bubbles:!0,composed:!0,detail:{values:{...this.values}}})),this.dispatchEvent(new CustomEvent("db-change",{bubbles:!0,composed:!0,detail:{values:{...this.values}}}))}}customElements.get("db-form")||customElements.define("db-form",DbForm);export{DbForm};