@designbasekorea/ui-wc 0.5.6 → 0.6.1
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.
- package/dist/chunks/lottie-35a9b0f5.js +1 -0
- package/dist/esm/components/animation-background/canvas-controller.js +1 -121
- package/dist/esm/components/animation-background/controls.js +1 -180
- package/dist/esm/components/animation-background/graphite-controller.js +1 -196
- package/dist/esm/components/animation-background/graphite-presets.js +1 -42
- package/dist/esm/components/animation-background/graphite-shader.js +1 -111
- package/dist/esm/components/animation-background/layers.js +1 -369
- package/dist/esm/components/animation-background/lumina-presets.js +1 -53
- package/dist/esm/components/animation-background/lumina-shaders.js +1 -181
- package/dist/esm/components/animation-background/lumina-utils.js +1 -60
- package/dist/esm/components/animation-background/particle-defaults.js +1 -36
- package/dist/esm/components/animation-background/renderers.js +1 -167
- package/dist/esm/components/animation-background/shader-controller.js +1 -154
- package/dist/esm/components/color-picker-utils.js +1 -134
- package/dist/esm/components/date-picker-utils.js +1 -140
- package/dist/esm/components/db-accordion.js +1 -304
- package/dist/esm/components/db-ad-banner.js +1 -455
- package/dist/esm/components/db-ai-chat-list.d.ts +43 -0
- package/dist/esm/components/db-ai-chat-list.js +1 -0
- package/dist/esm/components/db-ai-chat.d.ts +159 -0
- package/dist/esm/components/db-ai-chat.js +1 -0
- package/dist/esm/components/db-alert.js +1 -149
- package/dist/esm/components/db-animation-background.js +1 -486
- package/dist/esm/components/db-animation-text.js +1 -601
- package/dist/esm/components/db-app-badge.js +1 -88
- package/dist/esm/components/db-audio-player.js +1 -752
- package/dist/esm/components/db-avatar.js +1 -188
- package/dist/esm/components/db-backdrop.js +1 -139
- package/dist/esm/components/db-badge.js +1 -91
- package/dist/esm/components/db-banner.js +1 -188
- package/dist/esm/components/db-bottom-navigation.js +1 -146
- package/dist/esm/components/db-bottom-sheet.js +1 -481
- package/dist/esm/components/db-breadcrumbs.js +1 -329
- package/dist/esm/components/db-button.js +1 -316
- package/dist/esm/components/db-calendar.js +1 -675
- package/dist/esm/components/db-card.js +1 -265
- package/dist/esm/components/db-carousel.js +1 -264
- package/dist/esm/components/db-chat-composer.d.ts +134 -0
- package/dist/esm/components/db-chat-composer.js +1 -0
- package/dist/esm/components/db-chat-list.d.ts +47 -0
- package/dist/esm/components/db-chat-list.js +1 -0
- package/dist/esm/components/db-chat-message.d.ts +39 -0
- package/dist/esm/components/db-chat-message.js +1 -0
- package/dist/esm/components/db-chat-orb.d.ts +99 -0
- package/dist/esm/components/db-chat-orb.js +1 -0
- package/dist/esm/components/db-chat-room.d.ts +71 -0
- package/dist/esm/components/db-chat-room.js +1 -0
- package/dist/esm/components/db-chat-suggestions.d.ts +44 -0
- package/dist/esm/components/db-chat-suggestions.js +1 -0
- package/dist/esm/components/db-chat-typing.d.ts +22 -0
- package/dist/esm/components/db-chat-typing.js +1 -0
- package/dist/esm/components/db-chat-welcome.d.ts +32 -0
- package/dist/esm/components/db-chat-welcome.js +1 -0
- package/dist/esm/components/db-chat-widget.d.ts +146 -0
- package/dist/esm/components/db-chat-widget.js +1 -0
- package/dist/esm/components/db-checkbox.js +1 -202
- package/dist/esm/components/db-chip.js +1 -104
- package/dist/esm/components/db-code-block.js +1 -304
- package/dist/esm/components/db-color-picker.js +1 -746
- package/dist/esm/components/db-confirm.js +1 -191
- package/dist/esm/components/db-container.js +1 -39
- package/dist/esm/components/db-context-menu.js +1 -265
- package/dist/esm/components/db-countdown.js +1 -146
- package/dist/esm/components/db-cursor-follower.js +1 -173
- package/dist/esm/components/db-date-picker.js +1 -837
- package/dist/esm/components/db-divider.js +1 -66
- package/dist/esm/components/db-download-progress.d.ts +89 -0
- package/dist/esm/components/db-download-progress.js +1 -0
- package/dist/esm/components/db-drawer.js +1 -245
- package/dist/esm/components/db-dropdown.js +1 -493
- package/dist/esm/components/db-dropzone.js +1 -266
- package/dist/esm/components/db-email-verify.d.ts +64 -0
- package/dist/esm/components/db-email-verify.js +1 -0
- package/dist/esm/components/db-empty-state.js +1 -97
- package/dist/esm/components/db-file-uploader.js +1 -256
- package/dist/esm/components/db-floating-action-button.js +1 -139
- package/dist/esm/components/db-footer.js +1 -385
- package/dist/esm/components/db-form.js +1 -566
- package/dist/esm/components/db-gantt.js +1 -882
- package/dist/esm/components/db-gradient.js +1 -133
- package/dist/esm/components/db-grid-background.js +1 -909
- package/dist/esm/components/db-grid.js +1 -73
- package/dist/esm/components/db-icons.d.ts +3 -0
- package/dist/esm/components/db-icons.js +1 -82
- package/dist/esm/components/db-image-list.js +1 -214
- package/dist/esm/components/db-image-placeholder.js +1 -96
- package/dist/esm/components/db-image.js +1 -289
- package/dist/esm/components/db-indicator.js +1 -517
- package/dist/esm/components/db-input.js +1 -420
- package/dist/esm/components/db-kanban.js +1 -538
- package/dist/esm/components/db-label.js +1 -66
- package/dist/esm/components/db-lightbox.js +1 -372
- package/dist/esm/components/db-list.js +1 -340
- package/dist/esm/components/db-logo-svg.js +1 -72
- package/dist/esm/components/db-logo.js +1 -106
- package/dist/esm/components/db-lottie.js +1 -109
- package/dist/esm/components/db-markdown-editor.js +1 -458
- package/dist/esm/components/db-marquee.js +1 -402
- package/dist/esm/components/db-masonry.js +1 -94
- package/dist/esm/components/db-menu-item.js +1 -211
- package/dist/esm/components/db-modal.js +1 -522
- package/dist/esm/components/db-navbar.js +1 -680
- package/dist/esm/components/db-onboarding-modal.js +1 -322
- package/dist/esm/components/db-otp-input.d.ts +53 -0
- package/dist/esm/components/db-otp-input.js +1 -0
- package/dist/esm/components/db-page-header.js +1 -312
- package/dist/esm/components/db-pagination.js +1 -271
- package/dist/esm/components/db-phone-verify.d.ts +63 -0
- package/dist/esm/components/db-phone-verify.js +1 -0
- package/dist/esm/components/db-popover.js +1 -580
- package/dist/esm/components/db-progress-step.js +1 -166
- package/dist/esm/components/db-progress.js +1 -171
- package/dist/esm/components/db-progressbar.js +1 -72
- package/dist/esm/components/db-radio.js +1 -172
- package/dist/esm/components/db-random-gradient.js +1 -121
- package/dist/esm/components/db-range-slider.js +1 -811
- package/dist/esm/components/db-rating.js +1 -325
- package/dist/esm/components/db-reorder.js +1 -286
- package/dist/esm/components/db-resizable-panels.js +1 -282
- package/dist/esm/components/db-scroll-area.js +1 -126
- package/dist/esm/components/db-search-bar.js +1 -668
- package/dist/esm/components/db-section-app-download.js +1 -101
- package/dist/esm/components/db-section-contact.js +1 -102
- package/dist/esm/components/db-section-cta.js +1 -150
- package/dist/esm/components/db-section-faq.js +1 -120
- package/dist/esm/components/db-section-feature-grid.js +1 -137
- package/dist/esm/components/db-section-feature.js +1 -179
- package/dist/esm/components/db-section-hero.js +1 -243
- package/dist/esm/components/db-section-logo-cloud.js +1 -138
- package/dist/esm/components/db-section-pricing.js +1 -166
- package/dist/esm/components/db-section-stats.js +1 -129
- package/dist/esm/components/db-section-testimonials.js +1 -252
- package/dist/esm/components/db-section.js +1 -385
- package/dist/esm/components/db-segment-control.js +1 -231
- package/dist/esm/components/db-select.js +1 -571
- package/dist/esm/components/db-share-icons.js +1 -40
- package/dist/esm/components/db-share.js +1 -489
- package/dist/esm/components/db-sidebar.d.ts +20 -0
- package/dist/esm/components/db-sidebar.js +1 -1068
- package/dist/esm/components/db-skeleton.js +1 -94
- package/dist/esm/components/db-spinner.js +1 -102
- package/dist/esm/components/db-split-view.js +1 -297
- package/dist/esm/components/db-stack.js +1 -46
- package/dist/esm/components/db-stat.js +1 -218
- package/dist/esm/components/db-stepper.js +1 -398
- package/dist/esm/components/db-table.js +1 -412
- package/dist/esm/components/db-tabs.js +1 -335
- package/dist/esm/components/db-testimonial.d.ts +2 -0
- package/dist/esm/components/db-testimonial.js +1 -162
- package/dist/esm/components/db-textarea.js +1 -233
- package/dist/esm/components/db-time-picker.js +1 -523
- package/dist/esm/components/db-timeline.js +1 -174
- package/dist/esm/components/db-toast.js +1 -158
- package/dist/esm/components/db-toggle.js +1 -162
- package/dist/esm/components/db-toolbar.js +1 -94
- package/dist/esm/components/db-tooltip.js +1 -440
- package/dist/esm/components/db-top-banner.js +1 -121
- package/dist/esm/components/db-tutorial.js +1 -324
- package/dist/esm/components/db-two-factor.d.ts +71 -0
- package/dist/esm/components/db-two-factor.js +1 -0
- package/dist/esm/components/db-video-player.js +1 -503
- package/dist/esm/components/db-youtube-player.js +1 -194
- package/dist/esm/components/highlight-code.js +1 -65
- package/dist/esm/components/input-validation.js +1 -50
- package/dist/esm/components/marketing-block-host-utils.js +1 -9
- package/dist/esm/components/number-scrub.js +1 -117
- package/dist/esm/components/random-gradient-palettes.js +1 -67
- package/dist/esm/components/section-block-header-utils.js +1 -48
- package/dist/esm/helpers/confirm.js +1 -52
- package/dist/esm/helpers/toast.js +1 -73
- package/dist/esm/index.d.ts +16 -0
- package/dist/esm/index.js +1 -111
- package/dist/esm/node_modules/prismjs/components/prism-bash.js +1 -235
- package/dist/esm/node_modules/prismjs/components/prism-clike.js +1 -31
- package/dist/esm/node_modules/prismjs/components/prism-css.js +1 -64
- package/dist/esm/node_modules/prismjs/components/prism-javascript.js +1 -172
- package/dist/esm/node_modules/prismjs/components/prism-json.js +1 -27
- package/dist/esm/node_modules/prismjs/components/prism-jsx.js +1 -143
- package/dist/esm/node_modules/prismjs/components/prism-markup.js +1 -186
- package/dist/esm/node_modules/prismjs/components/prism-scss.js +1 -81
- package/dist/esm/node_modules/prismjs/components/prism-tsx.js +1 -15
- package/dist/esm/node_modules/prismjs/components/prism-typescript.js +1 -60
- package/dist/index.cjs +1 -55414
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1125 -2
- package/dist/index.esm.js +1 -38284
- package/dist/react/chunks/lottie-14e7addb.js +1 -0
- package/dist/react/index.cjs +1 -56503
- package/dist/react/index.d.ts +1637 -21
- package/dist/react/index.esm.js +1 -39373
- package/package.json +2 -2
- package/dist/chunks/lottie-e273b936.js +0 -17032
- 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
|
|
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
|
|
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};
|