@sitecore-jss/sitecore-jss-react 21.1.1 → 21.2.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.
package/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  This module is provided as a part of Sitecore JavaScript Rendering SDK (JSS). It contains React components and integration for JSS.
4
4
 
5
+ <!---
6
+ @TODO: Update to version 20.0.0 docs before release
7
+ -->
8
+ [Documentation](https://doc.sitecore.com/xp/en/developers/hd/190/sitecore-headless-development/sitecore-javascript-rendering-sdk--jss--for-react.html)
5
9
 
6
- [Documentation (Experience Platform)](https://doc.sitecore.com/xp/en/developers/hd/210/sitecore-headless-development/sitecore-javascript-rendering-sdk--jss--for-react.html)
7
-
8
- [API reference documentation](/ref-docs/sitecore-jss-react/)
10
+ [API reference documentation](/ref-docs/sitecore-jss-react/).
@@ -22,72 +22,106 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
25
37
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.FEaaSComponent = exports.FEAAS_MODULE_SRC = exports.FEAAS_COMPONENT_RENDERING_NAME = void 0;
27
- /* eslint-disable react/prop-types */
28
- const react_1 = __importStar(require("react"));
38
+ exports.composeComponentEndpoint = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.FEAAS_COMPONENT_RENDERING_NAME = void 0;
39
+ const react_1 = __importDefault(require("react"));
40
+ const FEAAS = __importStar(require("@sitecore-feaas/clientside/react"));
29
41
  const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
30
42
  exports.FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
31
- exports.FEAAS_MODULE_SRC = 'https://feaasstatic.blob.core.windows.net/packages/clientside/latest/browser/index.esm.js';
32
- const getDataFromFields = (fields) => {
33
- let data = {};
34
- data = Object.entries(fields).reduce((acc, [key]) => {
35
- acc[key] = (0, layout_1.getFieldValue)(fields, key);
36
- return acc;
37
- }, data);
38
- return data;
39
- };
40
- const FEaaSComponent = ({ params, fields }) => {
41
- if (!params ||
42
- !params.LibraryId ||
43
- !params.ComponentId ||
44
- !params.ComponentVersion ||
45
- !params.ComponentRevision ||
46
- !params.ComponentHostName) {
43
+ /**
44
+ * @param {FEaaSComponentProps} props component props
45
+ */
46
+ const FEaaSComponent = (props) => {
47
+ var _a, _b, _c, _d, _e, _f;
48
+ const computedRevision = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentRevision) || props.revisionFallback;
49
+ if ((!props.lastModified || !props.template) &&
50
+ (!props.params ||
51
+ !props.params.LibraryId ||
52
+ !props.params.ComponentId ||
53
+ !props.params.ComponentVersion ||
54
+ !props.params.ComponentHostName ||
55
+ !computedRevision)) {
47
56
  // Missing FEaaS component required props
48
57
  return null;
49
58
  }
50
- // Load script asynchronously on the page once, only if FEAAS component is used
51
- (0, react_1.useEffect)(() => {
52
- var _a;
53
- (_a = window.FEAASLoading) !== null && _a !== void 0 ? _a : (window.FEAASLoading = new Promise((resolve) => {
54
- const script = document.createElement('script');
55
- script.src = exports.FEAAS_MODULE_SRC;
56
- script.type = 'module';
57
- script.onload = resolve;
58
- document.head.appendChild(script);
59
- }));
60
- }, []);
61
- let data = '';
62
- if (params === null || params === void 0 ? void 0 : params.ComponentDataOverride) {
59
+ let data = null;
60
+ if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
63
61
  // Use override data if provided
64
- data = params.ComponentDataOverride;
62
+ data = props.params.ComponentDataOverride;
65
63
  }
66
- else if (fields) {
64
+ else if (props.fields) {
67
65
  // Otherwise use datasource data (provided in fields)
68
66
  // FEaaS expects wrapping "_" as catch-all datasource template id
69
- data = JSON.stringify({ _: getDataFromFields(fields) });
70
- }
71
- const reqProps = {
72
- library: params.LibraryId,
73
- cdn: params.ComponentHostName,
74
- component: params.ComponentId,
75
- version: params.ComponentVersion,
76
- revision: params.ComponentRevision,
77
- data,
78
- };
79
- const optProps = {};
80
- if (params.ComponentInstanceId) {
81
- optProps.instance = params.ComponentInstanceId;
67
+ data = JSON.stringify({ _: getDataFromFields(props.fields) });
82
68
  }
83
- if (params.ComponentHTMLOverride) {
84
- optProps.dangerouslySetInnerHTML = { __html: params.ComponentHTMLOverride };
85
- }
86
- return (react_1.default.createElement(react_1.default.Fragment, null,
87
- react_1.default.createElement("link", { rel: "preload", as: "style", href: `${reqProps.cdn}/styles/${reqProps.library}/published.css` }),
88
- react_1.default.createElement("link", { rel: "preload", as: "fetch", href: `${reqProps.cdn}/components/${reqProps.library}/${reqProps.component}/${reqProps.version}/${reqProps.revision}.html` }),
89
- react_1.default.createElement("link", { rel: "preload", as: "script", href: exports.FEAAS_MODULE_SRC }),
90
- react_1.default.createElement("feaas-stylesheet", { library: reqProps.library, cdn: reqProps.cdn }),
91
- react_1.default.createElement("feaas-component", Object.assign({}, reqProps, optProps))));
69
+ // FEaaS control would still be hydrated by client
70
+ // we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side
71
+ // this also allows component to fall back to full client-side rendering when template or src is empty
72
+ 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, revision: computedRevision }));
92
73
  };
93
74
  exports.FEaaSComponent = FEaaSComponent;
75
+ /**
76
+ * Fetches server component props required for server rendering, based on rendering params.
77
+ * Component endpoint will either be retrieved from params or from endpointOverride
78
+ * @param {FEaaSComponentParams} params component params
79
+ * @param {LayoutServicePageState} [pageState] page state to determine which component variant to use
80
+ * @param {string} [endpointOverride] optional override for component endpoint
81
+ */
82
+ function fetchFEaaSComponentServerProps(params, pageState, endpointOverride) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ const revisionFallback = pageState && pageState !== layout_1.LayoutServicePageState.Normal ? 'staged' : 'published';
85
+ const src = endpointOverride || (0, exports.composeComponentEndpoint)(params, revisionFallback);
86
+ try {
87
+ const { template, lastModified } = yield FEAAS.fetchComponent(src);
88
+ return {
89
+ revisionFallback,
90
+ template,
91
+ lastModified,
92
+ };
93
+ }
94
+ catch (e) {
95
+ console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
96
+ revisionFallback}" is present`);
97
+ console.error(e);
98
+ // leave revision fallback in so we can re-try with client-side rendering
99
+ return {
100
+ revisionFallback,
101
+ };
102
+ }
103
+ });
104
+ }
105
+ exports.fetchFEaaSComponentServerProps = fetchFEaaSComponentServerProps;
106
+ const getDataFromFields = (fields) => {
107
+ let data = {};
108
+ data = Object.entries(fields).reduce((acc, [key]) => {
109
+ acc[key] = (0, layout_1.getFieldValue)(fields, key);
110
+ return acc;
111
+ }, data);
112
+ return data;
113
+ };
114
+ /**
115
+ * Build component endpoint URL from component's params
116
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
117
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
118
+ * @returns component endpoint URL
119
+ */
120
+ const composeComponentEndpoint = (params, revisionFallback) => {
121
+ const revision = params.ComponentRevision || revisionFallback;
122
+ const hostname = params.ComponentHostName.startsWith('https://')
123
+ ? params.ComponentHostName
124
+ : `https://${params.ComponentHostName}`;
125
+ return `${hostname}/components/${params.LibraryId}/${params.ComponentId}/${params.ComponentVersion}/${revision}`;
126
+ };
127
+ exports.composeComponentEndpoint = composeComponentEndpoint;
@@ -40,7 +40,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.LinkPropTypes = exports.Link = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const prop_types_1 = __importDefault(require("prop-types"));
43
- const html_react_parser_1 = __importDefault(require("html-react-parser"));
44
43
  exports.Link = (0, react_1.forwardRef)((_a, ref) => {
45
44
  var { field, editable, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
46
45
  const children = otherProps.children;
@@ -59,13 +58,13 @@ exports.Link = (0, react_1.forwardRef)((_a, ref) => {
59
58
  // However, we cannot combine arbitrary unparsed HTML (innerHTML) based components with actual vDOM components (the children)
60
59
  // because the innerHTML is not parsed - it'd make a discontinuous vDOM. So, we'll go for the next best compromise of rendering the link field and children separately
61
60
  // as siblings. Should be "good enough" for most cases - and write your own helper if it isn't. Or bring xEditor out of 2006.
62
- const htmlProps = Object.assign(Object.assign({ className: 'sc-link-wrapper' }, otherProps), { key: 'editable' });
63
- const components = (0, html_react_parser_1.default)(markup, {
64
- htmlparser2: {
65
- lowerCaseTags: false,
66
- },
67
- });
68
- resultTags.push(react_1.default.createElement("span", Object.assign({}, htmlProps), components));
61
+ const htmlProps = Object.assign(Object.assign({ className: 'sc-link-wrapper', dangerouslySetInnerHTML: {
62
+ __html: markup,
63
+ } }, otherProps), { key: 'editable' });
64
+ // Exclude children, since 'dangerouslySetInnerHTML' and 'children' can't be set together
65
+ // and children will be added as a sibling
66
+ delete htmlProps.children;
67
+ resultTags.push(react_1.default.createElement("span", Object.assign({}, htmlProps)));
69
68
  // don't render normal link tag when editing, if no children exist
70
69
  // this preserves normal-ish behavior if not using a link body (no hacks required)
71
70
  if (!children) {
@@ -97,6 +97,9 @@ class PlaceholderCommon extends react_1.default.Component {
97
97
  if (componentRendering.componentName === HiddenRendering_1.HIDDEN_RENDERING_NAME) {
98
98
  component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering_1.HiddenRendering;
99
99
  }
100
+ else if (!componentRendering.componentName) {
101
+ component = () => react_1.default.createElement(react_1.default.Fragment, null);
102
+ }
100
103
  else {
101
104
  component = this.getComponentForRendering(componentRendering);
102
105
  }
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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.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.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;
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; } });
@@ -36,6 +36,7 @@ var Date_1 = require("./components/Date");
36
36
  Object.defineProperty(exports, "DateField", { enumerable: true, get: function () { return Date_1.DateField; } });
37
37
  var FEaaSComponent_1 = require("./components/FEaaSComponent");
38
38
  Object.defineProperty(exports, "FEaaSComponent", { enumerable: true, get: function () { return FEaaSComponent_1.FEaaSComponent; } });
39
+ Object.defineProperty(exports, "fetchFEaaSComponentServerProps", { enumerable: true, get: function () { return FEaaSComponent_1.fetchFEaaSComponentServerProps; } });
39
40
  var Link_1 = require("./components/Link");
40
41
  Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return Link_1.Link; } });
41
42
  Object.defineProperty(exports, "LinkPropTypes", { enumerable: true, get: function () { return Link_1.LinkPropTypes; } });
@@ -1,66 +1,95 @@
1
- /* eslint-disable react/prop-types */
2
- import React, { useEffect } from 'react';
3
- import { getFieldValue } from '@sitecore-jss/sitecore-jss/layout';
4
- export const FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
5
- export const FEAAS_MODULE_SRC = 'https://feaasstatic.blob.core.windows.net/packages/clientside/latest/browser/index.esm.js';
6
- const getDataFromFields = (fields) => {
7
- let data = {};
8
- data = Object.entries(fields).reduce((acc, [key]) => {
9
- acc[key] = getFieldValue(fields, key);
10
- return acc;
11
- }, data);
12
- return data;
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
+ });
13
9
  };
14
- export const FEaaSComponent = ({ params, fields }) => {
15
- if (!params ||
16
- !params.LibraryId ||
17
- !params.ComponentId ||
18
- !params.ComponentVersion ||
19
- !params.ComponentRevision ||
20
- !params.ComponentHostName) {
10
+ import React from 'react';
11
+ import * as FEAAS from '@sitecore-feaas/clientside/react';
12
+ import { LayoutServicePageState, getFieldValue, } from '@sitecore-jss/sitecore-jss/layout';
13
+ export const FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
14
+ /**
15
+ * @param {FEaaSComponentProps} props component props
16
+ */
17
+ export const FEaaSComponent = (props) => {
18
+ var _a, _b, _c, _d, _e, _f;
19
+ const computedRevision = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentRevision) || props.revisionFallback;
20
+ if ((!props.lastModified || !props.template) &&
21
+ (!props.params ||
22
+ !props.params.LibraryId ||
23
+ !props.params.ComponentId ||
24
+ !props.params.ComponentVersion ||
25
+ !props.params.ComponentHostName ||
26
+ !computedRevision)) {
21
27
  // Missing FEaaS component required props
22
28
  return null;
23
29
  }
24
- // Load script asynchronously on the page once, only if FEAAS component is used
25
- useEffect(() => {
26
- var _a;
27
- (_a = window.FEAASLoading) !== null && _a !== void 0 ? _a : (window.FEAASLoading = new Promise((resolve) => {
28
- const script = document.createElement('script');
29
- script.src = FEAAS_MODULE_SRC;
30
- script.type = 'module';
31
- script.onload = resolve;
32
- document.head.appendChild(script);
33
- }));
34
- }, []);
35
- let data = '';
36
- if (params === null || params === void 0 ? void 0 : params.ComponentDataOverride) {
30
+ let data = null;
31
+ if ((_b = props.params) === null || _b === void 0 ? void 0 : _b.ComponentDataOverride) {
37
32
  // Use override data if provided
38
- data = params.ComponentDataOverride;
33
+ data = props.params.ComponentDataOverride;
39
34
  }
40
- else if (fields) {
35
+ else if (props.fields) {
41
36
  // Otherwise use datasource data (provided in fields)
42
37
  // FEaaS expects wrapping "_" as catch-all datasource template id
43
- data = JSON.stringify({ _: getDataFromFields(fields) });
44
- }
45
- const reqProps = {
46
- library: params.LibraryId,
47
- cdn: params.ComponentHostName,
48
- component: params.ComponentId,
49
- version: params.ComponentVersion,
50
- revision: params.ComponentRevision,
51
- data,
52
- };
53
- const optProps = {};
54
- if (params.ComponentInstanceId) {
55
- optProps.instance = params.ComponentInstanceId;
38
+ data = JSON.stringify({ _: getDataFromFields(props.fields) });
56
39
  }
57
- if (params.ComponentHTMLOverride) {
58
- optProps.dangerouslySetInnerHTML = { __html: params.ComponentHTMLOverride };
59
- }
60
- return (React.createElement(React.Fragment, null,
61
- React.createElement("link", { rel: "preload", as: "style", href: `${reqProps.cdn}/styles/${reqProps.library}/published.css` }),
62
- React.createElement("link", { rel: "preload", as: "fetch", href: `${reqProps.cdn}/components/${reqProps.library}/${reqProps.component}/${reqProps.version}/${reqProps.revision}.html` }),
63
- React.createElement("link", { rel: "preload", as: "script", href: FEAAS_MODULE_SRC }),
64
- React.createElement("feaas-stylesheet", { library: reqProps.library, cdn: reqProps.cdn }),
65
- React.createElement("feaas-component", Object.assign({}, reqProps, optProps))));
40
+ // FEaaS control would still be hydrated by client
41
+ // we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side
42
+ // this also allows component to fall back to full client-side rendering when template or src is empty
43
+ 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, revision: computedRevision }));
44
+ };
45
+ /**
46
+ * Fetches server component props required for server rendering, based on rendering params.
47
+ * Component endpoint will either be retrieved from params or from endpointOverride
48
+ * @param {FEaaSComponentParams} params component params
49
+ * @param {LayoutServicePageState} [pageState] page state to determine which component variant to use
50
+ * @param {string} [endpointOverride] optional override for component endpoint
51
+ */
52
+ export function fetchFEaaSComponentServerProps(params, pageState, endpointOverride) {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ const revisionFallback = pageState && pageState !== LayoutServicePageState.Normal ? 'staged' : 'published';
55
+ const src = endpointOverride || composeComponentEndpoint(params, revisionFallback);
56
+ try {
57
+ const { template, lastModified } = yield FEAAS.fetchComponent(src);
58
+ return {
59
+ revisionFallback,
60
+ template,
61
+ lastModified,
62
+ };
63
+ }
64
+ catch (e) {
65
+ console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
66
+ revisionFallback}" is present`);
67
+ console.error(e);
68
+ // leave revision fallback in so we can re-try with client-side rendering
69
+ return {
70
+ revisionFallback,
71
+ };
72
+ }
73
+ });
74
+ }
75
+ const getDataFromFields = (fields) => {
76
+ let data = {};
77
+ data = Object.entries(fields).reduce((acc, [key]) => {
78
+ acc[key] = getFieldValue(fields, key);
79
+ return acc;
80
+ }, data);
81
+ return data;
82
+ };
83
+ /**
84
+ * Build component endpoint URL from component's params
85
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
86
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
87
+ * @returns component endpoint URL
88
+ */
89
+ export const composeComponentEndpoint = (params, revisionFallback) => {
90
+ const revision = params.ComponentRevision || revisionFallback;
91
+ const hostname = params.ComponentHostName.startsWith('https://')
92
+ ? params.ComponentHostName
93
+ : `https://${params.ComponentHostName}`;
94
+ return `${hostname}/components/${params.LibraryId}/${params.ComponentId}/${params.ComponentVersion}/${revision}`;
66
95
  };
@@ -11,7 +11,6 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import React, { forwardRef } from 'react';
13
13
  import PropTypes from 'prop-types';
14
- import parse from 'html-react-parser';
15
14
  export const Link = forwardRef((_a, ref) => {
16
15
  var { field, editable, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
17
16
  const children = otherProps.children;
@@ -30,13 +29,13 @@ export const Link = forwardRef((_a, ref) => {
30
29
  // However, we cannot combine arbitrary unparsed HTML (innerHTML) based components with actual vDOM components (the children)
31
30
  // because the innerHTML is not parsed - it'd make a discontinuous vDOM. So, we'll go for the next best compromise of rendering the link field and children separately
32
31
  // as siblings. Should be "good enough" for most cases - and write your own helper if it isn't. Or bring xEditor out of 2006.
33
- const htmlProps = Object.assign(Object.assign({ className: 'sc-link-wrapper' }, otherProps), { key: 'editable' });
34
- const components = parse(markup, {
35
- htmlparser2: {
36
- lowerCaseTags: false,
37
- },
38
- });
39
- resultTags.push(React.createElement("span", Object.assign({}, htmlProps), components));
32
+ const htmlProps = Object.assign(Object.assign({ className: 'sc-link-wrapper', dangerouslySetInnerHTML: {
33
+ __html: markup,
34
+ } }, otherProps), { key: 'editable' });
35
+ // Exclude children, since 'dangerouslySetInnerHTML' and 'children' can't be set together
36
+ // and children will be added as a sibling
37
+ delete htmlProps.children;
38
+ resultTags.push(React.createElement("span", Object.assign({}, htmlProps)));
40
39
  // don't render normal link tag when editing, if no children exist
41
40
  // this preserves normal-ish behavior if not using a link body (no hacks required)
42
41
  if (!children) {
@@ -91,6 +91,9 @@ export class PlaceholderCommon extends React.Component {
91
91
  if (componentRendering.componentName === HIDDEN_RENDERING_NAME) {
92
92
  component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering;
93
93
  }
94
+ else if (!componentRendering.componentName) {
95
+ component = () => React.createElement(React.Fragment, null);
96
+ }
94
97
  else {
95
98
  component = this.getComponentForRendering(componentRendering);
96
99
  }
package/dist/esm/index.js CHANGED
@@ -9,7 +9,7 @@ export { Image, getEEMarkup, } from './components/Image';
9
9
  export { RichText, RichTextPropTypes } from './components/RichText';
10
10
  export { Text } from './components/Text';
11
11
  export { DateField } from './components/Date';
12
- export { FEaaSComponent } from './components/FEaaSComponent';
12
+ export { FEaaSComponent, fetchFEaaSComponentServerProps, } from './components/FEaaSComponent';
13
13
  export { Link, LinkPropTypes } from './components/Link';
14
14
  export { File } from './components/File';
15
15
  export { VisitorIdentification } from './components/VisitorIdentification';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-jss/sitecore-jss-react",
3
- "version": "21.1.1",
3
+ "version": "21.2.0-canary.2",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -10,7 +10,8 @@
10
10
  "lint": "eslint ./src/**/*.tsx ./src/**/*.ts",
11
11
  "test": "mocha --require ts-node/register/transpile-only --require ./src/tests/shim.ts ./src/tests/jsdom-setup.ts ./src/tests/enzyme-setup.ts \"./src/**/*.test.ts\" \"./src/**/*.test.tsx\" --exit",
12
12
  "prepublishOnly": "npm run build",
13
- "coverage": "nyc npm test"
13
+ "coverage": "nyc npm test",
14
+ "generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --readme none --out ../../ref-docs/sitecore-jss-react src/index.ts --githubPages false"
14
15
  },
15
16
  "engines": {
16
17
  "node": ">=12",
@@ -26,7 +27,6 @@
26
27
  "url": "https://github.com/sitecore/jss/issues"
27
28
  },
28
29
  "devDependencies": {
29
- "@sitecore-feaas/clientside": "^0.1.24",
30
30
  "@types/chai": "^4.3.4",
31
31
  "@types/chai-string": "^1.4.2",
32
32
  "@types/deep-equal": "^1.0.1",
@@ -47,7 +47,7 @@
47
47
  "eslint": "^8.28.0",
48
48
  "eslint-plugin-react": "^7.31.11",
49
49
  "jsdom": "^20.0.3",
50
- "mocha": "^10.1.0",
50
+ "mocha": "^10.2.0",
51
51
  "nyc": "^15.1.0",
52
52
  "react": "^18.2.0",
53
53
  "react-dom": "^18.2.0",
@@ -61,15 +61,15 @@
61
61
  "react-dom": "^18.2.0"
62
62
  },
63
63
  "dependencies": {
64
- "@sitecore-jss/sitecore-jss": "^21.1.1",
64
+ "@sitecore-feaas/clientside": "^0.1.48",
65
+ "@sitecore-jss/sitecore-jss": "^21.2.0-canary.2",
65
66
  "deep-equal": "^2.1.0",
66
- "html-react-parser": "^3.0.4",
67
67
  "prop-types": "^15.8.1",
68
68
  "style-attr": "^1.3.0"
69
69
  },
70
70
  "description": "",
71
71
  "types": "types/index.d.ts",
72
- "gitHead": "ae9d7fc994fa11061b5a164ff6a86b3ccf845a4c",
72
+ "gitHead": "c4de04e7eb8c309eb944236345c24b9a1db00de7",
73
73
  "files": [
74
74
  "dist",
75
75
  "types"
@@ -1,18 +1,70 @@
1
- import { ComponentParams, ComponentFields } from '@sitecore-jss/sitecore-jss/layout';
1
+ import { ComponentFields, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
2
2
  export declare const FEAAS_COMPONENT_RENDERING_NAME = "FEaaSComponent";
3
- export declare const FEAAS_MODULE_SRC = "https://feaasstatic.blob.core.windows.net/packages/clientside/latest/browser/index.esm.js";
4
- export type FEaaSComponentParams = ComponentParams & {
3
+ /**
4
+ * Params from a Sitecore FEaaS rendering
5
+ */
6
+ export type FEaaSComponentParams = {
5
7
  LibraryId?: string;
6
8
  ComponentId?: string;
7
9
  ComponentVersion?: string;
8
- ComponentRevision?: string;
10
+ ComponentRevision?: RevisionType;
9
11
  ComponentHostName?: string;
10
12
  ComponentInstanceId?: string;
11
13
  ComponentDataOverride?: string;
12
14
  ComponentHTMLOverride?: string;
15
+ styles?: string;
16
+ RenderingIdentifier?: string;
13
17
  };
14
- export type FEaaSComponentProps = {
18
+ type RevisionType = number | 'staged' | 'published' | 'saved';
19
+ /**
20
+ * FEaaS props for server rendering.
21
+ */
22
+ type FEaaSComponentServerProps = {
23
+ /**
24
+ * HTML template for presentation rendered inside the component
25
+ */
26
+ template?: string;
27
+ /**
28
+ * the date component data was last modified
29
+ */
30
+ lastModified?: string;
31
+ /**
32
+ * Default revision to be fetched. Should be 'staged' for editing/preview. Can be overriden by params.ComponentRevision
33
+ */
34
+ revisionFallback?: RevisionType;
35
+ };
36
+ /**
37
+ * FEaaS props for client side component. Should be used as fallback when server props are not provided.
38
+ * Would also be passed on server to avoid hydration issues
39
+ */
40
+ type FEaaSComponentClientProps = {
41
+ /**
42
+ * parameters from Sitecore's FEAAS component
43
+ */
15
44
  params?: FEaaSComponentParams;
45
+ /**
46
+ * field data from component's datasource
47
+ */
16
48
  fields?: ComponentFields;
17
49
  };
18
- export declare const FEaaSComponent: ({ params, fields }: FEaaSComponentProps) => JSX.Element;
50
+ export type FEaaSComponentProps = FEaaSComponentServerProps & FEaaSComponentClientProps;
51
+ /**
52
+ * @param {FEaaSComponentProps} props component props
53
+ */
54
+ export declare const FEaaSComponent: (props: FEaaSComponentProps) => JSX.Element;
55
+ /**
56
+ * Fetches server component props required for server rendering, based on rendering params.
57
+ * Component endpoint will either be retrieved from params or from endpointOverride
58
+ * @param {FEaaSComponentParams} params component params
59
+ * @param {LayoutServicePageState} [pageState] page state to determine which component variant to use
60
+ * @param {string} [endpointOverride] optional override for component endpoint
61
+ */
62
+ export declare function fetchFEaaSComponentServerProps(params: FEaaSComponentParams, pageState?: LayoutServicePageState, endpointOverride?: string): Promise<FEaaSComponentProps>;
63
+ /**
64
+ * Build component endpoint URL from component's params
65
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
66
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
67
+ * @returns component endpoint URL
68
+ */
69
+ export declare const composeComponentEndpoint: (params: FEaaSComponentParams, revisionFallback: RevisionType) => string;
70
+ export {};
@@ -32,7 +32,7 @@ export type LinkProps = React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLA
32
32
  */
33
33
  showLinkTextWithChildrenPresent?: boolean;
34
34
  };
35
- export declare const Link: React.ForwardRefExoticComponent<Pick<LinkProps, "key" | "editable" | "field" | "showLinkTextWithChildrenPresent" | keyof React.AnchorHTMLAttributes<HTMLAnchorElement>> & React.RefAttributes<HTMLAnchorElement>>;
35
+ export declare const Link: React.ForwardRefExoticComponent<Pick<LinkProps, "key" | "field" | "editable" | "showLinkTextWithChildrenPresent" | keyof React.AnchorHTMLAttributes<HTMLAnchorElement>> & React.RefAttributes<HTMLAnchorElement>>;
36
36
  export declare const LinkPropTypes: {
37
37
  field: PropTypes.Validator<NonNullable<NonNullable<PropTypes.InferProps<{
38
38
  href: PropTypes.Requireable<any>;
package/types/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { Image, ImageProps, ImageField, getEEMarkup, ImageFieldValue, ImageSizeP
10
10
  export { RichText, RichTextProps, RichTextPropTypes, RichTextField } from './components/RichText';
11
11
  export { Text, TextField } from './components/Text';
12
12
  export { DateField, DateFieldProps } from './components/Date';
13
- export { FEaaSComponent, FEaaSComponentProps } from './components/FEaaSComponent';
13
+ export { FEaaSComponent, FEaaSComponentProps, FEaaSComponentParams, fetchFEaaSComponentServerProps, } from './components/FEaaSComponent';
14
14
  export { Link, LinkField, LinkFieldValue, LinkProps, LinkPropTypes } from './components/Link';
15
15
  export { File, FileField } from './components/File';
16
16
  export { VisitorIdentification } from './components/VisitorIdentification';