@runtypelabs/persona 2.0.0 → 2.1.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 +21 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.global.js +69 -69
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +21 -21
- package/dist/index.js.map +1 -1
- package/dist/widget.css +13 -0
- package/package.json +1 -1
- package/src/styles/widget.css +13 -0
- package/src/types/theme.ts +22 -0
- package/src/types.ts +24 -0
- package/src/utils/migration.ts +42 -1
- package/src/utils/theme.test.ts +33 -1
- package/src/utils/theme.ts +8 -0
- package/src/utils/tokens.ts +19 -0
package/dist/widget.css
CHANGED
|
@@ -927,6 +927,7 @@
|
|
|
927
927
|
|
|
928
928
|
.persona-widget-composer {
|
|
929
929
|
border-radius: var(--persona-input-radius, var(--persona-radius-lg, 0.5rem));
|
|
930
|
+
box-shadow: var(--persona-composer-shadow, none);
|
|
930
931
|
}
|
|
931
932
|
|
|
932
933
|
.persona-form-grid {
|
|
@@ -1168,6 +1169,18 @@
|
|
|
1168
1169
|
box-shadow: var(--persona-message-assistant-shadow, 0 1px 2px 0 rgb(0 0 0 / 0.05));
|
|
1169
1170
|
}
|
|
1170
1171
|
|
|
1172
|
+
#persona-root .vanilla-message-user-bubble.persona-shadow-sm {
|
|
1173
|
+
box-shadow: var(--persona-message-user-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
#persona-root .vanilla-tool-bubble.persona-shadow-sm {
|
|
1177
|
+
box-shadow: var(--persona-tool-bubble-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
#persona-root .vanilla-reasoning-bubble.persona-shadow-sm {
|
|
1181
|
+
box-shadow: var(--persona-reasoning-bubble-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1171
1184
|
/* Artifact markdown (no .vanilla-message-bubble wrapper) */
|
|
1172
1185
|
#persona-root .persona-markdown-bubble {
|
|
1173
1186
|
color: var(--persona-text, #111827);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runtypelabs/persona",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.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",
|
package/src/styles/widget.css
CHANGED
|
@@ -927,6 +927,7 @@
|
|
|
927
927
|
|
|
928
928
|
.persona-widget-composer {
|
|
929
929
|
border-radius: var(--persona-input-radius, var(--persona-radius-lg, 0.5rem));
|
|
930
|
+
box-shadow: var(--persona-composer-shadow, none);
|
|
930
931
|
}
|
|
931
932
|
|
|
932
933
|
.persona-form-grid {
|
|
@@ -1168,6 +1169,18 @@
|
|
|
1168
1169
|
box-shadow: var(--persona-message-assistant-shadow, 0 1px 2px 0 rgb(0 0 0 / 0.05));
|
|
1169
1170
|
}
|
|
1170
1171
|
|
|
1172
|
+
#persona-root .vanilla-message-user-bubble.persona-shadow-sm {
|
|
1173
|
+
box-shadow: var(--persona-message-user-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
#persona-root .vanilla-tool-bubble.persona-shadow-sm {
|
|
1177
|
+
box-shadow: var(--persona-tool-bubble-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
#persona-root .vanilla-reasoning-bubble.persona-shadow-sm {
|
|
1181
|
+
box-shadow: var(--persona-reasoning-bubble-shadow, 0 5px 15px rgba(15, 23, 42, 0.08));
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1171
1184
|
/* Artifact markdown (no .vanilla-message-bubble wrapper) */
|
|
1172
1185
|
#persona-root .persona-markdown-bubble {
|
|
1173
1186
|
color: var(--persona-text, #111827);
|
package/src/types/theme.ts
CHANGED
|
@@ -206,6 +206,8 @@ export interface MessageTokens {
|
|
|
206
206
|
background: TokenReference<'color'>;
|
|
207
207
|
text: TokenReference<'color'>;
|
|
208
208
|
borderRadius: TokenReference<'radius'>;
|
|
209
|
+
/** User bubble box-shadow (token ref or raw CSS, e.g. `none`). */
|
|
210
|
+
shadow?: string;
|
|
209
211
|
};
|
|
210
212
|
assistant: {
|
|
211
213
|
background: TokenReference<'color'>;
|
|
@@ -279,6 +281,23 @@ export interface AttachmentTokens {
|
|
|
279
281
|
};
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
/** Tool-call row chrome (collapsible tool bubbles). */
|
|
285
|
+
export interface ToolBubbleTokens {
|
|
286
|
+
/** Box-shadow for tool bubbles (token ref or raw CSS, e.g. `none`). */
|
|
287
|
+
shadow: string;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Reasoning / “thinking” row chrome. */
|
|
291
|
+
export interface ReasoningBubbleTokens {
|
|
292
|
+
shadow: string;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Composer (message input) chrome. */
|
|
296
|
+
export interface ComposerChromeTokens {
|
|
297
|
+
/** Box-shadow on the composer form (raw CSS, e.g. `none`). */
|
|
298
|
+
shadow: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
282
301
|
export interface ComponentTokens {
|
|
283
302
|
button: ButtonTokens;
|
|
284
303
|
input: InputTokens;
|
|
@@ -291,6 +310,9 @@ export interface ComponentTokens {
|
|
|
291
310
|
voice: VoiceTokens;
|
|
292
311
|
approval: ApprovalTokens;
|
|
293
312
|
attachment: AttachmentTokens;
|
|
313
|
+
toolBubble: ToolBubbleTokens;
|
|
314
|
+
reasoningBubble: ReasoningBubbleTokens;
|
|
315
|
+
composer: ComposerChromeTokens;
|
|
294
316
|
}
|
|
295
317
|
|
|
296
318
|
export interface PaletteExtras {
|
package/src/types.ts
CHANGED
|
@@ -714,6 +714,28 @@ export type AgentWidgetTheme = {
|
|
|
714
714
|
* @default "16px"
|
|
715
715
|
*/
|
|
716
716
|
panelBorderRadius?: string;
|
|
717
|
+
/**
|
|
718
|
+
* Box-shadow for user message bubbles (bubble message layout).
|
|
719
|
+
* @example "none" | "0 1px 2px rgba(0,0,0,0.05)"
|
|
720
|
+
*/
|
|
721
|
+
messageUserShadow?: string;
|
|
722
|
+
/**
|
|
723
|
+
* Box-shadow for assistant message bubbles (bubble message layout).
|
|
724
|
+
* Overrides the default subtle assistant shadow when set.
|
|
725
|
+
*/
|
|
726
|
+
messageAssistantShadow?: string;
|
|
727
|
+
/**
|
|
728
|
+
* Box-shadow for tool-call / function-call rows.
|
|
729
|
+
*/
|
|
730
|
+
toolBubbleShadow?: string;
|
|
731
|
+
/**
|
|
732
|
+
* Box-shadow for reasoning (“thinking”) rows.
|
|
733
|
+
*/
|
|
734
|
+
reasoningBubbleShadow?: string;
|
|
735
|
+
/**
|
|
736
|
+
* Box-shadow on the composer (input) container.
|
|
737
|
+
*/
|
|
738
|
+
composerShadow?: string;
|
|
717
739
|
};
|
|
718
740
|
|
|
719
741
|
export type AgentWidgetDockConfig = {
|
|
@@ -1141,6 +1163,8 @@ export type AgentWidgetApprovalConfig = {
|
|
|
1141
1163
|
};
|
|
1142
1164
|
|
|
1143
1165
|
export type AgentWidgetToolCallConfig = {
|
|
1166
|
+
/** Box-shadow for tool-call bubbles; overrides `theme.toolBubbleShadow` when set. */
|
|
1167
|
+
shadow?: string;
|
|
1144
1168
|
backgroundColor?: string;
|
|
1145
1169
|
borderColor?: string;
|
|
1146
1170
|
borderWidth?: string;
|
package/src/utils/migration.ts
CHANGED
|
@@ -139,6 +139,28 @@ export function migrateV1Theme(
|
|
|
139
139
|
migrated.components.panel = {};
|
|
140
140
|
}
|
|
141
141
|
migrated.components.panel.borderRadius = value;
|
|
142
|
+
} else if (key === 'messageUserShadow') {
|
|
143
|
+
if (!migrated.components) migrated.components = {};
|
|
144
|
+
if (!migrated.components.message) migrated.components.message = {};
|
|
145
|
+
if (!migrated.components.message.user) migrated.components.message.user = {};
|
|
146
|
+
(migrated.components.message.user as { shadow?: string }).shadow = value as string;
|
|
147
|
+
} else if (key === 'messageAssistantShadow') {
|
|
148
|
+
if (!migrated.components) migrated.components = {};
|
|
149
|
+
if (!migrated.components.message) migrated.components.message = {};
|
|
150
|
+
if (!migrated.components.message.assistant) migrated.components.message.assistant = {};
|
|
151
|
+
(migrated.components.message.assistant as { shadow?: string }).shadow = value as string;
|
|
152
|
+
} else if (key === 'toolBubbleShadow') {
|
|
153
|
+
if (!migrated.components) migrated.components = {};
|
|
154
|
+
if (!migrated.components.toolBubble) migrated.components.toolBubble = {};
|
|
155
|
+
(migrated.components.toolBubble as { shadow?: string }).shadow = value as string;
|
|
156
|
+
} else if (key === 'reasoningBubbleShadow') {
|
|
157
|
+
if (!migrated.components) migrated.components = {};
|
|
158
|
+
if (!migrated.components.reasoningBubble) migrated.components.reasoningBubble = {};
|
|
159
|
+
(migrated.components.reasoningBubble as { shadow?: string }).shadow = value as string;
|
|
160
|
+
} else if (key === 'composerShadow') {
|
|
161
|
+
if (!migrated.components) migrated.components = {};
|
|
162
|
+
if (!migrated.components.composer) migrated.components.composer = {};
|
|
163
|
+
(migrated.components.composer as { shadow?: string }).shadow = value as string;
|
|
142
164
|
}
|
|
143
165
|
}
|
|
144
166
|
|
|
@@ -165,8 +187,27 @@ export function validateV1Theme(v1Theme: unknown): {
|
|
|
165
187
|
return { valid: true, warnings: [] };
|
|
166
188
|
}
|
|
167
189
|
|
|
190
|
+
const v1ThemeChromeKeys = new Set([
|
|
191
|
+
'panelBorder',
|
|
192
|
+
'panelShadow',
|
|
193
|
+
'panelBorderRadius',
|
|
194
|
+
'messageUserShadow',
|
|
195
|
+
'messageAssistantShadow',
|
|
196
|
+
'toolBubbleShadow',
|
|
197
|
+
'reasoningBubbleShadow',
|
|
198
|
+
'composerShadow',
|
|
199
|
+
]);
|
|
200
|
+
|
|
168
201
|
const deprecatedProperties = Object.keys(theme).filter(
|
|
169
|
-
(key) =>
|
|
202
|
+
(key) =>
|
|
203
|
+
!(
|
|
204
|
+
key in v1ToV2Mapping ||
|
|
205
|
+
key in v1RadiusMapping ||
|
|
206
|
+
key === 'inputFontFamily' ||
|
|
207
|
+
key === 'inputFontWeight' ||
|
|
208
|
+
key.startsWith('panel') ||
|
|
209
|
+
v1ThemeChromeKeys.has(key)
|
|
210
|
+
)
|
|
170
211
|
);
|
|
171
212
|
|
|
172
213
|
if (deprecatedProperties.length > 0) {
|
package/src/utils/theme.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
|
|
3
3
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
4
|
-
import { createTheme, getActiveTheme, themeToCssVariables } from './theme';
|
|
4
|
+
import { applyThemeVariables, createTheme, getActiveTheme, themeToCssVariables } from './theme';
|
|
5
5
|
|
|
6
6
|
describe('theme utils', () => {
|
|
7
7
|
afterEach(() => {
|
|
@@ -122,4 +122,36 @@ describe('theme utils', () => {
|
|
|
122
122
|
expect(cssVars['--persona-md-h2-weight']).toBe('600');
|
|
123
123
|
expect(cssVars['--persona-md-prose-font-family']).toBe('Georgia, serif');
|
|
124
124
|
});
|
|
125
|
+
|
|
126
|
+
it('maps flat AgentWidgetTheme bubble shadow keys to consumer CSS variables', () => {
|
|
127
|
+
const cfg = {
|
|
128
|
+
colorScheme: 'light' as const,
|
|
129
|
+
theme: {
|
|
130
|
+
toolBubbleShadow: 'none',
|
|
131
|
+
reasoningBubbleShadow: 'none',
|
|
132
|
+
messageUserShadow: 'none',
|
|
133
|
+
messageAssistantShadow: 'none',
|
|
134
|
+
composerShadow: 'none',
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const active = getActiveTheme(cfg as any);
|
|
139
|
+
const cssVars = themeToCssVariables(active);
|
|
140
|
+
|
|
141
|
+
expect(cssVars['--persona-tool-bubble-shadow']).toBe('none');
|
|
142
|
+
expect(cssVars['--persona-reasoning-bubble-shadow']).toBe('none');
|
|
143
|
+
expect(cssVars['--persona-message-user-shadow']).toBe('none');
|
|
144
|
+
expect(cssVars['--persona-message-assistant-shadow']).toBe('none');
|
|
145
|
+
expect(cssVars['--persona-composer-shadow']).toBe('none');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('lets config.toolCall.shadow override theme tool bubble shadow on the root element', () => {
|
|
149
|
+
const el = document.createElement('div');
|
|
150
|
+
applyThemeVariables(el, {
|
|
151
|
+
colorScheme: 'light',
|
|
152
|
+
theme: { toolBubbleShadow: '0 1px 2px rgba(255,0,0,0.5)' },
|
|
153
|
+
toolCall: { shadow: 'none' },
|
|
154
|
+
} as any);
|
|
155
|
+
expect(el.style.getPropertyValue('--persona-tool-bubble-shadow').trim()).toBe('none');
|
|
156
|
+
});
|
|
125
157
|
});
|
package/src/utils/theme.ts
CHANGED
|
@@ -220,6 +220,14 @@ export const applyThemeVariables = (
|
|
|
220
220
|
for (const [name, value] of Object.entries(cssVars)) {
|
|
221
221
|
element.style.setProperty(name, value);
|
|
222
222
|
}
|
|
223
|
+
|
|
224
|
+
const toolCallShadow = (config as AgentWidgetConfig | undefined)?.toolCall?.shadow;
|
|
225
|
+
if (toolCallShadow !== undefined) {
|
|
226
|
+
element.style.setProperty(
|
|
227
|
+
'--persona-tool-bubble-shadow',
|
|
228
|
+
toolCallShadow.trim() === '' ? 'none' : toolCallShadow
|
|
229
|
+
);
|
|
230
|
+
}
|
|
223
231
|
};
|
|
224
232
|
|
|
225
233
|
export const createThemeObserver = (
|
package/src/utils/tokens.ts
CHANGED
|
@@ -271,6 +271,7 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
271
271
|
background: 'semantic.colors.primary',
|
|
272
272
|
text: 'semantic.colors.textInverse',
|
|
273
273
|
borderRadius: 'palette.radius.lg',
|
|
274
|
+
shadow: 'palette.shadows.sm',
|
|
274
275
|
},
|
|
275
276
|
assistant: {
|
|
276
277
|
background: 'semantic.colors.container',
|
|
@@ -280,6 +281,15 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
|
|
|
280
281
|
shadow: 'palette.shadows.sm',
|
|
281
282
|
},
|
|
282
283
|
},
|
|
284
|
+
toolBubble: {
|
|
285
|
+
shadow: 'palette.shadows.sm',
|
|
286
|
+
},
|
|
287
|
+
reasoningBubble: {
|
|
288
|
+
shadow: 'palette.shadows.sm',
|
|
289
|
+
},
|
|
290
|
+
composer: {
|
|
291
|
+
shadow: 'none',
|
|
292
|
+
},
|
|
283
293
|
markdown: {
|
|
284
294
|
inlineCode: {
|
|
285
295
|
background: 'semantic.colors.container',
|
|
@@ -637,6 +647,8 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
637
647
|
cssVars['--persona-components-message-user-background'] ?? cssVars['--persona-accent'];
|
|
638
648
|
cssVars['--persona-message-user-text'] =
|
|
639
649
|
cssVars['--persona-components-message-user-text'] ?? cssVars['--persona-text-inverse'];
|
|
650
|
+
cssVars['--persona-message-user-shadow'] =
|
|
651
|
+
cssVars['--persona-components-message-user-shadow'] ?? '0 5px 15px rgba(15, 23, 42, 0.08)';
|
|
640
652
|
cssVars['--persona-message-assistant-bg'] =
|
|
641
653
|
cssVars['--persona-components-message-assistant-background'] ?? cssVars['--persona-surface'];
|
|
642
654
|
cssVars['--persona-message-assistant-text'] =
|
|
@@ -646,6 +658,13 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
|
|
|
646
658
|
cssVars['--persona-message-assistant-shadow'] =
|
|
647
659
|
cssVars['--persona-components-message-assistant-shadow'] ?? '0 1px 2px 0 rgb(0 0 0 / 0.05)';
|
|
648
660
|
|
|
661
|
+
cssVars['--persona-tool-bubble-shadow'] =
|
|
662
|
+
cssVars['--persona-components-toolBubble-shadow'] ?? '0 5px 15px rgba(15, 23, 42, 0.08)';
|
|
663
|
+
cssVars['--persona-reasoning-bubble-shadow'] =
|
|
664
|
+
cssVars['--persona-components-reasoningBubble-shadow'] ?? '0 5px 15px rgba(15, 23, 42, 0.08)';
|
|
665
|
+
cssVars['--persona-composer-shadow'] =
|
|
666
|
+
cssVars['--persona-components-composer-shadow'] ?? 'none';
|
|
667
|
+
|
|
649
668
|
cssVars['--persona-md-inline-code-bg'] =
|
|
650
669
|
cssVars['--persona-components-markdown-inlineCode-background'] ?? cssVars['--persona-container'];
|
|
651
670
|
cssVars['--persona-md-inline-code-color'] =
|