@runtypelabs/persona 3.11.0 → 3.13.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.
@@ -130,7 +130,8 @@ var DEFAULT_WIDGET_CONFIG = {
130
130
  reasoningDisplay: {
131
131
  activePreview: false,
132
132
  previewMaxLines: 3,
133
- expandable: true
133
+ expandable: true,
134
+ loadingAnimation: "none"
134
135
  }
135
136
  },
136
137
  suggestionChips: [
@@ -3251,6 +3252,14 @@ var computeToolElapsed = (tool) => {
3251
3252
  );
3252
3253
  return formatElapsedMs(durationMs);
3253
3254
  };
3255
+ var computeReasoningElapsed = (reasoning) => {
3256
+ var _a, _b, _c;
3257
+ const durationMs = reasoning.durationMs !== void 0 ? reasoning.durationMs : Math.max(
3258
+ 0,
3259
+ ((_a = reasoning.completedAt) != null ? _a : Date.now()) - ((_c = (_b = reasoning.startedAt) != null ? _b : reasoning.completedAt) != null ? _c : Date.now())
3260
+ );
3261
+ return formatElapsedMs(durationMs);
3262
+ };
3254
3263
  var resolveToolHeaderText = (tool, template, fallback) => {
3255
3264
  var _a;
3256
3265
  if (!template) return fallback;
@@ -7911,6 +7920,7 @@ var morphMessages = (container, newContent, options = {}) => {
7911
7920
  morphStyle: "innerHTML",
7912
7921
  callbacks: {
7913
7922
  beforeNodeMorphed(oldNode, newNode) {
7923
+ var _a, _b;
7914
7924
  if (!(oldNode instanceof HTMLElement)) return;
7915
7925
  if (preserveTypingAnimation) {
7916
7926
  if (oldNode.classList.contains("persona-animate-typing")) {
@@ -7920,6 +7930,13 @@ var morphMessages = (container, newContent, options = {}) => {
7920
7930
  if (newNode instanceof HTMLElement && !newNode.hasAttribute("data-preserve-animation")) {
7921
7931
  return;
7922
7932
  }
7933
+ if (newNode instanceof HTMLElement && newNode.hasAttribute("data-preserve-animation")) {
7934
+ const oldText = (_a = oldNode.textContent) != null ? _a : "";
7935
+ const newText = (_b = newNode.textContent) != null ? _b : "";
7936
+ if (oldText !== newText) {
7937
+ return;
7938
+ }
7939
+ }
7923
7940
  return false;
7924
7941
  }
7925
7942
  }
@@ -7930,7 +7947,7 @@ var morphMessages = (container, newContent, options = {}) => {
7930
7947
 
7931
7948
  // src/utils/message-fingerprint.ts
7932
7949
  function computeMessageFingerprint(message, configVersion) {
7933
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A;
7950
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
7934
7951
  return [
7935
7952
  message.id,
7936
7953
  message.role,
@@ -7942,11 +7959,12 @@ function computeMessageFingerprint(message, configVersion) {
7942
7959
  (_i = (_h = message.llmContent) == null ? void 0 : _h.length) != null ? _i : 0,
7943
7960
  (_k = (_j = message.approval) == null ? void 0 : _j.status) != null ? _k : "",
7944
7961
  (_m = (_l = message.toolCall) == null ? void 0 : _l.status) != null ? _m : "",
7945
- (_p = (_o = (_n = message.toolCall) == null ? void 0 : _n.chunks) == null ? void 0 : _o.length) != null ? _p : 0,
7946
- (_t = (_s = (_r = (_q = message.toolCall) == null ? void 0 : _q.chunks) == null ? void 0 : _r[message.toolCall.chunks.length - 1]) == null ? void 0 : _s.slice(-32)) != null ? _t : "",
7947
- typeof ((_u = message.toolCall) == null ? void 0 : _u.args) === "string" ? message.toolCall.args.length : ((_v = message.toolCall) == null ? void 0 : _v.args) ? JSON.stringify(message.toolCall.args).length : 0,
7948
- (_y = (_x = (_w = message.reasoning) == null ? void 0 : _w.chunks) == null ? void 0 : _x.length) != null ? _y : 0,
7949
- (_A = (_z = message.contentParts) == null ? void 0 : _z.length) != null ? _A : 0,
7962
+ (_o = (_n = message.toolCall) == null ? void 0 : _n.name) != null ? _o : "",
7963
+ (_r = (_q = (_p = message.toolCall) == null ? void 0 : _p.chunks) == null ? void 0 : _q.length) != null ? _r : 0,
7964
+ (_v = (_u = (_t = (_s = message.toolCall) == null ? void 0 : _s.chunks) == null ? void 0 : _t[message.toolCall.chunks.length - 1]) == null ? void 0 : _u.slice(-32)) != null ? _v : "",
7965
+ typeof ((_w = message.toolCall) == null ? void 0 : _w.args) === "string" ? message.toolCall.args.length : ((_x = message.toolCall) == null ? void 0 : _x.args) ? JSON.stringify(message.toolCall.args).length : 0,
7966
+ (_A = (_z = (_y = message.reasoning) == null ? void 0 : _y.chunks) == null ? void 0 : _z.length) != null ? _A : 0,
7967
+ (_C = (_B = message.contentParts) == null ? void 0 : _B.length) != null ? _C : 0,
7950
7968
  configVersion
7951
7969
  ].join("\0");
7952
7970
  }
@@ -10068,7 +10086,7 @@ var updateReasoningBubbleUI = (messageId, bubble) => {
10068
10086
  }
10069
10087
  };
10070
10088
  var createReasoningBubble = (message, config) => {
10071
- var _a, _b, _c, _d, _e, _f, _g;
10089
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
10072
10090
  const reasoning = message.reasoning;
10073
10091
  const bubble = createElement(
10074
10092
  "div",
@@ -10111,13 +10129,23 @@ var createReasoningBubble = (message, config) => {
10111
10129
  const headerContent = createElement("div", "persona-flex persona-flex-col persona-text-left");
10112
10130
  const title = createElement("span", "persona-text-xs persona-text-persona-primary");
10113
10131
  const defaultSummary = "Thinking...";
10114
- const customSummary = (_e = (_d = config == null ? void 0 : config.reasoning) == null ? void 0 : _d.renderCollapsedSummary) == null ? void 0 : _e.call(_d, {
10132
+ const reasoningConfig = (_d = config == null ? void 0 : config.reasoning) != null ? _d : {};
10133
+ const startedAt = String((_e = reasoning.startedAt) != null ? _e : Date.now());
10134
+ const createElapsedSpan = () => {
10135
+ const span = createElement("span", "");
10136
+ span.setAttribute("data-tool-elapsed", startedAt);
10137
+ span.textContent = computeReasoningElapsed(reasoning);
10138
+ return span;
10139
+ };
10140
+ const customSummary = (_f = reasoningConfig.renderCollapsedSummary) == null ? void 0 : _f.call(reasoningConfig, {
10115
10141
  message,
10116
10142
  reasoning,
10117
10143
  defaultSummary,
10118
10144
  previewText,
10119
10145
  isActive,
10120
- config: config != null ? config : {}
10146
+ config: config != null ? config : {},
10147
+ elapsed: computeReasoningElapsed(reasoning),
10148
+ createElapsedElement: createElapsedSpan
10121
10149
  });
10122
10150
  if (typeof customSummary === "string" && customSummary.trim()) {
10123
10151
  title.textContent = customSummary;
@@ -10131,10 +10159,101 @@ var createReasoningBubble = (message, config) => {
10131
10159
  const status = createElement("span", "persona-text-xs persona-text-persona-primary");
10132
10160
  status.textContent = describeReasonStatus(reasoning);
10133
10161
  headerContent.appendChild(status);
10134
- if (reasoning.status === "complete") {
10135
- title.style.display = "none";
10136
- } else {
10162
+ const loadingAnimation = (_g = reasoningDisplayConfig.loadingAnimation) != null ? _g : "none";
10163
+ const activeTemplate = reasoningConfig.activeTextTemplate;
10164
+ const completeTemplate = reasoningConfig.completeTextTemplate;
10165
+ const currentTemplate = isActive ? activeTemplate : completeTemplate;
10166
+ const skipCustomElement = customSummary instanceof HTMLElement;
10167
+ const appendCharSpans = (container, text2, startIndex) => {
10168
+ let idx = startIndex;
10169
+ for (const char of text2) {
10170
+ const span = createElement("span", "persona-tool-char");
10171
+ span.style.setProperty("--char-index", String(idx));
10172
+ span.textContent = char === " " ? "\xA0" : char;
10173
+ container.appendChild(span);
10174
+ idx++;
10175
+ }
10176
+ return idx;
10177
+ };
10178
+ const renderFormattedTitle = (template, animated) => {
10179
+ title.textContent = "";
10180
+ const segments = parseFormattedTemplate(template, "");
10181
+ let charIndex = 0;
10182
+ for (const seg of segments) {
10183
+ const parent = seg.styles.length > 0 ? (() => {
10184
+ const w = createElement("span", seg.styles.map((s) => `persona-tool-text-${s}`).join(" "));
10185
+ title.appendChild(w);
10186
+ return w;
10187
+ })() : title;
10188
+ if (seg.isDuration && isActive) {
10189
+ parent.appendChild(createElapsedSpan());
10190
+ } else {
10191
+ const text2 = seg.isDuration ? computeReasoningElapsed(reasoning) : seg.text;
10192
+ if (animated) {
10193
+ charIndex = appendCharSpans(parent, text2, charIndex);
10194
+ } else {
10195
+ parent.appendChild(document.createTextNode(text2));
10196
+ }
10197
+ }
10198
+ }
10199
+ };
10200
+ if (!skipCustomElement && currentTemplate) {
10201
+ status.style.display = "none";
10137
10202
  title.style.display = "";
10203
+ if (isActive && loadingAnimation !== "none") {
10204
+ const animDuration = (_h = reasoningConfig.loadingAnimationDuration) != null ? _h : 2e3;
10205
+ title.setAttribute("data-preserve-animation", "true");
10206
+ if (loadingAnimation === "pulse") {
10207
+ title.classList.add("persona-tool-loading-pulse");
10208
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10209
+ renderFormattedTitle(currentTemplate, false);
10210
+ } else {
10211
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
10212
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10213
+ if (loadingAnimation === "shimmer-color") {
10214
+ if (reasoningConfig.loadingAnimationColor) {
10215
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
10216
+ }
10217
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
10218
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
10219
+ }
10220
+ }
10221
+ renderFormattedTitle(currentTemplate, true);
10222
+ }
10223
+ } else {
10224
+ renderFormattedTitle(currentTemplate, false);
10225
+ }
10226
+ } else if (!skipCustomElement && isActive && loadingAnimation !== "none") {
10227
+ title.style.display = "";
10228
+ const animDuration = (_i = reasoningConfig.loadingAnimationDuration) != null ? _i : 2e3;
10229
+ title.setAttribute("data-preserve-animation", "true");
10230
+ if (loadingAnimation === "pulse") {
10231
+ title.classList.add("persona-tool-loading-pulse");
10232
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10233
+ } else {
10234
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
10235
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10236
+ if (loadingAnimation === "shimmer-color") {
10237
+ if (reasoningConfig.loadingAnimationColor) {
10238
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
10239
+ }
10240
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
10241
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
10242
+ }
10243
+ }
10244
+ const text2 = title.textContent || defaultSummary;
10245
+ title.textContent = "";
10246
+ appendCharSpans(title, text2, 0);
10247
+ }
10248
+ if (reasoning.status === "complete") {
10249
+ title.style.display = "none";
10250
+ }
10251
+ } else if (!skipCustomElement) {
10252
+ if (reasoning.status === "complete") {
10253
+ title.style.display = "none";
10254
+ } else {
10255
+ title.style.display = "";
10256
+ }
10138
10257
  }
10139
10258
  let toggleIcon = null;
10140
10259
  if (expandable) {
@@ -10160,7 +10279,7 @@ var createReasoningBubble = (message, config) => {
10160
10279
  collapsedPreview.style.display = "none";
10161
10280
  collapsedPreview.style.whiteSpace = "pre-wrap";
10162
10281
  if (!expanded && isActive && reasoningDisplayConfig.activePreview && previewText) {
10163
- const renderedPreview = (_g = (_f = config == null ? void 0 : config.reasoning) == null ? void 0 : _f.renderCollapsedPreview) == null ? void 0 : _g.call(_f, {
10282
+ const renderedPreview = (_k = (_j = config == null ? void 0 : config.reasoning) == null ? void 0 : _j.renderCollapsedPreview) == null ? void 0 : _k.call(_j, {
10164
10283
  message,
10165
10284
  reasoning,
10166
10285
  defaultPreview: previewText,
@@ -1 +1 @@
1
- "use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var a in e)t(o,a,{get:e[a],enumerable:!0})},u=(o,e,a,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of c(e))!d.call(o,r)&&r!==a&&t(o,r,{get:()=>e[r],enumerable:!(s=l(e,r))||s.enumerable});return o};var g=o=>u(t({},"__esModule",{value:!0}),o);var h={};m(h,{THEME_EXAMPLES:()=>p,THEME_TOKEN_DOCS:()=>i,getThemeReference:()=>b});module.exports=g(h);var n={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var i={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides \u2014 semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals \u2014 backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color \u2014 buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500 \u2014 Primary brand color.",secondary:"palette.colors.gray.500 \u2014 Secondary color.",accent:"palette.colors.primary.600 \u2014 Accent/interactive color.",surface:"palette.colors.gray.50 \u2014 Panel/card backgrounds.",background:"palette.colors.gray.50 \u2014 Page background.",container:"palette.colors.gray.100 \u2014 Container backgrounds.",text:"palette.colors.gray.900 \u2014 Primary text.",textMuted:"palette.colors.gray.500 \u2014 Muted/secondary text.",textInverse:"palette.colors.gray.50 \u2014 Text on dark backgrounds.",border:"palette.colors.gray.200 \u2014 Default border color.",divider:"palette.colors.gray.200 \u2014 Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight \u2014 reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow \u2014 tool call row box-shadow.",reasoningBubble:"shadow \u2014 reasoning/thinking row box-shadow.",composer:"shadow \u2014 message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors \u2014 provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks.",properties:"renderCollapsedSummary, renderCollapsedPreview."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[] \u2014 Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean \u2014 show/hide the header section entirely.",showFooter:"boolean \u2014 show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right" \u2014 text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable), artifacts (sidebar config)."}}},p={darkIndigo:{description:"Dark mode with indigo accent \u2014 override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font \u2014 full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function b(){return{tokenDocs:i,defaultColorPalette:n.colors,defaultRadius:n.radius,examples:p,sdkPresets:["shop","minimal","fullscreen"]}}0&&(module.exports={THEME_EXAMPLES,THEME_TOKEN_DOCS,getThemeReference});
1
+ "use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var a in e)t(o,a,{get:e[a],enumerable:!0})},u=(o,e,a,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of c(e))!d.call(o,r)&&r!==a&&t(o,r,{get:()=>e[r],enumerable:!(s=l(e,r))||s.enumerable});return o};var g=o=>u(t({},"__esModule",{value:!0}),o);var h={};m(h,{THEME_EXAMPLES:()=>p,THEME_TOKEN_DOCS:()=>i,getThemeReference:()=>b});module.exports=g(h);var n={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var i={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides \u2014 semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals \u2014 backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color \u2014 buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500 \u2014 Primary brand color.",secondary:"palette.colors.gray.500 \u2014 Secondary color.",accent:"palette.colors.primary.600 \u2014 Accent/interactive color.",surface:"palette.colors.gray.50 \u2014 Panel/card backgrounds.",background:"palette.colors.gray.50 \u2014 Page background.",container:"palette.colors.gray.100 \u2014 Container backgrounds.",text:"palette.colors.gray.900 \u2014 Primary text.",textMuted:"palette.colors.gray.500 \u2014 Muted/secondary text.",textInverse:"palette.colors.gray.50 \u2014 Text on dark backgrounds.",border:"palette.colors.gray.200 \u2014 Default border color.",divider:"palette.colors.gray.200 \u2014 Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight \u2014 reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow \u2014 tool call row box-shadow.",reasoningBubble:"shadow \u2014 reasoning/thinking row box-shadow.",composer:"shadow \u2014 message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors \u2014 provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[] \u2014 Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean \u2014 show/hide the header section entirely.",showFooter:"boolean \u2014 show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right" \u2014 text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},p={darkIndigo:{description:"Dark mode with indigo accent \u2014 override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font \u2014 full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function b(){return{tokenDocs:i,defaultColorPalette:n.colors,defaultRadius:n.radius,examples:p,sdkPresets:["shop","minimal","fullscreen"]}}0&&(module.exports={THEME_EXAMPLES,THEME_TOKEN_DOCS,getThemeReference});
@@ -1 +1 @@
1
- var e={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var o={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides \u2014 semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals \u2014 backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color \u2014 buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500 \u2014 Primary brand color.",secondary:"palette.colors.gray.500 \u2014 Secondary color.",accent:"palette.colors.primary.600 \u2014 Accent/interactive color.",surface:"palette.colors.gray.50 \u2014 Panel/card backgrounds.",background:"palette.colors.gray.50 \u2014 Page background.",container:"palette.colors.gray.100 \u2014 Container backgrounds.",text:"palette.colors.gray.900 \u2014 Primary text.",textMuted:"palette.colors.gray.500 \u2014 Muted/secondary text.",textInverse:"palette.colors.gray.50 \u2014 Text on dark backgrounds.",border:"palette.colors.gray.200 \u2014 Default border color.",divider:"palette.colors.gray.200 \u2014 Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight \u2014 reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow \u2014 tool call row box-shadow.",reasoningBubble:"shadow \u2014 reasoning/thinking row box-shadow.",composer:"shadow \u2014 message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors \u2014 provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks.",properties:"renderCollapsedSummary, renderCollapsedPreview."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[] \u2014 Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean \u2014 show/hide the header section entirely.",showFooter:"boolean \u2014 show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right" \u2014 text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable), artifacts (sidebar config)."}}},r={darkIndigo:{description:"Dark mode with indigo accent \u2014 override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font \u2014 full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function m(){return{tokenDocs:o,defaultColorPalette:e.colors,defaultRadius:e.radius,examples:r,sdkPresets:["shop","minimal","fullscreen"]}}export{r as THEME_EXAMPLES,o as THEME_TOKEN_DOCS,m as getThemeReference};
1
+ var e={colors:{primary:{50:"#ffffff",100:"#f5f5f5",200:"#d4d4d4",300:"#a3a3a3",400:"#737373",500:"#171717",600:"#0f0f0f",700:"#0a0a0a",800:"#050505",900:"#030303",950:"#000000"},secondary:{50:"#f5f3ff",100:"#ede9fe",200:"#ddd6fe",300:"#c4b5fd",400:"#a78bfa",500:"#8b5cf6",600:"#7c3aed",700:"#6d28d9",800:"#5b21b6",900:"#4c1d95",950:"#2e1065"},accent:{50:"#ecfeff",100:"#cffafe",200:"#a5f3fc",300:"#67e8f9",400:"#22d3ee",500:"#06b6d4",600:"#0891b2",700:"#0e7490",800:"#155e75",900:"#164e63",950:"#083344"},gray:{50:"#f9fafb",100:"#f3f4f6",200:"#e5e7eb",300:"#d1d5db",400:"#9ca3af",500:"#6b7280",600:"#4b5563",700:"#374151",800:"#1f2937",900:"#111827",950:"#030712"},success:{50:"#f0fdf4",100:"#dcfce7",200:"#bbf7d0",300:"#86efac",400:"#4ade80",500:"#22c55e",600:"#16a34a",700:"#15803d",800:"#166534",900:"#14532d"},warning:{50:"#fefce8",100:"#fef9c3",200:"#fef08a",300:"#fde047",400:"#facc15",500:"#eab308",600:"#ca8a04",700:"#a16207",800:"#854d0e",900:"#713f12"},error:{50:"#fef2f2",100:"#fee2e2",200:"#fecaca",300:"#fca5a5",400:"#f87171",500:"#ef4444",600:"#dc2626",700:"#b91c1c",800:"#991b1b",900:"#7f1d1d"},info:{50:"#eff6ff",100:"#dbeafe",200:"#bfdbfe",300:"#93c5fd",400:"#60a5fa",500:"#3b82f6",600:"#2563eb",700:"#1d4ed8",800:"#1e40af",900:"#1e3a8a",950:"#172554"}},spacing:{0:"0px",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",5:"1.25rem",6:"1.5rem",8:"2rem",10:"2.5rem",12:"3rem",16:"4rem",20:"5rem",24:"6rem",32:"8rem",40:"10rem",48:"12rem",56:"14rem",64:"16rem"},typography:{fontFamily:{sans:'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',serif:'Georgia, Cambria, "Times New Roman", Times, serif',mono:"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"},fontSize:{xs:"0.75rem",sm:"0.875rem",base:"1rem",lg:"1.125rem",xl:"1.25rem","2xl":"1.5rem","3xl":"1.875rem","4xl":"2.25rem"},fontWeight:{normal:"400",medium:"500",semibold:"600",bold:"700"},lineHeight:{tight:"1.25",normal:"1.5",relaxed:"1.625"}},shadows:{none:"none",sm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",md:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",lg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",xl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)","2xl":"0 25px 50px -12px rgb(0 0 0 / 0.25)"},borders:{none:"none",sm:"1px solid",md:"2px solid",lg:"4px solid"},radius:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}};var o={overview:"Persona uses a three-layer design token system: palette \u2192 semantic \u2192 components. Most themes only need palette.colors overrides \u2014 semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).",layers:{palette:{description:"Primitive design tokens. Override specific shades to change the entire widget feel.",colors:{description:"7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.",scales:{gray:"Neutrals \u2014 backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).",primary:"Brand color \u2014 buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).",accent:"Secondary highlight. Key shades: 500 (default), 600 (hover).",secondary:"Tertiary color scale.",success:"Positive feedback (default: green).",warning:"Caution feedback (default: yellow).",error:"Error/danger feedback (default: red)."}},radius:{description:"Border radius scale. Add custom keys like launcher, button.",defaults:{none:"0px",sm:"0.125rem",md:"0.375rem",lg:"0.5rem",xl:"0.75rem","2xl":"1rem",full:"9999px"}},typography:{fontFamily:"Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.",fontSize:"Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).",fontWeight:"normal (400), medium (500), semibold (600), bold (700).",lineHeight:"tight (1.25), normal (1.5), relaxed (1.625)."},shadows:"Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.",borders:"Scale: none, sm (1px solid), md (2px solid), lg (4px solid).",spacing:"Scale: 0 (0px), 1 (0.25rem), 2 (0.5rem), 3 (0.75rem), 4 (1rem), 5 (1.25rem), 6 (1.5rem), 8 (2rem), 10 (2.5rem), 12 (3rem), 16-64."},semantic:{description:'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',colors:{primary:"palette.colors.primary.500 \u2014 Primary brand color.",secondary:"palette.colors.gray.500 \u2014 Secondary color.",accent:"palette.colors.primary.600 \u2014 Accent/interactive color.",surface:"palette.colors.gray.50 \u2014 Panel/card backgrounds.",background:"palette.colors.gray.50 \u2014 Page background.",container:"palette.colors.gray.100 \u2014 Container backgrounds.",text:"palette.colors.gray.900 \u2014 Primary text.",textMuted:"palette.colors.gray.500 \u2014 Muted/secondary text.",textInverse:"palette.colors.gray.50 \u2014 Text on dark backgrounds.",border:"palette.colors.gray.200 \u2014 Default border color.",divider:"palette.colors.gray.200 \u2014 Divider lines.",interactive:{default:"palette.colors.primary.500",hover:"palette.colors.primary.600",focus:"palette.colors.primary.700",active:"palette.colors.primary.800",disabled:"palette.colors.gray.300"},feedback:{success:"palette.colors.success.500",warning:"palette.colors.warning.500",error:"palette.colors.error.500",info:"palette.colors.primary.500"}},spacing:"xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).",typography:"fontFamily, fontSize, fontWeight, lineHeight \u2014 reference palette typography tokens."},components:{description:"UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.",button:{description:"Three variants: primary, secondary, ghost.",properties:"background, foreground, borderRadius, padding."},input:{description:"Message input field.",properties:"background, placeholder, borderRadius, padding, focus.border, focus.ring."},launcher:{description:"Floating launcher button.",properties:"size (60px), iconSize (28px), borderRadius, shadow."},panel:{description:"Chat panel container.",properties:"width, maxWidth (440px), height (600px), maxHeight, borderRadius, shadow."},header:{description:"Chat panel header.",properties:"background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom."},message:{description:"Chat message bubbles.",user:"background, text, borderRadius, shadow.",assistant:"background, text, borderRadius, border (optional), shadow (optional)."},markdown:{description:"Markdown rendering in messages and artifact pane.",properties:"inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight)."},voice:"recording (indicator, background, border), processing (icon, background), speaking (icon).",approval:"requested (background, border, text), approve (background, foreground), deny (background, foreground).",attachment:"image (background, border).",scrollToBottom:"Floating scroll-to-bottom affordance shared by transcript and event stream: background, foreground, border, size, borderRadius, shadow, padding, gap, fontSize, iconSize.",toolBubble:"shadow \u2014 tool call row box-shadow.",reasoningBubble:"shadow \u2014 reasoning/thinking row box-shadow.",composer:"shadow \u2014 message input form box-shadow.",artifact:"toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground)."}},colorScheme:'"dark" merges darkTheme overrides on top of theme. "auto" detects system preference or <html class="dark">. "light" is default. colorScheme does NOT auto-invert colors \u2014 provide dark palette and semantic overrides yourself.',plugins:{description:"Plugins transform theme tokens before resolution. Use with createTheme().",available:{brandPlugin:'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',accessibilityPlugin:"Enhanced focus indicators and disabled states.",highContrastPlugin:"Increased contrast for visual accessibility.",reducedMotionPlugin:"Disables all animations (sets transitions to 0ms).",animationsPlugin:"Adds transition and easing tokens."},usage:'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })'},widgetConfig:{description:'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',launcher:{description:"Floating launcher button and panel positioning.",properties:{enabled:"Show/hide the launcher button.",title:"Header title text.",subtitle:"Header subtitle text.",position:'"bottom-right" | "bottom-left" | "top-right" | "top-left".',width:"Chat panel width (CSS value).",fullHeight:"Fill full height of container.",mountMode:'"floating" | "docked".',agentIconText:"Emoji/text for agent icon.",border:"Border style for launcher button.",shadow:"Box shadow for launcher button.",collapsedMaxWidth:"Max-width for launcher pill when panel closed."}},sendButton:{description:"Send button appearance.",properties:"backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size."},closeButton:{description:"Close button (on launcher config).",properties:"closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius."},clearChat:{description:"Clear chat button (on launcher.clearChat config).",properties:"enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size."},scrollToBottom:{description:"Shared transcript + event-stream jump-to-latest affordance.",properties:'features.scrollToBottom.enabled, features.scrollToBottom.iconName, features.scrollToBottom.label (empty string renders icon-only). Defaults: enabled=true, iconName="arrow-down", label="".'},toolCall:{description:"Tool call display styling, text templates, loading animations, and rendering hooks. Text templates support placeholders ({toolName}, {duration}) and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"shadow, backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, headerPaddingX, headerPaddingY, contentBackgroundColor, contentTextColor, contentPaddingX, contentPaddingY, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration, renderCollapsedSummary, renderCollapsedPreview, renderGroupedSummary."},reasoning:{description:"Reasoning/thinking row rendering hooks, text templates, and loading animations. Text templates support {duration} placeholder and inline formatting (~dim~, *italic*, **bold**). renderCollapsedSummary receives elapsed (static string) and createElapsedElement() (live-updating span) in its context.",properties:"renderCollapsedSummary, renderCollapsedPreview, activeTextTemplate, completeTextTemplate, loadingAnimationColor, loadingAnimationSecondaryColor, loadingAnimationDuration."},approval:{description:"Tool approval bubble styling and behavior. Set to false to disable.",properties:"backgroundColor, borderColor, titleColor, descriptionColor, approveButtonColor, approveButtonTextColor, denyButtonColor, denyButtonTextColor, parameterBackgroundColor, parameterTextColor, title, approveLabel, denyLabel."},copy:{description:"Widget text content.",properties:"showWelcomeCard (boolean), welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel."},voiceRecognition:{description:"Voice input configuration.",properties:"enabled, pauseDuration, iconColor, backgroundColor."},textToSpeech:{description:"Text-to-speech for assistant messages.",properties:'enabled, provider ("browser" | "runtype"), browserFallback, voice, rate, pitch.'},suggestionChips:"string[] \u2014 Suggested prompts shown to the user.",messageActions:{description:"Message action buttons (copy, upvote, downvote).",properties:'enabled, showCopy, showUpvote, showDownvote, visibility ("hover" | "always"), align ("left" | "center" | "right"), layout ("pill-inside" | "row-inside").'},attachments:{description:"File attachment configuration.",properties:"enabled, allowedTypes (string[]), maxFileSize (bytes), maxFiles, buttonIconName, buttonTooltipText."},markdown:{description:"Markdown rendering configuration.",properties:"options (gfm, breaks, headerIds, headerPrefix, pedantic, mangle, silent), disableDefaultStyles."},layout:{description:"Layout configuration.",showHeader:"boolean \u2014 show/hide the header section entirely.",showFooter:"boolean \u2014 show/hide the footer/composer section entirely.",contentMaxWidth:'CSS width value for centering content (e.g. "720px", "90ch").',header:'"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton, showClearChat.',messages:'"bubble" | "flat" | "minimal". Options: groupConsecutive, avatar (show, position, userAvatar, assistantAvatar), timestamp (show, position).'},statusIndicator:{description:"Status text shown below the composer.",properties:{visible:"Show/hide the status indicator.",align:'"left" | "center" | "right" \u2014 text alignment (default: "right").',idleText:'Text shown when idle (default: "Online").',idleLink:"URL to open when idle text is clicked (wraps text in a link).",connectingText:'Text shown while connecting (default: "Connecting\u2026").',connectedText:'Text shown while streaming (default: "Streaming\u2026").',errorText:'Text shown on error (default: "Offline").'}},features:{description:"Feature flags.",properties:"showReasoning (AI thinking steps), showToolCalls (tool invocations), toolCallDisplay (collapsedMode, activePreview, activeMinHeight, previewMaxLines, grouped, expandable, loadingAnimation), reasoningDisplay (activePreview, activeMinHeight, previewMaxLines, expandable, loadingAnimation), artifacts (sidebar config)."}}},r={darkIndigo:{description:"Dark mode with indigo accent \u2014 override grays for dark backgrounds and semantic tokens for inverted text/surface",theme:{palette:{colors:{primary:{500:"#6366f1",600:"#4f46e5"},gray:{50:"#f1f5f9",100:"#1e293b",200:"#334155",500:"#94a3b8",900:"#0f172a",950:"#020617"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.900",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",textInverse:"palette.colors.gray.900",border:"palette.colors.gray.200"}}}},warmVintage:{description:"Warm sepia tones with serif font and subtle radius",theme:{palette:{colors:{primary:{500:"#b45309",600:"#92400e"},gray:{50:"#fef3c7",100:"#fef9c3",200:"#d6d3d1",500:"#78716c",900:"#44403c"}},radius:{sm:"0.125rem",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:'Georgia, Cambria, "Times New Roman", Times, serif'}}}}},neonCyberpunk:{description:"Neon on dark with monospace font \u2014 full semantic override for dark background",theme:{palette:{colors:{primary:{500:"#f0abfc",600:"#e879f9"},accent:{500:"#22d3ee",600:"#06b6d4"},gray:{50:"#f0abfc",100:"#1e0a3c",200:"#3b0764",500:"#c084fc",900:"#0c0a1a",950:"#050412"}},radius:{sm:"0",md:"0.25rem",lg:"0.375rem"},typography:{fontFamily:{sans:"ui-monospace, SFMono-Regular, Menlo, monospace"}}},semantic:{colors:{surface:"palette.colors.gray.900",background:"palette.colors.gray.950",container:"palette.colors.gray.100",text:"palette.colors.gray.50",textMuted:"palette.colors.gray.500",border:"palette.colors.gray.200"}}}},cleanRounded:{description:"Clean light theme with large radius and panel styling",theme:{palette:{radius:{sm:"6px",md:"8px",lg:"12px",launcher:"50px",button:"8px"}},components:{panel:{borderRadius:"16px",shadow:"palette.shadows.2xl"}}}}};function m(){return{tokenDocs:o,defaultColorPalette:e.colors,defaultRadius:e.radius,examples:r,sdkPresets:["shop","minimal","fullscreen"]}}export{r as THEME_EXAMPLES,o as THEME_TOKEN_DOCS,m as getThemeReference};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/persona",
3
- "version": "3.11.0",
3
+ "version": "3.13.0",
4
4
  "description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -1,6 +1,6 @@
1
1
  import { createElement } from "../utils/dom";
2
2
  import { AgentWidgetConfig, AgentWidgetMessage } from "../types";
3
- import { describeReasonStatus } from "../utils/formatting";
3
+ import { describeReasonStatus, computeReasoningElapsed, parseFormattedTemplate } from "../utils/formatting";
4
4
  import { renderLucideIcon } from "../utils/icons";
5
5
 
6
6
  // Expansion state per widget instance
@@ -112,13 +112,27 @@ export const createReasoningBubble = (message: AgentWidgetMessage, config?: Agen
112
112
  const headerContent = createElement("div", "persona-flex persona-flex-col persona-text-left");
113
113
  const title = createElement("span", "persona-text-xs persona-text-persona-primary");
114
114
  const defaultSummary = "Thinking...";
115
- const customSummary = config?.reasoning?.renderCollapsedSummary?.({
115
+ const reasoningConfig = config?.reasoning ?? {};
116
+
117
+ // Elapsed helpers — defined early so they're available to renderCollapsedSummary
118
+ const startedAt = String(reasoning.startedAt ?? Date.now());
119
+
120
+ const createElapsedSpan = (): HTMLElement => {
121
+ const span = createElement("span", "");
122
+ span.setAttribute("data-tool-elapsed", startedAt);
123
+ span.textContent = computeReasoningElapsed(reasoning);
124
+ return span;
125
+ };
126
+
127
+ const customSummary = reasoningConfig.renderCollapsedSummary?.({
116
128
  message,
117
129
  reasoning,
118
130
  defaultSummary,
119
131
  previewText,
120
132
  isActive,
121
133
  config: config ?? {},
134
+ elapsed: computeReasoningElapsed(reasoning),
135
+ createElapsedElement: createElapsedSpan,
122
136
  });
123
137
  if (typeof customSummary === "string" && customSummary.trim()) {
124
138
  title.textContent = customSummary;
@@ -130,14 +144,134 @@ export const createReasoningBubble = (message: AgentWidgetMessage, config?: Agen
130
144
  headerContent.appendChild(title);
131
145
  }
132
146
 
147
+ // Status span — used in the legacy (no-template) path
133
148
  const status = createElement("span", "persona-text-xs persona-text-persona-primary");
134
149
  status.textContent = describeReasonStatus(reasoning);
135
150
  headerContent.appendChild(status);
136
151
 
137
- if (reasoning.status === "complete") {
138
- title.style.display = "none";
139
- } else {
152
+ // Template and animation support
153
+ const loadingAnimation = reasoningDisplayConfig.loadingAnimation ?? "none";
154
+ const activeTemplate = reasoningConfig.activeTextTemplate;
155
+ const completeTemplate = reasoningConfig.completeTextTemplate;
156
+ const currentTemplate = isActive ? activeTemplate : completeTemplate;
157
+ const skipCustomElement = customSummary instanceof HTMLElement;
158
+
159
+ // Helper: append text as individual animated character spans
160
+ const appendCharSpans = (container: HTMLElement, text: string, startIndex: number): number => {
161
+ let idx = startIndex;
162
+ for (const char of text) {
163
+ const span = createElement("span", "persona-tool-char");
164
+ span.style.setProperty("--char-index", String(idx));
165
+ span.textContent = char === " " ? "\u00A0" : char;
166
+ container.appendChild(span);
167
+ idx++;
168
+ }
169
+ return idx;
170
+ };
171
+
172
+ /**
173
+ * Renders a template into the title element, handling:
174
+ * - Inline formatting markers: **bold**, *italic*, ~dim~
175
+ * - {duration} as a live-updating elapsed span (active) or static text (complete)
176
+ * - Character-by-character animation wrapping when `animated` is true
177
+ */
178
+ const renderFormattedTitle = (template: string, animated: boolean) => {
179
+ title.textContent = "";
180
+ const segments = parseFormattedTemplate(template, "");
181
+ let charIndex = 0;
182
+
183
+ for (const seg of segments) {
184
+ const parent = seg.styles.length > 0
185
+ ? (() => {
186
+ const w = createElement("span", seg.styles.map(s => `persona-tool-text-${s}`).join(" "));
187
+ title.appendChild(w);
188
+ return w;
189
+ })()
190
+ : title;
191
+
192
+ if (seg.isDuration && isActive) {
193
+ parent.appendChild(createElapsedSpan());
194
+ } else {
195
+ const text = seg.isDuration ? computeReasoningElapsed(reasoning) : seg.text;
196
+ if (animated) {
197
+ charIndex = appendCharSpans(parent, text, charIndex);
198
+ } else {
199
+ parent.appendChild(document.createTextNode(text));
200
+ }
201
+ }
202
+ }
203
+ };
204
+
205
+ // Apply template + animation, or fall back to legacy title/status approach
206
+ if (!skipCustomElement && currentTemplate) {
207
+ // Template mode: unified title replaces separate title/status spans
208
+ status.style.display = "none";
140
209
  title.style.display = "";
210
+
211
+ if (isActive && loadingAnimation !== "none") {
212
+ const animDuration = reasoningConfig.loadingAnimationDuration ?? 2000;
213
+ title.setAttribute("data-preserve-animation", "true");
214
+
215
+ if (loadingAnimation === "pulse") {
216
+ title.classList.add("persona-tool-loading-pulse");
217
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
218
+ renderFormattedTitle(currentTemplate, false);
219
+ } else {
220
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
221
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
222
+
223
+ if (loadingAnimation === "shimmer-color") {
224
+ if (reasoningConfig.loadingAnimationColor) {
225
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
226
+ }
227
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
228
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
229
+ }
230
+ }
231
+
232
+ renderFormattedTitle(currentTemplate, true);
233
+ }
234
+ } else {
235
+ renderFormattedTitle(currentTemplate, false);
236
+ }
237
+ } else if (!skipCustomElement && isActive && loadingAnimation !== "none") {
238
+ // Animation without template: animate the default "Thinking..." text
239
+ title.style.display = "";
240
+ const animDuration = reasoningConfig.loadingAnimationDuration ?? 2000;
241
+ title.setAttribute("data-preserve-animation", "true");
242
+
243
+ if (loadingAnimation === "pulse") {
244
+ title.classList.add("persona-tool-loading-pulse");
245
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
246
+ } else {
247
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
248
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
249
+
250
+ if (loadingAnimation === "shimmer-color") {
251
+ if (reasoningConfig.loadingAnimationColor) {
252
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
253
+ }
254
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
255
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
256
+ }
257
+ }
258
+
259
+ const text = title.textContent || defaultSummary;
260
+ title.textContent = "";
261
+ appendCharSpans(title, text, 0);
262
+ }
263
+
264
+ // Legacy: hide title on complete, show status
265
+ if (reasoning.status === "complete") {
266
+ title.style.display = "none";
267
+ }
268
+ } else if (!skipCustomElement) {
269
+ // Legacy path: no template, no animation
270
+ if (reasoning.status === "complete") {
271
+ title.style.display = "none";
272
+ } else {
273
+ title.style.display = "";
274
+ }
141
275
  }
142
276
 
143
277
  let toggleIcon: HTMLElement | null = null;
package/src/defaults.ts CHANGED
@@ -129,6 +129,7 @@ export const DEFAULT_WIDGET_CONFIG: Partial<AgentWidgetConfig> = {
129
129
  activePreview: false,
130
130
  previewMaxLines: 3,
131
131
  expandable: true,
132
+ loadingAnimation: "none",
132
133
  },
133
134
  },
134
135
  suggestionChips: [