@salesforce/retail-react-app 9.0.0 → 9.1.0-nightly-20260217081023

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/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## v9.1.0-dev
2
+ - Add Node 24 support. Drop Node 16 support [#3652](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3652)
3
+
1
4
  ## v9.0.0 (Feb 12, 2026)
2
5
  - [Feature] One Click Checkout (in Developer Preview) [#3552](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3552)
3
6
  - [Feature] Add `fuzzyPathMatching` to reduce computational overhead of route generation at time of application load [#3530](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/3530)
@@ -302,7 +302,7 @@ const OtpAuth = ({
302
302
  )}
303
303
 
304
304
  {/* Buttons */}
305
- <HStack spacing={4} width="100%" justifyContent="flex-end">
305
+ <HStack spacing={4} width="100%" justifyContent="center">
306
306
  {!hideCheckoutAsGuestButton && (
307
307
  <Button
308
308
  onClick={handleCheckoutAsGuest}
@@ -175,7 +175,8 @@ const ShopperAgentWindow = ({commerceAgentConfiguration, domainUrl}) => {
175
175
  commerceOrgId,
176
176
  siteId,
177
177
  enableConversationContext = 'false',
178
- conversationContext = []
178
+ conversationContext = [],
179
+ enableAgentFromFloatingButton = 'true'
179
180
  } = commerceAgentConfiguration
180
181
 
181
182
  // User session identifier hook
@@ -352,7 +353,8 @@ const ShopperAgentWindow = ({commerceAgentConfiguration, domainUrl}) => {
352
353
  embeddedServiceEndpoint,
353
354
  scrt2Url,
354
355
  locale.id,
355
- refreshToken
356
+ refreshToken,
357
+ enableAgentFromFloatingButton
356
358
  )
357
359
 
358
360
  // This component doesn't render visible UI, only manages the messaging service
@@ -509,7 +509,31 @@ describe('ShopperAgent Component', () => {
509
509
  'https://test.salesforce.com', // embeddedServiceEndpoint
510
510
  'https://test.salesforce.com/scrt2.js', // scrt2Url
511
511
  'en-US', // locale.id
512
- 'test-refresh-token' // refreshToken
512
+ 'test-refresh-token', // refreshToken
513
+ 'true' // enableAgentFromFloatingButton (default)
514
+ )
515
+ })
516
+
517
+ test('should call useMiaw with enableAgentFromFloatingButton false when configured', () => {
518
+ const props = {
519
+ ...defaultProps,
520
+ commerceAgentConfiguration: {
521
+ ...commerceAgentSettings,
522
+ enableAgentFromFloatingButton: 'false'
523
+ }
524
+ }
525
+
526
+ render(<ShopperAgent {...props} />)
527
+
528
+ expect(mockedUseMiaw).toHaveBeenCalledWith(
529
+ {loaded: true, error: false},
530
+ 'test-org-id',
531
+ 'test-service',
532
+ 'https://test.salesforce.com',
533
+ 'https://test.salesforce.com/scrt2.js',
534
+ 'en-US',
535
+ 'test-refresh-token',
536
+ 'false' // enableAgentFromFloatingButton
513
537
  )
514
538
  })
515
539
 
@@ -73,13 +73,15 @@ const normalizeLocaleToSalesforce = (locale) => {
73
73
  * @param {string} embeddedServiceDeploymentUrl - URL of the embedded service deployment
74
74
  * @param {string} scrt2Url - SCRT2 URL for the embedded messaging service
75
75
  * @param {string} locale - BCP-47 locale for the embedded messaging service
76
+ * @param {string} [enableAgentFromFloatingButton='true'] - When 'false', hides the floating chat button on load
76
77
  */
77
78
  const initEmbeddedMessaging = (
78
79
  salesforceOrgId,
79
80
  embeddedServiceDeploymentName,
80
81
  embeddedServiceDeploymentUrl,
81
82
  scrt2Url,
82
- locale
83
+ locale,
84
+ enableAgentFromFloatingButton = 'true'
83
85
  ) => {
84
86
  try {
85
87
  if (
@@ -93,6 +95,9 @@ const initEmbeddedMessaging = (
93
95
  window.embeddedservice_bootstrap.settings.language = salesforceLanguage
94
96
  window.embeddedservice_bootstrap.settings.disableStreamingResponses = true
95
97
  window.embeddedservice_bootstrap.settings.enableUserInputForConversationWithBot = false
98
+ // Hide floating chat button when enableAgentFromFloatingButton is 'false'
99
+ window.embeddedservice_bootstrap.settings.hideChatButtonOnLoad =
100
+ enableAgentFromFloatingButton !== 'true'
96
101
  window.embeddedservice_bootstrap.init(
97
102
  salesforceOrgId,
98
103
  embeddedServiceDeploymentName,
@@ -117,6 +122,7 @@ const initEmbeddedMessaging = (
117
122
  * @param {string} scrt2Url - SCRT2 URL for the embedded messaging service
118
123
  * @param {string} locale - BCP-47 locale for the embedded messaging service
119
124
  * @param {string} refreshToken - Refresh token for the embedded messaging service
125
+ * @param {string} [enableAgentFromFloatingButton='true'] - When 'false', hides the floating chat button on load
120
126
  */
121
127
  const useMiaw = (
122
128
  scriptLoadStatus,
@@ -125,7 +131,8 @@ const useMiaw = (
125
131
  embeddedServiceDeploymentUrl,
126
132
  scrt2Url,
127
133
  locale,
128
- refreshToken
134
+ refreshToken,
135
+ enableAgentFromFloatingButton = 'true'
129
136
  ) => {
130
137
  useEffect(() => {
131
138
  if (scriptLoadStatus.loaded && !scriptLoadStatus.error) {
@@ -135,7 +142,7 @@ const useMiaw = (
135
142
  embeddedServiceDeploymentUrl,
136
143
  scrt2Url,
137
144
  locale,
138
- refreshToken
145
+ enableAgentFromFloatingButton
139
146
  )
140
147
  }
141
148
  }, [
@@ -145,7 +152,8 @@ const useMiaw = (
145
152
  embeddedServiceDeploymentUrl,
146
153
  scrt2Url,
147
154
  locale,
148
- refreshToken
155
+ refreshToken,
156
+ enableAgentFromFloatingButton
149
157
  ])
150
158
  }
151
159
 
@@ -141,6 +141,7 @@ describe('useMiaw hook', () => {
141
141
  expect(
142
142
  window.embeddedservice_bootstrap.settings.enableUserInputForConversationWithBot
143
143
  ).toBe(false)
144
+ expect(window.embeddedservice_bootstrap.settings.hideChatButtonOnLoad).toBe(false)
144
145
  expect(window.embeddedservice_bootstrap.init).toHaveBeenCalledWith(
145
146
  'test-org-id',
146
147
  'test-deployment',
@@ -167,6 +168,18 @@ describe('useMiaw hook', () => {
167
168
  expect(window.embeddedservice_bootstrap.init).not.toHaveBeenCalled()
168
169
  })
169
170
 
171
+ test('should hide floating chat button when enableAgentFromFloatingButton is false', () => {
172
+ renderHook(() =>
173
+ useMiaw(
174
+ mockScriptLoadStatus,
175
+ ...Object.values(mockParams),
176
+ 'false' // enableAgentFromFloatingButton
177
+ )
178
+ )
179
+
180
+ expect(window.embeddedservice_bootstrap.settings.hideChatButtonOnLoad).toBe(true)
181
+ })
182
+
170
183
  test('should handle different locale mappings', () => {
171
184
  const testCases = [
172
185
  {locale: 'en-US', expected: 'en_US'},
@@ -20,7 +20,8 @@ export const getCommerceAgentConfig = () => {
20
20
  siteId: '',
21
21
  enableConversationContext: 'false',
22
22
  conversationContext: [],
23
- enableAgentFromHeader: 'false'
23
+ enableAgentFromHeader: 'false',
24
+ enableAgentFromFloatingButton: 'false'
24
25
  }
25
26
  return getConfig().app.commerceAgent ?? defaults
26
27
  }
@@ -9,6 +9,10 @@ const onClient = typeof window !== 'undefined'
9
9
  /**
10
10
  * Launch the chat using the embedded service bootstrap API
11
11
  *
12
+ * When the floating chat button is hidden (hideChatButtonOnLoad=true), this function
13
+ * first shows the chat button via utilAPI.showChatButton() before launching the chat,
14
+ * ensuring the chat window opens correctly.
15
+ *
12
16
  * @function launchChat
13
17
  * @returns {void}
14
18
  */
@@ -16,12 +20,16 @@ export function launchChat() {
16
20
  if (!onClient) return
17
21
 
18
22
  try {
19
- // Launch chat using the embedded service bootstrap API
20
- if (
21
- window.embeddedservice_bootstrap?.utilAPI &&
22
- typeof window.embeddedservice_bootstrap.utilAPI.launchChat === 'function'
23
- ) {
24
- window.embeddedservice_bootstrap.utilAPI.launchChat()
23
+ const utilAPI = window.embeddedservice_bootstrap?.utilAPI
24
+ if (!utilAPI) return
25
+ const hideChatButtonOnLoad =
26
+ window.embeddedservice_bootstrap?.settings?.hideChatButtonOnLoad === true
27
+ if (hideChatButtonOnLoad && typeof utilAPI.showChatButton === 'function') {
28
+ utilAPI.showChatButton()
29
+ }
30
+
31
+ if (typeof utilAPI.launchChat === 'function') {
32
+ utilAPI.launchChat()
25
33
  }
26
34
  } catch (error) {
27
35
  console.error('Shopper Agent: Error launching chat', error)
@@ -80,6 +80,54 @@ describe('shopper-agent-utils', () => {
80
80
  expect(() => launchChat()).not.toThrow()
81
81
  })
82
82
 
83
+ test('should call showChatButton before launchChat when hideChatButtonOnLoad is true', () => {
84
+ const mockShowChatButton = jest.fn()
85
+ const mockLaunchChat = jest.fn()
86
+
87
+ global.window = {
88
+ embeddedservice_bootstrap: {
89
+ settings: {
90
+ hideChatButtonOnLoad: true
91
+ },
92
+ utilAPI: {
93
+ showChatButton: mockShowChatButton,
94
+ launchChat: mockLaunchChat
95
+ }
96
+ }
97
+ }
98
+
99
+ launchChat()
100
+
101
+ expect(mockShowChatButton).toHaveBeenCalledTimes(1)
102
+ expect(mockLaunchChat).toHaveBeenCalledTimes(1)
103
+ // showChatButton must be called before launchChat
104
+ expect(mockShowChatButton.mock.invocationCallOrder[0]).toBeLessThan(
105
+ mockLaunchChat.mock.invocationCallOrder[0]
106
+ )
107
+ })
108
+
109
+ test('should not call showChatButton when hideChatButtonOnLoad is false', () => {
110
+ const mockShowChatButton = jest.fn()
111
+ const mockLaunchChat = jest.fn()
112
+
113
+ global.window = {
114
+ embeddedservice_bootstrap: {
115
+ settings: {
116
+ hideChatButtonOnLoad: false
117
+ },
118
+ utilAPI: {
119
+ showChatButton: mockShowChatButton,
120
+ launchChat: mockLaunchChat
121
+ }
122
+ }
123
+ }
124
+
125
+ launchChat()
126
+
127
+ expect(mockShowChatButton).not.toHaveBeenCalled()
128
+ expect(mockLaunchChat).toHaveBeenCalledTimes(1)
129
+ })
130
+
83
131
  test('should handle errors and log error', () => {
84
132
  const mockLaunchChat = jest.fn(() => {
85
133
  throw new Error('Launch error')
package/config/default.js CHANGED
@@ -105,7 +105,7 @@ module.exports = {
105
105
  '**/*.json'
106
106
  ],
107
107
  ssrParameters: {
108
- ssrFunctionNodeVersion: '22.x',
108
+ ssrFunctionNodeVersion: '24.x',
109
109
  proxyConfigs: [
110
110
  {
111
111
  host: 'kv7kzm78.api.commercecloud.salesforce.com',
@@ -145,7 +145,7 @@ module.exports = {
145
145
  ],
146
146
  // Additional parameters that configure Express app behavior.
147
147
  ssrParameters: {
148
- ssrFunctionNodeVersion: '22.x',
148
+ ssrFunctionNodeVersion: '24.x',
149
149
  proxyConfigs: [
150
150
  {
151
151
  host: 'localhost:8888',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/retail-react-app",
3
- "version": "9.0.0",
3
+ "version": "9.1.0-nightly-20260217081023",
4
4
  "license": "See license in LICENSE",
5
5
  "author": "cc-pwa-kit@salesforce.com",
6
6
  "ccExtensibility": {
@@ -46,10 +46,10 @@
46
46
  "@loadable/component": "^5.15.3",
47
47
  "@peculiar/webcrypto": "^1.4.2",
48
48
  "@salesforce/cc-datacloud-typescript": "1.1.2",
49
- "@salesforce/commerce-sdk-react": "5.0.0",
50
- "@salesforce/pwa-kit-dev": "3.16.0",
51
- "@salesforce/pwa-kit-react-sdk": "3.16.0",
52
- "@salesforce/pwa-kit-runtime": "3.16.0",
49
+ "@salesforce/commerce-sdk-react": "5.1.0-nightly-20260217081023",
50
+ "@salesforce/pwa-kit-dev": "3.17.0-nightly-20260217081023",
51
+ "@salesforce/pwa-kit-react-sdk": "3.17.0-nightly-20260217081023",
52
+ "@salesforce/pwa-kit-runtime": "3.17.0-nightly-20260217081023",
53
53
  "@tanstack/react-query": "^4.28.0",
54
54
  "@tanstack/react-query-devtools": "^4.29.1",
55
55
  "@testing-library/dom": "^9.0.1",
@@ -95,8 +95,8 @@
95
95
  }
96
96
  },
97
97
  "engines": {
98
- "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0",
99
- "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0"
98
+ "node": "^18.0.0 || ^20.0.0 || ^22.0.0 || ^24.0.0",
99
+ "npm": "^9.0.0 || ^10.0.0 || ^11.0.0"
100
100
  },
101
101
  "bundlesize": [
102
102
  {
@@ -108,5 +108,5 @@
108
108
  "maxSize": "366 kB"
109
109
  }
110
110
  ],
111
- "gitHead": "6c5fadd745fbd4f666d0887f45d01719e86b3ead"
111
+ "gitHead": "e5934d1d14a90adf3438d383d60aac5ca57449ed"
112
112
  }