@sitecore-jss/sitecore-jss-react 22.1.0-canary.9 → 22.2.0-canary.10

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 +52 -20
  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 +53 -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 +10 -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);
@@ -18,12 +18,15 @@ exports.PlaceholderCommon = 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"));
28
31
  class PlaceholderCommon extends react_1.default.Component {
29
32
  constructor(props) {
@@ -34,29 +37,38 @@ class PlaceholderCommon extends react_1.default.Component {
34
37
  this.updateKeyAttributes = this.updateKeyAttributes.bind(this);
35
38
  this.createRawElement = this.createRawElement.bind(this);
36
39
  }
37
- static getPlaceholderDataFromRenderingData(rendering, name) {
40
+ static getPlaceholderDataFromRenderingData(rendering, name, editMode) {
38
41
  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 **/
42
+ let phName = name.slice();
43
+ /**
44
+ * Process (SXA) dynamic placeholders
45
+ * Find and replace the matching dynamic placeholder e.g 'nameOfContainer-{*}' with the requested e.g. 'nameOfContainer-1'.
46
+ * For Metadata EditMode, we need to keep the raw placeholder name in place.
47
+ */
41
48
  if (rendering === null || rendering === void 0 ? void 0 : rendering.placeholders) {
42
49
  Object.keys(rendering.placeholders).forEach((placeholder) => {
43
- const patternPlaceholder = placeholder.indexOf('{*}') !== -1
44
- ? new RegExp(`^${placeholder.replace(/\{\*\}+/i, '\\d+')}$`)
50
+ const patternPlaceholder = (0, layout_1.isDynamicPlaceholder)(placeholder)
51
+ ? (0, layout_1.getDynamicPlaceholderPattern)(placeholder)
45
52
  : null;
46
- if (patternPlaceholder && patternPlaceholder.test(name)) {
47
- rendering.placeholders[name] = rendering.placeholders[placeholder];
48
- delete rendering.placeholders[placeholder];
53
+ if (patternPlaceholder && patternPlaceholder.test(phName)) {
54
+ if (editMode === layout_1.EditMode.Metadata) {
55
+ phName = placeholder;
56
+ }
57
+ else {
58
+ rendering.placeholders[phName] = rendering.placeholders[placeholder];
59
+ delete rendering.placeholders[placeholder];
60
+ }
49
61
  }
50
62
  });
51
63
  }
52
64
  if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
53
- result = rendering.placeholders[name];
65
+ result = rendering.placeholders[phName];
54
66
  }
55
67
  else {
56
68
  result = null;
57
69
  }
58
70
  if (!result) {
59
- console.warn(`Placeholder '${name}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
71
+ console.warn(`Placeholder '${phName}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
60
72
  return [];
61
73
  }
62
74
  return result;
@@ -78,13 +90,16 @@ class PlaceholderCommon extends react_1.default.Component {
78
90
  });
79
91
  }
80
92
  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
93
+ var _a;
94
+ const _b = this.props, { name, fields: placeholderFields, params: placeholderParams, missingComponentComponent, hiddenRenderingComponent } = _b, placeholderProps = __rest(_b, ["name", "fields", "params", "missingComponentComponent", "hiddenRenderingComponent"]);
95
+ const transformedComponents = placeholderData
83
96
  .map((rendering, index) => {
97
+ var _a, _b;
84
98
  const key = rendering.uid
85
99
  ? rendering.uid
86
100
  : `component-${index}`;
87
101
  const commonProps = { key };
102
+ let isEmpty = false;
88
103
  // if the element is not a 'component rendering', render it 'raw'
89
104
  if (!rendering.componentName &&
90
105
  rendering.name) {
@@ -92,11 +107,13 @@ class PlaceholderCommon extends react_1.default.Component {
92
107
  }
93
108
  const componentRendering = rendering;
94
109
  let component;
95
- if (componentRendering.componentName === HiddenRendering_1.HIDDEN_RENDERING_NAME) {
110
+ if (componentRendering.componentName === sitecore_jss_1.constants.HIDDEN_RENDERING_NAME) {
96
111
  component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering_1.HiddenRendering;
112
+ isEmpty = true;
97
113
  }
98
114
  else if (!componentRendering.componentName) {
99
115
  component = () => react_1.default.createElement(react_1.default.Fragment, null);
116
+ isEmpty = true;
100
117
  }
101
118
  else {
102
119
  component = this.getComponentForRendering(componentRendering);
@@ -119,20 +136,34 @@ class PlaceholderCommon extends react_1.default.Component {
119
136
  if (!component) {
120
137
  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
138
  component = missingComponentComponent !== null && missingComponentComponent !== void 0 ? missingComponentComponent : MissingComponent_1.MissingComponent;
139
+ isEmpty = true;
122
140
  }
123
141
  const finalProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), placeholderProps), ((placeholderFields || componentRendering.fields) && {
124
142
  fields: Object.assign(Object.assign({}, placeholderFields), componentRendering.fields),
125
143
  })), ((placeholderParams || componentRendering.params) && {
126
144
  params: Object.assign(Object.assign(Object.assign({}, placeholderParams), componentRendering.params), this.getSXAParams(componentRendering)),
127
145
  })), { rendering: componentRendering });
128
- return react_1.default.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
146
+ let rendered = react_1.default.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
147
+ if (!isEmpty) {
148
+ // assign type based on passed element - type='text/sitecore' should be ignored when renderEach Placeholder prop function is being used
149
+ const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
150
+ // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOC and tries to access its children props
151
+ // that's why we need to expose element's props here
152
+ 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));
153
+ }
154
+ // if editMode is equal to 'metadata' then emit shallow chromes for hydration in Pages
155
+ if (((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.editMode) === layout_1.EditMode.Metadata) {
156
+ return (react_1.default.createElement(PlaceholderMetadata_1.PlaceholderMetadata, { key: key, rendering: rendering }, rendered));
157
+ }
158
+ return rendered;
129
159
  })
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
- });
160
+ .filter((element) => element); // remove nulls
161
+ if (((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.editMode) === layout_1.EditMode.Metadata) {
162
+ return [
163
+ react_1.default.createElement(PlaceholderMetadata_1.PlaceholderMetadata, { key: this.props.rendering.uid, placeholderName: name, rendering: this.props.rendering }, transformedComponents),
164
+ ];
165
+ }
166
+ return transformedComponents;
136
167
  }
137
168
  getComponentForRendering(renderingDefinition) {
138
169
  var _a;
@@ -208,4 +239,5 @@ PlaceholderCommon.propTypes = {
208
239
  prop_types_1.default.func,
209
240
  ]),
210
241
  modifyComponentProps: prop_types_1.default.func,
242
+ sitecoreContext: prop_types_1.default.object,
211
243
  };
@@ -0,0 +1,67 @@
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.PlaceholderMetadata = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const layout_1 = require("@sitecore-jss/sitecore-jss/layout");
9
+ /**
10
+ * default value of uid for root placeholder when uid is not present.
11
+ */
12
+ const DEFAULT_PLACEHOLDER_UID = '00000000-0000-0000-0000-000000000000';
13
+ /**
14
+ * A React component to generate metadata blocks for a placeholder or rendering.
15
+ * It utilizes dynamic attributes based on whether the component acts as a placeholder
16
+ * or as a rendering to properly render the surrounding code blocks.
17
+ *
18
+ * @param {object} props The properties passed to the component.
19
+ * @param {ComponentRendering} props.rendering The rendering data.
20
+ * @param {string} [props.placeholderName] The name of the placeholder.
21
+ * @param {JSX.Element} props.children The child components or elements to be wrapped by the metadata code blocks.
22
+ * @returns {JSX.Element} A React fragment containing open and close code blocks surrounding the children elements.
23
+ */
24
+ const PlaceholderMetadata = ({ rendering, placeholderName, children, }) => {
25
+ const getCodeBlockAttributes = (kind, id, placeholderName) => {
26
+ const chrometype = placeholderName ? 'placeholder' : 'rendering';
27
+ const attributes = {
28
+ type: 'text/sitecore',
29
+ chrometype: chrometype,
30
+ className: 'scpm',
31
+ kind: kind,
32
+ };
33
+ if (kind === 'open') {
34
+ if (chrometype === 'placeholder' && placeholderName) {
35
+ let phId = '';
36
+ for (const placeholder of Object.keys(rendering.placeholders)) {
37
+ if (placeholderName === placeholder) {
38
+ phId = id
39
+ ? `${placeholderName}_${id}`
40
+ : `${placeholderName}_${DEFAULT_PLACEHOLDER_UID}`;
41
+ break;
42
+ }
43
+ // Check if the placeholder is a dynamic placeholder
44
+ if ((0, layout_1.isDynamicPlaceholder)(placeholder)) {
45
+ const pattern = (0, layout_1.getDynamicPlaceholderPattern)(placeholder);
46
+ // Check if the placeholder matches the dynamic placeholder pattern
47
+ if (pattern.test(placeholderName)) {
48
+ phId = id ? `${placeholder}_${id}` : `${placeholder}_${DEFAULT_PLACEHOLDER_UID}`;
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ attributes.id = phId;
54
+ }
55
+ else {
56
+ attributes.id = id;
57
+ }
58
+ }
59
+ return attributes;
60
+ };
61
+ const renderComponent = (uid, placeholderName) => (react_1.default.createElement(react_1.default.Fragment, null,
62
+ react_1.default.createElement("code", Object.assign({}, getCodeBlockAttributes('open', uid, placeholderName))),
63
+ children,
64
+ react_1.default.createElement("code", Object.assign({}, getCodeBlockAttributes('close', uid, placeholderName)))));
65
+ return react_1.default.createElement(react_1.default.Fragment, null, renderComponent(rendering.uid, placeholderName));
66
+ };
67
+ exports.PlaceholderMetadata = PlaceholderMetadata;