botframework-webchat-fluent-theme 4.18.1-main.20250804.93043a9 → 4.18.1-main.20250916.f2f7323

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 (33) hide show
  1. package/dist/botframework-webchat-fluent-theme.css.map +1 -1
  2. package/dist/botframework-webchat-fluent-theme.d.mts +6 -5
  3. package/dist/botframework-webchat-fluent-theme.d.ts +6 -5
  4. package/dist/botframework-webchat-fluent-theme.development.css.map +1 -1
  5. package/dist/botframework-webchat-fluent-theme.development.js +8 -8
  6. package/dist/botframework-webchat-fluent-theme.development.js.map +1 -1
  7. package/dist/botframework-webchat-fluent-theme.js +1 -1
  8. package/dist/botframework-webchat-fluent-theme.js.map +1 -1
  9. package/dist/botframework-webchat-fluent-theme.mjs +1 -1
  10. package/dist/botframework-webchat-fluent-theme.mjs.map +1 -1
  11. package/dist/botframework-webchat-fluent-theme.production.min.css.map +1 -1
  12. package/dist/botframework-webchat-fluent-theme.production.min.js +8 -8
  13. package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
  14. package/package.json +8 -7
  15. package/src/buildInfo.ts +9 -0
  16. package/src/components/activity/ActivityDecorator.module.css +0 -237
  17. package/src/components/activity/ActivityDecorator.tsx +17 -12
  18. package/src/components/activity/ActivityLoader.module.css +1 -1
  19. package/src/components/activity/ActivityLoader.tsx +19 -6
  20. package/src/components/activity/CopilotMessageHeader.tsx +22 -7
  21. package/src/components/activity/PartGroupingDecorator.module.css +480 -0
  22. package/src/components/activity/PartGroupingDecorator.tsx +69 -0
  23. package/src/components/assets/AssetComposer.tsx +2 -0
  24. package/src/components/theme/Theme.module.css +85 -41
  25. package/src/env.d.ts +10 -0
  26. package/src/external.umd/botframework-webchat-api/decorator.ts +2 -0
  27. package/src/external.umd/botframework-webchat-api/index.ts +2 -0
  28. package/src/external.umd/botframework-webchat-component/decorator.ts +2 -0
  29. package/src/external.umd/botframework-webchat-component/internal.ts +2 -0
  30. package/src/external.umd/react.ts +2 -0
  31. package/src/index.ts +6 -11
  32. package/src/private/FluentThemeProvider.tsx +9 -1
  33. package/src/tsconfig.json +8 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botframework-webchat-fluent-theme",
3
- "version": "4.18.1-main.20250804.93043a9",
3
+ "version": "4.18.1-main.20250916.f2f7323",
4
4
  "description": "Fluent theme for Bot Framework Web Chat",
5
5
  "main": "./dist/botframework-webchat-fluent-theme.js",
6
6
  "types": "./dist/botframework-webchat-fluent-theme.d.ts",
@@ -53,6 +53,7 @@
53
53
  "localDependencies": {
54
54
  "@msinternal/botframework-webchat-base": "development",
55
55
  "@msinternal/botframework-webchat-styles": "development",
56
+ "@msinternal/botframework-webchat-tsconfig": "development",
56
57
  "botframework-webchat-api": "production",
57
58
  "botframework-webchat-component": "production",
58
59
  "botframework-webchat-core": "production"
@@ -68,9 +69,9 @@
68
69
  ]
69
70
  },
70
71
  "devDependencies": {
71
- "@msinternal/botframework-webchat-base": "4.18.1-main.20250804.93043a9",
72
- "@msinternal/botframework-webchat-styles": "4.18.1-main.20250804.93043a9",
73
- "@tsconfig/strictest": "^2.0.5",
72
+ "@msinternal/botframework-webchat-base": "4.18.1-main.20250916.f2f7323",
73
+ "@msinternal/botframework-webchat-styles": "4.18.1-main.20250916.f2f7323",
74
+ "@msinternal/botframework-webchat-tsconfig": "4.18.1-main.20250916.f2f7323",
74
75
  "@types/math-random": "^1.0.2",
75
76
  "@types/node": "^24.1.0",
76
77
  "@types/react": "^16.14.65",
@@ -78,9 +79,9 @@
78
79
  "typescript": "~5.8.3"
79
80
  },
80
81
  "dependencies": {
81
- "botframework-webchat-api": "4.18.1-main.20250804.93043a9",
82
- "botframework-webchat-component": "4.18.1-main.20250804.93043a9",
83
- "botframework-webchat-core": "4.18.1-main.20250804.93043a9",
82
+ "botframework-webchat-api": "4.18.1-main.20250916.f2f7323",
83
+ "botframework-webchat-component": "4.18.1-main.20250916.f2f7323",
84
+ "botframework-webchat-core": "4.18.1-main.20250916.f2f7323",
84
85
  "classnames": "2.5.1",
85
86
  "inject-meta-tag": "0.0.1",
86
87
  "math-random": "2.0.1",
@@ -0,0 +1,9 @@
1
+ import { createBuildInfo } from '@msinternal/botframework-webchat-base/utils';
2
+
3
+ const buildInfo = createBuildInfo('botframework-webchat:fluent-theme');
4
+
5
+ buildInfo.set('buildTool', globalThis.WEB_CHAT_BUILD_INFO_BUILD_TOOL);
6
+ buildInfo.set('moduleFormat', globalThis.WEB_CHAT_BUILD_INFO_MODULE_FORMAT);
7
+ buildInfo.set('version', globalThis.WEB_CHAT_BUILD_INFO_VERSION);
8
+
9
+ export default buildInfo;
@@ -1,106 +1,5 @@
1
1
  :global(.webchat-fluent) .activity-decorator {
2
2
  display: contents;
3
- font-family: var(--webchat__font--primary);
4
-
5
- --webchat__bubble--inline-padding: var(--webchat-spacingHorizontalL);
6
- --webchat__bubble--block-padding: var(--webchat-spacingVerticalM);
7
- --webchat__bubble--min-height: var(--webchat-bubble-minHeight);
8
- --webchat__bubble--max-width: var(--webchat-bubble-maxWidth);
9
- --webchat__bubble--min-width: var(--webchat-bubble-minWidth);
10
-
11
- --webchat-bubble-maxWidth: var(--bubble-maxWidth, max(450px, 75%));
12
- --webchat-bubble-minWidth: var(--bubble-minWidth, auto);
13
- --webchat-bubble-minHeight: var(--bubble-minHeight, 36px);
14
- --webchat-externalLink-mask: var(
15
- --externalLink-mask,
16
- var(--webchat__icon-url--external-link) center center /
17
- 10px 10px
18
- );
19
- --webchat-externalLink-maxWidth: var(--externalLink-maxWidth, 204px);
20
-
21
- /* Override for stacked layout message which has user message bubble props */
22
- &:has(:global(.stacked-layout .webchat__bubble--from-user)) {
23
- --webchat__bubble--background-color: var(--webchat-colorBrandBackground2);
24
- --webchat__bubble--block-padding: var(--webchat-spacingVerticalS);
25
- --webchat__bubble--min-width: auto;
26
- }
27
- }
28
-
29
- /* Decorator fluent variant */
30
- :global(.webchat-fluent) .activity-decorator.variant-fluent {
31
- --webchat__bubble--background-color: var(--webchat-colorNeutralBackground1);
32
- --webchat__bubble--border-radius: var(--webchat-borderRadiusXLarge);
33
- --webchat__bubble--box-shadow: var(--webchat-shadow4);
34
- }
35
-
36
- /* Decorator copilot variant */
37
- :global(.webchat-fluent) .activity-decorator.variant-copilot {
38
- --webchat__bubble--border-radius: var(--webchat-borderRadiusXLarge);
39
-
40
- :global(.webchat__activity-status) {
41
- margin: 0 0 var(--webchat-spacingHorizontalXXS);
42
- }
43
-
44
- :global(.stacked-layout__status) {
45
- order: -1;
46
- }
47
-
48
- &:has(:global(.webchat__bubble--from-user)) :global(.webchat__bubble) {
49
- margin-block-end: var(--webchat-spacingVerticalM);
50
- }
51
-
52
- /* Hide generated badge as it is in the copilot header */
53
- :global(.webchat__bubble .webchat__text-content .webchat__text-content__generated-badge) {
54
- display: none;
55
- }
56
- }
57
-
58
- /* Decorator copilot variant which has bot message */
59
- :global(.webchat-fluent) .activity-decorator.variant-copilot:not(:has(:global(.webchat__bubble--from-user))) {
60
- --webchat__bubble--block-padding: 0;
61
- --webchat__bubble--border-radius: var(--webchat-borderRadiusMedium);
62
- --webchat__bubble--inline-padding: 0;
63
- --webchat__bubble--max-width: 100%;
64
- --webchat__bubble--min-height: 20px;
65
-
66
- display: flex;
67
- flex-flow: column nowrap;
68
- gap: var(--webchat-spacingVerticalS);
69
- margin-inline: var(--webchat-spacingHorizontalM);
70
- padding: var(--webchat-spacingVerticalMNudge) var(--webchat-spacingHorizontalM) var(--webchat-spacingVerticalM);
71
- position: relative;
72
-
73
- :global(.stacked-layout) {
74
- margin: 0;
75
- position: static;
76
- }
77
-
78
- :global(.webchat__bubble) {
79
- position: static;
80
- width: var(--webchat__bubble--max-width);
81
- }
82
-
83
- :global(.webchat__bubble .webchat__bubble__content) {
84
- display: flex;
85
- flex-direction: column;
86
- gap: var(--webchat-spacingVerticalS);
87
- margin-block: calc(var(--webchat-spacingVerticalS) * -1);
88
- margin-inline: 20px calc(var(--webchat-spacingHorizontalS) * -1);
89
- padding-block: var(--webchat-spacingVerticalS);
90
- padding-inline: var(--webchat-spacingHorizontalS);
91
- }
92
-
93
- :global(.webchat__bubble .collapsible-content .collapsible-content__content .stacked-layout__attachment-list) {
94
- margin-block-start: var(--webchat-spacingVerticalS);
95
- }
96
-
97
- :global(.webchat__bubble .collapsible-content .collapsible-content__content .stacked-layout__attachment) {
98
- max-width: var(--webchat__bubble--max-width);
99
- }
100
-
101
- :global(.stacked-layout__status) {
102
- display: none;
103
- }
104
3
  }
105
4
 
106
5
  /* Transcript activity non-empty */
@@ -108,82 +7,6 @@
108
7
  padding-block-end: var(--webchat-spacingVerticalXL);
109
8
  }
110
9
 
111
- /* Stacked layout */
112
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout) {
113
- display: flex;
114
- flex-flow: column nowrap;
115
- margin-inline: var(--webchat-spacingHorizontalMNudge);
116
-
117
- :global(.stacked-layout__title) {
118
- font-size: var(--webchat-fontSizeBase400);
119
- line-height: var(--webchat-lineHeightBase400);
120
- color: var(--webchat-colorNeutralForeground4);
121
- margin: var(--webchat__bubble--block-padding) var(--webchat__bubble--inline-padding);
122
- }
123
-
124
- :global(.stacked-layout__attachment-row) {
125
- margin-block-start: var(--webchat-spacingVerticalMNudge);
126
- }
127
-
128
- &:global(.stacked-layout--no-message .stacked-layout__attachment-row) {
129
- margin-block-start: 0;
130
- }
131
- }
132
-
133
- /* Stacked layout which has message bubble */
134
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .stacked-layout__content:has(.webchat__bubble)) {
135
- max-width: 100%;
136
- overflow: visible;
137
- }
138
-
139
- /* Message status */
140
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .stacked-layout__status) {
141
- font-size: var(--webchat__font-size--small);
142
- line-height: var(--webchat__line-height--small);
143
- }
144
-
145
- /* Message bubble */
146
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .webchat__bubble) {
147
- max-width: min(var(--webchat__bubble--max-width), 100%);
148
- min-width: var(--webchat__bubble--min-width);
149
- overflow: visible;
150
-
151
- /* Ensure activity loader doesn't have bubble and shadow */
152
- &:has(:global(.activity-loader)) :global(.webchat__bubble__content) {
153
- background: transparent;
154
- box-shadow: none;
155
- }
156
- }
157
-
158
- /* Message bubble content */
159
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .webchat__bubble .webchat__bubble__content) {
160
- background-color: var(--webchat__bubble--background-color);
161
- border-radius: var(--webchat__bubble--border-radius);
162
- border-width: 0;
163
- box-shadow: var(--webchat__bubble--box-shadow);
164
- box-sizing: border-box;
165
- color: var(--webchat-colorNeutralForeground1);
166
- max-width: 100%;
167
- min-height: var(--webchat__bubble--min-height);
168
- }
169
-
170
- /* Message bubble text content */
171
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .webchat__bubble .webchat__text-content) {
172
- font-size: var(--webchat__font-size--medium);
173
- line-height: var(--webchat__line-height--medium);
174
- min-height: auto;
175
- padding-block: var(--webchat__bubble--block-padding);
176
- padding-inline: var(--webchat__bubble--inline-padding);
177
-
178
- &:empty {
179
- padding-block-end: 0;
180
- }
181
-
182
- + :global(.webchat__text-content) {
183
- margin-top: calc(var(--webchat__bubble--block-padding) * -1);
184
- }
185
- }
186
-
187
10
  /* Message bubble text content generated badge */
188
11
  :global(.webchat-fluent)
189
12
  .activity-decorator
@@ -224,66 +47,6 @@
224
47
  color: var(--webchat-colorBrandForegroundLink);
225
48
  }
226
49
 
227
- /* Message bubble collapsible content */
228
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .webchat__bubble .collapsible-content) {
229
- :global(.collapsible-content__summary) {
230
- margin-block: var(--webchat__bubble--block-padding);
231
- margin-inline: var(--webchat__bubble--inline-padding);
232
-
233
- &:focus-visible {
234
- border-radius: var(--webchat-borderRadiusSmall);
235
- outline-offset: 4px;
236
- outline: var(--webchat-strokeWidthThick) solid var(--webchat-colorStrokeFocus2);
237
- }
238
- }
239
-
240
- :global(.collapsible-content__content) {
241
- margin-block: 0 var(--webchat__bubble--block-padding);
242
- }
243
-
244
- :global(.collapsible-content__content .stacked-layout__attachment-list) {
245
- gap: var(--webchat-spacingVerticalS);
246
- }
247
-
248
- :global(.collapsible-content__content .stacked-layout__attachment-row) {
249
- margin: 0;
250
- }
251
-
252
- :global(.collapsible-content__content .stacked-layout__attachment-row .webchat__text-content) {
253
- padding-block: 0;
254
- }
255
- }
256
-
257
- /* Message bubble code block content */
258
- :global(.webchat-fluent) .activity-decorator :global(.stacked-layout .webchat__bubble .code-block-content) {
259
- border-radius: var(--webchat-borderRadiusXLarge);
260
- border: var(--webchat-strokeWidthThin) solid var(--webchat-colorNeutralStroke1);
261
- font-size: var(--webchat-fontSizeBase300);
262
- font-weight: var(--webchat-fontWeightRegular);
263
- margin-block: 0;
264
- margin-inline: var(--webchat__bubble--inline-padding);
265
-
266
- :global(.code-block-content__header) {
267
- padding: var(--webchat-spacingVerticalM) var(--webchat-spacingHorizontalL);
268
- }
269
-
270
- :global(.code-block-content__code-block) {
271
- padding-block: var(--webchat-spacingVerticalM);
272
- padding-inline: var(--webchat-spacingHorizontalL) var(--webchat-spacingHorizontalS);
273
- }
274
-
275
- :global(.webchat__code-block-copy-button) {
276
- --webchat__code-block__copy-button--color: var(--webchat-colorNeutralForeground1);
277
- --webchat__code-block__copy-button--background: var(--webchat-colorNeutralBackground3);
278
-
279
- margin-block-start: var(--webchat-spacingVerticalM);
280
- margin-inline-end: var(--webchat-spacingHorizontalL);
281
- position: absolute;
282
- right: 0;
283
- top: 0;
284
- }
285
- }
286
-
287
50
  /* Markdown links and citation links */
288
51
  :global(.webchat-fluent)
289
52
  .activity-decorator
@@ -1,26 +1,31 @@
1
+ import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
1
2
  import { WebChatActivity } from 'botframework-webchat-component';
2
3
  import cx from 'classnames';
3
4
  import React, { ReactNode, memo } from 'react';
4
- import useVariants from '../../private/useVariants';
5
+ import { object, optional, pipe, readonly, type InferInput } from 'valibot';
6
+
5
7
  import { useStyles, useVariantClassName } from '../../styles';
6
8
  import styles from './ActivityDecorator.module.css';
7
- import CopilotMessageHeader from './CopilotMessageHeader';
8
9
 
9
- function ActivityDecorator({ activity, children }: Readonly<{ activity: WebChatActivity; children: ReactNode }>) {
10
+ const activityDecoratorPropsSchema = pipe(
11
+ object({
12
+ children: optional(reactNode())
13
+ }),
14
+ readonly()
15
+ );
16
+
17
+ type ActivityDecoratorProps = InferInput<typeof activityDecoratorPropsSchema>;
18
+
19
+ function ActivityDecorator(props: Readonly<{ activity: WebChatActivity; children: ReactNode }>) {
20
+ const { children } = validateProps(activityDecoratorPropsSchema, props);
21
+
10
22
  const classNames = useStyles(styles);
11
- const variants = useVariants();
12
23
  const variantClassName = useVariantClassName(styles);
13
24
 
14
- const shouldRenderHeader = variants.includes('copilot') && activity?.from?.role === 'bot' && !!children;
15
-
16
- return (
17
- <div className={cx(classNames['activity-decorator'], variantClassName)}>
18
- {shouldRenderHeader && <CopilotMessageHeader activity={activity} />}
19
- {children}
20
- </div>
21
- );
25
+ return <div className={cx(classNames['activity-decorator'], variantClassName)}>{children}</div>;
22
26
  }
23
27
 
24
28
  ActivityDecorator.displayName = 'ActivityDecorator';
25
29
 
26
30
  export default memo(ActivityDecorator);
31
+ export { activityDecoratorPropsSchema, type ActivityDecoratorProps };
@@ -11,6 +11,6 @@
11
11
  }
12
12
 
13
13
  &.variant-copilot {
14
- margin: var(--webchat-spacingVerticalXS) 0 0 -10px;
14
+ margin: var(--webchat-spacingVerticalXS) 0 var(--webchat-spacingVerticalXS) -10px;
15
15
  }
16
16
  }
@@ -1,24 +1,37 @@
1
+ import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
1
2
  import { useStyles } from '@msinternal/botframework-webchat-styles/react';
2
3
  import cx from 'classnames';
3
- import React, { Fragment, memo, type ReactNode } from 'react';
4
+ import React, { Fragment, memo } from 'react';
5
+ import { boolean, object, optional, pipe, readonly, string, type InferInput } from 'valibot';
4
6
 
5
7
  import { useVariantClassName } from '../../styles';
6
8
  import SlidingDots from '../assets/SlidingDots';
7
9
  import styles from './ActivityLoader.module.css';
8
10
 
9
- function FluentActivityLoader({
10
- children,
11
- showLoader = true
12
- }: Readonly<{ children?: ReactNode | undefined; showLoader?: boolean }>) {
11
+ const fluentActivityLoaderPropsSchema = pipe(
12
+ object({
13
+ children: optional(reactNode()),
14
+ className: optional(string()),
15
+ showLoader: optional(boolean(), true)
16
+ }),
17
+ readonly()
18
+ );
19
+
20
+ type FluentActivityLoaderProps = InferInput<typeof fluentActivityLoaderPropsSchema>;
21
+
22
+ function FluentActivityLoader(props: FluentActivityLoaderProps) {
23
+ const { children, className, showLoader } = validateProps(fluentActivityLoaderPropsSchema, props);
24
+
13
25
  const classNames = useStyles(styles);
14
26
  const variantClassName = useVariantClassName(classNames);
15
27
 
16
28
  return (
17
29
  <Fragment>
18
30
  {children}
19
- {showLoader && <SlidingDots className={cx(classNames['activity-loader'], variantClassName)} />}
31
+ {showLoader && <SlidingDots className={cx(classNames['activity-loader'], variantClassName, className)} />}
20
32
  </Fragment>
21
33
  );
22
34
  }
23
35
 
24
36
  export default memo(FluentActivityLoader);
37
+ export { fluentActivityLoaderPropsSchema, type FluentActivityLoaderProps };
@@ -1,15 +1,29 @@
1
- import React, { memo, useMemo, type CSSProperties } from 'react';
1
+ import { validateProps } from '@msinternal/botframework-webchat-react-valibot';
2
2
  import { WebChatActivity, hooks } from 'botframework-webchat-component';
3
-
4
- import useActivityStyleOptions from './private/useActivityStyleOptions';
5
- import isAIGeneratedActivity from './private/isAIGeneratedActivity';
6
- import useActivityAuthor from './private/useActivityAuthor';
3
+ import cx from 'classnames';
4
+ import React, { memo, useMemo, type CSSProperties } from 'react';
5
+ import { custom, object, optional, pipe, readonly, safeParse, string, type InferInput } from 'valibot';
7
6
  import { useStyles } from '../../styles';
8
7
  import styles from './CopilotMessageHeader.module.css';
8
+ import isAIGeneratedActivity from './private/isAIGeneratedActivity';
9
+ import useActivityAuthor from './private/useActivityAuthor';
10
+ import useActivityStyleOptions from './private/useActivityStyleOptions';
9
11
 
10
12
  const { useLocalizer } = hooks;
11
13
 
12
- function CopilotMessageHeader({ activity }: Readonly<{ activity?: WebChatActivity | undefined }>) {
14
+ const copilotMessageHeaderPropsSchema = pipe(
15
+ object({
16
+ activity: optional(custom<Readonly<WebChatActivity>>(value => safeParse(object({}), value).success)),
17
+ className: optional(string())
18
+ }),
19
+ readonly()
20
+ );
21
+
22
+ type CopilotMessageHeaderProps = InferInput<typeof copilotMessageHeaderPropsSchema>;
23
+
24
+ function CopilotMessageHeader(props: CopilotMessageHeaderProps) {
25
+ const { activity, className } = validateProps(copilotMessageHeaderPropsSchema, props);
26
+
13
27
  const [{ botAvatarImage, botAvatarBackgroundColor }] = useActivityStyleOptions(activity);
14
28
  const classNames = useStyles(styles);
15
29
  const localize = useLocalizer();
@@ -25,7 +39,7 @@ function CopilotMessageHeader({ activity }: Readonly<{ activity?: WebChatActivit
25
39
  const botTitle = author?.name || activity?.from?.name;
26
40
 
27
41
  return (
28
- <div className={classNames['copilot-message-header']}>
42
+ <div className={cx(classNames['copilot-message-header'], className)}>
29
43
  {avatarImage && (
30
44
  <img
31
45
  alt={localize('AVATAR_ALT', botTitle)}
@@ -47,3 +61,4 @@ function CopilotMessageHeader({ activity }: Readonly<{ activity?: WebChatActivit
47
61
  }
48
62
 
49
63
  export default memo(CopilotMessageHeader);
64
+ export { copilotMessageHeaderPropsSchema, type CopilotMessageHeaderProps };