@sitecore-content-sdk/react 1.1.0-canary.9 → 1.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 +11 -11
- package/dist/cjs/components/Date.js +3 -1
- package/dist/cjs/components/DefaultEmptyFieldEditingComponents.js +4 -4
- package/dist/cjs/components/DesignLibrary.js +118 -92
- package/dist/cjs/components/EditingScripts.js +8 -2
- package/dist/cjs/components/FEaaSComponent.js +1 -2
- package/dist/cjs/components/File.js +1 -3
- package/dist/cjs/components/Image.js +1 -0
- package/dist/cjs/components/Link.js +4 -3
- package/dist/cjs/components/RichText.js +8 -4
- package/dist/cjs/components/Text.js +1 -1
- package/dist/cjs/enhancers/withComponentMap.js +1 -3
- package/dist/cjs/enhancers/withEmptyFieldEditingComponent.js +12 -7
- package/dist/cjs/enhancers/withFieldMetadata.js +0 -2
- package/dist/cjs/enhancers/withPlaceholder.js +2 -1
- package/dist/esm/components/Date.js +3 -1
- package/dist/esm/components/DefaultEmptyFieldEditingComponents.js +4 -4
- package/dist/esm/components/DesignLibrary.js +118 -91
- package/dist/esm/components/EditingScripts.js +8 -2
- package/dist/esm/components/FEaaSComponent.js +1 -2
- package/dist/esm/components/File.js +1 -3
- package/dist/esm/components/Image.js +1 -0
- package/dist/esm/components/Link.js +4 -3
- package/dist/esm/components/RichText.js +8 -4
- package/dist/esm/components/Text.js +1 -1
- package/dist/esm/enhancers/withComponentMap.js +1 -3
- package/dist/esm/enhancers/withEmptyFieldEditingComponent.js +12 -7
- package/dist/esm/enhancers/withFieldMetadata.js +0 -2
- package/dist/esm/enhancers/withPlaceholder.js +2 -1
- package/package.json +14 -5
- package/types/components/Date.d.ts +1 -1
- package/types/components/DefaultEmptyFieldEditingComponents.d.ts +8 -2
- package/types/components/DesignLibrary.d.ts +17 -14
- package/types/components/Image.d.ts +1 -1
- package/types/components/Link.d.ts +1 -1
- package/types/components/RichText.d.ts +1 -1
- package/types/components/Text.d.ts +1 -1
- package/types/components/sharedTypes/props.d.ts +2 -2
- package/types/enhancers/withEmptyFieldEditingComponent.d.ts +3 -3
|
@@ -1,57 +1,44 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
/* eslint-disable jsdoc/require-param */
|
|
2
11
|
/* eslint-disable prefer-const */
|
|
3
|
-
import React, { useEffect,
|
|
12
|
+
import React, { useEffect, useState } from 'react';
|
|
4
13
|
import { Placeholder } from './Placeholder';
|
|
5
14
|
import { EDITING_COMPONENT_ID, EDITING_COMPONENT_PLACEHOLDER, } from '@sitecore-content-sdk/core/layout';
|
|
6
15
|
import { DesignLibraryStatus, getDesignLibraryStatusEvent, addComponentUpdateHandler, } from '@sitecore-content-sdk/core/editing';
|
|
7
16
|
import * as codegen from '@sitecore-content-sdk/core/codegen';
|
|
8
17
|
import { useSitecore } from '../enhancers/withSitecore';
|
|
18
|
+
import { PlaceholderMetadata } from './PlaceholderMetadata';
|
|
9
19
|
let { getDesignLibraryImportMapEvent, getDesignLibraryComponentPropsEvent, addComponentPreviewHandler, } = codegen;
|
|
10
20
|
export const __mockDependencies = (mocks) => {
|
|
11
21
|
addComponentPreviewHandler = mocks.addComponentPreviewHandler;
|
|
12
22
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
// useEffect will fire when components are ready - and we inform the whole wide world of it too
|
|
34
|
-
if (!componentReady) {
|
|
35
|
-
componentReady = true;
|
|
36
|
-
window.top.postMessage(getDesignLibraryStatusEvent(DesignLibraryStatus.READY, rootComponent.uid), '*');
|
|
37
|
-
}
|
|
38
|
-
const unsubscribe = addComponentUpdateHandler(persistedRoot, (updatedRoot) => {
|
|
39
|
-
setRootUpdate(Object.assign({}, updatedRoot));
|
|
40
|
-
setRenderKey((key) => key + 1);
|
|
41
|
-
});
|
|
42
|
-
// useEffect will cleanup event handler on re-render
|
|
43
|
-
return unsubscribe;
|
|
44
|
-
}, []);
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
// Send a rendered event only as effect of a component update command
|
|
47
|
-
if (renderKey === 0) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
window.top.postMessage(getDesignLibraryStatusEvent(DesignLibraryStatus.RENDERED, rootComponent.uid), '*');
|
|
51
|
-
}, [renderKey, rootComponent.uid]);
|
|
52
|
-
return (React.createElement(React.Fragment, null,
|
|
53
|
-
React.createElement("main", null,
|
|
54
|
-
React.createElement("div", { id: EDITING_COMPONENT_ID }, route && (React.createElement(Placeholder, { name: EDITING_COMPONENT_PLACEHOLDER, rendering: route, key: renderKey }))))));
|
|
23
|
+
const sendErrorEvent = (uid, error, type) => {
|
|
24
|
+
const errorEvent = codegen.getDesignLibraryComponentPreviewErrorEvent(uid, error, type);
|
|
25
|
+
console.error('Component Library: sending error event', errorEvent);
|
|
26
|
+
if (typeof window !== 'undefined') {
|
|
27
|
+
const target = window.parent && window.parent !== window ? window.parent : window;
|
|
28
|
+
target.postMessage(errorEvent, '*');
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const postToDL = (evt) => {
|
|
32
|
+
if (typeof window === 'undefined')
|
|
33
|
+
return;
|
|
34
|
+
const target = window.parent && window.parent !== window ? window.parent : window;
|
|
35
|
+
try {
|
|
36
|
+
console.log('Component Library: sending event', evt === null || evt === void 0 ? void 0 : evt.name, evt);
|
|
37
|
+
target.postMessage(evt, '*');
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('Component Library: postMessage failed', err, evt);
|
|
41
|
+
}
|
|
55
42
|
};
|
|
56
43
|
class ErrorBoundary extends React.Component {
|
|
57
44
|
constructor() {
|
|
@@ -69,9 +56,7 @@ class ErrorBoundary extends React.Component {
|
|
|
69
56
|
}
|
|
70
57
|
}
|
|
71
58
|
componentDidCatch(error) {
|
|
72
|
-
|
|
73
|
-
console.debug('Component Library: sending error event', errorEvent);
|
|
74
|
-
window.top.postMessage(errorEvent, '*');
|
|
59
|
+
sendErrorEvent(this.props.uid, error, codegen.DesignLibraryPreviewError.Render);
|
|
75
60
|
}
|
|
76
61
|
render() {
|
|
77
62
|
if (this.state.hasError) {
|
|
@@ -81,56 +66,98 @@ class ErrorBoundary extends React.Component {
|
|
|
81
66
|
}
|
|
82
67
|
}
|
|
83
68
|
/**
|
|
84
|
-
*
|
|
85
|
-
*
|
|
69
|
+
* Design Library component.
|
|
70
|
+
*
|
|
71
|
+
* Renders the **real** Sitecore component for `library` / `library-metadata` modes and,
|
|
72
|
+
* when generation is enabled (`page.mode.designLibrary.isVariantGeneration === true`),
|
|
73
|
+
* wires the **variant generation** handshake so the parent (DL Studio) can send
|
|
74
|
+
* generated code to preview and iterate on.
|
|
75
|
+
* @param {DesignLibraryProps} props
|
|
76
|
+
* @param {() => Promise<{ default: import('../codegen').ImportEntry[] }>} [props.loadImportMap] Optional async loader that resolves to the import-map used to resolve the generated component’s imports. Required when `isVariantGeneration` is true.
|
|
77
|
+
* @returns {JSX.Element} The preview surface, or `null` when not in Design Library mode.
|
|
86
78
|
*/
|
|
87
|
-
export const
|
|
79
|
+
export const DesignLibrary = ({ loadImportMap }) => {
|
|
80
|
+
var _a, _b;
|
|
88
81
|
const { page } = useSitecore();
|
|
89
|
-
const
|
|
90
|
-
const rendering = route === null || route === void 0 ? void 0 : route.placeholders[EDITING_COMPONENT_PLACEHOLDER][0];
|
|
82
|
+
const route = page.layout.sitecore.route;
|
|
83
|
+
const rendering = (_a = route === null || route === void 0 ? void 0 : route.placeholders[EDITING_COMPONENT_PLACEHOLDER]) === null || _a === void 0 ? void 0 : _a[0];
|
|
84
|
+
const { isDesignLibrary } = page.mode;
|
|
85
|
+
const isVariantGeneration = (_b = page.mode.designLibrary) === null || _b === void 0 ? void 0 : _b.isVariantGeneration;
|
|
86
|
+
const [propsState, setPropsState] = useState({
|
|
87
|
+
fields: rendering === null || rendering === void 0 ? void 0 : rendering.fields,
|
|
88
|
+
params: rendering === null || rendering === void 0 ? void 0 : rendering.params,
|
|
89
|
+
});
|
|
91
90
|
const [renderKey, setRenderKey] = useState(0);
|
|
92
|
-
const [initError, setInitError] = useState(false);
|
|
93
91
|
const [Component, setComponent] = useState(null);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return React.createElement("div", null, "No component found in layout data. Please check your layout data.");
|
|
99
|
-
}
|
|
92
|
+
const isGeneratedComponentActive = !!Component;
|
|
93
|
+
if (!isDesignLibrary)
|
|
94
|
+
return null;
|
|
95
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
100
96
|
useEffect(() => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
postToDL(getDesignLibraryStatusEvent(DesignLibraryStatus.READY, rendering.uid));
|
|
98
|
+
if (!isVariantGeneration) {
|
|
99
|
+
requestAnimationFrame(() => {
|
|
100
|
+
setRenderKey((k) => (k === 0 ? k + 1 : k));
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const unsubUpdate = addComponentUpdateHandler(rendering, (updated) => {
|
|
104
|
+
setPropsState({ fields: updated.fields, params: updated.params });
|
|
105
|
+
setRenderKey((k) => k + 1);
|
|
106
|
+
});
|
|
107
|
+
// useEffect will cleanup event handler on re-render
|
|
108
|
+
return () => unsubUpdate && unsubUpdate();
|
|
109
|
+
}, [isVariantGeneration, rendering]);
|
|
110
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
// Send a rendered event only as effect of a component update command
|
|
113
|
+
if (renderKey === 0)
|
|
114
|
+
return;
|
|
115
|
+
postToDL(getDesignLibraryStatusEvent(DesignLibraryStatus.RENDERED, rendering.uid));
|
|
116
|
+
}, [renderKey, rendering]);
|
|
117
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!isDesignLibrary || !isVariantGeneration)
|
|
120
|
+
return undefined;
|
|
121
|
+
let cancelled = false;
|
|
122
|
+
// since import map is loaded lazily, we only need to add preview event handler once the import map is loaded
|
|
123
|
+
// unsubscribe function for useEffect cleanup will also be returned once importMap promise has been resolved or rejected
|
|
124
|
+
let unsubscribe;
|
|
125
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
126
|
+
if (!loadImportMap) {
|
|
127
|
+
sendErrorEvent(rendering.uid, 'No loadImportMap provided', codegen.DesignLibraryPreviewError.RenderInit);
|
|
105
128
|
return;
|
|
106
129
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
let importMap;
|
|
131
|
+
try {
|
|
132
|
+
const mod = yield loadImportMap();
|
|
133
|
+
importMap = mod.default;
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
sendErrorEvent(rendering.uid, `Error loading import map: ${e}`, codegen.DesignLibraryPreviewError.RenderInit);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// account for component being unmounted while resolving async import map
|
|
140
|
+
if (cancelled)
|
|
141
|
+
return;
|
|
142
|
+
unsubscribe = addComponentPreviewHandler(importMap, (error, Component) => {
|
|
143
|
+
// Error event is already sent in the addComponentPreviewHandler
|
|
144
|
+
if (error)
|
|
145
|
+
return;
|
|
146
|
+
setComponent(() => Component);
|
|
147
|
+
setRenderKey((k) => k + 1);
|
|
148
|
+
});
|
|
149
|
+
const importMapEvent = getDesignLibraryImportMapEvent(rendering.uid, importMap);
|
|
150
|
+
postToDL(importMapEvent);
|
|
151
|
+
const propsEvent = getDesignLibraryComponentPropsEvent(rendering.uid, propsState.fields, propsState.params);
|
|
152
|
+
postToDL(propsEvent);
|
|
153
|
+
}))();
|
|
154
|
+
// return function that calls unsubscribe - if the component was mounted correctly
|
|
155
|
+
return () => {
|
|
156
|
+
cancelled = true;
|
|
157
|
+
unsubscribe && unsubscribe();
|
|
158
|
+
};
|
|
159
|
+
}, [isVariantGeneration, rendering]);
|
|
160
|
+
return (React.createElement("main", null, isGeneratedComponentActive ? (React.createElement(ErrorBoundary, { uid: rendering.uid, renderKey: renderKey },
|
|
161
|
+
React.createElement(PlaceholderMetadata, { rendering: rendering },
|
|
162
|
+
React.createElement(Component, { fields: propsState.fields, params: propsState.params, key: renderKey })))) : (React.createElement("div", { id: EDITING_COMPONENT_ID }, route && (React.createElement(Placeholder, { name: EDITING_COMPONENT_PLACEHOLDER, rendering: route, key: renderKey }))))));
|
|
136
163
|
};
|
|
@@ -17,8 +17,14 @@ export const EditingScripts = () => {
|
|
|
17
17
|
}
|
|
18
18
|
// In case of Design Library - render only the script for Design Library
|
|
19
19
|
if (mode.isDesignLibrary) {
|
|
20
|
-
// Add cache buster to the script URL
|
|
21
|
-
const
|
|
20
|
+
// Add cache buster to the script URL (format hh-dd-mm-yyyy, UTC)
|
|
21
|
+
const now = new Date();
|
|
22
|
+
const hour = String(now.getUTCHours()).padStart(2, '0');
|
|
23
|
+
const day = String(now.getUTCDate()).padStart(2, '0');
|
|
24
|
+
const month = String(now.getUTCMonth() + 1).padStart(2, '0');
|
|
25
|
+
const year = String(now.getUTCFullYear());
|
|
26
|
+
const cacheTimestamp = `${hour}-${day}-${month}-${year}`;
|
|
27
|
+
const scriptUrl = `${getDesignLibraryScriptLink((_a = api === null || api === void 0 ? void 0 : api.edge) === null || _a === void 0 ? void 0 : _a.edgeUrl)}?cb=${cacheTimestamp}`;
|
|
22
28
|
return (React.createElement(React.Fragment, null,
|
|
23
29
|
React.createElement("script", { src: scriptUrl, suppressHydrationWarning: true })));
|
|
24
30
|
}
|
|
@@ -78,8 +78,7 @@ function fetchComponentTemplate(src, params, revisionFallback) {
|
|
|
78
78
|
return template;
|
|
79
79
|
}
|
|
80
80
|
catch (error) {
|
|
81
|
-
console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision ||
|
|
82
|
-
revisionFallback}" is present`);
|
|
81
|
+
console.error(`Fetch FEAAS component from ${src} failed. Ensure the component revision "${params.ComponentRevision || revisionFallback}" is present`);
|
|
83
82
|
throw error;
|
|
84
83
|
}
|
|
85
84
|
});
|
|
@@ -18,9 +18,7 @@ export const File = (_a) => {
|
|
|
18
18
|
return null;
|
|
19
19
|
}
|
|
20
20
|
// handle link directly on field for forgetful devs
|
|
21
|
-
const file = (dynamicField.src
|
|
22
|
-
? field
|
|
23
|
-
: dynamicField.value);
|
|
21
|
+
const file = (dynamicField.src ? field : dynamicField.value);
|
|
24
22
|
if (!file) {
|
|
25
23
|
return null;
|
|
26
24
|
}
|
|
@@ -9,14 +9,15 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
+
/* eslint-disable no-unused-expressions, @typescript-eslint/no-unused-expressions */
|
|
12
13
|
import React, { forwardRef } from 'react';
|
|
13
14
|
import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
|
|
14
15
|
import { withFieldMetadata } from '../enhancers/withFieldMetadata';
|
|
15
16
|
import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
|
|
16
17
|
import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
|
|
17
|
-
export const Link = withFieldMetadata(withEmptyFieldEditingComponent(
|
|
18
|
-
// eslint-disable-next-line
|
|
19
|
-
|
|
18
|
+
export const Link = withFieldMetadata(withEmptyFieldEditingComponent(forwardRef(
|
|
19
|
+
// eslint-disable-next-line no-unused-vars
|
|
20
|
+
(_a, ref) => {
|
|
20
21
|
var { field, editable = true, showLinkTextWithChildrenPresent } = _a, otherProps = __rest(_a, ["field", "editable", "showLinkTextWithChildrenPresent"]);
|
|
21
22
|
const children = otherProps.children;
|
|
22
23
|
const dynamicField = field;
|
|
@@ -14,10 +14,14 @@ import { withFieldMetadata } from '../enhancers/withFieldMetadata';
|
|
|
14
14
|
import { withEmptyFieldEditingComponent } from '../enhancers/withEmptyFieldEditingComponent';
|
|
15
15
|
import { DefaultEmptyFieldEditingComponentText } from './DefaultEmptyFieldEditingComponents';
|
|
16
16
|
import { isFieldValueEmpty } from '@sitecore-content-sdk/core/layout';
|
|
17
|
-
export const RichText = withFieldMetadata(withEmptyFieldEditingComponent(
|
|
18
|
-
// eslint-disable-next-line
|
|
19
|
-
|
|
20
|
-
var
|
|
17
|
+
export const RichText = withFieldMetadata(withEmptyFieldEditingComponent(forwardRef((
|
|
18
|
+
// eslint-disable-next-line no-unused-vars
|
|
19
|
+
_a, ref) => {
|
|
20
|
+
var
|
|
21
|
+
// eslint-disable-next-line no-unused-vars
|
|
22
|
+
{ field, tag = 'div', editable = true } = _a, otherProps = __rest(_a,
|
|
23
|
+
// eslint-disable-next-line no-unused-vars
|
|
24
|
+
["field", "tag", "editable"]);
|
|
21
25
|
if (isFieldValueEmpty(field)) {
|
|
22
26
|
return null;
|
|
23
27
|
}
|
|
@@ -21,7 +21,7 @@ export const Text = withFieldMetadata(withEmptyFieldEditingComponent((_a) => {
|
|
|
21
21
|
}
|
|
22
22
|
// can't use editable value if we want to output unencoded
|
|
23
23
|
if (!encode) {
|
|
24
|
-
// eslint-disable-next-line no-param-reassign
|
|
24
|
+
// eslint-disable-next-line no-param-reassign, no-unused-vars
|
|
25
25
|
editable = false;
|
|
26
26
|
}
|
|
27
27
|
let output = field.value === undefined ? '' : field.value;
|
|
@@ -13,8 +13,6 @@ export function withComponentMap(Component) {
|
|
|
13
13
|
const context = useContext(ComponentMapReactContext);
|
|
14
14
|
return React.createElement(Component, Object.assign({}, props, { componentMap: props.componentMap || context }));
|
|
15
15
|
}
|
|
16
|
-
WithComponentMap.displayName = `withComponentMap(${Component.displayName ||
|
|
17
|
-
Component.name ||
|
|
18
|
-
'Anonymous'})`;
|
|
16
|
+
WithComponentMap.displayName = `withComponentMap(${Component.displayName || Component.name || 'Anonymous'})`;
|
|
19
17
|
return WithComponentMap;
|
|
20
18
|
}
|
|
@@ -10,20 +10,25 @@ export function withEmptyFieldEditingComponent(FieldComponent, options) {
|
|
|
10
10
|
var _a;
|
|
11
11
|
const { editable = true } = props;
|
|
12
12
|
if (((_a = props.field) === null || _a === void 0 ? void 0 : _a.metadata) && editable && isFieldValueEmpty(props.field)) {
|
|
13
|
-
|
|
13
|
+
const Component = props.emptyFieldEditingComponent || options.defaultEmptyFieldEditingComponent;
|
|
14
|
+
let resolvedProps = props;
|
|
15
|
+
// If no custom empty field editing component is provided, we can omit unnecessary props
|
|
16
|
+
// to do not insert them to html
|
|
17
|
+
if (!props.emptyFieldEditingComponent) {
|
|
18
|
+
resolvedProps = Object.assign(Object.assign({}, props), { editable: undefined, field: undefined });
|
|
19
|
+
}
|
|
20
|
+
return React.createElement(Component, Object.assign({}, resolvedProps));
|
|
14
21
|
}
|
|
15
22
|
return null;
|
|
16
23
|
};
|
|
17
24
|
if (options.isForwardRef) {
|
|
18
|
-
// eslint-disable-next-line react/display-name
|
|
19
25
|
return forwardRef((props, ref) => {
|
|
20
|
-
const
|
|
21
|
-
return (
|
|
26
|
+
const emptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
|
|
27
|
+
return (emptyFieldEditingComponent || (React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }))));
|
|
22
28
|
});
|
|
23
29
|
}
|
|
24
|
-
// eslint-disable-next-line react/display-name
|
|
25
30
|
return (props) => {
|
|
26
|
-
const
|
|
27
|
-
return
|
|
31
|
+
const emptyFieldEditingComponent = getEmptyFieldEditingComponent(props);
|
|
32
|
+
return emptyFieldEditingComponent || React.createElement(FieldComponent, Object.assign({}, props));
|
|
28
33
|
};
|
|
29
34
|
}
|
|
@@ -7,7 +7,6 @@ import { FieldMetadata } from '../components/FieldMetadata';
|
|
|
7
7
|
*/
|
|
8
8
|
export function withFieldMetadata(FieldComponent, isForwardRef = false) {
|
|
9
9
|
if (isForwardRef) {
|
|
10
|
-
// eslint-disable-next-line react/display-name
|
|
11
10
|
return forwardRef((props, ref) => {
|
|
12
11
|
var _a;
|
|
13
12
|
const { editable = true } = props;
|
|
@@ -19,7 +18,6 @@ export function withFieldMetadata(FieldComponent, isForwardRef = false) {
|
|
|
19
18
|
React.createElement(FieldComponent, Object.assign({}, props, { ref: ref }))));
|
|
20
19
|
});
|
|
21
20
|
}
|
|
22
|
-
// eslint-disable-next-line react/display-name
|
|
23
21
|
return (props) => {
|
|
24
22
|
var _a;
|
|
25
23
|
const { editable = true } = props;
|
|
@@ -44,7 +44,8 @@ export function withPlaceholder(placeholders, options) {
|
|
|
44
44
|
else {
|
|
45
45
|
placeholderData = PlaceholderCommon.getPlaceholderDataFromRenderingData(renderingData, placeholder, childProps.page.mode.isEditing);
|
|
46
46
|
if (placeholderData) {
|
|
47
|
-
childProps[placeholder] =
|
|
47
|
+
childProps[placeholder] =
|
|
48
|
+
this.getComponentsForRenderingData(placeholderData);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitecore-content-sdk/react",
|
|
3
|
-
"version": "1.1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@sitecore-feaas/clientside": "^0.6.0",
|
|
34
|
+
"@stylistic/eslint-plugin": "^5.2.2",
|
|
34
35
|
"@testing-library/dom": "^10.4.0",
|
|
35
36
|
"@testing-library/react": "^16.3.0",
|
|
36
37
|
"@types/chai": "^5.2.2",
|
|
@@ -41,14 +42,22 @@
|
|
|
41
42
|
"@types/react-dom": "^19.1.3",
|
|
42
43
|
"@types/sinon": "^17.0.4",
|
|
43
44
|
"@types/sinon-chai": "^4.0.0",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "8.39.0",
|
|
46
|
+
"@typescript-eslint/parser": "8.39.0",
|
|
44
47
|
"chai": "^4.3.7",
|
|
45
48
|
"chai-string": "^1.6.0",
|
|
46
49
|
"del-cli": "^6.0.0",
|
|
47
|
-
"eslint": "^
|
|
48
|
-
"eslint-
|
|
50
|
+
"eslint": "^9.32.0",
|
|
51
|
+
"eslint-config-prettier": "^10.1.8",
|
|
52
|
+
"eslint-plugin-import": "2.32.0",
|
|
53
|
+
"eslint-plugin-jsdoc": "52.0.3",
|
|
54
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
55
|
+
"eslint-plugin-react": "7.37.5",
|
|
56
|
+
"eslint-plugin-react-hooks": "5.2.0",
|
|
49
57
|
"jsdom": "^26.1.0",
|
|
50
58
|
"mocha": "^11.2.2",
|
|
51
59
|
"nyc": "^17.1.0",
|
|
60
|
+
"prettier": "^2.8.0",
|
|
52
61
|
"react": "^19.1.0",
|
|
53
62
|
"react-dom": "^19.1.0",
|
|
54
63
|
"sinon": "^20.0.0",
|
|
@@ -63,12 +72,12 @@
|
|
|
63
72
|
"react-dom": "^19.1.0"
|
|
64
73
|
},
|
|
65
74
|
"dependencies": {
|
|
66
|
-
"@sitecore-content-sdk/core": "1.1.0
|
|
75
|
+
"@sitecore-content-sdk/core": "1.1.0",
|
|
67
76
|
"fast-deep-equal": "^3.1.3"
|
|
68
77
|
},
|
|
69
78
|
"description": "",
|
|
70
79
|
"types": "types/index.d.ts",
|
|
71
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "0e6485c5849123ad20a7562750b2fe6cb44ae617",
|
|
72
81
|
"files": [
|
|
73
82
|
"dist",
|
|
74
83
|
"types"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { EditableFieldProps } from './sharedTypes';
|
|
3
3
|
import { FieldMetadata } from '@sitecore-content-sdk/core/layout';
|
|
4
|
-
export interface DateFieldProps extends EditableFieldProps {
|
|
4
|
+
export interface DateFieldProps extends EditableFieldProps<DateFieldProps> {
|
|
5
5
|
/** The date field data. */
|
|
6
6
|
[htmlAttributes: string]: unknown;
|
|
7
7
|
field: FieldMetadata & {
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare const DefaultEmptyFieldEditingComponentText: React.FC
|
|
3
|
-
|
|
2
|
+
export declare const DefaultEmptyFieldEditingComponentText: React.FC<{
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
tag?: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const DefaultEmptyFieldEditingComponentImage: React.FC<{
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
className?: string;
|
|
9
|
+
}>;
|
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import * as codegen from '@sitecore-content-sdk/core/codegen';
|
|
3
3
|
export declare const __mockDependencies: (mocks: any) => void;
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
* The import map to be used in variant generation mode.
|
|
7
|
-
*/
|
|
8
|
-
importMap?: codegen.ImportEntry[];
|
|
4
|
+
export type ImportMapImport = {
|
|
5
|
+
default: codegen.ImportEntry[];
|
|
9
6
|
};
|
|
10
|
-
/**
|
|
11
|
-
* This component is used to render the component in variant generation mode.
|
|
12
|
-
* It is used to send the import-map and component-props events to the parent window and render the dynamic component.
|
|
13
|
-
*/
|
|
14
|
-
export declare const VariantGeneration: (props: VariantGenerationProps) => JSX.Element;
|
|
15
7
|
type DesignLibraryProps = {
|
|
16
8
|
/**
|
|
17
|
-
* The import map to be used in variant generation mode.
|
|
9
|
+
* The dynamic import for import map to be used in variant generation mode.
|
|
18
10
|
* Currently it's optional but it will be required in the next major version.
|
|
19
11
|
*/
|
|
20
|
-
|
|
12
|
+
loadImportMap?: () => Promise<ImportMapImport>;
|
|
21
13
|
};
|
|
22
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Design Library component.
|
|
16
|
+
*
|
|
17
|
+
* Renders the **real** Sitecore component for `library` / `library-metadata` modes and,
|
|
18
|
+
* when generation is enabled (`page.mode.designLibrary.isVariantGeneration === true`),
|
|
19
|
+
* wires the **variant generation** handshake so the parent (DL Studio) can send
|
|
20
|
+
* generated code to preview and iterate on.
|
|
21
|
+
* @param {DesignLibraryProps} props
|
|
22
|
+
* @param {() => Promise<{ default: import('../codegen').ImportEntry[] }>} [props.loadImportMap] Optional async loader that resolves to the import-map used to resolve the generated component’s imports. Required when `isVariantGeneration` is true.
|
|
23
|
+
* @returns {JSX.Element} The preview surface, or `null` when not in Design Library mode.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DesignLibrary: ({ loadImportMap }: DesignLibraryProps) => React.JSX.Element;
|
|
23
26
|
export {};
|
|
@@ -25,7 +25,7 @@ export interface ImageSizeParameters {
|
|
|
25
25
|
/** Image scale. Defaults to 1.0 */
|
|
26
26
|
sc?: number;
|
|
27
27
|
}
|
|
28
|
-
export interface ImageProps extends EditableFieldProps {
|
|
28
|
+
export interface ImageProps extends EditableFieldProps<ImageProps> {
|
|
29
29
|
[attributeName: string]: unknown;
|
|
30
30
|
/** Image field data (consistent with other field types) */
|
|
31
31
|
field?: (ImageField | ImageFieldValue) & FieldMetadata;
|
|
@@ -16,7 +16,7 @@ export interface LinkFieldValue {
|
|
|
16
16
|
export interface LinkField {
|
|
17
17
|
value: LinkFieldValue;
|
|
18
18
|
}
|
|
19
|
-
export type LinkProps = EditableFieldProps & React.AnchorHTMLAttributes<HTMLAnchorElement> & RefAttributes<HTMLAnchorElement> & {
|
|
19
|
+
export type LinkProps = EditableFieldProps<LinkProps> & React.AnchorHTMLAttributes<HTMLAnchorElement> & RefAttributes<HTMLAnchorElement> & {
|
|
20
20
|
/** The link field data. */
|
|
21
21
|
field: (LinkField | LinkFieldValue) & FieldMetadata;
|
|
22
22
|
/**
|
|
@@ -4,7 +4,7 @@ import { FieldMetadata } from '@sitecore-content-sdk/core/layout';
|
|
|
4
4
|
export interface RichTextField extends FieldMetadata {
|
|
5
5
|
value?: string;
|
|
6
6
|
}
|
|
7
|
-
export interface RichTextProps extends EditableFieldProps {
|
|
7
|
+
export interface RichTextProps extends EditableFieldProps<RichTextProps> {
|
|
8
8
|
[htmlAttributes: string]: unknown;
|
|
9
9
|
/** The rich text field data. */
|
|
10
10
|
field?: RichTextField;
|
|
@@ -4,7 +4,7 @@ import { FieldMetadata } from '@sitecore-content-sdk/core/layout';
|
|
|
4
4
|
export interface TextField extends FieldMetadata {
|
|
5
5
|
value?: string | number;
|
|
6
6
|
}
|
|
7
|
-
export interface TextProps extends EditableFieldProps {
|
|
7
|
+
export interface TextProps extends EditableFieldProps<TextProps> {
|
|
8
8
|
[htmlAttributes: string]: unknown;
|
|
9
9
|
/** The text field data. */
|
|
10
10
|
field?: TextField;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared editing field props
|
|
3
3
|
*/
|
|
4
|
-
export interface EditableFieldProps {
|
|
4
|
+
export interface EditableFieldProps<EmptyFieldEditingComponentProps = unknown> {
|
|
5
5
|
/**
|
|
6
6
|
* Can be used to explicitly disable inline editing.
|
|
7
7
|
* @default true
|
|
@@ -10,5 +10,5 @@ export interface EditableFieldProps {
|
|
|
10
10
|
/**
|
|
11
11
|
* Custom element to render in Pages in edit mode if field value is empty
|
|
12
12
|
*/
|
|
13
|
-
emptyFieldEditingComponent?: React.ComponentClass<
|
|
13
|
+
emptyFieldEditingComponent?: React.ComponentClass<EmptyFieldEditingComponentProps> | React.FC<EmptyFieldEditingComponentProps>;
|
|
14
14
|
}
|
|
@@ -13,15 +13,15 @@ export interface WithEmptyFieldEditingComponentOptions {
|
|
|
13
13
|
*/
|
|
14
14
|
isForwardRef?: boolean;
|
|
15
15
|
}
|
|
16
|
-
interface WithEmptyFieldEditingComponentProps {
|
|
16
|
+
interface WithEmptyFieldEditingComponentProps<Props> {
|
|
17
17
|
field?: (Partial<Field> | GenericFieldValue) & FieldMetadata;
|
|
18
18
|
editable?: boolean;
|
|
19
|
-
emptyFieldEditingComponent?: React.ComponentClass | React.FC
|
|
19
|
+
emptyFieldEditingComponent?: React.ComponentClass<Props> | React.FC<Props>;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Returns the passed field component or default component in case field value is empty and edit mode is 'metadata'
|
|
23
23
|
* @param {ComponentType<FieldComponentProps>} FieldComponent the field component
|
|
24
24
|
* @param {WithEmptyFieldEditingComponentProps} options the options of the HOC;
|
|
25
25
|
*/
|
|
26
|
-
export declare function withEmptyFieldEditingComponent<FieldComponentProps extends WithEmptyFieldEditingComponentProps
|
|
26
|
+
export declare function withEmptyFieldEditingComponent<FieldComponentProps extends WithEmptyFieldEditingComponentProps<FieldComponentProps>, RefElementType = HTMLElement>(FieldComponent: ComponentType<FieldComponentProps>, options: WithEmptyFieldEditingComponentOptions): React.ForwardRefExoticComponent<React.PropsWithoutRef<FieldComponentProps> & React.RefAttributes<RefElementType>> | ((props: FieldComponentProps) => React.JSX.Element);
|
|
27
27
|
export {};
|