@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,184 @@
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 from 'react';
13
+ import PropTypes from 'prop-types';
14
+ import { MissingComponent } from './MissingComponent';
15
+ import { isDynamicPlaceholder, getDynamicPlaceholderPattern, } from '@sitecore-content-sdk/core/layout';
16
+ import { constants } from '@sitecore-content-sdk/core';
17
+ import { HiddenRendering } from './HiddenRendering';
18
+ import { FEaaSComponent, FEAAS_COMPONENT_RENDERING_NAME } from './FEaaSComponent';
19
+ import { FEaaSWrapper, FEAAS_WRAPPER_RENDERING_NAME } from './FEaaSWrapper';
20
+ import { BYOCComponent, BYOC_COMPONENT_RENDERING_NAME } from './BYOCComponent';
21
+ import { BYOCWrapper, BYOC_WRAPPER_RENDERING_NAME } from './BYOCWrapper';
22
+ import { PlaceholderMetadata } from './PlaceholderMetadata';
23
+ import ErrorBoundary from './ErrorBoundary';
24
+ export class PlaceholderCommon extends React.Component {
25
+ constructor(props) {
26
+ super(props);
27
+ this.state = {};
28
+ }
29
+ static getPlaceholderDataFromRenderingData(rendering, name, isEditing) {
30
+ let result;
31
+ let phName = name.slice();
32
+ /**
33
+ * Process (SXA) dynamic placeholders
34
+ * Find and replace the matching dynamic placeholder e.g 'nameOfContainer-{*}' with the requested e.g. 'nameOfContainer-1'.
35
+ * For Metadata EditMode, we need to keep the raw placeholder name in place.
36
+ */
37
+ if (rendering === null || rendering === void 0 ? void 0 : rendering.placeholders) {
38
+ Object.keys(rendering.placeholders).forEach((placeholder) => {
39
+ const patternPlaceholder = isDynamicPlaceholder(placeholder)
40
+ ? getDynamicPlaceholderPattern(placeholder)
41
+ : null;
42
+ if (patternPlaceholder && patternPlaceholder.test(phName)) {
43
+ if (isEditing) {
44
+ phName = placeholder;
45
+ }
46
+ else {
47
+ rendering.placeholders[phName] = rendering.placeholders[placeholder];
48
+ delete rendering.placeholders[placeholder];
49
+ }
50
+ }
51
+ });
52
+ }
53
+ if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
54
+ result = rendering.placeholders[phName];
55
+ }
56
+ else {
57
+ result = null;
58
+ }
59
+ if (!result) {
60
+ console.warn(`Placeholder '${phName}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
61
+ return [];
62
+ }
63
+ return result;
64
+ }
65
+ componentDidCatch(error) {
66
+ this.setState({ error });
67
+ }
68
+ getSXAParams(rendering) {
69
+ if (!rendering.params)
70
+ return {};
71
+ return (rendering.params.FieldNames && {
72
+ styles: `${rendering.params.GridParameters || ''} ${rendering.params.Styles || ''}`,
73
+ });
74
+ }
75
+ getComponentsForRenderingData(placeholderData) {
76
+ var _a;
77
+ const _b = this.props, { name, fields: placeholderFields, params: placeholderParams, missingComponentComponent, hiddenRenderingComponent } = _b, placeholderProps = __rest(_b, ["name", "fields", "params", "missingComponentComponent", "hiddenRenderingComponent"]);
78
+ const transformedComponents = placeholderData
79
+ .map((rendering, index) => {
80
+ var _a, _b;
81
+ const key = rendering.uid
82
+ ? rendering.uid
83
+ : `component-${index}`;
84
+ const commonProps = { key };
85
+ let isEmpty = false;
86
+ const componentRendering = rendering;
87
+ let component;
88
+ if (componentRendering.componentName === constants.HIDDEN_RENDERING_NAME) {
89
+ component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering;
90
+ isEmpty = true;
91
+ }
92
+ else if (!componentRendering.componentName) {
93
+ component = () => React.createElement(React.Fragment, null);
94
+ isEmpty = true;
95
+ }
96
+ else {
97
+ component = this.getComponentForRendering(componentRendering);
98
+ }
99
+ // Fallback/defaults for Sitecore Component renderings (in case not defined in component factory)
100
+ if (!component) {
101
+ if (componentRendering.componentName === FEAAS_COMPONENT_RENDERING_NAME) {
102
+ component = FEaaSComponent;
103
+ }
104
+ else if (componentRendering.componentName === FEAAS_WRAPPER_RENDERING_NAME) {
105
+ component = FEaaSWrapper;
106
+ }
107
+ else if (componentRendering.componentName === BYOC_COMPONENT_RENDERING_NAME) {
108
+ component = BYOCComponent;
109
+ }
110
+ else if (componentRendering.componentName === BYOC_WRAPPER_RENDERING_NAME) {
111
+ component = BYOCWrapper;
112
+ }
113
+ }
114
+ if (!component) {
115
+ 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.`);
116
+ component = missingComponentComponent !== null && missingComponentComponent !== void 0 ? missingComponentComponent : MissingComponent;
117
+ isEmpty = true;
118
+ }
119
+ const finalProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), placeholderProps), ((placeholderFields || componentRendering.fields) && {
120
+ fields: Object.assign(Object.assign({}, placeholderFields), componentRendering.fields),
121
+ })), ((placeholderParams || componentRendering.params) && {
122
+ params: Object.assign(Object.assign(Object.assign({}, placeholderParams), componentRendering.params), this.getSXAParams(componentRendering)),
123
+ })), { rendering: componentRendering });
124
+ let rendered = React.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
125
+ if (!isEmpty) {
126
+ // assign type based on passed element - type='text/sitecore' should be ignored when renderEach Placeholder prop function is being used
127
+ const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
128
+ // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOC and tries to access its children props
129
+ // that's why we need to expose element's props here
130
+ rendered = (React.createElement(ErrorBoundary, Object.assign({ key: rendered.type + '-' + index, errorComponent: this.props.errorComponent, componentLoadingMessage: this.props.componentLoadingMessage, type: type, isDynamic: ((_a = component.render) === null || _a === void 0 ? void 0 : _a.preload) ? true : false }, rendered.props), rendered));
131
+ }
132
+ // if in edit mode then emit shallow chromes for hydration in Pages
133
+ if ((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.pageEditing) {
134
+ return (React.createElement(PlaceholderMetadata, { key: key, rendering: rendering }, rendered));
135
+ }
136
+ return rendered;
137
+ })
138
+ .filter((element) => element); // remove nulls
139
+ if ((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageEditing) {
140
+ return [
141
+ React.createElement(PlaceholderMetadata, { key: this.props.rendering.uid, placeholderName: name, rendering: this.props.rendering }, transformedComponents),
142
+ ];
143
+ }
144
+ return transformedComponents;
145
+ }
146
+ getComponentForRendering(renderingDefinition) {
147
+ var _a;
148
+ const componentFactory = this.props.componentFactory;
149
+ if (!componentFactory || typeof componentFactory !== 'function') {
150
+ console.warn(`No componentFactory was available to service request for component ${renderingDefinition}`);
151
+ return null;
152
+ }
153
+ // Render SXA Rendering Variant
154
+ if ((_a = renderingDefinition.params) === null || _a === void 0 ? void 0 : _a.FieldNames) {
155
+ return componentFactory(renderingDefinition.componentName, renderingDefinition.params.FieldNames);
156
+ }
157
+ return componentFactory(renderingDefinition.componentName);
158
+ }
159
+ }
160
+ PlaceholderCommon.propTypes = {
161
+ rendering: PropTypes.oneOfType([
162
+ PropTypes.object,
163
+ PropTypes.object,
164
+ ]).isRequired,
165
+ fields: PropTypes.objectOf(PropTypes.oneOfType([
166
+ PropTypes.object,
167
+ PropTypes.object,
168
+ ]).isRequired),
169
+ params: PropTypes.objectOf(PropTypes.string.isRequired),
170
+ missingComponentComponent: PropTypes.oneOfType([
171
+ PropTypes.object,
172
+ PropTypes.func,
173
+ ]),
174
+ hiddenRenderingComponent: PropTypes.oneOfType([
175
+ PropTypes.object,
176
+ PropTypes.func,
177
+ ]),
178
+ errorComponent: PropTypes.oneOfType([
179
+ PropTypes.object,
180
+ PropTypes.func,
181
+ ]),
182
+ modifyComponentProps: PropTypes.func,
183
+ sitecoreContext: PropTypes.object,
184
+ };
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import { getDynamicPlaceholderPattern, isDynamicPlaceholder, } from '@sitecore-content-sdk/core/layout';
3
+ import { MetadataKind, DEFAULT_PLACEHOLDER_UID } from '@sitecore-content-sdk/core/editing';
4
+ /**
5
+ * A React component to generate metadata blocks for a placeholder or rendering.
6
+ * It utilizes dynamic attributes based on whether the component acts as a placeholder
7
+ * or as a rendering to properly render the surrounding code blocks.
8
+ * @param {object} props The properties passed to the component.
9
+ * @param {ComponentRendering} props.rendering The rendering data.
10
+ * @param {string} [props.placeholderName] The name of the placeholder.
11
+ * @param {JSX.Element} props.children The child components or elements to be wrapped by the metadata code blocks.
12
+ * @returns {JSX.Element} A React fragment containing open and close code blocks surrounding the children elements.
13
+ */
14
+ export const PlaceholderMetadata = ({ rendering, placeholderName, children, }) => {
15
+ const getCodeBlockAttributes = (kind, id, placeholderName) => {
16
+ const chrometype = placeholderName ? 'placeholder' : 'rendering';
17
+ const attributes = {
18
+ type: 'text/sitecore',
19
+ chrometype: chrometype,
20
+ className: 'scpm',
21
+ kind: kind,
22
+ };
23
+ if (kind === MetadataKind.Open) {
24
+ if (chrometype === 'placeholder' && placeholderName) {
25
+ let phId = '';
26
+ for (const placeholder of Object.keys(rendering.placeholders)) {
27
+ if (placeholderName === placeholder) {
28
+ phId = id
29
+ ? `${placeholderName}_${id}`
30
+ : `${placeholderName}_${DEFAULT_PLACEHOLDER_UID}`;
31
+ break;
32
+ }
33
+ // Check if the placeholder is a dynamic placeholder
34
+ if (isDynamicPlaceholder(placeholder)) {
35
+ const pattern = getDynamicPlaceholderPattern(placeholder);
36
+ // Check if the placeholder matches the dynamic placeholder pattern
37
+ if (pattern.test(placeholderName)) {
38
+ phId = id ? `${placeholder}_${id}` : `${placeholder}_${DEFAULT_PLACEHOLDER_UID}`;
39
+ break;
40
+ }
41
+ }
42
+ }
43
+ attributes.id = phId;
44
+ }
45
+ else {
46
+ attributes.id = id;
47
+ }
48
+ }
49
+ return attributes;
50
+ };
51
+ const renderComponent = (uid, placeholderName) => (React.createElement(React.Fragment, null,
52
+ React.createElement("code", Object.assign({}, getCodeBlockAttributes(MetadataKind.Open, uid, placeholderName))),
53
+ children,
54
+ React.createElement("code", Object.assign({}, getCodeBlockAttributes(MetadataKind.Close, uid, placeholderName)))));
55
+ return React.createElement(React.Fragment, null, renderComponent(rendering.uid, placeholderName));
56
+ };
@@ -0,0 +1,43 @@
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 { withFieldMetadata } from '../enhancers/withFieldMetadata';
15
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
16
+ import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
17
+ import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
18
+ export const RichText = withFieldMetadata(withEmptyFieldEditingComponent(
19
+ // eslint-disable-next-line react/display-name
20
+ forwardRef((_a, ref) => {
21
+ var { field, tag = 'div', editable = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable"]);
22
+ if (isFieldValueEmpty(field)) {
23
+ return null;
24
+ }
25
+ const htmlProps = Object.assign({ dangerouslySetInnerHTML: {
26
+ __html: field.value,
27
+ }, ref }, otherProps);
28
+ return React.createElement(tag || 'div', htmlProps);
29
+ }), { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, isForwardRef: true }), true);
30
+ export const RichTextPropTypes = {
31
+ field: PropTypes.shape({
32
+ value: PropTypes.string,
33
+ metadata: PropTypes.objectOf(PropTypes.any),
34
+ }),
35
+ tag: PropTypes.string,
36
+ editable: PropTypes.bool,
37
+ emptyFieldEditingComponent: PropTypes.oneOfType([
38
+ PropTypes.object,
39
+ PropTypes.func,
40
+ ]),
41
+ };
42
+ RichText.propTypes = RichTextPropTypes;
43
+ RichText.displayName = 'RichText';
@@ -0,0 +1,60 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import fastDeepEqual from 'fast-deep-equal/es6/react';
5
+ export const SitecoreContextReactContext = React.createContext({});
6
+ export const ComponentFactoryReactContext = React.createContext({});
7
+ export class SitecoreContext extends React.Component {
8
+ constructor(props) {
9
+ super(props);
10
+ /**
11
+ * Update context state. Value can be @type {LayoutServiceData} which will be automatically transformed
12
+ * or you can provide exact @type {SitecoreContextValue}
13
+ * @param {SitecoreContextValue | LayoutServiceData} value New context value
14
+ */
15
+ this.setContext = (value) => {
16
+ this.setState({
17
+ context: value.sitecore
18
+ ? this.constructContext(value)
19
+ : Object.assign({}, value),
20
+ });
21
+ };
22
+ const context = this.constructContext(props.layoutData);
23
+ this.state = {
24
+ context,
25
+ setContext: this.setContext,
26
+ };
27
+ }
28
+ constructContext(layoutData) {
29
+ var _a;
30
+ if (!layoutData) {
31
+ return {
32
+ pageEditing: false,
33
+ };
34
+ }
35
+ return Object.assign({ route: layoutData.sitecore.route, itemId: (_a = layoutData.sitecore.route) === null || _a === void 0 ? void 0 : _a.itemId }, layoutData.sitecore.context);
36
+ }
37
+ componentDidUpdate(prevProps) {
38
+ // In case if somebody will manage SitecoreContext state by passing fresh `layoutData` prop
39
+ // instead of using `updateSitecoreContext`
40
+ if (!fastDeepEqual(prevProps.layoutData, this.props.layoutData)) {
41
+ this.setContext(this.props.layoutData);
42
+ return;
43
+ }
44
+ }
45
+ render() {
46
+ return (React.createElement(ComponentFactoryReactContext.Provider, { value: this.props.componentFactory },
47
+ React.createElement(SitecoreContextReactContext.Provider, { value: this.state }, this.props.children)));
48
+ }
49
+ }
50
+ SitecoreContext.propTypes = {
51
+ children: PropTypes.any.isRequired,
52
+ componentFactory: PropTypes.func,
53
+ layoutData: PropTypes.shape({
54
+ sitecore: PropTypes.shape({
55
+ context: PropTypes.any,
56
+ route: PropTypes.any,
57
+ }),
58
+ }),
59
+ };
60
+ SitecoreContext.displayName = 'SitecoreContext';
@@ -0,0 +1,72 @@
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 from 'react';
13
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
14
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
15
+ import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
16
+ import PropTypes from 'prop-types';
17
+ import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
18
+ export const Text = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
19
+ var { field, tag, editable = true, encode = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "encode"]);
20
+ if (isFieldValueEmpty(field)) {
21
+ return null;
22
+ }
23
+ // can't use editable value if we want to output unencoded
24
+ if (!encode) {
25
+ // eslint-disable-next-line no-param-reassign
26
+ editable = false;
27
+ }
28
+ let output = field.value === undefined ? '' : field.value;
29
+ // when string value isn't formatted, we should format line breaks
30
+ const splitted = String(output).split('\n');
31
+ if (splitted.length) {
32
+ const formatted = [];
33
+ splitted.forEach((str, i) => {
34
+ const isLast = i === splitted.length - 1;
35
+ formatted.push(str);
36
+ if (!isLast) {
37
+ formatted.push(React.createElement("br", { key: i }));
38
+ }
39
+ });
40
+ output = formatted;
41
+ }
42
+ let children = null;
43
+ const htmlProps = Object.assign({}, otherProps);
44
+ if (!encode) {
45
+ htmlProps.dangerouslySetInnerHTML = {
46
+ __html: output,
47
+ };
48
+ }
49
+ else {
50
+ children = output;
51
+ }
52
+ if (tag || !encode) {
53
+ return React.createElement(tag || 'span', htmlProps, children);
54
+ }
55
+ else {
56
+ return React.createElement(React.Fragment, null, children);
57
+ }
58
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText }));
59
+ Text.propTypes = {
60
+ field: PropTypes.shape({
61
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
62
+ metadata: PropTypes.objectOf(PropTypes.any),
63
+ }),
64
+ tag: PropTypes.string,
65
+ editable: PropTypes.bool,
66
+ encode: PropTypes.bool,
67
+ emptyFieldEditingComponent: PropTypes.oneOfType([
68
+ PropTypes.object,
69
+ PropTypes.func,
70
+ ]),
71
+ };
72
+ Text.displayName = 'Text';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { ComponentFactoryReactContext } from '../components/SitecoreContext';
3
+ import { useContext } from 'react';
4
+ /**
5
+ * @param {React.ComponentClass<T> | React.FC<T>} Component
6
+ */
7
+ export function withComponentFactory(Component) {
8
+ /**
9
+ * @param {T} props - props to pass to the wrapped component
10
+ * @returns {JSX.Element} - the rendered component
11
+ */
12
+ function WithComponentFactory(props) {
13
+ const context = useContext(ComponentFactoryReactContext);
14
+ return React.createElement(Component, Object.assign({}, props, { componentFactory: props.componentFactory || context }));
15
+ }
16
+ WithComponentFactory.displayName = `withComponentFactory(${Component.displayName ||
17
+ Component.name ||
18
+ 'Anonymous'})`;
19
+ return WithComponentFactory;
20
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { useSitecoreContext } from './withSitecoreContext';
3
+ export const DefaultEditingError = () => (React.createElement("div", { className: "sc-jss-editing-error", role: "alert" }, "Datasource is required. Please choose a content item for this component."));
4
+ /**
5
+ * Checks whether a Sitecore datasource is present and renders appropriately depending on page mode (normal vs editing).
6
+ * @param {WithDatasourceCheckOptions} [options]
7
+ * @returns
8
+ * The wrapped component, if a datasource is present.
9
+ * A null component (in normal mode) or an error component (in editing mode), if a datasource is not present.
10
+ */
11
+ export function withDatasourceCheck(options) {
12
+ return function withDatasourceCheckHoc(Component) {
13
+ return function WithDatasourceCheck(props) {
14
+ var _a, _b;
15
+ const { sitecoreContext } = useSitecoreContext();
16
+ const EditingError = (_a = options === null || options === void 0 ? void 0 : options.editingErrorComponent) !== null && _a !== void 0 ? _a : DefaultEditingError;
17
+ return ((_b = props.rendering) === null || _b === void 0 ? void 0 : _b.dataSource) ? (React.createElement(Component, Object.assign({}, props))) : sitecoreContext.pageEditing ? (React.createElement(EditingError, null)) : null;
18
+ };
19
+ };
20
+ }
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { resetEditorChromes } from '..';
3
+ export const withEditorChromes = (WrappedComponent) => {
4
+ class Enhancer extends React.Component {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.displayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
8
+ }
9
+ componentDidUpdate() {
10
+ resetEditorChromes();
11
+ }
12
+ render() {
13
+ return React.createElement(WrappedComponent, Object.assign({}, this.props));
14
+ }
15
+ }
16
+ return Enhancer;
17
+ };
@@ -0,0 +1,29 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { isFieldValueEmpty, } from '@sitecore-content-sdk/core/layout';
3
+ /**
4
+ * Returns the passed field component or default component in case field value is empty and edit mode is 'metadata'
5
+ * @param {ComponentType<FieldComponentProps>} FieldComponent the field component
6
+ * @param {WithEmptyFieldEditingComponentProps} options the options of the HOC;
7
+ */
8
+ export function withEmptyFieldEditingComponent(FieldComponent, options) {
9
+ const getEmptyFieldEditingComponent = (props) => {
10
+ var _a;
11
+ const { editable = true } = props;
12
+ if (((_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata) && editable && isFieldValueEmpty(props.field)) {
13
+ return props.emptyFieldEditingComponent || options.defaultEmptyFieldEditingComponent;
14
+ }
15
+ return null;
16
+ };
17
+ if (options.isForwardRef) {
18
+ // eslint-disable-next-line react/display-name
19
+ return forwardRef((props, ref) => {
20
+ const EmptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
21
+ return (React.createElement(React.Fragment, null, (EmptyFieldEditingComponent && React.createElement(EmptyFieldEditingComponent, null)) || (React.createElement(FieldComponent, Object.assign({}, props, { ref: ref })))));
22
+ });
23
+ }
24
+ // eslint-disable-next-line react/display-name
25
+ return (props) => {
26
+ const EmptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
27
+ return (React.createElement(React.Fragment, null, (EmptyFieldEditingComponent && React.createElement(EmptyFieldEditingComponent, null)) || (React.createElement(FieldComponent, Object.assign({}, props)))));
28
+ };
29
+ }
@@ -0,0 +1,33 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { FieldMetadata } from '../components/FieldMetadata';
3
+ /**
4
+ * Wraps the field component with metadata markup intended to be used for chromes hydration in Pages
5
+ * @param {ComponentType<FieldComponentProps>} FieldComponent the field component
6
+ * @param {boolean} isForwardRef set to 'true' if forward reference is needed
7
+ */
8
+ export function withFieldMetadata(FieldComponent, isForwardRef = false) {
9
+ if (isForwardRef) {
10
+ // eslint-disable-next-line react/display-name
11
+ return forwardRef((props, ref) => {
12
+ var _a;
13
+ const { editable = true } = props;
14
+ const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
15
+ if (!metadata || !editable) {
16
+ return React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }));
17
+ }
18
+ return (React.createElement(FieldMetadata, { metadata: metadata },
19
+ React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }))));
20
+ });
21
+ }
22
+ // eslint-disable-next-line react/display-name
23
+ return (props) => {
24
+ var _a;
25
+ const { editable = true } = props;
26
+ const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
27
+ if (!metadata || !editable) {
28
+ return React.createElement(FieldComponent, Object.assign({}, props));
29
+ }
30
+ return (React.createElement(FieldMetadata, { metadata: metadata },
31
+ React.createElement(FieldComponent, Object.assign({}, props))));
32
+ };
33
+ }
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { PlaceholderCommon } from '../components/PlaceholderCommon';
3
+ import { withComponentFactory } from './withComponentFactory';
4
+ import { withSitecoreContext } from './withSitecoreContext';
5
+ /**
6
+ * @param {WithPlaceholderSpec} placeholders
7
+ * @param {WithPlaceholderOptions} [options]
8
+ */
9
+ export function withPlaceholder(placeholders, options) {
10
+ return (WrappedComponent) => {
11
+ class WithPlaceholder extends PlaceholderCommon {
12
+ constructor(props) {
13
+ super(props);
14
+ }
15
+ render() {
16
+ let childProps = Object.assign({}, this.props);
17
+ delete childProps.componentFactory;
18
+ if (options && options.propsTransformer) {
19
+ childProps = options.propsTransformer(childProps);
20
+ }
21
+ if (this.state.error) {
22
+ if (childProps.errorComponent) {
23
+ return React.createElement(childProps.errorComponent, { error: this.state.error });
24
+ }
25
+ return (React.createElement("div", { className: "sc-jss-placeholder-error" },
26
+ "A rendering error occurred: ",
27
+ this.state.error.message,
28
+ "."));
29
+ }
30
+ const renderingData = options && options.resolvePlaceholderDataFromProps
31
+ ? options.resolvePlaceholderDataFromProps(childProps)
32
+ : childProps.rendering;
33
+ const definitelyArrayPlacholders = !Array.isArray(placeholders)
34
+ ? [placeholders]
35
+ : placeholders;
36
+ definitelyArrayPlacholders.forEach((placeholder) => {
37
+ let placeholderData;
38
+ if (typeof placeholder !== 'string' && placeholder.placeholder && placeholder.prop) {
39
+ placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder.placeholder, childProps.sitecoreContext.pageEditing);
40
+ if (placeholderData) {
41
+ childProps[placeholder.prop] = this.getComponentsForRenderingData(placeholderData);
42
+ }
43
+ }
44
+ else {
45
+ placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder, childProps.sitecoreContext.pageEditing);
46
+ if (placeholderData) {
47
+ childProps[placeholder] = this.getComponentsForRenderingData(placeholderData);
48
+ }
49
+ }
50
+ });
51
+ return React.createElement(WrappedComponent, Object.assign({}, childProps));
52
+ }
53
+ }
54
+ WithPlaceholder.propTypes = PlaceholderCommon.propTypes;
55
+ return withSitecoreContext()(withComponentFactory(WithPlaceholder));
56
+ };
57
+ }
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { SitecoreContextReactContext } from '../components/SitecoreContext';
3
+ /**
4
+ * @param {WithSitecoreContextOptions} [options]
5
+ */
6
+ export function withSitecoreContext(options) {
7
+ return function withSitecoreContextHoc(Component) {
8
+ return function WithSitecoreContext(props) {
9
+ return (React.createElement(SitecoreContextReactContext.Consumer, null, (context) => (React.createElement(Component, Object.assign({}, props, { sitecoreContext: context.context, updateSitecoreContext: options && options.updatable && context.setContext })))));
10
+ };
11
+ };
12
+ }
13
+ /**
14
+ * This hook grants acсess to the current Sitecore page context
15
+ * by default JSS includes the following properties in this context:
16
+ * - pageEditing - Provided by Layout Service, a boolean indicating whether the route is being accessed via the Sitecore Editor.
17
+ * - pageState - Like pageEditing, but a string: normal, preview or edit.
18
+ * - site - Provided by Layout Service, an object containing the name of the current Sitecore site context.
19
+ * @see https://jss.sitecore.com/docs/techniques/extending-layout-service/layoutservice-extending-context
20
+ * @param {WithSitecoreContextOptions} [options] hook options
21
+ * @example
22
+ * const EditMode = () => {
23
+ * const { sitecoreContext } = useSitecoreContext();
24
+ * return <span>Edit Mode is {sitecoreContext.pageEditing ? 'active' : 'inactive'}</span>
25
+ * }
26
+ * @example
27
+ * const EditMode = () => {
28
+ * const { sitecoreContext, updateSitecoreContext } = useSitecoreContext({ updatable: true });
29
+ * const onClick = () => updateSitecoreContext({ pageEditing: true });
30
+ * return <span onClick={onClick}>Edit Mode is {sitecoreContext.pageEditing ? 'active' : 'inactive'}</span>
31
+ * }
32
+ * @returns {object} { sitecoreContext, updateSitecoreContext }
33
+ */
34
+ export function useSitecoreContext(options) {
35
+ const reactContext = React.useContext(SitecoreContextReactContext);
36
+ const updatable = options === null || options === void 0 ? void 0 : options.updatable;
37
+ return {
38
+ sitecoreContext: reactContext.context,
39
+ updateSitecoreContext: updatable ? reactContext.setContext : undefined,
40
+ };
41
+ }