@sitecore-content-sdk/react 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE.txt +202 -0
  2. package/README.md +10 -0
  3. package/dist/cjs/ComponentBuilder.js +25 -0
  4. package/dist/cjs/components/BYOCComponent.js +132 -0
  5. package/dist/cjs/components/BYOCWrapper.js +21 -0
  6. package/dist/cjs/components/ComponentLibraryLayout.js +80 -0
  7. package/dist/cjs/components/Date.js +57 -0
  8. package/dist/cjs/components/DefaultEmptyFieldEditingComponents.js +22 -0
  9. package/dist/cjs/components/EditingScripts.js +27 -0
  10. package/dist/cjs/components/ErrorBoundary.js +95 -0
  11. package/dist/cjs/components/FEaaSComponent.js +161 -0
  12. package/dist/cjs/components/FEaaSWrapper.js +18 -0
  13. package/dist/cjs/components/FieldMetadata.js +34 -0
  14. package/dist/cjs/components/File.js +51 -0
  15. package/dist/cjs/components/HiddenRendering.js +18 -0
  16. package/dist/cjs/components/Image.js +83 -0
  17. package/dist/cjs/components/Link.js +106 -0
  18. package/dist/cjs/components/MissingComponent.js +34 -0
  19. package/dist/cjs/components/Placeholder.js +72 -0
  20. package/dist/cjs/components/PlaceholderCommon.js +191 -0
  21. package/dist/cjs/components/PlaceholderMetadata.js +63 -0
  22. package/dist/cjs/components/RichText.js +82 -0
  23. package/dist/cjs/components/SitecoreContext.js +67 -0
  24. package/dist/cjs/components/Text.js +78 -0
  25. package/dist/cjs/components/sharedTypes.js +2 -0
  26. package/dist/cjs/enhancers/withComponentFactory.js +26 -0
  27. package/dist/cjs/enhancers/withDatasourceCheck.js +28 -0
  28. package/dist/cjs/enhancers/withEditorChromes.js +24 -0
  29. package/dist/cjs/enhancers/withEmptyFieldEditingComponent.js +65 -0
  30. package/dist/cjs/enhancers/withFieldMetadata.js +69 -0
  31. package/dist/cjs/enhancers/withPlaceholder.js +63 -0
  32. package/dist/cjs/enhancers/withSitecoreContext.js +48 -0
  33. package/dist/cjs/index.js +78 -0
  34. package/dist/cjs/utils.js +38 -0
  35. package/dist/esm/ComponentBuilder.js +21 -0
  36. package/dist/esm/components/BYOCComponent.js +91 -0
  37. package/dist/esm/components/BYOCWrapper.js +14 -0
  38. package/dist/esm/components/ComponentLibraryLayout.js +43 -0
  39. package/dist/esm/components/Date.js +51 -0
  40. package/dist/esm/components/DefaultEmptyFieldEditingComponents.js +14 -0
  41. package/dist/esm/components/EditingScripts.js +20 -0
  42. package/dist/esm/components/ErrorBoundary.js +60 -0
  43. package/dist/esm/components/FEaaSComponent.js +119 -0
  44. package/dist/esm/components/FEaaSWrapper.js +11 -0
  45. package/dist/esm/components/FieldMetadata.js +27 -0
  46. package/dist/esm/components/File.js +44 -0
  47. package/dist/esm/components/HiddenRendering.js +11 -0
  48. package/dist/esm/components/Image.js +77 -0
  49. package/dist/esm/components/Link.js +67 -0
  50. package/dist/esm/components/MissingComponent.js +27 -0
  51. package/dist/esm/components/Placeholder.js +66 -0
  52. package/dist/esm/components/PlaceholderCommon.js +184 -0
  53. package/dist/esm/components/PlaceholderMetadata.js +56 -0
  54. package/dist/esm/components/RichText.js +43 -0
  55. package/dist/esm/components/SitecoreContext.js +60 -0
  56. package/dist/esm/components/Text.js +72 -0
  57. package/dist/esm/components/sharedTypes.js +1 -0
  58. package/dist/esm/enhancers/withComponentFactory.js +20 -0
  59. package/dist/esm/enhancers/withDatasourceCheck.js +20 -0
  60. package/dist/esm/enhancers/withEditorChromes.js +17 -0
  61. package/dist/esm/enhancers/withEmptyFieldEditingComponent.js +29 -0
  62. package/dist/esm/enhancers/withFieldMetadata.js +33 -0
  63. package/dist/esm/enhancers/withPlaceholder.js +57 -0
  64. package/dist/esm/enhancers/withSitecoreContext.js +41 -0
  65. package/dist/esm/index.js +28 -0
  66. package/dist/esm/utils.js +33 -0
  67. package/package.json +78 -0
  68. package/types/ComponentBuilder.d.ts +27 -0
  69. package/types/components/BYOCComponent.d.ts +93 -0
  70. package/types/components/BYOCWrapper.d.ts +6 -0
  71. package/types/components/ComponentLibraryLayout.d.ts +2 -0
  72. package/types/components/Date.d.ts +16 -0
  73. package/types/components/DefaultEmptyFieldEditingComponents.d.ts +3 -0
  74. package/types/components/EditingScripts.d.ts +4 -0
  75. package/types/components/ErrorBoundary.d.ts +17 -0
  76. package/types/components/FEaaSComponent.d.ts +71 -0
  77. package/types/components/FEaaSWrapper.d.ts +3 -0
  78. package/types/components/FieldMetadata.d.ts +22 -0
  79. package/types/components/File.d.ts +18 -0
  80. package/types/components/HiddenRendering.d.ts +2 -0
  81. package/types/components/Image.d.ts +48 -0
  82. package/types/components/Link.d.ts +38 -0
  83. package/types/components/MissingComponent.d.ts +8 -0
  84. package/types/components/Placeholder.d.ts +20 -0
  85. package/types/components/PlaceholderCommon.d.ts +98 -0
  86. package/types/components/PlaceholderMetadata.d.ts +28 -0
  87. package/types/components/RichText.d.ts +29 -0
  88. package/types/components/SitecoreContext.d.ts +42 -0
  89. package/types/components/Text.d.ts +20 -0
  90. package/types/components/sharedTypes.d.ts +28 -0
  91. package/types/enhancers/withComponentFactory.d.ts +12 -0
  92. package/types/enhancers/withDatasourceCheck.d.ts +21 -0
  93. package/types/enhancers/withEditorChromes.d.ts +2 -0
  94. package/types/enhancers/withEmptyFieldEditingComponent.d.ts +27 -0
  95. package/types/enhancers/withFieldMetadata.d.ts +16 -0
  96. package/types/enhancers/withPlaceholder.d.ts +34 -0
  97. package/types/enhancers/withSitecoreContext.d.ts +40 -0
  98. package/types/index.d.ts +30 -0
  99. package/types/utils.d.ts +17 -0
@@ -0,0 +1,60 @@
1
+ import React, { Suspense } from 'react';
2
+ import { LayoutServicePageState } from '@sitecore-content-sdk/core/layout';
3
+ import { withSitecoreContext } from '../enhancers/withSitecoreContext';
4
+ class ErrorBoundary extends React.Component {
5
+ constructor(props) {
6
+ super(props);
7
+ this.defaultErrorMessage = 'There was a problem loading this section.';
8
+ this.defaultLoadingMessage = 'Loading component...';
9
+ this.state = { error: null };
10
+ }
11
+ static getDerivedStateFromError(error) {
12
+ return { error: error };
13
+ }
14
+ componentDidCatch(error, errorInfo) {
15
+ var _a, _b;
16
+ if (this.showErrorDetails()) {
17
+ console.error(`An error occurred in component ${(_a = this.props.rendering) === null || _a === void 0 ? void 0 : _a.componentName} (${(_b = this.props.rendering) === null || _b === void 0 ? void 0 : _b.uid}): `);
18
+ }
19
+ console.error({ error, errorInfo });
20
+ }
21
+ isInDevMode() {
22
+ return process.env.NODE_ENV === 'development';
23
+ }
24
+ showErrorDetails() {
25
+ var _a, _b;
26
+ return (this.isInDevMode() ||
27
+ ((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageState) === LayoutServicePageState.Edit ||
28
+ ((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.pageState) === LayoutServicePageState.Preview);
29
+ }
30
+ render() {
31
+ var _a;
32
+ if (this.state.error) {
33
+ if (this.props.errorComponent) {
34
+ return React.createElement(this.props.errorComponent, { error: this.state.error });
35
+ }
36
+ else {
37
+ if (this.showErrorDetails()) {
38
+ return (React.createElement("div", null,
39
+ React.createElement("div", { className: "sc-jss-placeholder-error" },
40
+ "A rendering error occurred in component",
41
+ ' ',
42
+ React.createElement("em", null, (_a = this.props.rendering) === null || _a === void 0 ? void 0 : _a.componentName),
43
+ React.createElement("br", null),
44
+ "Error: ",
45
+ React.createElement("em", null, this.state.error.message || JSON.stringify(this.state.error)))));
46
+ }
47
+ else {
48
+ return (React.createElement("div", null,
49
+ React.createElement("div", { className: "sc-jss-placeholder-error" }, this.defaultErrorMessage)));
50
+ }
51
+ }
52
+ }
53
+ // do not apply suspense on already dynamic components
54
+ if (this.props.isDynamic) {
55
+ return this.props.children;
56
+ }
57
+ return (React.createElement(Suspense, { fallback: React.createElement("h4", null, this.props.componentLoadingMessage || this.defaultLoadingMessage) }, this.props.children));
58
+ }
59
+ }
60
+ export default withSitecoreContext()(ErrorBoundary);
@@ -0,0 +1,119 @@
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 * as FEAAS from '@sitecore-feaas/clientside/react';
12
+ import { LayoutServicePageState } from '@sitecore-content-sdk/core/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)) {
28
+ // Missing FEaaS component required props
29
+ return null;
30
+ }
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
+ * @param {FEAAS.DataOptions} dataOptions - Options to customize data fetching.
91
+ * @returns {Promise<FEAAS.DataScopes>} A promise that resolves with the fetched data,
92
+ * or rejects with an error if data fetching encounters an issue.
93
+ * @throws {Error} If an error occurs during data fetching, it is propagated as an error.
94
+ */
95
+ function fetchData(dataOptions) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ try {
98
+ const fetchedData = yield FEAAS.DataSettings.fetch(dataOptions || {});
99
+ return fetchedData;
100
+ }
101
+ catch (error) {
102
+ console.error('Fetch FEAAS component data settings failed');
103
+ throw error;
104
+ }
105
+ });
106
+ }
107
+ /**
108
+ * Build component endpoint URL from component's params
109
+ * @param {FEaaSComponentParams} params rendering parameters for FEAAS component
110
+ * @param {RevisionType} revisionFallback fallback revision to fetch if revision is absent in params
111
+ * @returns component endpoint URL
112
+ */
113
+ export const composeComponentEndpoint = (params, revisionFallback) => {
114
+ const revision = params.ComponentRevision || revisionFallback;
115
+ const hostname = params.ComponentHostName.startsWith('https://')
116
+ ? params.ComponentHostName
117
+ : `https://${params.ComponentHostName}`;
118
+ return `${hostname}/components/${params.LibraryId}/${params.ComponentId}/${params.ComponentVersion}/${revision}`;
119
+ };
@@ -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
+ };
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { MetadataKind } from '@sitecore-content-sdk/core/editing';
4
+ /**
5
+ * The component which renders field metadata markup
6
+ * @param {FieldMetadataProps} props the props of the component
7
+ * @returns metadata markup wrapped around children
8
+ */
9
+ export const FieldMetadata = (props) => {
10
+ const data = JSON.stringify(props.metadata);
11
+ const attributes = {
12
+ type: 'text/sitecore',
13
+ chrometype: 'field',
14
+ className: 'scpm',
15
+ };
16
+ const codeOpenAttributes = Object.assign(Object.assign({}, attributes), { kind: MetadataKind.Open });
17
+ const codeCloseAttributes = Object.assign(Object.assign({}, attributes), { kind: MetadataKind.Close });
18
+ return (React.createElement(React.Fragment, null,
19
+ React.createElement("code", Object.assign({}, codeOpenAttributes), data),
20
+ props.children,
21
+ React.createElement("code", Object.assign({}, codeCloseAttributes))));
22
+ };
23
+ FieldMetadata.displayName = 'FieldMetadata';
24
+ FieldMetadata.propTypes = {
25
+ metadata: PropTypes.object.isRequired,
26
+ children: PropTypes.node.isRequired,
27
+ };
@@ -0,0 +1,44 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
13
+ import PropTypes from 'prop-types';
14
+ import React from 'react';
15
+ export const File = (_a) => {
16
+ var { field, children } = _a, otherProps = __rest(_a, ["field", "children"]);
17
+ const dynamicField = field;
18
+ if (isFieldValueEmpty(dynamicField)) {
19
+ return null;
20
+ }
21
+ // handle link directly on field for forgetful devs
22
+ const file = (dynamicField.src
23
+ ? field
24
+ : dynamicField.value);
25
+ if (!file) {
26
+ return null;
27
+ }
28
+ const linkText = !children ? file.title || file.displayName : null;
29
+ const anchorAttrs = {
30
+ href: file.src,
31
+ };
32
+ return React.createElement('a', Object.assign(Object.assign({}, anchorAttrs), otherProps), linkText, children);
33
+ };
34
+ File.propTypes = {
35
+ field: PropTypes.oneOfType([
36
+ PropTypes.shape({
37
+ src: PropTypes.string,
38
+ }),
39
+ PropTypes.shape({
40
+ value: PropTypes.object,
41
+ }),
42
+ ]).isRequired,
43
+ };
44
+ File.displayName = 'File';
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ const styles = {
3
+ backgroundImage: 'linear-gradient(45deg, #ffffff 25%, #dcdcdc 25%, #dcdcdc 50%, #ffffff 50%, #ffffff 75%, #dcdcdc 75%, #dcdcdc 100%)',
4
+ backgroundSize: '3px 3px',
5
+ display: 'flex',
6
+ justifyContent: 'center',
7
+ alignItems: 'center',
8
+ padding: '30px',
9
+ color: '#aaa',
10
+ };
11
+ export const HiddenRendering = () => React.createElement("div", { style: styles }, "The component is hidden");
@@ -0,0 +1,77 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { mediaApi } from '@sitecore-content-sdk/core/media';
13
+ import PropTypes from 'prop-types';
14
+ import React from 'react';
15
+ import { addClassName } from '../utils';
16
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
17
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
18
+ import { DefaultEmptyFieldEditingComponentImage } from './DefaultEmptyFieldEditingComponents';
19
+ import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
20
+ const getImageAttrs = (_a, imageParams, mediaUrlPrefix) => {
21
+ var { src, srcSet } = _a, otherAttrs = __rest(_a, ["src", "srcSet"]);
22
+ if (!src) {
23
+ return null;
24
+ }
25
+ addClassName(otherAttrs);
26
+ const newAttrs = Object.assign({}, otherAttrs);
27
+ // update image URL for jss handler and image rendering params
28
+ const resolvedSrc = mediaApi.updateImageUrl(src, imageParams, mediaUrlPrefix);
29
+ if (srcSet) {
30
+ // replace with HTML-formatted srcset, including updated image URLs
31
+ newAttrs.srcSet = mediaApi.getSrcSet(resolvedSrc, srcSet, imageParams, mediaUrlPrefix);
32
+ }
33
+ // always output original src as fallback for older browsers
34
+ newAttrs.src = resolvedSrc;
35
+ return newAttrs;
36
+ };
37
+ export const Image = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
38
+ var { editable = true, imageParams, field, mediaUrlPrefix } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix"]);
39
+ const dynamicMedia = field;
40
+ if (isFieldValueEmpty(dynamicMedia)) {
41
+ return null;
42
+ }
43
+ // some wise-guy/gal is passing in a 'raw' image object value
44
+ const img = dynamicMedia.src
45
+ ? field
46
+ : dynamicMedia.value;
47
+ if (!img) {
48
+ return null;
49
+ }
50
+ // prevent metadata from being passed to the img tag
51
+ if (img.metadata) {
52
+ delete img.metadata;
53
+ }
54
+ const attrs = getImageAttrs(Object.assign(Object.assign({}, img), otherProps), imageParams, mediaUrlPrefix);
55
+ if (attrs) {
56
+ return React.createElement("img", Object.assign({}, attrs));
57
+ }
58
+ return null; // we can't handle the truth
59
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentImage }));
60
+ Image.propTypes = {
61
+ field: PropTypes.oneOfType([
62
+ PropTypes.shape({
63
+ src: PropTypes.string,
64
+ }),
65
+ PropTypes.shape({
66
+ value: PropTypes.object,
67
+ }),
68
+ ]),
69
+ editable: PropTypes.bool,
70
+ mediaUrlPrefix: PropTypes.instanceOf(RegExp),
71
+ imageParams: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]).isRequired),
72
+ emptyFieldEditingComponent: PropTypes.oneOfType([
73
+ PropTypes.object,
74
+ PropTypes.func,
75
+ ]),
76
+ };
77
+ Image.displayName = 'Image';
@@ -0,0 +1,67 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React, { forwardRef } from 'react';
13
+ import PropTypes from 'prop-types';
14
+ import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
15
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
16
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
17
+ import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
18
+ export const Link = withFieldMetadata(withEmptyFieldEditingComponent(
19
+ // eslint-disable-next-line react/display-name
20
+ forwardRef((_a, ref) => {
21
+ var { field, editable = true, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
22
+ const children = otherProps.children;
23
+ const dynamicField = field;
24
+ if (isFieldValueEmpty(dynamicField)) {
25
+ return null;
26
+ }
27
+ // handle link directly on field for forgetful devs
28
+ const link = dynamicField.href
29
+ ? field
30
+ : dynamicField.value;
31
+ if (!link) {
32
+ return null;
33
+ }
34
+ const anchor = link.linktype !== 'anchor' && link.anchor ? `#${link.anchor}` : '';
35
+ const querystring = link.querystring ? `?${link.querystring}` : '';
36
+ const anchorAttrs = {
37
+ href: `${link.href}${querystring}${anchor}`,
38
+ className: link.class,
39
+ title: link.title,
40
+ target: link.target,
41
+ };
42
+ if (anchorAttrs.target === '_blank' && !anchorAttrs.rel) {
43
+ // information disclosure attack prevention keeps target blank site from getting ref to window.opener
44
+ anchorAttrs.rel = 'noopener noreferrer';
45
+ }
46
+ const linkText = showLinkTextWithChildrenPresent || !children ? link.text || link.href : null;
47
+ const element = React.createElement('a', Object.assign(Object.assign(Object.assign({}, anchorAttrs), otherProps), { key: 'link', ref }), linkText, children);
48
+ return React.createElement(React.Fragment, null, element);
49
+ }), { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, isForwardRef: true }), true);
50
+ export const LinkPropTypes = {
51
+ field: PropTypes.oneOfType([
52
+ PropTypes.shape({
53
+ href: PropTypes.oneOfType([PropTypes.string.isRequired, PropTypes.oneOf([null]).isRequired]),
54
+ }),
55
+ PropTypes.shape({
56
+ value: PropTypes.object,
57
+ }),
58
+ ]).isRequired,
59
+ editable: PropTypes.bool,
60
+ showLinkTextWithChildrenPresent: PropTypes.bool,
61
+ emptyFieldEditingComponent: PropTypes.oneOfType([
62
+ PropTypes.object,
63
+ PropTypes.func,
64
+ ]),
65
+ };
66
+ Link.propTypes = LinkPropTypes;
67
+ Link.displayName = 'Link';
@@ -0,0 +1,27 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ export const MissingComponent = (props) => {
4
+ const componentName = props.rendering && props.rendering.componentName
5
+ ? props.rendering.componentName
6
+ : 'Unnamed Component';
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.';
12
+ return (React.createElement("div", { style: {
13
+ background: 'darkorange',
14
+ outline: '5px solid orange',
15
+ padding: '10px',
16
+ color: 'white',
17
+ maxWidth: '500px',
18
+ } },
19
+ React.createElement("h2", null, componentName),
20
+ React.createElement("p", null, errorMessage)));
21
+ };
22
+ MissingComponent.propTypes = {
23
+ rendering: PropTypes.shape({
24
+ componentName: PropTypes.string,
25
+ }),
26
+ };
27
+ MissingComponent.displayName = 'MissingComponent';
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { PlaceholderCommon } from './PlaceholderCommon';
3
+ import { withComponentFactory } from '../enhancers/withComponentFactory';
4
+ import { PagesEditor } from '@sitecore-content-sdk/core/editing';
5
+ import { withSitecoreContext } from '../enhancers/withSitecoreContext';
6
+ class PlaceholderComponent extends PlaceholderCommon {
7
+ constructor(props) {
8
+ super(props);
9
+ this.isEmpty = false;
10
+ }
11
+ componentDidMount() {
12
+ if (this.isEmpty && PagesEditor.isActive()) {
13
+ PagesEditor.resetChromes();
14
+ }
15
+ }
16
+ /**
17
+ * Renders the placeholder when it is empty. The required CSS styles are applied to the placeholder in edit mode.
18
+ * @param {React.ReactNode | React.ReactElement[]} node react node
19
+ * @returns react node
20
+ */
21
+ renderEmptyPlaceholder(node) {
22
+ return React.createElement("div", { className: "sc-jss-empty-placeholder" }, node);
23
+ }
24
+ render() {
25
+ var _a, _b;
26
+ const childProps = Object.assign({}, this.props);
27
+ delete childProps.componentFactory;
28
+ if (this.state.error) {
29
+ if (childProps.errorComponent) {
30
+ return React.createElement(childProps.errorComponent, { error: this.state.error });
31
+ }
32
+ return (React.createElement("div", { className: "sc-jss-placeholder-error" },
33
+ "A rendering error occurred: ",
34
+ this.state.error.message,
35
+ "."));
36
+ }
37
+ const renderingData = childProps.rendering;
38
+ const placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name, (_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageEditing);
39
+ this.isEmpty = !placeholderData.length;
40
+ const components = this.getComponentsForRenderingData(placeholderData);
41
+ if (this.isEmpty) {
42
+ const rendered = this.props.renderEmpty ? this.props.renderEmpty(components) : components;
43
+ return ((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.pageEditing)
44
+ ? this.renderEmptyPlaceholder(rendered)
45
+ : rendered;
46
+ }
47
+ else if (this.props.render) {
48
+ return this.props.render(components, placeholderData, childProps);
49
+ }
50
+ else if (this.props.renderEach) {
51
+ const renderEach = this.props.renderEach;
52
+ return components.map((component, index) => {
53
+ if (component && component.props && component.props.type === 'text/sitecore') {
54
+ return component;
55
+ }
56
+ return renderEach(component, index);
57
+ });
58
+ }
59
+ else {
60
+ return components;
61
+ }
62
+ }
63
+ }
64
+ PlaceholderComponent.propTypes = PlaceholderCommon.propTypes;
65
+ const PlaceholderWithComponentFactory = withComponentFactory(PlaceholderComponent);
66
+ export const Placeholder = withSitecoreContext()(PlaceholderWithComponentFactory);