@runtypelabs/persona 4.23.2 → 4.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/animations/glyph-cycle.d.cts +1 -1
  2. package/dist/animations/glyph-cycle.d.ts +1 -1
  3. package/dist/animations/{types-CI7OckWI.d.cts → types-Db61aI9J.d.cts} +2 -0
  4. package/dist/animations/{types-CI7OckWI.d.ts → types-Db61aI9J.d.ts} +2 -0
  5. package/dist/animations/wipe.d.cts +1 -1
  6. package/dist/animations/wipe.d.ts +1 -1
  7. package/dist/animations-extra.d.cts +2 -0
  8. package/dist/animations-extra.d.ts +2 -0
  9. package/dist/approval-ui-3NMYNXBD.js +1 -0
  10. package/dist/approval-ui.cjs +2 -2
  11. package/dist/approval-ui.d.cts +215 -37
  12. package/dist/approval-ui.d.ts +215 -37
  13. package/dist/approval-ui.js +2 -2
  14. package/dist/{artifacts-ui-F4N6VMKF.js → artifacts-ui-IGB5YKLO.js} +4 -4
  15. package/dist/artifacts-ui.d.cts +210 -25
  16. package/dist/artifacts-ui.d.ts +210 -25
  17. package/dist/{chunk-NIKYKSNZ.js → chunk-7CO4T5KB.js} +1 -1
  18. package/dist/codegen.cjs +11 -11
  19. package/dist/codegen.js +13 -13
  20. package/dist/context-mentions.d.cts +210 -25
  21. package/dist/context-mentions.d.ts +210 -25
  22. package/dist/event-stream-view.d.cts +210 -25
  23. package/dist/event-stream-view.d.ts +210 -25
  24. package/dist/forms-ui.d.cts +245 -27
  25. package/dist/forms-ui.d.ts +245 -27
  26. package/dist/history-view.d.cts +2 -0
  27. package/dist/history-view.d.ts +2 -0
  28. package/dist/index.cjs +70 -69
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +270 -39
  31. package/dist/index.d.ts +270 -39
  32. package/dist/index.global.js +57 -54
  33. package/dist/index.global.js.map +1 -1
  34. package/dist/index.js +70 -69
  35. package/dist/index.js.map +1 -1
  36. package/dist/install.global.js +1 -1
  37. package/dist/install.global.js.map +1 -1
  38. package/dist/launcher.global.js +2 -2
  39. package/dist/launcher.global.js.map +1 -1
  40. package/dist/session-reconnect.d.cts +210 -25
  41. package/dist/session-reconnect.d.ts +210 -25
  42. package/dist/smart-dom-reader.d.cts +210 -25
  43. package/dist/smart-dom-reader.d.ts +210 -25
  44. package/dist/theme-editor-preview.cjs +74 -73
  45. package/dist/theme-editor-preview.d.cts +217 -25
  46. package/dist/theme-editor-preview.d.ts +217 -25
  47. package/dist/theme-editor-preview.js +51 -50
  48. package/dist/theme-editor.cjs +10 -10
  49. package/dist/theme-editor.d.cts +230 -27
  50. package/dist/theme-editor.d.ts +230 -27
  51. package/dist/theme-editor.js +10 -10
  52. package/dist/theme-reference.cjs +1 -1
  53. package/dist/theme-reference.d.cts +1522 -11
  54. package/dist/theme-reference.d.ts +1522 -11
  55. package/dist/theme-reference.js +1 -1
  56. package/dist/widget.css +1 -1
  57. package/package.json +3 -2
  58. package/src/__fixtures__/defaults-parity.v4.json +776 -0
  59. package/src/approval-ui-entry.ts +0 -1
  60. package/src/approval-ui-loader.ts +5 -4
  61. package/src/approval-ui.ts +0 -1
  62. package/src/client-identity-proof.test.ts +193 -0
  63. package/src/client-session-warm.test.ts +216 -0
  64. package/src/client-visitor-history.test.ts +6 -0
  65. package/src/client.ts +122 -30
  66. package/src/codegen.test.ts +24 -0
  67. package/src/components/activity-row.test.ts +100 -0
  68. package/src/components/activity-row.ts +136 -0
  69. package/src/components/approval-actions.test.ts +8 -5
  70. package/src/components/approval-actions.ts +19 -6
  71. package/src/components/approval-bubble.test.ts +56 -9
  72. package/src/components/approval-bubble.ts +36 -41
  73. package/src/components/composer-builder.ts +5 -2
  74. package/src/components/composer-parts.ts +10 -2
  75. package/src/components/header-builder.test.ts +32 -0
  76. package/src/components/header-builder.ts +7 -4
  77. package/src/components/header-layouts.test.ts +12 -0
  78. package/src/components/header-layouts.ts +3 -2
  79. package/src/components/launcher.ts +11 -2
  80. package/src/components/message-bubble.test.ts +22 -0
  81. package/src/components/message-bubble.ts +7 -3
  82. package/src/components/panel.test.ts +52 -1
  83. package/src/components/panel.ts +47 -8
  84. package/src/components/pill-composer-builder.test.ts +2 -0
  85. package/src/components/pill-composer-builder.ts +0 -1
  86. package/src/components/reasoning-bubble.ts +29 -17
  87. package/src/components/suggestions.test.ts +1 -0
  88. package/src/components/suggestions.ts +0 -16
  89. package/src/components/tool-bubble.ts +131 -114
  90. package/src/components/tool-details.test.ts +87 -0
  91. package/src/components/tool-details.ts +102 -0
  92. package/src/components/welcome.test.ts +8 -0
  93. package/src/components/welcome.ts +4 -2
  94. package/src/defaults-parity.test.ts +158 -0
  95. package/src/defaults.test.ts +69 -0
  96. package/src/defaults.ts +128 -49
  97. package/src/generated/runtype-openapi-contract.ts +2 -2
  98. package/src/index-core.ts +2 -0
  99. package/src/install.test.ts +24 -0
  100. package/src/install.ts +3 -1
  101. package/src/launcher-global.ts +2 -1
  102. package/src/launcher-variants.test.ts +52 -0
  103. package/src/runtime/init-update-reset.test.ts +21 -0
  104. package/src/session.ts +29 -6
  105. package/src/styles/widget-styles.test.ts +19 -0
  106. package/src/styles/widget.css +295 -23
  107. package/src/theme-editor/index.ts +2 -0
  108. package/src/theme-editor/preview-utils.test.ts +8 -0
  109. package/src/theme-editor/preview-utils.ts +7 -3
  110. package/src/theme-editor/sections.test.ts +31 -0
  111. package/src/theme-editor/sections.ts +55 -1
  112. package/src/theme-editor/state-preferences.test.ts +49 -0
  113. package/src/theme-editor/state.ts +73 -15
  114. package/src/theme-reference.test.ts +20 -0
  115. package/src/theme-reference.ts +11 -5
  116. package/src/tool-call-display-defaults.test.ts +33 -1
  117. package/src/types/theme.ts +80 -3
  118. package/src/types.ts +136 -22
  119. package/src/ui.activity-row.test.ts +91 -0
  120. package/src/ui.approval-plugin.test.ts +63 -0
  121. package/src/ui.composer-compact.test.ts +24 -2
  122. package/src/ui.composer-placement.test.ts +23 -0
  123. package/src/ui.detached-panel.test.ts +33 -6
  124. package/src/ui.docked.test.ts +19 -0
  125. package/src/ui.header-update-stability.test.ts +25 -0
  126. package/src/ui.identity-proof.test.ts +58 -0
  127. package/src/ui.launcher-teaser.test.ts +25 -0
  128. package/src/ui.message-width.test.ts +17 -2
  129. package/src/ui.reasoning-display.test.ts +92 -0
  130. package/src/ui.rebuild-composer.test.ts +20 -3
  131. package/src/ui.scroll.test.ts +32 -0
  132. package/src/ui.session-init.test.ts +312 -0
  133. package/src/ui.status-indicator.test.ts +82 -0
  134. package/src/ui.suggest-replies.test.ts +11 -0
  135. package/src/ui.ts +363 -74
  136. package/src/ui.v5-defaults.test.ts +144 -0
  137. package/src/ui.welcome.test.ts +92 -3
  138. package/src/utils/__snapshots__/tokens-parity.test.ts.snap +811 -140
  139. package/src/utils/code-generators.ts +14 -0
  140. package/src/utils/composer-compact.test.ts +0 -2
  141. package/src/utils/composer-compact.ts +2 -4
  142. package/src/utils/composer-placement.ts +2 -3
  143. package/src/utils/config-merge.test.ts +81 -5
  144. package/src/utils/config-merge.ts +13 -3
  145. package/src/utils/defaults-provenance.ts +67 -0
  146. package/src/utils/dock.ts +7 -1
  147. package/src/utils/launcher-variant.ts +16 -0
  148. package/src/utils/panel-config.ts +97 -0
  149. package/src/utils/status-indicator.ts +39 -0
  150. package/src/utils/theme.test.ts +182 -0
  151. package/src/utils/theme.ts +131 -18
  152. package/src/utils/tokens.test.ts +122 -1
  153. package/src/utils/tokens.ts +177 -17
  154. package/src/welcome.test.ts +23 -0
  155. package/src/welcome.ts +16 -9
  156. package/dist/approval-ui-K7R5Q5OC.js +0 -1
@@ -1,3 +1,4 @@
1
+ import { CIRCLE_LAUNCHER_TOKENS } from "./launcher-variant";
1
2
  import type {
2
3
  DeepPartial,
3
4
  PersonaTheme,
@@ -9,8 +10,8 @@ import type {
9
10
  SemanticTokens,
10
11
  } from '../types/theme';
11
12
  import {
12
- DEFAULT_FLOATING_LAUNCHER_MAX_WIDTH,
13
13
  DEFAULT_FLOATING_LAUNCHER_WIDTH,
14
+ resolveDefaultsVersion,
14
15
  } from '../defaults';
15
16
 
16
17
  // Detached/docked panel defaults, shared by the panel token defaults, the alias
@@ -25,7 +26,7 @@ const spacing = (() => {
25
26
  return s as Record<0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16 | 20 | 24 | 32 | 40 | 48 | 56 | 64, string>;
26
27
  })();
27
28
 
28
- export const DEFAULT_PALETTE = {
29
+ const DEFAULT_PALETTE_BASE = {
29
30
  colors: {
30
31
  primary: {
31
32
  50: '#ffffff',
@@ -209,7 +210,7 @@ export const DEFAULT_PALETTE = {
209
210
  },
210
211
  };
211
212
 
212
- export const DEFAULT_SEMANTIC: SemanticTokens = {
213
+ const DEFAULT_SEMANTIC_BASE: SemanticTokens = {
213
214
  colors: {
214
215
  primary: 'palette.colors.primary.500',
215
216
  secondary: 'palette.colors.secondary.500',
@@ -257,7 +258,7 @@ export const DEFAULT_SEMANTIC: SemanticTokens = {
257
258
  },
258
259
  };
259
260
 
260
- export const DEFAULT_COMPONENTS: ComponentTokens = {
261
+ const DEFAULT_COMPONENTS_BASE: ComponentTokens = {
261
262
  button: {
262
263
  primary: {
263
264
  // Primary Actions role: solid primary
@@ -305,13 +306,31 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
305
306
  },
306
307
  panel: {
307
308
  width: DEFAULT_FLOATING_LAUNCHER_WIDTH,
308
- maxWidth: DEFAULT_FLOATING_LAUNCHER_MAX_WIDTH,
309
- height: '600px',
310
- maxHeight: 'calc(100vh - 80px)',
309
+ // Matches the existing floating runtime geometry. `maxWidth` and
310
+ // `maxHeight` intentionally do not impose a second cap; ui.ts applies
311
+ // the responsive width and heightOffset rules for this mode.
312
+ maxWidth: 'none',
313
+ height: 'min(640px, max(200px, calc(100vh - 64px)))',
314
+ maxHeight: 'none',
311
315
  borderRadius: 'palette.radius.xl',
312
316
  shadow: 'palette.shadows.xl',
313
317
  inset: DEFAULT_PANEL_INSET,
314
318
  canvasBackground: DEFAULT_PANEL_CANVAS_BACKGROUND,
319
+ modes: {
320
+ floating: {
321
+ border: '1px solid var(--persona-border)',
322
+ shadow: 'palette.shadows.xl',
323
+ borderRadius: 'palette.radius.xl',
324
+ },
325
+ inline: {
326
+ border: '1px solid var(--persona-border)',
327
+ shadow: 'none',
328
+ borderRadius: 'palette.radius.xl',
329
+ },
330
+ docked: { border: 'none', shadow: 'none', borderRadius: 'palette.radius.xl' },
331
+ sidebar: { border: 'none', borderRadius: '0' },
332
+ mobile: { border: 'none', shadow: 'none', borderRadius: '0' },
333
+ },
315
334
  },
316
335
  header: {
317
336
  // Header role: solid primary. Border, subtitle, and action icons stay
@@ -319,11 +338,13 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
319
338
  background: 'palette.colors.primary.500',
320
339
  foreground: 'palette.colors.primary.50',
321
340
  borderRadius: 'palette.radius.xl palette.radius.xl 0 0',
322
- padding: 'semantic.spacing.md',
341
+ padding: '20px 24px',
342
+ minimalPadding: '16px 24px',
323
343
  iconBackground: 'palette.colors.primary.600',
324
344
  iconForeground: 'palette.colors.primary.50',
325
345
  },
326
346
  message: {
347
+ gap: '12px',
327
348
  user: {
328
349
  // User Messages role: solid primary
329
350
  background: 'palette.colors.primary.500',
@@ -532,6 +553,110 @@ export const DEFAULT_COMPONENTS: ComponentTokens = {
532
553
  },
533
554
  };
534
555
 
556
+ /** Shared defaults with a small opt-in V5 overlay. */
557
+ const DEFAULT_PALETTE_GRAY_V4 = DEFAULT_PALETTE_BASE.colors.gray;
558
+ const DEFAULT_PALETTE_GRAY_V5 = {
559
+ 50: '#fafafa', 100: '#f5f5f5', 200: '#e5e5e5', 300: '#d4d4d4',
560
+ 400: '#a3a3a3', 500: '#737373', 600: '#525252', 700: '#404040',
561
+ 800: '#262626', 900: '#171717', 950: '#0a0a0a',
562
+ };
563
+
564
+ export const DEFAULT_PALETTE_V4 = {
565
+ ...DEFAULT_PALETTE_BASE,
566
+ colors: { ...DEFAULT_PALETTE_BASE.colors, gray: DEFAULT_PALETTE_GRAY_V4 },
567
+ };
568
+ export const DEFAULT_PALETTE_V5 = {
569
+ ...DEFAULT_PALETTE_BASE,
570
+ colors: { ...DEFAULT_PALETTE_BASE.colors, gray: DEFAULT_PALETTE_GRAY_V5 },
571
+ radius: { none: '0px', sm: '4px', md: '8px', lg: '12px', xl: '16px', '2xl': '24px', full: '9999px' },
572
+ };
573
+ export const DEFAULT_PALETTE = DEFAULT_PALETTE_V4;
574
+
575
+ export const DEFAULT_SEMANTIC_V4 = DEFAULT_SEMANTIC_BASE;
576
+ export const DEFAULT_SEMANTIC_V5: SemanticTokens = {
577
+ ...DEFAULT_SEMANTIC_BASE,
578
+ colors: {
579
+ ...DEFAULT_SEMANTIC_BASE.colors,
580
+ surface: '#ffffff', background: '#ffffff', container: 'semantic.colors.surface',
581
+ textInverse: '#ffffff',
582
+ },
583
+ typography: { ...DEFAULT_SEMANTIC_BASE.typography, fontSize: '14px', lineHeight: '1.5' },
584
+ };
585
+ export const DEFAULT_SEMANTIC = DEFAULT_SEMANTIC_V4;
586
+
587
+ export const DEFAULT_COMPONENTS_V4 = DEFAULT_COMPONENTS_BASE;
588
+ export const DEFAULT_COMPONENTS_V5: ComponentTokens = {
589
+ ...DEFAULT_COMPONENTS_BASE,
590
+ launcher: CIRCLE_LAUNCHER_TOKENS,
591
+ activity: { rowHeight: "32px", labelSize: "13px", iconSize: "16px", indent: "0px", groupIndent: "0px", groupGap: "0px", groupPadding: "0px", transcriptGap: "0px", responseGap: "12px", bodyPadding: "4px 0", bodySize: "13px", bodyLineHeight: "1.5", bodyFontWeight: "400", sectionGap: "8px", bodySurface: "transparent" },
592
+ toolBubble: { shadow: "none" },
593
+ reasoningBubble: { shadow: "none" },
594
+ input: { ...DEFAULT_COMPONENTS_BASE.input, borderRadius: 'palette.radius.full' },
595
+ introCard: { ...DEFAULT_COMPONENTS_BASE.introCard, title: { fontSize: '22px', fontWeight: '500' } },
596
+ suggestion: {
597
+ chip: { ...DEFAULT_COMPONENTS_BASE.suggestion!.chip, fontWeight: '400' },
598
+ card: { ...DEFAULT_COMPONENTS_BASE.suggestion!.card, fontWeight: '400' },
599
+ list: { ...DEFAULT_COMPONENTS_BASE.suggestion!.list, fontWeight: '400' },
600
+ },
601
+ panel: {
602
+ ...DEFAULT_COMPONENTS_BASE.panel,
603
+ width: 'min(400px, calc(100vw - 24px))',
604
+ height: 'min(704px, calc(100dvh - 104px))',
605
+ borderRadius: 'palette.radius.xl',
606
+ },
607
+ header: {
608
+ ...DEFAULT_COMPONENTS_BASE.header,
609
+ background: 'semantic.colors.container', foreground: 'semantic.colors.text',
610
+ padding: '8px 8px 8px 16px', minimalPadding: '8px 8px 8px 16px',
611
+ minHeight: '48px', borderBottom: 'none',
612
+ iconBackground: 'transparent', iconForeground: 'semantic.colors.text', iconScale: '1',
613
+ controlSize: '28px', controlIconSize: '18px', controlStrokeWidth: '1.5',
614
+ actionIconForeground: 'semantic.colors.textMuted',
615
+ controlBorderRadius: '8px',
616
+ controlHoverBackground: 'color-mix(in srgb, var(--persona-text) 8%, transparent)',
617
+ controlHoverForeground: 'semantic.colors.text',
618
+ controlFocusOutline: '2px solid color-mix(in srgb, var(--persona-text) 50%, transparent)',
619
+ title: { fontSize: '14px', fontWeight: '500', lineHeight: '1.5' },
620
+ },
621
+ message: {
622
+ ...DEFAULT_COMPONENTS_BASE.message,
623
+ gap: '20px', fullscreenGap: '28px', topFadeHeight: '18px',
624
+ user: {
625
+ ...DEFAULT_COMPONENTS_BASE.message.user,
626
+ background: 'palette.colors.gray.100', text: 'semantic.colors.text',
627
+ borderRadius: 'palette.radius.xl', shadow: 'none', padding: '8px 14px',
628
+ fontSize: '14px', lineHeight: '1.5',
629
+ },
630
+ assistant: {
631
+ ...DEFAULT_COMPONENTS_BASE.message.assistant,
632
+ background: 'transparent', border: 'transparent', borderWidth: '0px',
633
+ borderRadius: '0px', shadow: 'none', padding: '0px',
634
+ fontSize: '14px', lineHeight: '1.55',
635
+ },
636
+ },
637
+ composer: {
638
+ ...DEFAULT_COMPONENTS_BASE.composer,
639
+ padding: '8px', fontSize: '15px', lineHeight: '1.5', controlSize: '32px', controlIconSize: '20px',
640
+ sendIconSize: '18px', sendButtonRadius: '9999px', footerBorder: 'none',
641
+ overlayBand: 'linear-gradient(to bottom, transparent, var(--persona-container) 24px)',
642
+ focusBorderColor: 'color-mix(in srgb, var(--persona-text) 28%, var(--persona-border))',
643
+ focusRing: '1px solid color-mix(in srgb, var(--persona-text) 12%, transparent)',
644
+ },
645
+ };
646
+ export const DEFAULT_COMPONENTS = DEFAULT_COMPONENTS_V4;
647
+
648
+ export type ThemeDefaultsVersion = 'v4' | 'v5';
649
+
650
+ export const resolveThemeDefaultsVersion = (future?: { v5Defaults?: boolean }): ThemeDefaultsVersion =>
651
+ resolveDefaultsVersion({ future });
652
+
653
+ export const resolveThemeDefaults = (future?: { v5Defaults?: boolean }) => {
654
+ const version = resolveThemeDefaultsVersion(future);
655
+ return version === 'v5'
656
+ ? { palette: DEFAULT_PALETTE_V5, semantic: DEFAULT_SEMANTIC_V5, components: DEFAULT_COMPONENTS_V5 }
657
+ : { palette: DEFAULT_PALETTE_V4, semantic: DEFAULT_SEMANTIC_V4, components: DEFAULT_COMPONENTS_V4 };
658
+ };
659
+
535
660
  export function resolveTokenValue(theme: PersonaTheme, path: string): string | undefined {
536
661
  if (
537
662
  !path.startsWith('palette.') &&
@@ -673,10 +798,11 @@ export function createTheme(
673
798
  userConfig?: DeepPartial<PersonaTheme>,
674
799
  options: CreateThemeOptions = {}
675
800
  ): PersonaTheme {
801
+ const defaults = resolveThemeDefaults(options.future);
676
802
  const baseTheme: PersonaTheme = {
677
- palette: DEFAULT_PALETTE as PersonaTheme['palette'],
678
- semantic: DEFAULT_SEMANTIC as PersonaTheme['semantic'],
679
- components: DEFAULT_COMPONENTS as PersonaTheme['components'],
803
+ palette: defaults.palette as PersonaTheme['palette'],
804
+ semantic: defaults.semantic as PersonaTheme['semantic'],
805
+ components: defaults.components as PersonaTheme['components'],
680
806
  };
681
807
 
682
808
  let theme: PersonaTheme = {
@@ -738,6 +864,30 @@ export function createTheme(
738
864
  ),
739
865
  } as PersonaTheme;
740
866
 
867
+ // A shared header padding is also the minimal-layout override unless the
868
+ // host supplies the more specific token. Both keys remain emitted CSS vars,
869
+ // so live updates and scheme changes restyle existing header DOM in place.
870
+ const activity = userConfig?.components?.activity;
871
+ for (const kind of ['toolBubble', 'reasoningBubble'] as const) {
872
+ for (const field of ['rowHeight', 'labelSize', 'iconSize', 'indent', 'bodySurface'] as const) {
873
+ if (activity?.[field] !== undefined) theme.components[kind][field] = activity[field];
874
+ }
875
+ }
876
+ const legacySurface = userConfig?.components?.collapsibleWidget?.surface;
877
+ if (legacySurface !== undefined && activity?.bodySurface === undefined) {
878
+ theme.components.activity = { ...theme.components.activity, bodySurface: legacySurface };
879
+ }
880
+
881
+ const suppliedHeader = userConfig?.components?.header;
882
+ if (suppliedHeader?.padding !== undefined && suppliedHeader.minimalPadding === undefined) {
883
+ theme.components.header.minimalPadding = theme.components.header.padding;
884
+ }
885
+
886
+ const suppliedMessage = userConfig?.components?.message;
887
+ if (suppliedMessage?.gap !== undefined && suppliedMessage.fullscreenGap === undefined) {
888
+ theme.components.message.fullscreenGap = theme.components.message.gap;
889
+ }
890
+
741
891
  if (options.validate !== false) {
742
892
  const validation = validateTheme(theme);
743
893
  if (!validation.valid) {
@@ -1224,12 +1374,21 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
1224
1374
  ]);
1225
1375
 
1226
1376
  // Collapsible widget chrome (tool/reasoning/approval bubbles)
1227
- cssVars['--cw-container'] =
1228
- cssVars['--persona-components-collapsibleWidget-container'] ?? cssVars['--persona-surface'];
1229
- cssVars['--cw-surface'] =
1230
- cssVars['--persona-components-collapsibleWidget-surface'] ?? cssVars['--persona-surface'];
1231
- cssVars['--cw-border'] =
1232
- cssVars['--persona-components-collapsibleWidget-border'] ?? cssVars['--persona-border'];
1377
+ const collapsibleWidgetAliases = [
1378
+ ['container', 'surface'],
1379
+ ['surface', 'surface'],
1380
+ ['border', 'border'],
1381
+ ] as const;
1382
+ for (const [name, semanticFallback] of collapsibleWidgetAliases) {
1383
+ const value =
1384
+ cssVars[`--persona-components-collapsibleWidget-${name}`] ??
1385
+ cssVars[`--persona-${semanticFallback}`];
1386
+ if (value !== undefined) {
1387
+ cssVars[`--persona-cw-${name}`] = value;
1388
+ // Kept for custom styles that adopted the original unprefixed aliases.
1389
+ cssVars[`--cw-${name}`] = value;
1390
+ }
1391
+ }
1233
1392
 
1234
1393
  emitAliases(cssVars, [
1235
1394
  ['message-border', 'components-message-border', 'border'],
@@ -1246,6 +1405,7 @@ export function themeToCssVariables(theme: PersonaTheme): Record<string, string>
1246
1405
  ['message-user-font-family', 'components-message-user-fontFamily'],
1247
1406
  ['message-user-line-height', 'components-message-user-lineHeight'],
1248
1407
  ['message-assistant-padding', 'components-message-assistant-padding'],
1408
+ ['message-assistant-border-width', 'components-message-assistant-borderWidth'],
1249
1409
  ['message-assistant-max-width', 'components-message-assistant-maxWidth'],
1250
1410
  ['message-assistant-font-size', 'components-message-assistant-fontSize'],
1251
1411
  ['message-assistant-font-family', 'components-message-assistant-fontFamily'],
@@ -274,3 +274,26 @@ describe("resolveConversationState", () => {
274
274
  expect(resolveConversationState([])).toBe("empty");
275
275
  });
276
276
  });
277
+
278
+ describe("V5 welcome layout defaults", () => {
279
+ it("centers the empty greeting with concise copy and dismisses every variant", () => {
280
+ for (const variant of ["card", "hero", "none"] as const) {
281
+ const resolved = resolveWelcomeConfig(config({ future: { v5Defaults: true }, welcome: { variant } }));
282
+ expect(resolved).toMatchObject({ layout: "centered", align: "center", title: "What can I help with?", subtitle: "", dismiss: "on-first-message", anchor: "bottom" });
283
+ expect(isWelcomeVisible(resolved, [userMessage])).toBe(false);
284
+ }
285
+ });
286
+
287
+ it("keeps explicit fields and legacy copy above V5 defaults", () => {
288
+ const resolved = resolveWelcomeConfig(config({ future: { v5Defaults: true }, copy: { welcomeTitle: "Legacy", welcomeSubtitle: "Scope" }, welcome: { layout: "top", variant: "hero", dismiss: "never", anchor: "bottom", align: "start" } }), true);
289
+ expect(resolved).toMatchObject({ title: "Legacy", subtitle: "Scope", layout: "top", dismiss: "never", anchor: "bottom", align: "start" });
290
+ });
291
+
292
+ it("makes centered fullscreen geometry available in either default mode", () => {
293
+ for (const v5Defaults of [false, true]) {
294
+ const resolved = resolveWelcomeConfig(config({ future: { v5Defaults }, welcome: { layout: "centered" } }), true);
295
+ expect(resolved.anchor).toBe("center");
296
+ expect(resolveWelcomeConfig(config({ future: { v5Defaults }, welcome: { layout: "centered", anchor: "bottom" } }), true).anchor).toBe("bottom");
297
+ }
298
+ });
299
+ });
package/src/welcome.ts CHANGED
@@ -55,6 +55,7 @@ export interface ResolvedWelcomeConfig {
55
55
  * Optional on the interface, always populated by `resolveWelcomeConfig`:
56
56
  * a plugin literal built against an older minor must still type-check.
57
57
  */
58
+ layout?: "top" | "centered";
58
59
  anchor?: AgentWidgetWelcomeAnchor;
59
60
  /** Percentage string; validated, falls back to "44%". */
60
61
  anchorComposerTop?: string;
@@ -80,10 +81,14 @@ const warnOnce = (config: AgentWidgetConfig | undefined, messages: string[]) =>
80
81
  * `copy` alias, else the default above.
81
82
  */
82
83
  export const resolveWelcomeConfig = (
83
- config?: AgentWidgetConfig
84
+ config?: AgentWidgetConfig,
85
+ fullscreen = config?.launcher?.fullHeight === true &&
86
+ !config.launcher.sidebarMode && config.launcher.mountMode !== "docked"
84
87
  ): ResolvedWelcomeConfig => {
85
88
  const welcome = config?.welcome;
86
89
  const copy = config?.copy;
90
+ const v5 = config?.future?.v5Defaults === true;
91
+ const layout = welcome?.layout ?? (v5 ? "centered" : "top");
87
92
 
88
93
  const variant: AgentWidgetWelcomeVariant = isSet(welcome, "variant")
89
94
  ? welcome!.variant!
@@ -91,13 +96,14 @@ export const resolveWelcomeConfig = (
91
96
  ? "none"
92
97
  : "card";
93
98
 
94
- // Hero IS the greeting: `dismiss` is forced and `message` is suppressed.
99
+ // Legacy V4 heroes force dismissal; opting into layout makes it configurable.
100
+ // A hero remains the greeting, so its separate message is always suppressed.
95
101
  const dismiss: AgentWidgetWelcomeDismiss =
96
- variant === "hero"
102
+ variant === "hero" && !v5 && welcome?.layout === undefined
97
103
  ? "on-first-message"
98
104
  : isSet(welcome, "dismiss")
99
105
  ? welcome!.dismiss!
100
- : "never";
106
+ : v5 || variant === "hero" ? "on-first-message" : "never";
101
107
 
102
108
  const conflicts: string[] = [];
103
109
  if (isSet(welcome, "title") && isSet(copy, "welcomeTitle")) {
@@ -120,14 +126,14 @@ export const resolveWelcomeConfig = (
120
126
  'welcome.message is ignored when welcome.variant is "hero": the hero is the greeting.'
121
127
  );
122
128
  }
123
- if (variant === "hero" && isSet(welcome, "dismiss") && welcome!.dismiss !== "on-first-message") {
129
+ if (!v5 && welcome?.layout === undefined && variant === "hero" && isSet(welcome, "dismiss") && welcome!.dismiss !== "on-first-message") {
124
130
  conflicts.push(
125
131
  'welcome.dismiss is pinned to "on-first-message" when welcome.variant is "hero".'
126
132
  );
127
133
  }
128
134
 
129
135
  const anchor: AgentWidgetWelcomeAnchor =
130
- welcome?.anchor === "center" ? "center" : "bottom";
136
+ welcome?.anchor ?? (layout === "centered" && fullscreen ? "center" : "bottom");
131
137
  const anchorTopValid = parseAnchorFraction(welcome?.anchorComposerTop) !== null;
132
138
  if (isSet(welcome, "anchorComposerTop") && !anchorTopValid) {
133
139
  conflicts.push(
@@ -147,16 +153,16 @@ export const resolveWelcomeConfig = (
147
153
  return {
148
154
  title: isSet(welcome, "title")
149
155
  ? welcome!.title!
150
- : copy?.welcomeTitle ?? DEFAULT_WELCOME_TITLE,
156
+ : copy?.welcomeTitle ?? (v5 ? "What can I help with?" : DEFAULT_WELCOME_TITLE),
151
157
  kicker: welcome?.kicker ?? "",
152
158
  subtitle: isSet(welcome, "subtitle")
153
159
  ? welcome!.subtitle!
154
- : copy?.welcomeSubtitle ?? DEFAULT_WELCOME_SUBTITLE,
160
+ : copy?.welcomeSubtitle ?? (v5 ? "" : DEFAULT_WELCOME_SUBTITLE),
155
161
  icon: welcome?.icon,
156
162
  align:
157
163
  welcome?.align === "start" || welcome?.align === "center"
158
164
  ? welcome.align
159
- : undefined,
165
+ : layout === "centered" ? "center" : undefined,
160
166
  iconPlacement:
161
167
  welcome?.icon && typeof welcome.icon !== "function" &&
162
168
  welcome.icon.placement === "inline"
@@ -165,6 +171,7 @@ export const resolveWelcomeConfig = (
165
171
  variant,
166
172
  dismiss,
167
173
  message: variant === "hero" ? undefined : welcome?.message,
174
+ layout,
168
175
  anchor,
169
176
  anchorComposerTop: anchorTopValid
170
177
  ? welcome!.anchorComposerTop!
@@ -1 +0,0 @@
1
- import{a as E,g as P}from"./chunk-NQLDCJAP.js";import{a as x}from"./chunk-7NQ4ZTHF.js";import{b as q,c as $}from"./chunk-Q735PSZL.js";import{a}from"./chunk-76IELU7F.js";var R=()=>{},z=t=>{R=t.webMcpToolTitle},I=t=>R(t);import{ChevronDown as Y,ChevronUp as ee,ShieldAlert as te,ShieldCheck as K,ShieldX as _}from"lucide";var k=new Map,B=t=>{let o=(t.startsWith(E)?t.slice(E.length):t).replace(/([a-z0-9])([A-Z])/g,"$1 $2").split(/[_\-\s.]+/).filter(Boolean);if(o.length===0)return t;let e=o.join(" ").toLowerCase();return e.charAt(0).toUpperCase()+e.slice(1)},F=t=>t?.approval!==!1?t?.approval:void 0,X=(t,r)=>{let o=F(r)?.detailsDisplay??"collapsed";return k.get(t)??o==="expanded"},j=(t,r,o)=>{let e=F(o);t.setAttribute("aria-expanded",r?"true":"false");let u=t.querySelector("[data-approval-details-label]");u&&(u.textContent=r?e?.hideDetailsLabel??"Hide details":e?.showDetailsLabel??"Show details");let i=t.querySelector("[data-approval-details-chevron]");if(i){i.innerHTML="";let g=x(r?ee:Y,14,"currentColor",2);g&&i.appendChild(g)}},V=(t,r,o)=>{let e=r.querySelector('button[data-bubble-type="approval"]'),u=r.querySelector("[data-approval-details]");if(!e||!u)return;let i=X(t,o);j(e,i,o),u.style.display=i?"":"none"};var Z=(t,r)=>{let o=t.approval,e=r?.approval!==!1?r?.approval:void 0,u=o?.status==="pending",i=a("div",["persona-approval-bubble","persona-w-full","persona-rounded-2xl","persona-border","persona-shadow-sm","persona-overflow-hidden"].join(" "));if(i.id=`bubble-${t.id}`,i.setAttribute("data-message-id",t.id),i.style.backgroundColor=e?.backgroundColor??"var(--persona-approval-bg, #fefce8)",i.style.borderColor=e?.borderColor??"var(--persona-approval-border, #fef08a)",i.style.boxShadow=e?.shadow!==void 0?e.shadow.trim()===""?"none":e.shadow:"var(--persona-approval-shadow, 0 5px 15px rgba(15, 23, 42, 0.08))",!o)return i;let g=a("div","persona-flex persona-items-start persona-gap-3 persona-px-4 persona-py-3"),l=a("div","persona-flex-shrink-0 persona-mt-0.5");l.setAttribute("data-approval-icon","true");let v=o.status==="denied"?_:o.status==="timeout"?te:K,C=o.status==="approved"?"var(--persona-feedback-success, #16a34a)":o.status==="denied"?"var(--persona-feedback-error, #dc2626)":o.status==="timeout"?"var(--persona-feedback-warning, #ca8a04)":e?.titleColor??"currentColor",A=x(v,20,C,2);A&&l.appendChild(A);let m=a("div","persona-flex-1 persona-min-w-0"),f=a("div","persona-flex persona-items-center persona-gap-2"),w=a("span","persona-text-sm persona-font-medium persona-text-persona-primary");if(e?.titleColor&&(w.style.color=e.titleColor),w.textContent=e?.title??"Approval Required",f.appendChild(w),!u){let s=a("span","persona-inline-flex persona-items-center persona-px-2 persona-py-0.5 persona-rounded-full persona-text-xs persona-font-medium");s.setAttribute("data-approval-status",o.status),o.status==="approved"?(s.style.backgroundColor="var(--persona-palette-colors-success-100, #dcfce7)",s.style.color="var(--persona-palette-colors-success-700, #15803d)",s.textContent="Approved"):o.status==="denied"?(s.style.backgroundColor="var(--persona-palette-colors-error-100, #fee2e2)",s.style.color="var(--persona-palette-colors-error-700, #b91c1c)",s.textContent="Denied"):o.status==="timeout"&&(s.style.backgroundColor="var(--persona-palette-colors-warning-100, #fef3c7)",s.style.color="var(--persona-palette-colors-warning-700, #b45309)",s.textContent="Timeout"),f.appendChild(s)}m.appendChild(f);let y=o.toolType==="webmcp"||o.toolName.startsWith(E)?I(o.toolName):void 0,N=e?.formatDescription?.({toolName:o.toolName,toolType:o.toolType,description:o.description,parameters:o.parameters,...y?{displayTitle:y}:{},...o.reason?{reason:o.reason}:{}}),D=!o.toolName,H=N||(D?o.description:`The assistant wants to use \u201C${y??B(o.toolName)}\u201D.`),h=a("p","persona-text-sm persona-mt-0.5 persona-text-persona-muted");if(h.setAttribute("data-approval-summary","true"),e?.descriptionColor&&(h.style.color=e.descriptionColor),h.textContent=H,m.appendChild(h),o.reason){let s=a("p","persona-text-sm persona-mt-1 persona-text-persona-muted");s.setAttribute("data-approval-reason","true"),e?.reasonColor?s.style.color=e.reasonColor:e?.descriptionColor&&(s.style.color=e.descriptionColor);let n=a("span","persona-font-medium");n.textContent=`${e?.reasonLabel??"Agent's stated reason:"} `,s.appendChild(n),s.appendChild(document.createTextNode(o.reason)),m.appendChild(s)}let W=e?.detailsDisplay??"collapsed",M=!!o.description&&!D,S=M||!!o.parameters;if(W!=="hidden"&&S){let s=X(t.id,r),n=a("button","persona-inline-flex persona-items-center persona-gap-1 persona-mt-1 persona-p-0 persona-border-none persona-bg-transparent persona-text-xs persona-font-medium persona-cursor-pointer persona-text-persona-muted");n.type="button",n.setAttribute("data-expand-header","true"),n.setAttribute("data-bubble-type","approval"),e?.descriptionColor&&(n.style.color=e.descriptionColor);let p=a("span");p.setAttribute("data-approval-details-label","true");let b=a("span","persona-inline-flex persona-items-center");b.setAttribute("data-approval-details-chevron","true"),n.append(p,b),j(n,s,r),m.appendChild(n);let c=a("div");if(c.setAttribute("data-approval-details","true"),c.style.display=s?"":"none",M){let d=a("p","persona-text-sm persona-mt-1 persona-text-persona-muted");e?.descriptionColor&&(d.style.color=e.descriptionColor),d.textContent=o.description,c.appendChild(d)}if(o.parameters){let d=a("pre","persona-mt-2 persona-text-xs persona-p-2 persona-rounded persona-overflow-x-auto persona-max-h-32 persona-bg-persona-container persona-text-persona-primary");e?.parameterBackgroundColor&&(d.style.backgroundColor=e.parameterBackgroundColor),e?.parameterTextColor&&(d.style.color=e.parameterTextColor),d.style.fontSize="0.75rem",d.style.lineHeight="1rem",d.textContent=P(o.parameters),c.appendChild(d)}m.appendChild(c)}if(u){let s=a("div","persona-flex persona-gap-2 persona-mt-2");s.setAttribute("data-approval-buttons","true");let n=a("button","persona-inline-flex persona-items-center persona-px-3 persona-py-1.5 persona-rounded-md persona-text-xs persona-font-medium persona-border-none persona-cursor-pointer");n.type="button",n.style.backgroundColor=e?.approveButtonColor??"var(--persona-approval-approve-bg, #22c55e)",n.style.color=e?.approveButtonTextColor??"#ffffff",n.setAttribute("data-approval-action","approve");let p=x(K,14,e?.approveButtonTextColor??"#ffffff",2);p&&(p.style.marginRight="4px",n.appendChild(p));let b=document.createTextNode(e?.approveLabel??"Approve");n.appendChild(b);let c=a("button","persona-inline-flex persona-items-center persona-px-3 persona-py-1.5 persona-rounded-md persona-text-xs persona-font-medium persona-cursor-pointer");c.type="button",c.style.backgroundColor=e?.denyButtonColor??"transparent",c.style.color=e?.denyButtonTextColor??"var(--persona-feedback-error, #dc2626)",c.style.border=`1px solid ${e?.denyButtonTextColor?e.denyButtonTextColor:"var(--persona-palette-colors-error-200, #fca5a5)"}`,c.setAttribute("data-approval-action","deny");let d=x(_,14,e?.denyButtonTextColor??"var(--persona-feedback-error, #dc2626)",2);d&&(d.style.marginRight="4px",c.appendChild(d));let L=document.createTextNode(e?.denyLabel??"Deny");c.appendChild(L),s.append(n,c),m.appendChild(s)}return g.append(l,m),i.appendChild(g),i};import{Ban as oe,ChevronDown as G,ShieldCheck as ne}from"lucide";var re=()=>({keyHandlers:new Map,popovers:new Map,pendingOrder:[],latestPendingApprovalId:null}),J=(t,r)=>{let o=t.keyHandlers.get(r);o&&(document.removeEventListener("keydown",o),t.keyHandlers.delete(r));let e=t.popovers.get(r);e&&(e.destroy(),t.popovers.delete(r))},T=(t,r)=>{J(t,r);let o=t.pendingOrder.indexOf(r);o!==-1&&t.pendingOrder.splice(o,1),t.latestPendingApprovalId===r&&(t.latestPendingApprovalId=t.pendingOrder.length?t.pendingOrder[t.pendingOrder.length-1]:null)},ae=t=>t?.approval!==!1?t?.approval:void 0,se=(t,r)=>{let o=r?.detailsDisplay??"collapsed";return k.get(t)??o==="expanded"},U=t=>{let r=a("span","persona-approval-kbd");return r.textContent=t,r},pe=(t,r)=>{let o=a("span","persona-approval-title");r?.titleColor&&(o.style.color=r.titleColor);let u=t.toolType==="webmcp"||t.toolName.startsWith(E)?I(t.toolName):void 0,i=r?.formatDescription?.({toolName:t.toolName,toolType:t.toolType,description:t.description??"",parameters:t.parameters,...u?{displayTitle:u}:{},...t.reason?{reason:t.reason}:{}});if(i)return o.textContent=i,o;let g=u??B(t.toolName),l=t.toolType&&t.toolType!=="webmcp"?t.toolType:null;o.append("The assistant wants to use ");let v=document.createElement("strong");if(v.textContent=g,o.appendChild(v),l){o.append(" from ");let C=document.createElement("strong");C.textContent=l,o.appendChild(C)}return o},le=t=>{let r=a("div","persona-approval-resolved"),o=x(oe,15,"currentColor",2);o&&r.appendChild(o);let e=a("span","persona-approval-resolved-name");return e.textContent=t.toolName?B(t.toolName):"Tool",r.append(e,document.createTextNode(t.status==="timeout"?" timed out":" denied")),r},ie=(t,r,o,e,u,i,g)=>{let l=a("div","persona-approval-card persona-shadow-sm");l.id=`bubble-${r.id}`,l.setAttribute("data-message-id",r.id),l.setAttribute("data-bubble-type","approval"),e?.backgroundColor&&(l.style.background=e.backgroundColor),e?.borderColor&&(l.style.borderColor=e.borderColor),e?.shadow!==void 0&&(l.style.boxShadow=e.shadow.trim()===""?"none":e.shadow);let v=e?.detailsDisplay??"collapsed",C=!!o.description&&v!=="hidden",A=o.parameters!=null&&v!=="hidden",m=C||A,f=m&&se(r.id,e),w=e?.showDetailsLabel??"Show details",O=e?.hideDetailsLabel??"Hide details",y=a("button","persona-approval-head");y.type="button",m?(y.setAttribute("data-action","toggle-params"),y.setAttribute("aria-expanded",f?"true":"false"),y.setAttribute("aria-label",f?O:w)):y.setAttribute("data-static","true");let N=a("span","persona-approval-logo"),D=x(ne,16,"currentColor",2);D&&N.appendChild(D),y.appendChild(N);let H=pe(o,e);if(m){let n=a("span","persona-approval-toggle");n.setAttribute("aria-hidden","true");let p=x(G,14,"currentColor",2);p&&n.appendChild(p),H.append(" "),H.appendChild(n)}y.appendChild(H),l.appendChild(y);let h=a("div","persona-approval-body");if(m){let n=a("div","persona-approval-details");if(n.setAttribute("data-role","params"),n.hidden=!f,C){let p=a("p","persona-approval-desc");e?.descriptionColor&&(p.style.color=e.descriptionColor),p.textContent=o.description,n.appendChild(p)}if(A){let p=a("pre","persona-approval-params");e?.parameterBackgroundColor&&(p.style.background=e.parameterBackgroundColor),e?.parameterTextColor&&(p.style.color=e.parameterTextColor),p.textContent=P(o.parameters),n.appendChild(p)}h.appendChild(n)}if(o.reason){let n=a("p","persona-approval-reason");e?.reasonColor?n.style.color=e.reasonColor:e?.descriptionColor&&(n.style.color=e.descriptionColor);let p=a("span","persona-approval-reason-label");p.textContent=`${e?.reasonLabel??"Agent's stated reason:"} `,n.append(p,document.createTextNode(o.reason)),h.appendChild(n)}let W=a("div","persona-approval-actions"),M=null,S=n=>{e?.approveButtonColor&&(n.style.background=e.approveButtonColor),e?.approveButtonTextColor&&(n.style.color=e.approveButtonTextColor)},s=a("button","persona-approval-deny");if(s.type="button",s.setAttribute("data-action","deny"),e?.denyButtonColor&&(s.style.background=e.denyButtonColor),e?.denyButtonTextColor&&(s.style.color=e.denyButtonTextColor),s.append(e?.denyLabel??"Deny"),g){let n=a("div","persona-approval-split"),p=a("button","persona-approval-primary");p.type="button",p.setAttribute("data-action","always"),S(p),p.append(e?.approveLabel??"Always allow",U("\u23CE"));let b=a("button","persona-approval-caret");b.type="button",b.setAttribute("data-action","toggle-menu"),b.setAttribute("aria-label","More options"),S(b);let c=x(G,15,"currentColor",2);c&&b.appendChild(c),n.append(p,b),W.append(n,s),s.append(U("Esc"));let d=a("div","persona-approval-menu"),L=a("button","persona-approval-menu-item");L.type="button",L.append("Allow once",U("\u2318\u23CE")),d.appendChild(L),M=q({anchor:n,content:d,placement:"bottom-start",matchAnchorWidth:!0}),t.popovers.set(r.id,M),L.addEventListener("click",()=>{T(t,r.id),u()})}else{let n=a("button","persona-approval-primary persona-approval-primary--solo");n.type="button",n.setAttribute("data-action","allow"),S(n),n.append(e?.approveLabel??"Allow"),W.append(n,s)}return h.appendChild(W),l.appendChild(h),l.addEventListener("click",n=>{let p=n.target instanceof Element?n.target.closest("[data-action]"):null;if(!p)return;let b=p.getAttribute("data-action");if(b==="toggle-params"){let c=l.querySelector('[data-role="params"]');if(c){let d=c.hidden;c.hidden=!d,y.setAttribute("aria-expanded",d?"true":"false"),y.setAttribute("aria-label",d?O:w),k.set(r.id,d)}return}if(b==="toggle-menu"){M?.toggle();return}if(b==="always"){T(t,r.id),u({remember:!0});return}if(b==="allow"){T(t,r.id),u();return}if(b==="deny"){T(t,r.id),i();return}}),l},Q=()=>{let t=re();return{plugin:{id:"persona-built-in-approval",renderApproval:({message:e,approve:u,deny:i,config:g})=>{let l=e?.approval;if(!l)return null;let v=ae(g);if(l.status!=="pending"){if(T(t,e.id),l.status==="approved"){let m=document.createElement("div");return m.style.display="none",m}return le(l)}J(t,e.id);let C=v?.enableAlwaysAllow===!0,A=ie(t,e,l,v,u,i,C);if(C){t.pendingOrder.includes(e.id)||t.pendingOrder.push(e.id),t.latestPendingApprovalId=t.pendingOrder[t.pendingOrder.length-1];let m=f=>{$(f)||e.id===t.latestPendingApprovalId&&(f.key!=="Escape"&&f.key!=="Enter"||(f.preventDefault(),f.stopImmediatePropagation(),T(t,e.id),f.key==="Escape"?i():f.metaKey||f.ctrlKey?u():u({remember:!0})))};t.keyHandlers.set(e.id,m),document.addEventListener("keydown",m)}return A}},teardown:()=>{for(let e of[...t.keyHandlers.keys(),...t.popovers.keys()])T(t,e);t.latestPendingApprovalId=null}}};export{k as approvalDetailsExpansionState,Z as createApprovalBubble,Q as createBuiltInApprovalPlugin,B as humanizeToolName,z as initApprovalUi,V as updateApprovalDetailsUI};