@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
@@ -0,0 +1,146 @@
1
+ import './db-chat-orb.js';
2
+ import './db-badge.js';
3
+ import './db-chat-welcome.js';
4
+ import './db-chat-composer.js';
5
+ import { DbChatSuggestion } from './db-chat-suggestions.js';
6
+ import './db-chat-message.js';
7
+ import './db-chat-typing.js';
8
+ import './db-avatar.js';
9
+
10
+ declare const VIEWS: readonly ["home", "messages", "conversation", "help"];
11
+ type ChatView = (typeof VIEWS)[number];
12
+ declare const POSITIONS: readonly ["bottom-right", "bottom-left"];
13
+ type ChatPosition = (typeof POSITIONS)[number];
14
+ interface DbChatWidgetMessage {
15
+ id?: string;
16
+ /** `assistant`(상담원/봇) 또는 `user` */
17
+ role?: 'assistant' | 'user';
18
+ text: string;
19
+ name?: string;
20
+ time?: string;
21
+ avatarSrc?: string;
22
+ avatarInitials?: string;
23
+ /** 말풍선 액션 (예: 'copy,like,dislike') — db-chat-message 로 전달 */
24
+ actions?: string;
25
+ }
26
+ interface DbChatWidgetConversation {
27
+ id?: string;
28
+ name: string;
29
+ avatarSrc?: string;
30
+ avatarInitials?: string;
31
+ preview?: string;
32
+ time?: string;
33
+ unread?: number;
34
+ online?: boolean;
35
+ }
36
+ /**
37
+ * FAB 로 열고 닫는 우측 하단 채팅 상담 위젯(껍데기).
38
+ *
39
+ * 홈·메시지·대화·도움말 4개 화면을 하단 탭으로 전환하며, 본문은 AI 채팅 프리미티브
40
+ * (`db-chat-welcome` · `db-chat-message` · `db-chat-typing` · `db-chat-composer`
41
+ * · `db-chat-suggestions` · `db-chat-orb`)를 조합해 구성합니다. 실제 백엔드 연동
42
+ * 없이 UI 골격만 제공하고, 상호작용은 이벤트로 위임합니다.
43
+ *
44
+ * @fires db-open - 패널 열림
45
+ * @fires db-close - 패널 닫힘
46
+ * @fires db-toggle - FAB 토글 (detail: { open })
47
+ * @fires db-view-change - 화면 전환 (detail: { view })
48
+ * @fires db-send - 메시지 전송 (detail: { text })
49
+ * @fires db-menu-select - 홈 메뉴 선택 (detail: { id, value })
50
+ * @fires db-quick-reply - 빠른 답변 선택 (detail: { id, value })
51
+ * @fires db-article-select - 도움말 문서 선택 (detail: { id, title })
52
+ * @fires db-conversation-select - 대화 목록 선택 (detail: { id })
53
+ * @fires db-message-action - 말풍선 액션 (detail: { action, text })
54
+ *
55
+ * @example
56
+ * const chat = document.createElement('db-chat-widget');
57
+ * chat.setAttribute('agent-name', '디지털 상담원');
58
+ * chat.setAttribute('unread', '2');
59
+ * document.body.appendChild(chat);
60
+ * chat.addEventListener('db-send', (e) => {
61
+ * chat.setTyping(true);
62
+ * setTimeout(() => {
63
+ * chat.setTyping(false);
64
+ * chat.addMessage({ role: 'assistant', text: '확인했어요!' });
65
+ * }, 900);
66
+ * });
67
+ */
68
+ declare class DbChatWidget extends HTMLElement {
69
+ static get observedAttributes(): string[];
70
+ private built;
71
+ private typing;
72
+ private _messages;
73
+ private _conversations;
74
+ private _menuItems;
75
+ private _quickReplies;
76
+ private _articles;
77
+ private launcher;
78
+ private launcherBadge;
79
+ private panel;
80
+ private headerEl;
81
+ private bodyEl;
82
+ private footerEl;
83
+ private navEl;
84
+ private composer;
85
+ private threadEl;
86
+ get open(): boolean;
87
+ set open(v: boolean);
88
+ get view(): ChatView;
89
+ set view(v: ChatView);
90
+ get position(): ChatPosition;
91
+ set position(v: ChatPosition);
92
+ get unread(): number;
93
+ set unread(v: number);
94
+ set messages(v: DbChatWidgetMessage[]);
95
+ get messages(): DbChatWidgetMessage[];
96
+ set conversations(v: DbChatWidgetConversation[]);
97
+ get conversations(): DbChatWidgetConversation[];
98
+ set menuItems(v: DbChatSuggestion[]);
99
+ get menuItems(): DbChatSuggestion[];
100
+ set quickReplies(v: DbChatSuggestion[]);
101
+ get quickReplies(): DbChatSuggestion[];
102
+ set articles(v: DbChatSuggestion[]);
103
+ get articles(): DbChatSuggestion[];
104
+ connectedCallback(): void;
105
+ attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
106
+ private hydrateFromAttributes;
107
+ private build;
108
+ private sync;
109
+ private syncOpenState;
110
+ private renderBadge;
111
+ private renderHeader;
112
+ private iconButton;
113
+ private renderBody;
114
+ private renderHome;
115
+ private renderMessages;
116
+ private renderConversation;
117
+ private renderHelp;
118
+ private buildMessage;
119
+ private buildTyping;
120
+ private buildEmpty;
121
+ private renderFooter;
122
+ private renderNav;
123
+ private scrollThreadToEnd;
124
+ private nowLabel;
125
+ private dispatch;
126
+ openWidget(): void;
127
+ close(): void;
128
+ toggle(): void;
129
+ setView(view: ChatView): void;
130
+ /** 스레드에 메시지를 추가하고 대화 화면으로 전환/렌더 */
131
+ addMessage(msg: DbChatWidgetMessage): void;
132
+ /** 챗봇 입력중(...) 표시 토글 */
133
+ setTyping(on: boolean): void;
134
+ /** 전송 중(정지 버튼) 상태 — 컴포저에 위임 */
135
+ setStreaming(on: boolean): void;
136
+ /** 스레드 전체 교체 */
137
+ setMessages(messages: DbChatWidgetMessage[]): void;
138
+ }
139
+ declare global {
140
+ interface HTMLElementTagNameMap {
141
+ 'db-chat-widget': DbChatWidget;
142
+ }
143
+ }
144
+
145
+ export { DbChatWidget };
146
+ export type { DbChatWidgetConversation, DbChatWidgetMessage };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t}from"./db-icons.js";import"./db-chat-orb.js";import"./db-badge.js";import"./db-chat-welcome.js";import"./db-chat-composer.js";import"./db-chat-suggestions.js";import"./db-chat-message.js";import"./db-chat-typing.js";import"./db-avatar.js";const e=["home","messages","conversation","help"],i=["bottom-right","bottom-left"],s=[{id:"products",title:"제품·정책 알아보기",description:"AI가 정확하게 안내해 드려요",icon:"sparkle"},{id:"services",title:"상담원과 대화하기",description:"지금 바로 대화를 시작하세요",icon:"mail"},{id:"status",title:"주문·배송 조회",description:"진행 상황을 확인해 보세요",icon:"package"}],a=[{id:"products",title:"제품·정책 알아보기"},{id:"services",title:"서비스 상담하기"}],r=[{id:"m1",role:"assistant",name:"상담원",text:"안녕하세요. 무엇을 도와드릴까요? 제품과 정책을 24시간 정확하게 안내해 드릴게요.",time:"오후 12:31"},{id:"m2",role:"assistant",name:"상담원",text:"아래에서 원하시는 도움을 선택하시거나, 자유롭게 메시지를 입력해 주세요.",time:"오후 12:31",actions:"like,dislike"}],n=[{id:"c1",name:"디지털 상담원",avatarInitials:"상",preview:"무엇을 도와드릴까요? 24시간 대기중이에요.",time:"방금",unread:1,online:!0},{id:"c2",name:"결제·환불 지원",avatarInitials:"결",preview:"환불 요청이 정상 접수되었습니다.",time:"어제"},{id:"c3",name:"온보딩 도우미",avatarInitials:"온",preview:"설치가 완료되면 알려드릴게요.",time:"3일 전"}],o=[{id:"a1",title:"시작하기 — 5분 만에 설정 완료",description:"계정 생성부터 첫 배포까지",icon:"sparkle"},{id:"a2",title:"요금제와 결제 안내",description:"플랜 비교 · 청구 주기",icon:"star"},{id:"a3",title:"팀원 초대와 권한 관리",description:"역할별 접근 권한 설정",icon:"user"},{id:"a4",title:"데이터 내보내기·백업",description:"안전하게 보관하는 방법",icon:"download"}],h={chat:'<path d="M4 5.5A1.5 1.5 0 0 1 5.5 4h13A1.5 1.5 0 0 1 20 5.5v9a1.5 1.5 0 0 1-1.5 1.5H9l-4 3.5V16H5.5A1.5 1.5 0 0 1 4 14.5z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>',home:'<path d="M4 10.5 12 4l8 6.5M6 9.5V19a1 1 0 0 0 1 1h3.5v-4.5a1.5 1.5 0 0 1 3 0V20H17a1 1 0 0 0 1-1V9.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>',help:'<circle cx="12" cy="12" r="8.25" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M9.6 9.4a2.5 2.5 0 0 1 4.9.6c0 1.7-2.5 2-2.5 3.6" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><circle cx="12" cy="16.6" r="0.95" fill="currentColor"/>',"close-x":'<path d="m6.5 6.5 11 11m0-11-11 11" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>'};function widgetIcon(t,e=20){const i=document.createElement("template");return i.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="${e}" height="${e}" fill="none" aria-hidden="true" focusable="false">${h[t]}</svg>`,i.content.firstElementChild}function el(t,e,i){const s=document.createElement(t);return e&&(s.className=e),null!=i&&(s.textContent=i),s}function parseJson(t,e){if(!t)return e;try{const i=JSON.parse(t);return Array.isArray(i)?i:e}catch{return e}}const l="designbase-wc-chat";class DbChatWidget extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.typing=!1,this._messages=r,this._conversations=n,this._menuItems=s,this._quickReplies=a,this._articles=o,this.composer=null,this.threadEl=null}static get observedAttributes(){return["open","view","position","agent-name","agent-avatar","agent-status","greeting","title","subtitle","placeholder","unread","accent","orb-variant","launcher-label","search-enabled"]}get open(){return this.hasAttribute("open")}set open(t){this.toggleAttribute("open",Boolean(t))}get view(){const t=this.getAttribute("view");return e.includes(t)?t:"home"}set view(t){this.setAttribute("view",t)}get position(){const t=this.getAttribute("position");return i.includes(t)?t:"bottom-right"}set position(t){this.setAttribute("position",t)}get unread(){return Number(this.getAttribute("unread")||0)}set unread(t){this.setAttribute("unread",String(t))}set messages(t){this._messages=Array.isArray(t)?t:[],this.built&&"conversation"===this.view&&this.renderBody()}get messages(){return this._messages}set conversations(t){this._conversations=Array.isArray(t)?t:[],this.built&&this.renderBody()}get conversations(){return this._conversations}set menuItems(t){this._menuItems=Array.isArray(t)?t:[],this.built&&"home"===this.view&&this.renderBody()}get menuItems(){return this._menuItems}set quickReplies(t){this._quickReplies=Array.isArray(t)?t:[],this.built&&"conversation"===this.view&&this.renderBody()}get quickReplies(){return this._quickReplies}set articles(t){this._articles=Array.isArray(t)?t:[],this.built&&"help"===this.view&&this.renderBody()}get articles(){return this._articles}connectedCallback(){this.hydrateFromAttributes(),this.build(),this.sync()}attributeChangedCallback(t,e,i){if(this.built&&e!==i){if("open"!==t)return"view"===t?(this.sync(),void this.dispatch("db-view-change",{view:this.view})):void this.sync();this.syncOpenState()}}hydrateFromAttributes(){this._messages=parseJson(this.getAttribute("messages"),this._messages),this._conversations=parseJson(this.getAttribute("conversations"),this._conversations),this._menuItems=parseJson(this.getAttribute("menu-items"),this._menuItems),this._quickReplies=parseJson(this.getAttribute("quick-replies"),this._quickReplies),this._articles=parseJson(this.getAttribute("articles"),this._articles)}build(){if(this.built)return;this.built=!0,this.classList.add(l),this.replaceChildren(),this.launcher=el("button",`${l}__launcher`),this.launcher.type="button",this.launcher.setAttribute("aria-haspopup","dialog");const t=el("span",`${l}__launcher-icon ${l}__launcher-icon--open`),e=el("db-chat-orb");e.setAttribute("size","s"),e.setAttribute("variant",this.getAttribute("orb-variant")||"violet"),e.setAttribute("state","idle"),t.append(e);const i=el("span",`${l}__launcher-icon ${l}__launcher-icon--close`);i.append(widgetIcon("close-x",24)),this.launcherBadge=document.createElement("db-badge"),this.launcherBadge.className=`${l}__launcher-badge`,this.launcherBadge.setAttribute("badge-style","number"),this.launcherBadge.setAttribute("variant","danger"),this.launcherBadge.setAttribute("size","s"),this.launcherBadge.setAttribute("max-count","99"),this.launcher.append(t,i,this.launcherBadge),this.launcher.addEventListener("click",()=>this.toggle()),this.panel=el("div",`${l}__panel`),this.panel.setAttribute("role","dialog"),this.panel.setAttribute("aria-modal","false"),this.headerEl=el("div",`${l}__header`),this.bodyEl=el("div",`${l}__body`),this.footerEl=el("div",`${l}__footer`),this.navEl=el("div",`${l}__nav`),this.panel.append(this.headerEl,this.bodyEl,this.footerEl,this.navEl),this.append(this.panel,this.launcher)}sync(){i.forEach(t=>this.classList.toggle(`${l}--${t}`,t===this.position)),e.forEach(t=>this.classList.toggle(`${l}--view-${t}`,t===this.view));const t=this.getAttribute("accent");t?this.style.setProperty("--dbchat-accent",t):this.style.removeProperty("--dbchat-accent"),this.renderBadge(),this.renderHeader(),this.renderBody(),this.renderFooter(),this.renderNav(),this.syncOpenState()}syncOpenState(){const t=this.open;this.classList.toggle(`${l}--open`,t),this.launcher.setAttribute("aria-expanded",String(t)),this.panel.setAttribute("aria-hidden",String(!t)),t?this.panel.removeAttribute("inert"):this.panel.setAttribute("inert",""),this.launcher.setAttribute("aria-label",this.getAttribute("launcher-label")||(t?"상담창 닫기":"상담 시작하기")),t&&"conversation"===this.view&&requestAnimationFrame(()=>this.composer?.focusInput())}renderBadge(){const t=this.unread;t>0?this.launcherBadge.setAttribute("count",String(t)):this.launcherBadge.removeAttribute("count"),this.launcherBadge.hidden=t<=0}renderHeader(){this.headerEl.replaceChildren();const e=this.view,i=this.getAttribute("agent-name")||"디지털 상담원",s=el("div",`${l}__header-bar`);if("conversation"===e){const e=this.iconButton(t("chevron-left",20),"뒤로",()=>this.setView("messages")),a=el("div",`${l}__header-identity`),r=el("db-chat-orb");r.className=`${l}__header-orb`,r.setAttribute("size","xs"),r.setAttribute("variant",this.getAttribute("orb-variant")||"violet");const n=el("div",`${l}__header-meta`);n.append(el("span",`${l}__header-name`,i),el("span",`${l}__header-status`,this.getAttribute("agent-status")||"보통 몇 분 내 응답")),a.append(r,n),s.append(e,a,this.iconButton(widgetIcon("close-x",20),"닫기",()=>this.close()))}else{const t="home"===e?"홈":"messages"===e?"메시지":"도움말";s.append(el("span",`${l}__header-title`,t),this.iconButton(widgetIcon("close-x",20),"닫기",()=>this.close()))}this.headerEl.append(s)}iconButton(t,e,i){const s=el("button",`${l}__icon-btn`);return s.type="button",s.setAttribute("aria-label",e),s.append(t),s.addEventListener("click",i),s}renderBody(){if(this.built)switch(this.threadEl=null,this.bodyEl.replaceChildren(),this.bodyEl.classList.toggle(`${l}__body--thread`,"conversation"===this.view),this.view){case"home":this.renderHome();break;case"messages":this.renderMessages();break;case"conversation":this.renderConversation();break;case"help":this.renderHelp()}}renderHome(){const e=el("db-chat-welcome",`${l}__welcome`);e.setAttribute("greeting",this.getAttribute("greeting")||"안녕하세요"),e.setAttribute("title",this.getAttribute("title")||"무엇을 도와드릴까요?"),e.setAttribute("highlight",this.getAttribute("highlight")||this.getAttribute("title")||"도와드릴까요"),e.setAttribute("subtitle",this.getAttribute("subtitle")||"제품·정책을 24시간 정확하게 안내해 드릴게요."),e.setAttribute("orb-variant",this.getAttribute("orb-variant")||"violet"),e.setAttribute("align","left"),e.setAttribute("orb-size","m"),this.bodyEl.append(e);const i=this._conversations[0];if(i){const e=el("button",`${l}__recent`);e.type="button";const s=el("db-avatar",`${l}__recent-avatar`);s.setAttribute("size","s"),s.setAttribute("variant","primary"),i.avatarSrc?s.setAttribute("src",i.avatarSrc):s.setAttribute("initials",i.avatarInitials||i.name.charAt(0)||"상"),i.online&&s.setAttribute("status","online"),i.unread&&(s.setAttribute("badge",String(i.unread)),s.setAttribute("badge-style","number"),s.setAttribute("badge-variant","primary"),s.setAttribute("badge-max-count","99"));const a=el("div",`${l}__recent-body`);a.append(el("span",`${l}__recent-title`,"최근 대화 이어가기"),el("span",`${l}__recent-preview`,i.preview||"")),e.append(s,a,t("chevron-right",18)),e.addEventListener("click",()=>{this.dispatch("db-conversation-select",{id:i.id}),this.setView("conversation")}),this.bodyEl.append(e)}if(this._menuItems.length){const t=el("db-chat-suggestions",`${l}__menu`);t.setAttribute("layout","card"),t.setAttribute("columns","1"),t.items=this._menuItems,t.addEventListener("db-select",t=>{t.stopPropagation();const e=t.detail;this.dispatch("db-menu-select",e),this.setView("conversation")}),this.bodyEl.append(t)}if("false"!==this.getAttribute("search-enabled")){const e=el("button",`${l}__search-entry`);e.type="button",e.append(t("search",18),el("span",void 0,"도움말 검색")),e.addEventListener("click",()=>this.setView("help")),this.bodyEl.append(e)}}renderMessages(){if(!this._conversations.length)return void this.bodyEl.append(this.buildEmpty("진행 중인 대화가 없어요","새 대화를 시작해 보세요."));const t=el("div",`${l}__conv-list`);this._conversations.forEach(e=>{const i=el("button",`${l}__conv`);i.type="button";const s=el("db-avatar",`${l}__conv-avatar`);s.setAttribute("size","m"),s.setAttribute("variant","primary"),e.avatarSrc?s.setAttribute("src",e.avatarSrc):s.setAttribute("initials",e.avatarInitials||e.name.charAt(0)||"?"),e.online&&s.setAttribute("status","online");const a=el("div",`${l}__conv-body`),r=el("div",`${l}__conv-top`);if(r.append(el("span",`${l}__conv-name`,e.name)),e.time&&r.append(el("span",`${l}__conv-time`,e.time)),a.append(r,el("span",`${l}__conv-preview`,e.preview||"")),i.append(s,a),e.unread){const t=el("db-badge",`${l}__conv-unread`);t.setAttribute("badge-style","number"),t.setAttribute("variant","primary"),t.setAttribute("size","s"),t.setAttribute("max-count","99"),t.setAttribute("count",String(e.unread)),i.append(t)}i.addEventListener("click",()=>{this.dispatch("db-conversation-select",{id:e.id}),this.setView("conversation")}),t.append(i)}),this.bodyEl.append(t)}renderConversation(){const t=el("div",`${l}__thread`);if(this._messages.forEach(e=>t.append(this.buildMessage(e))),this.threadEl=t,this.bodyEl.append(t),this.typing&&t.append(this.buildTyping()),this._quickReplies.length){const t=el("db-chat-suggestions");t.setAttribute("data-dbchat","quick"),t.setAttribute("layout","chip"),t.items=this._quickReplies,t.addEventListener("db-select",t=>{t.stopPropagation();const e=t.detail;this.dispatch("db-quick-reply",e),this.addMessage({role:"user",text:e.title,time:this.nowLabel()})}),this.bodyEl.append(t)}requestAnimationFrame(()=>this.scrollThreadToEnd())}renderHelp(){const e=el("div",`${l}__help-search`),i=el("span",`${l}__help-search-icon`);i.append(t("search",18));const s=el("input",`${l}__help-input`);if(s.type="search",s.placeholder="도움말 검색…",e.append(i,s),this.bodyEl.append(e),!this._articles.length)return void this.bodyEl.append(this.buildEmpty("문서가 없어요","검색어를 바꿔보세요."));const a=el("db-chat-suggestions",`${l}__articles`);a.setAttribute("layout","card"),a.setAttribute("columns","1"),a.items=this._articles,a.addEventListener("db-select",t=>{t.stopPropagation();const e=t.detail;this.dispatch("db-article-select",{id:e.id,title:e.title})}),this.bodyEl.append(a)}buildMessage(t){const e="user"===t.role?"user":"assistant",i=el("db-chat-message");return i.setAttribute("role",e),t.name&&i.setAttribute("name",t.name),t.time&&i.setAttribute("timestamp",t.time),t.avatarSrc&&i.setAttribute("avatar-src",t.avatarSrc),t.avatarInitials&&i.setAttribute("avatar-initials",t.avatarInitials),t.actions&&i.setAttribute("actions",t.actions),i.textContent=t.text,i.addEventListener("db-action",t=>{t.stopPropagation(),this.dispatch("db-message-action",t.detail)}),i}buildTyping(){const t=el("db-chat-typing",`${l}__typing`);return t.setAttribute("name",this.getAttribute("agent-name")||"상담원"),t.setAttribute("label","입력 중"),t}buildEmpty(t,e){const i=el("div",`${l}__empty`),s=el("db-chat-orb",`${l}__empty-orb`);return s.setAttribute("size","m"),s.setAttribute("variant",this.getAttribute("orb-variant")||"violet"),i.append(s,el("p",`${l}__empty-title`,t),el("p",`${l}__empty-desc`,e)),i}renderFooter(){const t="conversation"===this.view;if(this.footerEl.hidden=!t,!t)return this.composer=null,void this.footerEl.replaceChildren();if(!this.composer){this.footerEl.replaceChildren();const t=el("db-chat-composer",`${l}__composer`);t.setAttribute("placeholder",this.getAttribute("placeholder")||"메시지를 입력하세요…"),t.setAttribute("attach",""),t.setAttribute("voice",""),t.addEventListener("db-send",e=>{e.stopPropagation();const i=e.detail?.value?.trim();i&&(t.clear(),this.dispatch("db-send",{text:i}),this.addMessage({role:"user",text:i,time:this.nowLabel()}))}),t.addEventListener("db-stop",t=>{t.stopPropagation(),this.dispatch("db-stop")}),t.addEventListener("db-attach",t=>{t.stopPropagation(),this.dispatch("db-attach")}),t.addEventListener("db-voice",t=>{t.stopPropagation(),this.dispatch("db-voice")}),this.composer=t,this.footerEl.append(t)}}renderNav(){this.navEl.replaceChildren();const t="conversation"!==this.view;if(this.navEl.hidden=!t,!t)return;[{view:"home",icon:"home",label:"홈"},{view:"messages",icon:"chat",label:"메시지"},{view:"help",icon:"help",label:"도움말"}].forEach(t=>{const e=el("button",`${l}__tab`);e.type="button";const i=this.view===t.view;if(e.classList.toggle(`${l}__tab--active`,i),e.setAttribute("aria-current",String(i)),e.append(widgetIcon(t.icon,22),el("span",`${l}__tab-label`,t.label)),"messages"===t.view&&this.unread>0){const t=el("db-badge",`${l}__tab-badge`);t.setAttribute("badge-style","dot"),t.setAttribute("variant","danger"),t.setAttribute("size","s"),e.append(t)}e.addEventListener("click",()=>this.setView(t.view)),this.navEl.append(e)})}scrollThreadToEnd(){this.bodyEl.scrollTop=this.bodyEl.scrollHeight}nowLabel(){const t=new Date,e=t.getHours();return`${e<12?"오전":"오후"} ${e%12==0?12:e%12}:${t.getMinutes().toString().padStart(2,"0")}`}dispatch(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}openWidget(){this.open||(this.open=!0,this.dispatch("db-open"),this.dispatch("db-toggle",{open:!0}))}close(){this.open&&(this.open=!1,this.dispatch("db-close"),this.dispatch("db-toggle",{open:!1}))}toggle(){this.open?this.close():this.openWidget()}setView(t){this.view!==t&&(this.view=t)}addMessage(t){if(this._messages=[...this._messages,{id:`m${Date.now()}`,...t}],"conversation"===this.view)if(this.built&&this.threadEl){const e=this.threadEl.querySelector("db-chat-typing");this.threadEl.insertBefore(this.buildMessage(t),e),requestAnimationFrame(()=>this.scrollThreadToEnd())}else this.built&&this.renderBody();else this.view="conversation"}setTyping(t){if(this.typing=Boolean(t),!this.built||"conversation"!==this.view||!this.threadEl)return;const e=this.threadEl.querySelector("db-chat-typing");this.typing&&!e?(this.threadEl.append(this.buildTyping()),requestAnimationFrame(()=>this.scrollThreadToEnd())):!this.typing&&e&&e.remove()}setStreaming(t){this.composer?.setStreaming(Boolean(t))}setMessages(t){this.messages=t}}customElements.get("db-chat-widget")||customElements.define("db-chat-widget",DbChatWidget);export{DbChatWidget};
@@ -1,202 +1 @@
1
- import { createDbIcon } from './db-icons.js';
2
-
3
- const SIZES = ['s', 'm', 'l'];
4
- const CHECK_ICON_SIZE = 16;
5
- class DbCheckbox extends HTMLElement {
6
- constructor() {
7
- super(...arguments);
8
- this.built = false;
9
- this.handleChange = () => {
10
- if (!this.input)
11
- return;
12
- const checked = this.input.checked;
13
- this.toggleAttribute('checked', checked);
14
- if (this.indeterminate) {
15
- this.removeAttribute('indeterminate');
16
- this.input.indeterminate = false;
17
- }
18
- this.syncVisual();
19
- this.syncClasses();
20
- this.dispatchEvent(new CustomEvent('db-change', {
21
- detail: { checked, selected: checked },
22
- bubbles: true,
23
- composed: true,
24
- }));
25
- };
26
- }
27
- static get observedAttributes() {
28
- return [
29
- 'checked',
30
- 'selected',
31
- 'default-checked',
32
- 'default-selected',
33
- 'indeterminate',
34
- 'size',
35
- 'disabled',
36
- 'readonly',
37
- 'required',
38
- 'name',
39
- 'value',
40
- 'has-label',
41
- ];
42
- }
43
- get checked() {
44
- return this.input?.checked ?? (this.hasAttribute('checked') || this.hasAttribute('selected'));
45
- }
46
- set checked(value) {
47
- this.toggleAttribute('checked', value);
48
- if (this.input) {
49
- this.input.checked = value;
50
- this.syncVisual();
51
- this.syncClasses();
52
- }
53
- }
54
- get indeterminate() {
55
- return this.hasAttribute('indeterminate');
56
- }
57
- set indeterminate(value) {
58
- this.toggleAttribute('indeterminate', value);
59
- if (this.input) {
60
- this.input.indeterminate = value;
61
- this.syncVisual();
62
- this.syncClasses();
63
- }
64
- }
65
- get disabled() {
66
- return this.hasAttribute('disabled');
67
- }
68
- set disabled(value) {
69
- this.toggleAttribute('disabled', value);
70
- if (this.input)
71
- this.input.disabled = value;
72
- this.syncClasses();
73
- }
74
- get readOnly() {
75
- return this.hasAttribute('readonly');
76
- }
77
- set readOnly(value) {
78
- this.toggleAttribute('readonly', value);
79
- if (this.input)
80
- this.input.readOnly = value;
81
- this.syncClasses();
82
- }
83
- get required() {
84
- return this.hasAttribute('required');
85
- }
86
- set required(value) {
87
- this.toggleAttribute('required', value);
88
- if (this.input)
89
- this.input.required = value;
90
- }
91
- get size() {
92
- return this.getAttribute('size') || 'm';
93
- }
94
- set size(value) {
95
- this.setAttribute('size', value);
96
- }
97
- connectedCallback() {
98
- this.style.display = 'contents';
99
- if (!this.built) {
100
- this.build();
101
- }
102
- this.syncState();
103
- }
104
- attributeChangedCallback(name) {
105
- if (!this.built)
106
- return;
107
- if (name === 'checked' || name === 'selected') {
108
- if (this.input) {
109
- this.input.checked = this.hasAttribute('checked') || this.hasAttribute('selected');
110
- }
111
- this.syncVisual();
112
- this.syncClasses();
113
- return;
114
- }
115
- this.syncState();
116
- }
117
- get hasLabel() {
118
- return !this.hasAttribute('has-label') || this.getAttribute('has-label') !== 'false';
119
- }
120
- build() {
121
- this.root = document.createElement('label');
122
- this.root.className = 'designbase-wc-checkbox';
123
- this.input = document.createElement('input');
124
- this.input.type = 'checkbox';
125
- this.input.className = 'designbase-wc-checkbox__input';
126
- this.visual = document.createElement('span');
127
- this.visual.className = 'designbase-wc-checkbox__visual';
128
- this.visual.setAttribute('aria-hidden', 'true');
129
- this.labelEl = document.createElement('span');
130
- this.labelEl.className = 'designbase-wc-checkbox__label';
131
- while (this.firstChild) {
132
- this.labelEl.appendChild(this.firstChild);
133
- }
134
- this.root.append(this.input, this.visual, this.labelEl);
135
- this.appendChild(this.root);
136
- this.input.addEventListener('change', this.handleChange);
137
- this.built = true;
138
- }
139
- syncState() {
140
- if (!this.root || !this.input || !this.visual)
141
- return;
142
- const checked = this.hasAttribute('checked')
143
- || this.hasAttribute('selected')
144
- || (!this.hasAttribute('checked')
145
- && !this.hasAttribute('selected')
146
- && (this.hasAttribute('default-checked') || this.hasAttribute('default-selected')));
147
- const indeterminate = this.hasAttribute('indeterminate');
148
- this.input.checked = checked;
149
- this.input.indeterminate = indeterminate;
150
- this.input.disabled = this.disabled;
151
- this.input.readOnly = this.readOnly;
152
- this.input.required = this.required;
153
- this.input.name = this.getAttribute('name') || '';
154
- this.input.value = this.getAttribute('value') || '';
155
- if (this.hasLabel) {
156
- this.labelEl?.removeAttribute('hidden');
157
- }
158
- else {
159
- this.labelEl?.setAttribute('hidden', '');
160
- }
161
- this.syncVisual();
162
- this.syncClasses();
163
- }
164
- syncVisual() {
165
- if (!this.visual || !this.input)
166
- return;
167
- this.visual.replaceChildren();
168
- if (this.input.indeterminate) {
169
- const iconHost = document.createElement('span');
170
- iconHost.className = 'designbase-wc-checkbox__indeterminate-icon';
171
- iconHost.appendChild(createDbIcon('minus', CHECK_ICON_SIZE));
172
- this.visual.appendChild(iconHost);
173
- return;
174
- }
175
- if (this.input.checked) {
176
- const iconHost = document.createElement('span');
177
- iconHost.className = 'designbase-wc-checkbox__check-icon';
178
- iconHost.appendChild(createDbIcon('done', CHECK_ICON_SIZE));
179
- this.visual.appendChild(iconHost);
180
- }
181
- }
182
- syncClasses() {
183
- if (!this.root || !this.input)
184
- return;
185
- const size = SIZES.includes(this.size) ? this.size : 'm';
186
- const hasLabelText = this.hasLabel && Boolean(this.labelEl?.textContent?.trim());
187
- this.root.className = [
188
- 'designbase-wc-checkbox',
189
- `designbase-wc-checkbox--${size}`,
190
- this.input.checked && 'designbase-wc-checkbox--selected',
191
- this.input.indeterminate && 'designbase-wc-checkbox--indeterminate',
192
- this.disabled && 'designbase-wc-checkbox--disabled',
193
- this.readOnly && 'designbase-wc-checkbox--readonly',
194
- !hasLabelText && 'designbase-wc-checkbox--no-label',
195
- ].filter(Boolean).join(' ');
196
- }
197
- }
198
- if (!customElements.get('db-checkbox')) {
199
- customElements.define('db-checkbox', DbCheckbox);
200
- }
201
-
202
- export { DbCheckbox };
1
+ import{createDbIcon as t}from"./db-icons.js";const e=["s","m","l"];class DbCheckbox extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.handleChange=()=>{if(!this.input)return;const t=this.input.checked;this.toggleAttribute("checked",t),this.indeterminate&&(this.removeAttribute("indeterminate"),this.input.indeterminate=!1),this.syncVisual(),this.syncClasses(),this.dispatchEvent(new CustomEvent("db-change",{detail:{checked:t,selected:t},bubbles:!0,composed:!0}))}}static get observedAttributes(){return["checked","selected","default-checked","default-selected","indeterminate","size","disabled","readonly","required","name","value","has-label"]}get checked(){return this.input?.checked??(this.hasAttribute("checked")||this.hasAttribute("selected"))}set checked(t){this.toggleAttribute("checked",t),this.input&&(this.input.checked=t,this.syncVisual(),this.syncClasses())}get indeterminate(){return this.hasAttribute("indeterminate")}set indeterminate(t){this.toggleAttribute("indeterminate",t),this.input&&(this.input.indeterminate=t,this.syncVisual(),this.syncClasses())}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t),this.input&&(this.input.disabled=t),this.syncClasses()}get readOnly(){return this.hasAttribute("readonly")}set readOnly(t){this.toggleAttribute("readonly",t),this.input&&(this.input.readOnly=t),this.syncClasses()}get required(){return this.hasAttribute("required")}set required(t){this.toggleAttribute("required",t),this.input&&(this.input.required=t)}get size(){return this.getAttribute("size")||"m"}set size(t){this.setAttribute("size",t)}connectedCallback(){this.style.display="contents",this.built||this.build(),this.syncState()}attributeChangedCallback(t){if(this.built)return"checked"===t||"selected"===t?(this.input&&(this.input.checked=this.hasAttribute("checked")||this.hasAttribute("selected")),this.syncVisual(),void this.syncClasses()):void this.syncState()}get hasLabel(){return!this.hasAttribute("has-label")||"false"!==this.getAttribute("has-label")}build(){for(this.root=document.createElement("label"),this.root.className="designbase-wc-checkbox",this.input=document.createElement("input"),this.input.type="checkbox",this.input.className="designbase-wc-checkbox__input",this.visual=document.createElement("span"),this.visual.className="designbase-wc-checkbox__visual",this.visual.setAttribute("aria-hidden","true"),this.labelEl=document.createElement("span"),this.labelEl.className="designbase-wc-checkbox__label";this.firstChild;)this.labelEl.appendChild(this.firstChild);this.root.append(this.input,this.visual,this.labelEl),this.appendChild(this.root),this.input.addEventListener("change",this.handleChange),this.built=!0}syncState(){if(!this.root||!this.input||!this.visual)return;const t=this.hasAttribute("checked")||this.hasAttribute("selected")||!this.hasAttribute("checked")&&!this.hasAttribute("selected")&&(this.hasAttribute("default-checked")||this.hasAttribute("default-selected")),e=this.hasAttribute("indeterminate");this.input.checked=t,this.input.indeterminate=e,this.input.disabled=this.disabled,this.input.readOnly=this.readOnly,this.input.required=this.required,this.input.name=this.getAttribute("name")||"",this.input.value=this.getAttribute("value")||"",this.hasLabel?this.labelEl?.removeAttribute("hidden"):this.labelEl?.setAttribute("hidden",""),this.syncVisual(),this.syncClasses()}syncVisual(){if(this.visual&&this.input){if(this.visual.replaceChildren(),this.input.indeterminate){const e=document.createElement("span");return e.className="designbase-wc-checkbox__indeterminate-icon",e.appendChild(t("minus",16)),void this.visual.appendChild(e)}if(this.input.checked){const e=document.createElement("span");e.className="designbase-wc-checkbox__check-icon",e.appendChild(t("done",16)),this.visual.appendChild(e)}}}syncClasses(){if(!this.root||!this.input)return;const t=e.includes(this.size)?this.size:"m",i=this.hasLabel&&Boolean(this.labelEl?.textContent?.trim());this.root.className=["designbase-wc-checkbox",`designbase-wc-checkbox--${t}`,this.input.checked&&"designbase-wc-checkbox--selected",this.input.indeterminate&&"designbase-wc-checkbox--indeterminate",this.disabled&&"designbase-wc-checkbox--disabled",this.readOnly&&"designbase-wc-checkbox--readonly",!i&&"designbase-wc-checkbox--no-label"].filter(Boolean).join(" ")}}customElements.get("db-checkbox")||customElements.define("db-checkbox",DbCheckbox);export{DbCheckbox};
@@ -1,104 +1 @@
1
- import { createDbIcon } from './db-icons.js';
2
-
3
- const SIZES = ['s', 'm', 'l'];
4
- const VARIANTS = ['default', 'primary', 'success', 'warning', 'danger', 'info', 'neutral'];
5
- class DbChip extends HTMLElement {
6
- static get observedAttributes() {
7
- return ['label', 'size', 'variant', 'deletable', 'disabled', 'selected', 'full-width', 'clickable', 'start-icon', 'end-icon'];
8
- }
9
- connectedCallback() {
10
- this.render();
11
- }
12
- attributeChangedCallback() {
13
- this.render();
14
- }
15
- iconSize(size) {
16
- if (size === 's')
17
- return 12;
18
- if (size === 'l')
19
- return 20;
20
- return 16;
21
- }
22
- render() {
23
- const label = this.getAttribute('label') || this.textContent?.trim() || '';
24
- const size = this.getAttribute('size') || 'm';
25
- const variant = this.getAttribute('variant') || 'default';
26
- const disabled = this.hasAttribute('disabled');
27
- const deletable = this.hasAttribute('deletable');
28
- const selected = this.hasAttribute('selected');
29
- const fullWidth = this.hasAttribute('full-width');
30
- const clickable = this.hasAttribute('clickable');
31
- const startIcon = this.getAttribute('start-icon');
32
- const endIcon = this.getAttribute('end-icon');
33
- const resolvedSize = SIZES.includes(size) ? size : 'm';
34
- const resolvedVariant = VARIANTS.includes(variant) ? variant : 'default';
35
- const iconPx = this.iconSize(resolvedSize);
36
- this.className = [
37
- 'designbase-wc-chip',
38
- `designbase-wc-chip--${resolvedSize}`,
39
- `designbase-wc-chip--${resolvedVariant}`,
40
- deletable && 'designbase-wc-chip--deletable',
41
- disabled && 'designbase-wc-chip--disabled',
42
- selected && 'designbase-wc-chip--selected',
43
- clickable && 'designbase-wc-chip--clickable',
44
- fullWidth && 'designbase-wc-chip--full-width',
45
- ]
46
- .filter(Boolean)
47
- .join(' ');
48
- this.replaceChildren();
49
- if (clickable && !disabled) {
50
- this.setAttribute('role', 'button');
51
- this.tabIndex = 0;
52
- }
53
- else {
54
- this.removeAttribute('role');
55
- this.removeAttribute('tabindex');
56
- }
57
- if (startIcon) {
58
- const iconWrap = document.createElement('span');
59
- iconWrap.className = 'designbase-wc-chip__start-icon';
60
- iconWrap.append(createDbIcon(startIcon, iconPx));
61
- this.append(iconWrap);
62
- }
63
- const text = document.createElement('span');
64
- text.className = 'designbase-wc-chip__label';
65
- text.textContent = label;
66
- this.append(text);
67
- if (endIcon && !deletable) {
68
- const iconWrap = document.createElement('span');
69
- iconWrap.className = 'designbase-wc-chip__end-icon';
70
- iconWrap.append(createDbIcon(endIcon, iconPx));
71
- this.append(iconWrap);
72
- }
73
- if (deletable) {
74
- const button = document.createElement('button');
75
- button.type = 'button';
76
- button.className = 'designbase-wc-chip__delete-button';
77
- button.disabled = disabled;
78
- button.setAttribute('aria-label', `${label} 삭제`);
79
- button.append(createDbIcon('close', iconPx));
80
- button.addEventListener('click', (event) => {
81
- event.stopPropagation();
82
- if (!disabled) {
83
- this.dispatchEvent(new CustomEvent('db-delete', { bubbles: true, composed: true }));
84
- }
85
- });
86
- this.append(button);
87
- }
88
- this.onclick = () => {
89
- if (!disabled && clickable) {
90
- this.dispatchEvent(new CustomEvent('db-click', { bubbles: true, composed: true }));
91
- }
92
- };
93
- this.onkeydown = (event) => {
94
- if ((event.key === 'Enter' || event.key === ' ') && !disabled && clickable) {
95
- event.preventDefault();
96
- this.dispatchEvent(new CustomEvent('db-click', { bubbles: true, composed: true }));
97
- }
98
- };
99
- }
100
- }
101
- if (!customElements.get('db-chip'))
102
- customElements.define('db-chip', DbChip);
103
-
104
- export { DbChip };
1
+ import{isDbIconName as e,createDbIcon as t}from"./db-icons.js";const i=["s","m","l"],s=["default","primary","success","warning","danger","info","neutral"];class DbChip extends HTMLElement{static get observedAttributes(){return["label","size","variant","deletable","disabled","selected","full-width","clickable","start-icon","end-icon"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}iconSize(e){return"s"===e?12:"l"===e?20:16}render(){const n=this.getAttribute("label")||this.textContent?.trim()||"",c=this.getAttribute("size")||"m",a=this.getAttribute("variant")||"default",d=this.hasAttribute("disabled"),l=this.hasAttribute("deletable"),b=this.hasAttribute("selected"),h=this.hasAttribute("full-width"),r=this.hasAttribute("clickable"),o=this.getAttribute("start-icon"),p=this.getAttribute("end-icon"),u=i.includes(c)?c:"m",m=s.includes(a)?a:"default",g=this.iconSize(u);if(this.className=["designbase-wc-chip",`designbase-wc-chip--${u}`,`designbase-wc-chip--${m}`,l&&"designbase-wc-chip--deletable",d&&"designbase-wc-chip--disabled",b&&"designbase-wc-chip--selected",r&&"designbase-wc-chip--clickable",h&&"designbase-wc-chip--full-width"].filter(Boolean).join(" "),this.replaceChildren(),r&&!d?(this.setAttribute("role","button"),this.tabIndex=0):(this.removeAttribute("role"),this.removeAttribute("tabindex")),o&&e(o)){const e=document.createElement("span");e.className="designbase-wc-chip__start-icon",e.append(t(o,g)),this.append(e)}const w=document.createElement("span");if(w.className="designbase-wc-chip__label",w.textContent=n,this.append(w),p&&e(p)&&!l){const e=document.createElement("span");e.className="designbase-wc-chip__end-icon",e.append(t(p,g)),this.append(e)}if(l){const e=document.createElement("button");e.type="button",e.className="designbase-wc-chip__delete-button",e.disabled=d,e.setAttribute("aria-label",`${n} 삭제`),e.append(t("close",g)),e.addEventListener("click",e=>{e.stopPropagation(),d||this.dispatchEvent(new CustomEvent("db-delete",{bubbles:!0,composed:!0}))}),this.append(e)}this.onclick=()=>{!d&&r&&this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.onkeydown=e=>{"Enter"!==e.key&&" "!==e.key||d||!r||(e.preventDefault(),this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0})))}}}customElements.get("db-chip")||customElements.define("db-chip",DbChip);export{DbChip};