@runtypelabs/persona 3.29.0 → 3.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-CxvHw0X6.d.cts → types-B_Qazlm4.d.cts} +6 -0
- package/dist/animations/{types-CxvHw0X6.d.ts → types-B_Qazlm4.d.ts} +6 -0
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/codegen.cjs +6 -6
- package/dist/codegen.js +4 -4
- package/dist/index.cjs +47 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +127 -7
- package/dist/index.d.ts +127 -7
- package/dist/index.global.js +60 -60
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +47 -47
- package/dist/index.js.map +1 -1
- package/dist/launcher.global.js +2 -2
- package/dist/launcher.global.js.map +1 -1
- package/dist/plugin-kit.cjs +1 -0
- package/dist/plugin-kit.d.cts +98 -0
- package/dist/plugin-kit.d.ts +98 -0
- package/dist/plugin-kit.js +1 -0
- package/dist/smart-dom-reader.d.cts +113 -4
- package/dist/smart-dom-reader.d.ts +113 -4
- package/dist/theme-editor.cjs +38 -38
- package/dist/theme-editor.d.cts +117 -6
- package/dist/theme-editor.d.ts +117 -6
- package/dist/theme-editor.js +38 -38
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +2 -0
- package/dist/theme-reference.d.ts +2 -0
- package/dist/theme-reference.js +1 -1
- package/package.json +8 -2
- package/src/client.test.ts +40 -0
- package/src/client.ts +18 -4
- package/src/components/approval-bubble.test.ts +268 -0
- package/src/components/approval-bubble.ts +170 -20
- package/src/components/launcher.ts +6 -3
- package/src/components/tool-bubble.test.ts +39 -0
- package/src/components/tool-bubble.ts +4 -0
- package/src/generated/runtype-openapi-contract.ts +12 -0
- package/src/index-core.ts +1 -0
- package/src/plugin-kit.test.ts +230 -0
- package/src/plugin-kit.ts +294 -0
- package/src/plugins/types.ts +49 -2
- package/src/session.test.ts +99 -0
- package/src/session.ts +204 -32
- package/src/session.webmcp.test.ts +326 -6
- package/src/theme-editor/preview-utils.test.ts +10 -0
- package/src/theme-editor/preview-utils.ts +29 -1
- package/src/theme-editor/sections.test.ts +17 -0
- package/src/theme-editor/sections.ts +31 -0
- package/src/theme-reference.ts +1 -1
- package/src/types/theme.ts +2 -0
- package/src/types.ts +59 -2
- package/src/ui.approval-plugin.test.ts +204 -0
- package/src/ui.ts +149 -16
- package/src/utils/theme.test.ts +6 -2
- package/src/utils/theme.ts +0 -8
- package/src/utils/tokens.ts +6 -1
- package/src/webmcp-bridge.test.ts +66 -0
- package/src/webmcp-bridge.ts +49 -0
package/dist/theme-reference.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var c=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 d(e))!c.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
|
+
"use strict";var t=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var c=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 d(e))!c.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, shadow), 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});
|
|
@@ -306,6 +306,8 @@ interface ApprovalTokens {
|
|
|
306
306
|
background: TokenReference<'color'>;
|
|
307
307
|
border: TokenReference<'color'>;
|
|
308
308
|
text: TokenReference<'color'>;
|
|
309
|
+
/** Box-shadow for the approval bubble (token ref or raw CSS, e.g. `none`). */
|
|
310
|
+
shadow: string;
|
|
309
311
|
};
|
|
310
312
|
approve: ComponentTokenSet;
|
|
311
313
|
deny: ComponentTokenSet;
|
|
@@ -306,6 +306,8 @@ interface ApprovalTokens {
|
|
|
306
306
|
background: TokenReference<'color'>;
|
|
307
307
|
border: TokenReference<'color'>;
|
|
308
308
|
text: TokenReference<'color'>;
|
|
309
|
+
/** Box-shadow for the approval bubble (token ref or raw CSS, e.g. `none`). */
|
|
310
|
+
shadow: string;
|
|
309
311
|
};
|
|
310
312
|
approve: ComponentTokenSet;
|
|
311
313
|
deny: ComponentTokenSet;
|
package/dist/theme-reference.js
CHANGED
|
@@ -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, 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};
|
|
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, shadow), 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.
|
|
3
|
+
"version": "3.30.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",
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
"import": "./dist/smart-dom-reader.js",
|
|
38
38
|
"require": "./dist/smart-dom-reader.cjs"
|
|
39
39
|
},
|
|
40
|
+
"./plugin-kit": {
|
|
41
|
+
"types": "./dist/plugin-kit.d.ts",
|
|
42
|
+
"import": "./dist/plugin-kit.js",
|
|
43
|
+
"require": "./dist/plugin-kit.cjs"
|
|
44
|
+
},
|
|
40
45
|
"./animations/glyph-cycle": {
|
|
41
46
|
"types": "./dist/animations/glyph-cycle.d.ts",
|
|
42
47
|
"import": "./dist/animations/glyph-cycle.js",
|
|
@@ -104,7 +109,8 @@
|
|
|
104
109
|
"access": "public"
|
|
105
110
|
},
|
|
106
111
|
"scripts": {
|
|
107
|
-
"build": "rimraf dist && pnpm run build:styles && pnpm run build:client && pnpm run build:installer && pnpm run build:launcher && pnpm run build:theme-ref && pnpm run build:codegen && pnpm run build:theme-editor && pnpm run build:testing && pnpm run build:smart-dom-reader && pnpm run build:animations",
|
|
112
|
+
"build": "rimraf dist && pnpm run build:styles && pnpm run build:client && pnpm run build:installer && pnpm run build:launcher && pnpm run build:theme-ref && pnpm run build:codegen && pnpm run build:theme-editor && pnpm run build:testing && pnpm run build:smart-dom-reader && pnpm run build:plugin-kit && pnpm run build:animations",
|
|
113
|
+
"build:plugin-kit": "tsup src/plugin-kit.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting",
|
|
108
114
|
"build:theme-editor": "tsup src/theme-editor.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting",
|
|
109
115
|
"build:testing": "tsup src/testing.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting",
|
|
110
116
|
"build:smart-dom-reader": "tsup src/smart-dom-reader.ts --format esm,cjs --minify --dts --out-dir dist --no-splitting",
|
package/src/client.test.ts
CHANGED
|
@@ -3056,6 +3056,46 @@ describe('AgentWidgetClient — step_await parsing', () => {
|
|
|
3056
3056
|
expect(toolMsg!.agentMetadata?.awaitingLocalTool).toBe(true);
|
|
3057
3057
|
});
|
|
3058
3058
|
|
|
3059
|
+
it('emits a running tool message for WebMCP local_tool_required until the browser tool resolves', async () => {
|
|
3060
|
+
global.fetch = vi.fn().mockResolvedValue({
|
|
3061
|
+
ok: true,
|
|
3062
|
+
body: buildStepAwaitStream({
|
|
3063
|
+
awaitReason: 'local_tool_required',
|
|
3064
|
+
id: 'step-1',
|
|
3065
|
+
name: 'Test Step',
|
|
3066
|
+
stepType: 'prompt',
|
|
3067
|
+
index: 0,
|
|
3068
|
+
toolCallId: 'tc_webmcp_1',
|
|
3069
|
+
toolName: 'webmcp:get_product_by_url',
|
|
3070
|
+
executionId: 'exec_abc',
|
|
3071
|
+
startedAt: 1234,
|
|
3072
|
+
parameters: { path: '/jade/' },
|
|
3073
|
+
}),
|
|
3074
|
+
});
|
|
3075
|
+
|
|
3076
|
+
const client = new AgentWidgetClient({ apiUrl: 'http://localhost:8000' });
|
|
3077
|
+
const events: AgentWidgetEvent[] = [];
|
|
3078
|
+
await client.dispatch(
|
|
3079
|
+
{ messages: [{ id: 'u1', role: 'user', content: 'hi', createdAt: new Date().toISOString() }] },
|
|
3080
|
+
(e) => events.push(e)
|
|
3081
|
+
);
|
|
3082
|
+
|
|
3083
|
+
const toolMsg = events
|
|
3084
|
+
.filter((e) => e.type === 'message')
|
|
3085
|
+
.map((e) => (e as { message: AgentWidgetMessage }).message)
|
|
3086
|
+
.find((m) => m.variant === 'tool' && m.toolCall?.name === 'webmcp:get_product_by_url');
|
|
3087
|
+
|
|
3088
|
+
expect(toolMsg).toBeDefined();
|
|
3089
|
+
expect(toolMsg!.toolCall!.id).toBe('tc_webmcp_1');
|
|
3090
|
+
expect(toolMsg!.toolCall!.status).toBe('running');
|
|
3091
|
+
expect(toolMsg!.toolCall!.startedAt).toBe(1234);
|
|
3092
|
+
expect(toolMsg!.toolCall!.completedAt).toBeUndefined();
|
|
3093
|
+
expect(toolMsg!.toolCall!.durationMs).toBeUndefined();
|
|
3094
|
+
expect(toolMsg!.toolCall!.args).toEqual({ path: '/jade/' });
|
|
3095
|
+
expect(toolMsg!.agentMetadata?.executionId).toBe('exec_abc');
|
|
3096
|
+
expect(toolMsg!.agentMetadata?.awaitingLocalTool).toBe(true);
|
|
3097
|
+
});
|
|
3098
|
+
|
|
3059
3099
|
it('ignores step_await events whose awaitReason is not local_tool_required', async () => {
|
|
3060
3100
|
global.fetch = vi.fn().mockResolvedValue({
|
|
3061
3101
|
ok: true,
|
package/src/client.ts
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
ContentPart,
|
|
24
24
|
WebMcpConfirmHandler
|
|
25
25
|
} from "./types";
|
|
26
|
-
import { WebMcpBridge, computeClientToolsFingerprint } from "./webmcp-bridge";
|
|
26
|
+
import { WebMcpBridge, computeClientToolsFingerprint, isWebMcpToolName } from "./webmcp-bridge";
|
|
27
27
|
import {
|
|
28
28
|
extractTextFromJson,
|
|
29
29
|
createPlainTextParser,
|
|
@@ -2026,14 +2026,28 @@ export class AgentWidgetClient {
|
|
|
2026
2026
|
const toolId =
|
|
2027
2027
|
toolCallId ?? (payload.toolId as string) ?? `local-${nextSequence()}`;
|
|
2028
2028
|
const toolMessage = ensureToolMessage(toolId);
|
|
2029
|
+
const toolName = payload.toolName as string;
|
|
2030
|
+
const webMcpTool = isWebMcpToolName(toolName);
|
|
2029
2031
|
const tool = toolMessage.toolCall ?? { id: toolId, status: "pending" as const };
|
|
2030
|
-
tool.name =
|
|
2032
|
+
tool.name = toolName;
|
|
2031
2033
|
tool.args = payload.parameters;
|
|
2032
|
-
|
|
2034
|
+
// WebMCP tools are executed asynchronously by the browser AFTER this
|
|
2035
|
+
// `step_await` arrives. Keep them running until session.ts resolves
|
|
2036
|
+
// the page tool and records its actual elapsed time. Other local
|
|
2037
|
+
// tools (for example ask_user_question) keep the existing complete
|
|
2038
|
+
// state because they are waiting for a user interaction, not an
|
|
2039
|
+
// automatic page-tool execution.
|
|
2040
|
+
tool.status = webMcpTool ? "running" : "complete";
|
|
2033
2041
|
tool.chunks = tool.chunks ?? [];
|
|
2034
2042
|
tool.startedAt =
|
|
2035
2043
|
tool.startedAt ?? resolveTimestamp(payload.startedAt ?? payload.timestamp);
|
|
2036
|
-
|
|
2044
|
+
if (webMcpTool) {
|
|
2045
|
+
tool.completedAt = undefined;
|
|
2046
|
+
tool.duration = undefined;
|
|
2047
|
+
tool.durationMs = undefined;
|
|
2048
|
+
} else {
|
|
2049
|
+
tool.completedAt = tool.completedAt ?? tool.startedAt;
|
|
2050
|
+
}
|
|
2037
2051
|
toolMessage.toolCall = tool;
|
|
2038
2052
|
toolMessage.streaming = false;
|
|
2039
2053
|
toolMessage.agentMetadata = {
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import {
|
|
5
|
+
approvalDetailsExpansionState,
|
|
6
|
+
createApprovalBubble,
|
|
7
|
+
humanizeToolName,
|
|
8
|
+
updateApprovalDetailsUI,
|
|
9
|
+
} from "./approval-bubble";
|
|
10
|
+
import { recordWebMcpToolDisplayTitles } from "../webmcp-bridge";
|
|
11
|
+
import type {
|
|
12
|
+
AgentWidgetApproval,
|
|
13
|
+
AgentWidgetConfig,
|
|
14
|
+
AgentWidgetMessage,
|
|
15
|
+
} from "../types";
|
|
16
|
+
|
|
17
|
+
const makeMessage = (
|
|
18
|
+
approval: Partial<AgentWidgetApproval> = {}
|
|
19
|
+
): AgentWidgetMessage => ({
|
|
20
|
+
id: "msg-1",
|
|
21
|
+
role: "assistant",
|
|
22
|
+
content: "",
|
|
23
|
+
createdAt: new Date().toISOString(),
|
|
24
|
+
variant: "tool",
|
|
25
|
+
streaming: false,
|
|
26
|
+
approval: {
|
|
27
|
+
id: "appr-1",
|
|
28
|
+
status: "pending",
|
|
29
|
+
agentId: "agent-1",
|
|
30
|
+
executionId: "exec-1",
|
|
31
|
+
toolName: "add_to_cart",
|
|
32
|
+
description: "Approval required",
|
|
33
|
+
...approval,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("createApprovalBubble shadow", () => {
|
|
38
|
+
it("falls back to the themeable --persona-approval-shadow variable when no config.shadow is set", () => {
|
|
39
|
+
const bubble = createApprovalBubble(makeMessage());
|
|
40
|
+
expect(bubble.style.boxShadow).toContain("--persona-approval-shadow");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("applies a custom shadow from config.approval.shadow", () => {
|
|
44
|
+
const config: AgentWidgetConfig = {
|
|
45
|
+
approval: { shadow: "0 8px 24px rgba(0,0,0,0.15)" },
|
|
46
|
+
} as AgentWidgetConfig;
|
|
47
|
+
const bubble = createApprovalBubble(makeMessage(), config);
|
|
48
|
+
expect(bubble.style.boxShadow).toBe("0 8px 24px rgba(0,0,0,0.15)");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('maps an empty shadow string to "none"', () => {
|
|
52
|
+
const config: AgentWidgetConfig = {
|
|
53
|
+
approval: { shadow: " " },
|
|
54
|
+
} as AgentWidgetConfig;
|
|
55
|
+
const bubble = createApprovalBubble(makeMessage(), config);
|
|
56
|
+
expect(bubble.style.boxShadow).toBe("none");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("uses the themeable variable fallback when approval handling is disabled (approval: false)", () => {
|
|
60
|
+
const config: AgentWidgetConfig = { approval: false } as AgentWidgetConfig;
|
|
61
|
+
const bubble = createApprovalBubble(makeMessage(), config);
|
|
62
|
+
expect(bubble.style.boxShadow).toContain("--persona-approval-shadow");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const TOOL_DESCRIPTION =
|
|
67
|
+
"Add products to the shopping cart. IMPORTANT: If a product has required options you MUST include the variantId.";
|
|
68
|
+
|
|
69
|
+
const makeDetailedMessage = (
|
|
70
|
+
approval: Partial<AgentWidgetApproval> = {}
|
|
71
|
+
): AgentWidgetMessage =>
|
|
72
|
+
makeMessage({
|
|
73
|
+
toolType: "webmcp",
|
|
74
|
+
description: TOOL_DESCRIPTION,
|
|
75
|
+
parameters: { items: [{ productEntityId: 129, quantity: 1 }] },
|
|
76
|
+
...approval,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const getSummary = (bubble: HTMLElement) =>
|
|
80
|
+
bubble.querySelector("[data-approval-summary]") as HTMLElement | null;
|
|
81
|
+
const getToggle = (bubble: HTMLElement) =>
|
|
82
|
+
bubble.querySelector('button[data-bubble-type="approval"]') as HTMLElement | null;
|
|
83
|
+
const getDetails = (bubble: HTMLElement) =>
|
|
84
|
+
bubble.querySelector("[data-approval-details]") as HTMLElement | null;
|
|
85
|
+
|
|
86
|
+
beforeEach(() => {
|
|
87
|
+
approvalDetailsExpansionState.clear();
|
|
88
|
+
// Reset display titles recorded by a prior test (the map is rebuilt from
|
|
89
|
+
// each full snapshot, so recording an empty snapshot clears it).
|
|
90
|
+
recordWebMcpToolDisplayTitles([]);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("humanizeToolName", () => {
|
|
94
|
+
it("converts snake_case to a sentence", () => {
|
|
95
|
+
expect(humanizeToolName("add_to_cart")).toBe("Add to cart");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("strips the webmcp: prefix", () => {
|
|
99
|
+
expect(humanizeToolName("webmcp:add_to_cart")).toBe("Add to cart");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("splits camelCase and kebab-case", () => {
|
|
103
|
+
expect(humanizeToolName("getProductDetails")).toBe("Get product details");
|
|
104
|
+
expect(humanizeToolName("apply-promo-code")).toBe("Apply promo code");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("returns the input when nothing word-like remains", () => {
|
|
108
|
+
expect(humanizeToolName("")).toBe("");
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("createApprovalBubble summary and details", () => {
|
|
113
|
+
it("shows a friendly summary instead of the agent-facing description", () => {
|
|
114
|
+
const bubble = createApprovalBubble(makeDetailedMessage());
|
|
115
|
+
expect(getSummary(bubble)?.textContent).toBe(
|
|
116
|
+
"The assistant wants to use “Add to cart”."
|
|
117
|
+
);
|
|
118
|
+
expect(getSummary(bubble)?.textContent).not.toContain("IMPORTANT");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("collapses the description and parameters behind a toggle by default", () => {
|
|
122
|
+
const bubble = createApprovalBubble(makeDetailedMessage());
|
|
123
|
+
const toggle = getToggle(bubble);
|
|
124
|
+
const details = getDetails(bubble);
|
|
125
|
+
expect(toggle?.getAttribute("aria-expanded")).toBe("false");
|
|
126
|
+
expect(toggle?.textContent).toContain("Show details");
|
|
127
|
+
expect(details?.style.display).toBe("none");
|
|
128
|
+
expect(details?.textContent).toContain("IMPORTANT");
|
|
129
|
+
expect(details?.querySelector("pre")?.textContent).toContain("productEntityId");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("renders details expanded when detailsDisplay is 'expanded'", () => {
|
|
133
|
+
const config = { approval: { detailsDisplay: "expanded" } } as AgentWidgetConfig;
|
|
134
|
+
const bubble = createApprovalBubble(makeDetailedMessage(), config);
|
|
135
|
+
expect(getToggle(bubble)?.getAttribute("aria-expanded")).toBe("true");
|
|
136
|
+
expect(getToggle(bubble)?.textContent).toContain("Hide details");
|
|
137
|
+
expect(getDetails(bubble)?.style.display).toBe("");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("omits the details section entirely when detailsDisplay is 'hidden'", () => {
|
|
141
|
+
const config = { approval: { detailsDisplay: "hidden" } } as AgentWidgetConfig;
|
|
142
|
+
const bubble = createApprovalBubble(makeDetailedMessage(), config);
|
|
143
|
+
expect(getToggle(bubble)).toBeNull();
|
|
144
|
+
expect(getDetails(bubble)).toBeNull();
|
|
145
|
+
expect(bubble.textContent).not.toContain("IMPORTANT");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("respects a per-message expansion override from prior toggling", () => {
|
|
149
|
+
approvalDetailsExpansionState.set("msg-1", true);
|
|
150
|
+
const bubble = createApprovalBubble(makeDetailedMessage());
|
|
151
|
+
expect(getToggle(bubble)?.getAttribute("aria-expanded")).toBe("true");
|
|
152
|
+
expect(getDetails(bubble)?.style.display).toBe("");
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("uses formatDescription for the summary when provided", () => {
|
|
156
|
+
const config = {
|
|
157
|
+
approval: {
|
|
158
|
+
formatDescription: ({ toolName }: { toolName: string }) =>
|
|
159
|
+
`Allow the page to run ${toolName}?`,
|
|
160
|
+
},
|
|
161
|
+
} as AgentWidgetConfig;
|
|
162
|
+
const bubble = createApprovalBubble(makeDetailedMessage(), config);
|
|
163
|
+
expect(getSummary(bubble)?.textContent).toBe("Allow the page to run add_to_cart?");
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("falls back to the default summary when formatDescription returns a falsy value", () => {
|
|
167
|
+
const config = {
|
|
168
|
+
approval: { formatDescription: () => undefined },
|
|
169
|
+
} as AgentWidgetConfig;
|
|
170
|
+
const bubble = createApprovalBubble(makeDetailedMessage(), config);
|
|
171
|
+
expect(getSummary(bubble)?.textContent).toBe(
|
|
172
|
+
"The assistant wants to use “Add to cart”."
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("falls back to the raw description when there is no tool name, without duplicating it in details", () => {
|
|
177
|
+
const bubble = createApprovalBubble(makeDetailedMessage({ toolName: "" }));
|
|
178
|
+
expect(getSummary(bubble)?.textContent).toBe(TOOL_DESCRIPTION);
|
|
179
|
+
const details = getDetails(bubble);
|
|
180
|
+
expect(details?.textContent).not.toContain("IMPORTANT");
|
|
181
|
+
expect(details?.querySelector("pre")?.textContent).toContain("productEntityId");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("renders no toggle when there is nothing to show in details", () => {
|
|
185
|
+
const bubble = createApprovalBubble(
|
|
186
|
+
makeDetailedMessage({ toolName: "", description: "", parameters: undefined })
|
|
187
|
+
);
|
|
188
|
+
expect(getToggle(bubble)).toBeNull();
|
|
189
|
+
expect(getDetails(bubble)).toBeNull();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("prefers a declared WebMCP display title over the humanized tool name", () => {
|
|
193
|
+
recordWebMcpToolDisplayTitles([
|
|
194
|
+
{ name: "add_to_cart", description: "", title: "Add to Cart" },
|
|
195
|
+
]);
|
|
196
|
+
const bubble = createApprovalBubble(makeDetailedMessage());
|
|
197
|
+
expect(getSummary(bubble)?.textContent).toBe(
|
|
198
|
+
"The assistant wants to use “Add to Cart”."
|
|
199
|
+
);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("resolves the declared title for wire-prefixed tool names", () => {
|
|
203
|
+
recordWebMcpToolDisplayTitles([
|
|
204
|
+
{ name: "add_to_cart", description: "", title: "Add to Cart" },
|
|
205
|
+
]);
|
|
206
|
+
const bubble = createApprovalBubble(
|
|
207
|
+
makeDetailedMessage({ toolName: "webmcp:add_to_cart", toolType: undefined })
|
|
208
|
+
);
|
|
209
|
+
expect(getSummary(bubble)?.textContent).toBe(
|
|
210
|
+
"The assistant wants to use “Add to Cart”."
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("ignores recorded titles for non-WebMCP approvals", () => {
|
|
215
|
+
recordWebMcpToolDisplayTitles([
|
|
216
|
+
{ name: "add_to_cart", description: "", title: "Add to Cart" },
|
|
217
|
+
]);
|
|
218
|
+
const bubble = createApprovalBubble(
|
|
219
|
+
makeDetailedMessage({ toolType: undefined })
|
|
220
|
+
);
|
|
221
|
+
expect(getSummary(bubble)?.textContent).toBe(
|
|
222
|
+
"The assistant wants to use “Add to cart”."
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("passes the declared title to formatDescription as displayTitle", () => {
|
|
227
|
+
recordWebMcpToolDisplayTitles([
|
|
228
|
+
{ name: "add_to_cart", description: "", title: "Add to Cart" },
|
|
229
|
+
]);
|
|
230
|
+
const seen: unknown[] = [];
|
|
231
|
+
const config = {
|
|
232
|
+
approval: {
|
|
233
|
+
formatDescription: (ctx: { displayTitle?: string }) => {
|
|
234
|
+
seen.push(ctx.displayTitle);
|
|
235
|
+
return undefined;
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
} as AgentWidgetConfig;
|
|
239
|
+
createApprovalBubble(makeDetailedMessage(), config);
|
|
240
|
+
expect(seen).toEqual(["Add to Cart"]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("honors custom toggle labels", () => {
|
|
244
|
+
const config = {
|
|
245
|
+
approval: { showDetailsLabel: "Mehr anzeigen", hideDetailsLabel: "Weniger anzeigen" },
|
|
246
|
+
} as AgentWidgetConfig;
|
|
247
|
+
const bubble = createApprovalBubble(makeDetailedMessage(), config);
|
|
248
|
+
expect(getToggle(bubble)?.textContent).toContain("Mehr anzeigen");
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe("updateApprovalDetailsUI", () => {
|
|
253
|
+
it("syncs visibility and toggle state after the expansion state changes", () => {
|
|
254
|
+
const bubble = createApprovalBubble(makeDetailedMessage());
|
|
255
|
+
expect(getDetails(bubble)?.style.display).toBe("none");
|
|
256
|
+
|
|
257
|
+
approvalDetailsExpansionState.set("msg-1", true);
|
|
258
|
+
updateApprovalDetailsUI("msg-1", bubble);
|
|
259
|
+
expect(getDetails(bubble)?.style.display).toBe("");
|
|
260
|
+
expect(getToggle(bubble)?.getAttribute("aria-expanded")).toBe("true");
|
|
261
|
+
expect(getToggle(bubble)?.textContent).toContain("Hide details");
|
|
262
|
+
|
|
263
|
+
approvalDetailsExpansionState.set("msg-1", false);
|
|
264
|
+
updateApprovalDetailsUI("msg-1", bubble);
|
|
265
|
+
expect(getDetails(bubble)?.style.display).toBe("none");
|
|
266
|
+
expect(getToggle(bubble)?.textContent).toContain("Show details");
|
|
267
|
+
});
|
|
268
|
+
});
|