@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.
- package/LICENSE.txt +202 -202
- package/README.md +10 -10
- package/dist/cjs/components/Date.js +12 -4
- package/dist/cjs/components/DefaultEmptyFieldEditingComponents.js +22 -0
- package/dist/cjs/components/EditFrame.js +2 -2
- package/dist/cjs/components/EditingScripts.js +27 -0
- package/dist/cjs/components/ErrorBoundary.js +22 -7
- package/dist/cjs/components/FieldMetadata.js +33 -0
- package/dist/cjs/components/File.js +2 -1
- package/dist/cjs/components/HiddenRendering.js +7 -4
- package/dist/cjs/components/Image.js +15 -14
- package/dist/cjs/components/Link.js +13 -6
- package/dist/cjs/components/Placeholder.js +9 -6
- package/dist/cjs/components/PlaceholderCommon.js +69 -21
- package/dist/cjs/components/PlaceholderMetadata.js +67 -0
- package/dist/cjs/components/RichText.js +14 -3
- package/dist/cjs/components/Text.js +12 -4
- package/dist/cjs/enhancers/withEmptyFieldEditingComponent.js +56 -0
- package/dist/cjs/enhancers/withFieldMetadata.js +60 -0
- package/dist/cjs/enhancers/withPlaceholder.js +4 -3
- package/dist/cjs/index.js +17 -6
- package/dist/esm/components/Date.js +12 -3
- package/dist/esm/components/DefaultEmptyFieldEditingComponents.js +14 -0
- package/dist/esm/components/EditFrame.js +1 -1
- package/dist/esm/components/EditingScripts.js +20 -0
- package/dist/esm/components/ErrorBoundary.js +22 -7
- package/dist/esm/components/FieldMetadata.js +26 -0
- package/dist/esm/components/File.js +2 -1
- package/dist/esm/components/HiddenRendering.js +6 -3
- package/dist/esm/components/Image.js +15 -13
- package/dist/esm/components/Link.js +13 -6
- package/dist/esm/components/Placeholder.js +7 -4
- package/dist/esm/components/PlaceholderCommon.js +67 -21
- package/dist/esm/components/PlaceholderMetadata.js +60 -0
- package/dist/esm/components/RichText.js +14 -3
- package/dist/esm/components/Text.js +12 -3
- package/dist/esm/enhancers/withEmptyFieldEditingComponent.js +29 -0
- package/dist/esm/enhancers/withFieldMetadata.js +33 -0
- package/dist/esm/enhancers/withPlaceholder.js +4 -3
- package/dist/esm/index.js +6 -2
- package/package.json +5 -5
- package/types/components/Date.d.ts +4 -8
- package/types/components/DefaultEmptyFieldEditingComponents.d.ts +4 -0
- package/types/components/EditFrame.d.ts +1 -1
- package/types/components/EditingScripts.d.ts +5 -0
- package/types/components/ErrorBoundary.d.ts +4 -3
- package/types/components/FieldMetadata.d.ts +23 -0
- package/types/components/HiddenRendering.d.ts +0 -1
- package/types/components/Image.d.ts +4 -8
- package/types/components/Link.d.ts +7 -10
- package/types/components/Placeholder.d.ts +1 -4
- package/types/components/PlaceholderCommon.d.ts +22 -4
- package/types/components/PlaceholderMetadata.d.ts +30 -0
- package/types/components/RichText.d.ts +8 -8
- package/types/components/Text.d.ts +6 -10
- package/types/components/sharedTypes.d.ts +26 -1
- package/types/enhancers/withEmptyFieldEditingComponent.d.ts +28 -0
- package/types/enhancers/withFieldMetadata.d.ts +17 -0
- package/types/enhancers/withPlaceholder.d.ts +2 -4
- package/types/enhancers/withSitecoreContext.d.ts +4 -6
- package/types/index.d.ts +9 -4
|
@@ -12,13 +12,30 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
14
|
import { MissingComponent } from './MissingComponent';
|
|
15
|
+
import { EditMode, } from '@sitecore-jss/sitecore-jss/layout';
|
|
16
|
+
import { constants } from '@sitecore-jss/sitecore-jss';
|
|
15
17
|
import { convertAttributesToReactProps } from '../utils';
|
|
16
|
-
import { HiddenRendering
|
|
18
|
+
import { HiddenRendering } from './HiddenRendering';
|
|
17
19
|
import { FEaaSComponent, FEAAS_COMPONENT_RENDERING_NAME } from './FEaaSComponent';
|
|
18
20
|
import { FEaaSWrapper, FEAAS_WRAPPER_RENDERING_NAME } from './FEaaSWrapper';
|
|
19
21
|
import { BYOCComponent, BYOC_COMPONENT_RENDERING_NAME } from './BYOCComponent';
|
|
20
22
|
import { BYOCWrapper, BYOC_WRAPPER_RENDERING_NAME } from './BYOCWrapper';
|
|
23
|
+
import { PlaceholderMetadata } from './PlaceholderMetadata';
|
|
21
24
|
import ErrorBoundary from './ErrorBoundary';
|
|
25
|
+
/**
|
|
26
|
+
* Returns a regular expression pattern for a dynamic placeholder name.
|
|
27
|
+
* @param {string} placeholder Placeholder name with a dynamic segment (e.g. 'main-{*}')
|
|
28
|
+
* @returns Regular expression pattern for the dynamic segment
|
|
29
|
+
*/
|
|
30
|
+
export const getDynamicPlaceholderPattern = (placeholder) => {
|
|
31
|
+
return new RegExp(`^${placeholder.replace(/\{\*\}+/i, '\\d+')}$`);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Checks if the placeholder name is dynamic.
|
|
35
|
+
* @param {string} placeholder Placeholder name
|
|
36
|
+
* @returns True if the placeholder name is dynamic
|
|
37
|
+
*/
|
|
38
|
+
export const isDynamicPlaceholder = (placeholder) => placeholder.indexOf('{*}') !== -1;
|
|
22
39
|
export class PlaceholderCommon extends React.Component {
|
|
23
40
|
constructor(props) {
|
|
24
41
|
super(props);
|
|
@@ -28,29 +45,38 @@ export class PlaceholderCommon extends React.Component {
|
|
|
28
45
|
this.updateKeyAttributes = this.updateKeyAttributes.bind(this);
|
|
29
46
|
this.createRawElement = this.createRawElement.bind(this);
|
|
30
47
|
}
|
|
31
|
-
static getPlaceholderDataFromRenderingData(rendering, name) {
|
|
48
|
+
static getPlaceholderDataFromRenderingData(rendering, name, editMode) {
|
|
32
49
|
let result;
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
let phName = name.slice();
|
|
51
|
+
/**
|
|
52
|
+
* [Chromes Mode]: [SXA] it needs for deleting dynamics placeholder when we set him number(props.name) of container.
|
|
53
|
+
* from backend side we get common name of placeholder is called 'nameOfContainer-{*}' where '{*}' marker for replacing.
|
|
54
|
+
* [Metadata Mode]: We need to keep the raw placeholder name. e.g 'nameOfContainer-{*}' instead of 'nameOfContainer-1'
|
|
55
|
+
*/
|
|
35
56
|
if (rendering === null || rendering === void 0 ? void 0 : rendering.placeholders) {
|
|
36
57
|
Object.keys(rendering.placeholders).forEach((placeholder) => {
|
|
37
|
-
const patternPlaceholder = placeholder
|
|
38
|
-
?
|
|
58
|
+
const patternPlaceholder = isDynamicPlaceholder(placeholder)
|
|
59
|
+
? getDynamicPlaceholderPattern(placeholder)
|
|
39
60
|
: null;
|
|
40
|
-
if (patternPlaceholder && patternPlaceholder.test(
|
|
41
|
-
|
|
42
|
-
|
|
61
|
+
if (patternPlaceholder && patternPlaceholder.test(phName)) {
|
|
62
|
+
if (editMode === EditMode.Metadata) {
|
|
63
|
+
phName = placeholder;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
rendering.placeholders[phName] = rendering.placeholders[placeholder];
|
|
67
|
+
delete rendering.placeholders[placeholder];
|
|
68
|
+
}
|
|
43
69
|
}
|
|
44
70
|
});
|
|
45
71
|
}
|
|
46
72
|
if (rendering && rendering.placeholders && Object.keys(rendering.placeholders).length > 0) {
|
|
47
|
-
result = rendering.placeholders[
|
|
73
|
+
result = rendering.placeholders[phName];
|
|
48
74
|
}
|
|
49
75
|
else {
|
|
50
76
|
result = null;
|
|
51
77
|
}
|
|
52
78
|
if (!result) {
|
|
53
|
-
console.warn(`Placeholder '${
|
|
79
|
+
console.warn(`Placeholder '${phName}' was not found in the current rendering data`, JSON.stringify(rendering, null, 2));
|
|
54
80
|
return [];
|
|
55
81
|
}
|
|
56
82
|
return result;
|
|
@@ -72,13 +98,16 @@ export class PlaceholderCommon extends React.Component {
|
|
|
72
98
|
});
|
|
73
99
|
}
|
|
74
100
|
getComponentsForRenderingData(placeholderData) {
|
|
75
|
-
|
|
76
|
-
|
|
101
|
+
var _a;
|
|
102
|
+
const _b = this.props, { name, fields: placeholderFields, params: placeholderParams, missingComponentComponent, hiddenRenderingComponent } = _b, placeholderProps = __rest(_b, ["name", "fields", "params", "missingComponentComponent", "hiddenRenderingComponent"]);
|
|
103
|
+
const transformedComponents = placeholderData
|
|
77
104
|
.map((rendering, index) => {
|
|
105
|
+
var _a, _b;
|
|
78
106
|
const key = rendering.uid
|
|
79
107
|
? rendering.uid
|
|
80
108
|
: `component-${index}`;
|
|
81
109
|
const commonProps = { key };
|
|
110
|
+
let isEmpty = false;
|
|
82
111
|
// if the element is not a 'component rendering', render it 'raw'
|
|
83
112
|
if (!rendering.componentName &&
|
|
84
113
|
rendering.name) {
|
|
@@ -86,11 +115,13 @@ export class PlaceholderCommon extends React.Component {
|
|
|
86
115
|
}
|
|
87
116
|
const componentRendering = rendering;
|
|
88
117
|
let component;
|
|
89
|
-
if (componentRendering.componentName === HIDDEN_RENDERING_NAME) {
|
|
118
|
+
if (componentRendering.componentName === constants.HIDDEN_RENDERING_NAME) {
|
|
90
119
|
component = hiddenRenderingComponent !== null && hiddenRenderingComponent !== void 0 ? hiddenRenderingComponent : HiddenRendering;
|
|
120
|
+
isEmpty = true;
|
|
91
121
|
}
|
|
92
122
|
else if (!componentRendering.componentName) {
|
|
93
123
|
component = () => React.createElement(React.Fragment, null);
|
|
124
|
+
isEmpty = true;
|
|
94
125
|
}
|
|
95
126
|
else {
|
|
96
127
|
component = this.getComponentForRendering(componentRendering);
|
|
@@ -113,20 +144,34 @@ export class PlaceholderCommon extends React.Component {
|
|
|
113
144
|
if (!component) {
|
|
114
145
|
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.`);
|
|
115
146
|
component = missingComponentComponent !== null && missingComponentComponent !== void 0 ? missingComponentComponent : MissingComponent;
|
|
147
|
+
isEmpty = true;
|
|
116
148
|
}
|
|
117
149
|
const finalProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), placeholderProps), ((placeholderFields || componentRendering.fields) && {
|
|
118
150
|
fields: Object.assign(Object.assign({}, placeholderFields), componentRendering.fields),
|
|
119
151
|
})), ((placeholderParams || componentRendering.params) && {
|
|
120
152
|
params: Object.assign(Object.assign(Object.assign({}, placeholderParams), componentRendering.params), this.getSXAParams(componentRendering)),
|
|
121
153
|
})), { rendering: componentRendering });
|
|
122
|
-
|
|
154
|
+
let rendered = React.createElement(component, this.props.modifyComponentProps ? this.props.modifyComponentProps(finalProps) : finalProps);
|
|
155
|
+
if (!isEmpty) {
|
|
156
|
+
// assign type based on passed element - type='text/sitecore' should be ignored when renderEach Placeholder prop function is being used
|
|
157
|
+
const type = rendered.props.type === 'text/sitecore' ? rendered.props.type : '';
|
|
158
|
+
// wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOC and tries to access its children props
|
|
159
|
+
// that's why we need to expose element's props here
|
|
160
|
+
rendered = (React.createElement(ErrorBoundary, Object.assign({ key: rendered.type + '-' + index, errorComponent: this.props.errorComponent, componentLoadingMessage: this.props.componentLoadingMessage, type: type, isDynamic: ((_a = component.render) === null || _a === void 0 ? void 0 : _a.preload) ? true : false }, rendered.props), rendered));
|
|
161
|
+
}
|
|
162
|
+
// if editMode is equal to 'metadata' then emit shallow chromes for hydration in Pages
|
|
163
|
+
if (((_b = this.props.sitecoreContext) === null || _b === void 0 ? void 0 : _b.editMode) === EditMode.Metadata) {
|
|
164
|
+
return (React.createElement(PlaceholderMetadata, { key: key, rendering: rendering }, rendered));
|
|
165
|
+
}
|
|
166
|
+
return rendered;
|
|
123
167
|
})
|
|
124
|
-
.filter((element) => element)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
168
|
+
.filter((element) => element); // remove nulls
|
|
169
|
+
if (((_a = this.props.sitecoreContext) === null || _a === void 0 ? void 0 : _a.editMode) === EditMode.Metadata) {
|
|
170
|
+
return [
|
|
171
|
+
React.createElement(PlaceholderMetadata, { key: this.props.rendering.uid, placeholderName: name, rendering: this.props.rendering }, transformedComponents),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
return transformedComponents;
|
|
130
175
|
}
|
|
131
176
|
getComponentForRendering(renderingDefinition) {
|
|
132
177
|
var _a;
|
|
@@ -201,4 +246,5 @@ PlaceholderCommon.propTypes = {
|
|
|
201
246
|
PropTypes.func,
|
|
202
247
|
]),
|
|
203
248
|
modifyComponentProps: PropTypes.func,
|
|
249
|
+
sitecoreContext: PropTypes.object,
|
|
204
250
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getDynamicPlaceholderPattern, isDynamicPlaceholder } from './PlaceholderCommon';
|
|
3
|
+
/**
|
|
4
|
+
* default value of uid for root placeholder when uid is not present.
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_PLACEHOLDER_UID = '00000000-0000-0000-0000-000000000000';
|
|
7
|
+
/**
|
|
8
|
+
* A React component to generate metadata blocks for a placeholder or rendering.
|
|
9
|
+
* It utilizes dynamic attributes based on whether the component acts as a placeholder
|
|
10
|
+
* or as a rendering to properly render the surrounding code blocks.
|
|
11
|
+
*
|
|
12
|
+
* @param {object} props The properties passed to the component.
|
|
13
|
+
* @param {ComponentRendering} props.rendering The rendering data.
|
|
14
|
+
* @param {string} [props.placeholderName] The name of the placeholder.
|
|
15
|
+
* @param {JSX.Element} props.children The child components or elements to be wrapped by the metadata code blocks.
|
|
16
|
+
* @returns {JSX.Element} A React fragment containing open and close code blocks surrounding the children elements.
|
|
17
|
+
*/
|
|
18
|
+
export const PlaceholderMetadata = ({ rendering, placeholderName, children, }) => {
|
|
19
|
+
const getCodeBlockAttributes = (kind, id, placeholderName) => {
|
|
20
|
+
const chrometype = placeholderName ? 'placeholder' : 'rendering';
|
|
21
|
+
const attributes = {
|
|
22
|
+
type: 'text/sitecore',
|
|
23
|
+
chrometype: chrometype,
|
|
24
|
+
className: 'scpm',
|
|
25
|
+
kind: kind,
|
|
26
|
+
};
|
|
27
|
+
if (kind === 'open') {
|
|
28
|
+
if (chrometype === 'placeholder' && placeholderName) {
|
|
29
|
+
let phId = '';
|
|
30
|
+
for (const placeholder of Object.keys(rendering.placeholders)) {
|
|
31
|
+
if (placeholderName === placeholder) {
|
|
32
|
+
phId = id
|
|
33
|
+
? `${placeholderName}_${id}`
|
|
34
|
+
: `${placeholderName}_${DEFAULT_PLACEHOLDER_UID}`;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
// Check if the placeholder is a dynamic placeholder
|
|
38
|
+
if (isDynamicPlaceholder(placeholder)) {
|
|
39
|
+
const pattern = getDynamicPlaceholderPattern(placeholder);
|
|
40
|
+
// Check if the placeholder matches the dynamic placeholder pattern
|
|
41
|
+
if (pattern.test(placeholderName)) {
|
|
42
|
+
phId = id ? `${placeholder}_${id}` : `${placeholder}_${DEFAULT_PLACEHOLDER_UID}`;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
attributes.id = phId;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
attributes.id = id;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return attributes;
|
|
54
|
+
};
|
|
55
|
+
const renderComponent = (uid, placeholderName) => (React.createElement(React.Fragment, null,
|
|
56
|
+
React.createElement("code", Object.assign({}, getCodeBlockAttributes('open', uid, placeholderName))),
|
|
57
|
+
children,
|
|
58
|
+
React.createElement("code", Object.assign({}, getCodeBlockAttributes('close', uid, placeholderName)))));
|
|
59
|
+
return React.createElement(React.Fragment, null, renderComponent(rendering.uid, placeholderName));
|
|
60
|
+
};
|
|
@@ -11,23 +11,34 @@ 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
|
-
|
|
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 RichText = withFieldMetadata(withEmptyFieldEditingComponent(
|
|
19
|
+
// eslint-disable-next-line react/display-name
|
|
20
|
+
forwardRef((_a, ref) => {
|
|
15
21
|
var { field, tag = 'div', editable = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable"]);
|
|
16
|
-
if (!field || (!field.editable &&
|
|
22
|
+
if (!field || (!field.editable && isFieldValueEmpty(field))) {
|
|
17
23
|
return null;
|
|
18
24
|
}
|
|
19
25
|
const htmlProps = Object.assign({ dangerouslySetInnerHTML: {
|
|
20
26
|
__html: field.editable && editable ? field.editable : field.value,
|
|
21
27
|
}, ref }, otherProps);
|
|
22
28
|
return React.createElement(tag || 'div', htmlProps);
|
|
23
|
-
});
|
|
29
|
+
}), { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText, isForwardRef: true }), true);
|
|
24
30
|
export const RichTextPropTypes = {
|
|
25
31
|
field: PropTypes.shape({
|
|
26
32
|
value: PropTypes.string,
|
|
27
33
|
editable: PropTypes.string,
|
|
34
|
+
metadata: PropTypes.objectOf(PropTypes.any),
|
|
28
35
|
}),
|
|
29
36
|
tag: PropTypes.string,
|
|
30
37
|
editable: PropTypes.bool,
|
|
38
|
+
emptyFieldEditingComponent: PropTypes.oneOfType([
|
|
39
|
+
PropTypes.object,
|
|
40
|
+
PropTypes.func,
|
|
41
|
+
]),
|
|
31
42
|
};
|
|
32
43
|
RichText.propTypes = RichTextPropTypes;
|
|
33
44
|
RichText.displayName = 'RichText';
|
|
@@ -10,10 +10,14 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import React from 'react';
|
|
13
|
+
import { withFieldMetadata } from '../enhancers/withFieldMetadata';
|
|
14
|
+
import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
|
|
15
|
+
import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
|
|
13
16
|
import PropTypes from 'prop-types';
|
|
14
|
-
|
|
17
|
+
import { isFieldValueEmpty } from '@sitecore-jss/sitecore-jss/layout';
|
|
18
|
+
export const Text = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
|
|
15
19
|
var { field, tag, editable = true, encode = true } = _a, otherProps = __rest(_a, ["field", "tag", "editable", "encode"]);
|
|
16
|
-
if (!field || (!field.editable && (field
|
|
20
|
+
if (!field || (!field.editable && isFieldValueEmpty(field))) {
|
|
17
21
|
return null;
|
|
18
22
|
}
|
|
19
23
|
// can't use editable value if we want to output unencoded
|
|
@@ -59,14 +63,19 @@ export const Text = (_a) => {
|
|
|
59
63
|
else {
|
|
60
64
|
return React.createElement(React.Fragment, null, children);
|
|
61
65
|
}
|
|
62
|
-
};
|
|
66
|
+
}, { defaultEmptyFieldEditingComponent: DefaultEmptyFieldEditingComponentText }));
|
|
63
67
|
Text.propTypes = {
|
|
64
68
|
field: PropTypes.shape({
|
|
65
69
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
66
70
|
editable: PropTypes.string,
|
|
71
|
+
metadata: PropTypes.objectOf(PropTypes.any),
|
|
67
72
|
}),
|
|
68
73
|
tag: PropTypes.string,
|
|
69
74
|
editable: PropTypes.bool,
|
|
70
75
|
encode: PropTypes.bool,
|
|
76
|
+
emptyFieldEditingComponent: PropTypes.oneOfType([
|
|
77
|
+
PropTypes.object,
|
|
78
|
+
PropTypes.func,
|
|
79
|
+
]),
|
|
71
80
|
};
|
|
72
81
|
Text.displayName = 'Text';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { isFieldValueEmpty, } from '@sitecore-jss/sitecore-jss/layout';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the passed field component or default component in case field value is empty and edit mode is 'metadata'
|
|
5
|
+
* @param {ComponentType<FieldComponentProps>} FieldComponent the field component
|
|
6
|
+
* @param {WithEmptyFieldEditingComponentProps} options the options of the HOC;
|
|
7
|
+
*/
|
|
8
|
+
export function withEmptyFieldEditingComponent(FieldComponent, options) {
|
|
9
|
+
const getEmptyFieldEditingComponent = (props) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const { editable = true } = props;
|
|
12
|
+
if (((_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata) && editable && isFieldValueEmpty(props.field)) {
|
|
13
|
+
return props.emptyFieldEditingComponent || options.defaultEmptyFieldEditingComponent;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
};
|
|
17
|
+
if (options.isForwardRef) {
|
|
18
|
+
// eslint-disable-next-line react/display-name
|
|
19
|
+
return forwardRef((props, ref) => {
|
|
20
|
+
const EmptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
|
|
21
|
+
return (React.createElement(React.Fragment, null, (EmptyFieldEditingComponent && React.createElement(EmptyFieldEditingComponent, null)) || (React.createElement(FieldComponent, Object.assign({}, props, { ref: ref })))));
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
// eslint-disable-next-line react/display-name
|
|
25
|
+
return (props) => {
|
|
26
|
+
const EmptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
|
|
27
|
+
return (React.createElement(React.Fragment, null, (EmptyFieldEditingComponent && React.createElement(EmptyFieldEditingComponent, null)) || (React.createElement(FieldComponent, Object.assign({}, props)))));
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { FieldMetadata } from '../components/FieldMetadata';
|
|
3
|
+
/**
|
|
4
|
+
* Wraps the field component with metadata markup intended to be used for chromes hydration in Pages
|
|
5
|
+
* @param {ComponentType<FieldComponentProps>} FieldComponent the field component
|
|
6
|
+
* @param {boolean} isForwardRef set to 'true' if forward reference is needed
|
|
7
|
+
*/
|
|
8
|
+
export function withFieldMetadata(FieldComponent, isForwardRef = false) {
|
|
9
|
+
if (isForwardRef) {
|
|
10
|
+
// eslint-disable-next-line react/display-name
|
|
11
|
+
return forwardRef((props, ref) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const { editable = true } = props;
|
|
14
|
+
const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
|
|
15
|
+
if (!metadata || !editable) {
|
|
16
|
+
return React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }));
|
|
17
|
+
}
|
|
18
|
+
return (React.createElement(FieldMetadata, { metadata: metadata },
|
|
19
|
+
React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }))));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// eslint-disable-next-line react/display-name
|
|
23
|
+
return (props) => {
|
|
24
|
+
var _a;
|
|
25
|
+
const { editable = true } = props;
|
|
26
|
+
const metadata = (_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata;
|
|
27
|
+
if (!metadata || !editable) {
|
|
28
|
+
return React.createElement(FieldComponent, Object.assign({}, props));
|
|
29
|
+
}
|
|
30
|
+
return (React.createElement(FieldMetadata, { metadata: metadata },
|
|
31
|
+
React.createElement(FieldComponent, Object.assign({}, props))));
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { PlaceholderCommon } from '../components/PlaceholderCommon';
|
|
3
3
|
import { withComponentFactory } from './withComponentFactory';
|
|
4
|
+
import { withSitecoreContext } from './withSitecoreContext';
|
|
4
5
|
/**
|
|
5
6
|
* @param {WithPlaceholderSpec} placeholders
|
|
6
7
|
* @param {WithPlaceholderOptions} [options]
|
|
@@ -35,13 +36,13 @@ export function withPlaceholder(placeholders, options) {
|
|
|
35
36
|
definitelyArrayPlacholders.forEach((placeholder) => {
|
|
36
37
|
let placeholderData;
|
|
37
38
|
if (typeof placeholder !== 'string' && placeholder.placeholder && placeholder.prop) {
|
|
38
|
-
placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder.placeholder);
|
|
39
|
+
placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder.placeholder, childProps.sitecoreContext.editMode);
|
|
39
40
|
if (placeholderData) {
|
|
40
41
|
childProps[placeholder.prop] = this.getComponentsForRenderingData(placeholderData);
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
else {
|
|
44
|
-
placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder);
|
|
45
|
+
placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder, childProps.sitecoreContext.editMode);
|
|
45
46
|
if (placeholderData) {
|
|
46
47
|
childProps[placeholder] = this.getComponentsForRenderingData(placeholderData);
|
|
47
48
|
}
|
|
@@ -51,6 +52,6 @@ export function withPlaceholder(placeholders, options) {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
WithPlaceholder.propTypes = PlaceholderCommon.propTypes;
|
|
54
|
-
return withComponentFactory(WithPlaceholder);
|
|
55
|
+
return withSitecoreContext()(withComponentFactory(WithPlaceholder));
|
|
55
56
|
};
|
|
56
57
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { constants, enableDebug, ClientError } from '@sitecore-jss/sitecore-jss';
|
|
2
|
-
export { isEditorActive, resetEditorChromes, DefaultEditFrameButton, DefaultEditFrameButtons, } from '@sitecore-jss/sitecore-jss/
|
|
3
|
-
export { getContentStylesheetLink, getComponentLibraryStylesheetLinks, LayoutServicePageState, GraphQLLayoutService, RestLayoutService, getChildPlaceholder, getFieldValue, } from '@sitecore-jss/sitecore-jss/layout';
|
|
2
|
+
export { isEditorActive, resetEditorChromes, DefaultEditFrameButton, DefaultEditFrameButtons, } from '@sitecore-jss/sitecore-jss/editing';
|
|
3
|
+
export { getContentStylesheetLink, getComponentLibraryStylesheetLinks, LayoutServicePageState, GraphQLLayoutService, RestLayoutService, getChildPlaceholder, getFieldValue, EditMode, } from '@sitecore-jss/sitecore-jss/layout';
|
|
4
4
|
export { trackingApi, } from '@sitecore-jss/sitecore-jss/tracking';
|
|
5
5
|
export { GraphQLDictionaryService, RestDictionaryService, } from '@sitecore-jss/sitecore-jss/i18n';
|
|
6
6
|
export { DefaultRetryStrategy, GraphQLRequestClient, } from '@sitecore-jss/sitecore-jss/graphql';
|
|
@@ -24,3 +24,7 @@ export { withPlaceholder } from './enhancers/withPlaceholder';
|
|
|
24
24
|
export { withDatasourceCheck } from './enhancers/withDatasourceCheck';
|
|
25
25
|
export { EditFrame } from './components/EditFrame';
|
|
26
26
|
export { ComponentBuilder } from './ComponentBuilder';
|
|
27
|
+
export { withFieldMetadata } from './enhancers/withFieldMetadata';
|
|
28
|
+
export { withEmptyFieldEditingComponent } from './enhancers/withEmptyFieldEditingComponent';
|
|
29
|
+
export { EditingScripts } from './components/EditingScripts';
|
|
30
|
+
export { DefaultEmptyFieldEditingComponentText, DefaultEmptyFieldEditingComponentImage, } from './components/DefaultEmptyFieldEditingComponents';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-jss/sitecore-jss-react",
|
|
3
|
-
"version": "22.1.0
|
|
3
|
+
"version": "22.1.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"generate-docs": "npx typedoc --plugin typedoc-plugin-markdown --readme none --out ../../ref-docs/sitecore-jss-react src/index.ts --githubPages false"
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=20"
|
|
18
18
|
},
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Sitecore Corporation",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@types/chai-string": "^1.4.2",
|
|
32
32
|
"@types/enzyme": "^3.10.12",
|
|
33
33
|
"@types/mocha": "^10.0.1",
|
|
34
|
-
"@types/node": "
|
|
34
|
+
"@types/node": "20.14.2",
|
|
35
35
|
"@types/prop-types": "^15.7.5",
|
|
36
36
|
"@types/react": "^18.2.22",
|
|
37
37
|
"@types/react-dom": "^18.0.10",
|
|
@@ -61,14 +61,14 @@
|
|
|
61
61
|
"react-dom": "^18.2.0"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@sitecore-jss/sitecore-jss": "
|
|
64
|
+
"@sitecore-jss/sitecore-jss": "22.1.0",
|
|
65
65
|
"fast-deep-equal": "^3.1.3",
|
|
66
66
|
"prop-types": "^15.8.1",
|
|
67
67
|
"style-attr": "^1.3.0"
|
|
68
68
|
},
|
|
69
69
|
"description": "",
|
|
70
70
|
"types": "types/index.d.ts",
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "8f6fa5709f6b306bf40fb2b0775ae6c5ac4182e7",
|
|
72
72
|
"files": [
|
|
73
73
|
"dist",
|
|
74
74
|
"types"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/// <reference types="@types/react" />
|
|
2
2
|
import React from 'react';
|
|
3
|
-
|
|
3
|
+
import { EditableFieldProps } from './sharedTypes';
|
|
4
|
+
import { FieldMetadata } from '@sitecore-jss/sitecore-jss/layout';
|
|
5
|
+
export interface DateFieldProps extends EditableFieldProps {
|
|
4
6
|
/** The date field data. */
|
|
5
7
|
[htmlAttributes: string]: unknown;
|
|
6
|
-
field: {
|
|
8
|
+
field: FieldMetadata & {
|
|
7
9
|
value?: string;
|
|
8
10
|
editable?: string;
|
|
9
11
|
};
|
|
@@ -11,12 +13,6 @@ export interface DateFieldProps {
|
|
|
11
13
|
* The HTML element that will wrap the contents of the field.
|
|
12
14
|
*/
|
|
13
15
|
tag?: string;
|
|
14
|
-
/**
|
|
15
|
-
* Can be used to explicitly disable inline editing.
|
|
16
|
-
* If true and `field.editable` has a value, then `field.editable` will be processed and rendered as component output. If false, `field.editable` value will be ignored and not rendered.
|
|
17
|
-
* @default true
|
|
18
|
-
*/
|
|
19
|
-
editable?: boolean;
|
|
20
16
|
render?: (date: Date | null) => React.ReactNode;
|
|
21
17
|
}
|
|
22
18
|
export declare const DateField: React.FC<DateFieldProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@types/react" />
|
|
2
2
|
import React, { PropsWithChildren } from 'react';
|
|
3
|
-
import { EditFrameDataSource, EditButtonTypes } from '@sitecore-jss/sitecore-jss/
|
|
3
|
+
import { EditFrameDataSource, EditButtonTypes } from '@sitecore-jss/sitecore-jss/editing';
|
|
4
4
|
export interface EditFrameProps {
|
|
5
5
|
dataSource?: EditFrameDataSource;
|
|
6
6
|
buttons?: EditButtonTypes[];
|
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
import React, { ReactNode } from 'react';
|
|
3
3
|
import { ComponentRendering } from '@sitecore-jss/sitecore-jss/layout';
|
|
4
4
|
import { SitecoreContextValue } from './SitecoreContext';
|
|
5
|
-
type
|
|
5
|
+
type ErrorComponentProps = {
|
|
6
6
|
[prop: string]: unknown;
|
|
7
7
|
};
|
|
8
8
|
export type ErrorBoundaryProps = {
|
|
9
9
|
children: ReactNode;
|
|
10
10
|
sitecoreContext: SitecoreContextValue;
|
|
11
11
|
type: string;
|
|
12
|
-
|
|
12
|
+
isDynamic?: boolean;
|
|
13
|
+
errorComponent?: React.ComponentClass<ErrorComponentProps> | React.FC<ErrorComponentProps>;
|
|
13
14
|
rendering?: ComponentRendering;
|
|
14
15
|
componentLoadingMessage?: string;
|
|
15
16
|
};
|
|
16
|
-
declare const _default: (props: import("../enhancers/withSitecoreContext").
|
|
17
|
+
declare const _default: (props: import("@sitecore-jss/sitecore-jss/utils").EnhancedOmit<ErrorBoundaryProps, keyof import("../enhancers/withSitecoreContext").WithSitecoreContextProps>) => React.JSX.Element;
|
|
17
18
|
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="@types/react" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
interface FieldMetadataProps {
|
|
5
|
+
metadata: {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The component which renders field metadata markup
|
|
12
|
+
* @param {FieldMetadataProps} props the props of the component
|
|
13
|
+
* @returns metadata markup wrapped around children
|
|
14
|
+
*/
|
|
15
|
+
export declare const FieldMetadata: {
|
|
16
|
+
(props: FieldMetadataProps): JSX.Element;
|
|
17
|
+
displayName: string;
|
|
18
|
+
propTypes: {
|
|
19
|
+
metadata: PropTypes.Validator<object>;
|
|
20
|
+
children: PropTypes.Validator<NonNullable<PropTypes.ReactNodeLike>>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/// <reference types="@types/react" />
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { EditableFieldProps } from './sharedTypes';
|
|
4
|
+
import { FieldMetadata } from '@sitecore-jss/sitecore-jss/layout';
|
|
3
5
|
export interface ImageFieldValue {
|
|
4
6
|
[attributeName: string]: unknown;
|
|
5
7
|
src?: string;
|
|
@@ -25,16 +27,10 @@ export interface ImageSizeParameters {
|
|
|
25
27
|
/** Image scale. Defaults to 1.0 */
|
|
26
28
|
sc?: number;
|
|
27
29
|
}
|
|
28
|
-
export interface ImageProps {
|
|
30
|
+
export interface ImageProps extends EditableFieldProps {
|
|
29
31
|
[attributeName: string]: unknown;
|
|
30
32
|
/** Image field data (consistent with other field types) */
|
|
31
|
-
field?: ImageField | ImageFieldValue;
|
|
32
|
-
/**
|
|
33
|
-
* Can be used to explicitly disable inline editing.
|
|
34
|
-
* If true and `media.editable` has a value, then `media.editable` will be processed
|
|
35
|
-
* and rendered as component output. If false, `media.editable` value will be ignored and not rendered.
|
|
36
|
-
*/
|
|
37
|
-
editable?: boolean;
|
|
33
|
+
field?: (ImageField | ImageFieldValue) & FieldMetadata;
|
|
38
34
|
/**
|
|
39
35
|
* Parameters that will be attached to Sitecore media URLs
|
|
40
36
|
*/
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/// <reference types="@types/react" />
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { RefAttributes } from 'react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
+
import { EditableFieldProps } from './sharedTypes';
|
|
5
|
+
import { FieldMetadata } from '@sitecore-jss/sitecore-jss/layout';
|
|
4
6
|
export interface LinkFieldValue {
|
|
5
7
|
[attributeName: string]: unknown;
|
|
6
8
|
href?: string;
|
|
@@ -18,22 +20,16 @@ export interface LinkField {
|
|
|
18
20
|
editableFirstPart?: string;
|
|
19
21
|
editableLastPart?: string;
|
|
20
22
|
}
|
|
21
|
-
export type LinkProps = React.
|
|
23
|
+
export type LinkProps = EditableFieldProps & React.AnchorHTMLAttributes<HTMLAnchorElement> & RefAttributes<HTMLAnchorElement> & {
|
|
22
24
|
/** The link field data. */
|
|
23
|
-
field: LinkField | LinkFieldValue;
|
|
24
|
-
/**
|
|
25
|
-
* Can be used to explicitly disable inline editing.
|
|
26
|
-
* If true and `field.editable` has a value, then `field.editable` will be processed and rendered as component output. If false, `field.editable` value will be ignored and not rendered.
|
|
27
|
-
* @default true
|
|
28
|
-
*/
|
|
29
|
-
editable?: boolean;
|
|
25
|
+
field: (LinkField | LinkFieldValue) & FieldMetadata;
|
|
30
26
|
/**
|
|
31
27
|
* Displays a link text ('description' in Sitecore) even when children exist
|
|
32
28
|
* NOTE: when in Sitecore Experience Editor, this setting is ignored due to technical limitations, and the description is always rendered.
|
|
33
29
|
*/
|
|
34
30
|
showLinkTextWithChildrenPresent?: boolean;
|
|
35
31
|
};
|
|
36
|
-
export declare const Link: React.
|
|
32
|
+
export declare const Link: React.FC<LinkProps>;
|
|
37
33
|
export declare const LinkPropTypes: {
|
|
38
34
|
field: PropTypes.Validator<NonNullable<NonNullable<PropTypes.InferProps<{
|
|
39
35
|
href: PropTypes.Requireable<any>;
|
|
@@ -44,4 +40,5 @@ export declare const LinkPropTypes: {
|
|
|
44
40
|
}>>>>;
|
|
45
41
|
editable: PropTypes.Requireable<boolean>;
|
|
46
42
|
showLinkTextWithChildrenPresent: PropTypes.Requireable<boolean>;
|
|
43
|
+
emptyFieldEditingComponent: PropTypes.Requireable<NonNullable<React.ComponentClass<unknown, any> | React.FC<unknown>>>;
|
|
47
44
|
};
|
|
@@ -19,7 +19,4 @@ export interface PlaceholderComponentProps extends PlaceholderProps {
|
|
|
19
19
|
*/
|
|
20
20
|
renderEach?: (component: React.ReactNode, index: number) => React.ReactNode;
|
|
21
21
|
}
|
|
22
|
-
export declare const Placeholder:
|
|
23
|
-
(props: PlaceholderComponentProps): JSX.Element;
|
|
24
|
-
displayName: string;
|
|
25
|
-
};
|
|
22
|
+
export declare const Placeholder: (props: import("@sitecore-jss/sitecore-jss/utils").EnhancedOmit<PlaceholderComponentProps, keyof import("../enhancers/withSitecoreContext").WithSitecoreContextProps>) => React.JSX.Element;
|