@sitecore-jss/sitecore-jss-react 22.0.0-canary.9 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +202 -202
- package/README.md +10 -10
- package/dist/cjs/ComponentBuilder.js +25 -0
- package/dist/cjs/components/BYOCComponent.js +122 -0
- package/dist/cjs/components/BYOCWrapper.js +18 -0
- package/dist/cjs/components/Date.js +1 -4
- package/dist/cjs/components/FEaaSComponent.js +120 -61
- package/dist/cjs/components/FEaaSWrapper.js +18 -0
- package/dist/cjs/components/Image.js +6 -13
- package/dist/cjs/components/Link.js +8 -12
- package/dist/cjs/components/MissingComponent.js +6 -2
- package/dist/cjs/components/Placeholder.js +1 -29
- package/dist/cjs/components/PlaceholderCommon.js +21 -12
- package/dist/cjs/components/RichText.js +1 -5
- package/dist/cjs/components/SitecoreContext.js +2 -2
- package/dist/cjs/components/Text.js +1 -5
- package/dist/cjs/index.js +17 -3
- package/dist/cjs/utils.js +50 -2
- package/dist/esm/ComponentBuilder.js +21 -0
- package/dist/esm/components/BYOCComponent.js +91 -0
- package/dist/esm/components/BYOCWrapper.js +11 -0
- package/dist/esm/components/Date.js +1 -4
- package/dist/esm/components/FEaaSComponent.js +115 -61
- package/dist/esm/components/FEaaSWrapper.js +11 -0
- package/dist/esm/components/Image.js +6 -13
- package/dist/esm/components/Link.js +8 -12
- package/dist/esm/components/MissingComponent.js +6 -2
- package/dist/esm/components/Placeholder.js +2 -30
- package/dist/esm/components/PlaceholderCommon.js +21 -12
- package/dist/esm/components/RichText.js +1 -5
- package/dist/esm/components/SitecoreContext.js +2 -2
- package/dist/esm/components/Text.js +1 -5
- package/dist/esm/index.js +8 -4
- package/dist/esm/utils.js +47 -1
- package/package.json +9 -11
- package/types/ComponentBuilder.d.ts +28 -0
- package/types/components/BYOCComponent.d.ts +87 -0
- package/types/components/BYOCWrapper.d.ts +3 -0
- package/types/components/Date.d.ts +1 -0
- package/types/components/EditFrame.d.ts +1 -0
- package/types/components/FEaaSComponent.d.ts +59 -6
- package/types/components/FEaaSWrapper.d.ts +3 -0
- package/types/components/File.d.ts +1 -0
- package/types/components/HiddenRendering.d.ts +3 -1
- package/types/components/Image.d.ts +2 -6
- package/types/components/Link.d.ts +2 -1
- package/types/components/MissingComponent.d.ts +2 -0
- package/types/components/Placeholder.d.ts +1 -0
- package/types/components/PlaceholderCommon.d.ts +1 -0
- package/types/components/RichText.d.ts +1 -0
- package/types/components/SitecoreContext.d.ts +2 -1
- package/types/components/Text.d.ts +1 -0
- package/types/components/VisitorIdentification.d.ts +1 -0
- package/types/components/sharedTypes.d.ts +1 -0
- package/types/enhancers/withComponentFactory.d.ts +1 -0
- package/types/enhancers/withDatasourceCheck.d.ts +2 -1
- package/types/enhancers/withEditorChromes.d.ts +1 -0
- package/types/enhancers/withSitecoreContext.d.ts +2 -1
- package/types/index.d.ts +8 -4
- package/types/utils.d.ts +18 -1
|
@@ -0,0 +1,91 @@
|
|
|
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, _c;
|
|
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
|
+
let componentProps = {};
|
|
62
|
+
if ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentProps) {
|
|
63
|
+
try {
|
|
64
|
+
componentProps = (_b = JSON.parse(props.params.ComponentProps)) !== null && _b !== void 0 ? _b : {};
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error(`Parsing props for ${componentName} component from rendering params failed. Error: ${e}`);
|
|
68
|
+
return ErrorComponent ? (React.createElement(ErrorComponent, { error: e })) : (React.createElement(DefaultErrorComponent, { error: e }));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// apply props from item datasource
|
|
72
|
+
const dataSourcesData = Object.assign(Object.assign({}, props.fetchedData), { _: getDataFromFields((_c = props.fields) !== null && _c !== void 0 ? _c : {}) });
|
|
73
|
+
// we render fallback on client to avoid problems with client-only components
|
|
74
|
+
return (React.createElement(FEAAS.ExternalComponent, Object.assign({ componentName: componentName, clientFallback: fallbackComponent, datasources: dataSourcesData }, componentProps)));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Fetches server component props required for server rendering, based on rendering params.
|
|
79
|
+
* @param {BYOCComponentParams} params component params
|
|
80
|
+
*/
|
|
81
|
+
export function fetchBYOCComponentServerProps(params) {
|
|
82
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
const fetchDataOptions = params.ComponentDataOverride
|
|
84
|
+
? JSON.parse(params.ComponentDataOverride)
|
|
85
|
+
: {};
|
|
86
|
+
const fetchedData = yield FEAAS.DataSettings.fetch(fetchDataOptions || {});
|
|
87
|
+
return {
|
|
88
|
+
fetchedData,
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -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
|
+
};
|
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
export const DateField = (_a) => {
|
|
15
|
-
var { field, tag, editable, render } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "render"]);
|
|
15
|
+
var { field, tag, editable = true, render } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "render"]);
|
|
16
16
|
if (!field || (!field.editable && !field.value)) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
@@ -45,7 +45,4 @@ DateField.propTypes = {
|
|
|
45
45
|
editable: PropTypes.bool,
|
|
46
46
|
render: PropTypes.func,
|
|
47
47
|
};
|
|
48
|
-
DateField.defaultProps = {
|
|
49
|
-
editable: true,
|
|
50
|
-
};
|
|
51
48
|
DateField.displayName = 'Date';
|
|
@@ -1,66 +1,120 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import * as FEAAS from '@sitecore-feaas/clientside/react';
|
|
12
|
+
import { LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
|
|
13
|
+
import { getDataFromFields } from '../utils';
|
|
14
|
+
export const FEAAS_COMPONENT_RENDERING_NAME = 'FEaaSComponent';
|
|
15
|
+
/**
|
|
16
|
+
* @param {FEaaSComponentProps} props component props
|
|
17
|
+
*/
|
|
18
|
+
export const FEaaSComponent = (props) => {
|
|
19
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
20
|
+
const computedRevision = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.ComponentRevision) || props.revisionFallback;
|
|
21
|
+
if (!props.template &&
|
|
22
|
+
(!props.params ||
|
|
23
|
+
!props.params.LibraryId ||
|
|
24
|
+
!props.params.ComponentId ||
|
|
25
|
+
!props.params.ComponentVersion ||
|
|
26
|
+
!props.params.ComponentHostName ||
|
|
27
|
+
!computedRevision)) {
|
|
21
28
|
// Missing FEaaS component required props
|
|
22
29
|
return null;
|
|
23
30
|
}
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
31
|
+
// combine fetchedData from server with datasource data (if present)
|
|
32
|
+
const data = Object.assign(Object.assign({}, props.fetchedData), { _: getDataFromFields((_b = props.fields) !== null && _b !== void 0 ? _b : {}) });
|
|
33
|
+
// FEaaS control would still be hydrated by client
|
|
34
|
+
// we pass all the props as a workaround to avoid hydration error, until we convert all JSS components to server side
|
|
35
|
+
// this also allows component to fall back to full client-side rendering when template or src is empty
|
|
36
|
+
// FEAAS should not fetch anything, since JSS does the fetching - so we pass empty array into fetch param
|
|
37
|
+
return (React.createElement(FEAAS.Component, { data: 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, fetch: [] }));
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Fetches server component props required for server rendering, based on rendering params.
|
|
41
|
+
* Component endpoint will either be retrieved from params or from endpointOverride
|
|
42
|
+
* @param {FEaaSComponentParams} params component params
|
|
43
|
+
* @param {LayoutServicePageState} [pageState] page state to determine which component variant to use
|
|
44
|
+
* @param {string} [endpointOverride] optional override for component endpoint
|
|
45
|
+
*/
|
|
46
|
+
export function fetchFEaaSComponentServerProps(params, pageState, endpointOverride) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const revisionFallback = pageState && pageState !== LayoutServicePageState.Normal ? 'staged' : 'published';
|
|
49
|
+
const src = endpointOverride || composeComponentEndpoint(params, revisionFallback);
|
|
50
|
+
let template = '';
|
|
51
|
+
let fetchedData = {};
|
|
52
|
+
const fetchDataOptions = params.ComponentDataOverride
|
|
53
|
+
? JSON.parse(params.ComponentDataOverride)
|
|
54
|
+
: {};
|
|
55
|
+
try {
|
|
56
|
+
template = yield fetchComponentTemplate(src, params, revisionFallback);
|
|
57
|
+
fetchedData = yield fetchData(fetchDataOptions);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.error(e);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
fetchedData,
|
|
64
|
+
revisionFallback,
|
|
65
|
+
template,
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} src component endpoint
|
|
71
|
+
* @param {FEaaSComponentParams} params rendering parameters for FEAAS component
|
|
72
|
+
* @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
|
|
73
|
+
*/
|
|
74
|
+
function fetchComponentTemplate(src, params, revisionFallback) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
try {
|
|
77
|
+
const { template } = yield FEAAS.fetchComponent(src);
|
|
78
|
+
return template;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
|
|
82
|
+
revisionFallback}" is present`);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetches component data based on the provided data options.
|
|
89
|
+
* This function asynchronously fetches data using the FEAAS.DataSettings.fetch method.
|
|
90
|
+
*
|
|
91
|
+
* @param {FEAAS.DataOptions} dataOptions - Options to customize data fetching.
|
|
92
|
+
* @returns {Promise<FEAAS.DataScopes>} A promise that resolves with the fetched data,
|
|
93
|
+
* or rejects with an error if data fetching encounters an issue.
|
|
94
|
+
* @throws {Error} If an error occurs during data fetching, it is propagated as an error.
|
|
95
|
+
*/
|
|
96
|
+
function fetchData(dataOptions) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
try {
|
|
99
|
+
const fetchedData = yield FEAAS.DataSettings.fetch(dataOptions || {});
|
|
100
|
+
return fetchedData;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('Fetch FEAAS component data settings failed');
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build component endpoint URL from component's params
|
|
110
|
+
* @param {FEaaSComponentParams} params rendering parameters for FEAAS component
|
|
111
|
+
* @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
|
|
112
|
+
* @returns component endpoint URL
|
|
113
|
+
*/
|
|
114
|
+
export const composeComponentEndpoint = (params, revisionFallback) => {
|
|
115
|
+
const revision = params.ComponentRevision || revisionFallback;
|
|
116
|
+
const hostname = params.ComponentHostName.startsWith('https://')
|
|
117
|
+
? params.ComponentHostName
|
|
118
|
+
: `https://${params.ComponentHostName}`;
|
|
119
|
+
return `${hostname}/components/${params.LibraryId}/${params.ComponentId}/${params.ComponentVersion}/${revision}`;
|
|
66
120
|
};
|
|
@@ -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
|
+
};
|
|
@@ -12,8 +12,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { mediaApi } from '@sitecore-jss/sitecore-jss/media';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
import React from 'react';
|
|
15
|
-
import ReactDOMServer from 'react-dom/server';
|
|
16
15
|
import { addClassName, convertAttributesToReactProps } from '../utils';
|
|
16
|
+
import { getAttributesString } from '../utils';
|
|
17
17
|
const getEditableWrapper = (editableMarkup, ...otherProps) => (
|
|
18
18
|
// create an inline wrapper and use dangerouslySetInnerHTML.
|
|
19
19
|
// if we try to parse the EE value, the parser will strip invalid or disallowed attributes from html elements - and EE uses several
|
|
@@ -55,18 +55,14 @@ export const getEEMarkup = (imageField, imageParams, mediaUrlPrefix, otherProps)
|
|
|
55
55
|
if (!imgAttrs) {
|
|
56
56
|
return getEditableWrapper(imageField.editable);
|
|
57
57
|
}
|
|
58
|
-
const imgHtml =
|
|
58
|
+
const imgHtml = `<img ${getAttributesString(imgAttrs)} />`;
|
|
59
59
|
const editableMarkup = imageField.editable.replace(foundImg.imgTag, imgHtml);
|
|
60
60
|
return getEditableWrapper(editableMarkup);
|
|
61
61
|
};
|
|
62
62
|
export const Image = (_a) => {
|
|
63
|
-
var {
|
|
64
|
-
|
|
65
|
-
if (field
|
|
66
|
-
media = field;
|
|
67
|
-
}
|
|
68
|
-
const dynamicMedia = media;
|
|
69
|
-
if (!media ||
|
|
63
|
+
var { editable = true, imageParams, field, mediaUrlPrefix } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix"]);
|
|
64
|
+
const dynamicMedia = field;
|
|
65
|
+
if (!field ||
|
|
70
66
|
(!dynamicMedia.editable && !dynamicMedia.value && !dynamicMedia.src)) {
|
|
71
67
|
return null;
|
|
72
68
|
}
|
|
@@ -76,7 +72,7 @@ export const Image = (_a) => {
|
|
|
76
72
|
}
|
|
77
73
|
// some wise-guy/gal is passing in a 'raw' image object value
|
|
78
74
|
const img = dynamicMedia.src
|
|
79
|
-
?
|
|
75
|
+
? field
|
|
80
76
|
: dynamicMedia.value;
|
|
81
77
|
if (!img) {
|
|
82
78
|
return null;
|
|
@@ -110,7 +106,4 @@ Image.propTypes = {
|
|
|
110
106
|
mediaUrlPrefix: PropTypes.instanceOf(RegExp),
|
|
111
107
|
imageParams: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]).isRequired),
|
|
112
108
|
};
|
|
113
|
-
Image.defaultProps = {
|
|
114
|
-
editable: true,
|
|
115
|
-
};
|
|
116
109
|
Image.displayName = 'Image';
|
|
@@ -11,9 +11,8 @@ 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
|
-
var { field, editable, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
|
|
15
|
+
var { field, editable = true, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
|
|
17
16
|
const children = otherProps.children;
|
|
18
17
|
const dynamicField = field;
|
|
19
18
|
if (!field ||
|
|
@@ -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'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
resultTags.push(React.createElement("span", Object.assign({}, htmlProps)
|
|
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) {
|
|
@@ -81,7 +80,4 @@ export const LinkPropTypes = {
|
|
|
81
80
|
showLinkTextWithChildrenPresent: PropTypes.bool,
|
|
82
81
|
};
|
|
83
82
|
Link.propTypes = LinkPropTypes;
|
|
84
|
-
Link.defaultProps = {
|
|
85
|
-
editable: true,
|
|
86
|
-
};
|
|
87
83
|
Link.displayName = 'Link';
|
|
@@ -4,7 +4,11 @@ export const MissingComponent = (props) => {
|
|
|
4
4
|
const componentName = props.rendering && props.rendering.componentName
|
|
5
5
|
? props.rendering.componentName
|
|
6
6
|
: 'Unnamed Component';
|
|
7
|
-
|
|
7
|
+
// error override would mean component is not unimplemented
|
|
8
|
+
!props.errorOverride &&
|
|
9
|
+
console.log(`Component props for unimplemented '${componentName}' component`, props);
|
|
10
|
+
const errorMessage = props.errorOverride ||
|
|
11
|
+
'JSS component is missing React implementation. See the developer console for more information.';
|
|
8
12
|
return (React.createElement("div", { style: {
|
|
9
13
|
background: 'darkorange',
|
|
10
14
|
outline: '5px solid orange',
|
|
@@ -13,7 +17,7 @@ export const MissingComponent = (props) => {
|
|
|
13
17
|
maxWidth: '500px',
|
|
14
18
|
} },
|
|
15
19
|
React.createElement("h2", null, componentName),
|
|
16
|
-
React.createElement("p", null,
|
|
20
|
+
React.createElement("p", null, errorMessage)));
|
|
17
21
|
};
|
|
18
22
|
MissingComponent.propTypes = {
|
|
19
23
|
rendering: PropTypes.shape({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { PlaceholderCommon } from './PlaceholderCommon';
|
|
3
3
|
import { withComponentFactory } from '../enhancers/withComponentFactory';
|
|
4
|
-
import { HorizonEditor
|
|
4
|
+
import { HorizonEditor } from '@sitecore-jss/sitecore-jss/utils';
|
|
5
5
|
/**
|
|
6
6
|
* @param {HtmlElementRendering | ComponentRendering} rendering
|
|
7
7
|
*/
|
|
@@ -44,36 +44,8 @@ class PlaceholderComponent extends PlaceholderCommon {
|
|
|
44
44
|
}
|
|
45
45
|
const renderingData = childProps.rendering;
|
|
46
46
|
const placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name);
|
|
47
|
-
this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
|
|
48
|
-
// This is a workaround to insert Experience Editor-specific markup on the page for empty placeholders.
|
|
49
|
-
// It makes sure the markup is inserted by react and thus avoiding hydration errors when in editing mode
|
|
50
|
-
if (this.isEmpty && ExperienceEditor.isActive()) {
|
|
51
|
-
const codePos = placeholderData.findIndex((component) => component.name === 'code' &&
|
|
52
|
-
component.attributes.kind === 'open');
|
|
53
|
-
const plhId = placeholderData[codePos].attributes.id;
|
|
54
|
-
const emptyPlaceholderMarkup = [
|
|
55
|
-
{
|
|
56
|
-
name: 'span',
|
|
57
|
-
contents: null,
|
|
58
|
-
attributes: {
|
|
59
|
-
type: 'text/sitecore',
|
|
60
|
-
'sc-part-of': 'placeholder rendering',
|
|
61
|
-
style: 'display: none;',
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'div',
|
|
66
|
-
contents: null,
|
|
67
|
-
attributes: {
|
|
68
|
-
class: 'scEnabledChrome scEmptyPlaceholder',
|
|
69
|
-
'sc-part-of': 'placeholder',
|
|
70
|
-
'sc-placeholder-id': plhId,
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
];
|
|
74
|
-
placeholderData.splice(codePos + 1, 0, ...emptyPlaceholderMarkup);
|
|
75
|
-
}
|
|
76
47
|
const components = this.getComponentsForRenderingData(placeholderData);
|
|
48
|
+
this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
|
|
77
49
|
if (this.props.renderEmpty && this.isEmpty) {
|
|
78
50
|
const rendered = this.props.renderEmpty(components);
|
|
79
51
|
return components.length ? this.renderEmptyPlaceholder(rendered) : rendered;
|
|
@@ -15,14 +15,9 @@ import { MissingComponent } from './MissingComponent';
|
|
|
15
15
|
import { convertAttributesToReactProps } from '../utils';
|
|
16
16
|
import { HiddenRendering, HIDDEN_RENDERING_NAME } from './HiddenRendering';
|
|
17
17
|
import { FEaaSComponent, FEAAS_COMPONENT_RENDERING_NAME } from './FEaaSComponent';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
const EXCLUDE_PLACEHOLDERS_RENDER = [
|
|
23
|
-
new RegExp(/column-(\d{1})-\{\*\}/i),
|
|
24
|
-
new RegExp(/row-(\d{1})-\{\*\}/i),
|
|
25
|
-
];
|
|
18
|
+
import { FEaaSWrapper, FEAAS_WRAPPER_RENDERING_NAME } from './FEaaSWrapper';
|
|
19
|
+
import { BYOCComponent, BYOC_COMPONENT_RENDERING_NAME } from './BYOCComponent';
|
|
20
|
+
import { BYOCWrapper, BYOC_WRAPPER_RENDERING_NAME } from './BYOCWrapper';
|
|
26
21
|
export class PlaceholderCommon extends React.Component {
|
|
27
22
|
constructor(props) {
|
|
28
23
|
super(props);
|
|
@@ -38,8 +33,10 @@ export class PlaceholderCommon extends React.Component {
|
|
|
38
33
|
from backend side we get common name of placeholder is called 'nameOfContainer-{*}' where '{*}' marker for replacing **/
|
|
39
34
|
if (rendering === null || rendering === void 0 ? void 0 : rendering.placeholders) {
|
|
40
35
|
Object.keys(rendering.placeholders).forEach((placeholder) => {
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const patternPlaceholder = placeholder.indexOf('{*}') !== -1
|
|
37
|
+
? new RegExp(`^${placeholder.replace(/\{\*\}+/i, '\\d+')}$`)
|
|
38
|
+
: null;
|
|
39
|
+
if (patternPlaceholder && patternPlaceholder.test(name)) {
|
|
43
40
|
rendering.placeholders[name] = rendering.placeholders[placeholder];
|
|
44
41
|
delete rendering.placeholders[placeholder];
|
|
45
42
|
}
|
|
@@ -97,8 +94,20 @@ export class PlaceholderCommon extends React.Component {
|
|
|
97
94
|
else {
|
|
98
95
|
component = this.getComponentForRendering(componentRendering);
|
|
99
96
|
}
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
// Fallback/defaults for Sitecore Component renderings (in case not defined in component factory)
|
|
98
|
+
if (!component) {
|
|
99
|
+
if (componentRendering.componentName === FEAAS_COMPONENT_RENDERING_NAME) {
|
|
100
|
+
component = FEaaSComponent;
|
|
101
|
+
}
|
|
102
|
+
else if (componentRendering.componentName === FEAAS_WRAPPER_RENDERING_NAME) {
|
|
103
|
+
component = FEaaSWrapper;
|
|
104
|
+
}
|
|
105
|
+
else if (componentRendering.componentName === BYOC_COMPONENT_RENDERING_NAME) {
|
|
106
|
+
component = BYOCComponent;
|
|
107
|
+
}
|
|
108
|
+
else if (componentRendering.componentName === BYOC_WRAPPER_RENDERING_NAME) {
|
|
109
|
+
component = BYOCWrapper;
|
|
110
|
+
}
|
|
102
111
|
}
|
|
103
112
|
if (!component) {
|
|
104
113
|
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.`);
|
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import React, { forwardRef } from 'react';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
export const RichText = forwardRef((_a, ref) => {
|
|
15
|
-
var { field, tag, editable } = _a, otherProps = __rest(_a, ["field", "tag", "editable"]);
|
|
15
|
+
var { field, tag = 'div', editable = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable"]);
|
|
16
16
|
if (!field || (!field.editable && !field.value)) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
@@ -30,8 +30,4 @@ export const RichTextPropTypes = {
|
|
|
30
30
|
editable: PropTypes.bool,
|
|
31
31
|
};
|
|
32
32
|
RichText.propTypes = RichTextPropTypes;
|
|
33
|
-
RichText.defaultProps = {
|
|
34
|
-
tag: 'div',
|
|
35
|
-
editable: true,
|
|
36
|
-
};
|
|
37
33
|
RichText.displayName = 'RichText';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import
|
|
4
|
+
import fastDeepEqual from 'fast-deep-equal/es6/react';
|
|
5
5
|
export const SitecoreContextReactContext = React.createContext({});
|
|
6
6
|
export const ComponentFactoryReactContext = React.createContext({});
|
|
7
7
|
export class SitecoreContext extends React.Component {
|
|
@@ -37,7 +37,7 @@ export class SitecoreContext extends React.Component {
|
|
|
37
37
|
componentDidUpdate(prevProps) {
|
|
38
38
|
// In case if somebody will manage SitecoreContext state by passing fresh `layoutData` prop
|
|
39
39
|
// instead of using `updateSitecoreContext`
|
|
40
|
-
if (!
|
|
40
|
+
if (!fastDeepEqual(prevProps.layoutData, this.props.layoutData)) {
|
|
41
41
|
this.setContext(this.props.layoutData);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
export const Text = (_a) => {
|
|
15
|
-
var { field, tag, editable, encode } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "encode"]);
|
|
15
|
+
var { field, tag, editable = true, encode = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "encode"]);
|
|
16
16
|
if (!field || (!field.editable && (field.value === undefined || field.value === ''))) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
@@ -69,8 +69,4 @@ Text.propTypes = {
|
|
|
69
69
|
editable: PropTypes.bool,
|
|
70
70
|
encode: PropTypes.bool,
|
|
71
71
|
};
|
|
72
|
-
Text.defaultProps = {
|
|
73
|
-
editable: true,
|
|
74
|
-
encode: true,
|
|
75
|
-
};
|
|
76
72
|
Text.displayName = 'Text';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
export { constants, enableDebug } from '@sitecore-jss/sitecore-jss';
|
|
1
|
+
export { constants, enableDebug, ClientError } from '@sitecore-jss/sitecore-jss';
|
|
2
2
|
export { isEditorActive, resetEditorChromes, DefaultEditFrameButton, DefaultEditFrameButtons, } from '@sitecore-jss/sitecore-jss/utils';
|
|
3
|
-
export { LayoutServicePageState, GraphQLLayoutService, RestLayoutService, getChildPlaceholder, getFieldValue, } from '@sitecore-jss/sitecore-jss/layout';
|
|
3
|
+
export { getContentStylesheetLink, getComponentLibraryStylesheetLinks, LayoutServicePageState, GraphQLLayoutService, RestLayoutService, getChildPlaceholder, getFieldValue, } from '@sitecore-jss/sitecore-jss/layout';
|
|
4
4
|
export { trackingApi, } from '@sitecore-jss/sitecore-jss/tracking';
|
|
5
5
|
export { GraphQLDictionaryService, RestDictionaryService, } from '@sitecore-jss/sitecore-jss/i18n';
|
|
6
|
+
export { DefaultRetryStrategy, GraphQLRequestClient, } from '@sitecore-jss/sitecore-jss/graphql';
|
|
6
7
|
export { mediaApi } from '@sitecore-jss/sitecore-jss/media';
|
|
7
|
-
export { getFEAASLibraryStylesheetLinks } from '@sitecore-jss/sitecore-jss/feaas';
|
|
8
8
|
export { Placeholder } from './components/Placeholder';
|
|
9
9
|
export { Image, getEEMarkup, } from './components/Image';
|
|
10
10
|
export { RichText, RichTextPropTypes } from './components/RichText';
|
|
11
11
|
export { Text } from './components/Text';
|
|
12
12
|
export { DateField } from './components/Date';
|
|
13
|
-
export { FEaaSComponent } from './components/FEaaSComponent';
|
|
13
|
+
export { FEaaSComponent, fetchFEaaSComponentServerProps, } from './components/FEaaSComponent';
|
|
14
|
+
export { FEaaSWrapper } from './components/FEaaSWrapper';
|
|
15
|
+
export { BYOCComponent, fetchBYOCComponentServerProps, } from './components/BYOCComponent';
|
|
16
|
+
export { BYOCWrapper } from './components/BYOCWrapper';
|
|
14
17
|
export { Link, LinkPropTypes } from './components/Link';
|
|
15
18
|
export { File } from './components/File';
|
|
16
19
|
export { VisitorIdentification } from './components/VisitorIdentification';
|
|
@@ -20,3 +23,4 @@ export { withEditorChromes } from './enhancers/withEditorChromes';
|
|
|
20
23
|
export { withPlaceholder } from './enhancers/withPlaceholder';
|
|
21
24
|
export { withDatasourceCheck } from './enhancers/withDatasourceCheck';
|
|
22
25
|
export { EditFrame } from './components/EditFrame';
|
|
26
|
+
export { ComponentBuilder } from './ComponentBuilder';
|