@designbasekorea/ui-wc 0.5.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/esm/components/animation-background/layers.js +1 -1
  2. package/dist/esm/components/db-ai-chat-list.d.ts +43 -0
  3. package/dist/esm/components/db-ai-chat-list.js +1 -0
  4. package/dist/esm/components/db-ai-chat.d.ts +159 -0
  5. package/dist/esm/components/db-ai-chat.js +1 -0
  6. package/dist/esm/components/db-animation-background.js +1 -1
  7. package/dist/esm/components/db-chat-composer.d.ts +134 -0
  8. package/dist/esm/components/db-chat-composer.js +1 -0
  9. package/dist/esm/components/db-chat-list.d.ts +47 -0
  10. package/dist/esm/components/db-chat-list.js +1 -0
  11. package/dist/esm/components/db-chat-message.d.ts +39 -0
  12. package/dist/esm/components/db-chat-message.js +1 -0
  13. package/dist/esm/components/db-chat-orb.d.ts +99 -0
  14. package/dist/esm/components/db-chat-orb.js +1 -0
  15. package/dist/esm/components/db-chat-room.d.ts +71 -0
  16. package/dist/esm/components/db-chat-room.js +1 -0
  17. package/dist/esm/components/db-chat-suggestions.d.ts +44 -0
  18. package/dist/esm/components/db-chat-suggestions.js +1 -0
  19. package/dist/esm/components/db-chat-typing.d.ts +22 -0
  20. package/dist/esm/components/db-chat-typing.js +1 -0
  21. package/dist/esm/components/db-chat-welcome.d.ts +32 -0
  22. package/dist/esm/components/db-chat-welcome.js +1 -0
  23. package/dist/esm/components/db-chat-widget.d.ts +146 -0
  24. package/dist/esm/components/db-chat-widget.js +1 -0
  25. package/dist/esm/components/db-chip.js +1 -1
  26. package/dist/esm/components/db-download-progress.d.ts +89 -0
  27. package/dist/esm/components/db-download-progress.js +1 -0
  28. package/dist/esm/components/db-email-verify.d.ts +62 -0
  29. package/dist/esm/components/db-email-verify.js +1 -0
  30. package/dist/esm/components/db-icons.d.ts +3 -0
  31. package/dist/esm/components/db-icons.js +1 -1
  32. package/dist/esm/components/db-logo-svg.js +1 -1
  33. package/dist/esm/components/db-logo.js +1 -1
  34. package/dist/esm/components/db-otp-input.d.ts +53 -0
  35. package/dist/esm/components/db-otp-input.js +1 -0
  36. package/dist/esm/components/db-phone-verify.d.ts +61 -0
  37. package/dist/esm/components/db-phone-verify.js +1 -0
  38. package/dist/esm/components/db-testimonial.d.ts +2 -0
  39. package/dist/esm/components/db-testimonial.js +1 -1
  40. package/dist/esm/components/db-two-factor.d.ts +60 -0
  41. package/dist/esm/components/db-two-factor.js +1 -0
  42. package/dist/esm/components/highlight-code.js +1 -1
  43. package/dist/esm/index.d.ts +16 -0
  44. package/dist/esm/index.js +1 -1
  45. package/dist/index.cjs +1 -1
  46. package/dist/index.css +1 -1
  47. package/dist/index.d.ts +1091 -2
  48. package/dist/index.esm.js +1 -1
  49. package/dist/react/index.cjs +1 -1
  50. package/dist/react/index.d.ts +1620 -54
  51. package/dist/react/index.esm.js +1 -1
  52. package/package.json +1 -1
  53. /package/dist/chunks/{lottie-2637aa0f.js → lottie-0e23d630.js} +0 -0
  54. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-bash.js +0 -0
  55. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-clike.js +0 -0
  56. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-css.js +0 -0
  57. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-javascript.js +0 -0
  58. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-json.js +0 -0
  59. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-jsx.js +0 -0
  60. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-markup.js +0 -0
  61. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-scss.js +0 -0
  62. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-tsx.js +0 -0
  63. /package/dist/esm/node_modules/{prismjs → .pnpm/prismjs@1.30.0/node_modules/prismjs}/components/prism-typescript.js +0 -0
@@ -1 +1 @@
1
- import{LUMINA_NOISE_SVG as e,isLuminaType as t,FLUID_DEFAULT_COLORS as a,padColors as r,toAnimationDurationSec as n,LUMINA_ANIMATION_DURATION_SEC as s,toLuminaSpeed as i}from"./lumina-utils.js";import{getLuminaPresetColors as o}from"./lumina-presets.js";import{getGraphitePreset as l,GRAPHITE_DEFAULT_COLORS as d,isGraphitePresetId as m}from"./graphite-presets.js";import{getFallingParticleDefaults as u}from"./particle-defaults.js";import{CanvasAnimationController as p}from"./canvas-controller.js";import{ShaderAnimationController as g}from"./shader-controller.js";import{GraphiteShaderController as b}from"./graphite-controller.js";const f="designbase-wc-animation-background",h="graphite",y=new Set(["particles","stars","snow","flowers","confetti","aurora","plasma","mesh-flow","fluid","radiant","ethereal","graphite"]);function parseColors(e,t){if(!e)return t;try{const a=JSON.parse(e);return Array.isArray(a)&&a.length?a:t}catch{return e.split(",").map(e=>e.trim()).filter(Boolean)}}function parseAnimationBackgroundConfig(e){const t=function normalizeAnimationType(e){return e&&"gradient"!==e&&y.has(e)?e:h}(e.getAttribute("type")),a="light"===e.getAttribute("theme")?"light":"dark",r=e.getAttribute("intensity")||"subtle",n=e.getAttribute("preset")||void 0,s=e.getAttribute("zoom"),i="graphite"===t;let o=Number(s||1);if(i&&null===s){const e=m(n)?n:"graphite";o=l(e).scale}return{type:t,theme:a,intensity:r,blur:Number(e.getAttribute("blur")||80),speed:Number(e.getAttribute("speed")||3e3),direction:e.getAttribute("direction")||"left",colors:parseColors(e.getAttribute("colors"),i?[...d]:["#667eea","#764ba2","#f093fb"]),opacity:Number(e.getAttribute("opacity")||1),particleCount:Number(e.getAttribute("particle-count")||("particles"===t?15:50)),particleSize:Number(e.getAttribute("particle-size")||2),starCount:Number(e.getAttribute("star-count")||100),starSize:Number(e.getAttribute("star-size")||1.5),clickable:e.hasAttribute("clickable")&&"false"!==e.getAttribute("clickable"),wind:Number(e.getAttribute("wind")||.5),noise:Number(e.getAttribute("noise")??(i?.1:.05)),showVignette:!e.hasAttribute("show-vignette")||"false"!==e.getAttribute("show-vignette"),preset:n||(i?"graphite":void 0),zoom:o,shaderSpeed:Number(e.getAttribute("shader-speed")||.4),shaderIntensity:Number(e.getAttribute("shader-intensity")||1.2),warp:Number(e.getAttribute("warp")||1.4),disabled:e.hasAttribute("disabled")&&"false"!==e.getAttribute("disabled")}}function resolveColors(e){const{type:t,preset:r,colors:n}=e;if("graphite"===t)return r&&m(r)?[...l(r).colors]:n.length>=3?n.slice(0,3):[...d];if(r&&!m(r))return o(r);if("fluid"===t&&n.length<5)return a;if("snow"===t||"flowers"===t||"confetti"===t){const e=u(t);return 3===n.length&&"#667eea"===n[0]&&"#764ba2"===n[1]?e:n}return n}function createLuminaOverlays(t,a){const r=document.createDocumentFragment();if(t>0){const a=document.createElement("div");a.className=`${f}__lumina-noise`,a.style.backgroundImage=`url("${e}")`,a.style.opacity=String(t),r.appendChild(a)}if(a){const e=document.createElement("div");e.className=`${f}__lumina-vignette`,r.appendChild(e)}return r}function syncLuminaOverlays(t,a,r){let n=t.querySelector(`.${f}__lumina-noise`),s=t.querySelector(`.${f}__lumina-vignette`);a>0?(n||(n=document.createElement("div"),n.className=`${f}__lumina-noise`,n.style.backgroundImage=`url("${e}")`,n.style.mixBlendMode="overlay",t.appendChild(n)),n.style.opacity=String(a)):n?.remove(),r?s||(s=document.createElement("div"),s.className=`${f}__lumina-vignette`,t.appendChild(s)):s?.remove()}function mountAnimationLayers(e,t){const a=resolveColors(t);let o={};if(t.disabled)return o;switch(t.type){case"particles":case"stars":case"snow":case"flowers":case"confetti":{const r=document.createElement("div");r.className=`${f}__canvas-layer`,e.appendChild(r);const n=new p(r,{type:t.type,colors:a,speed:t.speed,particleCount:t.particleCount,particleSize:t.particleSize,starCount:t.starCount,starSize:t.starSize,clickable:t.clickable,wind:t.wind,layerOpacity:t.opacity});o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,speed:e.speed,particleCount:e.particleCount,particleSize:e.particleSize,starCount:e.starCount,starSize:e.starSize,clickable:e.clickable,wind:e.wind,layerOpacity:e.opacity})}};break}case"aurora":e.appendChild(function createMeshAuroraLayer(e,t,a,r,s){const i=document.createElement("div");i.className=`${f}__aurora-mesh`;const o="subtle"===r?.3:"medium"===r?.6:.8,l=n(t,5,1.25),d=e.length>=3?e:["#4f46e5","#ec4899","#06b6d4","#8b5cf6"],m="dark"===s?"screen":"multiply",u=`blur(${a}px)`,p=`${f}__aurora-blob`,g=[{backgroundColor:d[0],top:"-10%",left:"-10%",animationDuration:`${l}s`,animationDelay:"0s"},{backgroundColor:d[1],top:"-10%",right:"-10%",animationDuration:1.2*l+"s",animationDelay:"2s"},{backgroundColor:d[2],bottom:"-20%",left:"20%",animationDuration:1.5*l+"s",animationDelay:"4s"}];d[3]&&g.push({backgroundColor:d[3],bottom:"-10%",right:"-10%",animationDuration:1.1*l+"s",animationDelay:"1s"}),g.forEach(e=>{const t=document.createElement("div");t.className=p,Object.assign(t.style,{filter:u,opacity:String(o),mixBlendMode:m,...e}),i.appendChild(t)});const b=document.createElement("div");return b.className=`${f}__aurora-noise`,b.style.opacity="dark"===s?"0.03":"0.05",b.style.backgroundImage="url(\"data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E\")",i.appendChild(b),i}(a,t.speed,t.blur,t.intensity,t.theme));break;case"plasma":e.appendChild(function createPlasmaLayer(e,t,a){const n=document.createElement("div");n.className=`${f}__plasma`;const o=Math.random().toString(36).slice(2,11),l=r(e),c=e=>l[e%l.length],d=i(t),m=s/d,u=document.createElement("style");u.textContent=`\n @keyframes designbase-wc-plasma-move-1-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1); }\n 25% { transform: translate(10%, 10%) rotate(90deg) scale(1.2); }\n 50% { transform: translate(0, 20%) rotate(180deg) scale(1); }\n 75% { transform: translate(-10%, 10%) rotate(270deg) scale(0.9); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1); }\n }\n @keyframes designbase-wc-plasma-move-2-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1.2); }\n 33% { transform: translate(-20%, 0) rotate(120deg) scale(1); }\n 66% { transform: translate(20%, -10%) rotate(240deg) scale(0.8); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1.2); }\n }\n @keyframes designbase-wc-plasma-move-3-${o} {\n 0% { transform: translate(0, 0) scale(0.8); }\n 50% { transform: translate(15%, -15%) scale(1.4); }\n 100% { transform: translate(0, 0) scale(0.8); }\n }\n @keyframes designbase-wc-plasma-rotate-${o} {\n 0% { transform: rotate(0deg) scale(1.5); }\n 50% { transform: rotate(180deg) scale(2.0); }\n 100% { transform: rotate(360deg) scale(1.5); }\n }`,n.appendChild(u);const p=document.createElement("div");return p.className=`${f}__plasma-base`,p.style.backgroundColor=c(0),n.appendChild(p),[{top:"-10%",left:"-10%",width:"70%",height:"70%",background:`radial-gradient(circle, ${c(1)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-1-${o} ${m}s infinite linear`},{bottom:"-20%",right:"-10%",width:"80%",height:"80%",background:`radial-gradient(circle, ${c(2)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-2-${o} ${m}s infinite linear`},{top:"20%",left:"20%",width:"60%",height:"60%",background:`radial-gradient(circle, ${c(3)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-rotate-${o} ${m}s infinite linear`,extraClass:`${f}__plasma-blob--exclusion`},{top:"40%",right:"20%",width:"40%",height:"40%",background:c(4),animation:`designbase-wc-plasma-move-3-${o} ${m}s infinite ease-in-out`,extraClass:`${f}__plasma-blob--accent`,filter:`blur(${a}px)`,opacity:"0.6"}].forEach(e=>{const t=document.createElement("div");t.className=`${f}__plasma-blob${e.extraClass?` ${e.extraClass}`:""}`,Object.assign(t.style,{filter:e.filter||`blur(${a}px)`,opacity:e.opacity||"0.9",...e}),n.appendChild(t)}),n}(a,t.speed,t.blur)),e.appendChild(createLuminaOverlays(t.noise,t.showVignette));break;case"mesh-flow":case"fluid":case"radiant":case"ethereal":{const r=document.createElement("div");r.className=`${f}__shader-layer`,e.appendChild(r);const n=new g(r,{variant:t.type,colors:a,speed:t.speed,blur:t.blur,noise:t.noise,zoom:t.zoom});e.appendChild(createLuminaOverlays(t.noise,t.showVignette)),o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,speed:e.speed,blur:e.blur,noise:e.noise,zoom:e.zoom})}};break}case"graphite":{const r=document.createElement("div");r.className=`${f}__shader-layer`,e.appendChild(r);const n=new b(r,{colors:a,shaderSpeed:t.shaderSpeed,shaderIntensity:t.shaderIntensity,grain:t.noise,scale:t.zoom,warp:t.warp});o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,shaderSpeed:e.shaderSpeed,shaderIntensity:e.shaderIntensity,grain:e.noise,scale:e.zoom,warp:e.warp})}};break}}return o}function applyContainerStyles(e,a){const r=t(a.type),n="graphite"===a.type,s=r||n?"#000000":"dark"===a.theme?"var(--db-surface-base, #0f172a)":"var(--db-surface-base, #ffffff)";e.style.position="relative",e.style.overflow="hidden",e.style.backgroundColor=s}export{f as ANIMATION_BACKGROUND_CLASS,applyContainerStyles,mountAnimationLayers,parseAnimationBackgroundConfig,syncLuminaOverlays};
1
+ import{LUMINA_NOISE_SVG as e,isLuminaType as t,FLUID_DEFAULT_COLORS as a,padColors as r,toAnimationDurationSec as n,LUMINA_ANIMATION_DURATION_SEC as s,toLuminaSpeed as i}from"./lumina-utils.js";import{getLuminaPresetColors as o}from"./lumina-presets.js";import{getGraphitePreset as l,GRAPHITE_DEFAULT_COLORS as d,isGraphitePresetId as m}from"./graphite-presets.js";import{getFallingParticleDefaults as u}from"./particle-defaults.js";import{CanvasAnimationController as p}from"./canvas-controller.js";import{ShaderAnimationController as g}from"./shader-controller.js";import{GraphiteShaderController as b}from"./graphite-controller.js";const f="designbase-wc-animation-background",h="graphite",y=new Set(["particles","stars","snow","flowers","confetti","aurora","plasma","mesh-flow","fluid","radiant","ethereal","graphite"]);function parseColors(e,t){if(!e)return t;try{const a=JSON.parse(e);return Array.isArray(a)&&a.length?a:t}catch{return e.split(",").map(e=>e.trim()).filter(Boolean)}}function parseAnimationBackgroundConfig(e){const t=function normalizeAnimationType(e){return e&&"gradient"!==e&&y.has(e)?e:h}(e.getAttribute("type")),a="light"===e.getAttribute("theme")?"light":"dark",r=e.getAttribute("intensity")||"subtle",n=e.getAttribute("preset")||void 0,s=e.getAttribute("zoom"),i="graphite"===t;let o=Number(s||1);if(i&&null===s){const e=m(n)?n:"graphite";o=l(e).scale}return{type:t,theme:a,intensity:r,blur:Number(e.getAttribute("blur")||80),speed:Number(e.getAttribute("speed")||3e3),direction:e.getAttribute("direction")||"left",colors:parseColors(e.getAttribute("colors"),i?[...d]:["#667eea","#764ba2","#f093fb"]),opacity:Number(e.getAttribute("opacity")||1),particleCount:Number(e.getAttribute("particle-count")||("particles"===t?15:50)),particleSize:Number(e.getAttribute("particle-size")||2),starCount:Number(e.getAttribute("star-count")||100),starSize:Number(e.getAttribute("star-size")||1.5),clickable:e.hasAttribute("clickable")&&"false"!==e.getAttribute("clickable"),wind:Number(e.getAttribute("wind")||.5),noise:Number(e.getAttribute("noise")??(i?.1:.05)),showVignette:!e.hasAttribute("show-vignette")||"false"!==e.getAttribute("show-vignette"),preset:n||(i?"graphite":void 0),zoom:o,shaderSpeed:Number(e.getAttribute("shader-speed")||.4),shaderIntensity:Number(e.getAttribute("shader-intensity")||1.2),warp:Number(e.getAttribute("warp")||1.4),disabled:e.hasAttribute("disabled")&&"false"!==e.getAttribute("disabled")}}function resolveColors(e){const{type:t,preset:r,colors:n}=e;if("graphite"===t)return r&&m(r)?[...l(r).colors]:n.length>=3?n.slice(0,3):[...d];if(r&&!m(r))return o(r);if("fluid"===t&&n.length<5)return a;if("snow"===t||"flowers"===t||"confetti"===t){const e=u(t);return 3===n.length&&"#667eea"===n[0]&&"#764ba2"===n[1]?e:n}return n}function createLuminaOverlays(t,a){const r=document.createDocumentFragment();if(t>0){const a=document.createElement("div");a.className=`${f}__lumina-noise`,a.style.backgroundImage=`url("${e}")`,a.style.opacity=String(t),r.appendChild(a)}if(a){const e=document.createElement("div");e.className=`${f}__lumina-vignette`,r.appendChild(e)}return r}function syncLuminaOverlays(t,a,r){let n=t.querySelector(`.${f}__lumina-noise`),s=t.querySelector(`.${f}__lumina-vignette`);a>0?(n||(n=document.createElement("div"),n.className=`${f}__lumina-noise`,n.style.backgroundImage=`url("${e}")`,n.style.mixBlendMode="overlay",t.appendChild(n)),n.style.opacity=String(a)):n?.remove(),r?s||(s=document.createElement("div"),s.className=`${f}__lumina-vignette`,t.appendChild(s)):s?.remove()}function mountAnimationLayers(e,t){const a=resolveColors(t);let o={};if(t.disabled)return o;switch(t.type){case"particles":case"stars":case"snow":case"flowers":case"confetti":{const r=document.createElement("div");r.className=`${f}__canvas-layer`,e.appendChild(r);const n=new p(r,{type:t.type,colors:a,speed:t.speed,particleCount:t.particleCount,particleSize:t.particleSize,starCount:t.starCount,starSize:t.starSize,clickable:t.clickable,wind:t.wind,layerOpacity:t.opacity});o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,speed:e.speed,particleCount:e.particleCount,particleSize:e.particleSize,starCount:e.starCount,starSize:e.starSize,clickable:e.clickable,wind:e.wind,layerOpacity:e.opacity})}};break}case"aurora":e.appendChild(function createMeshAuroraLayer(e,t,a,r,s){const i=document.createElement("div");i.className=`${f}__aurora-mesh`;const o="subtle"===r?.3:"medium"===r?.6:.8,l=n(t,5,1.25),d=e.length>=3?e:["#4f46e5","#ec4899","#06b6d4","#8b5cf6"],m="dark"===s?"screen":"multiply",u=`blur(${a}px)`,p=`${f}__aurora-blob`,g=[{backgroundColor:d[0],top:"-10%",left:"-10%",animationDuration:`${l}s`,animationDelay:"0s"},{backgroundColor:d[1],top:"-10%",right:"-10%",animationDuration:1.2*l+"s",animationDelay:"2s"},{backgroundColor:d[2],bottom:"-20%",left:"20%",animationDuration:1.5*l+"s",animationDelay:"4s"}];d[3]&&g.push({backgroundColor:d[3],bottom:"-10%",right:"-10%",animationDuration:1.1*l+"s",animationDelay:"1s"}),g.forEach(e=>{const t=document.createElement("div");t.className=p,Object.assign(t.style,{filter:u,opacity:String(o),mixBlendMode:m,...e}),i.appendChild(t)});const b=document.createElement("div");return b.className=`${f}__aurora-noise`,b.style.opacity="dark"===s?"0.03":"0.05",b.style.backgroundImage="url(\"data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E\")",i.appendChild(b),i}(a,t.speed,t.blur,t.intensity,t.theme));break;case"plasma":e.appendChild(function createPlasmaLayer(e,t,a){const n=document.createElement("div");n.className=`${f}__plasma`;const o=Math.random().toString(36).slice(2,11),l=r(e),c=e=>l[e%l.length],d=i(t),m=s/d,u=document.createElement("style");u.textContent=`\n @keyframes designbase-wc-plasma-move-1-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1); }\n 25% { transform: translate(10%, 10%) rotate(90deg) scale(1.2); }\n 50% { transform: translate(0, 20%) rotate(180deg) scale(1); }\n 75% { transform: translate(-10%, 10%) rotate(270deg) scale(0.9); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1); }\n }\n @keyframes designbase-wc-plasma-move-2-${o} {\n 0% { transform: translate(0, 0) rotate(0deg) scale(1.2); }\n 33% { transform: translate(-20%, 0) rotate(120deg) scale(1); }\n 66% { transform: translate(20%, -10%) rotate(240deg) scale(0.8); }\n 100% { transform: translate(0, 0) rotate(360deg) scale(1.2); }\n }\n @keyframes designbase-wc-plasma-move-3-${o} {\n 0% { transform: translate(0, 0) scale(0.8); }\n 50% { transform: translate(15%, -15%) scale(1.4); }\n 100% { transform: translate(0, 0) scale(0.8); }\n }\n @keyframes designbase-wc-plasma-rotate-${o} {\n 0% { transform: rotate(0deg) scale(1.5); }\n 50% { transform: rotate(180deg) scale(2.0); }\n 100% { transform: rotate(360deg) scale(1.5); }\n }`,n.appendChild(u);const p=document.createElement("div");return p.className=`${f}__plasma-base`,p.style.backgroundColor=c(0),n.appendChild(p),[{top:"-10%",left:"-10%",width:"70%",height:"70%",background:`radial-gradient(circle, ${c(1)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-1-${o} ${m}s infinite linear`},{bottom:"-20%",right:"-10%",width:"80%",height:"80%",background:`radial-gradient(circle, ${c(2)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-move-2-${o} ${m}s infinite linear`},{top:"20%",left:"20%",width:"60%",height:"60%",background:`radial-gradient(circle, ${c(3)} 0%, transparent 70%)`,animation:`designbase-wc-plasma-rotate-${o} ${m}s infinite linear`,extraClass:`${f}__plasma-blob--exclusion`},{top:"40%",right:"20%",width:"40%",height:"40%",background:c(4),animation:`designbase-wc-plasma-move-3-${o} ${m}s infinite ease-in-out`,extraClass:`${f}__plasma-blob--accent`,filter:`blur(${a}px)`,opacity:"0.6"}].forEach(e=>{const t=document.createElement("div");t.className=`${f}__plasma-blob${e.extraClass?` ${e.extraClass}`:""}`,Object.assign(t.style,{filter:e.filter||`blur(${a}px)`,opacity:e.opacity||"0.9",...e}),n.appendChild(t)}),n}(a,t.speed,t.blur)),e.appendChild(createLuminaOverlays(t.noise,t.showVignette));break;case"mesh-flow":case"fluid":case"radiant":case"ethereal":{const r=document.createElement("div");r.className=`${f}__shader-layer`,e.appendChild(r);const n=new g(r,{variant:t.type,colors:a,speed:t.speed,blur:t.blur,noise:t.noise,zoom:t.zoom});e.appendChild(createLuminaOverlays(t.noise,t.showVignette)),o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,speed:e.speed,blur:e.blur,noise:e.noise,zoom:e.zoom})}};break}case"graphite":{const r=document.createElement("div");r.className=`${f}__shader-layer`,e.appendChild(r);const n=new b(r,{colors:a,shaderSpeed:t.shaderSpeed,shaderIntensity:t.shaderIntensity,grain:t.noise,scale:t.zoom,warp:t.warp});o={destroy:()=>n.destroy(),update:e=>{const t=resolveColors(e);n.updateOptions({colors:t,shaderSpeed:e.shaderSpeed,shaderIntensity:e.shaderIntensity,grain:e.noise,scale:e.zoom,warp:e.warp})}};break}}return o}function applyContainerStyles(e,a){const r=t(a.type),n="graphite"===a.type,s=r||n?"#000000":"dark"===a.theme?"var(--db-surface-base, #0f172a)":"var(--db-surface-base, #ffffff)";e.style.position="relative",e.style.overflow="hidden",e.style.backgroundColor=s,e.style.border="none"}export{f as ANIMATION_BACKGROUND_CLASS,applyContainerStyles,mountAnimationLayers,parseAnimationBackgroundConfig,syncLuminaOverlays};
@@ -0,0 +1,43 @@
1
+ import { DbIconName } from './db-icons.js';
2
+
3
+ interface DbAiChatItem {
4
+ id: string;
5
+ /** 대화 제목 */
6
+ title: string;
7
+ /** 그룹 라벨 (예: '오늘', '어제', '지난 7일'). 없으면 '최근 항목' */
8
+ group?: string;
9
+ /** 행 아이콘(선택) */
10
+ icon?: DbIconName;
11
+ }
12
+ /**
13
+ * AI 대화 이력 목록. 상단 '새 대화' 버튼 + 그룹별 최근 대화 리스트로 구성됩니다.
14
+ * (사람 간 대화 목록은 `db-chat-list` 를 사용하세요.)
15
+ *
16
+ * @fires db-new - 새 대화 시작
17
+ * @fires db-select - 대화 선택 (detail: { id, title })
18
+ *
19
+ * @example
20
+ * const list = document.querySelector('db-ai-chat-list');
21
+ * list.items = [{ id:'1', title:'다운로드 진행바 컴포넌트', group:'오늘' }];
22
+ * list.addEventListener('db-new', () => {});
23
+ * list.addEventListener('db-select', (e) => console.log(e.detail.id));
24
+ */
25
+ declare class DbAiChatList extends HTMLElement {
26
+ static get observedAttributes(): string[];
27
+ private _items;
28
+ get items(): DbAiChatItem[];
29
+ set items(v: DbAiChatItem[]);
30
+ get selectedId(): string;
31
+ set selectedId(v: string);
32
+ connectedCallback(): void;
33
+ attributeChangedCallback(): void;
34
+ private render;
35
+ }
36
+ declare global {
37
+ interface HTMLElementTagNameMap {
38
+ 'db-ai-chat-list': DbAiChatList;
39
+ }
40
+ }
41
+
42
+ export { DbAiChatList };
43
+ export type { DbAiChatItem };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t,isDbIconName as e}from"./db-icons.js";class DbAiChatList extends HTMLElement{constructor(){super(...arguments),this._items=[]}static get observedAttributes(){return["selected-id","new-label","title-label"]}get items(){return this._items}set items(t){this._items=Array.isArray(t)?t:[],this.render()}get selectedId(){return this.getAttribute("selected-id")||""}set selectedId(t){t?this.setAttribute("selected-id",t):this.removeAttribute("selected-id")}connectedCallback(){if(!this._items.length&&this.hasAttribute("items"))try{this._items=JSON.parse(this.getAttribute("items")||"[]")}catch{this._items=[]}this.render()}attributeChangedCallback(){this.render()}render(){this.className="designbase-wc-ai-chat-list",this.replaceChildren();const s=document.createElement("button");s.type="button",s.className="designbase-wc-ai-chat-list__new";const i=document.createElement("span");i.className="designbase-wc-ai-chat-list__new-icon",i.append(t("plus",18));const n=document.createElement("span");if(n.textContent=this.getAttribute("new-label")||"새 대화",s.append(i,n),s.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("db-new",{bubbles:!0,composed:!0}))}),this.append(s),!this._items.length)return;const a=new Map,c=this.getAttribute("title-label")||"최근 항목";for(const t of this._items){const e=t.group||c;a.has(e)||a.set(e,[]),a.get(e).push(t)}const d=this.selectedId,l=document.createElement("div");l.className="designbase-wc-ai-chat-list__scroll";for(const[s,i]of a){const n=document.createElement("div");n.className="designbase-wc-ai-chat-list__group";const a=document.createElement("div");a.className="designbase-wc-ai-chat-list__group-title",a.textContent=s,n.append(a);for(const s of i){const i=document.createElement("button");if(i.type="button",i.className=["designbase-wc-ai-chat-list__item",s.id===d&&"designbase-wc-ai-chat-list__item--selected"].filter(Boolean).join(" "),s.icon&&e(s.icon)){const e=document.createElement("span");e.className="designbase-wc-ai-chat-list__item-icon",e.append(t(s.icon,16)),i.append(e)}const a=document.createElement("span");a.className="designbase-wc-ai-chat-list__item-title",a.textContent=s.title,i.append(a),i.addEventListener("click",()=>{this.selectedId=s.id,this.dispatchEvent(new CustomEvent("db-select",{detail:{id:s.id,title:s.title},bubbles:!0,composed:!0}))}),n.append(i)}l.append(n)}this.append(l)}}customElements.get("db-ai-chat-list")||customElements.define("db-ai-chat-list",DbAiChatList);export{DbAiChatList};
@@ -0,0 +1,159 @@
1
+ import './db-chat-welcome.js';
2
+ import { DbChatSuggestion } from './db-chat-suggestions.js';
3
+ import './db-chat-message.js';
4
+ import './db-chat-typing.js';
5
+ import { DbChatTool, DbChatAttachOption, DbChatComposer } from './db-chat-composer.js';
6
+
7
+ interface DbArtifactOptions {
8
+ /** 패널 헤더 제목 */
9
+ title?: string;
10
+ /** 헤더 부제(선택) */
11
+ subtitle?: string;
12
+ /** 본문 HTML (setArtifactContent 로 요소를 직접 넣을 수도 있음) */
13
+ html?: string;
14
+ /** 인라인 카드와 동기화할 id (toggle 용) */
15
+ id?: string;
16
+ }
17
+ /** 채팅 스레드 안에 노출되는 결과물(아티팩트) 카드 */
18
+ interface DbChatArtifactRef {
19
+ id?: string;
20
+ title: string;
21
+ subtitle?: string;
22
+ icon?: string;
23
+ html?: string;
24
+ }
25
+ interface DbChatMessageData {
26
+ id?: string;
27
+ role?: 'user' | 'assistant' | 'system';
28
+ /** 평문 본문 */
29
+ text?: string;
30
+ /** HTML 본문 (text 대신) */
31
+ html?: string;
32
+ name?: string;
33
+ time?: string;
34
+ avatarSrc?: string;
35
+ avatarInitials?: string;
36
+ /** 말풍선 액션 (예: 'copy,regenerate,like,dislike') */
37
+ actions?: string;
38
+ status?: 'sending' | 'error';
39
+ variant?: 'bubble' | 'plain';
40
+ /** 스레드 인라인 결과물 카드 — 클릭 시 우측 아티팩트 패널 토글 */
41
+ artifact?: DbChatArtifactRef;
42
+ }
43
+ /**
44
+ * 전체 대화형 AI 채팅 화면. 시작 전(빈 상태)과 대화 중을 하나로 통합한 최상위 컴포넌트로,
45
+ * 채팅 프리미티브(`db-chat-welcome` · `db-chat-suggestions` · `db-chat-message`
46
+ * · `db-chat-typing` · `db-chat-composer`)를 조합합니다.
47
+ *
48
+ * - 메시지가 없으면 히어로(인사말 + 추천)를 중앙에 보여주고,
49
+ * - 메시지가 생기면 스크롤 스레드로 전환하며, 컴포저는 항상 하단에 고정됩니다.
50
+ *
51
+ * @fires db-send - 전송 (detail: { value, attachments })
52
+ * @fires db-stop - 생성 중지
53
+ * @fires db-tool-toggle - 툴 토글 (detail: { id, active })
54
+ * @fires db-attach - 첨부 종류 선택 (detail: { type })
55
+ * @fires db-attach-files - 파일 선택 (detail: { type, files })
56
+ * @fires db-voice - 음성 입력
57
+ * @fires db-suggestion-select - 추천 선택 (detail: { id, title, value })
58
+ * @fires db-message-action - 말풍선 액션 (detail: { action, text })
59
+ *
60
+ * @example
61
+ * const chat = document.querySelector('db-chat');
62
+ * chat.suggestions = [{ title:'카피 작성', icon:'edit' }];
63
+ * chat.tools = [{ id:'reason', label:'Reasoning', icon:'bulb' }];
64
+ * chat.addEventListener('db-send', (e) => {
65
+ * chat.addMessage({ role:'user', text: e.detail.value });
66
+ * chat.setTyping(true);
67
+ * });
68
+ */
69
+ declare class DbAiChat extends HTMLElement {
70
+ static get observedAttributes(): string[];
71
+ private built;
72
+ private typing;
73
+ private _messages;
74
+ private _suggestions;
75
+ private _tools;
76
+ private _attachOptions;
77
+ private mainEl;
78
+ private scrollEl;
79
+ private dockEl;
80
+ private composer;
81
+ private threadEl;
82
+ private artifactEl;
83
+ private artifactTitleEl;
84
+ private artifactSubtitleEl;
85
+ private artifactBodyEl;
86
+ private activeArtifactId;
87
+ private artifactSeq;
88
+ set messages(v: DbChatMessageData[]);
89
+ get messages(): DbChatMessageData[];
90
+ set suggestions(v: DbChatSuggestion[]);
91
+ get suggestions(): DbChatSuggestion[];
92
+ set tools(v: DbChatTool[]);
93
+ get tools(): DbChatTool[];
94
+ set attachOptions(v: DbChatAttachOption[]);
95
+ get attachOptions(): DbChatAttachOption[];
96
+ connectedCallback(): void;
97
+ attributeChangedCallback(name: string): void;
98
+ private build;
99
+ private buildArtifact;
100
+ private sync;
101
+ private syncArtifact;
102
+ private syncComposerToggles;
103
+ private renderContent;
104
+ private renderHero;
105
+ private renderThread;
106
+ private buildMessage;
107
+ private ensureArtifactId;
108
+ private buildArtifactCard;
109
+ private syncArtifactCardStates;
110
+ private toggleArtifactFromCard;
111
+ private buildTyping;
112
+ private renderDock;
113
+ private onSend;
114
+ private onSuggestionSelect;
115
+ private relay;
116
+ private scrollToEnd;
117
+ /** 메시지를 추가하고 스레드로 전환/스크롤. 추가된 메시지 id 반환 */
118
+ addMessage(msg: DbChatMessageData): string;
119
+ /** 특정 메시지 본문/속성 갱신 */
120
+ updateMessage(id: string, patch: Partial<DbChatMessageData>): void;
121
+ /** 스트리밍용: 마지막(또는 지정) 메시지 본문에 청크 이어붙이기 */
122
+ appendToMessage(id: string, chunk: string): void;
123
+ /** 전체 메시지 교체 */
124
+ setMessages(list: DbChatMessageData[]): void;
125
+ /** 대화를 비우고 히어로(빈 상태)로 복귀 */
126
+ clear(): void;
127
+ /** 생각 중(…) 표시 토글 */
128
+ setTyping(on: boolean): void;
129
+ /** 전송 중(정지 버튼) 상태 — 컴포저에 위임 */
130
+ setStreaming(on: boolean): void;
131
+ /** 입력창 포커스 */
132
+ focusInput(): void;
133
+ /** 컴포저 인스턴스 접근 */
134
+ getComposer(): DbChatComposer;
135
+ get artifactOpen(): boolean;
136
+ set artifactOpen(v: boolean);
137
+ /**
138
+ * 우측 아티팩트 패널을 엽니다(내용 지정 시 함께 세팅).
139
+ * 열리면 채팅 본문이 좌측으로 밀립니다.
140
+ * `id` 를 넘기면 스레드 인라인 카드 활성 상태가 동기화됩니다.
141
+ */
142
+ openArtifact(opts?: DbArtifactOptions): void;
143
+ /** 아티팩트 패널을 닫습니다. */
144
+ closeArtifact(): void;
145
+ /** 아티팩트 열림/닫힘 토글. */
146
+ toggleArtifact(): void;
147
+ /** 아티팩트 본문 요소(커스텀 콘텐츠를 직접 마운트할 때). */
148
+ getArtifactBody(): HTMLElement;
149
+ /** 아티팩트 본문을 요소로 교체합니다. */
150
+ setArtifactContent(node: Node): void;
151
+ }
152
+ declare global {
153
+ interface HTMLElementTagNameMap {
154
+ 'db-ai-chat': DbAiChat;
155
+ }
156
+ }
157
+
158
+ export { DbAiChat };
159
+ export type { DbArtifactOptions, DbChatArtifactRef, DbChatMessageData };
@@ -0,0 +1 @@
1
+ import"./db-chat-welcome.js";import"./db-chat-suggestions.js";import"./db-chat-message.js";import"./db-chat-typing.js";import"./db-chat-composer.js";import{createDbIcon as t,isDbIconName as e}from"./db-icons.js";const i="designbase-wc-ai-chat";let s=0;function el(t,e,i){const s=document.createElement(t);return e&&(s.className=e),null!=i&&(s.textContent=i),s}class DbAiChat extends HTMLElement{constructor(){super(...arguments),this.built=!1,this.typing=!1,this._messages=[],this._suggestions=[],this._tools=[],this._attachOptions=null,this.threadEl=null,this.activeArtifactId=null,this.artifactSeq=0,this.onSend=t=>{t.stopPropagation();const e=t.detail;this.dispatchEvent(new CustomEvent("db-send",{detail:e,bubbles:!0,composed:!0}))},this.onSuggestionSelect=t=>{t.stopPropagation();const e=t.detail,i=new CustomEvent("db-suggestion-select",{detail:e,bubbles:!0,composed:!0,cancelable:!0});this.dispatchEvent(i)&&(this.composer.value=e.value,this.composer.focusInput())}}static get observedAttributes(){return["greeting","title","highlight","subtitle","placeholder","orb-variant","suggestions-layout","suggestions-columns","disclaimer","voice","attach","max-width","artifact-open","artifact-title"]}set messages(t){this._messages=Array.isArray(t)?t.map(t=>({id:`m${s+=1}`,...t})):[],this.built&&this.renderContent()}get messages(){return this._messages}set suggestions(t){this._suggestions=Array.isArray(t)?t:[],this.built&&0===this._messages.length&&this.renderContent()}get suggestions(){return this._suggestions}set tools(t){this._tools=Array.isArray(t)?t:[],this.built&&(this.composer.tools=this._tools)}get tools(){return this._tools}set attachOptions(t){this._attachOptions=Array.isArray(t)?t:null,this.built&&this._attachOptions&&(this.composer.attachOptions=this._attachOptions)}get attachOptions(){return this._attachOptions??this.composer?.attachOptions??[]}connectedCallback(){this.built||this.build(),this.sync()}attributeChangedCallback(t){this.built&&("placeholder"!==t?"voice"!==t&&"attach"!==t?"disclaimer"!==t?"artifact-open"!==t?"artifact-title"!==t?this.sync():this.artifactTitleEl.textContent=this.getAttribute("artifact-title")||"":this.syncArtifact(!0):this.renderDock():this.syncComposerToggles():this.composer.setAttribute("placeholder",this.getAttribute("placeholder")||""))}build(){this.built=!0,this.classList.add(i),this.replaceChildren(),this.mainEl=el("div",`${i}__main`),this.scrollEl=el("div",`${i}__scroll`),this.dockEl=el("div",`${i}__dock`),this.composer=document.createElement("db-chat-composer"),this.composer.className=`${i}__composer`,this.composer.addEventListener("db-send",this.onSend),this.composer.addEventListener("db-stop",t=>this.relay(t,"db-stop")),this.composer.addEventListener("db-tool-toggle",t=>this.relay(t,"db-tool-toggle")),this.composer.addEventListener("db-attach",t=>this.relay(t,"db-attach")),this.composer.addEventListener("db-attach-files",t=>this.relay(t,"db-attach-files")),this.composer.addEventListener("db-voice",t=>this.relay(t,"db-voice")),this.mainEl.append(this.scrollEl,this.dockEl),this.buildArtifact(),this.append(this.mainEl,this.artifactEl)}buildArtifact(){this.artifactEl=el("aside",`${i}__artifact`),this.artifactEl.setAttribute("aria-hidden","true");const e=el("div",`${i}__artifact-panel`),s=el("div",`${i}__artifact-header`),a=el("div",`${i}__artifact-titles`);this.artifactTitleEl=el("div",`${i}__artifact-title`),this.artifactSubtitleEl=el("div",`${i}__artifact-subtitle`),this.artifactSubtitleEl.hidden=!0,a.append(this.artifactTitleEl,this.artifactSubtitleEl);const r=el("button",`${i}__artifact-close`);r.type="button",r.setAttribute("aria-label","아티팩트 닫기"),r.append(t("close",18)),r.addEventListener("click",()=>this.closeArtifact()),s.append(a,r),this.artifactBodyEl=el("div",`${i}__artifact-body`),e.append(s,this.artifactBodyEl),this.artifactEl.append(e)}sync(){const t=this.getAttribute("max-width")||"100%";this.style.setProperty("--dbchat-max",t),this.syncComposerToggles(),this.composer.setAttribute("placeholder",this.getAttribute("placeholder")||"무엇이든 물어보세요…"),this._tools.length&&(this.composer.tools=this._tools),this._attachOptions&&(this.composer.attachOptions=this._attachOptions);const e=this.getAttribute("artifact-title");null!=e&&(this.artifactTitleEl.textContent=e),this.renderContent(),this.renderDock(),this.syncArtifact(!1)}syncArtifact(t){const e=this.hasAttribute("artifact-open");this.classList.toggle(`${i}--artifact-open`,e),this.artifactEl.setAttribute("aria-hidden",String(!e)),this.artifactEl.toggleAttribute("inert",!e),e||(this.activeArtifactId=null),this.syncArtifactCardStates(),t&&this.dispatchEvent(new CustomEvent(e?"db-artifact-open":"db-artifact-close",{detail:e?{id:this.activeArtifactId}:{id:null},bubbles:!0,composed:!0}))}syncComposerToggles(){this.composer.toggleAttribute("voice",this.hasAttribute("voice")),this.composer.toggleAttribute("attach","false"!==this.getAttribute("attach"))}renderContent(){this.scrollEl.replaceChildren(),this.threadEl=null;const t=0===this._messages.length;this.classList.toggle(`${i}--empty`,t),t?this.renderHero():this.renderThread()}renderHero(){const t=el("div",`${i}__hero`),e=document.createElement("db-chat-welcome");if(e.className=`${i}__welcome`,this.getAttribute("greeting")&&e.setAttribute("greeting",this.getAttribute("greeting")),e.setAttribute("title",this.getAttribute("title")||"무엇을 도와드릴까요?"),this.getAttribute("highlight")&&e.setAttribute("highlight",this.getAttribute("highlight")),this.getAttribute("subtitle")&&e.setAttribute("subtitle",this.getAttribute("subtitle")),e.setAttribute("orb-variant",this.getAttribute("orb-variant")||"aurora"),e.setAttribute("align","center"),t.append(e),this._suggestions.length){const e=document.createElement("db-chat-suggestions");e.className=`${i}__suggestions`,e.setAttribute("layout",this.getAttribute("suggestions-layout")||"card"),e.setAttribute("columns",this.getAttribute("suggestions-columns")||"3"),e.items=this._suggestions,e.addEventListener("db-select",this.onSuggestionSelect),t.append(e)}this.scrollEl.append(t)}renderThread(){const t=el("div",`${i}__thread`);this._messages.forEach(e=>t.append(this.buildMessage(e))),this.threadEl=t,this.scrollEl.append(t),this.typing&&t.append(this.buildTyping()),requestAnimationFrame(()=>this.scrollToEnd())}buildMessage(t){const e=el("div",`${i}__turn`);e.dataset.id=t.id||"";const s=el("db-chat-message");return s.dataset.id=t.id||"",s.setAttribute("role",t.role||"assistant"),t.name&&s.setAttribute("name",t.name),t.time&&s.setAttribute("timestamp",t.time),t.avatarSrc&&s.setAttribute("avatar-src",t.avatarSrc),t.avatarInitials&&s.setAttribute("avatar-initials",t.avatarInitials),t.actions&&s.setAttribute("actions",t.actions),t.status&&s.setAttribute("status",t.status),t.variant&&s.setAttribute("variant",t.variant),null!=t.html?s.innerHTML=t.html:s.textContent=t.text||"",s.addEventListener("db-action",t=>this.relay(t,"db-message-action")),e.append(s),t.artifact&&(this.ensureArtifactId(t.artifact),e.append(this.buildArtifactCard(t.artifact))),e}ensureArtifactId(t){return t.id||(t.id=`art-${this.artifactSeq+=1}`),t.id}buildArtifactCard(s){const a=this.ensureArtifactId(s),r=el("button",`${i}__artifact-card`);r.type="button",r.dataset.artifactId=a,r.setAttribute("aria-pressed","false"),r.setAttribute("aria-label",`${s.title} 아티팩트 열기`);const n=el("span",`${i}__artifact-card-icon`),c=s.icon&&e(s.icon)?s.icon:"code";n.append(t(c,18));const l=el("div",`${i}__artifact-card-meta`);l.append(el("div",`${i}__artifact-card-title`,s.title)),s.subtitle&&l.append(el("div",`${i}__artifact-card-subtitle`,s.subtitle));const o=el("span",`${i}__artifact-card-chevron`);return o.append(t("chevron-right",16)),r.append(n,l,o),r.addEventListener("click",()=>this.toggleArtifactFromCard(s)),r}syncArtifactCardStates(){this.querySelectorAll(`.${i}__artifact-card`).forEach(t=>{const e=t,s=this.artifactOpen&&e.dataset.artifactId===this.activeArtifactId;e.classList.toggle(`${i}__artifact-card--active`,s),e.setAttribute("aria-pressed",String(s))})}toggleArtifactFromCard(t){const e=this.ensureArtifactId(t);this.artifactOpen&&this.activeArtifactId===e?this.closeArtifact():this.openArtifact({id:e,title:t.title,subtitle:t.subtitle,html:t.html})}buildTyping(){const t=el("db-chat-typing",`${i}__typing`),e=this.getAttribute("title")||"AI";return t.setAttribute("name",this.getAttribute("agent-name")||e),t.setAttribute("label","생각 중…"),t.setAttribute("avatar-initials","AI"),t}renderDock(){this.dockEl.replaceChildren(),this.dockEl.append(this.composer);const t=this.getAttribute("disclaimer");t&&this.dockEl.append(el("p",`${i}__disclaimer`,t))}relay(t,e){t.stopPropagation(),this.dispatchEvent(new CustomEvent(e,{detail:t.detail,bubbles:!0,composed:!0}))}scrollToEnd(){this.scrollEl.scrollTop=this.scrollEl.scrollHeight}addMessage(t){const e={id:`m${s+=1}`,...t},i=0===this._messages.length;if(this._messages.push(e),i||!this.threadEl)this.renderContent();else{const t=this.threadEl.querySelector("db-chat-typing"),i=this.buildMessage(e);t?this.threadEl.insertBefore(i,t):this.threadEl.append(i),requestAnimationFrame(()=>this.scrollToEnd())}return e.id}updateMessage(t,e){const s=this._messages.find(e=>e.id===t);if(!s)return;Object.assign(s,e);const a=this.threadEl?.querySelector(`db-chat-message[data-id="${t}"]`);if(!a)return;const r=a.querySelector(".designbase-wc-chat-message__content");if(!r||null==e.html&&null==e.text||(null!=e.html?r.innerHTML=e.html:r.textContent=e.text||""),e.status&&a.setAttribute("status",e.status),void 0!==e.artifact){const t=a.closest(`.${i}__turn`)||a.parentElement;t?.querySelector(`.${i}__artifact-card`)?.remove(),e.artifact&&t&&(this.ensureArtifactId(e.artifact),t.append(this.buildArtifactCard(e.artifact)),this.syncArtifactCardStates())}requestAnimationFrame(()=>this.scrollToEnd())}appendToMessage(t,e){const i=this._messages.find(e=>e.id===t);if(!i)return;i.text=(i.text||"")+e;const s=this.threadEl?.querySelector(`db-chat-message[data-id="${t}"]`),a=s?.querySelector(".designbase-wc-chat-message__content");a&&(a.textContent=i.text),requestAnimationFrame(()=>this.scrollToEnd())}setMessages(t){this.messages=t}clear(){this._messages=[],this.typing=!1,this.closeArtifact(),this.built&&this.renderContent()}setTyping(t){if(this.typing=Boolean(t),!this.built||!this.threadEl)return;const e=this.threadEl.querySelector("db-chat-typing");this.typing&&!e?(this.threadEl.append(this.buildTyping()),requestAnimationFrame(()=>this.scrollToEnd())):!this.typing&&e&&e.remove()}setStreaming(t){this.composer?.setStreaming(Boolean(t))}focusInput(){this.composer?.focusInput()}getComposer(){return this.composer}get artifactOpen(){return this.hasAttribute("artifact-open")}set artifactOpen(t){this.toggleAttribute("artifact-open",t)}openArtifact(t={}){null!=t.title&&(this.artifactTitleEl.textContent=t.title),null!=t.subtitle&&(this.artifactSubtitleEl.textContent=t.subtitle,this.artifactSubtitleEl.hidden=!t.subtitle),null!=t.html&&(this.artifactBodyEl.innerHTML=t.html),null!=t.id&&(this.activeArtifactId=t.id);const e=this.artifactOpen;this.artifactOpen=!0,e&&this.syncArtifactCardStates()}closeArtifact(){this.activeArtifactId=null;const t=this.artifactOpen;this.artifactOpen=!1,t||this.syncArtifactCardStates()}toggleArtifact(){this.artifactOpen?this.closeArtifact():this.artifactOpen=!0}getArtifactBody(){return this.artifactBodyEl}setArtifactContent(t){this.artifactBodyEl.replaceChildren(t)}}customElements.get("db-ai-chat")||customElements.define("db-ai-chat",DbAiChat);export{DbAiChat};
@@ -1 +1 @@
1
- import{parseAnimationBackgroundConfig as t,mountAnimationLayers as e,applyContainerStyles as s,syncLuminaOverlays as n,ANIMATION_BACKGROUND_CLASS as i}from"./animation-background/layers.js";import{getControlsForType as o,resetControlsToDefaults as l,getControlSliderBounds as r,controlSliderToAttr as a,writeControlAttribute as c,readControlValue as d,controlAttrToSlider as h}from"./animation-background/controls.js";import{isGraphitePresetId as u,getGraphitePreset as p}from"./animation-background/graphite-presets.js";import{createDbIcon as m}from"./db-icons.js";const b=i,g=["particles","stars","snow","flowers","confetti","mesh-flow","fluid","radiant","ethereal","graphite"],y=["mesh-flow","fluid","radiant","ethereal"];class DbAnimationBackground extends HTMLElement{constructor(){super(...arguments),this.panelOpen=!1,this.controlInputs=new Map,this.syncingControls=!1}static get observedAttributes(){return["type","theme","intensity","blur","speed","direction","colors","width","height","border-radius","opacity","blend-mode","particle-count","particle-size","star-count","star-size","wind","clickable","disabled","noise","show-vignette","preset","zoom","show-controls","shader-speed","shader-intensity","warp"]}connectedCallback(){this.style.display="block",this.render()}disconnectedCallback(){this.teardownLayers(),this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0)}attributeChangedCallback(t,e,s){this.isConnected&&e!==s&&("show-controls"!==t?this.syncingControls||("type"===t&&this.getBool("show-controls",!1)&&this.rebuildControlInputs(),this.applyConfig(),this.getBool("show-controls",!1)&&this.syncControlInputs()):this.syncControlsVisibility())}getBool(t,e=!1){return this.hasAttribute(t)?"false"!==this.getAttribute(t):e}getSizeStyle(t){if(!t)return;const e=Number(t);return Number.isFinite(e)?`${e}px`:t}getConfig(){return t(this)}teardownLayers(){this.layerHandle?.destroy?.(),this.layerHandle=void 0,this.mountedType=void 0,this.layersEl&&this.layersEl.replaceChildren()}remountLayers(t){this.layersEl&&(this.teardownLayers(),this.layerHandle=e(this.layersEl,t),this.mountedType=t.type)}canLiveUpdate(t){return this.mountedType===t.type&&g.includes(t.type)&&"function"==typeof this.layerHandle?.update}applyConfig(){const t=this.getConfig();this.className=[b,`${b}--${t.type}`,t.clickable&&!t.disabled&&`${b}--clickable`,t.disabled&&`${b}--disabled`,this.getBool("show-controls",!1)&&`${b}--show-controls`].filter(Boolean).join(" "),s(this,t);const e=this.getSizeStyle(this.getAttribute("width")),i=this.getSizeStyle(this.getAttribute("height")),o=this.getSizeStyle(this.getAttribute("border-radius"));e&&(this.style.width=e),i&&(this.style.height=i),o&&(this.style.borderRadius=o),this.style.opacity="",this.layersEl&&(this.layersEl.style.opacity=String(t.opacity));const l=this.getAttribute("blend-mode");if(l&&(this.style.mixBlendMode=l),t.disabled)return this.teardownLayers(),void this.syncClickable(t);this.canLiveUpdate(t)?(this.layerHandle?.update?.(t),this.layersEl&&y.includes(t.type)&&n(this.layersEl,t.noise,t.showVignette)):this.remountLayers(t),this.syncClickable(t)}syncClickable(t){this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0),t.clickable&&!t.disabled&&(this.clickHandler=()=>{this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.addEventListener("click",this.clickHandler))}render(){if(!this.layersEl){this.layersEl=document.createElement("div"),this.layersEl.className=`${b}__layers`,Object.assign(this.layersEl.style,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"0"}),this.contentEl=document.createElement("div"),this.contentEl.className=`${b}__content`,Object.assign(this.contentEl.style,{position:"relative",zIndex:"10",width:"100%",height:"100%"});const t=document.createElement("slot");this.contentEl.appendChild(t),this.append(this.layersEl,this.contentEl)}this.ensureControlsShell(),this.applyConfig(),this.syncControlsVisibility()}ensureControlsShell(){if(this.controlsRootEl)return;const t=document.createElement("div");t.className=`${b}__controls-root`,t.hidden=!0;const e=this.createIconButton("settings","컨트롤 열기",()=>{this.panelOpen=!this.panelOpen,this.syncPanelState()});e.setAttribute("variant","secondary"),e.className=`${b}__controls-gear`;const s=document.createElement("div");s.className=`${b}__controls-panel`,s.setAttribute("role","dialog"),s.hidden=!0,s.addEventListener("click",t=>t.stopPropagation());const n=document.createElement("div");n.className=`${b}__controls-head`;const i=document.createElement("span");i.className=`${b}__controls-title`,i.append(m("settings",14),document.createTextNode(" Controls"));const r=this.createIconButton("refresh","기본값으로 초기화",()=>{const t=this.getConfig(),e=o(t.type);if(this.syncingControls=!0,l(this,e),"graphite"===t.type){const t=p("graphite");this.setAttribute("zoom",String(t.scale)),this.setAttribute("colors",JSON.stringify(t.colors))}this.syncingControls=!1,this.applyConfig(),this.syncControlInputs()});r.className=`${b}__controls-icon-btn`,n.append(i,r),s.append(n),t.append(e,s),this.appendChild(t),this.controlsRootEl=t,this.panelEl=s}syncControlsVisibility(){if(!this.controlsRootEl)return;const t=this.getBool("show-controls",!1);this.controlsRootEl.hidden=!t,t?this.rebuildControlInputs():(this.panelOpen=!1,this.syncPanelState())}syncPanelState(){if(!this.controlsRootEl||!this.panelEl)return;const t=this.controlsRootEl.querySelector(`.${b}__controls-gear`);t&&(t.dataset.open=this.panelOpen?"true":"false",t.setAttribute("aria-expanded",this.panelOpen?"true":"false")),this.panelEl.hidden=!this.panelOpen}createIconButton(t,e,s){const n=document.createElement("db-button");return n.setAttribute("variant","tertiary"),n.setAttribute("size","s"),n.setAttribute("icon-only",""),n.setAttribute("start-icon",t),n.setAttribute("aria-label",e),n.addEventListener("click",t=>{t.stopPropagation(),s()}),n}rebuildControlInputs(){if(!this.panelEl)return;this.panelEl.querySelectorAll(`.${b}__controls-field`).forEach(t=>t.remove()),this.controlInputs.clear();const t=this.getConfig(),e=o(t.type),s=this.panelEl.querySelector(`.${b}__controls-title`);s&&(s.lastChild?.remove(),s.append(document.createTextNode(` ${t.type}`))),e.forEach(t=>{const e=this.createControlField(t);this.panelEl?.appendChild(e)}),this.syncControlInputs()}createControlField(t){const e=document.createElement("div");if(e.className=`${b}__controls-field`,e.dataset.attr=t.attr,"range"===t.kind){const s=r(t),n=document.createElement("db-range-slider");return n.className=`${b}__controls-range`,n.setAttribute("size","s"),n.setAttribute("full-width",""),n.setAttribute("show-label",""),n.setAttribute("label",t.label),n.setAttribute("show-value",""),n.setAttribute("value-position","top"),n.setAttribute("show-thumb-tooltip",""),n.setAttribute("min",String(s.min)),n.setAttribute("max",String(s.max)),n.setAttribute("step",String(s.step)),null!=s.fixed&&n.setAttribute("value-fixed",String(s.fixed)),n.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,a(t,s.value))}),e.appendChild(n),this.controlInputs.set(t.attr,n),e}if("select"===t.kind){const s=document.createElement("div");s.className=`${b}__controls-label`,s.textContent=t.label;const n=t.options??[];if(n.length>4){const i=document.createElement("db-select");i.className=`${b}__controls-select`,i.setAttribute("size","s"),i.setAttribute("full-width",""),i.setAttribute("options",JSON.stringify(n.map(t=>({value:t,label:t})))),i.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,s.value)}),e.append(s,i),this.controlInputs.set(t.attr,i)}else{const i=document.createElement("db-segment-control");i.className=`${b}__controls-seg`,i.setAttribute("size","s"),i.setAttribute("full-width",""),i.setAttribute("options",JSON.stringify(n.map(t=>({value:t,label:t})))),i.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,s.value)}),e.append(s,i),this.controlInputs.set(t.attr,i)}return e}if("toggle"===t.kind){const s=document.createElement("div");s.className=`${b}__controls-toggle`;const n=document.createElement("span");n.textContent=t.label;const i=document.createElement("db-toggle");return i.setAttribute("size","s"),i.addEventListener("db-change",e=>{const s=e.detail;this.commitControlValue(t,Boolean(s.checked))}),s.append(n,i),e.appendChild(s),this.controlInputs.set(t.attr,i),e}const s=document.createElement("div");s.className=`${b}__controls-label`,s.textContent=t.label;const n=document.createElement("div");return n.className=`${b}__controls-colors`,e.append(s,n),this.controlInputs.set(t.attr,n),e}commitControlValue(t,e){if(this.syncingControls=!0,c(this,t,e),"preset"===t.attr&&"graphite"===this.getConfig().type&&"string"==typeof e&&u(e)){const t=p(e);this.setAttribute("zoom",String(t.scale)),this.setAttribute("colors",JSON.stringify(t.colors))}this.syncingControls=!1,this.applyConfig()}syncControlInputs(){o(this.getConfig().type).forEach(t=>{const e=d(this,t),s=this.controlInputs.get(t.attr);if(s)if("range"===t.kind&&function isRangeSlider(t){return"DB-RANGE-SLIDER"===t.tagName}(s)){const n=Number(e);s.setAttribute("value",String(h(t,n)))}else if("select"===t.kind)s.setAttribute("value",String(e));else if("toggle"===t.kind){Boolean(e)?s.setAttribute("checked",""):s.removeAttribute("checked")}else"colors"===t.kind&&this.renderColorInputs(s,t,e)})}renderColorInputs(t,e,s){const n=[...s];t.replaceChildren();const commitStructuralChange=s=>{this.commitControlValue(e,s),this.renderColorInputs(t,e,s)};if(n.forEach((s,i)=>{const o=document.createElement("div");o.className=`${b}__controls-color`;const l=document.createElement("db-color-picker");if(l.className=`${b}__controls-color-picker`,l.setAttribute("size","s"),l.setAttribute("full-width",""),l.setAttribute("show-alpha","false"),l.setAttribute("show-eyedropper","false"),l.setAttribute("value",s),l.addEventListener("db-change",t=>{const s=t.detail,o=s?.value;"string"==typeof o&&o&&(n[i]=o,this.commitControlValue(e,[...n]))}),o.appendChild(l),n.length>1){const t=this.createIconButton("trash","색상 제거",()=>{commitStructuralChange(n.filter((t,e)=>e!==i))});t.className=`${b}__controls-color-remove`,o.appendChild(t)}t.appendChild(o)}),n.length<8){const e=this.createIconButton("plus","색상 추가",()=>{commitStructuralChange([...n,n[n.length-1]??"#ffffff"])});e.className=`${b}__controls-color-add`,t.appendChild(e)}}}customElements.get("db-animation-background")||customElements.define("db-animation-background",DbAnimationBackground);export{DbAnimationBackground};
1
+ import{parseAnimationBackgroundConfig as t,mountAnimationLayers as e,applyContainerStyles as s,syncLuminaOverlays as n,ANIMATION_BACKGROUND_CLASS as i}from"./animation-background/layers.js";import{getControlsForType as o,resetControlsToDefaults as l,getControlSliderBounds as r,controlSliderToAttr as a,writeControlAttribute as c,readControlValue as d,controlAttrToSlider as h}from"./animation-background/controls.js";import{isGraphitePresetId as u,getGraphitePreset as p}from"./animation-background/graphite-presets.js";import{createDbIcon as m}from"./db-icons.js";const b=i,g=["particles","stars","snow","flowers","confetti","mesh-flow","fluid","radiant","ethereal","graphite"],y=["mesh-flow","fluid","radiant","ethereal"];class DbAnimationBackground extends HTMLElement{constructor(){super(...arguments),this.panelOpen=!1,this.controlInputs=new Map,this.syncingControls=!1}static get observedAttributes(){return["type","theme","intensity","blur","speed","direction","colors","width","height","border-radius","opacity","blend-mode","particle-count","particle-size","star-count","star-size","wind","clickable","disabled","noise","show-vignette","preset","zoom","show-controls","shader-speed","shader-intensity","warp"]}connectedCallback(){this.style.display="block",this.render()}disconnectedCallback(){this.teardownLayers(),this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0)}attributeChangedCallback(t,e,s){this.isConnected&&e!==s&&("show-controls"!==t?this.syncingControls||("type"===t&&this.getBool("show-controls",!1)&&this.rebuildControlInputs(),this.applyConfig(),this.getBool("show-controls",!1)&&this.syncControlInputs()):this.syncControlsVisibility())}getBool(t,e=!1){return this.hasAttribute(t)?"false"!==this.getAttribute(t):e}getSizeStyle(t){if(!t)return;const e=Number(t);return Number.isFinite(e)?`${e}px`:t}getConfig(){return t(this)}teardownLayers(){this.layerHandle?.destroy?.(),this.layerHandle=void 0,this.mountedType=void 0,this.layersEl&&this.layersEl.replaceChildren()}remountLayers(t){this.layersEl&&(this.teardownLayers(),this.layerHandle=e(this.layersEl,t),this.mountedType=t.type)}canLiveUpdate(t){return this.mountedType===t.type&&g.includes(t.type)&&"function"==typeof this.layerHandle?.update}applyConfig(){const t=this.getConfig();this.className=[b,`${b}--${t.type}`,t.clickable&&!t.disabled&&`${b}--clickable`,t.disabled&&`${b}--disabled`,this.getBool("show-controls",!1)&&`${b}--show-controls`].filter(Boolean).join(" "),s(this,t);const e=this.getSizeStyle(this.getAttribute("width")),i=this.getSizeStyle(this.getAttribute("height")),o=this.getSizeStyle(this.getAttribute("border-radius"));e&&(this.style.width=e),i&&(this.style.height=i),this.style.borderRadius=o||"0",this.style.border="none",this.style.opacity="",this.layersEl&&(this.layersEl.style.opacity=String(t.opacity));const l=this.getAttribute("blend-mode");if(l&&(this.style.mixBlendMode=l),t.disabled)return this.teardownLayers(),void this.syncClickable(t);this.canLiveUpdate(t)?(this.layerHandle?.update?.(t),this.layersEl&&y.includes(t.type)&&n(this.layersEl,t.noise,t.showVignette)):this.remountLayers(t),this.syncClickable(t)}syncClickable(t){this.clickHandler&&(this.removeEventListener("click",this.clickHandler),this.clickHandler=void 0),t.clickable&&!t.disabled&&(this.clickHandler=()=>{this.dispatchEvent(new CustomEvent("db-click",{bubbles:!0,composed:!0}))},this.addEventListener("click",this.clickHandler))}render(){if(!this.layersEl){this.layersEl=document.createElement("div"),this.layersEl.className=`${b}__layers`,Object.assign(this.layersEl.style,{position:"absolute",inset:"0",width:"100%",height:"100%",zIndex:"0"}),this.contentEl=document.createElement("div"),this.contentEl.className=`${b}__content`,Object.assign(this.contentEl.style,{position:"relative",zIndex:"10",width:"100%",height:"100%"});const t=document.createElement("slot");this.contentEl.appendChild(t),this.append(this.layersEl,this.contentEl)}this.ensureControlsShell(),this.applyConfig(),this.syncControlsVisibility()}ensureControlsShell(){if(this.controlsRootEl)return;const t=document.createElement("div");t.className=`${b}__controls-root`,t.hidden=!0;const e=this.createIconButton("settings","컨트롤 열기",()=>{this.panelOpen=!this.panelOpen,this.syncPanelState()});e.setAttribute("variant","secondary"),e.className=`${b}__controls-gear`;const s=document.createElement("div");s.className=`${b}__controls-panel`,s.setAttribute("role","dialog"),s.hidden=!0,s.addEventListener("click",t=>t.stopPropagation());const n=document.createElement("div");n.className=`${b}__controls-head`;const i=document.createElement("span");i.className=`${b}__controls-title`,i.append(m("settings",14),document.createTextNode(" Controls"));const r=this.createIconButton("refresh","기본값으로 초기화",()=>{const t=this.getConfig(),e=o(t.type);if(this.syncingControls=!0,l(this,e),"graphite"===t.type){const t=p("graphite");this.setAttribute("zoom",String(t.scale)),this.setAttribute("colors",JSON.stringify(t.colors))}this.syncingControls=!1,this.applyConfig(),this.syncControlInputs()});r.className=`${b}__controls-icon-btn`,n.append(i,r),s.append(n),t.append(e,s),this.appendChild(t),this.controlsRootEl=t,this.panelEl=s}syncControlsVisibility(){if(!this.controlsRootEl)return;const t=this.getBool("show-controls",!1);this.controlsRootEl.hidden=!t,t?this.rebuildControlInputs():(this.panelOpen=!1,this.syncPanelState())}syncPanelState(){if(!this.controlsRootEl||!this.panelEl)return;const t=this.controlsRootEl.querySelector(`.${b}__controls-gear`);t&&(t.dataset.open=this.panelOpen?"true":"false",t.setAttribute("aria-expanded",this.panelOpen?"true":"false")),this.panelEl.hidden=!this.panelOpen}createIconButton(t,e,s){const n=document.createElement("db-button");return n.setAttribute("variant","tertiary"),n.setAttribute("size","s"),n.setAttribute("icon-only",""),n.setAttribute("start-icon",t),n.setAttribute("aria-label",e),n.addEventListener("click",t=>{t.stopPropagation(),s()}),n}rebuildControlInputs(){if(!this.panelEl)return;this.panelEl.querySelectorAll(`.${b}__controls-field`).forEach(t=>t.remove()),this.controlInputs.clear();const t=this.getConfig(),e=o(t.type),s=this.panelEl.querySelector(`.${b}__controls-title`);s&&(s.lastChild?.remove(),s.append(document.createTextNode(` ${t.type}`))),e.forEach(t=>{const e=this.createControlField(t);this.panelEl?.appendChild(e)}),this.syncControlInputs()}createControlField(t){const e=document.createElement("div");if(e.className=`${b}__controls-field`,e.dataset.attr=t.attr,"range"===t.kind){const s=r(t),n=document.createElement("db-range-slider");return n.className=`${b}__controls-range`,n.setAttribute("size","s"),n.setAttribute("full-width",""),n.setAttribute("show-label",""),n.setAttribute("label",t.label),n.setAttribute("show-value",""),n.setAttribute("value-position","top"),n.setAttribute("show-thumb-tooltip",""),n.setAttribute("min",String(s.min)),n.setAttribute("max",String(s.max)),n.setAttribute("step",String(s.step)),null!=s.fixed&&n.setAttribute("value-fixed",String(s.fixed)),n.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,a(t,s.value))}),e.appendChild(n),this.controlInputs.set(t.attr,n),e}if("select"===t.kind){const s=document.createElement("div");s.className=`${b}__controls-label`,s.textContent=t.label;const n=t.options??[];if(n.length>4){const i=document.createElement("db-select");i.className=`${b}__controls-select`,i.setAttribute("size","s"),i.setAttribute("full-width",""),i.setAttribute("options",JSON.stringify(n.map(t=>({value:t,label:t})))),i.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,s.value)}),e.append(s,i),this.controlInputs.set(t.attr,i)}else{const i=document.createElement("db-segment-control");i.className=`${b}__controls-seg`,i.setAttribute("size","s"),i.setAttribute("full-width",""),i.setAttribute("options",JSON.stringify(n.map(t=>({value:t,label:t})))),i.addEventListener("db-change",e=>{const s=e.detail;null!=s.value&&this.commitControlValue(t,s.value)}),e.append(s,i),this.controlInputs.set(t.attr,i)}return e}if("toggle"===t.kind){const s=document.createElement("div");s.className=`${b}__controls-toggle`;const n=document.createElement("span");n.textContent=t.label;const i=document.createElement("db-toggle");return i.setAttribute("size","s"),i.addEventListener("db-change",e=>{const s=e.detail;this.commitControlValue(t,Boolean(s.checked))}),s.append(n,i),e.appendChild(s),this.controlInputs.set(t.attr,i),e}const s=document.createElement("div");s.className=`${b}__controls-label`,s.textContent=t.label;const n=document.createElement("div");return n.className=`${b}__controls-colors`,e.append(s,n),this.controlInputs.set(t.attr,n),e}commitControlValue(t,e){if(this.syncingControls=!0,c(this,t,e),"preset"===t.attr&&"graphite"===this.getConfig().type&&"string"==typeof e&&u(e)){const t=p(e);this.setAttribute("zoom",String(t.scale)),this.setAttribute("colors",JSON.stringify(t.colors))}this.syncingControls=!1,this.applyConfig()}syncControlInputs(){o(this.getConfig().type).forEach(t=>{const e=d(this,t),s=this.controlInputs.get(t.attr);if(s)if("range"===t.kind&&function isRangeSlider(t){return"DB-RANGE-SLIDER"===t.tagName}(s)){const n=Number(e);s.setAttribute("value",String(h(t,n)))}else if("select"===t.kind)s.setAttribute("value",String(e));else if("toggle"===t.kind){Boolean(e)?s.setAttribute("checked",""):s.removeAttribute("checked")}else"colors"===t.kind&&this.renderColorInputs(s,t,e)})}renderColorInputs(t,e,s){const n=[...s];t.replaceChildren();const commitStructuralChange=s=>{this.commitControlValue(e,s),this.renderColorInputs(t,e,s)};if(n.forEach((s,i)=>{const o=document.createElement("div");o.className=`${b}__controls-color`;const l=document.createElement("db-color-picker");if(l.className=`${b}__controls-color-picker`,l.setAttribute("size","s"),l.setAttribute("full-width",""),l.setAttribute("show-alpha","false"),l.setAttribute("show-eyedropper","false"),l.setAttribute("value",s),l.addEventListener("db-change",t=>{const s=t.detail,o=s?.value;"string"==typeof o&&o&&(n[i]=o,this.commitControlValue(e,[...n]))}),o.appendChild(l),n.length>1){const t=this.createIconButton("trash","색상 제거",()=>{commitStructuralChange(n.filter((t,e)=>e!==i))});t.className=`${b}__controls-color-remove`,o.appendChild(t)}t.appendChild(o)}),n.length<8){const e=this.createIconButton("plus","색상 추가",()=>{commitStructuralChange([...n,n[n.length-1]??"#ffffff"])});e.className=`${b}__controls-color-add`,t.appendChild(e)}}}customElements.get("db-animation-background")||customElements.define("db-animation-background",DbAnimationBackground);export{DbAnimationBackground};
@@ -0,0 +1,134 @@
1
+ import { DbIconName } from './db-icons.js';
2
+ import './db-button.js';
3
+ import './db-chip.js';
4
+
5
+ interface DbChatTool {
6
+ /** 고유 id (이벤트 detail 로 전달) */
7
+ id: string;
8
+ /** 표시 라벨 */
9
+ label: string;
10
+ /** 시작 아이콘 (DbIconName) */
11
+ icon?: DbIconName;
12
+ /** 활성 여부 */
13
+ active?: boolean;
14
+ }
15
+ interface DbChatAttachOption {
16
+ /** 고유 id (예: 'image', 'file', 'camera') */
17
+ id: string;
18
+ /** 표시 라벨 */
19
+ label: string;
20
+ /** 메뉴 아이콘 (DbIconName) */
21
+ icon?: DbIconName;
22
+ /** 파일 선택 시 accept 값. 지정하면 파일 선택창을 엽니다. 없으면 db-attach 이벤트만 발행 */
23
+ accept?: string;
24
+ /** 카메라/캡처 (모바일). 'user' | 'environment' */
25
+ capture?: 'user' | 'environment';
26
+ /** 다중 선택 허용 */
27
+ multiple?: boolean;
28
+ /** 보조 설명 (선택) */
29
+ description?: string;
30
+ }
31
+ interface DbChatAttachment {
32
+ id: string;
33
+ name: string;
34
+ /** 바이트 크기 */
35
+ size: number;
36
+ /** MIME 타입 */
37
+ mime: string;
38
+ /** 표시 종류 (아이콘 결정) */
39
+ kind: 'image' | 'video' | 'file';
40
+ /** 원본 File (파일 선택 시) */
41
+ file?: File;
42
+ /** 이미지 미리보기 objectURL */
43
+ preview?: string;
44
+ }
45
+ /**
46
+ * AI 채팅 입력 컴포저. 채팅 시작 전/중 모두에서 사용합니다.
47
+ * 자동 높이 textarea + 툴바(첨부·툴 토글·음성·전송)로 구성되며,
48
+ * 전송 버튼은 `db-button`, 툴 토글·첨부 미리보기는 `db-chip` 을 재사용합니다.
49
+ *
50
+ * - 툴 토글: `db-chip` 의 `default`↔`primary` variant 로 선택 상태를 표현합니다.
51
+ * - 첨부: 첨부 버튼을 누르면 드롭다운이 열려 이미지·동영상·파일·카메라 등
52
+ * 여러 종류를 선택할 수 있고, 고른 파일은 삭제 가능한 칩으로 미리보기됩니다.
53
+ * - 전송 중(`streaming`)에는 전송 버튼이 정지 버튼으로 바뀝니다.
54
+ *
55
+ * @example
56
+ * const c = document.querySelector('db-chat-composer');
57
+ * c.tools = [{ id:'reason', label:'추론', icon:'bulb' }];
58
+ * c.addEventListener('db-send', (e) => console.log(e.detail.value, e.detail.attachments));
59
+ */
60
+ declare class DbChatComposer extends HTMLElement {
61
+ static get observedAttributes(): string[];
62
+ private built;
63
+ private _tools;
64
+ private _attachOptions;
65
+ private _attachments;
66
+ private attachMenuOpen;
67
+ private field;
68
+ private attachmentsEl;
69
+ private toolsEl;
70
+ private attachWrap;
71
+ private attachBtn;
72
+ private attachMenu;
73
+ private fileInput;
74
+ private micBtn;
75
+ private sendBtn;
76
+ get value(): string;
77
+ set value(v: string);
78
+ get streaming(): boolean;
79
+ set streaming(v: boolean);
80
+ get disabled(): boolean;
81
+ set disabled(v: boolean);
82
+ /** 툴 토글 목록 (JSON 프로퍼티) */
83
+ get tools(): DbChatTool[];
84
+ set tools(list: DbChatTool[]);
85
+ /** 첨부 드롭다운 옵션 목록 */
86
+ get attachOptions(): DbChatAttachOption[];
87
+ set attachOptions(list: DbChatAttachOption[]);
88
+ /** 현재 첨부 목록 (읽기 전용 복사본) */
89
+ get attachments(): DbChatAttachment[];
90
+ connectedCallback(): void;
91
+ disconnectedCallback(): void;
92
+ attributeChangedCallback(name: string): void;
93
+ private build;
94
+ private makeIconButton;
95
+ private sync;
96
+ private renderTools;
97
+ private renderAttachMenu;
98
+ private renderAttachments;
99
+ private renderSendButton;
100
+ private syncSendState;
101
+ private autoGrow;
102
+ private handleAttachClick;
103
+ private openAttachMenu;
104
+ private closeAttachMenu;
105
+ private handleOutsideClick;
106
+ private chooseAttachOption;
107
+ private handleFilePicked;
108
+ private addFile;
109
+ private attachmentMeta;
110
+ private handleInput;
111
+ private handleKeyDown;
112
+ private handleSendClick;
113
+ private submit;
114
+ /** 입력 필드를 비웁니다. */
115
+ clear(): void;
116
+ /** 첨부를 하나 제거합니다. */
117
+ removeAttachment(id: string): void;
118
+ /** 모든 첨부를 제거합니다. */
119
+ clearAttachments(): void;
120
+ /** 프로그램적으로 첨부를 추가합니다(파일 또는 메타). */
121
+ addAttachment(input: File | Omit<DbChatAttachment, 'id' | 'kind'>): void;
122
+ /** 입력 필드에 포커스합니다. */
123
+ focusInput(): void;
124
+ /** 전송 중(정지 버튼) 상태를 설정합니다. */
125
+ setStreaming(streaming: boolean): void;
126
+ }
127
+ declare global {
128
+ interface HTMLElementTagNameMap {
129
+ 'db-chat-composer': DbChatComposer;
130
+ }
131
+ }
132
+
133
+ export { DbChatComposer };
134
+ export type { DbChatAttachOption, DbChatAttachment, DbChatTool };
@@ -0,0 +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.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";t.forEach(t=>this.addFile(t)),this.dispatchEvent(new CustomEvent("db-attach-files",{detail:{type:e,files:t},bubbles:!0,composed:!0}))},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)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick,!0),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.append(t,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 c=document.createElement("span");if(c.className="designbase-wc-chat-composer__attach-item-label",c.textContent=s.label,n.append(c),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){const e=document.createElement("db-chip");e.setAttribute("label",t.name),e.setAttribute("size","s"),e.setAttribute("variant","neutral"),e.setAttribute("deletable",""),e.setAttribute("start-icon",i[t.kind]),e.addEventListener("db-delete",()=>this.removeAttachment(t.id)),this.attachmentsEl.append(e)}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())}addFile(t){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};this._attachments.push(s),this.renderAttachments(),this.dispatchEvent(new CustomEvent("db-attachment-add",{detail:{attachment:this.attachmentMeta(s)},bubbles:!0,composed:!0}))}attachmentMeta(t){return{id:t.id,name:t.name,size:t.size,mime:t.mime,kind:t.kind,file:t.file}}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())}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);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};
@@ -0,0 +1,47 @@
1
+ import './db-avatar.js';
2
+
3
+ interface DbChatListItem {
4
+ id: string;
5
+ /** 상대(대화방) 이름 */
6
+ name: string;
7
+ avatarSrc?: string;
8
+ avatarInitials?: string;
9
+ /** 마지막 메시지 미리보기 */
10
+ preview?: string;
11
+ /** 시간 라벨 (예: '방금', '어제') */
12
+ time?: string;
13
+ /** 안 읽은 수 */
14
+ unread?: number;
15
+ /** 온라인 표시 */
16
+ online?: boolean;
17
+ }
18
+ /**
19
+ * 사람 간 대화(메신저) 목록. 아바타 + 이름 + 미리보기 + 시간 + 안읽음 배지의 행 리스트로,
20
+ * 아바타는 `db-avatar` 를 재사용합니다. AI 대화 이력은 `db-ai-chat-list` 를 쓰세요.
21
+ *
22
+ * @fires db-select - 대화 선택 (detail: { id })
23
+ *
24
+ * @example
25
+ * const list = document.querySelector('db-chat-list');
26
+ * list.items = [{ id:'1', name:'디지털 상담원', preview:'무엇을 도와드릴까요?', time:'방금', unread:1, online:true }];
27
+ * list.addEventListener('db-select', (e) => console.log(e.detail.id));
28
+ */
29
+ declare class DbChatList extends HTMLElement {
30
+ static get observedAttributes(): string[];
31
+ private _items;
32
+ get items(): DbChatListItem[];
33
+ set items(v: DbChatListItem[]);
34
+ get selectedId(): string;
35
+ set selectedId(v: string);
36
+ connectedCallback(): void;
37
+ attributeChangedCallback(): void;
38
+ private render;
39
+ }
40
+ declare global {
41
+ interface HTMLElementTagNameMap {
42
+ 'db-chat-list': DbChatList;
43
+ }
44
+ }
45
+
46
+ export { DbChatList };
47
+ export type { DbChatListItem };
@@ -0,0 +1 @@
1
+ import"./db-avatar.js";class DbChatList extends HTMLElement{constructor(){super(...arguments),this._items=[]}static get observedAttributes(){return["selected-id"]}get items(){return this._items}set items(t){this._items=Array.isArray(t)?t:[],this.render()}get selectedId(){return this.getAttribute("selected-id")||""}set selectedId(t){t?this.setAttribute("selected-id",t):this.removeAttribute("selected-id")}connectedCallback(){if(!this._items.length&&this.hasAttribute("items"))try{this._items=JSON.parse(this.getAttribute("items")||"[]")}catch{this._items=[]}this.render()}attributeChangedCallback(){this.render()}render(){this.className="designbase-wc-chat-list",this.setAttribute("role","list"),this.replaceChildren();const t=this.selectedId;for(const e of this._items){const s=document.createElement("button");s.type="button",s.className=["designbase-wc-chat-list__item",e.id===t&&"designbase-wc-chat-list__item--selected"].filter(Boolean).join(" "),s.setAttribute("role","listitem");const a=document.createElement("db-avatar");a.className="designbase-wc-chat-list__avatar",a.setAttribute("size","l"),a.setAttribute("variant","primary"),e.avatarSrc?a.setAttribute("src",e.avatarSrc):e.avatarInitials&&a.setAttribute("initials",e.avatarInitials),e.online&&a.setAttribute("status","online");const i=document.createElement("span");i.className="designbase-wc-chat-list__body";const n=document.createElement("span");n.className="designbase-wc-chat-list__top";const c=document.createElement("span");if(c.className="designbase-wc-chat-list__name",c.textContent=e.name,n.append(c),e.time){const t=document.createElement("span");t.className="designbase-wc-chat-list__time",t.textContent=e.time,n.append(t)}const r=document.createElement("span");r.className="designbase-wc-chat-list__bottom";const d=document.createElement("span");if(d.className="designbase-wc-chat-list__preview",d.textContent=e.preview||"",r.append(d),e.unread&&e.unread>0){const t=document.createElement("span");t.className="designbase-wc-chat-list__unread",t.textContent=e.unread>99?"99+":String(e.unread),r.append(t)}i.append(n,r),s.append(a,i),s.addEventListener("click",()=>{this.selectedId=e.id,this.dispatchEvent(new CustomEvent("db-select",{detail:{id:e.id},bubbles:!0,composed:!0}))}),this.append(s)}}}customElements.get("db-chat-list")||customElements.define("db-chat-list",DbChatList);export{DbChatList};
@@ -0,0 +1,39 @@
1
+ import './db-avatar.js';
2
+
3
+ declare const ROLES: readonly ["user", "assistant", "system"];
4
+ type Role = (typeof ROLES)[number];
5
+ /**
6
+ * 채팅 메시지 한 줄. 본문은 라이트 DOM 자식으로 전달하며 컴포넌트가 감쌉니다.
7
+ * 아바타는 `db-avatar` 를 재사용합니다.
8
+ *
9
+ * @example
10
+ * <db-chat-message role="assistant" name="Orion" actions="copy,regenerate,like,dislike">
11
+ * 안녕하세요! 무엇을 도와드릴까요?
12
+ * </db-chat-message>
13
+ */
14
+ declare class DbChatMessage extends HTMLElement {
15
+ static get observedAttributes(): string[];
16
+ private built;
17
+ private contentEl;
18
+ private avatarWrap;
19
+ private headerEl;
20
+ private nameEl;
21
+ private timeEl;
22
+ private actionsEl;
23
+ get role(): Role;
24
+ set role(v: Role);
25
+ connectedCallback(): void;
26
+ attributeChangedCallback(name: string): void;
27
+ private build;
28
+ private sync;
29
+ private renderAvatar;
30
+ private renderActions;
31
+ private handleAction;
32
+ }
33
+ declare global {
34
+ interface HTMLElementTagNameMap {
35
+ 'db-chat-message': DbChatMessage;
36
+ }
37
+ }
38
+
39
+ export { DbChatMessage };
@@ -0,0 +1 @@
1
+ import{createDbIcon as t,isDbIconName as e}from"./db-icons.js";import"./db-avatar.js";const s=["user","assistant","system"],a={copy:"copy",regenerate:"refresh",like:"thumb-up",dislike:"thumb-down",edit:"edit"},i={copy:"복사",regenerate:"다시 생성",like:"좋아요",dislike:"싫어요",edit:"편집"};class DbChatMessage extends HTMLElement{constructor(){super(...arguments),this.built=!1}static get observedAttributes(){return["role","name","avatar-src","avatar-initials","timestamp","status","actions","variant"]}get role(){return s.includes(this.getAttribute("role"))?this.getAttribute("role"):"assistant"}set role(t){this.setAttribute("role",t)}connectedCallback(){this.built||this.build(),this.sync()}attributeChangedCallback(t){this.built&&("actions"===t&&this.renderActions(),this.sync())}build(){for(this.built=!0,this.contentEl=document.createElement("div"),this.contentEl.className="designbase-wc-chat-message__content";this.firstChild;)this.contentEl.append(this.firstChild);this.avatarWrap=document.createElement("div"),this.avatarWrap.className="designbase-wc-chat-message__avatar";const t=document.createElement("div");t.className="designbase-wc-chat-message__bubble",this.headerEl=document.createElement("div"),this.headerEl.className="designbase-wc-chat-message__header",this.nameEl=document.createElement("span"),this.nameEl.className="designbase-wc-chat-message__name",this.timeEl=document.createElement("span"),this.timeEl.className="designbase-wc-chat-message__time",this.headerEl.append(this.nameEl,this.timeEl),this.actionsEl=document.createElement("div"),this.actionsEl.className="designbase-wc-chat-message__actions",t.append(this.headerEl,this.contentEl,this.actionsEl),this.append(this.avatarWrap,t),this.renderAvatar(),this.renderActions()}sync(){this.className=["designbase-wc-chat-message",`designbase-wc-chat-message--${this.role}`,`designbase-wc-chat-message--${this.getAttribute("variant")||"bubble"}`,this.getAttribute("status")&&`designbase-wc-chat-message--${this.getAttribute("status")}`].filter(Boolean).join(" ");const t=this.getAttribute("name")||"";this.nameEl.textContent=t,this.nameEl.hidden=!t;const e=this.getAttribute("timestamp")||"";this.timeEl.textContent=e,this.timeEl.hidden=!e,this.headerEl.hidden=!t&&!e,this.renderAvatar()}renderAvatar(){const t=this.getAttribute("avatar-src"),e=this.getAttribute("avatar-initials"),s="assistant"===this.role||Boolean(t||e);if(this.avatarWrap.hidden=!s,!s)return void this.avatarWrap.replaceChildren();let a=this.avatarWrap.querySelector("db-avatar");a||(a=document.createElement("db-avatar"),this.avatarWrap.append(a)),a.setAttribute("size","s"),t?a.setAttribute("src",t):a.removeAttribute("src"),e?a.setAttribute("initials",e):a.removeAttribute("initials"),"assistant"!==this.role||t||e||a.setAttribute("variant","primary")}renderActions(){this.actionsEl.replaceChildren();const s=(this.getAttribute("actions")||"").split(",").map(t=>t.trim()).filter(Boolean);for(const n of s){const s=document.createElement("button");s.type="button",s.className="designbase-wc-chat-message__action",s.setAttribute("aria-label",i[n]||n);const r=a[n];s.append(t(r&&e(r)?r:"sparkle",16)),s.addEventListener("click",()=>this.handleAction(n,s)),this.actionsEl.append(s)}this.actionsEl.hidden=0===s.length}handleAction(t,e){if("copy"===t){const t=this.contentEl.textContent||"";navigator.clipboard?.writeText(t).catch(()=>{})}"like"!==t&&"dislike"!==t||e.classList.toggle("designbase-wc-chat-message__action--active"),this.dispatchEvent(new CustomEvent("db-action",{detail:{action:t,text:this.contentEl.textContent||""},bubbles:!0,composed:!0}))}}customElements.get("db-chat-message")||customElements.define("db-chat-message",DbChatMessage);export{DbChatMessage};