@sitecore-jss/sitecore-jss-react 21.3.1 → 21.4.0-canary.2

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.
@@ -39,6 +39,7 @@ exports.composeComponentEndpoint = exports.fetchFEaaSComponentServerProps = expo
39
39
  const react_1 = __importDefault(require("react"));
40
40
  const FEAAS = __importStar(require("@sitecore-feaas/clientside/react"));
41
41
  const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
42
+ const utils_1 = require("../utils");
42
43
  exports.FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
43
44
  /**
44
45
  * @param {FEaaSComponentProps} props component props
@@ -46,7 +47,7 @@ exports.FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
46
47
  const FEaaSComponent = (props) => {
47
48
  var _a, _b, _c, _d, _e, _f, _g;
48
49
  const computedRevision = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentRevision) || props.revisionFallback;
49
- if ((!props.lastModified || !props.template) &&
50
+ if (!props.template &&
50
51
  (!props.params ||
51
52
  !props.params.LibraryId ||
52
53
  !props.params.ComponentId ||
@@ -57,23 +58,25 @@ const FEaaSComponent = (props) => {
57
58
  return null;
58
59
  }
59
60
  let data = null;
60
- if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
61
- // Use override data if provided
62
- try {
63
- data = JSON.parse(props.params.ComponentDataOverride);
61
+ if (props.fetchedData === null || props.fetchedData === undefined) {
62
+ if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
63
+ // Use override data if provided
64
+ try {
65
+ data = JSON.parse(props.params.ComponentDataOverride);
66
+ }
67
+ catch (e) {
68
+ data = null;
69
+ }
64
70
  }
65
- catch (e) {
66
- data = null;
71
+ else if (props.fields) {
72
+ // Otherwise use datasource data (provided in fields)
73
+ data = (0, utils_1.getDataFromFields)(props.fields);
67
74
  }
68
75
  }
69
- else if (props.fields) {
70
- // Otherwise use datasource data (provided in fields)
71
- data = getDataFromFields(props.fields);
72
- }
73
76
  // FEaaS control would still be hydrated by client
74
77
  // we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side
75
78
  // this also allows component to fall back to full client-side rendering when template or src is empty
76
- return (react_1.default.createElement(FEAAS.Component, { data: data, template: props.template || '', "last-modified": props.lastModified, cdn: (_c = props.params) === null || _c === void 0 ? void 0 : _c.ComponentHostName, library: (_d = props.params) === null || _d === void 0 ? void 0 : _d.LibraryId, version: (_e = props.params) === null || _e === void 0 ? void 0 : _e.ComponentVersion, component: (_f = props.params) === null || _f === void 0 ? void 0 : _f.ComponentId, instance: (_g = props.params) === null || _g === void 0 ? void 0 : _g.ComponentInstanceId, revision: computedRevision }));
79
+ return (react_1.default.createElement(FEAAS.Component, { data: props.fetchedData || data, template: props.template, cdn: (_c = props.params) === null || _c === void 0 ? void 0 : _c.ComponentHostName, library: (_d = props.params) === null || _d === void 0 ? void 0 : _d.LibraryId, version: (_e = props.params) === null || _e === void 0 ? void 0 : _e.ComponentVersion, component: (_f = props.params) === null || _f === void 0 ? void 0 : _f.ComponentId, instance: (_g = props.params) === null || _g === void 0 ? void 0 : _g.ComponentInstanceId, revision: computedRevision }));
77
80
  };
78
81
  exports.FEaaSComponent = FEaaSComponent;
79
82
  /**
@@ -87,34 +90,65 @@ function fetchFEaaSComponentServerProps(params, pageState, endpointOverride) {
87
90
  return __awaiter(this, void 0, void 0, function* () {
88
91
  const revisionFallback = pageState && pageState !== layout_1.LayoutServicePageState.Normal ? 'staged' : 'published';
89
92
  const src = endpointOverride || (0, exports.composeComponentEndpoint)(params, revisionFallback);
93
+ let template = '';
94
+ let fetchedData = null;
95
+ const fetchDataOptions = params.ComponentDataOverride
96
+ ? JSON.parse(params.ComponentDataOverride)
97
+ : {};
90
98
  try {
91
- const { template, lastModified } = yield FEAAS.fetchComponent(src);
92
- return {
93
- revisionFallback,
94
- template,
95
- lastModified,
96
- };
99
+ template = yield fetchComponentTemplate(src, params, revisionFallback);
100
+ fetchedData = yield fetchData(fetchDataOptions);
97
101
  }
98
102
  catch (e) {
99
- console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
100
- revisionFallback}" is present`);
101
103
  console.error(e);
102
- // leave revision fallback in so we can re-try with client-side rendering
103
- return {
104
- revisionFallback,
105
- };
106
104
  }
105
+ return {
106
+ fetchedData,
107
+ revisionFallback,
108
+ template,
109
+ };
107
110
  });
108
111
  }
109
112
  exports.fetchFEaaSComponentServerProps = fetchFEaaSComponentServerProps;
110
- const getDataFromFields = (fields) => {
111
- let data = {};
112
- data = Object.entries(fields).reduce((acc, [key]) => {
113
- acc[key] = (0, layout_1.getFieldValue)(fields, key);
114
- return acc;
115
- }, data);
116
- return data;
117
- };
113
+ /**
114
+ * @param {string} src component endpoint
115
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
116
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
117
+ */
118
+ function fetchComponentTemplate(src, params, revisionFallback) {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ try {
121
+ const { template } = yield FEAAS.fetchComponent(src);
122
+ return template;
123
+ }
124
+ catch (error) {
125
+ console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
126
+ revisionFallback}" is present`);
127
+ throw error;
128
+ }
129
+ });
130
+ }
131
+ /**
132
+ * Fetches component data based on the provided data options.
133
+ * This function asynchronously fetches data using the FEAAS.DataSettings.fetch method.
134
+ *
135
+ * @param {FEAAS.DataOptions} dataOptions - Options to customize data fetching.
136
+ * @returns {Promise<FEAAS.DataScopes>} A promise that resolves with the fetched data,
137
+ * or rejects with an error if data fetching encounters an issue.
138
+ * @throws {Error} If an error occurs during data fetching, it is propagated as an error.
139
+ */
140
+ function fetchData(dataOptions) {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ try {
143
+ const fetchedData = yield FEAAS.DataSettings.fetch(dataOptions || {});
144
+ return fetchedData;
145
+ }
146
+ catch (error) {
147
+ console.error('Fetch FEAAS component data settings failed');
148
+ throw error;
149
+ }
150
+ });
151
+ }
118
152
  /**
119
153
  * Build component endpoint URL from component's params
120
154
  * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FEaaSWrapper = exports.FEAAS_WRAPPER_RENDERING_NAME = void 0;
7
+ const FEaaSComponent_1 = require("./FEaaSComponent");
8
+ const react_1 = __importDefault(require("react"));
9
+ exports.FEAAS_WRAPPER_RENDERING_NAME = 'FEaaSWrapper';
10
+ const FEaaSWrapper = (props) => {
11
+ var _a, _b;
12
+ const styles = `component feaas ${(_a = props.params) === null || _a === void 0 ? void 0 : _a.styles}`.trimEnd();
13
+ const id = (_b = props.params) === null || _b === void 0 ? void 0 : _b.RenderingIdentifier;
14
+ return (react_1.default.createElement("div", { className: styles, id: id ? id : undefined },
15
+ react_1.default.createElement("div", { className: "component-content" },
16
+ react_1.default.createElement(FEaaSComponent_1.FEaaSComponent, Object.assign({}, props)))));
17
+ };
18
+ exports.FEaaSWrapper = FEaaSWrapper;
@@ -18,8 +18,8 @@ exports.Image = exports.getEEMarkup = void 0;
18
18
  const media_1 = require("@sitecore-jss/sitecore-jss/media");
19
19
  const prop_types_1 = __importDefault(require("prop-types"));
20
20
  const react_1 = __importDefault(require("react"));
21
- const server_1 = __importDefault(require("react-dom/server"));
22
21
  const utils_1 = require("../utils");
22
+ const utils_2 = require("../utils");
23
23
  const getEditableWrapper = (editableMarkup, ...otherProps) => (
24
24
  // create an inline wrapper and use dangerouslySetInnerHTML.
25
25
  // if we try to parse the EE value, the parser will strip invalid or disallowed attributes from html elements - and EE uses several
@@ -61,7 +61,7 @@ const getEEMarkup = (imageField, imageParams, mediaUrlPrefix, otherProps) => {
61
61
  if (!imgAttrs) {
62
62
  return getEditableWrapper(imageField.editable);
63
63
  }
64
- const imgHtml = server_1.default.renderToStaticMarkup(react_1.default.createElement("img", Object.assign({}, imgAttrs)));
64
+ const imgHtml = `<img ${(0, utils_2.getAttributesString)(imgAttrs)} />`;
65
65
  const editableMarkup = imageField.editable.replace(foundImg.imgTag, imgHtml);
66
66
  return getEditableWrapper(editableMarkup);
67
67
  };
@@ -10,7 +10,11 @@ const MissingComponent = (props) => {
10
10
  const componentName = props.rendering && props.rendering.componentName
11
11
  ? props.rendering.componentName
12
12
  : 'Unnamed Component';
13
- console.log(`Component props for unimplemented '${componentName}' component`, props);
13
+ // error override would mean component is not unimplemented
14
+ !props.errorOverride &&
15
+ console.log(`Component props for unimplemented '${componentName}' component`, props);
16
+ const errorMessage = props.errorOverride ||
17
+ 'JSS component is missing React implementation. See the developer console for more information.';
14
18
  return (react_1.default.createElement("div", { style: {
15
19
  background: 'darkorange',
16
20
  outline: '5px solid orange',
@@ -19,7 +23,7 @@ const MissingComponent = (props) => {
19
23
  maxWidth: '500px',
20
24
  } },
21
25
  react_1.default.createElement("h2", null, componentName),
22
- react_1.default.createElement("p", null, "JSS component is missing React implementation. See the developer console for more information.")));
26
+ react_1.default.createElement("p", null, errorMessage)));
23
27
  };
24
28
  exports.MissingComponent = MissingComponent;
25
29
  exports.MissingComponent.propTypes = {
@@ -50,36 +50,8 @@ class PlaceholderComponent extends PlaceholderCommon_1.PlaceholderCommon {
50
50
  }
51
51
  const renderingData = childProps.rendering;
52
52
  const placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name);
53
- this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
54
- // This is a workaround to insert Experience Editor-specific markup on the page for empty placeholders.
55
- // It makes sure the markup is inserted by react and thus avoiding hydration errors when in editing mode
56
- if (this.isEmpty && utils_1.ExperienceEditor.isActive()) {
57
- const codePos = placeholderData.findIndex((component) => component.name === 'code' &&
58
- component.attributes.kind === 'open');
59
- const plhId = placeholderData[codePos].attributes.id;
60
- const emptyPlaceholderMarkup = [
61
- {
62
- name: 'span',
63
- contents: null,
64
- attributes: {
65
- type: 'text/sitecore',
66
- 'sc-part-of': 'placeholder rendering',
67
- style: 'display: none;',
68
- },
69
- },
70
- {
71
- name: 'div',
72
- contents: null,
73
- attributes: {
74
- class: 'scEnabledChrome scEmptyPlaceholder',
75
- 'sc-part-of': 'placeholder',
76
- 'sc-placeholder-id': plhId,
77
- },
78
- },
79
- ];
80
- placeholderData.splice(codePos + 1, 0, ...emptyPlaceholderMarkup);
81
- }
82
53
  const components = this.getComponentsForRenderingData(placeholderData);
54
+ this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
83
55
  if (this.props.renderEmpty && this.isEmpty) {
84
56
  const rendered = this.props.renderEmpty(components);
85
57
  return components.length ? this.renderEmptyPlaceholder(rendered) : rendered;
@@ -21,6 +21,9 @@ const MissingComponent_1 = require("./MissingComponent");
21
21
  const utils_1 = require("../utils");
22
22
  const HiddenRendering_1 = require("./HiddenRendering");
23
23
  const FEaaSComponent_1 = require("./FEaaSComponent");
24
+ const FEaaSWrapper_1 = require("./FEaaSWrapper");
25
+ const BYOCComponent_1 = require("./BYOCComponent");
26
+ const BYOCWrapper_1 = require("./BYOCWrapper");
24
27
  /**
25
28
  * These patterns need for right rendering Dynamic placeholders.
26
29
  * Must be distinguished Splitter components and another placeholders(containers)
@@ -103,8 +106,20 @@ class PlaceholderCommon extends react_1.default.Component {
103
106
  else {
104
107
  component = this.getComponentForRendering(componentRendering);
105
108
  }
106
- if (componentRendering.componentName === FEaaSComponent_1.FEAAS_COMPONENT_RENDERING_NAME) {
107
- component = FEaaSComponent_1.FEaaSComponent;
109
+ // Fallback/defaults for Sitecore Component renderings (in case not defined in component factory)
110
+ if (!component) {
111
+ if (componentRendering.componentName === FEaaSComponent_1.FEAAS_COMPONENT_RENDERING_NAME) {
112
+ component = FEaaSComponent_1.FEaaSComponent;
113
+ }
114
+ else if (componentRendering.componentName === FEaaSWrapper_1.FEAAS_WRAPPER_RENDERING_NAME) {
115
+ component = FEaaSWrapper_1.FEaaSWrapper;
116
+ }
117
+ else if (componentRendering.componentName === BYOCComponent_1.BYOC_COMPONENT_RENDERING_NAME) {
118
+ component = BYOCComponent_1.BYOCComponent;
119
+ }
120
+ else if (componentRendering.componentName === BYOCWrapper_1.BYOC_WRAPPER_RENDERING_NAME) {
121
+ component = BYOCWrapper_1.BYOCWrapper;
122
+ }
108
123
  }
109
124
  if (!component) {
110
125
  console.error(`Placeholder ${name} contains unknown component ${componentRendering.componentName}. Ensure that a React component exists for it, and that it is registered in your componentFactory.js.`);
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComponentBuilder = exports.EditFrame = exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.LinkPropTypes = exports.Link = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.DateField = exports.Text = exports.RichTextPropTypes = exports.RichText = exports.getEEMarkup = exports.Image = exports.Placeholder = exports.mediaApi = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.DefaultEditFrameButtons = exports.DefaultEditFrameButton = exports.resetEditorChromes = exports.isEditorActive = exports.enableDebug = exports.constants = void 0;
3
+ exports.ComponentBuilder = exports.EditFrame = exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.LinkPropTypes = exports.Link = exports.BYOCWrapper = exports.fetchBYOCComponentServerProps = exports.BYOCComponent = exports.FEaaSWrapper = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.DateField = exports.Text = exports.RichTextPropTypes = exports.RichText = exports.getEEMarkup = exports.Image = exports.Placeholder = exports.getFEAASLibraryStylesheetLinks = exports.mediaApi = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.DefaultEditFrameButtons = exports.DefaultEditFrameButton = exports.resetEditorChromes = exports.isEditorActive = exports.enableDebug = exports.constants = void 0;
4
4
  var sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
5
5
  Object.defineProperty(exports, "constants", { enumerable: true, get: function () { return sitecore_jss_1.constants; } });
6
6
  Object.defineProperty(exports, "enableDebug", { enumerable: true, get: function () { return sitecore_jss_1.enableDebug; } });
@@ -22,6 +22,8 @@ Object.defineProperty(exports, "GraphQLDictionaryService", { enumerable: true, g
22
22
  Object.defineProperty(exports, "RestDictionaryService", { enumerable: true, get: function () { return i18n_1.RestDictionaryService; } });
23
23
  var media_1 = require("@sitecore-jss/sitecore-jss/media");
24
24
  Object.defineProperty(exports, "mediaApi", { enumerable: true, get: function () { return media_1.mediaApi; } });
25
+ var feaas_1 = require("@sitecore-jss/sitecore-jss/feaas");
26
+ Object.defineProperty(exports, "getFEAASLibraryStylesheetLinks", { enumerable: true, get: function () { return feaas_1.getFEAASLibraryStylesheetLinks; } });
25
27
  var Placeholder_1 = require("./components/Placeholder");
26
28
  Object.defineProperty(exports, "Placeholder", { enumerable: true, get: function () { return Placeholder_1.Placeholder; } });
27
29
  var Image_1 = require("./components/Image");
@@ -37,6 +39,13 @@ Object.defineProperty(exports, "DateField", { enumerable: true, get: function ()
37
39
  var FEaaSComponent_1 = require("./components/FEaaSComponent");
38
40
  Object.defineProperty(exports, "FEaaSComponent", { enumerable: true, get: function () { return FEaaSComponent_1.FEaaSComponent; } });
39
41
  Object.defineProperty(exports, "fetchFEaaSComponentServerProps", { enumerable: true, get: function () { return FEaaSComponent_1.fetchFEaaSComponentServerProps; } });
42
+ var FEaaSWrapper_1 = require("./components/FEaaSWrapper");
43
+ Object.defineProperty(exports, "FEaaSWrapper", { enumerable: true, get: function () { return FEaaSWrapper_1.FEaaSWrapper; } });
44
+ var BYOCComponent_1 = require("./components/BYOCComponent");
45
+ Object.defineProperty(exports, "BYOCComponent", { enumerable: true, get: function () { return BYOCComponent_1.BYOCComponent; } });
46
+ Object.defineProperty(exports, "fetchBYOCComponentServerProps", { enumerable: true, get: function () { return BYOCComponent_1.fetchBYOCComponentServerProps; } });
47
+ var BYOCWrapper_1 = require("./components/BYOCWrapper");
48
+ Object.defineProperty(exports, "BYOCWrapper", { enumerable: true, get: function () { return BYOCWrapper_1.BYOCWrapper; } });
40
49
  var Link_1 = require("./components/Link");
41
50
  Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return Link_1.Link; } });
42
51
  Object.defineProperty(exports, "LinkPropTypes", { enumerable: true, get: function () { return Link_1.LinkPropTypes; } });
package/dist/cjs/utils.js CHANGED
@@ -1,6 +1,18 @@
1
1
  "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
2
13
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addClassName = exports.convertAttributesToReactProps = exports.convertStyleAttribute = exports.convertKebabCasetoCamelCase = void 0;
14
+ exports.getDataFromFields = exports.getAttributesString = exports.addClassName = exports.convertAttributesToReactProps = exports.convertStyleAttribute = exports.convertKebabCasetoCamelCase = void 0;
15
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
4
16
  const style_attr_1 = require("style-attr");
5
17
  // https://stackoverflow.com/a/10426674/9324
6
18
  const convertKebabCasetoCamelCase = (str) => str.replace(/^.|-./g, (letter, index) => index === 0 ? letter.toLowerCase() : letter.substr(1).toUpperCase());
@@ -51,7 +63,7 @@ exports.convertAttributesToReactProps = convertAttributesToReactProps;
51
63
  /**
52
64
  * "class" property will be transformed into or appended to "className" instead.
53
65
  * @param {string} otherAttrs all other props included on the image component
54
- * * @returns {void}
66
+ * @returns {void}
55
67
  */
56
68
  const addClassName = (otherAttrs) => {
57
69
  if (otherAttrs.class) {
@@ -68,3 +80,39 @@ const addClassName = (otherAttrs) => {
68
80
  }
69
81
  };
70
82
  exports.addClassName = addClassName;
83
+ /**
84
+ * Converts the given tag attributes object to a string
85
+ * @param {Object.<string, unknown>} attributes the attributes object
86
+ * @returns {string} string representation of the attributes
87
+ */
88
+ const getAttributesString = (attributes) => {
89
+ const { className } = attributes, restAttributes = __rest(attributes, ["className"]);
90
+ const attributesEntries = Object.entries(restAttributes).map(([key, value]) => {
91
+ if (typeof value === 'object') {
92
+ const valueString = JSON.stringify(value)
93
+ .replace(/"|{|}/g, '')
94
+ .replace(/,/g, ';');
95
+ return `${key}="${valueString}"`;
96
+ }
97
+ return `${key}="${value}"`;
98
+ });
99
+ if (className) {
100
+ attributesEntries.push(`class="${className}"`);
101
+ }
102
+ return attributesEntries.join(' ');
103
+ };
104
+ exports.getAttributesString = getAttributesString;
105
+ /**
106
+ * Used in FEAAS and BYOC implementations to convert datasource item field values into component props
107
+ * @param {ComponentFields} fields field collection from Sitecore
108
+ * @returns JSON object that can be used as props
109
+ */
110
+ const getDataFromFields = (fields) => {
111
+ let data = {};
112
+ data = Object.entries(fields).reduce((acc, [key]) => {
113
+ acc[key] = (0, layout_1.getFieldValue)(fields, key);
114
+ return acc;
115
+ }, data);
116
+ return data;
117
+ };
118
+ exports.getDataFromFields = getDataFromFields;
@@ -0,0 +1,94 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React from 'react';
11
+ import { getDataFromFields } from '../utils';
12
+ import { MissingComponent } from './MissingComponent';
13
+ import * as FEAAS from '@sitecore-feaas/clientside/react';
14
+ export const BYOC_COMPONENT_RENDERING_NAME = 'BYOCComponent';
15
+ const DefaultErrorComponent = (props) => {
16
+ var _a;
17
+ return (React.createElement("div", null,
18
+ "A rendering error occurred: ", (_a = props.error) === null || _a === void 0 ? void 0 :
19
+ _a.message,
20
+ "."));
21
+ };
22
+ /**
23
+ * BYOCComponent facilitate the rendering of external components. It manages potential errors,
24
+ * missing components, and customization of error messages or alternative rendering components.
25
+ * @param {ByocComponentProps} props component props
26
+ * @returns dynamicly rendered component or Missing Component error frame
27
+ */
28
+ export class BYOCComponent extends React.Component {
29
+ constructor(props) {
30
+ super(props);
31
+ this.state = {};
32
+ }
33
+ static getDerivedStateFromError(error) {
34
+ // Update state so the next render will show the fallback UI.
35
+ return { error: error };
36
+ }
37
+ componentDidCatch(error) {
38
+ this.setState({ error });
39
+ }
40
+ render() {
41
+ var _a, _b;
42
+ const props = this.props;
43
+ if (this.state.error) {
44
+ return this.props.errorComponent ? (React.createElement(this.props.errorComponent, { error: this.state.error })) : (React.createElement(DefaultErrorComponent, { error: this.state.error }));
45
+ }
46
+ const { ComponentName: componentName } = props.params || {};
47
+ if (!componentName) {
48
+ const noNameProps = {
49
+ errorOverride: 'BYOC: The ComponentName for this rendering is missing',
50
+ };
51
+ return props.missingComponentComponent ? (React.createElement(this.props.missingComponentComponent, Object.assign({}, noNameProps))) : (React.createElement(MissingComponent, Object.assign({}, noNameProps)));
52
+ }
53
+ const unRegisteredComponentProps = {
54
+ rendering: {
55
+ componentName: componentName,
56
+ },
57
+ errorOverride: 'BYOC: This component was not registered.',
58
+ };
59
+ const fallbackComponent = this.props.missingComponentComponent ? (React.createElement(this.props.missingComponentComponent, Object.assign({}, unRegisteredComponentProps))) : (React.createElement(MissingComponent, Object.assign({}, unRegisteredComponentProps)));
60
+ const ErrorComponent = this.props.errorComponent;
61
+ const isNull = Object.keys(props.fetchedData).length === 0;
62
+ let componentProps = isNull ? null : props.fetchedData;
63
+ if (!componentProps) {
64
+ if ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentProps) {
65
+ try {
66
+ componentProps = (_b = JSON.parse(props.params.ComponentProps)) !== null && _b !== void 0 ? _b : {};
67
+ }
68
+ catch (e) {
69
+ console.error(`Parsing props for ${componentName} component from rendering params failed. Error: ${e}`);
70
+ return ErrorComponent ? (React.createElement(ErrorComponent, { error: e })) : (React.createElement(DefaultErrorComponent, { error: e }));
71
+ }
72
+ }
73
+ else {
74
+ componentProps = props.fields ? getDataFromFields(props.fields) : {};
75
+ }
76
+ }
77
+ return (React.createElement(FEAAS.ExternalComponent, Object.assign({ componentName: componentName, fallback: fallbackComponent }, componentProps)));
78
+ }
79
+ }
80
+ /**
81
+ * Fetches server component props required for server rendering, based on rendering params.
82
+ * @param {BYOCComponentParams} params component params
83
+ */
84
+ export function fetchBYOCComponentServerProps(params) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const fetchDataOptions = params.ComponentProps
87
+ ? JSON.parse(params.ComponentProps)
88
+ : {};
89
+ const fetchedData = yield FEAAS.DataSettings.fetch(fetchDataOptions || {});
90
+ return {
91
+ fetchedData,
92
+ };
93
+ });
94
+ }
@@ -0,0 +1,11 @@
1
+ import { BYOCComponent } from './BYOCComponent';
2
+ import React from 'react';
3
+ export const BYOC_WRAPPER_RENDERING_NAME = 'BYOCWrapper';
4
+ export const BYOCWrapper = (props) => {
5
+ var _a, _b, _c;
6
+ const styles = (_b = (_a = props.params) === null || _a === void 0 ? void 0 : _a.styles) === null || _b === void 0 ? void 0 : _b.trimEnd();
7
+ const id = (_c = props.params) === null || _c === void 0 ? void 0 : _c.RenderingIdentifier;
8
+ return (React.createElement("div", { className: styles ? styles : undefined, id: id ? id : undefined },
9
+ React.createElement("div", { className: "component-content" },
10
+ React.createElement(BYOCComponent, Object.assign({}, props)))));
11
+ };
@@ -9,7 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import React from 'react';
11
11
  import * as FEAAS from '@sitecore-feaas/clientside/react';
12
- import { LayoutServicePageState, getFieldValue, } from '@sitecore-jss/sitecore-jss/layout';
12
+ import { LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
13
+ import { getDataFromFields } from '../utils';
13
14
  export const FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
14
15
  /**
15
16
  * @param {FEaaSComponentProps} props component props
@@ -17,7 +18,7 @@ export const FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
17
18
  export const FEaaSComponent = (props) => {
18
19
  var _a, _b, _c, _d, _e, _f, _g;
19
20
  const computedRevision = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentRevision) || props.revisionFallback;
20
- if ((!props.lastModified || !props.template) &&
21
+ if (!props.template &&
21
22
  (!props.params ||
22
23
  !props.params.LibraryId ||
23
24
  !props.params.ComponentId ||
@@ -28,23 +29,25 @@ export const FEaaSComponent = (props) => {
28
29
  return null;
29
30
  }
30
31
  let data = null;
31
- if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
32
- // Use override data if provided
33
- try {
34
- data = JSON.parse(props.params.ComponentDataOverride);
32
+ if (props.fetchedData === null || props.fetchedData === undefined) {
33
+ if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
34
+ // Use override data if provided
35
+ try {
36
+ data = JSON.parse(props.params.ComponentDataOverride);
37
+ }
38
+ catch (e) {
39
+ data = null;
40
+ }
35
41
  }
36
- catch (e) {
37
- data = null;
42
+ else if (props.fields) {
43
+ // Otherwise use datasource data (provided in fields)
44
+ data = getDataFromFields(props.fields);
38
45
  }
39
46
  }
40
- else if (props.fields) {
41
- // Otherwise use datasource data (provided in fields)
42
- data = getDataFromFields(props.fields);
43
- }
44
47
  // FEaaS control would still be hydrated by client
45
48
  // we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side
46
49
  // this also allows component to fall back to full client-side rendering when template or src is empty
47
- return (React.createElement(FEAAS.Component, { data: data, template: props.template || '', "last-modified": props.lastModified, cdn: (_c = props.params) === null || _c === void 0 ? void 0 : _c.ComponentHostName, library: (_d = props.params) === null || _d === void 0 ? void 0 : _d.LibraryId, version: (_e = props.params) === null || _e === void 0 ? void 0 : _e.ComponentVersion, component: (_f = props.params) === null || _f === void 0 ? void 0 : _f.ComponentId, instance: (_g = props.params) === null || _g === void 0 ? void 0 : _g.ComponentInstanceId, revision: computedRevision }));
50
+ return (React.createElement(FEAAS.Component, { data: props.fetchedData || data, template: props.template, cdn: (_c = props.params) === null || _c === void 0 ? void 0 : _c.ComponentHostName, library: (_d = props.params) === null || _d === void 0 ? void 0 : _d.LibraryId, version: (_e = props.params) === null || _e === void 0 ? void 0 : _e.ComponentVersion, component: (_f = props.params) === null || _f === void 0 ? void 0 : _f.ComponentId, instance: (_g = props.params) === null || _g === void 0 ? void 0 : _g.ComponentInstanceId, revision: computedRevision }));
48
51
  };
49
52
  /**
50
53
  * Fetches server component props required for server rendering, based on rendering params.
@@ -57,33 +60,64 @@ export function fetchFEaaSComponentServerProps(params, pageState, endpointOverri
57
60
  return __awaiter(this, void 0, void 0, function* () {
58
61
  const revisionFallback = pageState && pageState !== LayoutServicePageState.Normal ? 'staged' : 'published';
59
62
  const src = endpointOverride || composeComponentEndpoint(params, revisionFallback);
63
+ let template = '';
64
+ let fetchedData = null;
65
+ const fetchDataOptions = params.ComponentDataOverride
66
+ ? JSON.parse(params.ComponentDataOverride)
67
+ : {};
60
68
  try {
61
- const { template, lastModified } = yield FEAAS.fetchComponent(src);
62
- return {
63
- revisionFallback,
64
- template,
65
- lastModified,
66
- };
69
+ template = yield fetchComponentTemplate(src, params, revisionFallback);
70
+ fetchedData = yield fetchData(fetchDataOptions);
67
71
  }
68
72
  catch (e) {
73
+ console.error(e);
74
+ }
75
+ return {
76
+ fetchedData,
77
+ revisionFallback,
78
+ template,
79
+ };
80
+ });
81
+ }
82
+ /**
83
+ * @param {string} src component endpoint
84
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
85
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
86
+ */
87
+ function fetchComponentTemplate(src, params, revisionFallback) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ try {
90
+ const { template } = yield FEAAS.fetchComponent(src);
91
+ return template;
92
+ }
93
+ catch (error) {
69
94
  console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
70
95
  revisionFallback}" is present`);
71
- console.error(e);
72
- // leave revision fallback in so we can re-try with client-side rendering
73
- return {
74
- revisionFallback,
75
- };
96
+ throw error;
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * Fetches component data based on the provided data options.
102
+ * This function asynchronously fetches data using the FEAAS.DataSettings.fetch method.
103
+ *
104
+ * @param {FEAAS.DataOptions} dataOptions - Options to customize data fetching.
105
+ * @returns {Promise<FEAAS.DataScopes>} A promise that resolves with the fetched data,
106
+ * or rejects with an error if data fetching encounters an issue.
107
+ * @throws {Error} If an error occurs during data fetching, it is propagated as an error.
108
+ */
109
+ function fetchData(dataOptions) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ try {
112
+ const fetchedData = yield FEAAS.DataSettings.fetch(dataOptions || {});
113
+ return fetchedData;
114
+ }
115
+ catch (error) {
116
+ console.error('Fetch FEAAS component data settings failed');
117
+ throw error;
76
118
  }
77
119
  });
78
120
  }
79
- const getDataFromFields = (fields) => {
80
- let data = {};
81
- data = Object.entries(fields).reduce((acc, [key]) => {
82
- acc[key] = getFieldValue(fields, key);
83
- return acc;
84
- }, data);
85
- return data;
86
- };
87
121
  /**
88
122
  * Build component endpoint URL from component's params
89
123
  * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
@@ -0,0 +1,11 @@
1
+ import { FEaaSComponent } from './FEaaSComponent';
2
+ import React from 'react';
3
+ export const FEAAS_WRAPPER_RENDERING_NAME = 'FEaaSWrapper';
4
+ export const FEaaSWrapper = (props) => {
5
+ var _a, _b;
6
+ const styles = `component feaas ${(_a = props.params) === null || _a === void 0 ? void 0 : _a.styles}`.trimEnd();
7
+ const id = (_b = props.params) === null || _b === void 0 ? void 0 : _b.RenderingIdentifier;
8
+ return (React.createElement("div", { className: styles, id: id ? id : undefined },
9
+ React.createElement("div", { className: "component-content" },
10
+ React.createElement(FEaaSComponent, Object.assign({}, props)))));
11
+ };