@shopgate/engage 7.32.0-beta.3 → 7.32.0-beta.5

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 (166) hide show
  1. package/admin-preview/components/FrontendSettingsPreviewBridge/FrontendSettingsPreviewBridge.d.ts +2 -1
  2. package/admin-preview/components/FrontendSettingsPreviewBridge/FrontendSettingsPreviewBridge.d.ts.map +1 -1
  3. package/admin-preview/components/FrontendSettingsPreviewBridge/FrontendSettingsPreviewBridge.js +23 -1
  4. package/admin-preview/components/FrontendSettingsPreviewBridge/helpers.d.ts +7 -1
  5. package/admin-preview/components/FrontendSettingsPreviewBridge/helpers.d.ts.map +1 -1
  6. package/admin-preview/components/FrontendSettingsPreviewBridge/helpers.js +14 -2
  7. package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts +6 -0
  8. package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts.map +1 -1
  9. package/components/Badge/Badge.d.ts +30 -0
  10. package/components/Badge/Badge.d.ts.map +1 -0
  11. package/components/Badge/Badge.js +48 -0
  12. package/components/Badge/index.d.ts +3 -0
  13. package/components/Badge/index.d.ts.map +1 -0
  14. package/components/Badge/index.js +1 -0
  15. package/components/Badge/spec.d.ts +2 -0
  16. package/components/Badge/spec.d.ts.map +1 -0
  17. package/components/Badge/spec.js +75 -0
  18. package/components/View/components/Content/index.d.ts.map +1 -1
  19. package/components/View/components/Content/index.js +4 -1
  20. package/components/index.d.ts +1 -0
  21. package/components/index.d.ts.map +1 -1
  22. package/components/index.js +2 -1
  23. package/core/hooks/useLocalStorage.d.ts +8 -0
  24. package/core/hooks/useLocalStorage.d.ts.map +1 -1
  25. package/core/hooks/useLocalStorage.js +22 -15
  26. package/core/initialization/fetchSettings.d.ts +12 -0
  27. package/core/initialization/fetchSettings.d.ts.map +1 -0
  28. package/core/initialization/fetchSettings.js +134 -0
  29. package/core/initialization/index.d.ts +33 -2
  30. package/core/initialization/index.d.ts.map +1 -1
  31. package/core/initialization/index.js +25 -103
  32. package/package.json +9 -9
  33. package/page/components/NotFound.d.ts +7 -0
  34. package/page/components/NotFound.d.ts.map +1 -0
  35. package/page/components/NotFound.js +1 -2
  36. package/page/components/ResponsiveWidgetImage/ResponsiveWidgetImage.d.ts +52 -0
  37. package/page/components/ResponsiveWidgetImage/ResponsiveWidgetImage.d.ts.map +1 -0
  38. package/page/components/ResponsiveWidgetImage/index.d.ts +2 -0
  39. package/page/components/ResponsiveWidgetImage/index.d.ts.map +1 -0
  40. package/page/components/WidgetRichText/WidgetRichText.d.ts +25 -0
  41. package/page/components/WidgetRichText/WidgetRichText.d.ts.map +1 -0
  42. package/page/components/WidgetRichText/index.d.ts +2 -0
  43. package/page/components/WidgetRichText/index.d.ts.map +1 -0
  44. package/page/components/WidgetVideo/WidgetVideo.d.ts +43 -0
  45. package/page/components/WidgetVideo/WidgetVideo.d.ts.map +1 -0
  46. package/page/components/WidgetVideo/WidgetVideo.js +33 -39
  47. package/page/components/WidgetVideo/index.d.ts +2 -0
  48. package/page/components/WidgetVideo/index.d.ts.map +1 -0
  49. package/page/components/Widgets/Overlay.d.ts +17 -0
  50. package/page/components/Widgets/Overlay.d.ts.map +1 -0
  51. package/page/components/Widgets/Overlay.js +24 -38
  52. package/page/components/Widgets/Tooltip.d.ts +20 -0
  53. package/page/components/Widgets/Tooltip.d.ts.map +1 -0
  54. package/page/components/Widgets/Tooltip.js +6 -10
  55. package/page/components/Widgets/Widget.d.ts +32 -0
  56. package/page/components/Widgets/Widget.d.ts.map +1 -0
  57. package/page/components/Widgets/Widget.js +7 -18
  58. package/page/components/Widgets/WidgetContext.d.ts +32 -38
  59. package/page/components/Widgets/WidgetContext.d.ts.map +1 -0
  60. package/page/components/Widgets/WidgetContext.js +2 -8
  61. package/page/components/Widgets/WidgetProvider.d.ts +25 -0
  62. package/page/components/Widgets/WidgetProvider.d.ts.map +1 -0
  63. package/page/components/Widgets/WidgetProvider.js +5 -12
  64. package/page/components/Widgets/Widgets.d.ts +16 -0
  65. package/page/components/Widgets/Widgets.d.ts.map +1 -0
  66. package/page/components/Widgets/Widgets.js +5 -12
  67. package/page/components/Widgets/WidgetsPreviewContext.d.ts +21 -0
  68. package/page/components/Widgets/WidgetsPreviewContext.d.ts.map +1 -0
  69. package/page/components/Widgets/WidgetsPreviewContext.js +5 -7
  70. package/page/components/Widgets/WidgetsPreviewProvider.d.ts +18 -0
  71. package/page/components/Widgets/WidgetsPreviewProvider.d.ts.map +1 -0
  72. package/page/components/Widgets/WidgetsPreviewProvider.js +5 -6
  73. package/page/components/Widgets/constants.d.ts +5 -0
  74. package/page/components/Widgets/constants.d.ts.map +1 -0
  75. package/page/components/Widgets/constants.js +3 -1
  76. package/page/components/Widgets/events.d.ts +38 -0
  77. package/page/components/Widgets/events.d.ts.map +1 -0
  78. package/page/components/Widgets/events.js +8 -12
  79. package/page/components/Widgets/helpers.d.ts +50 -0
  80. package/page/components/Widgets/helpers.d.ts.map +1 -0
  81. package/page/components/Widgets/helpers.js +8 -13
  82. package/page/components/Widgets/hooks.d.ts +13 -0
  83. package/page/components/Widgets/hooks.d.ts.map +1 -0
  84. package/page/components/Widgets/hooks.js +13 -11
  85. package/page/components/Widgets/index.d.ts +3 -0
  86. package/page/components/Widgets/index.d.ts.map +1 -0
  87. package/page/components/Widgets/types.d.ts +111 -113
  88. package/page/components/Widgets/types.d.ts.map +1 -0
  89. package/page/components/Widgets/types.js +1 -0
  90. package/page/components/index.d.ts +5 -0
  91. package/page/components/index.d.ts.map +1 -0
  92. package/page/constants/actionTypes.d.ts +4 -0
  93. package/page/constants/actionTypes.d.ts.map +1 -0
  94. package/page/constants/index.d.ts +25 -0
  95. package/page/constants/index.d.ts.map +1 -0
  96. package/page/helpers/index.d.ts +67 -62
  97. package/page/helpers/index.d.ts.map +1 -0
  98. package/page/helpers/index.js +24 -25
  99. package/page/hooks/index.d.ts +54 -53
  100. package/page/hooks/index.d.ts.map +1 -0
  101. package/page/hooks/index.js +20 -15
  102. package/page/selectors/index.d.ts +32 -0
  103. package/page/selectors/index.d.ts.map +1 -0
  104. package/page/widgets/Video/Video.d.ts +6 -0
  105. package/page/widgets/Video/Video.d.ts.map +1 -0
  106. package/page/widgets/Video/Video.js +0 -2
  107. package/page/widgets/Video/hooks.d.ts +53 -0
  108. package/page/widgets/Video/hooks.d.ts.map +1 -0
  109. package/page/widgets/Video/hooks.js +4 -12
  110. package/page/widgets/Video/index.d.ts +2 -0
  111. package/page/widgets/Video/index.d.ts.map +1 -0
  112. package/product/components/Description/index.js +0 -2
  113. package/product/components/ProductCard/index.js +1 -0
  114. package/product/components/ProductGrid/components/Item/components/ItemDetails/index.js +1 -1
  115. package/product/components/ProductGrid/components/Item/components/ItemImage/index.js +10 -0
  116. package/product/components/ProductGrid/components/Item/components/ItemName/index.js +1 -0
  117. package/product/components/ProductGrid/components/Item/index.js +0 -1
  118. package/product/components/ProductGrid/components/Layout/index.js +17 -3
  119. package/product/components/ProductGrid/constants.d.ts +2 -0
  120. package/product/components/ProductGrid/constants.d.ts.map +1 -0
  121. package/product/components/ProductGrid/constants.js +1 -0
  122. package/product/components/ProductGrid/hooks.d.ts +18 -0
  123. package/product/components/ProductGrid/hooks.d.ts.map +1 -0
  124. package/product/components/ProductGrid/hooks.js +49 -0
  125. package/product/components/ProductGrid/index.js +3 -6
  126. package/product/components/ProductGrid/spec.js +3 -0
  127. package/product/components/ProductList/components/Layout/index.js +8 -20
  128. package/settings/reducers/appSettings.d.ts.map +1 -1
  129. package/settings/reducers/appSettings.js +8 -0
  130. package/settings/selectors/appSettings.d.ts +8 -0
  131. package/settings/selectors/appSettings.d.ts.map +1 -1
  132. package/settings/selectors/appSettings.js +6 -1
  133. package/settings/types/appSettings.d.ts +21 -0
  134. package/settings/types/appSettings.d.ts.map +1 -1
  135. package/styles/helpers/index.d.ts +1 -0
  136. package/styles/helpers/index.js +1 -0
  137. package/styles/helpers/loadThemeCss.d.ts +14 -0
  138. package/styles/helpers/loadThemeCss.d.ts.map +1 -0
  139. package/styles/helpers/loadThemeCss.js +112 -0
  140. package/styles/index.d.ts +1 -1
  141. package/styles/index.d.ts.map +1 -1
  142. package/styles/reset/root.js +1 -1
  143. package/styles/theme/createDefaultThemeOptions/index.d.ts.map +1 -1
  144. package/styles/theme/createDefaultThemeOptions/index.js +12 -1
  145. package/styles/theme/createTheme/createComponents.types.d.ts +22 -0
  146. package/styles/theme/createTheme/createComponents.types.d.ts.map +1 -1
  147. package/styles/theme/createTheme/createComponents.types.js +23 -1
  148. package/styles/theme/createTheme/createCssVarsForColorSchemeThemes.d.ts.map +1 -1
  149. package/styles/theme/createTheme/createCssVarsForColorSchemeThemes.js +4 -1
  150. package/styles/theme/createTheme/index.d.ts +1 -0
  151. package/styles/theme/createTheme/index.d.ts.map +1 -1
  152. package/styles/theme/createTheme/index.js +2 -0
  153. package/styles/theme/createTheme/types.d.ts +2 -2
  154. package/styles/theme/createTheme/types.d.ts.map +1 -1
  155. package/styles/theme/createTheme/types.js +2 -3
  156. package/styles/theme/hooks/useColorScheme.d.ts +4 -3
  157. package/styles/theme/hooks/useColorScheme.d.ts.map +1 -1
  158. package/styles/theme/hooks/useColorScheme.js +4 -3
  159. package/styles/theme/index.d.ts +1 -1
  160. package/styles/theme/index.d.ts.map +1 -1
  161. package/styles/theme/providers/ColorSchemeContext.d.ts +19 -0
  162. package/styles/theme/providers/ColorSchemeContext.d.ts.map +1 -0
  163. package/styles/theme/providers/ColorSchemeContext.js +6 -0
  164. package/styles/theme/providers/ThemeProvider.d.ts +2 -12
  165. package/styles/theme/providers/ThemeProvider.d.ts.map +1 -1
  166. package/styles/theme/providers/ThemeProvider.js +32 -8
@@ -0,0 +1,134 @@
1
+ import { withScope, captureMessage, Severity as SentrySeverity } from '@sentry/browser';
2
+ import appConfig from '@shopgate/pwa-common/helpers/config';
3
+ import { receiveShopSettings, errorShopSettings } from '@shopgate/engage/settings/action-creators/shopSettings';
4
+ import { receiveMerchantSettings } from '@shopgate/engage/settings/action-creators/merchantSettings';
5
+ import { receiveAppSettings } from '@shopgate/engage/settings/action-creators/appSettings';
6
+ const REQUEST_TIMEOUT = 3000;
7
+
8
+ /**
9
+ * The payload types the settings action creators declare. Derived rather than written out,
10
+ * because shopSettings and merchantSettings are untyped JS whose JSDoc describes their payload
11
+ * as `{Array}` / `{Object}` whereas the JSONP files actually send a settings object. Deriving
12
+ * keeps this file honest about the mismatch and picks up the real types once that JSDoc is fixed.
13
+ */
14
+
15
+ /**
16
+ * Injects a script tag to fetch a settings JSONP.
17
+ * @param id The script id.
18
+ * @param src The script url.
19
+ * @param onError Callback for error situations.
20
+ */
21
+ const injectScript = (id, src, onError) => {
22
+ const existingTag = document.querySelector(`#${id}`);
23
+ if (existingTag) {
24
+ existingTag.remove();
25
+ }
26
+ const scriptTag = document.createElement('script');
27
+ scriptTag.setAttribute('src', src);
28
+ scriptTag.setAttribute('id', id);
29
+ scriptTag.onerror = onError;
30
+ document.head.appendChild(scriptTag);
31
+ };
32
+
33
+ /**
34
+ * Loads a single JSONP settings source. Resolves when the payload arrived, when the script
35
+ * failed to load, or when REQUEST_TIMEOUT elapsed - it never rejects, so that no single
36
+ * source can block or delay app start indefinitely.
37
+ * @param params The loader params.
38
+ * @returns A promise that resolves once the source settled.
39
+ */
40
+ const loadJsonpSettings = params => new Promise(resolve => {
41
+ const {
42
+ id,
43
+ url,
44
+ callbackName,
45
+ onReceive,
46
+ onError
47
+ } = params;
48
+ let settled = false;
49
+ let timeout;
50
+
51
+ /**
52
+ * Resolves the promise once, whichever of payload / error / timeout comes first.
53
+ */
54
+ const settle = () => {
55
+ if (settled) {
56
+ return;
57
+ }
58
+ settled = true;
59
+ clearTimeout(timeout);
60
+ resolve();
61
+ };
62
+
63
+ // Started before the callback and the script are wired up, so that a synchronously firing
64
+ // callback / error (e.g. a data: url) settles against an already assigned timeout - otherwise
65
+ // clearTimeout would no-op and this timer would still fire a false timeout warning.
66
+ timeout = setTimeout(() => {
67
+ withScope(scope => {
68
+ scope.setLevel(SentrySeverity.Warning);
69
+ scope.setExtra('settingsUrl', url);
70
+ scope.setExtra('timeout', REQUEST_TIMEOUT);
71
+ captureMessage(`Fetching settings took too long: ${id}`);
72
+ });
73
+ settle();
74
+ }, REQUEST_TIMEOUT);
75
+
76
+ // Registered before the script is injected, since the JSONP files guard their call with
77
+ // `window.setX && window.setX(...)` - a callback assigned too late is a silent no-op.
78
+ // Deliberately never removed: the timeout may settle while the script is still in flight,
79
+ // and a payload arriving after that should still hydrate the store.
80
+ window[callbackName] = settings => {
81
+ onReceive(settings);
82
+ settle();
83
+ };
84
+ injectScript(id, url, error => {
85
+ withScope(scope => {
86
+ scope.setLevel(SentrySeverity.Error);
87
+ scope.setExtra('settingsUrl', url);
88
+ captureMessage(`Fetching settings failed: ${id}`);
89
+ });
90
+ onError?.(error);
91
+ settle();
92
+ });
93
+ });
94
+
95
+ /**
96
+ * Fetches all configured JSONP settings sources in parallel. Sources without a configured url
97
+ * are skipped. Never rejects - every source falls back to the defaults of its reducer.
98
+ * @param store Reference to the store.
99
+ * @returns A promise that resolves once all configured sources settled.
100
+ */
101
+ export const fetchSettings = async store => {
102
+ const {
103
+ settingsUrl,
104
+ merchantSettingsUrl,
105
+ appSettingsUrl
106
+ } = appConfig;
107
+ const loaders = [];
108
+ if (settingsUrl) {
109
+ loaders.push(loadJsonpSettings({
110
+ id: 'shop-settings-jsonp',
111
+ url: settingsUrl,
112
+ callbackName: 'setShopSettings',
113
+ onReceive: settings => store.dispatch(receiveShopSettings(settings)),
114
+ onError: error => store.dispatch(errorShopSettings(error))
115
+ }));
116
+ }
117
+ if (merchantSettingsUrl) {
118
+ loaders.push(loadJsonpSettings({
119
+ id: 'merchant-settings-jsonp',
120
+ url: merchantSettingsUrl,
121
+ callbackName: 'setMerchantSettings',
122
+ onReceive: settings => store.dispatch(receiveMerchantSettings(settings))
123
+ }));
124
+ }
125
+ if (appSettingsUrl) {
126
+ loaders.push(loadJsonpSettings({
127
+ id: 'app-settings-jsonp',
128
+ url: appSettingsUrl,
129
+ callbackName: 'setAppSettings',
130
+ onReceive: settings => store.dispatch(receiveAppSettings(settings))
131
+ }));
132
+ }
133
+ await Promise.all(loaders);
134
+ };
@@ -1,4 +1,35 @@
1
- export function initialize(locales: Object, reducers: Function, subscribers: any[]): Promise<{
2
- store: Object;
1
+ import type { Store as ReduxStore, UnknownAction } from 'redux';
2
+ import { configureStore } from '@shopgate/pwa-common/store';
3
+ declare global {
4
+ interface Window {
5
+ SGConnectDev?: {
6
+ isDevBrowser: boolean;
7
+ isDev: boolean;
8
+ };
9
+ }
10
+ }
11
+ /**
12
+ * The app's redux store. Assembled here because configureStore is untyped JS whose JSDoc widens
13
+ * the return value to `Object`.
14
+ *
15
+ * dispatch stays permissive rather than using redux-thunk's ThunkDispatch: the action creators
16
+ * this module dispatches are untyped JS annotated `@returns {Object}` / `{Function}`, which match
17
+ * neither UnknownAction nor ThunkAction. Tightening it here would only force casts at every call
18
+ * site - it needs the JSDoc on those action creators to be fixed first.
19
+ */
20
+ type Store = Omit<ReduxStore<unknown, UnknownAction>, 'dispatch'> & {
21
+ dispatch: (action: unknown) => unknown;
22
+ };
23
+ /**
24
+ * Initializes the app: sets up i18n, creates the store, fetches the client information and the
25
+ * dynamic settings, and runs all registered app initialization handlers.
26
+ * @param locales An object with locales.
27
+ * @param reducers The reducers from the theme.
28
+ * @param subscribers The subscribers to the streams middleware.
29
+ * @returns The initialized store.
30
+ */
31
+ export declare const initialize: (locales: Record<string, unknown>, reducers: Parameters<typeof configureStore>[0], subscribers: Parameters<typeof configureStore>[1]) => Promise<{
32
+ store: Store;
3
33
  }>;
34
+ export {};
4
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/initialization/index.js"],"names":[],"mappings":"AAuIO,oCAJI,MAAM;;GAuDhB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../core/initialization/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,IAAI,UAAU,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAgB5D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,YAAY,CAAC,EAAE;YACb,YAAY,EAAE,OAAO,CAAC;YACtB,KAAK,EAAE,OAAO,CAAC;SAChB,CAAC;KACH;CACF;AAED;;;;;;;;GAQG;AACH,KAAK,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,UAAU,CAAC,GAAG;IAClE,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;CACxC,CAAC;AAMF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,GACrB,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,UAAU,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,EAC9C,aAAa,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;;EAuDlD,CAAC"}
@@ -1,118 +1,37 @@
1
- import { withScope, captureMessage, Severity as SentrySeverity } from '@sentry/browser';
2
1
  import moment from 'moment';
3
2
  import { configureStore } from '@shopgate/pwa-common/store';
4
3
  import { appWillInit, appWillStart } from '@shopgate/pwa-common/action-creators/app';
5
4
  import { i18n, getAppBaseUrl, isDev, hasSGJavaScriptBridge, hasWebBridge } from '@shopgate/engage/core/helpers';
6
5
  import fetchClientInformation from '@shopgate/pwa-common/actions/client/fetchClientInformation';
7
- import appConfig from '@shopgate/pwa-common/helpers/config';
6
+ import { appConfig } from '@shopgate/engage';
8
7
  import { appInitialization, configuration } from '@shopgate/engage/core/collections';
9
8
  import { CONFIGURATION_COLLECTION_KEY_BASE_URL } from '@shopgate/engage/core/constants';
10
- import { loadCustomStyles } from '@shopgate/engage/styles';
11
- import { receiveShopSettings, errorShopSettings } from '@shopgate/engage/settings/action-creators/shopSettings';
12
- import { receiveMerchantSettings } from '@shopgate/engage/settings/action-creators/merchantSettings';
13
- const {
14
- locales: {
15
- currency: currencyLocale = null
16
- } = {},
17
- settingsUrl,
18
- merchantSettingsUrl
19
- } = appConfig;
20
- const REQUEST_TIMEOUT = 3000;
21
- /**
22
- * Injects a script tag to fetch the shop settings JSONP.
23
- * @param {string} id The script id
24
- * @param {string} src The script url
25
- * @param {Function} onError Callback for error situations.
26
- */
27
- const injectScript = (id, src, onError) => {
28
- let scriptTag = document.querySelector(`#${id}`);
29
- if (scriptTag) {
30
- scriptTag.remove();
31
- }
32
- scriptTag = document.createElement('script');
33
- scriptTag.setAttribute('src', src);
34
- scriptTag.setAttribute('id', id);
35
- scriptTag.onerror = onError;
36
- document.querySelector('head').appendChild(scriptTag);
37
- };
9
+ import { loadCustomStyles, loadThemeCss } from '@shopgate/engage/styles';
10
+ import { fetchSettings } from "./fetchSettings";
38
11
 
39
12
  /**
40
- * Fetches settings
41
- * @param {Object} store Reference to the store
42
- * @returns {Promise}
13
+ * The app's redux store. Assembled here because configureStore is untyped JS whose JSDoc widens
14
+ * the return value to `Object`.
15
+ *
16
+ * dispatch stays permissive rather than using redux-thunk's ThunkDispatch: the action creators
17
+ * this module dispatches are untyped JS annotated `@returns {Object}` / `{Function}`, which match
18
+ * neither UnknownAction nor ThunkAction. Tightening it here would only force casts at every call
19
+ * site - it needs the JSDoc on those action creators to be fixed first.
43
20
  */
44
- const fetchSettings = store => new Promise((resolve, reject) => {
45
- if (!settingsUrl) {
46
- reject();
47
- return;
48
- }
49
- let timeout;
50
- let merchantReceived = null;
51
- let shopReceived = null;
52
-
53
- /**
54
- * Evaluates if completed.
55
- */
56
- const evaluateEnd = () => {
57
- if (!merchantReceived && merchantSettingsUrl || !shopReceived) {
58
- return;
59
- }
60
- clearTimeout(timeout);
61
- timeout = null;
62
- resolve();
63
- };
64
21
 
65
- // Add the callbacks for the JSONP
66
- window.setShopSettings = settings => {
67
- store.dispatch(receiveShopSettings(settings));
68
- shopReceived = true;
69
- evaluateEnd();
70
- };
71
- window.setMerchantSettings = settings => {
72
- store.dispatch(receiveMerchantSettings(settings));
73
- merchantReceived = true;
74
- evaluateEnd();
75
- };
76
-
77
- // Error handling
78
- injectScript('shop-settings-jsonp', settingsUrl, error => {
79
- withScope(scope => {
80
- scope.setLevel(SentrySeverity.Error);
81
- scope.setExtra('settingsUrl', settingsUrl);
82
- captureMessage('Fetching shop settings failed');
83
- });
84
- clearTimeout(timeout);
85
- timeout = null;
86
- store.dispatch(errorShopSettings(error));
87
- reject();
88
- });
89
- if (merchantSettingsUrl) {
90
- injectScript('merchant-settings-jsonp', merchantSettingsUrl, () => {
91
- withScope(scope => {
92
- scope.setLevel(SentrySeverity.Error);
93
- scope.setExtra('settingsUrl', merchantSettingsUrl);
94
- captureMessage('Fetching merchant settings failed');
95
- });
96
- clearTimeout(timeout);
97
- timeout = null;
98
- reject();
99
- });
100
- }
101
- timeout = setTimeout(() => {
102
- withScope(scope => {
103
- scope.setLevel(SentrySeverity.Warning);
104
- scope.setExtra('settingsUrl', settingsUrl);
105
- scope.setExtra('timeout', REQUEST_TIMEOUT);
106
- captureMessage('Fetching shop settings took too long');
107
- });
108
- }, REQUEST_TIMEOUT);
109
- });
22
+ const {
23
+ locales: {
24
+ currency: currencyLocale = null
25
+ } = {}
26
+ } = appConfig;
110
27
 
111
28
  /**
112
- *
113
- * @param {Object} locales An object with locales.
114
- * @param {Function} reducers The reducers from the theme.
115
- * @param {Array} subscribers The subscribers to the streams middleware.
29
+ * Initializes the app: sets up i18n, creates the store, fetches the client information and the
30
+ * dynamic settings, and runs all registered app initialization handlers.
31
+ * @param locales An object with locales.
32
+ * @param reducers The reducers from the theme.
33
+ * @param subscribers The subscribers to the streams middleware.
34
+ * @returns The initialized store.
116
35
  */
117
36
  export const initialize = async (locales, reducers, subscribers) => {
118
37
  moment.locale(process.env.LOCALE);
@@ -142,7 +61,10 @@ export const initialize = async (locales, reducers, subscribers) => {
142
61
  configuration.set(CONFIGURATION_COLLECTION_KEY_BASE_URL, getAppBaseUrl());
143
62
  store.dispatch(appWillInit(`${window.location.pathname}${window.location.search}`));
144
63
  try {
145
- const promises = [fetchSettings(store), loadCustomStyles()];
64
+ // The order of the style loaders does not affect the cascade: loadThemeCss pins its link to
65
+ // the theme css insertion point in the html template, while loadCustomStyles appends its link
66
+ // to the end of the head.
67
+ const promises = [fetchSettings(store), loadCustomStyles(), loadThemeCss()];
146
68
  await Promise.all(promises);
147
69
  } catch (e) {
148
70
  // Nothing to see here.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopgate/engage",
3
- "version": "7.32.0-beta.3",
3
+ "version": "7.32.0-beta.5",
4
4
  "description": "Shopgate's ENGAGE library.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Shopgate <support@shopgate.com>",
@@ -17,13 +17,13 @@
17
17
  "scripts": {},
18
18
  "dependencies": {
19
19
  "@emotion/react": "^11.14.0",
20
- "@shopgate/native-modules": "1.0.0-beta.25",
21
- "@shopgate/pwa-common": "7.32.0-beta.3",
22
- "@shopgate/pwa-common-commerce": "7.32.0-beta.3",
23
- "@shopgate/pwa-core": "7.32.0-beta.3",
24
- "@shopgate/pwa-ui-ios": "7.32.0-beta.3",
25
- "@shopgate/pwa-ui-material": "7.32.0-beta.3",
26
- "@shopgate/pwa-ui-shared": "7.32.0-beta.3",
20
+ "@shopgate/native-modules": "1.0.0-beta.32",
21
+ "@shopgate/pwa-common": "7.32.0-beta.5",
22
+ "@shopgate/pwa-common-commerce": "7.32.0-beta.5",
23
+ "@shopgate/pwa-core": "7.32.0-beta.5",
24
+ "@shopgate/pwa-ui-ios": "7.32.0-beta.5",
25
+ "@shopgate/pwa-ui-material": "7.32.0-beta.5",
26
+ "@shopgate/pwa-ui-shared": "7.32.0-beta.5",
27
27
  "@stripe/react-stripe-js": "^1.16.5",
28
28
  "@stripe/stripe-js": "^1.44.1",
29
29
  "@virtuous/conductor": "~2.5.0",
@@ -46,7 +46,7 @@
46
46
  "validate.js": "^0.13.1"
47
47
  },
48
48
  "devDependencies": {
49
- "@shopgate/pwa-unit-test": "7.32.0-beta.3",
49
+ "@shopgate/pwa-unit-test": "7.31.3",
50
50
  "@types/color": "^4.2.0",
51
51
  "@types/lodash": "^4.17.24",
52
52
  "@types/react-dom": "^17.0.2",
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The NotFoundPage component renders a "Page Not Found" view
3
+ * with options to navigate back or to the home page.
4
+ */
5
+ declare const NotFound: () => import("react").JSX.Element;
6
+ export default NotFound;
7
+ //# sourceMappingURL=NotFound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotFound.d.ts","sourceRoot":"","sources":["../../../page/components/NotFound.tsx"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,QAAA,MAAM,QAAQ,mCA2Bb,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -1,4 +1,4 @@
1
- import React, { useCallback } from 'react';
1
+ import { useCallback } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
3
  import RippleButton from '@shopgate/pwa-ui-shared/RippleButton';
4
4
  import { I18n, Typography } from '@shopgate/engage/components';
@@ -32,7 +32,6 @@ const useStyles = makeStyles()(theme => ({
32
32
  /**
33
33
  * The NotFoundPage component renders a "Page Not Found" view
34
34
  * with options to navigate back or to the home page.
35
- * @returns {JSX.Element}
36
35
  */
37
36
  const NotFound = () => {
38
37
  const {
@@ -0,0 +1,52 @@
1
+ export default Protector;
2
+ export type OnImageRatioChange = (ratio: string) => any;
3
+ export type CustomResponsiveImageProps = {
4
+ /**
5
+ * Whether to enable the parallax effect.
6
+ */
7
+ enableParallax?: boolean | undefined;
8
+ /**
9
+ * The border radius to apply to the image.
10
+ */
11
+ borderRadius?: number | undefined;
12
+ /**
13
+ * The breakpoint from which on a higher resolution image should
14
+ * be loaded.
15
+ */
16
+ breakpoint?: import("../../../styles/theme").Breakpoint | undefined;
17
+ /**
18
+ * Whether the image is used as a banner (full width and height of
19
+ * its container).
20
+ */
21
+ isBanner?: boolean | undefined;
22
+ /**
23
+ * Called when the aspect ratio of the image
24
+ * changes.
25
+ */
26
+ onImageRatioChange?: OnImageRatioChange | undefined;
27
+ };
28
+ export type Theme = import("@shopgate/engage/styles").Theme;
29
+ export type Breakpoint = Theme["breakpoints"]["keys"][0];
30
+ export type ImgProps = React.ImgHTMLAttributes<HTMLImageElement>;
31
+ export type ResponsiveImageProps = CustomResponsiveImageProps & ImgProps;
32
+ /**
33
+ * The ResponsiveWidgetImage component renders an image that adapts to different screen sizes.
34
+ * It renders a image with higher resolution on larger screens
35
+ * It can apply a parallax effect when scrolling.
36
+ *
37
+ * @param {ResponsiveImageProps} props The component props.
38
+ * @returns {JSX.Element}
39
+ */
40
+ declare function Protector({ src, ...rest }: ResponsiveImageProps): JSX.Element;
41
+ declare namespace Protector {
42
+ namespace propTypes {
43
+ let src: PropTypes.Requireable<string>;
44
+ }
45
+ namespace defaultProps {
46
+ let src_1: null;
47
+ export { src_1 as src };
48
+ }
49
+ }
50
+ import React from 'react';
51
+ import PropTypes from 'prop-types';
52
+ //# sourceMappingURL=ResponsiveWidgetImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResponsiveWidgetImage.d.ts","sourceRoot":"","sources":["../../../../page/components/ResponsiveWidgetImage/ResponsiveWidgetImage.jsx"],"names":[],"mappings":";yCASW,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;oBAeH,OAAO,yBAAyB,EAAE,KAAK;yBACvC,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;uBAC/B,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;mCACzC,0BAA0B,GAAG,QAAQ;AAgKnD;;;;;;;GAOG;AACH,6CAHW,oBAAoB,GAClB,GAAG,CAAC,OAAO,CASvB;;;;;;;;;;kBA1MmD,OAAO;sBACrC,YAAY"}
@@ -0,0 +1,2 @@
1
+ export { default } from "./ResponsiveWidgetImage";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../page/components/ResponsiveWidgetImage/index.js"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ export default WidgetRichText;
2
+ /**
3
+ * @param {Object} props The component props.
4
+ * @param {string} props.content The rich text content.
5
+ * @param {string} [props.className] An optional class name.
6
+ * @returns {JSX.Element}
7
+ */
8
+ declare function WidgetRichText({ content, className, }: {
9
+ content: string;
10
+ className?: string | undefined;
11
+ }): JSX.Element;
12
+ declare namespace WidgetRichText {
13
+ namespace propTypes {
14
+ let className: PropTypes.Requireable<string>;
15
+ let content: PropTypes.Requireable<string>;
16
+ }
17
+ namespace defaultProps {
18
+ let content_1: string;
19
+ export { content_1 as content };
20
+ let className_1: null;
21
+ export { className_1 as className };
22
+ }
23
+ }
24
+ import PropTypes from 'prop-types';
25
+ //# sourceMappingURL=WidgetRichText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetRichText.d.ts","sourceRoot":"","sources":["../../../../page/components/WidgetRichText/WidgetRichText.jsx"],"names":[],"mappings":";AA2DA;;;;;GAKG;AACH,yDAJG;IAAsB,OAAO,EAArB,MAAM;IACS,SAAS;CAChC,GAAU,GAAG,CAAC,OAAO,CAmBvB;;;;;;;;;;;;;sBAjFqB,YAAY"}
@@ -0,0 +1,2 @@
1
+ export { default } from "./WidgetRichText";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../page/components/WidgetRichText/index.js"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Props of the {@link WidgetVideo} component.
3
+ */
4
+ export interface WidgetVideoProps {
5
+ /**
6
+ * Whether the video is used in a banner.
7
+ */
8
+ isBanner?: boolean;
9
+ /**
10
+ * The video URL.
11
+ */
12
+ url?: string | null;
13
+ /**
14
+ * Whether the video is muted.
15
+ */
16
+ muted?: boolean;
17
+ /**
18
+ * Whether the video is looping.
19
+ */
20
+ loop?: boolean;
21
+ /**
22
+ * Whether the video controls are shown.
23
+ */
24
+ controls?: boolean;
25
+ /**
26
+ * Whether the video should autoplay.
27
+ */
28
+ autoplay?: boolean;
29
+ /**
30
+ * The border radius value.
31
+ */
32
+ borderRadius?: number;
33
+ /**
34
+ * The link URL.
35
+ */
36
+ link?: string | null;
37
+ }
38
+ /**
39
+ * The WidgetVideo component is used to display a video in a widget.
40
+ */
41
+ declare const WidgetVideo: ({ isBanner, url, muted, loop, controls, autoplay, borderRadius, link, }: WidgetVideoProps) => import("react").JSX.Element | null;
42
+ export default WidgetVideo;
43
+ //# sourceMappingURL=WidgetVideo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetVideo.d.ts","sourceRoot":"","sources":["../../../../page/components/WidgetVideo/WidgetVideo.tsx"],"names":[],"mappings":"AAsDA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,QAAA,MAAM,WAAW,GAAI,yEASlB,gBAAgB,uCAsFlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,11 +1,19 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import { useEffect, useMemo, useState, useRef } from 'react';
2
2
  import { makeStyles } from '@shopgate/engage/styles';
3
3
  import { useReduceMotion } from '@shopgate/engage/a11y/hooks';
4
4
  import { usePrevious, useAppEventOnReturnFromBackground } from '@shopgate/engage/core/hooks';
5
- import { ConditionalWrapper, Link } from '@shopgate/engage/components';
6
- import PropTypes from 'prop-types';
5
+ import { ConditionalWrapper, Link as EngageLink } from '@shopgate/engage/components';
7
6
  import { isHttpsUrl } from "../../helpers";
7
+
8
+ // `Link` is a redux-connected component whose react-redux connect() typing resolves its own props
9
+ // (href/children) to `never`; alias it to its actual usable prop shape.
8
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
+ const Link = EngageLink;
12
+
13
+ /**
14
+ * Style parameters for the widget video.
15
+ */
16
+
9
17
  const useStyles = makeStyles()((_theme, {
10
18
  borderRadius
11
19
  }) => ({
@@ -36,28 +44,22 @@ const useStyles = makeStyles()((_theme, {
36
44
  }
37
45
  }));
38
46
 
47
+ /**
48
+ * Props of the {@link WidgetVideo} component.
49
+ */
50
+
39
51
  /**
40
52
  * The WidgetVideo component is used to display a video in a widget.
41
- * @param {Object} props The component props.
42
- * @param {boolean} props.isBanner Whether the video is used in a banner.
43
- * @param {string} props.url The video URL.
44
- * @param {boolean} props.muted Whether the video is muted.
45
- * @param {boolean} props.loop Whether the video is looping.
46
- * @param {boolean} props.controls Whether the video controls are shown.
47
- * @param {boolean} props.autoplay Whether the video should autoplay.
48
- * @param {number} props.borderRadius The border radius value.
49
- * @param {string} props.link The link URL.
50
- * @returns {JSX.Element}
51
53
  */
52
54
  const WidgetVideo = ({
53
- isBanner,
54
- url,
55
- muted,
56
- loop,
57
- controls,
58
- autoplay,
59
- borderRadius,
60
- link
55
+ isBanner = false,
56
+ url = null,
57
+ muted = false,
58
+ loop = false,
59
+ controls = false,
60
+ autoplay = false,
61
+ borderRadius = 0,
62
+ link = null
61
63
  }) => {
62
64
  const reduceMotion = useReduceMotion();
63
65
  const autoplayValue = reduceMotion ? false : isBanner || autoplay;
@@ -68,7 +70,7 @@ const WidgetVideo = ({
68
70
  borderRadius
69
71
  });
70
72
  const [hasError, setHasError] = useState(false);
71
- const videoRef = React.useRef(null);
73
+ const videoRef = useRef(null);
72
74
  const prevUrl = usePrevious(url);
73
75
  const isValidUrl = useMemo(() => url ? isHttpsUrl(url) : false, [url]);
74
76
  const showControls = useMemo(() => {
@@ -81,25 +83,27 @@ const WidgetVideo = ({
81
83
 
82
84
  // Resume video playback when app returned from background
83
85
  useAppEventOnReturnFromBackground(() => {
84
- if (!videoRef.current || reduceMotion || !autoplayValue) {
86
+ const video = videoRef.current;
87
+ if (!video || reduceMotion || !autoplayValue) {
85
88
  return;
86
89
  }
87
- videoRef.current.play();
90
+ video.play();
88
91
  });
89
92
  useEffect(() => {
90
- if (!videoRef.current) {
93
+ const video = videoRef.current;
94
+ if (!video) {
91
95
  return;
92
96
  }
93
97
  if (reduceMotion) {
94
98
  // Pause playback when reduced motion settings changed after video was rendered
95
- videoRef.current.pause();
99
+ video.pause();
96
100
  return;
97
101
  }
98
102
  if (autoplayValue) {
99
- videoRef.current.play();
103
+ video.play();
100
104
  } else {
101
- videoRef.current.pause();
102
- videoRef.current.currentTime = 0;
105
+ video.pause();
106
+ video.currentTime = 0;
103
107
  }
104
108
  }, [autoplayValue, reduceMotion]);
105
109
  useEffect(() => {
@@ -146,14 +150,4 @@ const WidgetVideo = ({
146
150
  })
147
151
  });
148
152
  };
149
- WidgetVideo.defaultProps = {
150
- isBanner: false,
151
- link: null,
152
- url: null,
153
- muted: false,
154
- loop: false,
155
- controls: false,
156
- autoplay: false,
157
- borderRadius: 0
158
- };
159
153
  export default WidgetVideo;
@@ -0,0 +1,2 @@
1
+ export { default } from './WidgetVideo';
2
+ //# sourceMappingURL=index.d.ts.map