@sitecore-jss/sitecore-jss-react 22.1.0-canary.9 → 22.1.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.
Files changed (61) hide show
  1. package/LICENSE.txt +202 -202
  2. package/README.md +10 -10
  3. package/dist/cjs/components/Date.js +12 -4
  4. package/dist/cjs/components/DefaultEmptyFieldEditingComponents.js +22 -0
  5. package/dist/cjs/components/EditFrame.js +2 -2
  6. package/dist/cjs/components/EditingScripts.js +27 -0
  7. package/dist/cjs/components/ErrorBoundary.js +22 -7
  8. package/dist/cjs/components/FieldMetadata.js +33 -0
  9. package/dist/cjs/components/File.js +2 -1
  10. package/dist/cjs/components/HiddenRendering.js +7 -4
  11. package/dist/cjs/components/Image.js +15 -14
  12. package/dist/cjs/components/Link.js +13 -6
  13. package/dist/cjs/components/Placeholder.js +9 -6
  14. package/dist/cjs/components/PlaceholderCommon.js +69 -21
  15. package/dist/cjs/components/PlaceholderMetadata.js +67 -0
  16. package/dist/cjs/components/RichText.js +14 -3
  17. package/dist/cjs/components/Text.js +12 -4
  18. package/dist/cjs/enhancers/withEmptyFieldEditingComponent.js +56 -0
  19. package/dist/cjs/enhancers/withFieldMetadata.js +60 -0
  20. package/dist/cjs/enhancers/withPlaceholder.js +4 -3
  21. package/dist/cjs/index.js +17 -6
  22. package/dist/esm/components/Date.js +12 -3
  23. package/dist/esm/components/DefaultEmptyFieldEditingComponents.js +14 -0
  24. package/dist/esm/components/EditFrame.js +1 -1
  25. package/dist/esm/components/EditingScripts.js +20 -0
  26. package/dist/esm/components/ErrorBoundary.js +22 -7
  27. package/dist/esm/components/FieldMetadata.js +26 -0
  28. package/dist/esm/components/File.js +2 -1
  29. package/dist/esm/components/HiddenRendering.js +6 -3
  30. package/dist/esm/components/Image.js +15 -13
  31. package/dist/esm/components/Link.js +13 -6
  32. package/dist/esm/components/Placeholder.js +7 -4
  33. package/dist/esm/components/PlaceholderCommon.js +67 -21
  34. package/dist/esm/components/PlaceholderMetadata.js +60 -0
  35. package/dist/esm/components/RichText.js +14 -3
  36. package/dist/esm/components/Text.js +12 -3
  37. package/dist/esm/enhancers/withEmptyFieldEditingComponent.js +29 -0
  38. package/dist/esm/enhancers/withFieldMetadata.js +33 -0
  39. package/dist/esm/enhancers/withPlaceholder.js +4 -3
  40. package/dist/esm/index.js +6 -2
  41. package/package.json +5 -5
  42. package/types/components/Date.d.ts +4 -8
  43. package/types/components/DefaultEmptyFieldEditingComponents.d.ts +4 -0
  44. package/types/components/EditFrame.d.ts +1 -1
  45. package/types/components/EditingScripts.d.ts +5 -0
  46. package/types/components/ErrorBoundary.d.ts +4 -3
  47. package/types/components/FieldMetadata.d.ts +23 -0
  48. package/types/components/HiddenRendering.d.ts +0 -1
  49. package/types/components/Image.d.ts +4 -8
  50. package/types/components/Link.d.ts +7 -10
  51. package/types/components/Placeholder.d.ts +1 -4
  52. package/types/components/PlaceholderCommon.d.ts +22 -4
  53. package/types/components/PlaceholderMetadata.d.ts +30 -0
  54. package/types/components/RichText.d.ts +8 -8
  55. package/types/components/Text.d.ts +6 -10
  56. package/types/components/sharedTypes.d.ts +26 -1
  57. package/types/enhancers/withEmptyFieldEditingComponent.d.ts +28 -0
  58. package/types/enhancers/withFieldMetadata.d.ts +17 -0
  59. package/types/enhancers/withPlaceholder.d.ts +2 -4
  60. package/types/enhancers/withSitecoreContext.d.ts +4 -6
  61. package/types/index.d.ts +9 -4
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.withFieldMetadata = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const FieldMetadata_1 = require("../components/FieldMetadata");
29
+ /**
30
+ * Wraps the field component with metadata markup intended to be used for chromes hydration in Pages
31
+ * @param {ComponentType<FieldComponentProps>} FieldComponent the field component
32
+ * @param {boolean} isForwardRef set to 'true' if forward reference is needed
33
+ */
34
+ function withFieldMetadata(FieldComponent, isForwardRef = false) {
35
+ if (isForwardRef) {
36
+ // eslint-disable-next-line react/display-name
37
+ return (0, react_1.forwardRef)((props, ref) => {
38
+ var _a;
39
+ const { editable = true } = props;
40
+ const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
41
+ if (!metadata || !editable) {
42
+ return react_1.default.createElement(FieldComponent, Object.assign({}, props, { ref: ref }));
43
+ }
44
+ return (react_1.default.createElement(FieldMetadata_1.FieldMetadata, { metadata: metadata },
45
+ react_1.default.createElement(FieldComponent, Object.assign({}, props, { ref: ref }))));
46
+ });
47
+ }
48
+ // eslint-disable-next-line react/display-name
49
+ return (props) => {
50
+ var _a;
51
+ const { editable = true } = props;
52
+ const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
53
+ if (!metadata || !editable) {
54
+ return react_1.default.createElement(FieldComponent, Object.assign({}, props));
55
+ }
56
+ return (react_1.default.createElement(FieldMetadata_1.FieldMetadata, { metadata: metadata },
57
+ react_1.default.createElement(FieldComponent, Object.assign({}, props))));
58
+ };
59
+ }
60
+ exports.withFieldMetadata = withFieldMetadata;
@@ -7,6 +7,7 @@ exports.withPlaceholder = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const PlaceholderCommon_1 = require("../components/PlaceholderCommon");
9
9
  const withComponentFactory_1 = require("./withComponentFactory");
10
+ const withSitecoreContext_1 = require("./withSitecoreContext");
10
11
  /**
11
12
  * @param {WithPlaceholderSpec} placeholders
12
13
  * @param {WithPlaceholderOptions} [options]
@@ -41,13 +42,13 @@ function withPlaceholder(placeholders, options) {
41
42
  definitelyArrayPlacholders.forEach((placeholder) => {
42
43
  let placeholderData;
43
44
  if (typeof placeholder !== 'string' && placeholder.placeholder && placeholder.prop) {
44
- placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder.placeholder);
45
+ placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder.placeholder, childProps.sitecoreContext.editMode);
45
46
  if (placeholderData) {
46
47
  childProps[placeholder.prop] = this.getComponentsForRenderingData(placeholderData);
47
48
  }
48
49
  }
49
50
  else {
50
- placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder);
51
+ placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder, childProps.sitecoreContext.editMode);
51
52
  if (placeholderData) {
52
53
  childProps[placeholder] = this.getComponentsForRenderingData(placeholderData);
53
54
  }
@@ -57,7 +58,7 @@ function withPlaceholder(placeholders, options) {
57
58
  }
58
59
  }
59
60
  WithPlaceholder.propTypes = PlaceholderCommon_1.PlaceholderCommon.propTypes;
60
- return (0, withComponentFactory_1.withComponentFactory)(WithPlaceholder);
61
+ return (0, withSitecoreContext_1.withSitecoreContext)()((0, withComponentFactory_1.withComponentFactory)(WithPlaceholder));
61
62
  };
62
63
  }
63
64
  exports.withPlaceholder = withPlaceholder;
package/dist/cjs/index.js CHANGED
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ComponentBuilder = exports.EditFrame = exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.LinkPropTypes = exports.Link = exports.BYOCWrapper = exports.fetchBYOCComponentServerProps = exports.BYOCComponent = exports.FEaaSWrapper = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.DateField = exports.Text = exports.RichTextPropTypes = exports.RichText = exports.getEEMarkup = exports.Image = exports.Placeholder = exports.mediaApi = exports.GraphQLRequestClient = exports.DefaultRetryStrategy = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.getComponentLibraryStylesheetLinks = exports.getContentStylesheetLink = exports.DefaultEditFrameButtons = exports.DefaultEditFrameButton = exports.resetEditorChromes = exports.isEditorActive = exports.ClientError = exports.enableDebug = exports.constants = void 0;
3
+ exports.EditingScripts = exports.withEmptyFieldEditingComponent = exports.withFieldMetadata = exports.ComponentBuilder = exports.EditFrame = exports.withDatasourceCheck = exports.withPlaceholder = exports.withEditorChromes = exports.useSitecoreContext = exports.withSitecoreContext = exports.SitecoreContextReactContext = exports.SitecoreContext = exports.VisitorIdentification = exports.File = exports.LinkPropTypes = exports.Link = exports.BYOCWrapper = exports.fetchBYOCComponentServerProps = exports.BYOCComponent = exports.FEaaSWrapper = exports.fetchFEaaSComponentServerProps = exports.FEaaSComponent = exports.DateField = exports.Text = exports.RichTextPropTypes = exports.RichText = exports.getEEMarkup = exports.Image = exports.Placeholder = exports.mediaApi = exports.GraphQLRequestClient = exports.DefaultRetryStrategy = exports.RestDictionaryService = exports.GraphQLDictionaryService = exports.trackingApi = exports.EditMode = exports.getFieldValue = exports.getChildPlaceholder = exports.RestLayoutService = exports.GraphQLLayoutService = exports.LayoutServicePageState = exports.getComponentLibraryStylesheetLinks = exports.getContentStylesheetLink = exports.DefaultEditFrameButtons = exports.DefaultEditFrameButton = exports.resetEditorChromes = exports.isEditorActive = exports.ClientError = exports.enableDebug = exports.constants = void 0;
4
+ exports.DefaultEmptyFieldEditingComponentImage = exports.DefaultEmptyFieldEditingComponentText = void 0;
4
5
  var sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
5
6
  Object.defineProperty(exports, "constants", { enumerable: true, get: function () { return sitecore_jss_1.constants; } });
6
7
  Object.defineProperty(exports, "enableDebug", { enumerable: true, get: function () { return sitecore_jss_1.enableDebug; } });
7
8
  Object.defineProperty(exports, "ClientError", { enumerable: true, get: function () { return sitecore_jss_1.ClientError; } });
8
- var utils_1 = require("@sitecore-jss/sitecore-jss/utils");
9
- Object.defineProperty(exports, "isEditorActive", { enumerable: true, get: function () { return utils_1.isEditorActive; } });
10
- Object.defineProperty(exports, "resetEditorChromes", { enumerable: true, get: function () { return utils_1.resetEditorChromes; } });
11
- Object.defineProperty(exports, "DefaultEditFrameButton", { enumerable: true, get: function () { return utils_1.DefaultEditFrameButton; } });
12
- Object.defineProperty(exports, "DefaultEditFrameButtons", { enumerable: true, get: function () { return utils_1.DefaultEditFrameButtons; } });
9
+ var editing_1 = require("@sitecore-jss/sitecore-jss/editing");
10
+ Object.defineProperty(exports, "isEditorActive", { enumerable: true, get: function () { return editing_1.isEditorActive; } });
11
+ Object.defineProperty(exports, "resetEditorChromes", { enumerable: true, get: function () { return editing_1.resetEditorChromes; } });
12
+ Object.defineProperty(exports, "DefaultEditFrameButton", { enumerable: true, get: function () { return editing_1.DefaultEditFrameButton; } });
13
+ Object.defineProperty(exports, "DefaultEditFrameButtons", { enumerable: true, get: function () { return editing_1.DefaultEditFrameButtons; } });
13
14
  var layout_1 = require("@sitecore-jss/sitecore-jss/layout");
14
15
  Object.defineProperty(exports, "getContentStylesheetLink", { enumerable: true, get: function () { return layout_1.getContentStylesheetLink; } });
15
16
  Object.defineProperty(exports, "getComponentLibraryStylesheetLinks", { enumerable: true, get: function () { return layout_1.getComponentLibraryStylesheetLinks; } });
@@ -18,6 +19,7 @@ Object.defineProperty(exports, "GraphQLLayoutService", { enumerable: true, get:
18
19
  Object.defineProperty(exports, "RestLayoutService", { enumerable: true, get: function () { return layout_1.RestLayoutService; } });
19
20
  Object.defineProperty(exports, "getChildPlaceholder", { enumerable: true, get: function () { return layout_1.getChildPlaceholder; } });
20
21
  Object.defineProperty(exports, "getFieldValue", { enumerable: true, get: function () { return layout_1.getFieldValue; } });
22
+ Object.defineProperty(exports, "EditMode", { enumerable: true, get: function () { return layout_1.EditMode; } });
21
23
  var tracking_1 = require("@sitecore-jss/sitecore-jss/tracking");
22
24
  Object.defineProperty(exports, "trackingApi", { enumerable: true, get: function () { return tracking_1.trackingApi; } });
23
25
  var i18n_1 = require("@sitecore-jss/sitecore-jss/i18n");
@@ -73,3 +75,12 @@ var EditFrame_1 = require("./components/EditFrame");
73
75
  Object.defineProperty(exports, "EditFrame", { enumerable: true, get: function () { return EditFrame_1.EditFrame; } });
74
76
  var ComponentBuilder_1 = require("./ComponentBuilder");
75
77
  Object.defineProperty(exports, "ComponentBuilder", { enumerable: true, get: function () { return ComponentBuilder_1.ComponentBuilder; } });
78
+ var withFieldMetadata_1 = require("./enhancers/withFieldMetadata");
79
+ Object.defineProperty(exports, "withFieldMetadata", { enumerable: true, get: function () { return withFieldMetadata_1.withFieldMetadata; } });
80
+ var withEmptyFieldEditingComponent_1 = require("./enhancers/withEmptyFieldEditingComponent");
81
+ Object.defineProperty(exports, "withEmptyFieldEditingComponent", { enumerable: true, get: function () { return withEmptyFieldEditingComponent_1.withEmptyFieldEditingComponent; } });
82
+ var EditingScripts_1 = require("./components/EditingScripts");
83
+ Object.defineProperty(exports, "EditingScripts", { enumerable: true, get: function () { return EditingScripts_1.EditingScripts; } });
84
+ var DefaultEmptyFieldEditingComponents_1 = require("./components/DefaultEmptyFieldEditingComponents");
85
+ Object.defineProperty(exports, "DefaultEmptyFieldEditingComponentText", { enumerable: true, get: function () { return DefaultEmptyFieldEditingComponents_1.DefaultEmptyFieldEditingComponentText; } });
86
+ Object.defineProperty(exports, "DefaultEmptyFieldEditingComponentImage", { enumerable: true, get: function () { return DefaultEmptyFieldEditingComponents_1.DefaultEmptyFieldEditingComponentImage; } });
@@ -11,9 +11,13 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import React from 'react';
13
13
  import PropTypes from 'prop-types';
14
- export const DateField = (_a) => {
14
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
15
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
16
+ import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
17
+ import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
18
+ export const DateField = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
15
19
  var { field, tag, editable = true, render } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "render"]);
16
- if (!field || (!field.editable && !field.value)) {
20
+ if (!field || (!field.editable && isFieldValueEmpty(field))) {
17
21
  return null;
18
22
  }
19
23
  let children;
@@ -35,14 +39,19 @@ export const DateField = (_a) => {
35
39
  else {
36
40
  return React.createElement(React.Fragment, null, children);
37
41
  }
38
- };
42
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText }));
39
43
  DateField.propTypes = {
40
44
  field: PropTypes.shape({
41
45
  value: PropTypes.string,
42
46
  editable: PropTypes.string,
47
+ metadata: PropTypes.objectOf(PropTypes.any),
43
48
  }).isRequired,
44
49
  tag: PropTypes.string,
45
50
  editable: PropTypes.bool,
46
51
  render: PropTypes.func,
52
+ emptyFieldEditingComponent: PropTypes.oneOfType([
53
+ PropTypes.object,
54
+ PropTypes.func,
55
+ ]),
47
56
  };
48
57
  DateField.displayName = 'Date';
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ export const DefaultEmptyFieldEditingComponentText = () => {
3
+ return React.createElement("span", null, "[No text in field]");
4
+ };
5
+ export const DefaultEmptyFieldEditingComponentImage = () => {
6
+ const inlineStyles = {
7
+ minWidth: '48px',
8
+ minHeight: '48px',
9
+ maxWidth: '400px',
10
+ maxHeight: '400px',
11
+ cursor: 'pointer',
12
+ };
13
+ return (React.createElement("img", { alt: "", src: 'data:image/svg+xml,%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 240 240" style="enable-background:new 0 0 240 240;" xml:space="preserve"%3E%3Cstyle type="text/css"%3E .st0%7Bfill:none;%7D .st1%7Bfill:%23969696;%7D .st2%7Bfill:%23FFFFFF;%7D .st3%7Bfill:%23FFFFFF;stroke:%23FFFFFF;stroke-width:0.75;stroke-miterlimit:10;%7D%0A%3C/style%3E%3Cg%3E%3Crect class="st0" width="240" height="240"/%3E%3Cg%3E%3Cg%3E%3Crect x="20" y="20" class="st1" width="200" height="200"/%3E%3C/g%3E%3Cg%3E%3Ccircle class="st2" cx="174" cy="67" r="14"/%3E%3Cpath class="st2" d="M174,54c7.17,0,13,5.83,13,13s-5.83,13-13,13s-13-5.83-13-13S166.83,54,174,54 M174,52 c-8.28,0-15,6.72-15,15s6.72,15,15,15s15-6.72,15-15S182.28,52,174,52L174,52z"/%3E%3C/g%3E%3Cpolyline class="st3" points="29.5,179.25 81.32,122.25 95.41,137.75 137.23,91.75 209.5,179.75 "/%3E%3C/g%3E%3C/g%3E%3C/svg%3E', className: "scEmptyImage", style: inlineStyles }));
14
+ };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSitecoreContext } from '../enhancers/withSitecoreContext';
3
- import { mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/utils';
3
+ import { mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/editing';
4
4
  export const EditFrame = ({ children, dataSource, buttons, title, tooltip, cssClass, parameters, }) => {
5
5
  var _a;
6
6
  const { sitecoreContext } = useSitecoreContext();
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { EditMode, LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
3
+ import { useSitecoreContext } from '../enhancers/withSitecoreContext';
4
+ /**
5
+ * Renders client scripts and data for editing/preview mode in Pages.
6
+ * This script is only rendered when EditMode is Metadata, otherwise it renders nothing.
7
+ */
8
+ export const EditingScripts = () => {
9
+ const { sitecoreContext: { pageState, editMode, clientData, clientScripts }, } = useSitecoreContext();
10
+ // Don't render anything if not in editing/preview mode
11
+ if (pageState === LayoutServicePageState.Normal)
12
+ return React.createElement(React.Fragment, null);
13
+ if (editMode === EditMode.Metadata) {
14
+ return (React.createElement(React.Fragment, null, clientScripts === null || clientScripts === void 0 ? void 0 :
15
+ clientScripts.map((src, index) => (React.createElement("script", { src: src, key: index }))),
16
+ clientData &&
17
+ Object.keys(clientData).map((id) => (React.createElement("script", { key: id, id: id, type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(clientData[id]) } })))));
18
+ }
19
+ return React.createElement(React.Fragment, null);
20
+ };
@@ -1,9 +1,10 @@
1
1
  import React, { Suspense } from 'react';
2
+ import { LayoutServicePageState } from '@sitecore-jss/sitecore-jss/layout';
2
3
  import { withSitecoreContext } from '../enhancers/withSitecoreContext';
3
4
  class ErrorBoundary extends React.Component {
4
5
  constructor(props) {
5
6
  super(props);
6
- this.defaultErrorMessage = 'There was a problem loading this section.'; // eslint-disable-line
7
+ this.defaultErrorMessage = 'There was a problem loading this section.';
7
8
  this.defaultLoadingMessage = 'Loading component...';
8
9
  this.state = { error: null };
9
10
  }
@@ -11,27 +12,37 @@ class ErrorBoundary extends React.Component {
11
12
  return { error: error };
12
13
  }
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
+ }
14
19
  console.error({ error, errorInfo });
15
20
  }
16
21
  isInDevMode() {
17
22
  return process.env.NODE_ENV === 'development';
18
23
  }
19
- render() {
24
+ showErrorDetails() {
20
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;
21
32
  if (this.state.error) {
22
- if (this.props.customErrorComponent) {
23
- return React.createElement(this.props.customErrorComponent, { error: this.state.error });
33
+ if (this.props.errorComponent) {
34
+ return React.createElement(this.props.errorComponent, { error: this.state.error });
24
35
  }
25
36
  else {
26
- if (this.isInDevMode() || ((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageEditing)) {
37
+ if (this.showErrorDetails()) {
27
38
  return (React.createElement("div", null,
28
39
  React.createElement("div", { className: "sc-jss-placeholder-error" },
29
40
  "A rendering error occurred in component",
30
41
  ' ',
31
- React.createElement("em", null, (_b = this.props.rendering) === null || _b === void 0 ? void 0 : _b.componentName),
42
+ React.createElement("em", null, (_a = this.props.rendering) === null || _a === void 0 ? void 0 : _a.componentName),
32
43
  React.createElement("br", null),
33
44
  "Error: ",
34
- React.createElement("em", null, this.state.error.message))));
45
+ React.createElement("em", null, this.state.error.message || JSON.stringify(this.state.error)))));
35
46
  }
36
47
  else {
37
48
  return (React.createElement("div", null,
@@ -39,6 +50,10 @@ class ErrorBoundary extends React.Component {
39
50
  }
40
51
  }
41
52
  }
53
+ // do not apply suspense on already dynamic components
54
+ if (this.props.isDynamic) {
55
+ return this.props.children;
56
+ }
42
57
  return (React.createElement(Suspense, { fallback: React.createElement("h4", null, this.props.componentLoadingMessage || this.defaultLoadingMessage) }, this.props.children));
43
58
  }
44
59
  }
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ /**
4
+ * The component which renders field metadata markup
5
+ * @param {FieldMetadataProps} props the props of the component
6
+ * @returns metadata markup wrapped around children
7
+ */
8
+ export const FieldMetadata = (props) => {
9
+ const data = JSON.stringify(props.metadata);
10
+ const attributes = {
11
+ type: 'text/sitecore',
12
+ chrometype: 'field',
13
+ className: 'scpm',
14
+ };
15
+ const codeOpenAttributes = Object.assign(Object.assign({}, attributes), { kind: 'open' });
16
+ const codeCloseAttributes = Object.assign(Object.assign({}, attributes), { kind: 'close' });
17
+ return (React.createElement(React.Fragment, null,
18
+ React.createElement("code", Object.assign({}, codeOpenAttributes), data),
19
+ props.children,
20
+ React.createElement("code", Object.assign({}, codeCloseAttributes))));
21
+ };
22
+ FieldMetadata.displayName = 'FieldMetadata';
23
+ FieldMetadata.propTypes = {
24
+ metadata: PropTypes.object.isRequired,
25
+ children: PropTypes.node.isRequired,
26
+ };
@@ -9,6 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
+ import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
12
13
  import PropTypes from 'prop-types';
13
14
  import React from 'react';
14
15
  export const File = (_a) => {
@@ -17,7 +18,7 @@ export const File = (_a) => {
17
18
  */
18
19
  var { field, children } = _a, otherProps = __rest(_a, ["field", "children"]);
19
20
  const dynamicField = field;
20
- if (!field || (!dynamicField.value && !dynamicField.src)) {
21
+ if (!field || isFieldValueEmpty(dynamicField)) {
21
22
  return null;
22
23
  }
23
24
  // handle link directly on field for forgetful devs
@@ -1,8 +1,11 @@
1
1
  import React from 'react';
2
2
  const styles = {
3
- height: '100px',
4
3
  backgroundImage: 'linear-gradient(45deg, #ffffff 25%, #dcdcdc 25%, #dcdcdc 50%, #ffffff 50%, #ffffff 75%, #dcdcdc 75%, #dcdcdc 100%)',
5
4
  backgroundSize: '3px 3px',
5
+ display: 'flex',
6
+ justifyContent: 'center',
7
+ alignItems: 'center',
8
+ padding: '30px',
9
+ color: '#aaa',
6
10
  };
7
- export const HiddenRendering = () => React.createElement("div", { style: styles });
8
- export const HIDDEN_RENDERING_NAME = 'Hidden Rendering';
11
+ export const HiddenRendering = () => React.createElement("div", { style: styles }, "The component is hidden");
@@ -14,6 +14,10 @@ import PropTypes from 'prop-types';
14
14
  import React from 'react';
15
15
  import { addClassName, convertAttributesToReactProps } from '../utils';
16
16
  import { getAttributesString } from '../utils';
17
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
18
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
19
+ import { DefaultEmptyFieldEditingComponentImage } from './DefaultEmptyFieldEditingComponents';
20
+ import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
17
21
  const getEditableWrapper = (editableMarkup, ...otherProps) => (
18
22
  // create an inline wrapper and use dangerouslySetInnerHTML.
19
23
  // if we try to parse the EE value, the parser will strip invalid or disallowed attributes from html elements - and EE uses several
@@ -59,11 +63,10 @@ export const getEEMarkup = (imageField, imageParams, mediaUrlPrefix, otherProps)
59
63
  const editableMarkup = imageField.editable.replace(foundImg.imgTag, imgHtml);
60
64
  return getEditableWrapper(editableMarkup);
61
65
  };
62
- export const Image = (_a) => {
66
+ export const Image = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
63
67
  var { editable = true, imageParams, field, mediaUrlPrefix } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix"]);
64
68
  const dynamicMedia = field;
65
- if (!field ||
66
- (!dynamicMedia.editable && !dynamicMedia.value && !dynamicMedia.src)) {
69
+ if (!field || (!dynamicMedia.editable && isFieldValueEmpty(dynamicMedia))) {
67
70
  return null;
68
71
  }
69
72
  const imageField = dynamicMedia;
@@ -77,22 +80,17 @@ export const Image = (_a) => {
77
80
  if (!img) {
78
81
  return null;
79
82
  }
83
+ // prevent metadata from being passed to the img tag
84
+ if (img.metadata) {
85
+ delete img.metadata;
86
+ }
80
87
  const attrs = getImageAttrs(Object.assign(Object.assign({}, img), otherProps), imageParams, mediaUrlPrefix);
81
88
  if (attrs) {
82
89
  return React.createElement("img", Object.assign({}, attrs));
83
90
  }
84
91
  return null; // we can't handle the truth
85
- };
92
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentImage }));
86
93
  Image.propTypes = {
87
- media: PropTypes.oneOfType([
88
- PropTypes.shape({
89
- src: PropTypes.string,
90
- }),
91
- PropTypes.shape({
92
- value: PropTypes.object,
93
- editable: PropTypes.string,
94
- }),
95
- ]),
96
94
  field: PropTypes.oneOfType([
97
95
  PropTypes.shape({
98
96
  src: PropTypes.string,
@@ -105,5 +103,9 @@ Image.propTypes = {
105
103
  editable: PropTypes.bool,
106
104
  mediaUrlPrefix: PropTypes.instanceOf(RegExp),
107
105
  imageParams: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]).isRequired),
106
+ emptyFieldEditingComponent: PropTypes.oneOfType([
107
+ PropTypes.object,
108
+ PropTypes.func,
109
+ ]),
108
110
  };
109
111
  Image.displayName = 'Image';
@@ -11,14 +11,17 @@ 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
- export const Link = forwardRef((_a, ref) => {
14
+ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
15
+ import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
16
+ import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
17
+ import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
18
+ export const Link = withFieldMetadata(withEmptyFieldEditingComponent(
19
+ // eslint-disable-next-line react/display-name
20
+ forwardRef((_a, ref) => {
15
21
  var { field, editable = true, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
16
22
  const children = otherProps.children;
17
23
  const dynamicField = field;
18
- if (!field ||
19
- (!dynamicField.editableFirstPart &&
20
- !dynamicField.value &&
21
- !dynamicField.href)) {
24
+ if (!field || (!dynamicField.editableFirstPart && isFieldValueEmpty(dynamicField))) {
22
25
  return null;
23
26
  }
24
27
  const resultTags = [];
@@ -64,7 +67,7 @@ export const Link = forwardRef((_a, ref) => {
64
67
  const linkText = showLinkTextWithChildrenPresent || !children ? link.text || link.href : null;
65
68
  resultTags.push(React.createElement('a', Object.assign(Object.assign(Object.assign({}, anchorAttrs), otherProps), { key: 'link', ref }), linkText, children));
66
69
  return React.createElement(React.Fragment, null, resultTags);
67
- });
70
+ }), { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, isForwardRef: true }), true);
68
71
  export const LinkPropTypes = {
69
72
  field: PropTypes.oneOfType([
70
73
  PropTypes.shape({
@@ -78,6 +81,10 @@ export const LinkPropTypes = {
78
81
  ]).isRequired,
79
82
  editable: PropTypes.bool,
80
83
  showLinkTextWithChildrenPresent: PropTypes.bool,
84
+ emptyFieldEditingComponent: PropTypes.oneOfType([
85
+ PropTypes.object,
86
+ PropTypes.func,
87
+ ]),
81
88
  };
82
89
  Link.propTypes = LinkPropTypes;
83
90
  Link.displayName = 'Link';
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  import { PlaceholderCommon } from './PlaceholderCommon';
3
3
  import { withComponentFactory } from '../enhancers/withComponentFactory';
4
- import { HorizonEditor } from '@sitecore-jss/sitecore-jss/utils';
4
+ import { HorizonEditor } from '@sitecore-jss/sitecore-jss/editing';
5
+ import { withSitecoreContext } from '../enhancers/withSitecoreContext';
5
6
  /**
6
7
  * @param {HtmlElementRendering | ComponentRendering} rendering
7
8
  */
@@ -31,6 +32,7 @@ class PlaceholderComponent extends PlaceholderCommon {
31
32
  return React.createElement("div", { className: "sc-jss-empty-placeholder" }, node);
32
33
  }
33
34
  render() {
35
+ var _a;
34
36
  const childProps = Object.assign({}, this.props);
35
37
  delete childProps.componentFactory;
36
38
  if (this.state.error) {
@@ -43,9 +45,9 @@ class PlaceholderComponent extends PlaceholderCommon {
43
45
  "."));
44
46
  }
45
47
  const renderingData = childProps.rendering;
46
- const placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name);
47
- const components = this.getComponentsForRenderingData(placeholderData);
48
+ const placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name, (_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.editMode);
48
49
  this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
50
+ const components = this.getComponentsForRenderingData(placeholderData);
49
51
  if (this.props.renderEmpty && this.isEmpty) {
50
52
  const rendered = this.props.renderEmpty(components);
51
53
  return components.length ? this.renderEmptyPlaceholder(rendered) : rendered;
@@ -71,4 +73,5 @@ class PlaceholderComponent extends PlaceholderCommon {
71
73
  }
72
74
  }
73
75
  PlaceholderComponent.propTypes = PlaceholderCommon.propTypes;
74
- export const Placeholder = withComponentFactory(PlaceholderComponent);
76
+ const PlaceholderWithComponentFactory = withComponentFactory(PlaceholderComponent);
77
+ export const Placeholder = withSitecoreContext()(PlaceholderWithComponentFactory);