@designbasekorea/ui-wc 0.8.12 → 0.9.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.
- package/CHANGELOG.md +56 -0
- package/LICENSE-PAYMENT-LOGOS.md +437 -0
- package/README.md +61 -23
- package/dist/esm/components/db-achievement-list.d.ts +31 -0
- package/dist/esm/components/db-achievement-list.js +1 -0
- package/dist/esm/components/db-achievement-modal.d.ts +38 -0
- package/dist/esm/components/db-achievement-modal.js +1 -0
- package/dist/esm/components/db-ai-chain-of-thought.d.ts +14 -0
- package/dist/esm/components/db-ai-chain-of-thought.js +1 -0
- package/dist/esm/components/db-ai-chat.js +1 -1
- package/dist/esm/components/db-ai-checkpoint.d.ts +14 -0
- package/dist/esm/components/db-ai-checkpoint.js +1 -0
- package/dist/esm/components/db-ai-confirmation.d.ts +14 -0
- package/dist/esm/components/db-ai-confirmation.js +1 -0
- package/dist/esm/components/db-ai-context.d.ts +15 -0
- package/dist/esm/components/db-ai-context.js +1 -0
- package/dist/esm/components/db-ai-conversation.d.ts +21 -0
- package/dist/esm/components/db-ai-conversation.js +1 -0
- package/dist/esm/components/db-ai-execution-quote.d.ts +41 -0
- package/dist/esm/components/db-ai-execution-quote.js +1 -0
- package/dist/esm/components/db-ai-file-tree.d.ts +14 -0
- package/dist/esm/components/db-ai-file-tree.js +1 -0
- package/dist/esm/components/db-ai-glow.d.ts +1 -1
- package/dist/esm/components/db-ai-inline-citation.d.ts +16 -0
- package/dist/esm/components/db-ai-inline-citation.js +1 -0
- package/dist/esm/components/db-ai-message.d.ts +19 -0
- package/dist/esm/components/db-ai-message.js +1 -0
- package/dist/esm/components/db-ai-model-select.d.ts +36 -0
- package/dist/esm/components/db-ai-model-select.js +1 -0
- package/dist/esm/components/db-ai-plan.d.ts +14 -0
- package/dist/esm/components/db-ai-plan.js +1 -0
- package/dist/esm/components/db-ai-queue.d.ts +14 -0
- package/dist/esm/components/db-ai-queue.js +1 -0
- package/dist/esm/components/db-ai-reasoning.d.ts +14 -0
- package/dist/esm/components/db-ai-reasoning.js +1 -0
- package/dist/esm/components/db-ai-sources.d.ts +14 -0
- package/dist/esm/components/db-ai-sources.js +1 -0
- package/dist/esm/components/db-ai-stack-trace.d.ts +14 -0
- package/dist/esm/components/db-ai-stack-trace.js +1 -0
- package/dist/esm/components/db-ai-subagent.d.ts +14 -0
- package/dist/esm/components/db-ai-subagent.js +1 -0
- package/dist/esm/components/db-ai-task-status.d.ts +26 -0
- package/dist/esm/components/db-ai-task-status.js +1 -0
- package/dist/esm/components/db-ai-task.d.ts +14 -0
- package/dist/esm/components/db-ai-task.js +1 -0
- package/dist/esm/components/db-ai-terminal.d.ts +14 -0
- package/dist/esm/components/db-ai-terminal.js +1 -0
- package/dist/esm/components/db-ai-test-results.d.ts +14 -0
- package/dist/esm/components/db-ai-test-results.js +1 -0
- package/dist/esm/components/db-ai-tool.d.ts +14 -0
- package/dist/esm/components/db-ai-tool.js +1 -0
- package/dist/esm/components/db-attachment-list.d.ts +38 -0
- package/dist/esm/components/db-attachment-list.js +1 -0
- package/dist/esm/components/db-bento-card.d.ts +55 -0
- package/dist/esm/components/db-bento-card.js +1 -0
- package/dist/esm/components/db-bento-grid.d.ts +25 -0
- package/dist/esm/components/db-bento-grid.js +1 -0
- package/dist/esm/components/db-boarding-pass-stack.d.ts +49 -0
- package/dist/esm/components/db-boarding-pass-stack.js +1 -0
- package/dist/esm/components/db-boarding-pass.d.ts +32 -0
- package/dist/esm/components/db-boarding-pass.js +1 -0
- package/dist/esm/components/db-border-beam.d.ts +52 -0
- package/dist/esm/components/db-border-beam.js +1 -0
- package/dist/esm/components/db-button.d.ts +1 -1
- package/dist/esm/components/db-button.js +1 -1
- package/dist/esm/components/db-chat-composer.d.ts +2 -0
- package/dist/esm/components/db-chat-composer.js +1 -1
- package/dist/esm/components/db-chat-message.d.ts +1 -1
- package/dist/esm/components/db-chat-orb.d.ts +1 -1
- package/dist/esm/components/db-chat-widget.d.ts +1 -1
- package/dist/esm/components/db-color-picker.d.ts +1 -0
- package/dist/esm/components/db-color-picker.js +1 -1
- package/dist/esm/components/db-confetti.d.ts +90 -0
- package/dist/esm/components/db-confetti.js +1 -0
- package/dist/esm/components/db-context-bar.d.ts +13 -0
- package/dist/esm/components/db-context-bar.js +1 -0
- package/dist/esm/components/db-credit-balance.d.ts +17 -0
- package/dist/esm/components/db-credit-balance.js +1 -0
- package/dist/esm/components/db-credit-card.d.ts +51 -0
- package/dist/esm/components/db-credit-card.js +1 -0
- package/dist/esm/components/db-credit-dropdown.d.ts +31 -0
- package/dist/esm/components/db-credit-dropdown.js +1 -0
- package/dist/esm/components/db-credit-history.d.ts +31 -0
- package/dist/esm/components/db-credit-history.js +1 -0
- package/dist/esm/components/db-credit-recharge-modal.d.ts +35 -0
- package/dist/esm/components/db-credit-recharge-modal.js +1 -0
- package/dist/esm/components/db-credit-recharge.d.ts +39 -0
- package/dist/esm/components/db-credit-recharge.js +1 -0
- package/dist/esm/components/db-design-canvas.d.ts +137 -0
- package/dist/esm/components/db-design-canvas.js +1 -0
- package/dist/esm/components/db-design-toolbar.d.ts +60 -0
- package/dist/esm/components/db-design-toolbar.js +1 -0
- package/dist/esm/components/db-device-mockup.d.ts +100 -0
- package/dist/esm/components/db-device-mockup.js +1 -0
- package/dist/esm/components/db-download-progress.d.ts +1 -1
- package/dist/esm/components/db-drawer.js +1 -1
- package/dist/esm/components/db-dropdown.d.ts +2 -0
- package/dist/esm/components/db-dropdown.js +1 -1
- package/dist/esm/components/db-email-verify.d.ts +1 -1
- package/dist/esm/components/db-file-uploader.d.ts +10 -0
- package/dist/esm/components/db-filter-bar.d.ts +34 -0
- package/dist/esm/components/db-filter-bar.js +1 -0
- package/dist/esm/components/db-flight-status.d.ts +33 -0
- package/dist/esm/components/db-flight-status.js +1 -0
- package/dist/esm/components/db-floating-action-button.d.ts +24 -14
- package/dist/esm/components/db-floating-action-button.js +1 -1
- package/dist/esm/components/db-footer.d.ts +3 -0
- package/dist/esm/components/db-footer.js +1 -1
- package/dist/esm/components/db-form.js +1 -1
- package/dist/esm/components/db-glyph-matrix.d.ts +58 -0
- package/dist/esm/components/db-glyph-matrix.js +1 -0
- package/dist/esm/components/db-icons.d.ts +1 -1
- package/dist/esm/components/db-icons.js +1 -1
- package/dist/esm/components/db-menu-item.d.ts +2 -0
- package/dist/esm/components/db-menu-item.js +1 -1
- package/dist/esm/components/db-modal.d.ts +1 -1
- package/dist/esm/components/db-modal.js +1 -1
- package/dist/esm/components/db-navbar.d.ts +3 -1
- package/dist/esm/components/db-navbar.js +1 -1
- package/dist/esm/components/db-navigation-rail.d.ts +1 -1
- package/dist/esm/components/db-node.d.ts +83 -0
- package/dist/esm/components/db-node.js +1 -0
- package/dist/esm/components/db-notification-dropdown.d.ts +30 -0
- package/dist/esm/components/db-notification-dropdown.js +1 -0
- package/dist/esm/components/db-notification-inbox.d.ts +25 -0
- package/dist/esm/components/db-notification-inbox.js +1 -0
- package/dist/esm/components/db-otp-input.d.ts +1 -1
- package/dist/esm/components/db-phone-verify.d.ts +1 -1
- package/dist/esm/components/db-plan-overview.d.ts +26 -0
- package/dist/esm/components/db-plan-overview.js +1 -0
- package/dist/esm/components/db-popover.js +1 -1
- package/dist/esm/components/db-progressive-blur.d.ts +35 -0
- package/dist/esm/components/db-progressive-blur.js +1 -0
- package/dist/esm/components/db-receipt.d.ts +37 -0
- package/dist/esm/components/db-receipt.js +1 -0
- package/dist/esm/components/db-search-bar.js +1 -1
- package/dist/esm/components/db-segment-control.js +1 -1
- package/dist/esm/components/db-select.js +1 -1
- package/dist/esm/components/db-sidebar.d.ts +14 -1
- package/dist/esm/components/db-sidebar.js +1 -1
- package/dist/esm/components/db-split-view.d.ts +2 -0
- package/dist/esm/components/db-split-view.js +1 -1
- package/dist/esm/components/db-textarea.js +1 -1
- package/dist/esm/components/db-ticket.d.ts +18 -0
- package/dist/esm/components/db-ticket.js +1 -0
- package/dist/esm/components/db-time-picker.d.ts +1 -1
- package/dist/esm/components/db-tool-button.d.ts +57 -0
- package/dist/esm/components/db-tool-button.js +1 -0
- package/dist/esm/components/db-tweet-card.d.ts +101 -0
- package/dist/esm/components/db-tweet-card.js +1 -0
- package/dist/esm/components/db-two-factor.d.ts +1 -1
- package/dist/esm/components/db-voice-control.d.ts +25 -0
- package/dist/esm/components/db-voice-control.js +1 -0
- package/dist/esm/components/db-workspace-invite-modal.d.ts +51 -0
- package/dist/esm/components/db-workspace-invite-modal.js +1 -0
- package/dist/esm/components/db-workspace-members.d.ts +36 -0
- package/dist/esm/components/db-workspace-members.js +1 -0
- package/dist/esm/components/device-mockup-style.js +1 -0
- package/dist/esm/components/flight-route.js +1 -0
- package/dist/esm/components/node-style.js +1 -0
- package/dist/esm/components/paper-card.d.ts +26 -0
- package/dist/esm/components/paper-card.js +1 -0
- package/dist/esm/components/random-gradient-palettes.d.ts +4 -0
- package/dist/esm/core/ai-element.d.ts +47 -0
- package/dist/esm/core/ai-element.js +1 -0
- package/dist/esm/core/credit-ui.js +1 -0
- package/dist/esm/core/i18n.d.ts +153 -0
- package/dist/esm/core/i18n.js +1 -1
- package/dist/esm/core/notification-ui.d.ts +17 -0
- package/dist/esm/core/notification-ui.js +1 -0
- package/dist/esm/helpers/payment-brands.d.ts +56 -0
- package/dist/esm/helpers/payment-brands.js +1 -0
- package/dist/esm/helpers/toast.d.ts +2 -3
- package/dist/esm/index.d.ts +62 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/node_modules/@designbasekorea/ui-contracts/dist/components.js +1 -1
- package/dist/esm/ui-contracts/dist/components.d.d.ts +76 -0
- package/dist/esm/ui-contracts/dist/primitives.d.d.ts +21 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2149 -23
- package/dist/index.esm.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +786 -6727
- package/dist/react/index.esm.js +1 -1
- package/package.json +13 -7
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DbAiDataElement } from '../core/ai-element.js';
|
|
2
|
+
|
|
3
|
+
/** AI Elements: terminal. App-owned data and actions; no provider calls. */
|
|
4
|
+
declare class DbAiTerminal extends DbAiDataElement {
|
|
5
|
+
static get observedAttributes(): string[];
|
|
6
|
+
protected view(): Node[];
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
'db-ai-terminal': DbAiTerminal;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { DbAiTerminal };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DbAiDataElement as t,aiCode as e}from"../core/ai-element.js";class DbAiTerminal extends t{static get observedAttributes(){return["label","status","input","output","open"]}view(){const t=[];return this.attr("input")&&t.push(e(`$ ${this.attr("input")}`,"bash")),t.push(e(this.attr("output"),"text")),[this.disclosure("root",this.attr("label","terminal"),this.state,t,this.hasAttribute("open"),"code")]}}customElements.get("db-ai-terminal")||customElements.define("db-ai-terminal",DbAiTerminal);export{DbAiTerminal};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DbAiDataElement } from '../core/ai-element.js';
|
|
2
|
+
|
|
3
|
+
/** AI Elements: test-results. App-owned data and actions; no provider calls. */
|
|
4
|
+
declare class DbAiTestResults extends DbAiDataElement {
|
|
5
|
+
static get observedAttributes(): string[];
|
|
6
|
+
protected view(): Node[];
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
'db-ai-test-results': DbAiTestResults;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { DbAiTestResults };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DbAiDataElement as t,aiNode as e}from"../core/ai-element.js";import{t as s}from"../core/i18n.js";class DbAiTestResults extends t{static get observedAttributes(){return["items","label","status","open"]}view(){const t=this.rows.filter(t=>"complete"===t.status).length,i=this.rows.filter(t=>"error"===t.status).length,r=e("div","designbase-wc-ai__timeline","");r.append(...this.rows.map(t=>this.itemLine(t)));const l=`${this.attr("label","tests")} · ${t} ${s("aiElement.passed")}${i?` · ${i} ${s("aiElement.failed")}`:""}`;return[this.disclosure("root",l,i?"error":this.state,[r],this.hasAttribute("open"),"circle-checked")]}}customElements.get("db-ai-test-results")||customElements.define("db-ai-test-results",DbAiTestResults);export{DbAiTestResults};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DbAiDataElement } from '../core/ai-element.js';
|
|
2
|
+
|
|
3
|
+
/** AI Elements: tool. App-owned data and actions; no provider calls. */
|
|
4
|
+
declare class DbAiTool extends DbAiDataElement {
|
|
5
|
+
static get observedAttributes(): string[];
|
|
6
|
+
protected view(): Node[];
|
|
7
|
+
}
|
|
8
|
+
declare global {
|
|
9
|
+
interface HTMLElementTagNameMap {
|
|
10
|
+
'db-ai-tool': DbAiTool;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { DbAiTool };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DbAiDataElement as t,aiNode as e,aiCode as s}from"../core/ai-element.js";import{t as i}from"../core/i18n.js";class DbAiTool extends t{static get observedAttributes(){return["label","description","status","input","output","language","open"]}view(){const t=[];for(const o of["input","output"])this.hasAttribute(o)&&t.push(e("span","designbase-wc-ai__meta",i(`aiElement.${o}`)),s(this.attr(o),this.attr("language")||"json"));return this.attr("description")&&t.push(e("p","designbase-wc-ai__description",this.attr("description"))),[this.disclosure("root",this.attr("label","tool"),this.state,t,this.hasAttribute("open"),"code")]}}customElements.get("db-ai-tool")||customElements.define("db-ai-tool",DbAiTool);export{DbAiTool};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import './db-button.js';
|
|
2
|
+
import { DbElement } from '../core/base-element.js';
|
|
3
|
+
import './db-badge.js';
|
|
4
|
+
import './db-progressbar.js';
|
|
5
|
+
|
|
6
|
+
type DbAttachmentState = 'queued' | 'uploading' | 'processing' | 'ready' | 'error' | 'cancelled';
|
|
7
|
+
interface DbAttachment {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
bytes: number;
|
|
11
|
+
state: DbAttachmentState;
|
|
12
|
+
progress?: number | null;
|
|
13
|
+
error?: string;
|
|
14
|
+
canOpen?: boolean;
|
|
15
|
+
canRetry?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface DbAttachmentAction {
|
|
18
|
+
id: string;
|
|
19
|
+
}
|
|
20
|
+
/** Controlled presentation. No timer, upload request, public URL or storage credential. */
|
|
21
|
+
declare class DbAttachmentList extends DbElement {
|
|
22
|
+
private data;
|
|
23
|
+
static get observedAttributes(): string[];
|
|
24
|
+
get attachments(): DbAttachment[];
|
|
25
|
+
set attachments(value: DbAttachment[]);
|
|
26
|
+
connectedCallback(): void;
|
|
27
|
+
attributeChangedCallback(): void;
|
|
28
|
+
private blocked;
|
|
29
|
+
private render;
|
|
30
|
+
}
|
|
31
|
+
declare global {
|
|
32
|
+
interface HTMLElementTagNameMap {
|
|
33
|
+
'db-attachment-list': DbAttachmentList;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { DbAttachmentList };
|
|
38
|
+
export type { DbAttachment, DbAttachmentAction, DbAttachmentState };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./db-button.js";import{createDbIcon as t}from"./db-icons.js";import{DbElement as e}from"../core/base-element.js";import{textNode as a,creditAction as s,replaceView as r}from"../core/credit-ui.js";import{t as n}from"../core/i18n.js";import"./db-badge.js";import"./db-progressbar.js";const i=["queued","uploading","processing","ready","error","cancelled"];class DbAttachmentList extends e{constructor(){super(...arguments),this.data=[]}static get observedAttributes(){return["label","loading","disabled","error"]}get attachments(){return this.data.map(t=>({...t}))}set attachments(t){const e=new Set;this.data=Array.isArray(t)?t.filter(t=>!(!t||"string"!=typeof t.id||!t.id||e.has(t.id)||"string"!=typeof t.name||!Number.isSafeInteger(t.bytes)||t.bytes<0||!i.includes(t.state)||null!=t.progress&&(!Number.isFinite(t.progress)||t.progress<0||t.progress>100)||void 0!==t.error&&"string"!=typeof t.error||void 0!==t.canOpen&&"boolean"!=typeof t.canOpen||void 0!==t.canRetry&&"boolean"!=typeof t.canRetry)&&(e.add(t.id),!0)).map(t=>({...t})):[],this.isConnected&&this.render()}connectedCallback(){this.upgradeProperties(["attachments"]),this.cleanups.listen(this,"db-click",t=>{if(!(t.target instanceof HTMLElement)||this.blocked())return;const e=t.target;if("attachment-reload"===e.dataset.action)return void this.dbEmit("reload");if(this.hasAttribute("error"))return;const a=this.data.find(t=>t.id===e.dataset.attachmentId);if(!a)return;const s=e.dataset.intent,r="queued"===a.state||"uploading"===a.state;("cancel"===s&&r||"retry"===s&&a.canRetry&&["error","cancelled"].includes(a.state)||"remove"===s&&["ready","error","cancelled"].includes(a.state)||"open"===s&&"ready"===a.state&&a.canOpen)&&this.dbEmit(s,{id:a.id})}),this.render()}attributeChangedCallback(){this.isConnected&&this.render()}blocked(){return this.hasAttribute("loading")||this.hasAttribute("disabled")}render(){const e=document.activeElement,i=e instanceof HTMLElement&&this.contains(e),d=i?e.closest("[data-id]")?.dataset.id:void 0,o=d?Array.from(this.querySelectorAll("[data-id]")).findIndex(t=>t.dataset.id===d):-1,c="designbase-wc-attachment-list";this.classList.add(c),this.setAttribute("aria-busy",String(this.hasAttribute("loading")));const l=a("div",`${c}__header`,""),u=a("h3","",this.getAttribute("label")||n("attachment.title"));u.tabIndex=-1,l.append(u,a("span","",String(this.data.length)));const h=[l],p=this.getAttribute("error");if(p){const t=a("p",`${c}__error`,p);t.setAttribute("role","alert"),h.push(t,s("attachment-reload",n("attachment.reload"),this.blocked()))}if(this.hasAttribute("loading")||!this.data.length){const t=a("p",`${c}__message`,n(this.hasAttribute("loading")?"loading":"attachment.empty"));t.setAttribute("role","status"),h.push(t)}else{const e=a("ul",`${c}__list`,"");for(const r of this.data){const i=a("li",`${c}__row`,"");i.dataset.state=r.state,i.dataset.id=r.id;const d=a("div",`${c}__content`,""),o=a("div",`${c}__identity`,""),l=r.bytes<1024?`${r.bytes} B`:r.bytes<1048576?`${(r.bytes/1024).toFixed(1)} KB`:`${(r.bytes/1048576).toFixed(1)} MB`;o.append(a("strong","",r.name),a("span","",l));const u=document.createElement("db-badge");u.setAttribute("type","text"),u.setAttribute("variant","secondary"),u.textContent=n(`attachment.${r.state}`);const h={queued:"clock",uploading:"upload",processing:"clock",ready:"circle-checked",error:"error-filled",cancelled:"close"};if(u.prepend(t(h[r.state],14)),d.append(o,u),i.append(d),"uploading"===r.state&&null!=r.progress){const t=document.createElement("db-progressbar");t.setAttribute("value",String(r.progress)),t.setAttribute("size","s"),t.setAttribute("variant","primary"),t.setAttribute("full-width",""),t.setAttribute("label",`${r.name} · ${Math.round(r.progress)}%`),i.append(t)}else"uploading"===r.state&&i.append(a("p",`${c}__message`,n("attachment.unknown")));"error"===r.state&&r.error&&i.append(a("p",`${c}__error`,r.error));const b=a("div",`${c}__actions`,""),add=t=>{const e=s(`attachment-${t}:${r.id}`,n(`attachment.${t}`),this.blocked()||!!p);e.dataset.attachmentId=r.id,e.dataset.intent=t,e.setAttribute("aria-label",`${r.name} · ${n(`attachment.${t}`)}`),b.append(e)};"queued"!==r.state&&"uploading"!==r.state||add("cancel"),r.canRetry&&["error","cancelled"].includes(r.state)&&add("retry"),"ready"===r.state&&r.canOpen&&add("open"),["ready","error","cancelled"].includes(r.state)&&add("remove"),i.append(b),e.append(i)}h.push(e)}if(r(this,...h),i&&!this.contains(document.activeElement)){const t=Array.from(this.querySelectorAll("[data-id]")),e=t[Math.min(Math.max(o,0),t.length-1)],a=e?.querySelector("db-button:not([disabled])");(a||u).focus()}}}customElements.get("db-attachment-list")||customElements.define("db-attachment-list",DbAttachmentList);export{DbAttachmentList};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { BentoCardVariant, BentoCardSize, BentoCardImagePosition } from '../ui-contracts/dist/components.d.js';
|
|
2
|
+
|
|
3
|
+
declare class DbBentoCard extends HTMLElement {
|
|
4
|
+
static get observedAttributes(): string[];
|
|
5
|
+
private built;
|
|
6
|
+
private bgWrapper?;
|
|
7
|
+
private imgEl?;
|
|
8
|
+
private contentWrapper?;
|
|
9
|
+
private iconEl?;
|
|
10
|
+
private titleEl?;
|
|
11
|
+
private descEl?;
|
|
12
|
+
private ctaWrapper?;
|
|
13
|
+
private ctaBtn?;
|
|
14
|
+
private ctaTextSpan?;
|
|
15
|
+
private overlayEl?;
|
|
16
|
+
get name(): string;
|
|
17
|
+
set name(value: string);
|
|
18
|
+
get description(): string;
|
|
19
|
+
set description(value: string);
|
|
20
|
+
get icon(): string;
|
|
21
|
+
set icon(value: string);
|
|
22
|
+
get href(): string;
|
|
23
|
+
set href(value: string);
|
|
24
|
+
get cta(): string;
|
|
25
|
+
set cta(value: string);
|
|
26
|
+
get colSpan(): string;
|
|
27
|
+
set colSpan(value: string);
|
|
28
|
+
get rowSpan(): string;
|
|
29
|
+
set rowSpan(value: string);
|
|
30
|
+
get variant(): BentoCardVariant;
|
|
31
|
+
set variant(value: BentoCardVariant);
|
|
32
|
+
get size(): BentoCardSize;
|
|
33
|
+
set size(value: BentoCardSize);
|
|
34
|
+
get disabled(): boolean;
|
|
35
|
+
set disabled(value: boolean);
|
|
36
|
+
get image(): string;
|
|
37
|
+
set image(value: string);
|
|
38
|
+
get imageAlt(): string;
|
|
39
|
+
set imageAlt(value: string);
|
|
40
|
+
get imagePosition(): BentoCardImagePosition;
|
|
41
|
+
set imagePosition(value: BentoCardImagePosition);
|
|
42
|
+
connectedCallback(): void;
|
|
43
|
+
disconnectedCallback(): void;
|
|
44
|
+
attributeChangedCallback(): void;
|
|
45
|
+
private handleCtaClick;
|
|
46
|
+
private build;
|
|
47
|
+
private sync;
|
|
48
|
+
}
|
|
49
|
+
declare global {
|
|
50
|
+
interface HTMLElementTagNameMap {
|
|
51
|
+
'db-bento-card': DbBentoCard;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { DbBentoCard };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createDbIcon as t,isDbIconName as e}from"./db-icons.js";import{sanitizeHref as i}from"../core/safe-url.js";import{t as s}from"../core/i18n.js";import{coerceToContract as a}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BENTO_CARD_VARIANTS as r,BENTO_CARD_SIZES as n,BENTO_CARD_IMAGE_POSITIONS as h}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const c="designbase-wc-bento-card";class DbBentoCard extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.handleCtaClick=t=>{this.disabled?t.preventDefault():this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0,detail:{name:this.name,href:this.href}}))}}static get observedAttributes(){return["name","title","description","icon","href","cta","col-span","row-span","variant","size","target","disabled","image","image-alt","image-position"]}get name(){return this.getAttribute("name")||this.getAttribute("title")||""}set name(t){this.setAttribute("name",t)}get description(){return this.getAttribute("description")||""}set description(t){this.setAttribute("description",t)}get icon(){return this.getAttribute("icon")||""}set icon(t){this.setAttribute("icon",t)}get href(){return this.getAttribute("href")||""}set href(t){this.setAttribute("href",t)}get cta(){return this.getAttribute("cta")||""}set cta(t){this.setAttribute("cta",t)}get colSpan(){const t=this.getAttribute("col-span");return t&&["1","2","3","4"].includes(t)?t:"1"}set colSpan(t){this.setAttribute("col-span",t)}get rowSpan(){const t=this.getAttribute("row-span");return t&&["1","2","3"].includes(t)?t:"1"}set rowSpan(t){this.setAttribute("row-span",t)}get variant(){return a(this.getAttribute("variant"),r,"default")}set variant(t){this.setAttribute("variant",t)}get size(){return a(this.getAttribute("size"),n,"m")}set size(t){this.setAttribute("size",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get image(){return this.getAttribute("image")||""}set image(t){this.setAttribute("image",t)}get imageAlt(){return this.getAttribute("image-alt")||this.name}set imageAlt(t){this.setAttribute("image-alt",t)}get imagePosition(){return a(this.getAttribute("image-position"),h,"top")}set imagePosition(t){this.setAttribute("image-position",t)}connectedCallback(){this.built||(this.build(),this.built=!0),this.sync()}disconnectedCallback(){this.ctaBtn?.removeEventListener("click",this.handleCtaClick)}attributeChangedCallback(){this.built&&this.sync()}build(){const e=Array.from(this.childNodes);this.bgWrapper=document.createElement("div"),this.bgWrapper.className=`${c}__background`,this.bgWrapper.setAttribute("aria-hidden","true"),e.forEach(t=>{this.bgWrapper?.appendChild(t)}),this.contentWrapper=document.createElement("div"),this.contentWrapper.className=`${c}__content`,this.iconEl=document.createElement("div"),this.iconEl.className=`${c}__icon`,this.iconEl.setAttribute("aria-hidden","true"),this.titleEl=document.createElement("h3"),this.titleEl.className=`${c}__title`,this.descEl=document.createElement("p"),this.descEl.className=`${c}__description`,this.contentWrapper.append(this.iconEl,this.titleEl,this.descEl),this.ctaWrapper=document.createElement("div"),this.ctaWrapper.className=`${c}__cta`,this.ctaBtn=document.createElement("a"),this.ctaBtn.className=`${c}__cta-btn`,this.ctaBtn.addEventListener("click",this.handleCtaClick),this.ctaTextSpan=document.createElement("span"),this.ctaBtn.appendChild(this.ctaTextSpan);const i=t("arrow-right",16);i.setAttribute("aria-hidden","true"),this.ctaBtn.appendChild(i),this.ctaWrapper.appendChild(this.ctaBtn),this.overlayEl=document.createElement("div"),this.overlayEl.className=`${c}__overlay`,this.overlayEl.setAttribute("aria-hidden","true"),this.append(this.bgWrapper,this.contentWrapper,this.ctaWrapper,this.overlayEl)}sync(){if(this.classList.add(c),this.titleEl&&(this.titleEl.textContent=this.name,this.titleEl.hidden=!this.name),this.descEl&&(this.descEl.textContent=this.description,this.descEl.hidden=!this.description),this.iconEl){const i=this.icon;i&&e(i)?(this.iconEl.replaceChildren(t(i,24)),this.iconEl.hidden=!1):i?(this.iconEl.replaceChildren(t("sparkle",24)),this.iconEl.hidden=!1):(this.iconEl.replaceChildren(),this.iconEl.hidden=!0)}const a=this.href,h=this.cta||s("bentoCard.cta");if(this.ctaWrapper&&this.ctaBtn&&this.ctaTextSpan)if(a||this.cta){this.ctaWrapper.hidden=!1,this.ctaTextSpan.textContent=h,this.ctaBtn.href=i(a,"#");const t=this.getAttribute("target");t?(this.ctaBtn.target=t,"_blank"===t&&(this.ctaBtn.rel="noopener noreferrer")):a.startsWith("http://")||a.startsWith("https://")?(this.ctaBtn.target="_blank",this.ctaBtn.rel="noopener noreferrer"):(this.ctaBtn.removeAttribute("target"),this.ctaBtn.removeAttribute("rel"))}else this.ctaWrapper.hidden=!0;const l=this.image;l?(this.imgEl||(this.imgEl=document.createElement("img"),this.imgEl.className=`${c}__image`,this.bgWrapper?.prepend(this.imgEl)),this.imgEl.src=l,this.imgEl.alt=this.imageAlt,this.classList.add(`${c}--has-image`),this.classList.remove(`${c}--image-top`,`${c}--image-cover`),this.classList.add(`${c}--image-${this.imagePosition}`)):(this.imgEl&&(this.imgEl.remove(),this.imgEl=void 0),this.classList.remove(`${c}--has-image`,`${c}--image-top`,`${c}--image-cover`)),r.forEach(t=>{this.classList.remove(`${c}--${t}`)}),n.forEach(t=>{this.classList.remove(`${c}--${t}`)}),["1","2","3","4"].forEach(t=>{this.classList.remove(`${c}--col-${t}`)}),["1","2","3"].forEach(t=>{this.classList.remove(`${c}--row-${t}`)}),this.classList.add(`${c}--${this.variant}`),this.classList.add(`${c}--${this.size}`),this.classList.add(`${c}--col-${this.colSpan}`),this.classList.add(`${c}--row-${this.rowSpan}`),this.disabled?(this.setAttribute("aria-disabled","true"),this.classList.add(`${c}--disabled`),this.ctaBtn?.setAttribute("tabindex","-1"),this.ctaBtn?.setAttribute("aria-disabled","true")):(this.removeAttribute("aria-disabled"),this.classList.remove(`${c}--disabled`),this.ctaBtn?.removeAttribute("tabindex"),this.ctaBtn?.removeAttribute("aria-disabled"))}}customElements.get("db-bento-card")||customElements.define("db-bento-card",DbBentoCard);export{DbBentoCard};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BentoGridColumns, BentoGridSize } from '../ui-contracts/dist/components.d.js';
|
|
2
|
+
|
|
3
|
+
declare class DbBentoGrid extends HTMLElement {
|
|
4
|
+
static get observedAttributes(): string[];
|
|
5
|
+
private built;
|
|
6
|
+
get cols(): BentoGridColumns;
|
|
7
|
+
set cols(value: BentoGridColumns);
|
|
8
|
+
get size(): BentoGridSize;
|
|
9
|
+
set size(value: BentoGridSize);
|
|
10
|
+
get gap(): string;
|
|
11
|
+
set gap(value: string);
|
|
12
|
+
get autoRows(): string;
|
|
13
|
+
set autoRows(value: string);
|
|
14
|
+
connectedCallback(): void;
|
|
15
|
+
disconnectedCallback(): void;
|
|
16
|
+
attributeChangedCallback(): void;
|
|
17
|
+
private sync;
|
|
18
|
+
}
|
|
19
|
+
declare global {
|
|
20
|
+
interface HTMLElementTagNameMap {
|
|
21
|
+
'db-bento-grid': DbBentoGrid;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { DbBentoGrid };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{coerceToContract as t}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BENTO_GRID_COLUMNS as s,BENTO_GRID_SIZES as e}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const i="designbase-wc-bento-grid";class DbBentoGrid extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["cols","columns","gap","auto-rows","size"]}get cols(){const e=this.getAttribute("cols")||this.getAttribute("columns");return t(e,s,"3")}set cols(t){this.setAttribute("cols",t)}get size(){return t(this.getAttribute("size"),e,"m")}set size(t){this.setAttribute("size",t)}get gap(){return this.getAttribute("gap")||"m"}set gap(t){this.setAttribute("gap",t)}get autoRows(){return this.getAttribute("auto-rows")||""}set autoRows(t){this.setAttribute("auto-rows",t)}connectedCallback(){this.built||(this.built=!0),this.sync()}disconnectedCallback(){}attributeChangedCallback(){this.built&&this.sync()}sync(){this.classList.add(i),s.forEach(t=>{this.classList.remove(`${i}--cols-${t}`)}),e.forEach(t=>{this.classList.remove(`${i}--${t}`)}),["s","m","l"].forEach(t=>{this.classList.remove(`${i}--gap-${t}`)});const t=this.cols;this.classList.add(`${i}--cols-${t}`),this.classList.add(`${i}--${this.size}`);const o=this.gap;["s","m","l"].includes(o)?(this.classList.add(`${i}--gap-${o}`),this.style.removeProperty("--bento-gap")):o&&this.style.setProperty("--bento-gap",o);const r=this.autoRows;r?this.style.setProperty("--bento-auto-rows",r):this.style.removeProperty("--bento-auto-rows")}}customElements.get("db-bento-grid")||customElements.define("db-bento-grid",DbBentoGrid);export{DbBentoGrid};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { DbElement } from '../core/base-element.js';
|
|
2
|
+
import './db-boarding-pass.js';
|
|
3
|
+
|
|
4
|
+
interface DbTravelPass {
|
|
5
|
+
id: string;
|
|
6
|
+
issuer: string;
|
|
7
|
+
origin: string;
|
|
8
|
+
destination: string;
|
|
9
|
+
originName?: string;
|
|
10
|
+
destinationName?: string;
|
|
11
|
+
passenger?: string;
|
|
12
|
+
serviceNumber?: string;
|
|
13
|
+
date?: string;
|
|
14
|
+
boardingTime?: string;
|
|
15
|
+
departureTime?: string;
|
|
16
|
+
arrivalTime?: string;
|
|
17
|
+
terminal?: string;
|
|
18
|
+
gate?: string;
|
|
19
|
+
seat?: string;
|
|
20
|
+
travelClass?: string;
|
|
21
|
+
codeImageSrc?: string;
|
|
22
|
+
}
|
|
23
|
+
interface DbTravelPassChange {
|
|
24
|
+
index: number;
|
|
25
|
+
pass: DbTravelPass;
|
|
26
|
+
}
|
|
27
|
+
/** Selectable journey wallet composed with the real db-boarding-pass element. */
|
|
28
|
+
declare class DbBoardingPassStack extends DbElement {
|
|
29
|
+
static get observedAttributes(): string[];
|
|
30
|
+
private data?;
|
|
31
|
+
private instanceId;
|
|
32
|
+
private view;
|
|
33
|
+
get passes(): DbTravelPass[];
|
|
34
|
+
set passes(value: DbTravelPass[]);
|
|
35
|
+
get selectedIndex(): number;
|
|
36
|
+
set selectedIndex(value: number);
|
|
37
|
+
connectedCallback(): void;
|
|
38
|
+
attributeChangedCallback(): void;
|
|
39
|
+
private select;
|
|
40
|
+
private render;
|
|
41
|
+
}
|
|
42
|
+
declare global {
|
|
43
|
+
interface HTMLElementTagNameMap {
|
|
44
|
+
'db-boarding-pass-stack': DbBoardingPassStack;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { DbBoardingPassStack };
|
|
49
|
+
export type { DbTravelPass, DbTravelPassChange };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DbElement as e}from"../core/base-element.js";import{paperNode as t,paperJson as s}from"./paper-card.js";import"./db-boarding-pass.js";let i=0;const a=["id","issuer","origin","destination","originName","destinationName","passenger","serviceNumber","date","boardingTime","departureTime","arrivalTime","terminal","gate","seat","travelClass","codeImageSrc"],sanitize=e=>Array.isArray(e)?e.filter(e=>e&&"object"==typeof e&&["id","issuer","origin","destination"].every(t=>"string"==typeof e[t])).map(e=>Object.fromEntries(a.filter(t=>"string"==typeof e[t]).map(t=>[t,e[t]]))):[];class DbBoardingPassStack extends e{constructor(){super(...arguments),this.instanceId="db-travel-wallet-"+ ++i,this.view=t("section","db-boarding-pass-stack__view")}static get observedAttributes(){return["passes","selected-index","label","action-label","disabled"]}get passes(){return sanitize(this.data??s(this.getAttribute("passes")))}set passes(e){this.data=null==e?void 0:sanitize(e),this.isConnected&&this.render()}get selectedIndex(){const e=Number(this.getAttribute("selected-index")||0);return Number.isFinite(e)?Math.max(0,Math.min(this.passes.length-1,Math.floor(e))):0}set selectedIndex(e){this.setAttribute("selected-index",String(e))}connectedCallback(){this.classList.add("db-boarding-pass-stack"),this.upgradeProperties(["passes","selectedIndex"]),this.view.parentNode||this.prepend(this.view),this.render()}attributeChangedCallback(){this.isConnected&&this.render()}select(e){if(this.hasAttribute("disabled"))return;this.selectedIndex=e,this.view.querySelector(`button[data-index="${this.selectedIndex}"]`)?.focus();const t=this.passes[this.selectedIndex];t&&this.dbEmit("change",{index:this.selectedIndex,pass:t})}render(){const e=this.passes,s=this.selectedIndex,i=this.view.contains(document.activeElement)&&document.activeElement instanceof HTMLButtonElement;if(this.view.setAttribute("aria-label",this.getAttribute("label")||"나의 탑승권"),!e.length)return void this.view.replaceChildren(t("p","db-boarding-pass-stack__empty","등록된 탑승권이 없습니다."));const r=t("div","db-boarding-pass-stack__tabs");r.setAttribute("role","tablist"),r.setAttribute("aria-label","여정 선택"),r.setAttribute("aria-orientation","vertical"),e.forEach((i,a)=>{const n=t("button","db-boarding-pass-stack__tab");n.type="button",n.dataset.index=String(a),n.id=`${this.instanceId}-tab-${a}`,n.setAttribute("aria-controls",`${this.instanceId}-panel`),n.setAttribute("role","tab"),n.setAttribute("aria-selected",String(a===s)),n.setAttribute("aria-label",`${i.origin} → ${i.destination}${i.seat?` · 좌석 ${i.seat}`:""}`),n.tabIndex=a===s?0:-1,n.disabled=this.hasAttribute("disabled"),n.append(t("strong","",`${i.origin} → ${i.destination}`),t("span","",[i.issuer,i.date,i.seat&&`좌석 ${i.seat}`].filter(Boolean).join(" · "))),n.addEventListener("click",()=>this.select(a)),n.addEventListener("keydown",t=>{let s=a;if("ArrowDown"===t.key||"ArrowRight"===t.key)s=(a+1)%e.length;else if("ArrowUp"===t.key||"ArrowLeft"===t.key)s=(a-1+e.length)%e.length;else if("Home"===t.key)s=0;else{if("End"!==t.key)return;s=e.length-1}t.preventDefault(),this.select(s)}),r.append(n)});const n=t("div","db-boarding-pass-stack__panel");n.id=`${this.instanceId}-panel`,n.setAttribute("role","tabpanel"),n.setAttribute("aria-labelledby",`${this.instanceId}-tab-${s}`),n.setAttribute("aria-label",`${e[s].origin} → ${e[s].destination} 탑승권`);const d=document.createElement("db-boarding-pass"),o=e[s];for(const e of a)"id"!==e&&o[e]&&d.setAttribute(e.replace(/[A-Z]/g,e=>"-"+e.toLowerCase()),o[e]);d.setAttribute("reference",o.id),d.setAttribute("layout","vertical"),this.getAttribute("action-label")&&d.setAttribute("action-label",this.getAttribute("action-label")),d.toggleAttribute("disabled",this.hasAttribute("disabled")),n.append(d),this.view.replaceChildren(r,n),i&&this.view.querySelector(`button[data-index="${s}"]`)?.focus()}}customElements.get("db-boarding-pass-stack")||customElements.define("db-boarding-pass-stack",DbBoardingPassStack);export{DbBoardingPassStack};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DbPaperCard } from './paper-card.js';
|
|
2
|
+
|
|
3
|
+
interface DbBoardingPassLabels {
|
|
4
|
+
origin: string;
|
|
5
|
+
destination: string;
|
|
6
|
+
passenger: string;
|
|
7
|
+
service: string;
|
|
8
|
+
date: string;
|
|
9
|
+
boarding: string;
|
|
10
|
+
departure: string;
|
|
11
|
+
arrival: string;
|
|
12
|
+
terminal: string;
|
|
13
|
+
gate: string;
|
|
14
|
+
seat: string;
|
|
15
|
+
travelClass: string;
|
|
16
|
+
}
|
|
17
|
+
declare class DbBoardingPass extends DbPaperCard {
|
|
18
|
+
static get observedAttributes(): string[];
|
|
19
|
+
private customLabels;
|
|
20
|
+
protected upgradeNames(): string[];
|
|
21
|
+
get labels(): DbBoardingPassLabels;
|
|
22
|
+
set labels(value: Partial<DbBoardingPassLabels>);
|
|
23
|
+
protected render(): void;
|
|
24
|
+
}
|
|
25
|
+
declare global {
|
|
26
|
+
interface HTMLElementTagNameMap {
|
|
27
|
+
'db-boarding-pass': DbBoardingPass;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { DbBoardingPass };
|
|
32
|
+
export type { DbBoardingPassLabels };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DbPaperCard as e,paperNode as t,paperDetails as a}from"./paper-card.js";const s={origin:"출발",destination:"도착",passenger:"탑승객",service:"편명",date:"날짜",boarding:"탑승 시각",departure:"출발 시각",arrival:"도착 시각",terminal:"터미널",gate:"게이트",seat:"좌석",travelClass:"등급"};class DbBoardingPass extends e{constructor(){super(...arguments),this.customLabels={}}static get observedAttributes(){return["layout","issuer","origin","origin-name","destination","destination-name","passenger","service-number","date","boarding-time","departure-time","arrival-time","terminal","gate","seat","travel-class","reference","code-image-src","code-alt","note","action-label","disabled"]}upgradeNames(){return["labels"]}get labels(){return{...s,...this.customLabels}}set labels(e){this.customLabels={};for(const t of Object.keys(s))"string"==typeof e?.[t]&&(this.customLabels[t]=e[t]);this.isConnected&&this.render()}render(){const e=this.labels,s=t("section","db-paper__main"),r=t("header","db-paper__pass-header");r.append(t("strong","db-paper__issuer",this.attr("issuer")||"탑승권"),t("span","",this.attr("service-number"))),s.append(r);const n=t("div","db-paper__route"),endpoint=(e,a)=>{const s=t("div","db-paper__endpoint");return s.append(t("span","db-paper__label",a),t("strong","db-paper__airport",this.attr(e)||"—")),this.attr(e+"-name")&&s.append(t("span","db-paper__city",this.attr(e+"-name"))),s};if(n.append(endpoint("origin",e.origin),t("span","db-paper__route-arrow","→"),endpoint("destination",e.destination)),s.append(n),this.attr("passenger")){const a=t("div","db-paper__passenger");a.append(t("span","db-paper__label",e.passenger),t("strong","",this.attr("passenger"))),s.append(a)}const i=[],add=(e,t)=>{this.attr(e)&&i.push({label:t,value:this.attr(e)})};add("date",e.date),add("travel-class",e.travelClass),add("boarding-time",e.boarding),add("departure-time",e.departure),add("arrival-time",e.arrival),i.length&&s.append(a(i));const p=t("div","db-paper__stub");p.append(this.code(this.attr("reference")));const d=[];for(const[t,a]of[["terminal",e.terminal],["gate",e.gate],["seat",e.seat]])this.attr(t)&&d.push({label:a,value:this.attr(t)});d.length&&p.append(a(d)),this.attr("note")&&p.append(t("p","db-paper__note",this.attr("note")));const o=this.action(this.attr("reference"));o&&p.append(o),this.replace(s,p)}}customElements.get("db-boarding-pass")||customElements.define("db-boarding-pass",DbBoardingPass);export{DbBoardingPass};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BorderBeamVariant } from '../ui-contracts/dist/components.d.js';
|
|
2
|
+
|
|
3
|
+
declare class DbBorderBeam extends HTMLElement {
|
|
4
|
+
static get observedAttributes(): string[];
|
|
5
|
+
private built;
|
|
6
|
+
private beamEl?;
|
|
7
|
+
private currentPlaybackRate;
|
|
8
|
+
private targetPlaybackRate;
|
|
9
|
+
private speedAnimRafId;
|
|
10
|
+
private rampPlaybackRate;
|
|
11
|
+
private onParentEnter;
|
|
12
|
+
private onParentLeave;
|
|
13
|
+
get size(): string;
|
|
14
|
+
set size(value: string);
|
|
15
|
+
get duration(): number;
|
|
16
|
+
set duration(value: number);
|
|
17
|
+
get delay(): number;
|
|
18
|
+
set delay(value: number);
|
|
19
|
+
get colorFrom(): string;
|
|
20
|
+
set colorFrom(value: string);
|
|
21
|
+
get colorTo(): string;
|
|
22
|
+
set colorTo(value: string);
|
|
23
|
+
get borderWidth(): number;
|
|
24
|
+
set borderWidth(value: number);
|
|
25
|
+
get reverse(): boolean;
|
|
26
|
+
set reverse(value: boolean);
|
|
27
|
+
get initialOffset(): number;
|
|
28
|
+
set initialOffset(value: number);
|
|
29
|
+
get anchor(): number;
|
|
30
|
+
set anchor(value: number);
|
|
31
|
+
get variant(): BorderBeamVariant;
|
|
32
|
+
set variant(value: BorderBeamVariant);
|
|
33
|
+
get radius(): string;
|
|
34
|
+
set radius(value: string);
|
|
35
|
+
get hoverSpeed(): number;
|
|
36
|
+
set hoverSpeed(value: number);
|
|
37
|
+
get hoverScale(): number;
|
|
38
|
+
set hoverScale(value: number);
|
|
39
|
+
connectedCallback(): void;
|
|
40
|
+
disconnectedCallback(): void;
|
|
41
|
+
attributeChangedCallback(): void;
|
|
42
|
+
private build;
|
|
43
|
+
private updateRadius;
|
|
44
|
+
private sync;
|
|
45
|
+
}
|
|
46
|
+
declare global {
|
|
47
|
+
interface HTMLElementTagNameMap {
|
|
48
|
+
'db-border-beam': DbBorderBeam;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { DbBorderBeam };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{coerceToContract as t}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BORDER_BEAM_VARIANTS as e}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const r="designbase-wc-border-beam",s={s:60,m:120,l:200,xl:300};class DbBorderBeam extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.currentPlaybackRate=1,this.targetPlaybackRate=1,this.speedAnimRafId=null,this.onParentEnter=()=>{this.classList.add(`${r}--hovered`),this.rampPlaybackRate(this.hoverSpeed,400)},this.onParentLeave=()=>{this.classList.remove(`${r}--hovered`),this.rampPlaybackRate(1,500)}}static get observedAttributes(){return["size","duration","delay","color-from","color-to","border-width","reverse","initial-offset","anchor","variant","radius","hover-speed","hover-scale"]}rampPlaybackRate(t,e=400){this.targetPlaybackRate=t,null!==this.speedAnimRafId&&(cancelAnimationFrame(this.speedAnimRafId),this.speedAnimRafId=null);const r=this.currentPlaybackRate,s=performance.now(),tick=t=>{const i=t-s,a=Math.min(1,i/e),o=1-Math.pow(1-a,3);if(this.currentPlaybackRate=r+(this.targetPlaybackRate-r)*o,this.beamEl){const t=this.beamEl.getAnimations();for(let e=0;e<t.length;e++)t[e].playbackRate=this.currentPlaybackRate}this.speedAnimRafId=a<1?requestAnimationFrame(tick):null};this.speedAnimRafId=requestAnimationFrame(tick)}get size(){return this.getAttribute("size")||"120"}set size(t){this.setAttribute("size",t)}get duration(){const t=parseFloat(this.getAttribute("duration")||"8");return Number.isFinite(t)&&t>0?t:8}set duration(t){this.setAttribute("duration",String(t))}get delay(){const t=parseFloat(this.getAttribute("delay")||"0");return Number.isFinite(t)?t:0}set delay(t){this.setAttribute("delay",String(t))}get colorFrom(){return this.getAttribute("color-from")||""}set colorFrom(t){this.setAttribute("color-from",t)}get colorTo(){return this.getAttribute("color-to")||""}set colorTo(t){this.setAttribute("color-to",t)}get borderWidth(){const t=parseFloat(this.getAttribute("border-width")||"2");return Number.isFinite(t)&&t>0?t:2}set borderWidth(t){this.setAttribute("border-width",String(t))}get reverse(){return this.hasAttribute("reverse")}set reverse(t){t?this.setAttribute("reverse",""):this.removeAttribute("reverse")}get initialOffset(){const t=parseFloat(this.getAttribute("initial-offset")||"0");return Number.isFinite(t)?t:0}set initialOffset(t){this.setAttribute("initial-offset",String(t))}get anchor(){const t=parseFloat(this.getAttribute("anchor")||"90");return Number.isFinite(t)?t:90}set anchor(t){this.setAttribute("anchor",String(t))}get variant(){return t(this.getAttribute("variant"),e,"default")}set variant(t){this.setAttribute("variant",t)}get radius(){return this.getAttribute("radius")||""}set radius(t){this.setAttribute("radius",t)}get hoverSpeed(){const t=parseFloat(this.getAttribute("hover-speed")||"1.8");return Number.isFinite(t)&&t>0?t:1.8}set hoverSpeed(t){this.setAttribute("hover-speed",String(t))}get hoverScale(){const t=parseFloat(this.getAttribute("hover-scale")||"1.25");return Number.isFinite(t)&&t>0?t:1.25}set hoverScale(t){this.setAttribute("hover-scale",String(t))}connectedCallback(){this.setAttribute("aria-hidden","true"),this.built||(this.build(),this.built=!0);const t=this.parentElement;t&&(t.addEventListener("mouseenter",this.onParentEnter),t.addEventListener("mouseleave",this.onParentLeave)),this.sync()}disconnectedCallback(){const t=this.parentElement;t&&(t.removeEventListener("mouseenter",this.onParentEnter),t.removeEventListener("mouseleave",this.onParentLeave)),null!==this.speedAnimRafId&&(cancelAnimationFrame(this.speedAnimRafId),this.speedAnimRafId=null)}attributeChangedCallback(){this.built&&this.sync()}build(){this.classList.add(r);const t=document.createElement("div");t.className=`${r}__beam`,this.beamEl=t,this.replaceChildren(t)}updateRadius(){const t=this.radius;if(t){const e=/^\d+(\.\d+)?$/.test(t)?`${t}px`:t;return void this.style.setProperty("--border-beam-radius",e)}const e=this.parentElement;if(e){const t=window.getComputedStyle(e).borderRadius;if(t&&"0px"!==t)return void this.style.setProperty("--border-beam-radius",t)}this.style.setProperty("--border-beam-radius","16px")}sync(){e.forEach(t=>this.classList.remove(`${r}--${t}`)),this.classList.add(`${r}--${this.variant}`);const t=this.size;let i=120;if(t in s)i=s[t];else{const e=parseFloat(t);Number.isFinite(e)&&e>0&&(i=e)}this.style.setProperty("--border-beam-size",`${i}px`),this.style.setProperty("--border-beam-duration",`${this.duration}s`),this.style.setProperty("--border-beam-delay",`${this.delay}s`),this.style.setProperty("--border-beam-border-width",`${this.borderWidth}px`),this.style.setProperty("--border-beam-anchor",`${this.anchor}%`),this.style.setProperty("--border-beam-initial-offset",`${this.initialOffset}%`),this.style.setProperty("--border-beam-direction",this.reverse?"reverse":"normal"),this.style.setProperty("--border-beam-hover-scale",String(this.hoverScale));const a=this.colorFrom;a?this.style.setProperty("--border-beam-color-from",a):this.style.removeProperty("--border-beam-color-from");const o=this.colorTo;o?this.style.setProperty("--border-beam-color-to",o):this.style.removeProperty("--border-beam-color-to"),this.updateRadius()}}customElements.get("db-border-beam")||customElements.define("db-border-beam",DbBorderBeam);export{DbBorderBeam};
|
|
@@ -50,7 +50,7 @@ declare class DbButton extends HTMLElement {
|
|
|
50
50
|
private syncRadius;
|
|
51
51
|
private syncAccentStyle;
|
|
52
52
|
/**
|
|
53
|
-
* outline 스타일의 회전하는 테두리
|
|
53
|
+
* outline·prism 스타일의 회전하는 테두리 레이어.
|
|
54
54
|
*
|
|
55
55
|
* conic-gradient 의 각도를 직접 애니메이션하려면 `@property` 가 필요해 기준선이 올라간다.
|
|
56
56
|
* 대신 넘치는 정사각형을 `overflow: hidden` 컨테이너 안에서 회전시키고,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{sanitizeHref as s}from"../core/safe-url.js";import{coerceWithAliases as i,coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BUTTON_RADII as r,BUTTON_SIZES as a,BUTTON_ACCENT_STYLES as c,BUTTON_VARIANTS as o,BUTTON_VARIANT_ALIASES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const l=["disabled","loading","icon-only","full-width"];class DbButton extends HTMLElement{constructor(){super(...arguments),this.handleClick=t=>{if(this.disabled||this.loading)return t.preventDefault(),void t.stopPropagation();this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}));const e=this.href;if(e){"_blank"===(this.getAttribute("target")||"_self")?window.open(e,"_blank","noopener,noreferrer"):window.location.assign(e)}},this.handleKeyDown=t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed"),this.click())},this.handleKeyUp=t=>{"Enter"!==t.key&&" "!==t.key||this.classList.remove("designbase-wc-button--pressed")},this.handlePointerDown=()=>{this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed")},this.handlePointerUp=()=>{this.classList.remove("designbase-wc-button--pressed")}}static get observedAttributes(){return["variant","size","radius","accent-style","type","href","loading-text","start-icon","end-icon",...l]}get variant(){return i(this.getAttribute("variant"),o,d,"primary")}set variant(t){this.setAttribute("variant",t)}get size(){return n(this.getAttribute("size"),a,"m")}set size(t){this.setAttribute("size",t)}get radius(){const t=this.getAttribute("radius");return t?n(t,r,r[0]):""}set radius(t){t?this.setAttribute("radius",t):this.removeAttribute("radius")}get accentStyle(){return n(this.getAttribute("accent-style"),c,"solid")}set accentStyle(t){t?this.setAttribute("accent-style",t):this.removeAttribute("accent-style")}get type(){return this.getAttribute("type")||"button"}set type(t){this.setAttribute("type",t)}get href(){return s(this.getAttribute("href"),"")}set href(t){t?this.setAttribute("href",t):this.removeAttribute("href")}get loadingText(){return this.getAttribute("loading-text")||""}set loadingText(t){t?this.setAttribute("loading-text",t):this.removeAttribute("loading-text")}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get loading(){return this.hasAttribute("loading")}set loading(t){this.toggleAttribute("loading",t)}get iconOnly(){return this.hasAttribute("icon-only")}set iconOnly(t){this.toggleAttribute("icon-only",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.addEventListener("keyup",this.handleKeyUp),this.addEventListener("pointerdown",this.handlePointerDown),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointerleave",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.syncAttributes()}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown),this.removeEventListener("keyup",this.handleKeyUp),this.removeEventListener("pointerdown",this.handlePointerDown),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointerleave",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){this.syncAttributes()}syncAttributes(){this.classList.add("designbase-wc-button"),this.setAttribute("role","button"),this.setAttribute("aria-disabled",String(this.disabled||this.loading)),this.loading?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy"),this.disabled||this.loading?this.removeAttribute("tabindex"):this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.syncModifier("variant",this.variant),this.syncModifier("size",this.size),this.syncRadius(),this.syncAccentStyle(),this.syncAccentField(),this.syncAccentRing(),this.syncBooleanModifier("disabled"),this.syncBooleanModifier("icon-only"),this.syncBooleanModifier("full-width"),this.syncLoadingVisual(),this.loading?(this.querySelector(":scope > .designbase-wc-button__start-icon")?.remove(),this.querySelector(":scope > .designbase-wc-button__end-icon")?.remove()):this.syncIcons()}getIconSize(){return"s"===this.size?16:"l"===this.size?24:20}resolveIconName(e){if(e&&t(e))return e}isManagedIconNode(t){return t instanceof HTMLElement&&(t.classList.contains("designbase-wc-button__start-icon")||t.classList.contains("designbase-wc-button__end-icon")||t.classList.contains("designbase-wc-button__spinner")||t.classList.contains("designbase-wc-button__accent-field")||t.classList.contains("designbase-wc-button__accent-glass")||t.classList.contains("designbase-wc-button__accent-orb")||t.classList.contains("designbase-wc-button__accent-ring"))}syncIcons(){const t=this.resolveIconName(this.getAttribute("start-icon")),s=this.resolveIconName(this.getAttribute("end-icon")),i=this.getIconSize();let n=this.querySelector(":scope > .designbase-wc-button__start-icon");if(t){if(!n){n=document.createElement("span"),n.className="designbase-wc-button__start-icon",n.setAttribute("aria-hidden","true");const t=Array.from(this.childNodes).find(t=>!this.isManagedIconNode(t));t?this.insertBefore(n,t):this.append(n)}n.replaceChildren(e(t,i))}else n?.remove();let r=this.querySelector(":scope > .designbase-wc-button__end-icon");s?(r||(r=document.createElement("span"),r.className="designbase-wc-button__end-icon",r.setAttribute("aria-hidden","true")),r.replaceChildren(e(s,i)),this.append(r)):r?.remove()}getDefaultRadiusClass(){if(r.includes(this.radius))return`designbase-wc-button--radius-${this.radius}`;const t=a.includes(this.size)?this.size:"m";return`designbase-wc-button--radius-${"s"===t||"l"===t?t:"m"}`}syncRadius(){r.forEach(t=>this.classList.remove(`designbase-wc-button--radius-${t}`)),this.classList.add(this.getDefaultRadiusClass())}syncAccentStyle(){if(c.forEach(t=>this.classList.remove(`designbase-wc-button--accent-${t}`)),"accent"!==this.variant)return;const t=this.accentStyle,e=c.includes(t)?t:"solid";this.classList.add(`designbase-wc-button--accent-${e}`)}syncAccentRing(){const t="accent"===this.variant&&"outline"
|
|
1
|
+
import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import{sanitizeHref as s}from"../core/safe-url.js";import{coerceWithAliases as i,coerceToContract as n}from"../node_modules/@designbasekorea/ui-contracts/dist/primitives.js";import{BUTTON_RADII as r,BUTTON_SIZES as a,BUTTON_ACCENT_STYLES as c,BUTTON_VARIANTS as o,BUTTON_VARIANT_ALIASES as d}from"../node_modules/@designbasekorea/ui-contracts/dist/components.js";const l=["disabled","loading","icon-only","full-width"];class DbButton extends HTMLElement{constructor(){super(...arguments),this.handleClick=t=>{if(this.disabled||this.loading)return t.preventDefault(),void t.stopPropagation();this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}));const e=this.href;if(e){"_blank"===(this.getAttribute("target")||"_self")?window.open(e,"_blank","noopener,noreferrer"):window.location.assign(e)}},this.handleKeyDown=t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed"),this.click())},this.handleKeyUp=t=>{"Enter"!==t.key&&" "!==t.key||this.classList.remove("designbase-wc-button--pressed")},this.handlePointerDown=()=>{this.disabled||this.loading||this.classList.add("designbase-wc-button--pressed")},this.handlePointerUp=()=>{this.classList.remove("designbase-wc-button--pressed")}}static get observedAttributes(){return["variant","size","radius","accent-style","type","href","loading-text","start-icon","end-icon",...l]}get variant(){return i(this.getAttribute("variant"),o,d,"primary")}set variant(t){this.setAttribute("variant",t)}get size(){return n(this.getAttribute("size"),a,"m")}set size(t){this.setAttribute("size",t)}get radius(){const t=this.getAttribute("radius");return t?n(t,r,r[0]):""}set radius(t){t?this.setAttribute("radius",t):this.removeAttribute("radius")}get accentStyle(){return n(this.getAttribute("accent-style"),c,"solid")}set accentStyle(t){t?this.setAttribute("accent-style",t):this.removeAttribute("accent-style")}get type(){return this.getAttribute("type")||"button"}set type(t){this.setAttribute("type",t)}get href(){return s(this.getAttribute("href"),"")}set href(t){t?this.setAttribute("href",t):this.removeAttribute("href")}get loadingText(){return this.getAttribute("loading-text")||""}set loadingText(t){t?this.setAttribute("loading-text",t):this.removeAttribute("loading-text")}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get loading(){return this.hasAttribute("loading")}set loading(t){this.toggleAttribute("loading",t)}get iconOnly(){return this.hasAttribute("icon-only")}set iconOnly(t){this.toggleAttribute("icon-only",t)}get fullWidth(){return this.hasAttribute("full-width")}set fullWidth(t){this.toggleAttribute("full-width",t)}connectedCallback(){this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeyDown),this.addEventListener("keyup",this.handleKeyUp),this.addEventListener("pointerdown",this.handlePointerDown),this.addEventListener("pointerup",this.handlePointerUp),this.addEventListener("pointerleave",this.handlePointerUp),this.addEventListener("pointercancel",this.handlePointerUp),this.syncAttributes()}disconnectedCallback(){this.removeEventListener("click",this.handleClick),this.removeEventListener("keydown",this.handleKeyDown),this.removeEventListener("keyup",this.handleKeyUp),this.removeEventListener("pointerdown",this.handlePointerDown),this.removeEventListener("pointerup",this.handlePointerUp),this.removeEventListener("pointerleave",this.handlePointerUp),this.removeEventListener("pointercancel",this.handlePointerUp)}attributeChangedCallback(){this.syncAttributes()}syncAttributes(){this.classList.add("designbase-wc-button"),this.setAttribute("role","button"),this.setAttribute("aria-disabled",String(this.disabled||this.loading)),this.loading?this.setAttribute("aria-busy","true"):this.removeAttribute("aria-busy"),this.disabled||this.loading?this.removeAttribute("tabindex"):this.hasAttribute("tabindex")||this.setAttribute("tabindex","0"),this.syncModifier("variant",this.variant),this.syncModifier("size",this.size),this.syncRadius(),this.syncAccentStyle(),this.syncAccentField(),this.syncAccentRing(),this.syncBooleanModifier("disabled"),this.syncBooleanModifier("icon-only"),this.syncBooleanModifier("full-width"),this.syncLoadingVisual(),this.loading?(this.querySelector(":scope > .designbase-wc-button__start-icon")?.remove(),this.querySelector(":scope > .designbase-wc-button__end-icon")?.remove()):this.syncIcons()}getIconSize(){return"s"===this.size?16:"l"===this.size?24:20}resolveIconName(e){if(e&&t(e))return e}isManagedIconNode(t){return t instanceof HTMLElement&&(t.classList.contains("designbase-wc-button__start-icon")||t.classList.contains("designbase-wc-button__end-icon")||t.classList.contains("designbase-wc-button__spinner")||t.classList.contains("designbase-wc-button__accent-field")||t.classList.contains("designbase-wc-button__accent-glass")||t.classList.contains("designbase-wc-button__accent-orb")||t.classList.contains("designbase-wc-button__accent-ring"))}syncIcons(){const t=this.resolveIconName(this.getAttribute("start-icon")),s=this.resolveIconName(this.getAttribute("end-icon")),i=this.getIconSize();let n=this.querySelector(":scope > .designbase-wc-button__start-icon");if(t){if(!n){n=document.createElement("span"),n.className="designbase-wc-button__start-icon",n.setAttribute("aria-hidden","true");const t=Array.from(this.childNodes).find(t=>!this.isManagedIconNode(t));t?this.insertBefore(n,t):this.append(n)}n.replaceChildren(e(t,i))}else n?.remove();let r=this.querySelector(":scope > .designbase-wc-button__end-icon");s?(r||(r=document.createElement("span"),r.className="designbase-wc-button__end-icon",r.setAttribute("aria-hidden","true")),r.replaceChildren(e(s,i)),this.append(r)):r?.remove()}getDefaultRadiusClass(){if(r.includes(this.radius))return`designbase-wc-button--radius-${this.radius}`;const t=a.includes(this.size)?this.size:"m";return`designbase-wc-button--radius-${"s"===t||"l"===t?t:"m"}`}syncRadius(){r.forEach(t=>this.classList.remove(`designbase-wc-button--radius-${t}`)),this.classList.add(this.getDefaultRadiusClass())}syncAccentStyle(){if(c.forEach(t=>this.classList.remove(`designbase-wc-button--accent-${t}`)),"accent"!==this.variant)return;const t=this.accentStyle,e=c.includes(t)?t:"solid";this.classList.add(`designbase-wc-button--accent-${e}`)}syncAccentRing(){const t="accent"===this.variant&&["outline","prism"].includes(this.accentStyle),e=this.querySelector(":scope > .designbase-wc-button__accent-ring");if(!t)return void e?.remove();if(e)return;const s=document.createElement("span");s.className="designbase-wc-button__accent-ring",s.setAttribute("aria-hidden","true");const i=document.createElement("span");i.className="designbase-wc-button__accent-ring-spin",s.appendChild(i),this.insertBefore(s,this.firstChild)}syncAccentField(){const t="accent"===this.variant&&"gradient"===this.accentStyle,e=this.querySelector(":scope > .designbase-wc-button__accent-field"),s=this.querySelector(":scope > .designbase-wc-button__accent-glass");if(!t)return e?.remove(),void s?.remove();let i=e;if(!i){i=document.createElement("span"),i.className="designbase-wc-button__accent-field",i.setAttribute("aria-hidden","true");for(let t=1;t<=5;t+=1){const e=document.createElement("span");e.className=`designbase-wc-button__accent-orb designbase-wc-button__accent-orb--${t}`,i.appendChild(e)}this.insertBefore(i,this.firstChild)}if(!s){const t=document.createElement("span");t.className="designbase-wc-button__accent-glass",t.setAttribute("aria-hidden","true"),i.insertAdjacentElement("afterend",t)}}syncModifier(t,e){if(Array.from(this.classList).filter(e=>e.startsWith(`designbase-wc-button--${t}-`)).forEach(t=>this.classList.remove(t)),"variant"===t||"size"===t){("variant"===t?o:a).forEach(t=>this.classList.remove(`designbase-wc-button--${t}`)),this.classList.add(`designbase-wc-button--${e}`)}}syncBooleanModifier(t){const e=`designbase-wc-button--${t}`;this.classList.toggle(e,this.hasAttribute(t))}getSpinnerSize(){return a.includes(this.size)?this.size:"m"}syncLoadingVisual(){this.classList.toggle("designbase-wc-button--loading",this.loading);const t=this.querySelector(":scope > .designbase-wc-button__spinner");if(!this.loading)return void t?.remove();const e=`designbase-wc-button__spinner designbase-wc-spinner designbase-wc-spinner--circular designbase-wc-spinner--${this.getSpinnerSize()}`;if(t)return t.className=e,void t.setAttribute("aria-hidden","true");const s=document.createElement("span");s.className=e,s.setAttribute("aria-hidden","true"),s.innerHTML='<svg class="designbase-wc-spinner__circular" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle class="designbase-wc-spinner__circular-track" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"></circle><circle class="designbase-wc-spinner__circular-indicator" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"></circle></svg>',this.insertBefore(s,this.firstChild)}}customElements.get("db-button")||customElements.define("db-button",DbButton);export{DbButton};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DbIconName } from './db-icons.js';
|
|
2
2
|
import './db-button.js';
|
|
3
3
|
import './db-chip.js';
|
|
4
|
+
import './db-voice-control.js';
|
|
4
5
|
|
|
5
6
|
interface DbChatTool {
|
|
6
7
|
/** 고유 id (이벤트 detail 로 전달) */
|
|
@@ -99,6 +100,7 @@ declare class DbChatComposer extends HTMLElement {
|
|
|
99
100
|
private renderAttachMenu;
|
|
100
101
|
private renderAttachments;
|
|
101
102
|
private renderSendButton;
|
|
103
|
+
private get voiceActive();
|
|
102
104
|
private syncSendState;
|
|
103
105
|
private autoGrow;
|
|
104
106
|
private handleAttachClick;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";const s=[{id:"image",label:"사진·이미지",icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:"동영상",icon:"video",accept:"video/*",multiple:!0},{id:"file",label:"문서·파일",icon:"file-new",accept:"",multiple:!0},{id:"camera",label:"카메라 촬영",icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const i={image:"gallery",video:"video",file:"file-new"};let a=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=s,this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>{if("Escape"===t.key&&this.attachMenuOpen)return t.preventDefault(),void this.closeAttachMenu();"Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())},this.handleSendClick=()=>{this.disabled||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:s,this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==t?this.sync():this.renderSendButton()}}build(){this.built=!0,this.className="designbase-wc-chat-composer",this.replaceChildren();const t=document.createElement("div");t.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const e=document.createElement("div");e.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),e.append(this.field);const s=document.createElement("div");s.className="designbase-wc-chat-composer__toolbar";const i=document.createElement("div");i.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label","첨부"),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",i.append(this.attachWrap,this.toolsEl);const a=document.createElement("div");a.className="designbase-wc-chat-composer__trailing",this.micBtn=this.makeIconButton("microphone","음성 입력","db-voice"),this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),a.append(this.micBtn,this.sendBtn),s.append(i,a),t.append(this.attachmentsEl,e,s),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true"),this.dropOverlay.innerHTML='<span class="designbase-wc-chat-composer__drop-label">파일을 놓으면 첨부됩니다</span>',this.append(t,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=this.getAttribute("placeholder")||"메시지를 입력하세요…",this.field.disabled=this.disabled;const t=this.getAttribute("max-length");t?this.field.maxLength=Number(t):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const e of this._tools){const s=document.createElement("db-chip");s.setAttribute("label",e.label),s.setAttribute("size","s"),s.setAttribute("clickable",""),s.setAttribute("variant",e.active?"primary":"default"),e.icon&&t(e.icon)&&s.setAttribute("start-icon",e.icon),s.setAttribute("aria-pressed",String(!!e.active)),s.addEventListener("db-click",()=>{this.disabled||(e.active=!e.active,s.setAttribute("variant",e.active?"primary":"default"),s.setAttribute("aria-pressed",String(!!e.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:e.id,active:!!e.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(s)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const s of this._attachOptions){const i=document.createElement("button");i.type="button",i.className="designbase-wc-chat-composer__attach-item",i.setAttribute("role","menuitem");const a=document.createElement("span");a.className="designbase-wc-chat-composer__attach-item-icon",s.icon&&t(s.icon)&&a.append(e(s.icon,18));const n=document.createElement("span");n.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=s.label,n.append(h),s.description){const t=document.createElement("span");t.className="designbase-wc-chat-composer__attach-item-desc",t.textContent=s.description,n.append(t)}i.append(a,n),i.addEventListener("click",()=>this.chooseAttachOption(s)),this.attachMenu.append(i)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const s=document.createElement("div");s.className="designbase-wc-chat-composer__thumb";const i=document.createElement("img");i.src=t.preview,i.alt=t.name;const a=document.createElement("button");a.type="button",a.className="designbase-wc-chat-composer__thumb-remove",a.setAttribute("aria-label",`${t.name} 제거`),a.append(e("close",12)),a.addEventListener("click",()=>this.removeAttachment(t.id)),s.append(i,a),this.attachmentsEl.append(s);continue}const s=document.createElement("db-chip");s.setAttribute("label",t.name),s.setAttribute("size","s"),s.setAttribute("variant","neutral"),s.setAttribute("deletable",""),s.setAttribute("start-icon",i[t.kind]),s.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(s)}this.syncSendState()}renderSendButton(){const t=this.streaming;this.sendBtn.setAttribute("variant",t?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",t?"stop":"send"),this.sendBtn.setAttribute("aria-label",t?"생성 중지":"전송"),this.syncSendState()}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${a+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${a+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
|
|
1
|
+
import{isDbIconName as t,createDbIcon as e}from"./db-icons.js";import"./db-button.js";import"./db-chip.js";import"./db-voice-control.js";const s=[{id:"image",label:"사진·이미지",icon:"gallery",accept:"image/*",multiple:!0},{id:"video",label:"동영상",icon:"video",accept:"video/*",multiple:!0},{id:"file",label:"문서·파일",icon:"file-new",accept:"",multiple:!0},{id:"camera",label:"카메라 촬영",icon:"camera",accept:"image/*",capture:"environment"}];function kindFromMime(t){return t.startsWith("image/")?"image":t.startsWith("video/")?"video":"file"}const i={image:"gallery",video:"video",file:"file-new"};let a=0;class DbChatComposer extends HTMLElement{constructor(){super(...arguments),this.built=!1,this._tools=[],this._attachOptions=s,this._attachments=[],this.attachMenuOpen=!1,this.dragDepth=0,this.handleAttachClick=()=>{this.disabled||(this.attachMenuOpen?this.closeAttachMenu():this.openAttachMenu())},this.handleOutsideClick=t=>{this.attachMenuOpen&&(this.attachWrap.contains(t.target)||this.closeAttachMenu())},this.handleFilePicked=()=>{const t=Array.from(this.fileInput.files||[]);if(!t.length)return;const e=this.fileInput.dataset.type||"file";this.addFiles(t,e)},this.handleDragEnter=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),this.dragDepth+=1,this.showDropOverlay(!0))},this.handleDragOver=t=>{this.hasAttribute("attach")&&!this.disabled&&this.hasDragFiles(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))},this.handleDragLeave=t=>{this.hasAttribute("attach")&&this.hasDragFiles(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&this.showDropOverlay(!1))},this.handleDrop=t=>{if(!this.hasAttribute("attach")||this.disabled)return;if(!this.hasDragFiles(t))return;t.preventDefault(),t.stopPropagation(),this.dragDepth=0,this.showDropOverlay(!1);const e=Array.from(t.dataTransfer?.files||[]);e.length&&(this.addFiles(e,"drop"),this.focusInput())},this.handleInput=()=>{this.autoGrow(),this.syncSendState(),this.dispatchEvent(new CustomEvent("db-input",{detail:{value:this.field.value},bubbles:!0,composed:!0}))},this.handleKeyDown=t=>"Escape"===t.key&&this.voiceActive?(t.preventDefault(),void this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:"cancel"},bubbles:!0,composed:!0}))):"Escape"===t.key&&this.attachMenuOpen?(t.preventDefault(),void this.closeAttachMenu()):void("Enter"!==t.key||t.shiftKey||t.isComposing||(t.preventDefault(),this.submit())),this.handleSendClick=()=>{this.disabled||this.voiceActive||(this.streaming?this.dispatchEvent(new CustomEvent("db-stop",{bubbles:!0,composed:!0})):this.submit())}}static get observedAttributes(){return["placeholder","value","disabled","streaming","voice","attach","max-length","send-label","voice-state","voice-message","voice-disabled"]}get value(){return this.field?.value??this.getAttribute("value")??""}set value(t){this.field&&(this.field.value=t,this.autoGrow(),this.syncSendState()),t?this.setAttribute("value",t):this.removeAttribute("value")}get streaming(){return this.hasAttribute("streaming")}set streaming(t){this.toggleAttribute("streaming",t)}get disabled(){return this.hasAttribute("disabled")}set disabled(t){this.toggleAttribute("disabled",t)}get tools(){return this._tools}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&this.renderTools()}get attachOptions(){return this._attachOptions}set attachOptions(t){this._attachOptions=Array.isArray(t)&&t.length?t:s,this.built&&this.renderAttachMenu()}get attachments(){return this._attachments.map(t=>({...t}))}connectedCallback(){this.built||this.build(),this.sync(),requestAnimationFrame(()=>this.autoGrow()),document.addEventListener("click",this.handleOutsideClick,!0),this.addEventListener("dragenter",this.handleDragEnter),this.addEventListener("dragover",this.handleDragOver),this.addEventListener("dragleave",this.handleDragLeave),this.addEventListener("drop",this.handleDrop)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),this.removeEventListener("dragenter",this.handleDragEnter),this.removeEventListener("dragover",this.handleDragOver),this.removeEventListener("dragleave",this.handleDragLeave),this.removeEventListener("drop",this.handleDrop),this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview))}attributeChangedCallback(t){if(this.built){if("value"===t){const t=this.getAttribute("value")||"";return this.field.value!==t&&(this.field.value=t,this.autoGrow()),void this.syncSendState()}"streaming"!==t?this.sync():this.renderSendButton()}}build(){this.built=!0,this.className="designbase-wc-chat-composer",this.replaceChildren();const t=document.createElement("div");t.className="designbase-wc-chat-composer__surface",this.attachmentsEl=document.createElement("div"),this.attachmentsEl.className="designbase-wc-chat-composer__attachments",this.attachmentsEl.hidden=!0;const e=document.createElement("div");e.className="designbase-wc-chat-composer__field-row",this.field=document.createElement("textarea"),this.field.className="designbase-wc-chat-composer__field",this.field.rows=1,this.field.addEventListener("input",this.handleInput),this.field.addEventListener("keydown",this.handleKeyDown),e.append(this.field);const s=document.createElement("div");s.className="designbase-wc-chat-composer__toolbar";const i=document.createElement("div");i.className="designbase-wc-chat-composer__leading",this.attachWrap=document.createElement("div"),this.attachWrap.className="designbase-wc-chat-composer__attach-wrap",this.attachBtn=document.createElement("db-button"),this.attachBtn.className="designbase-wc-chat-composer__attach",this.attachBtn.setAttribute("variant","ghost"),this.attachBtn.setAttribute("icon-only",""),this.attachBtn.setAttribute("radius","pill"),this.attachBtn.setAttribute("size","m"),this.attachBtn.setAttribute("start-icon","paperclip"),this.attachBtn.setAttribute("aria-label","첨부"),this.attachBtn.setAttribute("aria-haspopup","menu"),this.attachBtn.addEventListener("db-click",this.handleAttachClick),this.attachMenu=document.createElement("div"),this.attachMenu.className="designbase-wc-chat-composer__attach-menu",this.attachMenu.setAttribute("role","menu"),this.attachMenu.hidden=!0,this.attachWrap.append(this.attachBtn,this.attachMenu),this.fileInput=document.createElement("input"),this.fileInput.type="file",this.fileInput.className="designbase-wc-chat-composer__file-input",this.fileInput.hidden=!0,this.fileInput.addEventListener("change",this.handleFilePicked),this.toolsEl=document.createElement("div"),this.toolsEl.className="designbase-wc-chat-composer__tools",i.append(this.attachWrap,this.toolsEl);const a=document.createElement("div");a.className="designbase-wc-chat-composer__trailing",this.micBtn=document.createElement("db-voice-control"),this.micBtn.setAttribute("compact","");for(const t of["start","stop","cancel"])this.micBtn.addEventListener(`db-${t}`,e=>{e.stopPropagation(),this.disabled||this.streaming||this.hasAttribute("voice-disabled")||this.dispatchEvent(new CustomEvent("db-voice",{detail:{action:t},bubbles:!0,composed:!0}))});this.micBtn.classList.add("designbase-wc-chat-composer__mic"),this.sendBtn=document.createElement("db-button"),this.sendBtn.className="designbase-wc-chat-composer__send",this.sendBtn.setAttribute("icon-only",""),this.sendBtn.setAttribute("radius","pill"),this.sendBtn.setAttribute("size","m"),this.sendBtn.addEventListener("db-click",this.handleSendClick),a.append(this.micBtn,this.sendBtn),s.append(i,a),t.append(this.attachmentsEl,e,s),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="designbase-wc-chat-composer__drop-overlay",this.dropOverlay.hidden=!0,this.dropOverlay.setAttribute("aria-hidden","true"),this.dropOverlay.innerHTML='<span class="designbase-wc-chat-composer__drop-label">파일을 놓으면 첨부됩니다</span>',this.append(t,this.dropOverlay,this.fileInput),this.renderTools(),this.renderAttachMenu(),this.renderSendButton()}makeIconButton(t,e,s){const i=document.createElement("db-button");return i.setAttribute("variant","ghost"),i.setAttribute("icon-only",""),i.setAttribute("radius","pill"),i.setAttribute("size","m"),i.setAttribute("start-icon",t),i.setAttribute("aria-label",e),i.addEventListener("db-click",()=>{this.disabled||this.dispatchEvent(new CustomEvent(s,{bubbles:!0,composed:!0}))}),i}sync(){this.classList.toggle("designbase-wc-chat-composer--disabled",this.disabled),this.classList.toggle("designbase-wc-chat-composer--streaming",this.streaming),this.field.placeholder=this.getAttribute("placeholder")||"메시지를 입력하세요…",this.field.disabled=this.disabled,this.field.readOnly=this.voiceActive;const t=this.getAttribute("max-length");t?this.field.maxLength=Number(t):this.field.removeAttribute("maxlength"),this.attachWrap.hidden=!this.hasAttribute("attach"),this.micBtn.hidden=!this.hasAttribute("voice"),this.micBtn.setAttribute("state",this.getAttribute("voice-state")||"idle"),this.micBtn.setAttribute("message",this.getAttribute("voice-message")||""),this.micBtn.toggleAttribute("disabled",this.disabled||this.streaming||this.hasAttribute("voice-disabled")),this.hasAttribute("attach")||this.closeAttachMenu(),this.autoGrow(),this.syncSendState()}renderTools(){this.toolsEl.replaceChildren();for(const e of this._tools){const s=document.createElement("db-chip");s.setAttribute("label",e.label),s.setAttribute("size","s"),s.setAttribute("clickable",""),s.setAttribute("variant",e.active?"primary":"default"),e.icon&&t(e.icon)&&s.setAttribute("start-icon",e.icon),s.setAttribute("aria-pressed",String(!!e.active)),s.addEventListener("db-click",()=>{this.disabled||(e.active=!e.active,s.setAttribute("variant",e.active?"primary":"default"),s.setAttribute("aria-pressed",String(!!e.active)),this.dispatchEvent(new CustomEvent("db-tool-toggle",{detail:{id:e.id,active:!!e.active},bubbles:!0,composed:!0})))}),this.toolsEl.append(s)}}renderAttachMenu(){this.attachMenu.replaceChildren();for(const s of this._attachOptions){const i=document.createElement("button");i.type="button",i.className="designbase-wc-chat-composer__attach-item",i.setAttribute("role","menuitem");const a=document.createElement("span");a.className="designbase-wc-chat-composer__attach-item-icon",s.icon&&t(s.icon)&&a.append(e(s.icon,18));const n=document.createElement("span");n.className="designbase-wc-chat-composer__attach-item-text";const h=document.createElement("span");if(h.className="designbase-wc-chat-composer__attach-item-label",h.textContent=s.label,n.append(h),s.description){const t=document.createElement("span");t.className="designbase-wc-chat-composer__attach-item-desc",t.textContent=s.description,n.append(t)}i.append(a,n),i.addEventListener("click",()=>this.chooseAttachOption(s)),this.attachMenu.append(i)}}renderAttachments(){this.attachmentsEl.replaceChildren(),this.attachmentsEl.hidden=0===this._attachments.length;for(const t of this._attachments){if("image"===t.kind&&t.preview){const s=document.createElement("div");s.className="designbase-wc-chat-composer__thumb";const i=document.createElement("img");i.src=t.preview,i.alt=t.name;const a=document.createElement("button");a.type="button",a.className="designbase-wc-chat-composer__thumb-remove",a.setAttribute("aria-label",`${t.name} 제거`),a.append(e("close",12)),a.addEventListener("click",()=>this.removeAttachment(t.id)),s.append(i,a),this.attachmentsEl.append(s);continue}const s=document.createElement("db-chip");s.setAttribute("label",t.name),s.setAttribute("size","s"),s.setAttribute("variant","neutral"),s.setAttribute("deletable",""),s.setAttribute("start-icon",i[t.kind]),s.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(s)}this.syncSendState()}renderSendButton(){const t=this.streaming;this.sendBtn.setAttribute("variant",t?"secondary":"primary"),this.sendBtn.setAttribute("start-icon",t?"stop":"send"),this.sendBtn.setAttribute("aria-label",t?"생성 중지":"전송"),this.syncSendState()}get voiceActive(){return this.hasAttribute("voice")&&["starting","listening","stopping"].includes(this.getAttribute("voice-state")||"idle")}syncSendState(){if(!this.sendBtn)return;const t=0===this.value.trim().length&&0===this._attachments.length,e=this.disabled||this.voiceActive||!this.streaming&&t;this.sendBtn.toggleAttribute("disabled",e)}autoGrow(){this.field&&0!==this.field.clientWidth&&(this.field.style.height="auto",this.field.style.height=`${Math.min(this.field.scrollHeight,200)}px`)}openAttachMenu(){this.attachMenuOpen=!0,this.attachMenu.hidden=!1,this.attachBtn.setAttribute("aria-expanded","true"),this.classList.add("designbase-wc-chat-composer--attach-open"),requestAnimationFrame(()=>this.attachMenu.classList.add("designbase-wc-chat-composer__attach-menu--visible"))}closeAttachMenu(){this.attachMenuOpen&&(this.attachMenuOpen=!1,this.attachMenu.hidden=!0,this.attachMenu.classList.remove("designbase-wc-chat-composer__attach-menu--visible"),this.attachBtn.setAttribute("aria-expanded","false"),this.classList.remove("designbase-wc-chat-composer--attach-open"))}chooseAttachOption(t){this.closeAttachMenu(),this.dispatchEvent(new CustomEvent("db-attach",{detail:{type:t.id},bubbles:!0,composed:!0})),void 0!==t.accept&&(this.fileInput.value="",this.fileInput.accept=t.accept,this.fileInput.multiple=!!t.multiple,t.capture?this.fileInput.setAttribute("capture",t.capture):this.fileInput.removeAttribute("capture"),this.fileInput.dataset.type=t.id,this.fileInput.click())}hasDragFiles(t){return Array.from(t.dataTransfer?.types||[]).includes("Files")}showDropOverlay(t){this.dropOverlay&&(this.dropOverlay.hidden=!t,this.classList.toggle("designbase-wc-chat-composer--drop-active",t))}addFile(t){if(this.hasAttachment(t))return!1;const e=kindFromMime(t.type),s={id:`att-${a+=1}`,name:t.name,size:t.size,mime:t.type,kind:e,file:t,preview:"image"===e?URL.createObjectURL(t):void 0};return this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0})),!0}hasAttachment(t){return this._attachments.some(e=>e.file&&e.file.name===t.name&&e.file.size===t.size&&e.file.type===t.type&&e.file.lastModified===t.lastModified)}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file,preview:t.preview}}submit(){const t=this.field.value.trim();if(!t&&0===this._attachments.length||this.disabled||this.streaming||this.voiceActive)return;const e=new CustomEvent("db-send",{detail:{value:t,attachments:this._attachments.map(t=>this.attachmentMeta(t))},bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(e)&&(this.clear(),this.clearAttachments())}addFiles(t,e="file"){const s=Array.from(t||[]).filter(Boolean);if(!s.length)return;const i=s.filter(t=>this.addFile(t));i.length&&this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:i},bubbles:!0,composed:!0}))}send(){this.submit()}clear(){this.value=""}removeAttachment(t){const e=this._attachments.find(e=>e.id===t);e&&(e.preview&&URL.revokeObjectURL(e.preview),this._attachments=this._attachments.filter(e=>e.id!==t),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-remove",{detail:{id:t},bubbles:!0,composed:!0})))}clearAttachments(){this._attachments.forEach(t=>t.preview&&URL.revokeObjectURL(t.preview)),this._attachments=[],this.renderAttachments()}addAttachment(t){if(t instanceof File)return void this.addFile(t);if(t.file&&this.hasAttachment(t.file))return;const e=kindFromMime(t.mime);this._attachments.push({id:`att-${a+=1}`,kind:e,...t}),this.renderAttachments()}focusInput(){this.field?.focus()}setStreaming(t){this.streaming=t}}customElements.get("db-chat-composer")||customElements.define("db-chat-composer",DbChatComposer);export{DbChatComposer};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CHAT_ORB_SIZES, CHAT_ORB_VARIANTS, CHAT_ORB_STATES, CHAT_ORB_THEMES } from '
|
|
1
|
+
import { CHAT_ORB_SIZES, CHAT_ORB_VARIANTS, CHAT_ORB_STATES, CHAT_ORB_THEMES } from '../ui-contracts/dist/components.d.js';
|
|
2
2
|
|
|
3
3
|
type OrbSize = (typeof CHAT_ORB_SIZES)[number];
|
|
4
4
|
type OrbVariant = (typeof CHAT_ORB_VARIANTS)[number];
|
|
@@ -6,7 +6,7 @@ import { DbChatSuggestion } from './db-chat-suggestions.js';
|
|
|
6
6
|
import './db-chat-message.js';
|
|
7
7
|
import './db-chat-typing.js';
|
|
8
8
|
import './db-avatar.js';
|
|
9
|
-
import { CHAT_WIDGET_VIEWS, CHAT_WIDGET_POSITIONS } from '
|
|
9
|
+
import { CHAT_WIDGET_VIEWS, CHAT_WIDGET_POSITIONS } from '../ui-contracts/dist/components.d.js';
|
|
10
10
|
|
|
11
11
|
type ChatView = (typeof CHAT_WIDGET_VIEWS)[number];
|
|
12
12
|
type ChatPosition = (typeof CHAT_WIDGET_POSITIONS)[number];
|