@sitecore-jss/sitecore-jss-react 22.1.0-canary.9 → 22.2.0-canary.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 (59) hide show
  1. package/dist/cjs/components/Date.js +12 -4
  2. package/dist/cjs/components/DefaultEmptyFieldEditingComponents.js +22 -0
  3. package/dist/cjs/components/EditFrame.js +2 -2
  4. package/dist/cjs/components/EditingScripts.js +27 -0
  5. package/dist/cjs/components/ErrorBoundary.js +22 -7
  6. package/dist/cjs/components/FieldMetadata.js +33 -0
  7. package/dist/cjs/components/File.js +2 -1
  8. package/dist/cjs/components/HiddenRendering.js +7 -4
  9. package/dist/cjs/components/Image.js +15 -14
  10. package/dist/cjs/components/Link.js +13 -6
  11. package/dist/cjs/components/Placeholder.js +9 -6
  12. package/dist/cjs/components/PlaceholderCommon.js +69 -21
  13. package/dist/cjs/components/PlaceholderMetadata.js +67 -0
  14. package/dist/cjs/components/RichText.js +14 -3
  15. package/dist/cjs/components/Text.js +12 -4
  16. package/dist/cjs/enhancers/withEmptyFieldEditingComponent.js +56 -0
  17. package/dist/cjs/enhancers/withFieldMetadata.js +60 -0
  18. package/dist/cjs/enhancers/withPlaceholder.js +4 -3
  19. package/dist/cjs/index.js +17 -6
  20. package/dist/esm/components/Date.js +12 -3
  21. package/dist/esm/components/DefaultEmptyFieldEditingComponents.js +14 -0
  22. package/dist/esm/components/EditFrame.js +1 -1
  23. package/dist/esm/components/EditingScripts.js +20 -0
  24. package/dist/esm/components/ErrorBoundary.js +22 -7
  25. package/dist/esm/components/FieldMetadata.js +26 -0
  26. package/dist/esm/components/File.js +2 -1
  27. package/dist/esm/components/HiddenRendering.js +6 -3
  28. package/dist/esm/components/Image.js +15 -13
  29. package/dist/esm/components/Link.js +13 -6
  30. package/dist/esm/components/Placeholder.js +7 -4
  31. package/dist/esm/components/PlaceholderCommon.js +67 -21
  32. package/dist/esm/components/PlaceholderMetadata.js +60 -0
  33. package/dist/esm/components/RichText.js +14 -3
  34. package/dist/esm/components/Text.js +12 -3
  35. package/dist/esm/enhancers/withEmptyFieldEditingComponent.js +29 -0
  36. package/dist/esm/enhancers/withFieldMetadata.js +33 -0
  37. package/dist/esm/enhancers/withPlaceholder.js +4 -3
  38. package/dist/esm/index.js +6 -2
  39. package/package.json +5 -5
  40. package/types/components/Date.d.ts +4 -8
  41. package/types/components/DefaultEmptyFieldEditingComponents.d.ts +4 -0
  42. package/types/components/EditFrame.d.ts +1 -1
  43. package/types/components/EditingScripts.d.ts +5 -0
  44. package/types/components/ErrorBoundary.d.ts +4 -3
  45. package/types/components/FieldMetadata.d.ts +23 -0
  46. package/types/components/HiddenRendering.d.ts +0 -1
  47. package/types/components/Image.d.ts +4 -8
  48. package/types/components/Link.d.ts +7 -10
  49. package/types/components/Placeholder.d.ts +1 -4
  50. package/types/components/PlaceholderCommon.d.ts +22 -4
  51. package/types/components/PlaceholderMetadata.d.ts +30 -0
  52. package/types/components/RichText.d.ts +8 -8
  53. package/types/components/Text.d.ts +6 -10
  54. package/types/components/sharedTypes.d.ts +26 -1
  55. package/types/enhancers/withEmptyFieldEditingComponent.d.ts +28 -0
  56. package/types/enhancers/withFieldMetadata.d.ts +17 -0
  57. package/types/enhancers/withPlaceholder.d.ts +2 -4
  58. package/types/enhancers/withSitecoreContext.d.ts +4 -6
  59. package/types/index.d.ts +9 -4
@@ -17,9 +17,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.DateField = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const prop_types_1 = __importDefault(require("prop-types"));
20
- const DateField = (_a) => {
20
+ const withFieldMetadata_1 = require("../enhancers/withFieldMetadata");
21
+ const withEmptyFieldEditingComponent_1 = require("../enhancers/withEmptyFieldEditingComponent");
22
+ const DefaultEmptyFieldEditingComponents_1 = require("./DefaultEmptyFieldEditingComponents");
23
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
24
+ exports.DateField = (0, withFieldMetadata_1.withFieldMetadata)((0, withEmptyFieldEditingComponent_1.withEmptyFieldEditingComponent)((_a) => {
21
25
  var { field, tag, editable = true, render } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "render"]);
22
- if (!field || (!field.editable && !field.value)) {
26
+ if (!field || (!field.editable && (0, layout_1.isFieldValueEmpty)(field))) {
23
27
  return null;
24
28
  }
25
29
  let children;
@@ -41,15 +45,19 @@ const DateField = (_a) => {
41
45
  else {
42
46
  return react_1.default.createElement(react_1.default.Fragment, null, children);
43
47
  }
44
- };
45
- exports.DateField = DateField;
48
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponents_1.DefaultEmptyFieldEditingComponentText }));
46
49
  exports.DateField.propTypes = {
47
50
  field: prop_types_1.default.shape({
48
51
  value: prop_types_1.default.string,
49
52
  editable: prop_types_1.default.string,
53
+ metadata: prop_types_1.default.objectOf(prop_types_1.default.any),
50
54
  }).isRequired,
51
55
  tag: prop_types_1.default.string,
52
56
  editable: prop_types_1.default.bool,
53
57
  render: prop_types_1.default.func,
58
+ emptyFieldEditingComponent: prop_types_1.default.oneOfType([
59
+ prop_types_1.default.object,
60
+ prop_types_1.default.func,
61
+ ]),
54
62
  };
55
63
  exports.DateField.displayName = 'Date';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DefaultEmptyFieldEditingComponentImage = exports.DefaultEmptyFieldEditingComponentText = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const DefaultEmptyFieldEditingComponentText = () => {
9
+ return react_1.default.createElement("span", null, "[No text in field]");
10
+ };
11
+ exports.DefaultEmptyFieldEditingComponentText = DefaultEmptyFieldEditingComponentText;
12
+ const DefaultEmptyFieldEditingComponentImage = () => {
13
+ const inlineStyles = {
14
+ minWidth: '48px',
15
+ minHeight: '48px',
16
+ maxWidth: '400px',
17
+ maxHeight: '400px',
18
+ cursor: 'pointer',
19
+ };
20
+ return (react_1.default.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 }));
21
+ };
22
+ exports.DefaultEmptyFieldEditingComponentImage = DefaultEmptyFieldEditingComponentImage;
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.EditFrame = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const withSitecoreContext_1 = require("../enhancers/withSitecoreContext");
9
- const utils_1 = require("@sitecore-jss/sitecore-jss/utils");
9
+ const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
10
10
  const EditFrame = ({ children, dataSource, buttons, title, tooltip, cssClass, parameters, }) => {
11
11
  var _a;
12
12
  const { sitecoreContext } = (0, withSitecoreContext_1.useSitecoreContext)();
@@ -30,7 +30,7 @@ const EditFrame = ({ children, dataSource, buttons, title, tooltip, cssClass, pa
30
30
  chromeData.contextItemUri = frameProps.sc_item;
31
31
  }
32
32
  chromeData.commands = buttons === null || buttons === void 0 ? void 0 : buttons.map((value) => {
33
- return (0, utils_1.mapButtonToCommand)(value, dataSource === null || dataSource === void 0 ? void 0 : dataSource.itemId, parameters);
33
+ return (0, editing_1.mapButtonToCommand)(value, dataSource === null || dataSource === void 0 ? void 0 : dataSource.itemId, parameters);
34
34
  });
35
35
  return (react_1.default.createElement("div", Object.assign({ className: "scLooseFrameZone" }, frameProps),
36
36
  react_1.default.createElement("span", { className: "scChromeData" }, JSON.stringify(chromeData)),
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EditingScripts = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
9
+ const withSitecoreContext_1 = require("../enhancers/withSitecoreContext");
10
+ /**
11
+ * Renders client scripts and data for editing/preview mode in Pages.
12
+ * This script is only rendered when EditMode is Metadata, otherwise it renders nothing.
13
+ */
14
+ const EditingScripts = () => {
15
+ const { sitecoreContext: { pageState, editMode, clientData, clientScripts }, } = (0, withSitecoreContext_1.useSitecoreContext)();
16
+ // Don't render anything if not in editing/preview mode
17
+ if (pageState === layout_1.LayoutServicePageState.Normal)
18
+ return react_1.default.createElement(react_1.default.Fragment, null);
19
+ if (editMode === layout_1.EditMode.Metadata) {
20
+ return (react_1.default.createElement(react_1.default.Fragment, null, clientScripts === null || clientScripts === void 0 ? void 0 :
21
+ clientScripts.map((src, index) => (react_1.default.createElement("script", { src: src, key: index }))),
22
+ clientData &&
23
+ Object.keys(clientData).map((id) => (react_1.default.createElement("script", { key: id, id: id, type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(clientData[id]) } })))));
24
+ }
25
+ return react_1.default.createElement(react_1.default.Fragment, null);
26
+ };
27
+ exports.EditingScripts = EditingScripts;
@@ -24,11 +24,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  const react_1 = __importStar(require("react"));
27
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
27
28
  const withSitecoreContext_1 = require("../enhancers/withSitecoreContext");
28
29
  class ErrorBoundary extends react_1.default.Component {
29
30
  constructor(props) {
30
31
  super(props);
31
- this.defaultErrorMessage = 'There was a problem loading this section.'; // eslint-disable-line
32
+ this.defaultErrorMessage = 'There was a problem loading this section.';
32
33
  this.defaultLoadingMessage = 'Loading component...';
33
34
  this.state = { error: null };
34
35
  }
@@ -36,27 +37,37 @@ class ErrorBoundary extends react_1.default.Component {
36
37
  return { error: error };
37
38
  }
38
39
  componentDidCatch(error, errorInfo) {
40
+ var _a, _b;
41
+ if (this.showErrorDetails()) {
42
+ 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}): `);
43
+ }
39
44
  console.error({ error, errorInfo });
40
45
  }
41
46
  isInDevMode() {
42
47
  return process.env.NODE_ENV === 'development';
43
48
  }
44
- render() {
49
+ showErrorDetails() {
45
50
  var _a, _b;
51
+ return (this.isInDevMode() ||
52
+ ((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageState) === layout_1.LayoutServicePageState.Edit ||
53
+ ((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.pageState) === layout_1.LayoutServicePageState.Preview);
54
+ }
55
+ render() {
56
+ var _a;
46
57
  if (this.state.error) {
47
- if (this.props.customErrorComponent) {
48
- return react_1.default.createElement(this.props.customErrorComponent, { error: this.state.error });
58
+ if (this.props.errorComponent) {
59
+ return react_1.default.createElement(this.props.errorComponent, { error: this.state.error });
49
60
  }
50
61
  else {
51
- if (this.isInDevMode() || ((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.pageEditing)) {
62
+ if (this.showErrorDetails()) {
52
63
  return (react_1.default.createElement("div", null,
53
64
  react_1.default.createElement("div", { className: "sc-jss-placeholder-error" },
54
65
  "A rendering error occurred in component",
55
66
  ' ',
56
- react_1.default.createElement("em", null, (_b = this.props.rendering) === null || _b === void 0 ? void 0 : _b.componentName),
67
+ react_1.default.createElement("em", null, (_a = this.props.rendering) === null || _a === void 0 ? void 0 : _a.componentName),
57
68
  react_1.default.createElement("br", null),
58
69
  "Error: ",
59
- react_1.default.createElement("em", null, this.state.error.message))));
70
+ react_1.default.createElement("em", null, this.state.error.message || JSON.stringify(this.state.error)))));
60
71
  }
61
72
  else {
62
73
  return (react_1.default.createElement("div", null,
@@ -64,6 +75,10 @@ class ErrorBoundary extends react_1.default.Component {
64
75
  }
65
76
  }
66
77
  }
78
+ // do not apply suspense on already dynamic components
79
+ if (this.props.isDynamic) {
80
+ return this.props.children;
81
+ }
67
82
  return (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("h4", null, this.props.componentLoadingMessage || this.defaultLoadingMessage) }, this.props.children));
68
83
  }
69
84
  }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FieldMetadata = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const prop_types_1 = __importDefault(require("prop-types"));
9
+ /**
10
+ * The component which renders field metadata markup
11
+ * @param {FieldMetadataProps} props the props of the component
12
+ * @returns metadata markup wrapped around children
13
+ */
14
+ const FieldMetadata = (props) => {
15
+ const data = JSON.stringify(props.metadata);
16
+ const attributes = {
17
+ type: 'text/sitecore',
18
+ chrometype: 'field',
19
+ className: 'scpm',
20
+ };
21
+ const codeOpenAttributes = Object.assign(Object.assign({}, attributes), { kind: 'open' });
22
+ const codeCloseAttributes = Object.assign(Object.assign({}, attributes), { kind: 'close' });
23
+ return (react_1.default.createElement(react_1.default.Fragment, null,
24
+ react_1.default.createElement("code", Object.assign({}, codeOpenAttributes), data),
25
+ props.children,
26
+ react_1.default.createElement("code", Object.assign({}, codeCloseAttributes))));
27
+ };
28
+ exports.FieldMetadata = FieldMetadata;
29
+ exports.FieldMetadata.displayName = 'FieldMetadata';
30
+ exports.FieldMetadata.propTypes = {
31
+ metadata: prop_types_1.default.object.isRequired,
32
+ children: prop_types_1.default.node.isRequired,
33
+ };
@@ -15,6 +15,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.File = void 0;
18
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
18
19
  const prop_types_1 = __importDefault(require("prop-types"));
19
20
  const react_1 = __importDefault(require("react"));
20
21
  const File = (_a) => {
@@ -23,7 +24,7 @@ const File = (_a) => {
23
24
  */
24
25
  var { field, children } = _a, otherProps = __rest(_a, ["field", "children"]);
25
26
  const dynamicField = field;
26
- if (!field || (!dynamicField.value && !dynamicField.src)) {
27
+ if (!field || (0, layout_1.isFieldValueEmpty)(dynamicField)) {
27
28
  return null;
28
29
  }
29
30
  // handle link directly on field for forgetful devs
@@ -3,13 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.HIDDEN_RENDERING_NAME = exports.HiddenRendering = void 0;
6
+ exports.HiddenRendering = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const styles = {
9
- height: '100px',
10
9
  backgroundImage: 'linear-gradient(45deg, #ffffff 25%, #dcdcdc 25%, #dcdcdc 50%, #ffffff 50%, #ffffff 75%, #dcdcdc 75%, #dcdcdc 100%)',
11
10
  backgroundSize: '3px 3px',
11
+ display: 'flex',
12
+ justifyContent: 'center',
13
+ alignItems: 'center',
14
+ padding: '30px',
15
+ color: '#aaa',
12
16
  };
13
- const HiddenRendering = () => react_1.default.createElement("div", { style: styles });
17
+ const HiddenRendering = () => react_1.default.createElement("div", { style: styles }, "The component is hidden");
14
18
  exports.HiddenRendering = HiddenRendering;
15
- exports.HIDDEN_RENDERING_NAME = 'Hidden Rendering';
@@ -20,6 +20,10 @@ const prop_types_1 = __importDefault(require("prop-types"));
20
20
  const react_1 = __importDefault(require("react"));
21
21
  const utils_1 = require("../utils");
22
22
  const utils_2 = require("../utils");
23
+ const withFieldMetadata_1 = require("../enhancers/withFieldMetadata");
24
+ const withEmptyFieldEditingComponent_1 = require("../enhancers/withEmptyFieldEditingComponent");
25
+ const DefaultEmptyFieldEditingComponents_1 = require("./DefaultEmptyFieldEditingComponents");
26
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
23
27
  const getEditableWrapper = (editableMarkup, ...otherProps) => (
24
28
  // create an inline wrapper and use dangerouslySetInnerHTML.
25
29
  // if we try to parse the EE value, the parser will strip invalid or disallowed attributes from html elements - and EE uses several
@@ -66,11 +70,10 @@ const getEEMarkup = (imageField, imageParams, mediaUrlPrefix, otherProps) => {
66
70
  return getEditableWrapper(editableMarkup);
67
71
  };
68
72
  exports.getEEMarkup = getEEMarkup;
69
- const Image = (_a) => {
73
+ exports.Image = (0, withFieldMetadata_1.withFieldMetadata)((0, withEmptyFieldEditingComponent_1.withEmptyFieldEditingComponent)((_a) => {
70
74
  var { editable = true, imageParams, field, mediaUrlPrefix } = _a, otherProps = __rest(_a, ["editable", "imageParams", "field", "mediaUrlPrefix"]);
71
75
  const dynamicMedia = field;
72
- if (!field ||
73
- (!dynamicMedia.editable && !dynamicMedia.value && !dynamicMedia.src)) {
76
+ if (!field || (!dynamicMedia.editable && (0, layout_1.isFieldValueEmpty)(dynamicMedia))) {
74
77
  return null;
75
78
  }
76
79
  const imageField = dynamicMedia;
@@ -84,23 +87,17 @@ const Image = (_a) => {
84
87
  if (!img) {
85
88
  return null;
86
89
  }
90
+ // prevent metadata from being passed to the img tag
91
+ if (img.metadata) {
92
+ delete img.metadata;
93
+ }
87
94
  const attrs = getImageAttrs(Object.assign(Object.assign({}, img), otherProps), imageParams, mediaUrlPrefix);
88
95
  if (attrs) {
89
96
  return react_1.default.createElement("img", Object.assign({}, attrs));
90
97
  }
91
98
  return null; // we can't handle the truth
92
- };
93
- exports.Image = Image;
99
+ }, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponents_1.DefaultEmptyFieldEditingComponentImage }));
94
100
  exports.Image.propTypes = {
95
- media: prop_types_1.default.oneOfType([
96
- prop_types_1.default.shape({
97
- src: prop_types_1.default.string,
98
- }),
99
- prop_types_1.default.shape({
100
- value: prop_types_1.default.object,
101
- editable: prop_types_1.default.string,
102
- }),
103
- ]),
104
101
  field: prop_types_1.default.oneOfType([
105
102
  prop_types_1.default.shape({
106
103
  src: prop_types_1.default.string,
@@ -113,5 +110,9 @@ exports.Image.propTypes = {
113
110
  editable: prop_types_1.default.bool,
114
111
  mediaUrlPrefix: prop_types_1.default.instanceOf(RegExp),
115
112
  imageParams: prop_types_1.default.objectOf(prop_types_1.default.oneOfType([prop_types_1.default.number.isRequired, prop_types_1.default.string.isRequired]).isRequired),
113
+ emptyFieldEditingComponent: prop_types_1.default.oneOfType([
114
+ prop_types_1.default.object,
115
+ prop_types_1.default.func,
116
+ ]),
116
117
  };
117
118
  exports.Image.displayName = 'Image';
@@ -40,14 +40,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.LinkPropTypes = exports.Link = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const prop_types_1 = __importDefault(require("prop-types"));
43
- exports.Link = (0, react_1.forwardRef)((_a, ref) => {
43
+ const withFieldMetadata_1 = require("../enhancers/withFieldMetadata");
44
+ const withEmptyFieldEditingComponent_1 = require("../enhancers/withEmptyFieldEditingComponent");
45
+ const DefaultEmptyFieldEditingComponents_1 = require("./DefaultEmptyFieldEditingComponents");
46
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
47
+ exports.Link = (0, withFieldMetadata_1.withFieldMetadata)((0, withEmptyFieldEditingComponent_1.withEmptyFieldEditingComponent)(
48
+ // eslint-disable-next-line react/display-name
49
+ (0, react_1.forwardRef)((_a, ref) => {
44
50
  var { field, editable = true, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
45
51
  const children = otherProps.children;
46
52
  const dynamicField = field;
47
- if (!field ||
48
- (!dynamicField.editableFirstPart &&
49
- !dynamicField.value &&
50
- !dynamicField.href)) {
53
+ if (!field || (!dynamicField.editableFirstPart && (0, layout_1.isFieldValueEmpty)(dynamicField))) {
51
54
  return null;
52
55
  }
53
56
  const resultTags = [];
@@ -93,7 +96,7 @@ exports.Link = (0, react_1.forwardRef)((_a, ref) => {
93
96
  const linkText = showLinkTextWithChildrenPresent || !children ? link.text || link.href : null;
94
97
  resultTags.push(react_1.default.createElement('a', Object.assign(Object.assign(Object.assign({}, anchorAttrs), otherProps), { key: 'link', ref }), linkText, children));
95
98
  return react_1.default.createElement(react_1.default.Fragment, null, resultTags);
96
- });
99
+ }), { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponents_1.DefaultEmptyFieldEditingComponentText, isForwardRef: true }), true);
97
100
  exports.LinkPropTypes = {
98
101
  field: prop_types_1.default.oneOfType([
99
102
  prop_types_1.default.shape({
@@ -107,6 +110,10 @@ exports.LinkPropTypes = {
107
110
  ]).isRequired,
108
111
  editable: prop_types_1.default.bool,
109
112
  showLinkTextWithChildrenPresent: prop_types_1.default.bool,
113
+ emptyFieldEditingComponent: prop_types_1.default.oneOfType([
114
+ prop_types_1.default.object,
115
+ prop_types_1.default.func,
116
+ ]),
110
117
  };
111
118
  exports.Link.propTypes = exports.LinkPropTypes;
112
119
  exports.Link.displayName = 'Link';
@@ -7,7 +7,8 @@ exports.Placeholder = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const PlaceholderCommon_1 = require("./PlaceholderCommon");
9
9
  const withComponentFactory_1 = require("../enhancers/withComponentFactory");
10
- const utils_1 = require("@sitecore-jss/sitecore-jss/utils");
10
+ const editing_1 = require("@sitecore-jss/sitecore-jss/editing");
11
+ const withSitecoreContext_1 = require("../enhancers/withSitecoreContext");
11
12
  /**
12
13
  * @param {HtmlElementRendering | ComponentRendering} rendering
13
14
  */
@@ -22,8 +23,8 @@ class PlaceholderComponent extends PlaceholderCommon_1.PlaceholderCommon {
22
23
  }
23
24
  componentDidMount() {
24
25
  super.componentDidMount();
25
- if (this.isEmpty && utils_1.HorizonEditor.isActive()) {
26
- utils_1.HorizonEditor.resetChromes();
26
+ if (this.isEmpty && editing_1.HorizonEditor.isActive()) {
27
+ editing_1.HorizonEditor.resetChromes();
27
28
  }
28
29
  }
29
30
  /**
@@ -37,6 +38,7 @@ class PlaceholderComponent extends PlaceholderCommon_1.PlaceholderCommon {
37
38
  return react_1.default.createElement("div", { className: "sc-jss-empty-placeholder" }, node);
38
39
  }
39
40
  render() {
41
+ var _a;
40
42
  const childProps = Object.assign({}, this.props);
41
43
  delete childProps.componentFactory;
42
44
  if (this.state.error) {
@@ -49,9 +51,9 @@ class PlaceholderComponent extends PlaceholderCommon_1.PlaceholderCommon {
49
51
  "."));
50
52
  }
51
53
  const renderingData = childProps.rendering;
52
- const placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name);
53
- const components = this.getComponentsForRenderingData(placeholderData);
54
+ const placeholderData = PlaceholderCommon_1.PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, this.props.name, (_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.editMode);
54
55
  this.isEmpty = placeholderData.every((rendering) => isRawRendering(rendering));
56
+ const components = this.getComponentsForRenderingData(placeholderData);
55
57
  if (this.props.renderEmpty && this.isEmpty) {
56
58
  const rendered = this.props.renderEmpty(components);
57
59
  return components.length ? this.renderEmptyPlaceholder(rendered) : rendered;
@@ -77,4 +79,5 @@ class PlaceholderComponent extends PlaceholderCommon_1.PlaceholderCommon {
77
79
  }
78
80
  }
79
81
  PlaceholderComponent.propTypes = PlaceholderCommon_1.PlaceholderCommon.propTypes;
80
- exports.Placeholder = (0, withComponentFactory_1.withComponentFactory)(PlaceholderComponent);
82
+ const PlaceholderWithComponentFactory = (0, withComponentFactory_1.withComponentFactory)(PlaceholderComponent);
83
+ exports.Placeholder = (0, withSitecoreContext_1.withSitecoreContext)()(PlaceholderWithComponentFactory);
@@ -14,17 +14,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.PlaceholderCommon = void 0;
17
+ exports.PlaceholderCommon = exports.isDynamicPlaceholder = exports.getDynamicPlaceholderPattern = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const prop_types_1 = __importDefault(require("prop-types"));
20
20
  const MissingComponent_1 = require("./MissingComponent");
21
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
22
+ const sitecore_jss_1 = require("@sitecore-jss/sitecore-jss");
21
23
  const utils_1 = require("../utils");
22
24
  const HiddenRendering_1 = require("./HiddenRendering");
23
25
  const FEaaSComponent_1 = require("./FEaaSComponent");
24
26
  const FEaaSWrapper_1 = require("./FEaaSWrapper");
25
27
  const BYOCComponent_1 = require("./BYOCComponent");
26
28
  const BYOCWrapper_1 = require("./BYOCWrapper");
29
+ const PlaceholderMetadata_1 = require("./PlaceholderMetadata");
27
30
  const ErrorBoundary_1 = __importDefault(require("./ErrorBoundary"));
31
+ /**
32
+ * Returns a regular expression pattern for a dynamic placeholder name.
33
+ * @param {string} placeholder Placeholder name with a dynamic segment (e.g. 'main-{*}')
34
+ * @returns Regular expression pattern for the dynamic segment
35
+ */
36
+ const getDynamicPlaceholderPattern = (placeholder) => {
37
+ return new RegExp(`^${placeholder.replace(/\{\*\}+/i, '\\d+')}$`);
38
+ };
39
+ exports.getDynamicPlaceholderPattern = getDynamicPlaceholderPattern;
40
+ /**
41
+ * Checks if the placeholder name is dynamic.
42
+ * @param {string} placeholder Placeholder name
43
+ * @returns True if the placeholder name is dynamic
44
+ */
45
+ const isDynamicPlaceholder = (placeholder) => placeholder.indexOf('{*}') !== -1;
46
+ exports.isDynamicPlaceholder = isDynamicPlaceholder;
28
47
  class PlaceholderCommon extends react_1.default.Component {
29
48
  constructor(props) {
30
49
  super(props);
@@ -34,29 +53,38 @@ class PlaceholderCommon extends react_1.default.Component {
34
53
  this.updateKeyAttributes = this.updateKeyAttributes.bind(this);
35
54
  this.createRawElement = this.createRawElement.bind(this);
36
55
  }
37
- static getPlaceholderDataFromRenderingData(rendering, name) {
56
+ static getPlaceholderDataFromRenderingData(rendering, name, editMode) {
38
57
  let result;
39
- /** [SXA] it needs for deleting dynamics placeholder when we set him number(props.name) of container.
40
- from backend side we get common name of placeholder is called 'nameOfContainer-{*}' where '{*}' marker for replacing **/
58
+ let phName = name.slice();
59
+ /**
60
+ * [Chromes Mode]: [SXA] it needs for deleting dynamics placeholder when we set him number(props.name) of container.
61
+ * from backend side we get common name of placeholder is called 'nameOfContainer-{*}' where '{*}' marker for replacing.
62
+ * [Metadata Mode]: We need to keep the raw placeholder name. e.g 'nameOfContainer-{*}' instead of 'nameOfContainer-1'
63
+ */
41
64
  if (rendering === null || rendering === void 0 ? void 0 : rendering.placeholders) {
42
65
  Object.keys(rendering.placeholders).forEach((placeholder) => {
43
- const patternPlaceholder = placeholder.indexOf('{*}') !== -1
44
- ? new RegExp(`^${placeholder.replace(/\{\*\}+/i, '\\d+')}$`)
66
+ const patternPlaceholder = (0, exports.isDynamicPlaceholder)(placeholder)
67
+ ? (0, exports.getDynamicPlaceholderPattern)(placeholder)
45
68
  : null;
46
- if (patternPlaceholder && patternPlaceholder.test(name)) {
47
- rendering.placeholders[name] = rendering.placeholders[placeholder];
48
- delete rendering.placeholders[placeholder];
69
+ if (patternPlaceholder && patternPlaceholder.test(phName)) {
70
+ if (editMode === layout_1.EditMode.Metadata) {
71
+ phName = placeholder;
72
+ }
73
+ else {
74
+ rendering.placeholders[phName] = rendering.placeholders[placeholder];
75
+ delete rendering.placeholders[placeholder];
76
+ }
49
77
  }
50
78
  });
51
79
  }
52
80
  if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
53
- result = rendering.placeholders[name];
81
+ result = rendering.placeholders[phName];
54
82
  }
55
83
  else {
56
84
  result = null;
57
85
  }
58
86
  if (!result) {
59
- console.warn(`Placeholder '${name}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
87
+ console.warn(`Placeholder '${phName}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
60
88
  return [];
61
89
  }
62
90
  return result;
@@ -78,13 +106,16 @@ class PlaceholderCommon extends react_1.default.Component {
78
106
  });
79
107
  }
80
108
  getComponentsForRenderingData(placeholderData) {
81
- const _a = this.props, { name, fields: placeholderFields, params: placeholderParams, missingComponentComponent, hiddenRenderingComponent } = _a, placeholderProps = __rest(_a, ["name", "fields", "params", "missingComponentComponent", "hiddenRenderingComponent"]);
82
- return placeholderData
109
+ var _a;
110
+ const _b = this.props, { name, fields: placeholderFields, params: placeholderParams, missingComponentComponent, hiddenRenderingComponent } = _b, placeholderProps = __rest(_b, ["name", "fields", "params", "missingComponentComponent", "hiddenRenderingComponent"]);
111
+ const transformedComponents = placeholderData
83
112
  .map((rendering, index) => {
113
+ var _a, _b;
84
114
  const key = rendering.uid
85
115
  ? rendering.uid
86
116
  : `component-${index}`;
87
117
  const commonProps = { key };
118
+ let isEmpty = false;
88
119
  // if the element is not a 'component rendering', render it 'raw'
89
120
  if (!rendering.componentName &&
90
121
  rendering.name) {
@@ -92,11 +123,13 @@ class PlaceholderCommon extends react_1.default.Component {
92
123
  }
93
124
  const componentRendering = rendering;
94
125
  let component;
95
- if (componentRendering.componentName === HiddenRendering_1.HIDDEN_RENDERING_NAME) {
126
+ if (componentRendering.componentName === sitecore_jss_1.constants.HIDDEN_RENDERING_NAME) {
96
127
  component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering_1.HiddenRendering;
128
+ isEmpty = true;
97
129
  }
98
130
  else if (!componentRendering.componentName) {
99
131
  component = () => react_1.default.createElement(react_1.default.Fragment, null);
132
+ isEmpty = true;
100
133
  }
101
134
  else {
102
135
  component = this.getComponentForRendering(componentRendering);
@@ -119,20 +152,34 @@ class PlaceholderCommon extends react_1.default.Component {
119
152
  if (!component) {
120
153
  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.`);
121
154
  component = missingComponentComponent !== null && missingComponentComponent !== void 0 ? missingComponentComponent : MissingComponent_1.MissingComponent;
155
+ isEmpty = true;
122
156
  }
123
157
  const finalProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), placeholderProps), ((placeholderFields || componentRendering.fields) && {
124
158
  fields: Object.assign(Object.assign({}, placeholderFields), componentRendering.fields),
125
159
  })), ((placeholderParams || componentRendering.params) && {
126
160
  params: Object.assign(Object.assign(Object.assign({}, placeholderParams), componentRendering.params), this.getSXAParams(componentRendering)),
127
161
  })), { rendering: componentRendering });
128
- return react_1.default.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
162
+ let rendered = react_1.default.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
163
+ if (!isEmpty) {
164
+ // assign type based on passed element - type='text/sitecore' should be ignored when renderEach Placeholder prop function is being used
165
+ const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
166
+ // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOC and tries to access its children props
167
+ // that's why we need to expose element's props here
168
+ rendered = (react_1.default.createElement(ErrorBoundary_1.default, 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));
169
+ }
170
+ // if editMode is equal to 'metadata' then emit shallow chromes for hydration in Pages
171
+ if (((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.editMode) === layout_1.EditMode.Metadata) {
172
+ return (react_1.default.createElement(PlaceholderMetadata_1.PlaceholderMetadata, { key: key, rendering: rendering }, rendered));
173
+ }
174
+ return rendered;
129
175
  })
130
- .filter((element) => element)
131
- .map((element, id) => {
132
- // assign type based on passed element - type='text/sitecore' should be ignored when renderEach Placeholder prop function is being used
133
- const type = element.props.type === 'text/sitecore' ? element.props.type : '';
134
- return (react_1.default.createElement(ErrorBoundary_1.default, { key: element.type + '-' + id, customErrorComponent: this.props.errorComponent, rendering: element.props.rendering, componentLoadingMessage: this.props.componentLoadingMessage, type: type }, element));
135
- });
176
+ .filter((element) => element); // remove nulls
177
+ if (((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.editMode) === layout_1.EditMode.Metadata) {
178
+ return [
179
+ react_1.default.createElement(PlaceholderMetadata_1.PlaceholderMetadata, { key: this.props.rendering.uid, placeholderName: name, rendering: this.props.rendering }, transformedComponents),
180
+ ];
181
+ }
182
+ return transformedComponents;
136
183
  }
137
184
  getComponentForRendering(renderingDefinition) {
138
185
  var _a;
@@ -208,4 +255,5 @@ PlaceholderCommon.propTypes = {
208
255
  prop_types_1.default.func,
209
256
  ]),
210
257
  modifyComponentProps: prop_types_1.default.func,
258
+ sitecoreContext: prop_types_1.default.object,
211
259
  };