@runtypelabs/persona 3.2.2 → 3.4.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/dist/index.cjs +281 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -1
- package/dist/index.d.ts +53 -1
- package/dist/index.global.js +321 -80
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +277 -36
- package/dist/index.js.map +1 -1
- package/dist/theme-reference.cjs +1 -0
- package/dist/theme-reference.d.cts +899 -0
- package/dist/theme-reference.d.ts +899 -0
- package/dist/theme-reference.js +1 -0
- package/dist/widget.css +62 -0
- package/package.json +8 -2
- package/src/components/composer-builder.ts +20 -4
- package/src/components/demo-carousel.ts +699 -0
- package/src/components/header-builder.ts +1 -1
- package/src/index.ts +8 -0
- package/src/styles/widget.css +62 -0
- package/src/theme-reference.ts +371 -0
- package/src/types.ts +4 -0
- package/src/ui.ts +31 -14
package/src/index.ts
CHANGED
|
@@ -194,6 +194,14 @@ export type {
|
|
|
194
194
|
ComboButtonHandle
|
|
195
195
|
} from "./utils/buttons";
|
|
196
196
|
|
|
197
|
+
// Demo carousel exports
|
|
198
|
+
export { createDemoCarousel } from "./components/demo-carousel";
|
|
199
|
+
export type {
|
|
200
|
+
DemoCarouselItem,
|
|
201
|
+
DemoCarouselOptions,
|
|
202
|
+
DemoCarouselHandle
|
|
203
|
+
} from "./components/demo-carousel";
|
|
204
|
+
|
|
197
205
|
// Theme system exports
|
|
198
206
|
export {
|
|
199
207
|
createTheme,
|
package/src/styles/widget.css
CHANGED
|
@@ -1222,6 +1222,68 @@
|
|
|
1222
1222
|
font-size: 0.8125rem;
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
|
+
/* Code block copy button */
|
|
1226
|
+
.persona-code-block-wrapper {
|
|
1227
|
+
position: relative;
|
|
1228
|
+
margin: 0.5rem 0;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
.persona-code-block-wrapper pre {
|
|
1232
|
+
margin: 0 !important;
|
|
1233
|
+
border-top-left-radius: 0 !important;
|
|
1234
|
+
border-top-right-radius: 0 !important;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
.persona-code-block-header {
|
|
1238
|
+
display: flex;
|
|
1239
|
+
align-items: center;
|
|
1240
|
+
justify-content: space-between;
|
|
1241
|
+
background-color: var(--persona-md-code-block-bg, #f3f4f6);
|
|
1242
|
+
border: 1px solid var(--persona-md-code-block-border-color, #e5e7eb);
|
|
1243
|
+
border-bottom: none;
|
|
1244
|
+
border-top-left-radius: var(--persona-md-code-block-border-radius, 0.375rem);
|
|
1245
|
+
border-top-right-radius: var(--persona-md-code-block-border-radius, 0.375rem);
|
|
1246
|
+
padding: 0.25rem 0.5rem 0.25rem 0.75rem;
|
|
1247
|
+
font-size: 0.75rem;
|
|
1248
|
+
color: var(--persona-text-muted, #6b7280);
|
|
1249
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.persona-code-copy-btn {
|
|
1253
|
+
display: inline-flex;
|
|
1254
|
+
align-items: center;
|
|
1255
|
+
gap: 0.25rem;
|
|
1256
|
+
background: none;
|
|
1257
|
+
border: 1px solid transparent;
|
|
1258
|
+
border-radius: 0.25rem;
|
|
1259
|
+
padding: 0.25rem 0.5rem;
|
|
1260
|
+
cursor: pointer;
|
|
1261
|
+
color: var(--persona-text-muted, #6b7280);
|
|
1262
|
+
font-size: 0.75rem;
|
|
1263
|
+
font-family: inherit;
|
|
1264
|
+
line-height: 1;
|
|
1265
|
+
transition: color 0.15s ease, border-color 0.15s ease;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
.persona-code-copy-btn:hover {
|
|
1269
|
+
color: var(--persona-text, #111827);
|
|
1270
|
+
border-color: var(--persona-md-code-block-border-color, #e5e7eb);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
.persona-code-copy-btn.persona-code-copied {
|
|
1274
|
+
color: #16a34a;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
.persona-code-copy-btn.persona-code-copy-generating {
|
|
1278
|
+
cursor: default;
|
|
1279
|
+
opacity: 0.5;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
.persona-code-copy-btn.persona-code-copy-generating:hover {
|
|
1283
|
+
color: var(--persona-text-muted, #6b7280);
|
|
1284
|
+
border-color: transparent;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1225
1287
|
/* Ensure all links in chat bubbles have underlines */
|
|
1226
1288
|
.vanilla-message-bubble a {
|
|
1227
1289
|
text-decoration: underline;
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Reference — Structured documentation and examples for the Persona v2 theme system.
|
|
3
|
+
*
|
|
4
|
+
* Exported via the `@runtypelabs/persona/theme-reference` entry point so it stays
|
|
5
|
+
* out of the IIFE widget bundle. Intended for AI/MCP tool consumption.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { DEFAULT_PALETTE } from './utils/tokens'
|
|
9
|
+
import type { DeepPartial, PersonaTheme } from './types/theme'
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Token System Documentation
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export const THEME_TOKEN_DOCS = {
|
|
16
|
+
overview:
|
|
17
|
+
'Persona uses a three-layer design token system: palette → semantic → components. Most themes only need palette.colors overrides — semantic and component layers auto-derive from palette values. Config also accepts non-theme appearance options (launcher, sendButton, toolCall, etc.).',
|
|
18
|
+
|
|
19
|
+
layers: {
|
|
20
|
+
palette: {
|
|
21
|
+
description:
|
|
22
|
+
'Primitive design tokens. Override specific shades to change the entire widget feel.',
|
|
23
|
+
colors: {
|
|
24
|
+
description:
|
|
25
|
+
'7 color scales, each with shades 50 (lightest) to 950 (darkest). Override only the shades you need.',
|
|
26
|
+
scales: {
|
|
27
|
+
gray: 'Neutrals — backgrounds, text, borders. Key shades: 50 (lightest bg), 100 (secondary bg), 200 (borders), 500 (muted text), 900 (primary text).',
|
|
28
|
+
primary:
|
|
29
|
+
'Brand color — buttons, links, interactive elements. Key shades: 500 (default), 600 (hover).',
|
|
30
|
+
accent: 'Secondary highlight. Key shades: 500 (default), 600 (hover).',
|
|
31
|
+
secondary: 'Tertiary color scale.',
|
|
32
|
+
success: 'Positive feedback (default: green).',
|
|
33
|
+
warning: 'Caution feedback (default: yellow).',
|
|
34
|
+
error: 'Error/danger feedback (default: red).',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
radius: {
|
|
38
|
+
description: 'Border radius scale. Add custom keys like launcher, button.',
|
|
39
|
+
defaults: {
|
|
40
|
+
none: '0px',
|
|
41
|
+
sm: '0.125rem',
|
|
42
|
+
md: '0.375rem',
|
|
43
|
+
lg: '0.5rem',
|
|
44
|
+
xl: '0.75rem',
|
|
45
|
+
'2xl': '1rem',
|
|
46
|
+
full: '9999px',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
typography: {
|
|
50
|
+
fontFamily:
|
|
51
|
+
'Three stacks: sans (system-ui), serif (Georgia), mono (ui-monospace). Override individual stack values.',
|
|
52
|
+
fontSize:
|
|
53
|
+
'Scale: xs (0.75rem), sm (0.875rem), base (1rem), lg (1.125rem), xl (1.25rem), 2xl (1.5rem), 3xl (1.875rem), 4xl (2.25rem).',
|
|
54
|
+
fontWeight: 'normal (400), medium (500), semibold (600), bold (700).',
|
|
55
|
+
lineHeight: 'tight (1.25), normal (1.5), relaxed (1.625).',
|
|
56
|
+
},
|
|
57
|
+
shadows:
|
|
58
|
+
'Scale: none, sm, md, lg, xl, 2xl. Values are CSS box-shadow strings.',
|
|
59
|
+
borders: 'Scale: none, sm (1px solid), md (2px solid), lg (4px solid).',
|
|
60
|
+
spacing:
|
|
61
|
+
'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.',
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
semantic: {
|
|
65
|
+
description:
|
|
66
|
+
'Design intent tokens. Auto-derived from palette by default. Override to redirect token resolution. Values are token reference strings like "palette.colors.primary.500".',
|
|
67
|
+
colors: {
|
|
68
|
+
primary: 'palette.colors.primary.500 — Primary brand color.',
|
|
69
|
+
secondary: 'palette.colors.gray.500 — Secondary color.',
|
|
70
|
+
accent: 'palette.colors.primary.600 — Accent/interactive color.',
|
|
71
|
+
surface: 'palette.colors.gray.50 — Panel/card backgrounds.',
|
|
72
|
+
background: 'palette.colors.gray.50 — Page background.',
|
|
73
|
+
container: 'palette.colors.gray.100 — Container backgrounds.',
|
|
74
|
+
text: 'palette.colors.gray.900 — Primary text.',
|
|
75
|
+
textMuted: 'palette.colors.gray.500 — Muted/secondary text.',
|
|
76
|
+
textInverse: 'palette.colors.gray.50 — Text on dark backgrounds.',
|
|
77
|
+
border: 'palette.colors.gray.200 — Default border color.',
|
|
78
|
+
divider: 'palette.colors.gray.200 — Divider lines.',
|
|
79
|
+
interactive: {
|
|
80
|
+
default: 'palette.colors.primary.500',
|
|
81
|
+
hover: 'palette.colors.primary.600',
|
|
82
|
+
focus: 'palette.colors.primary.700',
|
|
83
|
+
active: 'palette.colors.primary.800',
|
|
84
|
+
disabled: 'palette.colors.gray.300',
|
|
85
|
+
},
|
|
86
|
+
feedback: {
|
|
87
|
+
success: 'palette.colors.success.500',
|
|
88
|
+
warning: 'palette.colors.warning.500',
|
|
89
|
+
error: 'palette.colors.error.500',
|
|
90
|
+
info: 'palette.colors.primary.500',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
spacing:
|
|
94
|
+
'xs (0.25rem), sm (0.5rem), md (1rem), lg (1.5rem), xl (2rem), 2xl (2.5rem).',
|
|
95
|
+
typography:
|
|
96
|
+
'fontFamily, fontSize, fontWeight, lineHeight — reference palette typography tokens.',
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
components: {
|
|
100
|
+
description:
|
|
101
|
+
'UI element tokens. Rarely needed for basic theming. Override for fine-grained control. All values are token references or raw CSS strings.',
|
|
102
|
+
button: {
|
|
103
|
+
description: 'Three variants: primary, secondary, ghost.',
|
|
104
|
+
properties: 'background, foreground, borderRadius, padding.',
|
|
105
|
+
},
|
|
106
|
+
input: {
|
|
107
|
+
description: 'Message input field.',
|
|
108
|
+
properties:
|
|
109
|
+
'background, placeholder, borderRadius, padding, focus.border, focus.ring.',
|
|
110
|
+
},
|
|
111
|
+
launcher: {
|
|
112
|
+
description: 'Floating launcher button.',
|
|
113
|
+
properties: 'size (60px), iconSize (28px), borderRadius, shadow.',
|
|
114
|
+
},
|
|
115
|
+
panel: {
|
|
116
|
+
description: 'Chat panel container.',
|
|
117
|
+
properties:
|
|
118
|
+
'width, maxWidth (400px), height (600px), maxHeight, borderRadius, shadow.',
|
|
119
|
+
},
|
|
120
|
+
header: {
|
|
121
|
+
description: 'Chat panel header.',
|
|
122
|
+
properties:
|
|
123
|
+
'background, border, borderRadius, padding, iconBackground, iconForeground, titleForeground, subtitleForeground, actionIconForeground, shadow, borderBottom.',
|
|
124
|
+
},
|
|
125
|
+
message: {
|
|
126
|
+
description: 'Chat message bubbles.',
|
|
127
|
+
user: 'background, text, borderRadius, shadow.',
|
|
128
|
+
assistant:
|
|
129
|
+
'background, text, borderRadius, border (optional), shadow (optional).',
|
|
130
|
+
},
|
|
131
|
+
markdown: {
|
|
132
|
+
description: 'Markdown rendering in messages and artifact pane.',
|
|
133
|
+
properties:
|
|
134
|
+
'inlineCode (background, foreground), link.foreground, prose.fontFamily, heading.h1/h2 (fontSize, fontWeight).',
|
|
135
|
+
},
|
|
136
|
+
voice:
|
|
137
|
+
'recording (indicator, background, border), processing (icon, background), speaking (icon).',
|
|
138
|
+
approval:
|
|
139
|
+
'requested (background, border, text), approve (background, foreground), deny (background, foreground).',
|
|
140
|
+
attachment: 'image (background, border).',
|
|
141
|
+
toolBubble: 'shadow — tool call row box-shadow.',
|
|
142
|
+
reasoningBubble: 'shadow — reasoning/thinking row box-shadow.',
|
|
143
|
+
composer: 'shadow — message input form box-shadow.',
|
|
144
|
+
artifact:
|
|
145
|
+
'toolbar (icon styling, copy menu), tab (background, active states), pane (background, toolbarBackground).',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
colorScheme:
|
|
150
|
+
'"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 — provide dark palette and semantic overrides yourself.',
|
|
151
|
+
|
|
152
|
+
plugins: {
|
|
153
|
+
description:
|
|
154
|
+
'Plugins transform theme tokens before resolution. Use with createTheme().',
|
|
155
|
+
available: {
|
|
156
|
+
brandPlugin:
|
|
157
|
+
'Auto-generates full color scales from a single brand hex: brandPlugin({ colors: { primary: "#7c3aed" } }).',
|
|
158
|
+
accessibilityPlugin:
|
|
159
|
+
'Enhanced focus indicators and disabled states.',
|
|
160
|
+
highContrastPlugin: 'Increased contrast for visual accessibility.',
|
|
161
|
+
reducedMotionPlugin:
|
|
162
|
+
'Disables all animations (sets transitions to 0ms).',
|
|
163
|
+
animationsPlugin: 'Adds transition and easing tokens.',
|
|
164
|
+
},
|
|
165
|
+
usage:
|
|
166
|
+
'createTheme(themeOverrides, { plugins: [brandPlugin({ colors: { primary: "#7c3aed" } })] })',
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
widgetConfig: {
|
|
170
|
+
description:
|
|
171
|
+
'Non-theme config options on the widget config object that affect appearance. These are siblings of "theme" in the config, not nested inside it.',
|
|
172
|
+
launcher: {
|
|
173
|
+
description: 'Floating launcher button and panel positioning.',
|
|
174
|
+
properties: {
|
|
175
|
+
enabled: 'Show/hide the launcher button.',
|
|
176
|
+
title: 'Header title text.',
|
|
177
|
+
subtitle: 'Header subtitle text.',
|
|
178
|
+
position:
|
|
179
|
+
'"bottom-right" | "bottom-left" | "top-right" | "top-left".',
|
|
180
|
+
width: 'Chat panel width (CSS value).',
|
|
181
|
+
fullHeight: 'Fill full height of container.',
|
|
182
|
+
mountMode: '"floating" | "docked".',
|
|
183
|
+
agentIconText: 'Emoji/text for agent icon.',
|
|
184
|
+
border: 'Border style for launcher button.',
|
|
185
|
+
shadow: 'Box shadow for launcher button.',
|
|
186
|
+
collapsedMaxWidth: 'Max-width for launcher pill when panel closed.',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
sendButton: {
|
|
190
|
+
description: 'Send button appearance.',
|
|
191
|
+
properties:
|
|
192
|
+
'backgroundColor, textColor, borderWidth, borderColor, paddingX, paddingY, iconText, iconName, size.',
|
|
193
|
+
},
|
|
194
|
+
closeButton: {
|
|
195
|
+
description: 'Close button (on launcher config).',
|
|
196
|
+
properties:
|
|
197
|
+
'closeButtonSize, closeButtonColor, closeButtonBackgroundColor, closeButtonBorderWidth, closeButtonBorderColor, closeButtonBorderRadius.',
|
|
198
|
+
},
|
|
199
|
+
clearChat: {
|
|
200
|
+
description: 'Clear chat button (on launcher.clearChat config).',
|
|
201
|
+
properties:
|
|
202
|
+
'enabled, iconColor, backgroundColor, borderWidth, borderColor, borderRadius, size.',
|
|
203
|
+
},
|
|
204
|
+
toolCall: {
|
|
205
|
+
description: 'Tool call display styling.',
|
|
206
|
+
properties:
|
|
207
|
+
'backgroundColor, borderColor, borderWidth, borderRadius, headerBackgroundColor, headerTextColor, contentBackgroundColor, contentTextColor, codeBlockBackgroundColor, codeBlockBorderColor, codeBlockTextColor, toggleTextColor, labelTextColor.',
|
|
208
|
+
},
|
|
209
|
+
copy: {
|
|
210
|
+
description: 'Widget text content.',
|
|
211
|
+
properties:
|
|
212
|
+
'welcomeTitle, welcomeSubtitle, inputPlaceholder, sendButtonLabel.',
|
|
213
|
+
},
|
|
214
|
+
voiceRecognition: {
|
|
215
|
+
description: 'Voice input configuration.',
|
|
216
|
+
properties: 'enabled, pauseDuration, iconColor, backgroundColor.',
|
|
217
|
+
},
|
|
218
|
+
suggestionChips:
|
|
219
|
+
'string[] — Suggested prompts shown to the user.',
|
|
220
|
+
layout: {
|
|
221
|
+
description: 'Layout configuration.',
|
|
222
|
+
header: '"default" | "minimal". Options: showIcon, showTitle, showSubtitle, showCloseButton.',
|
|
223
|
+
messages:
|
|
224
|
+
'"bubble" | "flat" | "minimal". Avatar and timestamp options available.',
|
|
225
|
+
},
|
|
226
|
+
features: {
|
|
227
|
+
description: 'Feature flags.',
|
|
228
|
+
properties:
|
|
229
|
+
'showReasoning (AI thinking steps), showToolCalls (tool invocations), artifacts (sidebar config).',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Example Themes
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
export interface ThemeExample {
|
|
239
|
+
description: string
|
|
240
|
+
colorScheme?: 'light' | 'dark' | 'auto'
|
|
241
|
+
theme: DeepPartial<PersonaTheme>
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export const THEME_EXAMPLES: Record<string, ThemeExample> = {
|
|
245
|
+
darkIndigo: {
|
|
246
|
+
description:
|
|
247
|
+
'Dark mode with indigo accent — override grays for dark backgrounds and semantic tokens for inverted text/surface',
|
|
248
|
+
theme: {
|
|
249
|
+
palette: {
|
|
250
|
+
colors: {
|
|
251
|
+
primary: { 500: '#6366f1', 600: '#4f46e5' },
|
|
252
|
+
gray: {
|
|
253
|
+
50: '#f1f5f9',
|
|
254
|
+
100: '#1e293b',
|
|
255
|
+
200: '#334155',
|
|
256
|
+
500: '#94a3b8',
|
|
257
|
+
900: '#0f172a',
|
|
258
|
+
950: '#020617',
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
semantic: {
|
|
263
|
+
colors: {
|
|
264
|
+
surface: 'palette.colors.gray.900',
|
|
265
|
+
background: 'palette.colors.gray.900',
|
|
266
|
+
container: 'palette.colors.gray.100',
|
|
267
|
+
text: 'palette.colors.gray.50',
|
|
268
|
+
textMuted: 'palette.colors.gray.500',
|
|
269
|
+
textInverse: 'palette.colors.gray.900',
|
|
270
|
+
border: 'palette.colors.gray.200',
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
warmVintage: {
|
|
276
|
+
description: 'Warm sepia tones with serif font and subtle radius',
|
|
277
|
+
theme: {
|
|
278
|
+
palette: {
|
|
279
|
+
colors: {
|
|
280
|
+
primary: { 500: '#b45309', 600: '#92400e' },
|
|
281
|
+
gray: {
|
|
282
|
+
50: '#fef3c7',
|
|
283
|
+
100: '#fef9c3',
|
|
284
|
+
200: '#d6d3d1',
|
|
285
|
+
500: '#78716c',
|
|
286
|
+
900: '#44403c',
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
radius: { sm: '0.125rem', md: '0.25rem', lg: '0.375rem' },
|
|
290
|
+
typography: {
|
|
291
|
+
fontFamily: {
|
|
292
|
+
sans: 'Georgia, Cambria, "Times New Roman", Times, serif',
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
neonCyberpunk: {
|
|
299
|
+
description:
|
|
300
|
+
'Neon on dark with monospace font — full semantic override for dark background',
|
|
301
|
+
theme: {
|
|
302
|
+
palette: {
|
|
303
|
+
colors: {
|
|
304
|
+
primary: { 500: '#f0abfc', 600: '#e879f9' },
|
|
305
|
+
accent: { 500: '#22d3ee', 600: '#06b6d4' },
|
|
306
|
+
gray: {
|
|
307
|
+
50: '#f0abfc',
|
|
308
|
+
100: '#1e0a3c',
|
|
309
|
+
200: '#3b0764',
|
|
310
|
+
500: '#c084fc',
|
|
311
|
+
900: '#0c0a1a',
|
|
312
|
+
950: '#050412',
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
radius: { sm: '0', md: '0.25rem', lg: '0.375rem' },
|
|
316
|
+
typography: {
|
|
317
|
+
fontFamily: {
|
|
318
|
+
sans: 'ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
semantic: {
|
|
323
|
+
colors: {
|
|
324
|
+
surface: 'palette.colors.gray.900',
|
|
325
|
+
background: 'palette.colors.gray.950',
|
|
326
|
+
container: 'palette.colors.gray.100',
|
|
327
|
+
text: 'palette.colors.gray.50',
|
|
328
|
+
textMuted: 'palette.colors.gray.500',
|
|
329
|
+
border: 'palette.colors.gray.200',
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
cleanRounded: {
|
|
335
|
+
description: 'Clean light theme with large radius and panel styling',
|
|
336
|
+
theme: {
|
|
337
|
+
palette: {
|
|
338
|
+
radius: {
|
|
339
|
+
sm: '6px',
|
|
340
|
+
md: '8px',
|
|
341
|
+
lg: '12px',
|
|
342
|
+
launcher: '50px',
|
|
343
|
+
button: '8px',
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
components: {
|
|
347
|
+
panel: { borderRadius: '16px', shadow: 'palette.shadows.2xl' },
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// ---------------------------------------------------------------------------
|
|
354
|
+
// Reference Payload
|
|
355
|
+
// ---------------------------------------------------------------------------
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Complete theme reference payload for AI / MCP tool consumption.
|
|
359
|
+
*
|
|
360
|
+
* Returns token system docs, the default color palette and radius scale,
|
|
361
|
+
* example themes, and a list of SDK-bundled presets.
|
|
362
|
+
*/
|
|
363
|
+
export function getThemeReference() {
|
|
364
|
+
return {
|
|
365
|
+
tokenDocs: THEME_TOKEN_DOCS,
|
|
366
|
+
defaultColorPalette: DEFAULT_PALETTE.colors,
|
|
367
|
+
defaultRadius: DEFAULT_PALETTE.radius,
|
|
368
|
+
examples: THEME_EXAMPLES,
|
|
369
|
+
sdkPresets: ['shop', 'minimal', 'fullscreen'],
|
|
370
|
+
}
|
|
371
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -884,7 +884,11 @@ export type AgentWidgetClearChatConfig = {
|
|
|
884
884
|
|
|
885
885
|
export type AgentWidgetStatusIndicatorConfig = {
|
|
886
886
|
visible?: boolean;
|
|
887
|
+
/** Text alignment. Default: 'right'. */
|
|
888
|
+
align?: 'left' | 'center' | 'right';
|
|
887
889
|
idleText?: string;
|
|
890
|
+
/** URL to open in a new tab when the idle text is clicked. */
|
|
891
|
+
idleLink?: string;
|
|
888
892
|
connectingText?: string;
|
|
889
893
|
connectedText?: string;
|
|
890
894
|
errorText?: string;
|
package/src/ui.ts
CHANGED
|
@@ -604,6 +604,23 @@ export const createAgentExperience = (
|
|
|
604
604
|
return statusCopy[status];
|
|
605
605
|
};
|
|
606
606
|
|
|
607
|
+
/** Update statusText element, rendering a link for idle status when idleLink is configured. */
|
|
608
|
+
function applyStatusToElement(el: HTMLElement, text: string, statusCfg: typeof statusConfig, status: string): void {
|
|
609
|
+
if (status === "idle" && statusCfg.idleLink) {
|
|
610
|
+
el.textContent = "";
|
|
611
|
+
const link = document.createElement("a");
|
|
612
|
+
link.href = statusCfg.idleLink;
|
|
613
|
+
link.target = "_blank";
|
|
614
|
+
link.rel = "noopener noreferrer";
|
|
615
|
+
link.textContent = text;
|
|
616
|
+
link.style.color = "inherit";
|
|
617
|
+
link.style.textDecoration = "none";
|
|
618
|
+
el.appendChild(link);
|
|
619
|
+
} else {
|
|
620
|
+
el.textContent = text;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
607
624
|
const { wrapper, panel } = createWrapper(config);
|
|
608
625
|
const panelElements = buildPanel(config, launcherEnabled);
|
|
609
626
|
let {
|
|
@@ -2670,14 +2687,14 @@ export const createAgentExperience = (
|
|
|
2670
2687
|
},
|
|
2671
2688
|
onStatusChanged(status) {
|
|
2672
2689
|
const currentStatusConfig = config.statusIndicator ?? {};
|
|
2673
|
-
const getCurrentStatusText = (
|
|
2674
|
-
if (
|
|
2675
|
-
if (
|
|
2676
|
-
if (
|
|
2677
|
-
if (
|
|
2678
|
-
return statusCopy[
|
|
2690
|
+
const getCurrentStatusText = (s: AgentWidgetSessionStatus): string => {
|
|
2691
|
+
if (s === "idle") return currentStatusConfig.idleText ?? statusCopy.idle;
|
|
2692
|
+
if (s === "connecting") return currentStatusConfig.connectingText ?? statusCopy.connecting;
|
|
2693
|
+
if (s === "connected") return currentStatusConfig.connectedText ?? statusCopy.connected;
|
|
2694
|
+
if (s === "error") return currentStatusConfig.errorText ?? statusCopy.error;
|
|
2695
|
+
return statusCopy[s];
|
|
2679
2696
|
};
|
|
2680
|
-
statusText
|
|
2697
|
+
applyStatusToElement(statusText, getCurrentStatusText(status), currentStatusConfig, status);
|
|
2681
2698
|
},
|
|
2682
2699
|
onStreamingChanged(streaming) {
|
|
2683
2700
|
isStreaming = streaming;
|
|
@@ -4815,14 +4832,14 @@ export const createAgentExperience = (
|
|
|
4815
4832
|
// Update status text if status is currently set
|
|
4816
4833
|
if (session) {
|
|
4817
4834
|
const currentStatus = session.getStatus();
|
|
4818
|
-
const getCurrentStatusText = (
|
|
4819
|
-
if (
|
|
4820
|
-
if (
|
|
4821
|
-
if (
|
|
4822
|
-
if (
|
|
4823
|
-
return statusCopy[
|
|
4835
|
+
const getCurrentStatusText = (s: AgentWidgetSessionStatus): string => {
|
|
4836
|
+
if (s === "idle") return statusIndicatorConfig.idleText ?? statusCopy.idle;
|
|
4837
|
+
if (s === "connecting") return statusIndicatorConfig.connectingText ?? statusCopy.connecting;
|
|
4838
|
+
if (s === "connected") return statusIndicatorConfig.connectedText ?? statusCopy.connected;
|
|
4839
|
+
if (s === "error") return statusIndicatorConfig.errorText ?? statusCopy.error;
|
|
4840
|
+
return statusCopy[s];
|
|
4824
4841
|
};
|
|
4825
|
-
statusText
|
|
4842
|
+
applyStatusToElement(statusText, getCurrentStatusText(currentStatus), statusIndicatorConfig, currentStatus);
|
|
4826
4843
|
}
|
|
4827
4844
|
},
|
|
4828
4845
|
open() {
|