@salesforce/ui-bundle-template-feature-react-agentforce-conversation-client 11.49.4 → 11.51.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/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [11.51.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.50.0...v11.51.0) (2026-08-07)
7
+
8
+ **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
9
+
10
+
11
+
12
+
13
+
14
+ ## [11.50.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.49.4...v11.50.0) (2026-08-07)
15
+
16
+ **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
17
+
18
+
19
+
20
+
21
+
6
22
  ## [11.49.4](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.49.3...v11.49.4) (2026-08-07)
7
23
 
8
24
  **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
@@ -18,8 +18,8 @@
18
18
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
19
19
  },
20
20
  "dependencies": {
21
- "@salesforce/platform-sdk": "^11.49.4",
22
- "@salesforce/ui-bundle": "^11.49.4",
21
+ "@salesforce/platform-sdk": "^11.51.0",
22
+ "@salesforce/ui-bundle": "^11.51.0",
23
23
  "@tailwindcss/vite": "^4.1.17",
24
24
  "class-variance-authority": "^0.7.1",
25
25
  "clsx": "^2.1.1",
@@ -45,8 +45,8 @@
45
45
  "@graphql-eslint/eslint-plugin": "^4.1.0",
46
46
  "@graphql-tools/utils": "^11.0.0",
47
47
  "@playwright/test": "^1.49.0",
48
- "@salesforce/graphiti": "^11.49.4",
49
- "@salesforce/vite-plugin-ui-bundle": "^11.49.4",
48
+ "@salesforce/graphiti": "^11.51.0",
49
+ "@salesforce/vite-plugin-ui-bundle": "^11.51.0",
50
50
  "@testing-library/jest-dom": "^6.6.3",
51
51
  "@testing-library/react": "^16.1.0",
52
52
  "@testing-library/user-event": "^14.5.2",
@@ -6,59 +6,21 @@
6
6
 
7
7
  import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
8
8
  import type { AgentforceClientConfig } from "@salesforce/agentforce-conversation-client";
9
+ import { createAccEmbedder } from "@salesforce/agentforce-conversation-client/ui-bundle";
9
10
  import { useEffect, useMemo, useRef } from "react";
10
- import type {
11
- ResolvedEmbedOptions,
12
- AgentforceConversationClientProps,
13
- } from "../types/conversation";
11
+ import type { AgentforceConversationClientProps } from "../types/conversation";
14
12
 
15
- const GLOBAL_HOST_ID = "agentforce-conversation-client-global-host";
16
- const SINGLETON_KEY = "__agentforceConversationClientSingleton";
17
-
18
- interface AgentforceConversationClientSingleton {
19
- initPromise?: Promise<void>;
20
- initialized: boolean;
21
- }
22
-
23
- interface WindowWithAgentforceSingleton extends Window {
24
- [SINGLETON_KEY]?: AgentforceConversationClientSingleton;
25
- }
26
-
27
- type GlobalWithSfdcEnv = typeof globalThis & {
28
- SFDC_ENV?: {
29
- orgUrl?: string;
30
- };
31
- };
32
-
33
- function getSingleton(): AgentforceConversationClientSingleton {
34
- const win = window as WindowWithAgentforceSingleton;
35
- if (!win[SINGLETON_KEY]) {
36
- win[SINGLETON_KEY] = {
37
- initialized: false,
38
- };
39
- }
40
- return win[SINGLETON_KEY]!;
41
- }
42
-
43
- function getOrCreateGlobalHost(): HTMLDivElement {
44
- let host = document.getElementById(GLOBAL_HOST_ID) as HTMLDivElement | null;
45
- if (!host) {
46
- host = document.createElement("div");
47
- host.id = GLOBAL_HOST_ID;
48
- document.body.appendChild(host);
49
- }
50
- return host;
51
- }
52
-
53
- function getDefaultEmbedOptions(): ResolvedEmbedOptions {
54
- const sfdcEnv = (globalThis as GlobalWithSfdcEnv).SFDC_ENV;
55
- return { salesforceOrigin: sfdcEnv?.orgUrl };
56
- }
13
+ // The embed orchestration (window singleton, global host, dev frontdoor fetch,
14
+ // SFDC_ENV default, partial-embed cleanup) lives in the shared, framework-agnostic
15
+ // @salesforce/agentforce-conversation-client/ui-bundle glue. We hand it the
16
+ // low-level embed function via dependency injection.
17
+ const embedder = createAccEmbedder<AgentforceClientConfig>(embedAgentforceClient);
57
18
 
58
19
  /**
59
20
  * React wrapper that embeds the Agentforce Conversation Client (copilot/agent UI)
60
21
  * using Lightning Out. Requires a valid Salesforce session for the given org.
61
- * Config is passed through from the consumer to the embed client as-is.
22
+ * Flat props are normalized into an `AgentforceClientConfig` and passed through
23
+ * to the shared embedder as-is.
62
24
  */
63
25
  export function AgentforceConversationClient({
64
26
  agentId,
@@ -109,96 +71,18 @@ export function AgentforceConversationClient({
109
71
  const inline = normalizedAgentforceClientConfig?.renderingConfig?.mode === "inline";
110
72
 
111
73
  useEffect(() => {
112
- if (!normalizedAgentforceClientConfig?.agentId) {
113
- throw new Error(
114
- "AgentforceConversationClient requires agentId. " +
115
- "Pass flat props only (agentId, agentLabel, inline, headerEnabled, showHeaderIcon, width, height, styleTokens).",
116
- );
117
- }
118
-
119
- const singleton = getSingleton();
120
- if (singleton.initialized || singleton.initPromise) {
121
- return;
122
- }
123
-
124
- if (inline && !containerRef.current) {
125
- return;
126
- }
127
-
128
- const initialize = (options: ResolvedEmbedOptions) => {
129
- if (singleton.initialized) {
130
- return;
131
- }
132
- const existingEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
133
- if (existingEmbed) {
134
- singleton.initialized = true;
135
- return;
136
- }
137
- const host = inline ? containerRef.current! : getOrCreateGlobalHost();
138
-
139
- try {
140
- embedAgentforceClient({
141
- container: host,
142
- salesforceOrigin: salesforceOrigin ?? options.salesforceOrigin,
143
- frontdoorUrl: frontdoorUrl ?? options.frontdoorUrl,
144
- agentforceClientConfig: normalizedAgentforceClientConfig,
145
- onReady,
146
- onError,
147
- });
148
- singleton.initialized = true;
149
- } catch (err) {
150
- // Strip a partially-created LO element so the next mount can retry.
151
- const partialEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
152
- partialEmbed?.remove();
153
- console.error("AgentforceConversationClient: initialization failed", err);
154
- }
155
- };
156
-
157
- const safeInitialize = (options: ResolvedEmbedOptions) => {
158
- try {
159
- initialize(options);
160
- } catch (initErr) {
161
- console.error("AgentforceConversationClient: initialization failed", initErr);
162
- singleton.initialized = false;
163
- }
164
- };
165
-
166
- const shouldFetchFrontdoor = window.location.hostname === "localhost";
167
-
168
- if (shouldFetchFrontdoor) {
169
- singleton.initPromise = fetch("/__lo/frontdoor")
170
- .then(async (res) => {
171
- if (!res.ok) {
172
- console.error("frontdoor fetch failed");
173
- return;
174
- }
175
- const { frontdoorUrl: resolvedFrontdoorUrl } = await res.json();
176
- safeInitialize({ frontdoorUrl: resolvedFrontdoorUrl });
177
- })
178
- .catch((err) => {
179
- console.error("AgentforceConversationClient: failed to fetch frontdoor URL", err);
180
- })
181
- .finally(() => {
182
- singleton.initPromise = undefined;
183
- });
184
- } else {
185
- singleton.initPromise = Promise.resolve()
186
- .then(() => {
187
- safeInitialize(getDefaultEmbedOptions());
188
- })
189
- .catch((err) => {
190
- console.error("AgentforceConversationClient: failed to embed Agentforce client", err);
191
- })
192
- .finally(() => {
193
- singleton.initPromise = undefined;
194
- });
195
- }
74
+ embedder.embedAcc(
75
+ normalizedAgentforceClientConfig,
76
+ { salesforceOrigin, frontdoorUrl },
77
+ containerRef.current,
78
+ { onReady, onError },
79
+ );
196
80
 
197
81
  return () => {
198
82
  // Intentionally no cleanup:
199
83
  // This component guarantees a single LO initialization per window.
200
84
  };
201
- }, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig, inline, onReady, onError]);
85
+ }, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig, onReady, onError]);
202
86
 
203
87
  if (!inline) {
204
88
  return null;
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2020",
3
+ "target": "ES2022",
4
4
  "useDefineForClassFields": true,
5
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
6
  "module": "ESNext",
7
7
  "skipLibCheck": true,
8
8
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.49.4",
3
+ "version": "11.51.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
9
- "version": "11.49.4",
9
+ "version": "11.51.0",
10
10
  "license": "SEE LICENSE IN LICENSE.txt",
11
11
  "dependencies": {
12
12
  "fast-xml-parser": "^5.9.3",
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.49.4",
3
+ "version": "11.51.0",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-feature-react-agentforce-conversation-client",
3
- "version": "11.49.4",
3
+ "version": "11.51.0",
4
4
  "description": "Embedded Agentforce conversation client feature for UI Bundles",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "author": "",
@@ -26,7 +26,7 @@
26
26
  "clean": "rm -rf dist"
27
27
  },
28
28
  "dependencies": {
29
- "@salesforce/agentforce-conversation-client": "^11.49.4"
29
+ "@salesforce/agentforce-conversation-client": "^11.51.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/react": "^19.2.7",
@@ -6,59 +6,21 @@
6
6
 
7
7
  import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
8
8
  import type { AgentforceClientConfig } from "@salesforce/agentforce-conversation-client";
9
+ import { createAccEmbedder } from "@salesforce/agentforce-conversation-client/ui-bundle";
9
10
  import { useEffect, useMemo, useRef } from "react";
10
- import type {
11
- ResolvedEmbedOptions,
12
- AgentforceConversationClientProps,
13
- } from "../types/conversation";
11
+ import type { AgentforceConversationClientProps } from "../types/conversation";
14
12
 
15
- const GLOBAL_HOST_ID = "agentforce-conversation-client-global-host";
16
- const SINGLETON_KEY = "__agentforceConversationClientSingleton";
17
-
18
- interface AgentforceConversationClientSingleton {
19
- initPromise?: Promise<void>;
20
- initialized: boolean;
21
- }
22
-
23
- interface WindowWithAgentforceSingleton extends Window {
24
- [SINGLETON_KEY]?: AgentforceConversationClientSingleton;
25
- }
26
-
27
- type GlobalWithSfdcEnv = typeof globalThis & {
28
- SFDC_ENV?: {
29
- orgUrl?: string;
30
- };
31
- };
32
-
33
- function getSingleton(): AgentforceConversationClientSingleton {
34
- const win = window as WindowWithAgentforceSingleton;
35
- if (!win[SINGLETON_KEY]) {
36
- win[SINGLETON_KEY] = {
37
- initialized: false,
38
- };
39
- }
40
- return win[SINGLETON_KEY]!;
41
- }
42
-
43
- function getOrCreateGlobalHost(): HTMLDivElement {
44
- let host = document.getElementById(GLOBAL_HOST_ID) as HTMLDivElement | null;
45
- if (!host) {
46
- host = document.createElement("div");
47
- host.id = GLOBAL_HOST_ID;
48
- document.body.appendChild(host);
49
- }
50
- return host;
51
- }
52
-
53
- function getDefaultEmbedOptions(): ResolvedEmbedOptions {
54
- const sfdcEnv = (globalThis as GlobalWithSfdcEnv).SFDC_ENV;
55
- return { salesforceOrigin: sfdcEnv?.orgUrl };
56
- }
13
+ // The embed orchestration (window singleton, global host, dev frontdoor fetch,
14
+ // SFDC_ENV default, partial-embed cleanup) lives in the shared, framework-agnostic
15
+ // @salesforce/agentforce-conversation-client/ui-bundle glue. We hand it the
16
+ // low-level embed function via dependency injection.
17
+ const embedder = createAccEmbedder<AgentforceClientConfig>(embedAgentforceClient);
57
18
 
58
19
  /**
59
20
  * React wrapper that embeds the Agentforce Conversation Client (copilot/agent UI)
60
21
  * using Lightning Out. Requires a valid Salesforce session for the given org.
61
- * Config is passed through from the consumer to the embed client as-is.
22
+ * Flat props are normalized into an `AgentforceClientConfig` and passed through
23
+ * to the shared embedder as-is.
62
24
  */
63
25
  export function AgentforceConversationClient({
64
26
  agentId,
@@ -109,96 +71,18 @@ export function AgentforceConversationClient({
109
71
  const inline = normalizedAgentforceClientConfig?.renderingConfig?.mode === "inline";
110
72
 
111
73
  useEffect(() => {
112
- if (!normalizedAgentforceClientConfig?.agentId) {
113
- throw new Error(
114
- "AgentforceConversationClient requires agentId. " +
115
- "Pass flat props only (agentId, agentLabel, inline, headerEnabled, showHeaderIcon, width, height, styleTokens).",
116
- );
117
- }
118
-
119
- const singleton = getSingleton();
120
- if (singleton.initialized || singleton.initPromise) {
121
- return;
122
- }
123
-
124
- if (inline && !containerRef.current) {
125
- return;
126
- }
127
-
128
- const initialize = (options: ResolvedEmbedOptions) => {
129
- if (singleton.initialized) {
130
- return;
131
- }
132
- const existingEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
133
- if (existingEmbed) {
134
- singleton.initialized = true;
135
- return;
136
- }
137
- const host = inline ? containerRef.current! : getOrCreateGlobalHost();
138
-
139
- try {
140
- embedAgentforceClient({
141
- container: host,
142
- salesforceOrigin: salesforceOrigin ?? options.salesforceOrigin,
143
- frontdoorUrl: frontdoorUrl ?? options.frontdoorUrl,
144
- agentforceClientConfig: normalizedAgentforceClientConfig,
145
- onReady,
146
- onError,
147
- });
148
- singleton.initialized = true;
149
- } catch (err) {
150
- // Strip a partially-created LO element so the next mount can retry.
151
- const partialEmbed = document.querySelector('lightning-out-application[data-lo="acc"]');
152
- partialEmbed?.remove();
153
- console.error("AgentforceConversationClient: initialization failed", err);
154
- }
155
- };
156
-
157
- const safeInitialize = (options: ResolvedEmbedOptions) => {
158
- try {
159
- initialize(options);
160
- } catch (initErr) {
161
- console.error("AgentforceConversationClient: initialization failed", initErr);
162
- singleton.initialized = false;
163
- }
164
- };
165
-
166
- const shouldFetchFrontdoor = window.location.hostname === "localhost";
167
-
168
- if (shouldFetchFrontdoor) {
169
- singleton.initPromise = fetch("/__lo/frontdoor")
170
- .then(async (res) => {
171
- if (!res.ok) {
172
- console.error("frontdoor fetch failed");
173
- return;
174
- }
175
- const { frontdoorUrl: resolvedFrontdoorUrl } = await res.json();
176
- safeInitialize({ frontdoorUrl: resolvedFrontdoorUrl });
177
- })
178
- .catch((err) => {
179
- console.error("AgentforceConversationClient: failed to fetch frontdoor URL", err);
180
- })
181
- .finally(() => {
182
- singleton.initPromise = undefined;
183
- });
184
- } else {
185
- singleton.initPromise = Promise.resolve()
186
- .then(() => {
187
- safeInitialize(getDefaultEmbedOptions());
188
- })
189
- .catch((err) => {
190
- console.error("AgentforceConversationClient: failed to embed Agentforce client", err);
191
- })
192
- .finally(() => {
193
- singleton.initPromise = undefined;
194
- });
195
- }
74
+ embedder.embedAcc(
75
+ normalizedAgentforceClientConfig,
76
+ { salesforceOrigin, frontdoorUrl },
77
+ containerRef.current,
78
+ { onReady, onError },
79
+ );
196
80
 
197
81
  return () => {
198
82
  // Intentionally no cleanup:
199
83
  // This component guarantees a single LO initialization per window.
200
84
  };
201
- }, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig, inline, onReady, onError]);
85
+ }, [salesforceOrigin, frontdoorUrl, normalizedAgentforceClientConfig, onReady, onError]);
202
86
 
203
87
  if (!inline) {
204
88
  return null;