@designbasekorea/ui-wc 0.2.1 → 0.2.2

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 (239) hide show
  1. package/README.md +322 -29
  2. package/dist/esm/components/animation-background/canvas-controller.js +1 -0
  3. package/dist/esm/components/animation-background/layers.js +1 -0
  4. package/dist/esm/components/animation-background/lumina-presets.js +1 -0
  5. package/dist/esm/components/animation-background/lumina-shaders.js +1 -0
  6. package/dist/esm/components/animation-background/lumina-utils.js +1 -0
  7. package/dist/esm/components/animation-background/particle-defaults.js +1 -0
  8. package/dist/esm/components/animation-background/renderers.js +1 -0
  9. package/dist/esm/components/animation-background/shader-controller.js +1 -0
  10. package/dist/esm/components/color-picker-utils.js +1 -0
  11. package/dist/esm/components/date-picker-utils.js +1 -0
  12. package/dist/esm/components/db-accordion.d.ts +40 -0
  13. package/dist/esm/components/db-accordion.js +1 -0
  14. package/dist/esm/components/db-ad-banner.d.ts +41 -0
  15. package/dist/esm/components/db-ad-banner.js +1 -0
  16. package/dist/esm/components/db-alert.d.ts +24 -0
  17. package/dist/esm/components/db-alert.js +1 -0
  18. package/dist/esm/components/db-animation-background.d.ts +20 -0
  19. package/dist/esm/components/db-animation-background.js +1 -0
  20. package/dist/esm/components/db-animation-text.d.ts +32 -0
  21. package/dist/esm/components/db-animation-text.js +1 -0
  22. package/dist/esm/components/db-app-badge.d.ts +20 -0
  23. package/dist/esm/components/db-app-badge.js +1 -0
  24. package/dist/esm/components/db-audio-player.d.ts +82 -0
  25. package/dist/esm/components/db-audio-player.js +1 -0
  26. package/dist/esm/components/db-avatar.d.ts +18 -0
  27. package/dist/esm/components/db-avatar.js +1 -0
  28. package/dist/esm/components/db-backdrop.d.ts +24 -0
  29. package/dist/esm/components/db-backdrop.js +1 -0
  30. package/dist/esm/components/db-badge.d.ts +27 -0
  31. package/dist/esm/components/db-badge.js +1 -0
  32. package/dist/esm/components/db-banner.d.ts +28 -0
  33. package/dist/esm/components/db-banner.js +1 -0
  34. package/dist/esm/components/db-bottom-navigation.d.ts +29 -0
  35. package/dist/esm/components/db-bottom-navigation.js +1 -0
  36. package/dist/esm/components/db-bottom-sheet.d.ts +49 -0
  37. package/dist/esm/components/db-bottom-sheet.js +1 -0
  38. package/dist/esm/components/db-breadcrumbs.d.ts +24 -0
  39. package/dist/esm/components/db-breadcrumbs.js +1 -0
  40. package/dist/esm/components/db-button.d.ts +57 -0
  41. package/dist/esm/components/db-button.js +1 -0
  42. package/dist/esm/components/db-calendar.d.ts +78 -0
  43. package/dist/esm/components/db-calendar.js +1 -0
  44. package/dist/esm/components/db-card.d.ts +42 -0
  45. package/dist/esm/components/db-card.js +1 -0
  46. package/dist/esm/components/db-carousel.d.ts +35 -0
  47. package/dist/esm/components/db-carousel.js +1 -0
  48. package/dist/esm/components/db-checkbox.d.ts +35 -0
  49. package/dist/esm/components/db-checkbox.js +1 -0
  50. package/dist/esm/components/db-chip.d.ts +14 -0
  51. package/dist/esm/components/db-chip.js +1 -0
  52. package/dist/esm/components/db-code-block.d.ts +28 -0
  53. package/dist/esm/components/db-code-block.js +1 -0
  54. package/dist/esm/components/db-color-picker.d.ts +83 -0
  55. package/dist/esm/components/db-color-picker.js +1 -0
  56. package/dist/esm/components/db-confirm.d.ts +23 -0
  57. package/dist/esm/components/db-confirm.js +1 -0
  58. package/dist/esm/components/db-container.d.ts +13 -0
  59. package/dist/esm/components/db-container.js +1 -0
  60. package/dist/esm/components/db-context-menu.d.ts +46 -0
  61. package/dist/esm/components/db-context-menu.js +1 -0
  62. package/dist/esm/components/db-countdown.d.ts +23 -0
  63. package/dist/esm/components/db-countdown.js +1 -0
  64. package/dist/esm/components/db-cursor-follower.d.ts +32 -0
  65. package/dist/esm/components/db-cursor-follower.js +1 -0
  66. package/dist/esm/components/db-date-picker.d.ts +84 -0
  67. package/dist/esm/components/db-date-picker.js +1 -0
  68. package/dist/esm/components/db-divider.d.ts +13 -0
  69. package/dist/esm/components/db-divider.js +1 -0
  70. package/dist/esm/components/db-drawer.d.ts +32 -0
  71. package/dist/esm/components/db-drawer.js +1 -0
  72. package/dist/esm/components/db-dropdown.d.ts +70 -0
  73. package/dist/esm/components/db-dropdown.js +1 -0
  74. package/dist/esm/components/db-dropzone.d.ts +29 -0
  75. package/dist/esm/components/db-dropzone.js +1 -0
  76. package/dist/esm/components/db-empty-state.d.ts +14 -0
  77. package/dist/esm/components/db-empty-state.js +1 -0
  78. package/dist/esm/components/db-file-uploader.d.ts +27 -0
  79. package/dist/esm/components/db-file-uploader.js +1 -0
  80. package/dist/esm/components/db-floating-action-button.d.ts +24 -0
  81. package/dist/esm/components/db-floating-action-button.js +1 -0
  82. package/dist/esm/components/db-form.d.ts +94 -0
  83. package/dist/esm/components/db-form.js +1 -0
  84. package/dist/esm/components/db-gradient.d.ts +26 -0
  85. package/dist/esm/components/db-gradient.js +1 -0
  86. package/dist/esm/components/db-grid.d.ts +20 -0
  87. package/dist/esm/components/db-grid.js +1 -0
  88. package/dist/esm/components/db-icons.js +1 -0
  89. package/dist/esm/components/db-image-list.d.ts +35 -0
  90. package/dist/esm/components/db-image-list.js +1 -0
  91. package/dist/esm/components/db-image-placeholder.d.ts +16 -0
  92. package/dist/esm/components/db-image-placeholder.js +1 -0
  93. package/dist/esm/components/db-image.d.ts +34 -0
  94. package/dist/esm/components/db-image.js +1 -0
  95. package/dist/esm/components/db-indicator.d.ts +46 -0
  96. package/dist/esm/components/db-indicator.js +1 -0
  97. package/dist/esm/components/db-input.d.ts +51 -0
  98. package/dist/esm/components/db-input.js +1 -0
  99. package/dist/esm/components/db-label.d.ts +13 -0
  100. package/dist/esm/components/db-label.js +1 -0
  101. package/dist/esm/components/db-lightbox.d.ts +52 -0
  102. package/dist/esm/components/db-lightbox.js +1 -0
  103. package/dist/esm/components/db-list.d.ts +46 -0
  104. package/dist/esm/components/db-list.js +1 -0
  105. package/dist/esm/components/db-logo-svg.js +1 -0
  106. package/dist/esm/components/db-logo.d.ts +15 -0
  107. package/dist/esm/components/db-logo.js +1 -0
  108. package/dist/esm/components/db-lottie.d.ts +20 -0
  109. package/dist/esm/components/db-lottie.js +1 -0
  110. package/dist/esm/components/db-markdown-editor.d.ts +53 -0
  111. package/dist/esm/components/db-markdown-editor.js +1 -0
  112. package/dist/esm/components/db-marquee.d.ts +34 -0
  113. package/dist/esm/components/db-marquee.js +1 -0
  114. package/dist/esm/components/db-masonry.d.ts +24 -0
  115. package/dist/esm/components/db-masonry.js +1 -0
  116. package/dist/esm/components/db-menu-item.d.ts +30 -0
  117. package/dist/esm/components/db-menu-item.js +1 -0
  118. package/dist/esm/components/db-modal.d.ts +63 -0
  119. package/dist/esm/components/db-modal.js +1 -0
  120. package/dist/esm/components/db-navbar.d.ts +57 -0
  121. package/dist/esm/components/db-navbar.js +1 -0
  122. package/dist/esm/components/db-onboarding-modal.d.ts +57 -0
  123. package/dist/esm/components/db-onboarding-modal.js +1 -0
  124. package/dist/esm/components/db-page-header.d.ts +33 -0
  125. package/dist/esm/components/db-page-header.js +1 -0
  126. package/dist/esm/components/db-pagination.d.ts +25 -0
  127. package/dist/esm/components/db-pagination.js +1 -0
  128. package/dist/esm/components/db-popover.d.ts +62 -0
  129. package/dist/esm/components/db-popover.js +1 -0
  130. package/dist/esm/components/db-progress-step.d.ts +28 -0
  131. package/dist/esm/components/db-progress-step.js +1 -0
  132. package/dist/esm/components/db-progress.d.ts +15 -0
  133. package/dist/esm/components/db-progress.js +1 -0
  134. package/dist/esm/components/db-progressbar.d.ts +13 -0
  135. package/dist/esm/components/db-progressbar.js +1 -0
  136. package/dist/esm/components/db-radio.d.ts +34 -0
  137. package/dist/esm/components/db-radio.js +1 -0
  138. package/dist/esm/components/db-random-gradient.d.ts +24 -0
  139. package/dist/esm/components/db-random-gradient.js +1 -0
  140. package/dist/esm/components/db-range-slider.d.ts +64 -0
  141. package/dist/esm/components/db-range-slider.js +1 -0
  142. package/dist/esm/components/db-rating.d.ts +31 -0
  143. package/dist/esm/components/db-rating.js +1 -0
  144. package/dist/esm/components/db-reorder.d.ts +38 -0
  145. package/dist/esm/components/db-reorder.js +1 -0
  146. package/dist/esm/components/db-resizable-panels.d.ts +42 -0
  147. package/dist/esm/components/db-resizable-panels.js +1 -0
  148. package/dist/esm/components/db-scroll-area.d.ts +23 -0
  149. package/dist/esm/components/db-scroll-area.js +1 -0
  150. package/dist/esm/components/db-search-bar.d.ts +53 -0
  151. package/dist/esm/components/db-search-bar.js +1 -0
  152. package/dist/esm/components/db-section-app-download.d.ts +32 -0
  153. package/dist/esm/components/db-section-app-download.js +1 -0
  154. package/dist/esm/components/db-section-contact.d.ts +22 -0
  155. package/dist/esm/components/db-section-contact.js +1 -0
  156. package/dist/esm/components/db-section-feature.d.ts +34 -0
  157. package/dist/esm/components/db-section-feature.js +1 -0
  158. package/dist/esm/components/db-section-hero.d.ts +34 -0
  159. package/dist/esm/components/db-section-hero.js +1 -0
  160. package/dist/esm/components/db-section.d.ts +44 -0
  161. package/dist/esm/components/db-section.js +1 -0
  162. package/dist/esm/components/db-segment-control.d.ts +41 -0
  163. package/dist/esm/components/db-segment-control.js +1 -0
  164. package/dist/esm/components/db-select.d.ts +66 -0
  165. package/dist/esm/components/db-select.js +1 -0
  166. package/dist/esm/components/db-share-icons.js +1 -0
  167. package/dist/esm/components/db-share.d.ts +48 -0
  168. package/dist/esm/components/db-share.js +1 -0
  169. package/dist/esm/components/db-sidebar.d.ts +59 -0
  170. package/dist/esm/components/db-sidebar.js +1 -0
  171. package/dist/esm/components/db-skeleton.d.ts +13 -0
  172. package/dist/esm/components/db-skeleton.js +1 -0
  173. package/dist/esm/components/db-spinner.d.ts +27 -0
  174. package/dist/esm/components/db-spinner.js +1 -0
  175. package/dist/esm/components/db-split-view.d.ts +33 -0
  176. package/dist/esm/components/db-split-view.js +1 -0
  177. package/dist/esm/components/db-stack.d.ts +13 -0
  178. package/dist/esm/components/db-stack.js +1 -0
  179. package/dist/esm/components/db-stat.d.ts +26 -0
  180. package/dist/esm/components/db-stat.js +1 -0
  181. package/dist/esm/components/db-stepper.d.ts +49 -0
  182. package/dist/esm/components/db-stepper.js +1 -0
  183. package/dist/esm/components/db-table.d.ts +39 -0
  184. package/dist/esm/components/db-table.js +1 -0
  185. package/dist/esm/components/db-tabs.d.ts +48 -0
  186. package/dist/esm/components/db-tabs.js +1 -0
  187. package/dist/esm/components/db-testimonial.d.ts +27 -0
  188. package/dist/esm/components/db-testimonial.js +1 -0
  189. package/dist/esm/components/db-textarea.d.ts +33 -0
  190. package/dist/esm/components/db-textarea.js +1 -0
  191. package/dist/esm/components/db-time-picker.d.ts +62 -0
  192. package/dist/esm/components/db-time-picker.js +1 -0
  193. package/dist/esm/components/db-timeline.d.ts +29 -0
  194. package/dist/esm/components/db-timeline.js +1 -0
  195. package/dist/esm/components/db-toast.d.ts +23 -0
  196. package/dist/esm/components/db-toast.js +1 -0
  197. package/dist/esm/components/db-toggle.d.ts +35 -0
  198. package/dist/esm/components/db-toggle.js +1 -0
  199. package/dist/esm/components/db-toolbar.d.ts +25 -0
  200. package/dist/esm/components/db-toolbar.js +1 -0
  201. package/dist/esm/components/db-tooltip.d.ts +55 -0
  202. package/dist/esm/components/db-tooltip.js +1 -0
  203. package/dist/esm/components/db-top-banner.d.ts +17 -0
  204. package/dist/esm/components/db-top-banner.js +1 -0
  205. package/dist/esm/components/db-tutorial.d.ts +54 -0
  206. package/dist/esm/components/db-tutorial.js +1 -0
  207. package/dist/esm/components/db-video-player.d.ts +67 -0
  208. package/dist/esm/components/db-video-player.js +1 -0
  209. package/dist/esm/components/db-youtube-player.d.ts +22 -0
  210. package/dist/esm/components/db-youtube-player.js +1 -0
  211. package/dist/esm/components/highlight-code.js +1 -0
  212. package/dist/esm/components/input-validation.js +1 -0
  213. package/dist/esm/components/number-scrub.js +1 -0
  214. package/dist/esm/components/random-gradient-palettes.js +1 -0
  215. package/dist/esm/helpers/confirm.d.ts +30 -0
  216. package/dist/esm/helpers/confirm.js +1 -0
  217. package/dist/esm/helpers/toast.d.ts +56 -0
  218. package/dist/esm/helpers/toast.js +1 -0
  219. package/dist/esm/index.d.ts +100 -0
  220. package/dist/esm/index.js +1 -0
  221. package/dist/esm/node_modules/prismjs/components/prism-bash.js +1 -0
  222. package/dist/esm/node_modules/prismjs/components/prism-clike.js +1 -0
  223. package/dist/esm/node_modules/prismjs/components/prism-css.js +1 -0
  224. package/dist/esm/node_modules/prismjs/components/prism-javascript.js +1 -0
  225. package/dist/esm/node_modules/prismjs/components/prism-json.js +1 -0
  226. package/dist/esm/node_modules/prismjs/components/prism-jsx.js +1 -0
  227. package/dist/esm/node_modules/prismjs/components/prism-markup.js +1 -0
  228. package/dist/esm/node_modules/prismjs/components/prism-scss.js +1 -0
  229. package/dist/esm/node_modules/prismjs/components/prism-tsx.js +1 -0
  230. package/dist/esm/node_modules/prismjs/components/prism-typescript.js +1 -0
  231. package/dist/index.cjs +1 -1
  232. package/dist/index.css +1 -1
  233. package/dist/index.d.ts +160 -3
  234. package/dist/index.esm.js +1 -1
  235. package/dist/react/index.cjs +1 -1
  236. package/dist/react/index.d.ts +176 -48
  237. package/dist/react/index.esm.js +1 -1
  238. package/package.json +10 -2
  239. /package/dist/chunks/{lottie-2c3b8673.js → lottie-e741cdda.js} +0 -0
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @designbasekorea/ui-wc
2
2
 
3
- Designbase **Web Components** — Vue 3, Angular, React, vanilla HTML에서 공통으로 사용하는 웹 컴포넌트 원본입니다.
3
+ Designbase **Web Components** — Vue 3, Angular, React, vanilla HTML에서 공통으로 사용하는 웹 컴포넌트 라이브러리입니다.
4
4
 
5
- React 사용자는 `@designbasekorea/ui-wc/react`의 `Button`, `Input`, `Tabs` wrapper를 사용할 수 있습니다. vanilla/Vue/Angular는 `<db-button>` 같은 Custom Elements를 직접 사용할 수 있습니다. 기존 `@designbasekorea/ui` React 패키지는 별도 레거시/완성형 패키지로 유지합니다.
5
+ 100여 개의 커스텀 엘리먼트를 제공하며, React 전용 wrapper(`@designbasekorea/ui-wc/react`)도 포함합니다.
6
6
 
7
7
  ## 설치
8
8
 
@@ -10,75 +10,368 @@ React 사용자는 `@designbasekorea/ui-wc/react`의 `Button`, `Input`, `Tabs` w
10
10
  npm install @designbasekorea/ui-wc @designbasekorea/tokens @designbasekorea/theme
11
11
  ```
12
12
 
13
- ## 사용법
13
+ ## 기본 사용법
14
14
 
15
15
  ```ts
16
+ // CSS (필수 — 순서 중요)
16
17
  import '@designbasekorea/tokens/dist/css/tokens.css';
17
18
  import '@designbasekorea/theme/dist/css/theme.css';
18
19
  import '@designbasekorea/ui-wc/dist/index.css';
20
+
21
+ // 전체 등록 (모든 컴포넌트를 한 번에)
19
22
  import '@designbasekorea/ui-wc';
20
23
  ```
21
24
 
22
25
  ```html
23
26
  <db-button variant="primary">저장</db-button>
24
27
  <db-input label="이메일" placeholder="you@example.com"></db-input>
25
- <db-tabs labels="홈,탐색,알림" active-index="0"></db-tabs>
28
+ <db-tabs items='[{"id":"a","label":"홈"},{"id":"b","label":"탐색"}]'></db-tabs>
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 트리셰이킹 / 개별 import
34
+
35
+ 빌드 번들 크기를 줄이려면 `./components/*` 경로로 개별 임포트합니다. 사용한 컴포넌트만 번들에 포함됩니다.
36
+
37
+ ```ts
38
+ import '@designbasekorea/tokens/dist/css/tokens.css';
39
+ import '@designbasekorea/theme/dist/css/theme.css';
40
+ import '@designbasekorea/ui-wc/dist/index.css';
41
+
42
+ // 필요한 컴포넌트만 임포트
43
+ import '@designbasekorea/ui-wc/components/db-button';
44
+ import '@designbasekorea/ui-wc/components/db-input';
45
+ ```
46
+
47
+ TypeScript에서 클래스를 직접 임포트할 수도 있습니다.
48
+
49
+ ```ts
50
+ import { DbButton } from '@designbasekorea/ui-wc/components/db-button';
26
51
  ```
27
52
 
53
+ ---
54
+
28
55
  ## React wrapper
29
56
 
30
57
  ```tsx
31
58
  import '@designbasekorea/tokens/dist/css/tokens.css';
32
59
  import '@designbasekorea/theme/dist/css/theme.css';
33
60
  import '@designbasekorea/ui-wc/dist/index.css';
34
- import { Button } from '@designbasekorea/ui-wc/react';
61
+ import { Button, Input, Toggle } from '@designbasekorea/ui-wc/react';
62
+
63
+ <Button variant="primary" onDbClick={() => save()}>저장</Button>
64
+ <Input label="이메일" onChange={e => setValue(e.detail.value)} />
65
+ <Toggle checked={agreed} onDbChange={e => setAgreed(e.detail.checked)} />
66
+ ```
67
+
68
+ ---
69
+
70
+ ## 명령형 헬퍼
71
+
72
+ DOM 없이 JavaScript로 토스트·확인 다이얼로그를 직접 제어합니다.
73
+
74
+ ### toast
75
+
76
+ ```ts
77
+ import { toast } from '@designbasekorea/ui-wc';
78
+
79
+ // 단축 메서드
80
+ toast.success('저장되었습니다');
81
+ toast.error('오류가 발생했습니다', { description: '잠시 후 다시 시도하세요' });
82
+ toast.warning('용량이 거의 찼습니다');
83
+ toast.info('업데이트가 준비됐습니다');
84
+
85
+ // 전체 옵션
86
+ toast({
87
+ title: '처리 중…',
88
+ status: 'info',
89
+ duration: 0, // 0이면 수동으로 닫을 때까지 유지
90
+ position: 'bottom-center',
91
+ showProgress: true,
92
+ });
35
93
 
36
- <Button variant="primary" onPress={() => save()}>
37
- 저장
38
- </Button>
94
+ // 수동 제어
95
+ const handle = toast.success('파일 업로드 완료');
96
+ handle.close(); // 프로그래밍으로 닫기
97
+
98
+ // 전체 닫기
99
+ toast.dismissAll();
100
+ toast.dismissAll('top-right'); // 특정 위치만
101
+ ```
102
+
103
+ **position 옵션:** `top-right` (기본) · `top-left` · `top-center` · `bottom-right` · `bottom-left` · `bottom-center`
104
+
105
+ ### confirm
106
+
107
+ ```ts
108
+ import { confirm } from '@designbasekorea/ui-wc';
109
+ // 전역 confirm과 충돌을 피하려면:
110
+ import { dbConfirm } from '@designbasekorea/ui-wc';
111
+
112
+ const ok = await confirm({
113
+ title: '정말 삭제하시겠습니까?',
114
+ message: '이 작업은 되돌릴 수 없습니다.',
115
+ variant: 'danger',
116
+ confirmText: '삭제',
117
+ cancelText: '취소',
118
+ });
119
+ if (ok) deleteItem();
120
+ ```
121
+
122
+ ---
123
+
124
+ ## property 설정 (복합 데이터)
125
+
126
+ JSON 문자열 속성 대신 JavaScript 배열·객체를 직접 할당할 수 있습니다.
127
+
128
+ ```ts
129
+ const tabs = document.querySelector('db-tabs');
130
+
131
+ // 이전 방식 (여전히 동작)
132
+ tabs.setAttribute('items', JSON.stringify([{ id: 'a', label: '홈' }]));
133
+
134
+ // 권장 방식 — property setter
135
+ tabs.items = [
136
+ { id: 'home', label: '홈' },
137
+ { id: 'search', label: '탐색' },
138
+ ];
139
+
140
+ const navbar = document.querySelector('db-navbar');
141
+ navbar.items = [{ label: '소개', href: '/about' }];
142
+ navbar.userProfile = { name: '홍길동', avatar: '/avatar.png' };
143
+ navbar.userProfile = null; // 프로필 영역 제거
39
144
  ```
40
145
 
41
- ## 컴포넌트 (11개)
146
+ property setter를 지원하는 컴포넌트: `db-tabs`, `db-navbar`, `db-sidebar`, `db-bottom-navigation`, `db-tutorial`, `db-gradient`, `db-section-feature`, `db-section-hero`, `db-section-app-download`, `db-table`
147
+
148
+ ---
149
+
150
+ ## 폼 통합
151
+
152
+ `db-toggle`과 `db-select`는 `formAssociated = true`를 지원해 네이티브 `<form>` 제출에 참여합니다.
153
+
154
+ ```html
155
+ <form id="settings-form">
156
+ <db-toggle name="notify" value="yes"></db-toggle>
157
+ <db-select name="lang" options='[{"value":"ko","label":"한국어"},{"value":"en","label":"English"}]'></db-select>
158
+ <button type="submit">저장</button>
159
+ </form>
160
+ ```
161
+
162
+ ```ts
163
+ document.getElementById('settings-form').addEventListener('submit', e => {
164
+ const data = new FormData(e.target);
165
+ // data.get('notify') → 'yes' (토글이 켜진 경우)
166
+ // data.get('lang') → 'ko'
167
+ });
168
+
169
+ // form.reset() 시 자동 초기화
170
+ // form disabled 시 자동 비활성화
171
+ ```
172
+
173
+ `db-input`과 `db-textarea`는 내부 `<input>`/`<textarea>`가 Light DOM에 있어 기존에도 form 제출에 참여하며, 이번 업데이트로 host 엘리먼트에서 네이티브 `input`/`change` 이벤트도 발행합니다.
174
+
175
+ ```ts
176
+ // host 엘리먼트에서 네이티브 이벤트 수신 가능
177
+ document.querySelector('db-input').addEventListener('change', e => {
178
+ console.log(e.target.value); // e.target === <db-input>
179
+ });
180
+ document.querySelector('db-input').addEventListener('input', handler);
181
+ ```
182
+
183
+ ---
184
+
185
+ ## 컴포넌트 목록
186
+
187
+ > 현재 100개 이상의 컴포넌트를 제공합니다. 전체 목록은 [Storybook](#storybook)을 참고하세요.
188
+
189
+ ### 폼 / 입력
42
190
 
43
191
  | 태그 | 설명 |
44
192
  |------|------|
45
- | `db-button` | 버튼 |
46
- | `db-input` | 텍스트 입력 |
193
+ | `db-button` | 버튼 (variant, size, loading, icon 지원) |
194
+ | `db-input` | 텍스트 입력 (password, search, number scrub 지원) |
195
+ | `db-textarea` | 여러 줄 텍스트 입력 |
196
+ | `db-select` | 드롭다운 선택 (단일/다중, 검색 지원) |
47
197
  | `db-checkbox` | 체크박스 |
48
- | `db-toggle` | 토글 |
49
- | `db-badge` | 뱃지 |
198
+ | `db-toggle` | 토글 스위치 |
199
+ | `db-radio` | 라디오 버튼 |
200
+ | `db-range-slider` | 범위 슬라이더 |
201
+ | `db-rating` | 별점 입력 |
202
+ | `db-color-picker` | 색상 선택기 |
203
+ | `db-date-picker` | 날짜 선택 |
204
+ | `db-time-picker` | 시간 선택 |
205
+ | `db-search-bar` | 검색 바 |
206
+ | `db-form` | 폼 컨테이너 |
207
+
208
+ ### 피드백 / 오버레이
209
+
210
+ | 태그 | 설명 |
211
+ |------|------|
212
+ | `db-modal` | 모달 다이얼로그 |
213
+ | `db-confirm` | 확인 다이얼로그 |
214
+ | `db-toast` | 토스트 알림 |
215
+ | `db-tooltip` | 툴팁 |
216
+ | `db-popover` | 팝오버 |
217
+ | `db-drawer` | 사이드 드로어 |
218
+ | `db-bottom-sheet` | 하단 시트 |
219
+ | `db-alert` | 인라인 알림 |
220
+ | `db-banner` | 배너 |
221
+ | `db-backdrop` | 배경 오버레이 |
50
222
  | `db-spinner` | 로딩 스피너 |
51
- | `db-card` | 카드 |
223
+ | `db-skeleton` | 스켈레톤 로더 |
224
+
225
+ ### 탐색
226
+
227
+ | 태그 | 설명 |
228
+ |------|------|
52
229
  | `db-tabs` | 탭 |
53
- | `db-modal` | 모달 (`<dialog>`) |
54
- | `db-dropdown` | 드롭다운 |
55
- | `db-tooltip` | 툴팁 |
230
+ | `db-navbar` | 상단 네비게이션 |
231
+ | `db-sidebar` | 사이드바 |
232
+ | `db-bottom-navigation` | 하단 탭 네비게이션 |
233
+ | `db-breadcrumbs` | 브레드크럼 |
234
+ | `db-pagination` | 페이지네이션 |
235
+ | `db-page-header` | 페이지 헤더 |
236
+ | `db-segment-control` | 세그먼트 컨트롤 |
237
+ | `db-stepper` | 단계 진행 |
238
+ | `db-progress-step` | 프로그레스 스텝 |
56
239
 
57
- ## 이벤트
240
+ ### 데이터 표시
58
241
 
59
- 커스텀 이벤트는 `db-` 접두사를 사용합니다.
242
+ | 태그 | 설명 |
243
+ |------|------|
244
+ | `db-table` | 테이블 |
245
+ | `db-card` | 카드 |
246
+ | `db-badge` | 뱃지 |
247
+ | `db-chip` | 칩 |
248
+ | `db-avatar` | 아바타 |
249
+ | `db-stat` | 통계 수치 |
250
+ | `db-timeline` | 타임라인 |
251
+ | `db-list` | 리스트 |
252
+ | `db-empty-state` | 빈 상태 |
253
+ | `db-progress` | 진행률 바 |
254
+ | `db-progressbar` | 게이지형 진행바 |
255
+ | `db-indicator` | 단계 표시기 |
256
+ | `db-countdown` | 카운트다운 |
60
257
 
61
- - `db-click` — Button
62
- - `db-input` — Input (`detail.value`)
63
- - `db-change` — Checkbox, Toggle, Tabs, Dropdown
64
- - `db-close` — Modal
258
+ ### 레이아웃
65
259
 
66
- ## 스타일
260
+ | 태그 | 설명 |
261
+ |------|------|
262
+ | `db-container` | 콘텐츠 컨테이너 |
263
+ | `db-stack` | 수직/수평 스택 |
264
+ | `db-grid` · `db-grid-item` | 그리드 레이아웃 |
265
+ | `db-divider` | 구분선 |
266
+ | `db-scroll-area` | 스크롤 영역 |
267
+ | `db-split-view` | 분할 뷰 |
268
+ | `db-resizable-panels` | 크기 조절 패널 |
269
+ | `db-masonry` | 메이슨리 레이아웃 |
270
+ | `db-toolbar` | 툴바 |
271
+ | `db-section` | 섹션 래퍼 |
67
272
 
68
- Light DOM + 글로벌 `--db-*` CSS 변수. 자세한 내용은 [docs/STYLING.md](./docs/STYLING.md).
273
+ ### 미디어
274
+
275
+ | 태그 | 설명 |
276
+ |------|------|
277
+ | `db-image` | 이미지 (lazy load, fallback) |
278
+ | `db-image-list` | 이미지 목록 |
279
+ | `db-lightbox` | 라이트박스 |
280
+ | `db-carousel` | 캐러셀 슬라이더 |
281
+ | `db-video-player` | 비디오 플레이어 |
282
+ | `db-youtube-player` | 유튜브 플레이어 |
283
+ | `db-audio-player` | 오디오 플레이어 |
284
+ | `db-lottie` | Lottie 애니메이션 |
285
+
286
+ ### 기타
287
+
288
+ | 태그 | 설명 |
289
+ |------|------|
290
+ | `db-accordion` | 아코디언 |
291
+ | `db-dropdown` | 드롭다운 메뉴 |
292
+ | `db-context-menu` | 컨텍스트 메뉴 |
293
+ | `db-menu-item` | 메뉴 아이템 |
294
+ | `db-reorder` | 드래그 정렬 |
295
+ | `db-dropzone` | 파일 드롭존 |
296
+ | `db-file-uploader` | 파일 업로더 |
297
+ | `db-code-block` | 코드 블록 |
298
+ | `db-markdown-editor` | 마크다운 에디터 |
299
+ | `db-tutorial` | 온보딩 튜토리얼 |
300
+ | `db-calendar` | 달력 |
301
+ | `db-share` | 공유 버튼 |
302
+ | `db-floating-action-button` | FAB |
303
+ | `db-top-banner` | 최상단 배너 |
304
+ | `db-onboarding-modal` | 온보딩 모달 |
305
+ | `db-label` | 레이블 |
306
+ | `db-logo` | 로고 |
307
+ | `db-gradient` | 그라디언트 배경 |
308
+ | `db-marquee` | 마르키 스크롤 |
309
+ | `db-animation-text` | 텍스트 애니메이션 |
310
+ | `db-animation-background` | 배경 애니메이션 |
311
+ | `db-cursor-follower` | 커서 팔로워 |
312
+ | `db-section-hero` | 히어로 섹션 |
313
+ | `db-section-feature` | 피처 섹션 |
314
+ | `db-section-contact` | 문의 섹션 |
315
+ | `db-section-app-download` | 앱 다운로드 섹션 |
316
+ | `db-app-badge` | 앱스토어/구글플레이 뱃지 |
317
+ | `db-ad-banner` | 광고 배너 |
318
+ | `db-testimonial` | 추천사 |
319
+
320
+ ---
321
+
322
+ ## 주요 이벤트
323
+
324
+ 모든 커스텀 이벤트는 `db-` 접두사를 사용하며 `bubbles: true, composed: true`로 발행됩니다.
325
+
326
+ | 이벤트 | 발행 컴포넌트 | `detail` |
327
+ |--------|-------------|---------|
328
+ | `db-click` | `db-button` | — |
329
+ | `db-input` | `db-input`, `db-textarea` | `{ value: string }` |
330
+ | `db-change` | `db-input`, `db-textarea`, `db-select`, `db-checkbox`, `db-toggle`, `db-radio`, `db-range-slider`, `db-rating`, `db-tabs`, … | `{ value }` 또는 `{ checked }` |
331
+ | `db-focus` / `db-blur` | `db-input`, `db-textarea` | — |
332
+ | `db-open` / `db-close` | `db-modal`, `db-drawer`, `db-bottom-sheet`, `db-toast`, … | — |
333
+ | `db-confirm` / `db-cancel` | `db-confirm` | — |
334
+ | `db-step-change` | `db-tutorial` | `{ step: number }` |
335
+ | `db-page-change` | `db-pagination` | `{ page: number }` |
336
+ | `db-sort` | `db-table` | `{ column, direction }` |
337
+ | `db-select` | `db-table` | `{ selectedRows }` |
338
+
339
+ `db-input`, `db-textarea`는 네이티브 `input` / `change` 이벤트도 host에서 함께 발행합니다.
340
+
341
+ ---
342
+
343
+ ## 스타일 커스터마이징
344
+
345
+ Light DOM 기반으로 렌더링되므로 CSS 선택자로 직접 스타일링할 수 있습니다.
346
+
347
+ ```css
348
+ /* 글로벌 CSS 변수로 테마 조정 */
349
+ :root {
350
+ --db-color-primary: #6366f1;
351
+ --db-radius-m: 8px;
352
+ }
353
+
354
+ /* 또는 컴포넌트 내부 클래스 직접 스타일링 */
355
+ db-button .designbase-wc-button {
356
+ font-weight: 700;
357
+ }
358
+ ```
359
+
360
+ 자세한 내용은 [docs/STYLING.md](./docs/STYLING.md).
361
+
362
+ ---
69
363
 
70
364
  ## 프레임워크별 가이드
71
365
 
72
366
  - [멀티플랫폼 가이드](../../docs/MULTI-PLATFORM-GUIDE.md)
73
- - [WordPress 관리자 연동](../../docs/WORDPRESS-INTEGRATION.md)
74
- - [크로스플랫폼 컴포넌트 전략](../../docs/CROSS_PLATFORM_COMPONENT_STRATEGY.md)
75
367
  - [React 통합](../../docs/REACT-WC-INTEGRATION.md)
76
368
  - [Vue / Angular 통합](../../docs/VUE-ANGULAR-INTEGRATION.md)
369
+ - [WordPress 관리자 연동](../../docs/WORDPRESS-INTEGRATION.md)
370
+ - [크로스플랫폼 컴포넌트 전략](../../docs/CROSS_PLATFORM_COMPONENT_STRATEGY.md)
77
371
 
78
372
  ## Storybook
79
373
 
80
374
  ```bash
81
375
  npm run storybook
376
+ # http://localhost:6007
82
377
  ```
83
-
84
- 포트: `6007`
@@ -0,0 +1 @@
1
+ import{drawFallingParticles as e,drawStars as t,drawParticles as s}from"./renderers.js";const i=["snow","flowers","confetti"];class CanvasAnimationController{constructor(n,a){this.options=a,this.raf=0,this.frameCount=0,this.mouse={x:-9999,y:-9999},this.particlesRef={current:[]},this.starsRef={current:[]},this.fallingRef={current:[]},this.tick=()=>{const n=this.canvas.getContext("2d");if(!n)return void(this.raf=requestAnimationFrame(this.tick));const a=window.devicePixelRatio||1,o=this.canvas.width/a,r=this.canvas.height/a,{type:c,colors:h,speed:l,particleCount:u,particleSize:v,starCount:m,starSize:d,clickable:f,wind:p,layerOpacity:w}=this.options;n.clearRect(0,0,o,r);const g=this.frameCount*(3e3/(l||3e3));switch(this.frameCount+=1,c){case"particles":s(n,o,r,this.particlesRef,{count:u,colors:h,size:v,mouse:this.mouse,clickable:f});break;case"stars":t(n,o,r,this.starsRef,{count:m,colors:h,size:d,time:g});break;case"snow":case"flowers":case"confetti":(function isFallingType(e){return i.includes(e)})(c)&&e(n,o,r,this.fallingRef,c,{count:u,colors:h,size:v,speed:l,wind:p,layerOpacity:w})}this.raf=requestAnimationFrame(this.tick)},this.container=n,this.canvas=document.createElement("canvas"),this.canvas.className="designbase-wc-animation-background__canvas",n.appendChild(this.canvas),this.onResize=()=>this.resize(),this.onMouseMove=e=>{if("particles"!==a.type)return;const t=n.getBoundingClientRect();this.mouse={x:e.clientX-t.left,y:e.clientY-t.top}},this.onMouseLeave=()=>{this.mouse={x:-9999,y:-9999}},n.addEventListener("mousemove",this.onMouseMove),n.addEventListener("mouseleave",this.onMouseLeave),window.addEventListener("resize",this.onResize),this.particlesRef.current=[],this.starsRef.current=[],this.fallingRef.current=[],this.frameCount=0,this.resize(),this.tick()}destroy(){cancelAnimationFrame(this.raf),this.container.removeEventListener("mousemove",this.onMouseMove),this.container.removeEventListener("mouseleave",this.onMouseLeave),window.removeEventListener("resize",this.onResize),this.canvas.remove()}resize(){const e=window.devicePixelRatio||1,t=this.container.getBoundingClientRect();this.canvas.width=t.width*e,this.canvas.height=t.height*e,this.canvas.style.width=`${t.width}px`,this.canvas.style.height=`${t.height}px`;const s=this.canvas.getContext("2d");s&&s.setTransform(e,0,0,e,0,0)}}export{CanvasAnimationController};
@@ -0,0 +1 @@
1
+ import{isLuminaType as e,FLUID_DEFAULT_COLORS as t,padColors as a,LUMINA_NOISE_SVG as r,LUMINA_ANIMATION_DURATION_SEC as n,toLuminaSpeed as i}from"./lumina-utils.js";import{getLuminaPresetColors as s}from"./lumina-presets.js";import{getFallingParticleDefaults as o}from"./particle-defaults.js";import{CanvasAnimationController as l}from"./canvas-controller.js";import{ShaderAnimationController as d}from"./shader-controller.js";const m="designbase-wc-animation-background";function parseColors(e,t){if(!e)return t;try{const a=JSON.parse(e);return Array.isArray(a)&&a.length?a:t}catch{return e.split(",").map(e=>e.trim()).filter(Boolean)}}function parseAnimationBackgroundConfig(e){return{type:e.getAttribute("type")||"gradient",theme:"light"===e.getAttribute("theme")?"light":"dark",intensity:e.getAttribute("intensity")||"subtle",blur:Number(e.getAttribute("blur")||80),speed:Number(e.getAttribute("speed")||3e3),direction:e.getAttribute("direction")||"left",colors:parseColors(e.getAttribute("colors"),["#667eea","#764ba2","#f093fb"]),opacity:Number(e.getAttribute("opacity")||1),particleCount:Number(e.getAttribute("particle-count")||50),particleSize:Number(e.getAttribute("particle-size")||2),starCount:Number(e.getAttribute("star-count")||100),starSize:Number(e.getAttribute("star-size")||1.5),clickable:e.hasAttribute("clickable")&&"false"!==e.getAttribute("clickable"),wind:Number(e.getAttribute("wind")||.5),showGrid:e.hasAttribute("show-grid")&&"false"!==e.getAttribute("show-grid"),gridSize:Number(e.getAttribute("grid-size")||40),gridColor:e.getAttribute("grid-color")||void 0,gridOpacity:Number(e.getAttribute("grid-opacity")||.1),noise:Number(e.getAttribute("noise")||.05),showVignette:!e.hasAttribute("show-vignette")||"false"!==e.getAttribute("show-vignette"),preset:e.getAttribute("preset")||void 0,zoom:Number(e.getAttribute("zoom")||1),disabled:e.hasAttribute("disabled")&&"false"!==e.getAttribute("disabled")}}function createLuminaOverlays(e,t){const a=document.createDocumentFragment();if(e>0){const t=document.createElement("div");t.className=`${m}__lumina-noise`,t.style.backgroundImage=`url("${r}")`,t.style.opacity=String(e),a.appendChild(t)}if(t){const e=document.createElement("div");e.className=`${m}__lumina-vignette`,a.appendChild(e)}return a}function mountAnimationLayers(e,r){const u=function resolveColors(e){const{type:a,preset:r,colors:n}=e;if(r)return s(r);if("fluid"===a&&n.length<5)return t;if("snow"===a||"flowers"===a||"confetti"===a){const e=o(a);return 3===n.length&&"#667eea"===n[0]&&"#764ba2"===n[1]?e:n}return n}(r);let g={};if(r.disabled)return g;switch(r.type){case"particles":case"stars":case"snow":case"flowers":case"confetti":{const t=document.createElement("div");t.className=`${m}__canvas-layer`,e.appendChild(t);const a=new l(t,{type:r.type,colors:u,speed:r.speed,particleCount:r.particleCount,particleSize:r.particleSize,starCount:r.starCount,starSize:r.starSize,clickable:r.clickable,wind:r.wind,layerOpacity:r.opacity});g={destroy:()=>a.destroy()};break}case"aurora":e.appendChild(function createMeshAuroraLayer(e,t,a,r,n){const i=document.createElement("div");i.className=`${m}__aurora-mesh`;const s="subtle"===r?.3:"medium"===r?.6:.8,o=Math.max(5,t/1e3),l=e.length>=3?e:["#4f46e5","#ec4899","#06b6d4","#8b5cf6"],d="dark"===n?"screen":"multiply",u=`blur(${a}px)`,g=`${m}__aurora-blob`,p=[{backgroundColor:l[0],top:"-10%",left:"-10%",animationDuration:`${o}s`,animationDelay:"0s"},{backgroundColor:l[1],top:"-10%",right:"-10%",animationDuration:1.2*o+"s",animationDelay:"2s"},{backgroundColor:l[2],bottom:"-20%",left:"20%",animationDuration:1.5*o+"s",animationDelay:"4s"}];l[3]&&p.push({backgroundColor:l[3],bottom:"-10%",right:"-10%",animationDuration:1.1*o+"s",animationDelay:"1s"}),p.forEach(e=>{const t=document.createElement("div");t.className=g,Object.assign(t.style,{filter:u,opacity:String(s),mixBlendMode:d,...e}),i.appendChild(t)});const b=document.createElement("div");return b.className=`${m}__aurora-noise`,b.style.opacity="dark"===n?"0.03":"0.05",b.style.backgroundImage="url(\"data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E\")",i.appendChild(b),i}(u,r.speed,r.blur,r.intensity,r.theme));break;case"plasma":e.appendChild(function createPlasmaLayer(e,t,r){const s=document.createElement("div");s.className=`${m}__plasma`;const o=Math.random().toString(36).slice(2,11),l=a(e),c=e=>l[e%l.length],d=i(t),u=n/d,g=document.createElement("style");g.textContent=`\n @keyframes designbase-wc-plasma-move-1-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1); }\n 25% { transform: translate(10%, 10%) rotate(90deg) scale(1.2); }\n 50% { transform: translate(0, 20%) rotate(180deg) scale(1); }\n 75% { transform: translate(-10%, 10%) rotate(270deg) scale(0.9); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1); }\n }\n @keyframes designbase-wc-plasma-move-2-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1.2); }\n 33% { transform: translate(-20%, 0) rotate(120deg) scale(1); }\n 66% { transform: translate(20%, -10%) rotate(240deg) scale(0.8); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1.2); }\n }\n @keyframes designbase-wc-plasma-move-3-${o} {\n 0% { transform: translate(0, 0) scale(0.8); }\n 50% { transform: translate(15%, -15%) scale(1.4); }\n 100% { transform: translate(0, 0) scale(0.8); }\n }\n @keyframes designbase-wc-plasma-rotate-${o} {\n 0% { transform: rotate(0deg) scale(1.5); }\n 50% { transform: rotate(180deg) scale(2.0); }\n 100% { transform: rotate(360deg) scale(1.5); }\n }`,s.appendChild(g);const p=document.createElement("div");return p.className=`${m}__plasma-base`,p.style.backgroundColor=c(0),s.appendChild(p),[{top:"-10%",left:"-10%",width:"70%",height:"70%",background:`radial-gradient(circle, ${c(1)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-1-${o} ${u}s infinite linear`},{bottom:"-20%",right:"-10%",width:"80%",height:"80%",background:`radial-gradient(circle, ${c(2)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-2-${o} ${u}s infinite linear`},{top:"20%",left:"20%",width:"60%",height:"60%",background:`radial-gradient(circle, ${c(3)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-rotate-${o} ${u}s infinite linear`,extraClass:`${m}__plasma-blob--exclusion`},{top:"40%",right:"20%",width:"40%",height:"40%",background:c(4),animation:`designbase-wc-plasma-move-3-${o} ${u}s infinite ease-in-out`,extraClass:`${m}__plasma-blob--accent`,filter:`blur(${r}px)`,opacity:"0.6"}].forEach(e=>{const t=document.createElement("div");t.className=`${m}__plasma-blob${e.extraClass?` ${e.extraClass}`:""}`,Object.assign(t.style,{filter:e.filter||`blur(${r}px)`,opacity:e.opacity||"0.9",...e}),s.appendChild(t)}),s}(u,r.speed,r.blur)),e.appendChild(createLuminaOverlays(r.noise,r.showVignette));break;case"mesh-flow":case"fluid":case"radiant":case"ethereal":{const t=document.createElement("div");t.className=`${m}__shader-layer`,e.appendChild(t);const a=new d(t,{variant:r.type,colors:u,speed:r.speed,blur:r.blur,noise:r.noise,zoom:r.zoom});e.appendChild(createLuminaOverlays(r.noise,r.showVignette)),g={destroy:()=>a.destroy()};break}case"gradient":e.appendChild(function createGradientLayer(e,t,a){const r=document.createDocumentFragment(),n=document.createElement("style");n.textContent="@keyframes designbase-wc-gradient-move {\n 0% { background-position: 0% 50%; }\n 50% { background-position: 100% 50%; }\n 100% { background-position: 0% 50%; }\n }",r.appendChild(n);const i=document.createElement("div");i.className=`${m}__css-layer`;const s=(t.length>0?t:["#ccc"]).join(", ");let o="90deg",l="";switch(e){case"up":o="0deg";break;case"down":o="180deg";break;case"left":o="270deg";break;case"right":o="90deg";break;case"diagonal":o="45deg";break;case"radial":l=`radial-gradient(circle, ${s})`}l||(l=`linear-gradient(${o}, ${s})`);const d=`${Math.max(2,a/1e3)}s`;return i.style.backgroundImage=l,i.style.backgroundSize="200% 200%",i.style.animation=`designbase-wc-gradient-move ${d} ease infinite`,r.appendChild(i),r}(r.direction,u,r.speed))}return g}function applyContainerStyles(t,a){const r=e(a.type)?"#000000":"dark"===a.theme?"var(--db-surface-base, #0f172a)":"var(--db-surface-base, #ffffff)";t.style.position="relative",t.style.overflow="hidden","gradient"!==a.type?t.style.backgroundColor=r:t.style.backgroundColor=""}function getEffectiveGridColor(e){return e.gridColor??("dark"===e.theme?"#ffffff":"#000000")}export{m as ANIMATION_BACKGROUND_CLASS,applyContainerStyles,getEffectiveGridColor,mountAnimationLayers,parseAnimationBackgroundConfig};
@@ -0,0 +1 @@
1
+ const F=[{id:"neon_dream",name:"Neon Dream",colors:["#7000FF","#FF00AA","#3300FF","#FFCC00","#00FFFF"]},{id:"sunset_bliss",name:"Sunset Bliss",colors:["#FF9900","#FF00CC","#6600FF","#FF5500","#220055"]},{id:"deep_ocean",name:"Deep Ocean",colors:["#001133","#0044FF","#00DDFF","#00FFAA","#000066"]},{id:"forest_mist",name:"Forest Mist",colors:["#002200","#00FF44","#AAFF00","#006622","#CCFFCC"]},{id:"northern_lights",name:"Northern Lights",colors:["#000000","#00FF99","#AA00FF","#0044FF","#FFFFFF"]},{id:"monochrome_fog",name:"Monochrome Fog",colors:["#000000","#333333","#888888","#CCCCCC","#FFFFFF"]},{id:"cotton_candy",name:"Cotton Candy",colors:["#FFC0CB","#87CEFA","#E0FFFF","#DDA0DD","#FF69B4"]},{id:"cyber_glitch",name:"Cyber Glitch",colors:["#1A1A1D","#C3073F","#6F2232","#950740","#4E4E50"]},{id:"golden_hour",name:"Golden Hour",colors:["#FF4E50","#FC913A","#F9D423","#EDE574","#E1F5C4"]}];function getLuminaPresetColors(o){const e=F.find(F=>F.id===o);return e?.colors??F[0].colors}export{F as LUMINA_COLOR_PRESETS,getLuminaPresetColors};
@@ -0,0 +1 @@
1
+ const o="\n attribute vec4 aVertexPosition;\n void main() {\n gl_Position = aVertexPosition;\n }\n";function getLuminaFragmentShader(o){switch(o){case"mesh-flow":return"\n precision highp float;\n uniform vec2 uResolution;\n uniform float uTime;\n uniform vec3 uColors[5];\n uniform float uSpeed;\n uniform float uSoftness;\n void main() {\n vec2 uv = gl_FragCoord.xy / uResolution.xy;\n float aspect = uResolution.x / uResolution.y;\n vec2 p = uv;\n p.x *= aspect;\n float t = uTime * uSpeed * 0.1;\n vec3 col = mix(uColors[0], uColors[4], uv.y * 0.6 + 0.2);\n for(int i = 1; i < 4; i++) {\n float fi = float(i);\n float offset = fi * 4.0;\n vec2 q = p;\n q.x += sin(q.y * 1.5 + t + offset) * 0.2;\n q.y += cos(q.x * 0.8 - t + offset) * 0.1;\n float waveCenterY = 0.5 + 0.3 * sin(q.x * 1.0 + t * 0.8 + offset);\n float thickness = 0.15 + 0.15 * sin(q.x * 2.5 + t * 1.2 + offset);\n float w = thickness * (1.0 + uSoftness * 3.0);\n float dist = abs(q.y - waveCenterY);\n float blurAmount = 0.1 + uSoftness * 0.4;\n float intensity = smoothstep(w + blurAmount, w - blurAmount, dist);\n intensity *= 0.7;\n vec3 bandColor = uColors[i];\n bandColor = mix(bandColor, uColors[i+1], sin(p.x + t)*0.2 + 0.2);\n col = mix(col, bandColor, intensity);\n }\n float noise = fract(sin(dot(gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453);\n col += (noise - 0.5) * 0.03;\n gl_FragColor = vec4(col, 1.0);\n }\n";case"radiant":return"\n precision highp float;\n uniform vec2 uResolution;\n uniform float uTime;\n uniform vec3 uColors[5];\n uniform float uNoiseStrength;\n uniform float uSoftness;\n float random(vec2 st) {\n return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);\n }\n void main() {\n vec2 uv = gl_FragCoord.xy / uResolution.xy;\n float aspect = uResolution.x / uResolution.y;\n uv.x *= aspect;\n float t = uTime * 0.15;\n vec3 col = uColors[0];\n for(int i = 1; i < 5; i++) {\n float fi = float(i);\n vec2 pos = vec2(\n 0.5 * aspect + 0.4 * sin(t * (0.5 + fi * 0.2) + fi * 1.5),\n 0.5 + 0.4 * cos(t * (0.4 + fi * 0.15) + fi)\n );\n float d = length(uv - pos);\n float radius = 0.6 + uSoftness * 1.0;\n float intensity = smoothstep(radius, 0.0, d);\n col = mix(col, uColors[i], intensity * 0.7);\n }\n float grain = random(gl_FragCoord.xy + uTime);\n col += (grain - 0.5) * uNoiseStrength;\n gl_FragColor = vec4(col, 1.0);\n }\n";case"ethereal":return"\n precision highp float;\n uniform vec2 uResolution;\n uniform float uTime;\n uniform vec3 uColors[5];\n uniform float uNoiseStrength;\n uniform float uSoftness;\n float random (in vec2 st) {\n return fract(sin(dot(st.xy, vec2(12.9898,78.233)))*43758.5453123);\n }\n float noise (in vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n vec2 u = f*f*(3.0-2.0*f);\n return mix( mix( random( i + vec2(0.0,0.0) ),\n random( i + vec2(1.0,0.0) ), u.x),\n mix( random( i + vec2(0.0,1.0) ),\n random( i + vec2(1.0,1.0) ), u.x), u.y);\n }\n #define OCTAVES 5\n float fbm (in vec2 st) {\n float value = 0.0;\n float amplitude = 0.5;\n for (int i = 0; i < OCTAVES; i++) {\n value += amplitude * noise(st);\n st *= 2.0;\n amplitude *= 0.5;\n }\n return value;\n }\n void main() {\n vec2 uv = gl_FragCoord.xy/uResolution.xy;\n float aspect = uResolution.x/uResolution.y;\n uv.x *= aspect;\n float t = uTime * 0.05;\n float scale = 5.0 - uSoftness * 3.0;\n vec2 st = uv * scale;\n vec2 q = vec2(0.);\n q.x = fbm( st + 0.00*t );\n q.y = fbm( st + vec2(1.0) );\n vec2 r = vec2(0.);\n r.x = fbm( st + 1.0*q + vec2(1.7,9.2)+ 0.15*t );\n r.y = fbm( st + 1.0*q + vec2(8.3,2.8)+ 0.126*t );\n float f = fbm(st + r);\n vec3 color = mix(uColors[0], uColors[1], clamp((f*f)*4.0,0.0,1.0));\n color = mix(color, uColors[2], clamp(length(q),0.0,1.0));\n color = mix(color, uColors[3], clamp(length(r.x),0.0,1.0));\n color = mix(color, uColors[4], clamp(r.y*r.y, 0.0, 1.0));\n float grain = random(gl_FragCoord.xy + uTime);\n color += (grain - 0.5) * uNoiseStrength;\n gl_FragColor = vec4(color,1.0);\n }\n";default:return"\n precision highp float;\n uniform vec2 uResolution;\n uniform float uTime;\n uniform vec3 uColors[5];\n uniform float uNoiseStrength;\n uniform float uSoftness;\n uniform float uZoom;\n float random(vec2 st) {\n return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);\n }\n void main() {\n vec2 uv = (gl_FragCoord.xy - 0.5 * uResolution.xy) / min(uResolution.y, uResolution.x);\n float t = uTime * 0.2;\n float scale = mix(1.8, 0.45, uSoftness) / max(0.25, uZoom);\n vec2 p = uv * scale;\n for(float i = 1.0; i <= 4.0; i++){\n p.x += 0.6 / i * sin(i * 3.0 * p.y + t);\n p.y += 0.6 / i * cos(i * 3.0 * p.x + t);\n }\n float w1 = 0.5 + 0.5 * sin(p.x + t);\n float w2 = 0.5 + 0.5 * sin(p.y + t * 0.8);\n float w3 = 0.5 + 0.5 * sin(p.x + p.y);\n vec3 col = uColors[0];\n col = mix(col, uColors[1], smoothstep(0.1, 0.9, w1));\n col = mix(col, uColors[2], smoothstep(0.1, 0.9, w2));\n col = mix(col, uColors[3], smoothstep(0.1, 0.9, w3));\n float w4 = w1 * w2 * w3;\n col = mix(col, uColors[4], w4);\n float grain = random(gl_FragCoord.xy + uTime);\n col += (grain - 0.5) * uNoiseStrength;\n gl_FragColor = vec4(col, 1.0);\n }\n"}}export{o as VS_SOURCE,getLuminaFragmentShader};
@@ -0,0 +1 @@
1
+ const e=60,t=["plasma","mesh-flow","fluid","radiant","ethereal"];function isLuminaType(e){return t.includes(e)}function toLuminaSpeed(e){return Math.max(.1,e/3e3)}function toLuminaSoftness(e){return Math.min(1,e/200)}function clampZoom(e){return Math.min(4,Math.max(.25,e))}function hexToRgb(e){const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?[parseInt(t[1],16)/255,parseInt(t[2],16)/255,parseInt(t[3],16)/255]:[0,0,0]}function padColors(e,t=5){return 0===e.length?["#7000FF","#FF00AA","#3300FF","#FFCC00","#00FFFF"]:Array.from({length:t},(t,n)=>e[n%e.length])}const n=["#0d0221","#5b21b6","#db2777","#38bdf8","#e9d5ff"],i="data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='1'/%3E%3C/svg%3E";export{n as FLUID_DEFAULT_COLORS,e as LUMINA_ANIMATION_DURATION_SEC,t as LUMINA_ANIMATION_TYPES,i as LUMINA_NOISE_SVG,clampZoom,hexToRgb,isLuminaType,padColors,toLuminaSoftness,toLuminaSpeed};
@@ -0,0 +1 @@
1
+ const f=["#ffffff","#f0f9ff","#e0f2fe"],e=["#ffb7c5","#ff91a4","#f8c8dc","#ffc0cb","#fda4af"],c=["#f44336","#e91e63","#9c27b0","#673ab7","#3f51b5","#2196f3","#03a9f4","#00bcd4","#4caf50","#ffeb3b","#ffc107","#ff9800"];function getFallingParticleDefaults(a){switch(a){case"snow":default:return f;case"flowers":return e;case"confetti":return c}}export{c as CONFETTI_DEFAULT_COLORS,e as FLOWERS_DEFAULT_COLORS,f as SNOW_DEFAULT_COLORS,getFallingParticleDefaults};
@@ -0,0 +1 @@
1
+ function createFallingParticle(a,o,t,e=!1){return{x:Math.random()*a,y:e?Math.random()*o:-20,size:Math.random()*(t.maxSize-t.minSize)+t.minSize,speedX:(Math.random()-.5)*t.wind,speedY:Math.random()*(t.maxSpeedY-t.minSpeedY)+t.minSpeedY,opacity:.5*Math.random()+.3,rotation:Math.random()*Math.PI*2,rotationSpeed:.05*(Math.random()-.5),color:t.colors[Math.floor(Math.random()*t.colors.length)]}}const drawFallingParticles=(a,o,t,e,r,n)=>{const l=3e3/(n.speed||3e3),i=Math.max(1,.5*n.size),c={minSize:i,maxSize:Math.max(i+.5,1.5*n.size),minSpeedY:.4*l,maxSpeedY:1.2*l,wind:n.wind*l,colors:n.colors};e.current.length!==n.count&&(e.current=Array.from({length:n.count},()=>createFallingParticle(o,t,c,!0))),e.current.forEach(e=>{e.y+=e.speedY,e.x+=e.speedX+.5*Math.sin(e.y/50)*l,e.rotation+=e.rotationSpeed,e.y>t+20&&Object.assign(e,createFallingParticle(o,t,c)),e.x>o+20&&(e.x=-20),e.x<-20&&(e.x=o+20),a.save(),a.translate(e.x,e.y),a.rotate(e.rotation),a.fillStyle=e.color,a.globalAlpha=e.opacity*n.layerOpacity,function drawFallingParticleShape(a,o,t){return"snow"===o?(a.beginPath(),a.arc(0,0,t,0,2*Math.PI),void a.fill()):"flowers"===o?(a.beginPath(),a.moveTo(0,0),a.bezierCurveTo(t,-t,2*t,t,0,2*t),a.bezierCurveTo(2*-t,t,-t,-t,0,0),void a.fill()):void a.fillRect(-t/2,-t/2,t,t)}(a,r,e.size),a.restore()}),a.globalAlpha=1},drawParticles=(a,o,t,e,r)=>{e.current.length!==r.count&&(e.current=Array.from({length:r.count}).map(()=>({x:Math.random()*o,y:Math.random()*t,vx:1.5*(Math.random()-.5),vy:1.5*(Math.random()-.5),size:Math.random()*r.size+1,color:r.colors[Math.floor(Math.random()*r.colors.length)]})));const n=e.current;n.forEach((e,l)=>{if(e.x+=e.vx,e.y+=e.vy,(e.x<0||e.x>o)&&(e.vx*=-1),(e.y<0||e.y>t)&&(e.vy*=-1),r.clickable){const a=r.mouse.x-e.x,o=r.mouse.y-e.y,t=Math.sqrt(a*a+o*o);if(t<150){const r=(150-t)/150;e.vx+=a/t*r*.5,e.vy+=o/t*r*.5}const n=3,l=Math.sqrt(e.vx*e.vx+e.vy*e.vy);l>n&&(e.vx=e.vx/l*n,e.vy=e.vy/l*n)}a.beginPath(),a.arc(e.x,e.y,e.size,0,2*Math.PI),a.fillStyle=e.color,a.fill();for(let o=l+1;o<n.length;o++){const t=n[o],r=e.x-t.x,l=e.y-t.y,i=Math.sqrt(r*r+l*l);i<100&&(a.beginPath(),a.strokeStyle=e.color,a.globalAlpha=1-i/100,a.lineWidth=.5,a.moveTo(e.x,e.y),a.lineTo(t.x,t.y),a.stroke(),a.globalAlpha=1)}})},drawStars=(a,o,t,e,r)=>{e.current.length!==r.count&&(e.current=Array.from({length:r.count}).map(()=>({x:Math.random()*o,y:Math.random()*t,size:Math.random()*r.size,blinkSpeed:.05*Math.random()+.01,color:r.colors[Math.floor(Math.random()*r.colors.length)]}))),e.current.forEach(o=>{o.y-=.05,o.y<0&&(o.y=t);const e=.5+.5*Math.sin(r.time*o.blinkSpeed);a.beginPath(),a.arc(o.x,o.y,o.size,0,2*Math.PI),a.fillStyle=o.color,a.globalAlpha=e,a.fill(),a.globalAlpha=1})};export{drawFallingParticles,drawParticles,drawStars};
@@ -0,0 +1 @@
1
+ import{padColors as t,hexToRgb as e,toLuminaSpeed as r,toLuminaSoftness as i,clampZoom as a}from"./lumina-utils.js";import{VS_SOURCE as n,getLuminaFragmentShader as o}from"./lumina-shaders.js";function loadShader(t,e,r){const i=t.createShader(e);return i?(t.shaderSource(i,r),t.compileShader(i),t.getShaderParameter(i,t.COMPILE_STATUS)?i:(t.deleteShader(i),null)):null}class ShaderAnimationController{constructor(n,o){this.options=o,this.raf=0,this.startTime=performance.now(),this.render=()=>{const n=this.gl,o=this.program,s=this.positionBuffer;if(!n||!o||!s)return;const{colors:h,speed:f,blur:c,noise:m,zoom:d,variant:u}=this.options,{width:l,height:g}=this.resizeCanvas();if(0===l||0===g)return void(this.raf=requestAnimationFrame(this.render));n.viewport(0,0,l,g),n.useProgram(o);const v=n.getAttribLocation(o,"aVertexPosition"),S=n.getUniformLocation(o,"uResolution"),A=n.getUniformLocation(o,"uTime"),p=n.getUniformLocation(o,"uColors"),w=n.getUniformLocation(o,"uSpeed"),R=n.getUniformLocation(o,"uSoftness"),b=n.getUniformLocation(o,"uNoiseStrength"),T=n.getUniformLocation(o,"uZoom");n.enableVertexAttribArray(v),n.bindBuffer(n.ARRAY_BUFFER,s),n.vertexAttribPointer(v,2,n.FLOAT,!1,0,0),n.uniform2f(S,l,g);const x=t(h),F=r(f),B=i(c),L=.6*F,P=a(d),U=(performance.now()-this.startTime)/1e3;"mesh-flow"===u?(A&&n.uniform1f(A,U),w&&n.uniform1f(w,L),R&&n.uniform1f(R,B)):(A&&n.uniform1f(A,U*F),R&&n.uniform1f(R,B),b&&n.uniform1f(b,m),"fluid"===u&&T&&n.uniform1f(T,P));const C=new Float32Array(15);for(let t=0;t<5;t++){const r=e(x[t]);C[3*t]=r[0],C[3*t+1]=r[1],C[3*t+2]=r[2]}p&&n.uniform3fv(p,C),n.drawArrays(n.TRIANGLE_STRIP,0,4),this.raf=requestAnimationFrame(this.render)},this.container=n,this.canvas=document.createElement("canvas"),this.canvas.className="designbase-wc-animation-background__shader-canvas",n.appendChild(this.canvas),this.init()}resizeCanvas(){const t=this.container.getBoundingClientRect(),e=window.devicePixelRatio||1;return this.canvas.width=Math.max(1,t.width*e),this.canvas.height=Math.max(1,t.height*e),this.canvas.style.width=`${t.width}px`,this.canvas.style.height=`${t.height}px`,{width:this.canvas.width,height:this.canvas.height}}init(){const t=this.canvas.getContext("webgl");if(!t)return;this.gl=t;const{variant:e}=this.options,r=o(e),i=t.createProgram();if(!i)return;const a=loadShader(t,t.VERTEX_SHADER,n),s=loadShader(t,t.FRAGMENT_SHADER,r);if(!a||!s)return;if(t.attachShader(i,a),t.attachShader(i,s),t.linkProgram(i),!t.getProgramParameter(i,t.LINK_STATUS))return;this.program=i,this.vertexShader=a,this.fragmentShader=s;const h=t.createBuffer();h&&(this.positionBuffer=h,t.bindBuffer(t.ARRAY_BUFFER,h),t.bufferData(t.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),t.STATIC_DRAW),this.observer=new ResizeObserver(()=>this.resizeCanvas()),this.observer.observe(this.container),this.startTime=performance.now(),this.render())}destroy(){cancelAnimationFrame(this.raf),this.observer?.disconnect();const t=this.gl;t&&this.program&&(this.vertexShader&&t.deleteShader(this.vertexShader),this.fragmentShader&&t.deleteShader(this.fragmentShader),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),t.deleteProgram(this.program)),this.canvas.remove()}}export{ShaderAnimationController};
@@ -0,0 +1 @@
1
+ const clamp=(t,r,a)=>Math.max(r,Math.min(a,t)),normalizeHex=t=>{const r=(t||"").trim().toUpperCase();return r?r.startsWith("#")?r:`#${r}`:""},isHex=t=>/^#?[0-9A-Fa-f]{6}$/.test(t||""),hexToRgb=t=>{const r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t.trim());return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:null},toHex=(t,r,a)=>{const h=t=>clamp(Math.round(t),0,255).toString(16).padStart(2,"0");return`#${h(t)}${h(r)}${h(a)}`.toUpperCase()},rgbToHsv=(t,r,a)=>{t/=255,r/=255,a/=255;const e=Math.max(t,r,a),s=e-Math.min(t,r,a);let n=0;if(0!==s){switch(e){case t:n=(r-a)/s+(r<a?6:0);break;case r:n=(a-t)/s+2;break;case a:n=(t-r)/s+4}n*=60}return{h:n,s:100*(0===e?0:s/e),v:100*e}},hsvToRgb=(t,r,a)=>{const e=(a/=100)*(r/=100),s=e*(1-Math.abs(t/60%2-1)),n=a-e;let o=0,c=0,u=0;return t>=0&&t<60?(o=e,c=s,u=0):t<120?(o=s,c=e,u=0):t<180?(o=0,c=e,u=s):t<240?(o=0,c=s,u=e):t<300?(o=s,c=0,u=e):(o=e,c=0,u=s),{r:Math.round(255*(o+n)),g:Math.round(255*(c+n)),b:Math.round(255*(u+n))}},rgbToHsl=(t,r,a)=>{t/=255,r/=255,a/=255;const e=Math.max(t,r,a),s=Math.min(t,r,a);let n=0,o=0;const c=(e+s)/2;if(e!==s){const u=e-s;switch(o=c>.5?u/(2-e-s):u/(e+s),e){case t:n=(r-a)/u+(r<a?6:0);break;case r:n=(a-t)/u+2;break;case a:n=(t-r)/u+4}n*=60}return{h:n,s:100*o,l:100*c}},formatColor=(t,r,a,e,s)=>{const n=s/100;switch(t){case"hex":default:return a;case"rgb":return`rgb(${r.r}, ${r.g}, ${r.b})`;case"rgba":return`rgba(${r.r}, ${r.g}, ${r.b}, ${n.toFixed(2)})`;case"hsl":return`hsl(${Math.round(e.h)}, ${Math.round(e.s)}%, ${Math.round(e.l)}%)`;case"hsla":return`hsla(${Math.round(e.h)}, ${Math.round(e.s)}%, ${Math.round(e.l)}%, ${n.toFixed(2)})`}};export{clamp,formatColor,hexToRgb,hsvToRgb,isHex,normalizeHex,rgbToHsl,rgbToHsv,toHex};
@@ -0,0 +1 @@
1
+ const startOfDay=t=>{const e=new Date(t);return e.setHours(0,0,0,0),e},endOfDay=t=>{const e=new Date(t);return e.setHours(23,59,59,999),e},addDays=(t,e)=>{const n=new Date(t);return n.setDate(n.getDate()+e),startOfDay(n)},getMonthEnd=t=>endOfDay(new Date(t.getFullYear(),t.getMonth()+1,0)),getYearEnd=t=>endOfDay(new Date(t.getFullYear(),11,31)),clampRange=(t,e,n)=>{let{start:a,end:r}=t;return e&&a<e&&(a=startOfDay(e)),n&&r>n&&(r=endOfDay(n)),a>r?{start:r,end:a}:{start:a,end:r}},t=[{id:"today",label:"오늘",getRange:({today:t})=>clampRange({start:startOfDay(t),end:endOfDay(t)})},{id:"yesterday",label:"어제",getRange:({today:t})=>{const e=addDays(t,-1);return clampRange({start:e,end:endOfDay(e)})}},{id:"this-week",label:"이번 주",getRange:({today:t,startOfWeek:e,minDate:n,maxDate:a})=>{const r=((t,e)=>{const n=t.getDay();return addDays(t,-("monday"===e?(n+6)%7:n))})(t,e);return clampRange({start:r,end:(o=r,endOfDay(addDays(o,6)))},n,a);var o}},{id:"this-month",label:"이번 달",getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),a.getMonth(),1))),end:getMonthEnd(t)},e,n);var a}},{id:"this-year",label:"올해",getRange:({today:t,minDate:e,maxDate:n})=>{return clampRange({start:(a=t,startOfDay(new Date(a.getFullYear(),0,1))),end:getYearEnd(t)},e,n);var a}},{id:"custom",label:"사용자 지정",getRange:()=>null}],addMonths=(t,e)=>{const n=new Date(t);return n.setDate(1),n.setMonth(n.getMonth()+e),n},toISODate=t=>`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,parseISODate=t=>{if(!t)return null;const e=t.trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const n=new Date(Number(e[1]),Number(e[2])-1,Number(e[3]));return Number.isNaN(n.getTime())?null:startOfDay(n)},formatDisplayDate=(t,e="ko-KR")=>t.toLocaleDateString(e),generateWeekdays=t=>{const e=["일","월","화","수","목","금","토"];return"monday"===t&&e.push(e.shift()),e},generateCalendarGrid=(t,e,n=!1)=>{const a=t.getFullYear(),r=t.getMonth(),o=new Date(a,r,1),s="monday"===e?(o.getDay()+6)%7:o.getDay();if(n){const t=[];for(let e=0;e<s;e+=1)t.push(null);const e=new Date(a,r+1,0).getDate();for(let n=1;n<=e;n+=1)t.push(new Date(a,r,n));return t}const u=new Date(o);return u.setDate(u.getDate()-s),Array.from({length:42},(t,e)=>{const n=new Date(u);return n.setDate(u.getDate()+e),n})},detectActivePresetId=(t,e,n)=>{if(!t)return"custom";const a=t.start.toDateString(),r=t.end.toDateString();for(const t of e){if("custom"===t.id)continue;const e=t.getRange(n);if(e&&(e.start.toDateString()===a&&e.end.toDateString()===r))return t.id}return"custom"},formatPanelInputDate=(t,e)=>t?t.toLocaleDateString(e,{year:"numeric",month:"short",day:"numeric"}):"";export{t as DEFAULT_DATE_PICKER_PRESETS,addMonths,detectActivePresetId,endOfDay,formatDisplayDate,formatPanelInputDate,generateCalendarGrid,generateWeekdays,parseISODate,startOfDay,toISODate};
@@ -0,0 +1,40 @@
1
+ interface AccordionItemConfig {
2
+ id?: string;
3
+ title: string;
4
+ disabled?: boolean;
5
+ itemType?: 'icon' | 'number' | 'question' | 'none';
6
+ icon?: string;
7
+ }
8
+ declare class DbAccordion extends HTMLElement {
9
+ static get observedAttributes(): string[];
10
+ private expanded;
11
+ private isRendering;
12
+ private suppressExpandedAttrCallback;
13
+ private childObserver?;
14
+ get items(): AccordionItemConfig[];
15
+ set items(value: AccordionItemConfig[] | string);
16
+ get allowMultiple(): boolean;
17
+ set allowMultiple(value: boolean);
18
+ get expandedItems(): string[] | string;
19
+ set expandedItems(value: string[] | string);
20
+ connectedCallback(): void;
21
+ disconnectedCallback(): void;
22
+ attributeChangedCallback(name: string): void;
23
+ /** id와 index 문자열 충돌 방지 — 항목당 단일 키만 사용 */
24
+ private resolveItemKey;
25
+ private getExpandMode;
26
+ private syncExpandedFromAttributes;
27
+ private iconSize;
28
+ private collectPanelContent;
29
+ private isItemExpanded;
30
+ private syncExpandedState;
31
+ private render;
32
+ private toggle;
33
+ }
34
+ declare global {
35
+ interface HTMLElementTagNameMap {
36
+ 'db-accordion': DbAccordion;
37
+ }
38
+ }
39
+
40
+ export { DbAccordion };
@@ -0,0 +1 @@
1
+ import{createDbIcon as e}from"./db-icons.js";class DbAccordion extends HTMLElement{constructor(){super(...arguments),this.expanded=new Set,this.isRendering=!1,this.suppressExpandedAttrCallback=!1}static get observedAttributes(){return["items","variant","size","allow-multiple","expand-mode","expanded-items","default-item-type"]}get items(){try{const e=JSON.parse(this.getAttribute("items")||"[]");return Array.isArray(e)?e:[]}catch{return[]}}set items(e){this.setAttribute("items","string"==typeof e?e:JSON.stringify(e))}get allowMultiple(){return this.hasAttribute("allow-multiple")}set allowMultiple(e){this.toggleAttribute("allow-multiple",e)}get expandedItems(){const e=(this.getAttribute("expanded-items")||"").trim();if(!e)return[];if("all"===e)return this.items.map((e,t)=>this.resolveItemKey(e,t));try{const t=JSON.parse(e);if(Array.isArray(t))return t.map(e=>String(e).trim()).filter(Boolean)}catch{}return e.split(",").map(e=>e.trim()).filter(Boolean)}set expandedItems(e){Array.isArray(e)?this.setAttribute("expanded-items",e.join(",")):this.setAttribute("expanded-items",e)}connectedCallback(){this.syncExpandedFromAttributes(),this.render(),this.childObserver=new MutationObserver(e=>{if(this.isRendering)return;e.some(e=>Array.from(e.addedNodes).some(e=>e instanceof HTMLElement&&e.hasAttribute("slot")))&&this.render()}),this.childObserver.observe(this,{childList:!0})}disconnectedCallback(){this.childObserver?.disconnect()}attributeChangedCallback(e){if(this.isConnected){if("expanded-items"===e){if(this.suppressExpandedAttrCallback)return;return this.syncExpandedFromAttributes(),void this.syncExpandedState()}return"expand-mode"===e||"allow-multiple"===e?(this.syncExpandedFromAttributes(),void this.syncExpandedState()):"items"===e?(this.syncExpandedFromAttributes(),void this.render()):void this.render()}}resolveItemKey(e,t){return e.id??String(t)}getExpandMode(){const e=this.getAttribute("expand-mode");return"single"===e||"multiple"===e||"all"===e?e:(this.hasAttribute("allow-multiple"),"multiple")}syncExpandedFromAttributes(){const e=this.items.map((e,t)=>this.resolveItemKey(e,t)),t=this.expandedItems,s=this.getExpandMode();t.length>0?this.expanded=new Set(t.filter(t=>e.includes(t))):this.expanded="all"!==s?new Set:new Set(e)}iconSize(e){return"s"===e?16:"l"===e?24:20}collectPanelContent(){const e=new Map,register=(t,s)=>{if(!(t instanceof HTMLElement)||"SLOT"===t.tagName)return;e.has(s)||e.set(s,[]);const i=e.get(s);i.includes(t)||i.push(t)};return Array.from(this.children).forEach(e=>{const t=e.getAttribute("slot")?.match(/^content-(\d+)$/);t&&register(e,Number(t[1]))}),this.querySelectorAll(":scope > .designbase-wc-accordion__item").forEach((e,t)=>{const s=e.querySelector(":scope > .designbase-wc-accordion__content > .designbase-wc-accordion__content-inner");s&&Array.from(s.children).forEach(e=>register(e,t))}),e}isItemExpanded(e,t){return this.expanded.has(this.resolveItemKey(e,t))}syncExpandedState(){const e=this.items;this.querySelectorAll(":scope > .designbase-wc-accordion__item").forEach((t,s)=>{const i=e[s];if(!i)return;const n=this.isItemExpanded(i,s);t.classList.toggle("designbase-wc-accordion__item--expanded",n),t.classList.toggle("designbase-wc-accordion__item--disabled",Boolean(i.disabled));const a=t.querySelector(".designbase-wc-accordion__trigger"),d=t.querySelector(".designbase-wc-accordion__content");a?.setAttribute("aria-expanded",String(n)),d?.setAttribute("aria-hidden",String(!n))})}render(){this.isRendering=!0;const t=this.collectPanelContent(),s=this.getAttribute("variant")||"default",i=this.getAttribute("size")||"m",n=this.getExpandMode(),a=this.getAttribute("default-item-type")||"none",d=this.items,r=this.iconSize(i);this.className=["designbase-wc-accordion",`designbase-wc-accordion--${s}`,`designbase-wc-accordion--${i}`,"multiple"===n&&"designbase-wc-accordion--multiple","single"===n&&"designbase-wc-accordion--single","all"===n&&"designbase-wc-accordion--all"].filter(Boolean).join(" "),this.setAttribute("role","region"),this.setAttribute("aria-label","아코디언"),this.querySelectorAll(":scope > .designbase-wc-accordion__item").forEach(e=>e.remove()),d.forEach((i,n)=>{const d=this.resolveItemKey(i,n),c=this.isItemExpanded(i,n),o=document.createElement("div");o.className=["designbase-wc-accordion__item",`designbase-wc-accordion__item--${s}`,c&&"designbase-wc-accordion__item--expanded",i.disabled&&"designbase-wc-accordion__item--disabled"].filter(Boolean).join(" "),o.dataset.itemKey=d;const l=document.createElement("button");l.type="button",l.className="designbase-wc-accordion__trigger",l.disabled=Boolean(i.disabled),l.setAttribute("aria-expanded",String(c)),l.setAttribute("aria-controls",`accordion-content-${d}`),l.addEventListener("click",()=>{i.disabled||this.toggle(d)});const m=i.itemType||a;if("number"===m){const e=document.createElement("div");e.className="designbase-wc-accordion__number",e.textContent=`${n+1}.`,l.append(e)}else if("question"===m){const e=document.createElement("div");e.className="designbase-wc-accordion__question",e.textContent="Q.",l.append(e)}else if("icon"===m&&i.icon){const t=document.createElement("div");t.className="designbase-wc-accordion__icon",t.append(e(i.icon,r)),l.append(t)}const p=document.createElement("span");p.className="designbase-wc-accordion__title",p.textContent=i.title;const h=document.createElement("div");h.className="designbase-wc-accordion__chevron",h.append(e("chevron-down",r)),l.append(p,h);const u=document.createElement("div");u.id=`accordion-content-${d}`,u.className="designbase-wc-accordion__content",u.setAttribute("aria-hidden",String(!c));const b=document.createElement("div");b.className="designbase-wc-accordion__content-inner",(t.get(n)||[]).forEach(e=>{e.removeAttribute("slot"),b.append(e)}),u.append(b),o.append(l,u),this.append(o)}),this.isRendering=!1}toggle(e){const t=this.getExpandMode();this.expanded.has(e)?this.expanded.delete(e):"single"===t?this.expanded=new Set([e]):this.expanded.add(e);const s=Array.from(this.expanded);this.syncExpandedState(),this.suppressExpandedAttrCallback=!0,this.expandedItems=s,this.suppressExpandedAttrCallback=!1,this.dispatchEvent(new CustomEvent("db-change",{detail:{expandedItems:s},bubbles:!0,composed:!0}))}}customElements.get("db-accordion")||customElements.define("db-accordion",DbAccordion);export{DbAccordion};
@@ -0,0 +1,41 @@
1
+ declare class DbAdBanner extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ private built;
4
+ private visible;
5
+ private progress;
6
+ private autoCloseTimer?;
7
+ private rootEl?;
8
+ private gradientEl?;
9
+ private contentEl?;
10
+ private closeBtn?;
11
+ private iconEl?;
12
+ private labelEl?;
13
+ private badgeEl?;
14
+ private titleEl?;
15
+ private subtitleEl?;
16
+ private countdownWrapEl?;
17
+ private countdownEl?;
18
+ private actionsEl?;
19
+ private ctaEl?;
20
+ private progressEl?;
21
+ private progressBarEl?;
22
+ connectedCallback(): void;
23
+ disconnectedCallback(): void;
24
+ attributeChangedCallback(name: string): void;
25
+ private getBool;
26
+ private getType;
27
+ private getVariant;
28
+ private build;
29
+ private handleClose;
30
+ private stopAutoClose;
31
+ private startAutoClose;
32
+ private renderGradientWrapper;
33
+ private updateUI;
34
+ }
35
+ declare global {
36
+ interface HTMLElementTagNameMap {
37
+ 'db-ad-banner': DbAdBanner;
38
+ }
39
+ }
40
+
41
+ export { DbAdBanner };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t}from"./db-icons.js";const e="designbase-wc-ad-banner",s={hero:"지금 바로 시작하세요",topbar:"🎉 신규 가입 시 10,000원 적립금 증정!",card:"프리미엄 멤버십",floating:"오늘만 특가!"},i={hero:"최대 50% 할인된 가격으로 프리미엄 서비스를 경험해보세요. 기간 한정 특별 혜택!",topbar:"오늘 하루만 특별 혜택",card:"무제한 서비스 이용권을 특별가에 만나보세요",floating:"장바구니에 담긴 상품 추가 20% 할인"},n={hero:"자세히 보기",topbar:"지금 가입하기",card:"알아보기",floating:"할인받기"},a={hero:"star",topbar:"trending-up",card:"star-filled",floating:"cart"},l={primary:"primary",secondary:"secondary",success:"success",warning:"warning",error:"error"};class DbAdBanner extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.visible=!0,this.progress=100}static get observedAttributes(){return["type","variant","title","subtitle","cta-text","auto-close","close-delay","use-random-gradient","gradient-scheme","gradient-tone","gradient-animated","countdown-end-date","show-countdown","open"]}connectedCallback(){this.style.display="block",this.built||(this.built=!0,this.build()),this.updateUI()}disconnectedCallback(){this.stopAutoClose()}attributeChangedCallback(t){this.built&&("open"===t&&(this.visible="false"!==this.getAttribute("open")),this.updateUI())}getBool(t,e=!1){if(!this.hasAttribute(t))return e;const s=this.getAttribute(t);return""===s||"true"===s}getType(){const t=this.getAttribute("type")||"hero";return["hero","topbar","card","floating"].includes(t)?t:"hero"}getVariant(){const t=this.getAttribute("variant")||"primary";return["primary","secondary","success","warning","error"].includes(t)?t:"primary"}build(){this.rootEl=document.createElement("div"),this.contentEl=document.createElement("div"),this.contentEl.className=`${e}__content`,this.closeBtn=document.createElement("button"),this.closeBtn.type="button",this.closeBtn.className=`${e}__close`,this.closeBtn.setAttribute("aria-label","닫기"),this.closeBtn.append(t("close",20)),this.closeBtn.addEventListener("click",()=>this.handleClose());const s=document.createElement("div");s.className=`${e}__main`,this.iconEl=document.createElement("div"),this.iconEl.className=`${e}__icon`,this.labelEl=document.createElement("span"),this.labelEl.className=`${e}__label`,this.labelEl.textContent="특별 이벤트",this.badgeEl=document.createElement("span"),this.badgeEl.className=`${e}__badge`,this.badgeEl.textContent="HOT DEAL",this.titleEl=document.createElement("h2"),this.titleEl.className=`${e}__title`,this.subtitleEl=document.createElement("p"),this.subtitleEl.className=`${e}__subtitle`;const i=document.createElement("div");i.className=`${e}__text`,this.countdownWrapEl=document.createElement("div"),this.countdownWrapEl.className=`${e}__countdown`,this.countdownEl=document.createElement("db-countdown"),this.countdownEl.setAttribute("size","s"),this.countdownEl.setAttribute("variant","compact"),this.countdownEl.setAttribute("show-labels","false"),this.countdownWrapEl.append(this.countdownEl),i.append(this.titleEl,this.subtitleEl,this.countdownWrapEl),this.actionsEl=document.createElement("div"),this.actionsEl.className=`${e}__actions`,this.ctaEl=document.createElement("db-button"),this.ctaEl.className=`${e}__cta`,this.ctaEl.setAttribute("variant","primary"),this.ctaEl.setAttribute("end-icon","arrow-right"),this.ctaEl.addEventListener("click",t=>{t.stopPropagation(),this.dispatchEvent(new CustomEvent("db-cta-click",{bubbles:!0,composed:!0}))}),this.actionsEl.append(this.ctaEl),s.append(this.iconEl,i,this.actionsEl),this.progressEl=document.createElement("div"),this.progressEl.className=`${e}__progress`,this.progressBarEl=document.createElement("div"),this.progressBarEl.className=`${e}__progress-bar`,this.progressEl.append(this.progressBarEl),this.contentEl.append(this.closeBtn,s,this.progressEl),this.rootEl.append(this.contentEl),this.append(this.rootEl)}handleClose(){this.visible=!1,this.hidden=!0,this.stopAutoClose(),this.dispatchEvent(new CustomEvent("db-close",{bubbles:!0,composed:!0}))}stopAutoClose(){this.autoCloseTimer&&(window.clearInterval(this.autoCloseTimer),this.autoCloseTimer=void 0)}startAutoClose(t){this.stopAutoClose(),this.progress=100,this.autoCloseTimer=window.setInterval(()=>{this.progress-=100/(t/100),this.progressBarEl&&(this.progressBarEl.style.width=`${Math.max(this.progress,0)}%`),this.progress<=0&&this.handleClose()},100)}renderGradientWrapper(t){this.rootEl&&this.contentEl&&(t?(this.gradientEl||(this.gradientEl=document.createElement("db-random-gradient"),this.gradientEl.className=`${e}__gradient-bg`,this.gradientEl.setAttribute("height","100%"),this.gradientEl.setAttribute("width","100%")),this.gradientEl.parentElement!==this.rootEl&&this.rootEl.replaceChildren(this.gradientEl),this.contentEl.parentElement!==this.gradientEl&&this.gradientEl.append(this.contentEl)):(this.gradientEl&&(this.gradientEl.remove(),this.gradientEl=void 0),this.contentEl.parentElement!==this.rootEl&&this.rootEl.replaceChildren(this.contentEl)))}updateUI(){if(!this.visible||"false"===this.getAttribute("open"))return void(this.hidden=!0);this.hidden=!1;const r=this.getType(),o=this.getVariant(),h=this.getAttribute("title")||s[r],d=this.getAttribute("subtitle")||i[r],c=this.getAttribute("cta-text")||n[r],E=this.getBool("auto-close"),u=Math.max(Number(this.getAttribute("close-delay")||5e3),1e3),b=this.getBool("use-random-gradient"),p=this.getAttribute("gradient-tone")||"vivid",g=!this.hasAttribute("gradient-animated")||"false"!==this.getAttribute("gradient-animated"),m=this.getBool("show-countdown"),A=this.getAttribute("countdown-end-date");this.rootEl&&(this.rootEl.className=[e,`${e}--type-${r}`,`${e}--variant-${o}`,E&&`${e}--auto-close`,b&&`${e}--with-gradient`,b&&"light"===p&&`${e}--gradient-light`].filter(Boolean).join(" ")),b&&this.gradientEl&&(this.gradientEl.setAttribute("scheme",this.getAttribute("gradient-scheme")||l[o]),this.gradientEl.setAttribute("tone",p),this.gradientEl.setAttribute("animated",g?"true":"false")),this.renderGradientWrapper(b),this.iconEl&&(this.iconEl.replaceChildren(t(a[r],"card"===r?32:"floating"===r?28:24)),this.labelEl&&this.iconEl.append(this.labelEl),this.badgeEl&&this.iconEl.append(this.badgeEl),this.labelEl&&(this.labelEl.hidden="topbar"!==r),this.badgeEl&&(this.badgeEl.hidden="floating"!==r)),this.titleEl&&(this.titleEl.textContent=h),this.subtitleEl&&(this.subtitleEl.textContent=d),this.countdownWrapEl&&this.countdownEl&&(this.countdownWrapEl.hidden=!(m&&A),m&&A&&this.countdownEl.setAttribute("end-date",A)),this.ctaEl&&(this.ctaEl.textContent=c,this.ctaEl.setAttribute("size","hero"===r?"l":"card"===r?"s":"m"),"floating"===r?this.ctaEl.setAttribute("full-width",""):this.ctaEl.removeAttribute("full-width")),this.progressEl&&(this.progressEl.hidden=!E),this.progressBarEl&&E&&(this.progressBarEl.style.width=`${this.progress}%`),this.stopAutoClose(),E&&this.startAutoClose(u)}}customElements.get("db-ad-banner")||customElements.define("db-ad-banner",DbAdBanner);export{DbAdBanner};
@@ -0,0 +1,24 @@
1
+ import './db-button.js';
2
+
3
+ interface DbAlertAction {
4
+ label: string;
5
+ variant?: 'primary' | 'secondary' | 'tertiary' | 'danger';
6
+ size?: 's' | 'm' | 'l';
7
+ disabled?: boolean;
8
+ }
9
+ declare class DbAlert extends HTMLElement {
10
+ static get observedAttributes(): string[];
11
+ connectedCallback(): void;
12
+ attributeChangedCallback(): void;
13
+ private getIconName;
14
+ private parseActionButtons;
15
+ private render;
16
+ }
17
+ declare global {
18
+ interface HTMLElementTagNameMap {
19
+ 'db-alert': DbAlert;
20
+ }
21
+ }
22
+
23
+ export { DbAlert };
24
+ export type { DbAlertAction };