@uniformdev/canvas-react 17.7.1-alpha.34 → 18.0.1-alpha.3
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 +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.esm.js +455 -1
- package/dist/index.js +482 -1
- package/dist/index.mjs +455 -1
- package/package.json +6 -6
package/LICENSE.txt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
©
|
|
1
|
+
© 2023 Uniform Systems, Inc. All Rights Reserved.
|
|
2
2
|
See details of Uniform Systems, Inc. Master Subscription Agreement here: https://uniform.dev/eula
|
package/dist/index.d.ts
CHANGED
|
@@ -6,22 +6,22 @@ import React$1, { Key, ReactNode } from 'react';
|
|
|
6
6
|
* TProps is the Canvas component's parameters object after
|
|
7
7
|
* all enhancers have been applied.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
type ComponentProps<TProps = unknown> = TProps & {
|
|
10
10
|
component: ComponentInstance;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
13
|
* Function that maps a Canvas component instance to its React component to render it.
|
|
14
14
|
* The resolver would commonly inspect the `type` and possibly `variant` of the component to decide.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
type RenderComponentResolver = (component: ComponentInstance) => React.ComponentType<ComponentProps<any>> | null;
|
|
17
17
|
/** Function that renders Canvas system internals */
|
|
18
|
-
|
|
18
|
+
type SystemRenderFunction = (component: ComponentInstance, key: Key, renderChild: (component: ComponentInstance, key: Key) => JSX.Element | null) => JSX.Element | null;
|
|
19
19
|
/** Configures rendering of system components (tests, pz) */
|
|
20
|
-
|
|
20
|
+
type SystemRenderConfig = {
|
|
21
21
|
test: SystemRenderFunction;
|
|
22
22
|
personalization: SystemRenderFunction;
|
|
23
23
|
};
|
|
24
|
-
|
|
24
|
+
type ComponentStore = {
|
|
25
25
|
register: (options: {
|
|
26
26
|
type: string;
|
|
27
27
|
component: React.ComponentType<ComponentProps<any>>;
|
|
@@ -29,7 +29,7 @@ declare type ComponentStore = {
|
|
|
29
29
|
get: (name: string) => React.ComponentType<ComponentProps<any>> | undefined;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
type CompositionProps<TRenderProps = unknown> = {
|
|
33
33
|
/** The root component in the composition */
|
|
34
34
|
data: ComponentInstance;
|
|
35
35
|
/** Resolves a React component to render a Canvas component, generally by inspecting type/variant */
|
|
@@ -48,7 +48,7 @@ declare type CompositionProps<TRenderProps = unknown> = {
|
|
|
48
48
|
*/
|
|
49
49
|
behaviorTracking?: 'onLoad' | 'onView';
|
|
50
50
|
};
|
|
51
|
-
|
|
51
|
+
type CompositionContext = {
|
|
52
52
|
/** The parent composition */
|
|
53
53
|
composition: ComponentInstance;
|
|
54
54
|
/** The current function to translate component data into React components */
|
|
@@ -71,12 +71,12 @@ declare function Composition<TRenderProps = unknown>({ data, resolveRenderer, ch
|
|
|
71
71
|
**/
|
|
72
72
|
declare function DefaultNotImplementedComponent(props: ComponentProps): JSX.Element | null;
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
type CustomSlotChildRenderFunc = (options: {
|
|
75
75
|
child: ReactNode;
|
|
76
76
|
component: ComponentInstance;
|
|
77
77
|
key: Key;
|
|
78
78
|
}) => JSX.Element;
|
|
79
|
-
|
|
79
|
+
type SlotProps<TSlotNames extends string> = {
|
|
80
80
|
/** Name of the slot to render */
|
|
81
81
|
name: TSlotNames;
|
|
82
82
|
/**
|
|
@@ -96,7 +96,7 @@ declare type SlotProps<TSlotNames extends string> = {
|
|
|
96
96
|
/** Renders a named Slot within a Composition. */
|
|
97
97
|
declare function Slot<TSlotNames extends string = string>({ name, resolveRenderer, children, emptyPlaceholder, }: SlotProps<TSlotNames>): JSX.Element | null;
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
type UseCompositionEventEffectOptions = Omit<Partial<SubscribeToCompositionOptions>, 'callback'> & {
|
|
100
100
|
enabled: boolean;
|
|
101
101
|
effect: () => void;
|
|
102
102
|
};
|
package/dist/index.esm.js
CHANGED
|
@@ -1 +1,455 @@
|
|
|
1
|
-
|
|
1
|
+
// src/components/Composition.tsx
|
|
2
|
+
import { CANVAS_ENRICHMENT_TAG_PARAM } from "@uniformdev/canvas";
|
|
3
|
+
import { Track, TrackFragment, useUniformContext } from "@uniformdev/context-react";
|
|
4
|
+
import React3, { createContext, useContext } from "react";
|
|
5
|
+
|
|
6
|
+
// src/convertComponentToProps.ts
|
|
7
|
+
function convertComponentToProps(component) {
|
|
8
|
+
var _a;
|
|
9
|
+
const parameters = (_a = component.parameters) != null ? _a : {};
|
|
10
|
+
const renderComponentProps = {
|
|
11
|
+
...Object.keys(parameters).reduce((acc, cur) => {
|
|
12
|
+
acc[cur] = parameters[cur].value;
|
|
13
|
+
return acc;
|
|
14
|
+
}, {}),
|
|
15
|
+
...component.data,
|
|
16
|
+
component
|
|
17
|
+
};
|
|
18
|
+
return renderComponentProps;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/storeDefinition.ts
|
|
22
|
+
var createComponentStore = () => {
|
|
23
|
+
const components = /* @__PURE__ */ new Map();
|
|
24
|
+
return {
|
|
25
|
+
register: ({ type, component }) => {
|
|
26
|
+
components.set(type, component);
|
|
27
|
+
},
|
|
28
|
+
get: (name) => {
|
|
29
|
+
return components.get(name);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
var createComponentStoreResolver = (options) => {
|
|
34
|
+
return (component) => {
|
|
35
|
+
const resolved = options.store.get(component.type);
|
|
36
|
+
return resolved || options.defaultComponent || null;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/store.ts
|
|
41
|
+
var componentStore = createComponentStore();
|
|
42
|
+
var registerUniformComponent = ({
|
|
43
|
+
type,
|
|
44
|
+
component
|
|
45
|
+
}) => {
|
|
46
|
+
if (Array.isArray(type)) {
|
|
47
|
+
type.forEach((t) => {
|
|
48
|
+
componentStore.register({
|
|
49
|
+
type: t,
|
|
50
|
+
component
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
componentStore.register({
|
|
55
|
+
type,
|
|
56
|
+
component
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var componentStoreResolver = createComponentStoreResolver({
|
|
61
|
+
store: componentStore
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// src/components/Slot.tsx
|
|
65
|
+
import {
|
|
66
|
+
CANVAS_LOCALE_TAG_PARAM,
|
|
67
|
+
CANVAS_PERSONALIZE_TYPE,
|
|
68
|
+
CANVAS_TEST_TYPE,
|
|
69
|
+
IN_CONTEXT_EDITOR_COMPONENT_START_ROLE,
|
|
70
|
+
PLACEHOLDER_ID
|
|
71
|
+
} from "@uniformdev/canvas";
|
|
72
|
+
import React2 from "react";
|
|
73
|
+
|
|
74
|
+
// src/defaultSystemComponentResolver.tsx
|
|
75
|
+
import {
|
|
76
|
+
mapSlotToPersonalizedVariations,
|
|
77
|
+
mapSlotToTestVariations
|
|
78
|
+
} from "@uniformdev/canvas";
|
|
79
|
+
import { Personalize, Test } from "@uniformdev/context-react";
|
|
80
|
+
import * as React from "react";
|
|
81
|
+
var defaultSystemComponentResolver = {
|
|
82
|
+
test: (component, key, renderChild) => {
|
|
83
|
+
var _a, _b, _c, _d, _e;
|
|
84
|
+
const testComponent = component;
|
|
85
|
+
const variants = (_b = (_a = testComponent.slots) == null ? void 0 : _a.test) != null ? _b : [];
|
|
86
|
+
const testName = (_e = (_d = (_c = testComponent.parameters) == null ? void 0 : _c.test) == null ? void 0 : _d.value) != null ? _e : "Untitled Test";
|
|
87
|
+
const finalVariants = mapSlotToTestVariations(variants);
|
|
88
|
+
return /* @__PURE__ */ React.createElement(
|
|
89
|
+
Test,
|
|
90
|
+
{
|
|
91
|
+
key,
|
|
92
|
+
variations: finalVariants,
|
|
93
|
+
name: testName,
|
|
94
|
+
component: (variation) => renderChild(variation, key)
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
personalization: (component, key, renderChild) => {
|
|
99
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
100
|
+
const pzComponent = component;
|
|
101
|
+
const processedVariants = mapSlotToPersonalizedVariations((_a = pzComponent == null ? void 0 : pzComponent.slots) == null ? void 0 : _a.pz);
|
|
102
|
+
return /* @__PURE__ */ React.createElement(
|
|
103
|
+
Personalize,
|
|
104
|
+
{
|
|
105
|
+
key,
|
|
106
|
+
variations: processedVariants,
|
|
107
|
+
count: Number((_d = (_c = (_b = pzComponent.parameters) == null ? void 0 : _b.count) == null ? void 0 : _c.value) != null ? _d : 1),
|
|
108
|
+
name: (_g = (_f = (_e = pzComponent.parameters) == null ? void 0 : _e.trackingEventName) == null ? void 0 : _f.value) != null ? _g : "Untitled Personalization",
|
|
109
|
+
component: (variation) => renderChild(variation, 0)
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/components/Slot.tsx
|
|
116
|
+
function Slot({
|
|
117
|
+
name,
|
|
118
|
+
resolveRenderer,
|
|
119
|
+
children,
|
|
120
|
+
emptyPlaceholder
|
|
121
|
+
}) {
|
|
122
|
+
var _a;
|
|
123
|
+
const compositionContext = useComposition();
|
|
124
|
+
if (!(compositionContext == null ? void 0 : compositionContext.composition)) {
|
|
125
|
+
throw new Error("Slot must be rendered within a Composition");
|
|
126
|
+
}
|
|
127
|
+
const { composition: layout, resolveRenderer: parentResolveRenderer } = compositionContext;
|
|
128
|
+
if (!layout) {
|
|
129
|
+
throw new Error("Cannot use Slot without a Composition wrapper.");
|
|
130
|
+
}
|
|
131
|
+
const slot = (_a = layout.slots) == null ? void 0 : _a[name];
|
|
132
|
+
if (!slot || !Array.isArray(slot)) {
|
|
133
|
+
if (process.env.NODE_ENV === "development") {
|
|
134
|
+
console.warn(
|
|
135
|
+
`[canvas-dev] slot '${name}' was rendered, but it was not defined on its component. This is expected if the slot is optional, otherwise it may indicate a typo. Component:`,
|
|
136
|
+
layout
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const resolver = resolveRenderer != null ? resolveRenderer : parentResolveRenderer;
|
|
142
|
+
const systemResolver = defaultSystemComponentResolver;
|
|
143
|
+
const finalChildren = slot.map((component, index) => {
|
|
144
|
+
const child = renderComponent({
|
|
145
|
+
component,
|
|
146
|
+
resolveRenderer: resolver,
|
|
147
|
+
resolveSystem: systemResolver,
|
|
148
|
+
key: `inner-${index}`,
|
|
149
|
+
indexInSlot: index,
|
|
150
|
+
slotName: name,
|
|
151
|
+
parentComponent: layout,
|
|
152
|
+
slotChildrenCount: slot.length,
|
|
153
|
+
emptyPlaceholder
|
|
154
|
+
});
|
|
155
|
+
const elements = children ? children({ child, component, key: `wrapped-inner-${index}` }) : child;
|
|
156
|
+
return React2.createElement(React2.Fragment, { key: index }, elements);
|
|
157
|
+
});
|
|
158
|
+
return React2.createElement(React2.Fragment, void 0, finalChildren);
|
|
159
|
+
}
|
|
160
|
+
function renderComponent({
|
|
161
|
+
component,
|
|
162
|
+
resolveRenderer,
|
|
163
|
+
resolveSystem,
|
|
164
|
+
key = 0,
|
|
165
|
+
indexInSlot,
|
|
166
|
+
slotName,
|
|
167
|
+
parentComponent,
|
|
168
|
+
slotChildrenCount,
|
|
169
|
+
emptyPlaceholder
|
|
170
|
+
}) {
|
|
171
|
+
var _a, _b, _c, _d;
|
|
172
|
+
const RenderComponent = resolveRenderer == null ? void 0 : resolveRenderer(component);
|
|
173
|
+
if (component.type === CANVAS_TEST_TYPE) {
|
|
174
|
+
return resolveSystem.test(
|
|
175
|
+
component,
|
|
176
|
+
key,
|
|
177
|
+
(component2, key2) => renderComponent({ component: component2, resolveRenderer, resolveSystem, key: key2 })
|
|
178
|
+
);
|
|
179
|
+
} else if (component.type === CANVAS_PERSONALIZE_TYPE) {
|
|
180
|
+
return resolveSystem.personalization(
|
|
181
|
+
component,
|
|
182
|
+
key,
|
|
183
|
+
(component2, key2) => renderComponent({ component: component2, resolveRenderer, resolveSystem, key: key2 })
|
|
184
|
+
);
|
|
185
|
+
} else if (RenderComponent) {
|
|
186
|
+
const props = convertComponentToProps(component);
|
|
187
|
+
const shouldRenderContextualEditingTags = Boolean(component._id);
|
|
188
|
+
const isPlaceholder = component._id === PLACEHOLDER_ID;
|
|
189
|
+
return /* @__PURE__ */ React2.createElement(Composition, { key, data: component, resolveRenderer }, !shouldRenderContextualEditingTags ? null : /* @__PURE__ */ React2.createElement(
|
|
190
|
+
"script",
|
|
191
|
+
{
|
|
192
|
+
key,
|
|
193
|
+
"data-role": IN_CONTEXT_EDITOR_COMPONENT_START_ROLE,
|
|
194
|
+
"data-parent-id": parentComponent == null ? void 0 : parentComponent._id,
|
|
195
|
+
"data-parent-type": parentComponent == null ? void 0 : parentComponent.type,
|
|
196
|
+
"data-component-id": component._id,
|
|
197
|
+
"data-slot-name": slotName != null ? slotName : "",
|
|
198
|
+
"data-component-index": indexInSlot != null ? indexInSlot : "",
|
|
199
|
+
"data-total-components": slotChildrenCount != null ? slotChildrenCount : "",
|
|
200
|
+
"data-component-name": component.type,
|
|
201
|
+
"data-is-placeholder": isPlaceholder ? "true" : void 0,
|
|
202
|
+
"data-is-localized": ((_a = component.parameters) == null ? void 0 : _a[CANVAS_LOCALE_TAG_PARAM]) ? "true" : void 0,
|
|
203
|
+
"data-component-title": (_d = (_c = (_b = component.parameters) == null ? void 0 : _b.title) == null ? void 0 : _c.value) != null ? _d : ""
|
|
204
|
+
}
|
|
205
|
+
), isPlaceholder && emptyPlaceholder !== void 0 ? emptyPlaceholder : /* @__PURE__ */ React2.createElement(RenderComponent, { ...props }), !shouldRenderContextualEditingTags ? null : /* @__PURE__ */ React2.createElement("script", { "data-role": "component-end" }));
|
|
206
|
+
} else if (process.env.NODE_ENV !== "production") {
|
|
207
|
+
console.warn(
|
|
208
|
+
`[canvas] found component of type '${component.type}' which the resolveRenderer prop returned no component for. Nothing will be rendered. The resolveRenderer function may need to be extended to handle the new type.`,
|
|
209
|
+
component
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/components/Composition.tsx
|
|
216
|
+
var CompositionContext = createContext(void 0);
|
|
217
|
+
function useComposition() {
|
|
218
|
+
return useContext(CompositionContext);
|
|
219
|
+
}
|
|
220
|
+
var componentStoreResolver2 = (component) => {
|
|
221
|
+
const resolved = componentStore.get(component.type);
|
|
222
|
+
return resolved || null;
|
|
223
|
+
};
|
|
224
|
+
function Composition({
|
|
225
|
+
data,
|
|
226
|
+
resolveRenderer,
|
|
227
|
+
children,
|
|
228
|
+
behaviorTracking
|
|
229
|
+
}) {
|
|
230
|
+
var _a, _b, _c;
|
|
231
|
+
const parentLayout = useComposition();
|
|
232
|
+
const contextContextProviderPresent = useUniformContext({ throwOnMissingProvider: false }) !== void 0;
|
|
233
|
+
if (!data) {
|
|
234
|
+
if (process.env.NODE_ENV === "development") {
|
|
235
|
+
console.warn(`[canvas-dev] Composition was rendered with no data, nothing will be output.`);
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const context = {
|
|
240
|
+
composition: data,
|
|
241
|
+
resolveRenderer: resolveRenderer || (parentLayout == null ? void 0 : parentLayout.resolveRenderer) || componentStoreResolver2,
|
|
242
|
+
behaviorTracking: (_a = behaviorTracking != null ? behaviorTracking : parentLayout == null ? void 0 : parentLayout.behaviorTracking) != null ? _a : "onView"
|
|
243
|
+
};
|
|
244
|
+
const enrichmentTags = (_c = (_b = data.parameters) == null ? void 0 : _b[CANVAS_ENRICHMENT_TAG_PARAM]) == null ? void 0 : _c.value;
|
|
245
|
+
const TrackComponent = context.behaviorTracking === "onLoad" ? TrackFragment : Track;
|
|
246
|
+
const resolvedChildren = resolveChildren({
|
|
247
|
+
children,
|
|
248
|
+
data,
|
|
249
|
+
hasParentLayout: Boolean(parentLayout)
|
|
250
|
+
});
|
|
251
|
+
return /* @__PURE__ */ React3.createElement(CompositionContext.Provider, { value: context }, contextContextProviderPresent ? /* @__PURE__ */ React3.createElement(TrackComponent, { behavior: enrichmentTags }, resolvedChildren) : resolvedChildren);
|
|
252
|
+
}
|
|
253
|
+
function resolveChildren({
|
|
254
|
+
children,
|
|
255
|
+
data,
|
|
256
|
+
hasParentLayout
|
|
257
|
+
}) {
|
|
258
|
+
var _a;
|
|
259
|
+
let compositionChildren = children;
|
|
260
|
+
if (!compositionChildren && !hasParentLayout) {
|
|
261
|
+
const rootComponent = componentStore.get(data.type);
|
|
262
|
+
if (rootComponent) {
|
|
263
|
+
compositionChildren = React3.createElement(rootComponent, convertComponentToProps(data));
|
|
264
|
+
} else {
|
|
265
|
+
if (Object.keys((_a = data.slots) != null ? _a : {}).length > 1 && process.env.NODE_ENV === "development") {
|
|
266
|
+
console.warn(
|
|
267
|
+
`[canvas-dev] All the slots in component '${data.type}' are rendered in no particular order. Use '<Slot name={slotName} />' to reliably render the slots.`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
compositionChildren = Object.keys(data.slots || {}).map((slotName) => /* @__PURE__ */ React3.createElement(Slot, { key: slotName, name: slotName }));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const renderChildren = typeof compositionChildren === "function" ? compositionChildren(convertComponentToProps(data)) : compositionChildren;
|
|
274
|
+
return renderChildren;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/components/DefaultNotImplementedComponent.tsx
|
|
278
|
+
import { CANVAS_LOCALIZATION_TYPE } from "@uniformdev/canvas";
|
|
279
|
+
import React4 from "react";
|
|
280
|
+
var wrapperStyles = {
|
|
281
|
+
borderLeft: "4px solid #e42535",
|
|
282
|
+
padding: "16px",
|
|
283
|
+
fontSize: "16px",
|
|
284
|
+
borderRadius: "0 8px 8px 0",
|
|
285
|
+
margin: "8px",
|
|
286
|
+
backgroundColor: "rgba(255, 255, 255, 0.45)",
|
|
287
|
+
color: "#1d3557"
|
|
288
|
+
};
|
|
289
|
+
function DefaultNotImplementedComponent(props) {
|
|
290
|
+
var _a;
|
|
291
|
+
const componentType = (_a = props.component) == null ? void 0 : _a.type;
|
|
292
|
+
if (!componentType) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
if (componentType === CANVAS_LOCALIZATION_TYPE) {
|
|
296
|
+
return /* @__PURE__ */ React4.createElement("div", { style: wrapperStyles }, /* @__PURE__ */ React4.createElement("p", null, "Seems like localization is not enabled in your application. Please read our documentation on how to", " ", /* @__PURE__ */ React4.createElement(
|
|
297
|
+
"a",
|
|
298
|
+
{
|
|
299
|
+
href: "https://docs.uniform.app/guides/composition/localization#activate-front-end",
|
|
300
|
+
target: "_blank",
|
|
301
|
+
style: { fontWeight: "bolder", textDecoration: "underline" },
|
|
302
|
+
rel: "noreferrer"
|
|
303
|
+
},
|
|
304
|
+
"enable localization in your front-end application."
|
|
305
|
+
)));
|
|
306
|
+
}
|
|
307
|
+
return /* @__PURE__ */ React4.createElement("div", { style: wrapperStyles }, /* @__PURE__ */ React4.createElement("h2", null, "Component: ", /* @__PURE__ */ React4.createElement("code", null, componentType)), /* @__PURE__ */ React4.createElement("p", null, /* @__PURE__ */ React4.createElement("code", null, /* @__PURE__ */ React4.createElement("strong", null, componentType)), " ", "has no React implementation. It may need to be added to your ", /* @__PURE__ */ React4.createElement("code", null, "resolveRenderer()"), " function."), /* @__PURE__ */ React4.createElement("details", null, /* @__PURE__ */ React4.createElement("summary", { style: { cursor: "pointer" } }, "Props"), /* @__PURE__ */ React4.createElement("pre", null, JSON.stringify(props, null, 2))));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// src/hooks/useCompositionEventEffect.ts
|
|
311
|
+
import {
|
|
312
|
+
CANVAS_DRAFT_STATE,
|
|
313
|
+
createEventBus,
|
|
314
|
+
subscribeToComposition
|
|
315
|
+
} from "@uniformdev/canvas";
|
|
316
|
+
import { useEffect } from "react";
|
|
317
|
+
function useCompositionEventEffect({
|
|
318
|
+
enabled,
|
|
319
|
+
projectId,
|
|
320
|
+
compositionId,
|
|
321
|
+
effect
|
|
322
|
+
}) {
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
if (!enabled || !compositionId || !projectId) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
let goodbye = void 0;
|
|
328
|
+
const loadEffect = async () => {
|
|
329
|
+
const eventBus = await createEventBus();
|
|
330
|
+
if (eventBus) {
|
|
331
|
+
goodbye = subscribeToComposition({
|
|
332
|
+
eventBus,
|
|
333
|
+
compositionId,
|
|
334
|
+
compositionState: CANVAS_DRAFT_STATE,
|
|
335
|
+
projectId,
|
|
336
|
+
callback: effect,
|
|
337
|
+
event: "updated"
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
loadEffect();
|
|
342
|
+
return () => {
|
|
343
|
+
if (goodbye) {
|
|
344
|
+
goodbye();
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}, [compositionId, enabled, projectId, effect]);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/hooks/useContextualEditing.ts
|
|
351
|
+
import {
|
|
352
|
+
createCanvasChannel,
|
|
353
|
+
IN_CONTEXT_EDITOR_QUERY_STRING_PARAM,
|
|
354
|
+
isUpdateCompositionMessage
|
|
355
|
+
} from "@uniformdev/canvas";
|
|
356
|
+
import { useEffect as useEffect2, useMemo, useState } from "react";
|
|
357
|
+
var previewScriptId = "uniform-canvas-preview-script";
|
|
358
|
+
var createApiEnhancer = ({ apiUrl }) => {
|
|
359
|
+
return async (message) => {
|
|
360
|
+
const response = await fetch(apiUrl, {
|
|
361
|
+
method: "post",
|
|
362
|
+
body: JSON.stringify({
|
|
363
|
+
composition: message.composition,
|
|
364
|
+
hash: message.hash
|
|
365
|
+
}),
|
|
366
|
+
headers: {
|
|
367
|
+
"Content-Type": "application/json"
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
const json = await response.json();
|
|
371
|
+
if (!response.ok) {
|
|
372
|
+
throw new Error("Error reading enhanced composition");
|
|
373
|
+
}
|
|
374
|
+
const body = json;
|
|
375
|
+
return body.composition;
|
|
376
|
+
};
|
|
377
|
+
};
|
|
378
|
+
var useContextualEditing = ({
|
|
379
|
+
initialCompositionValue,
|
|
380
|
+
enhance = (message) => message.composition
|
|
381
|
+
}) => {
|
|
382
|
+
const [contextualComposition, setContextualComposition] = useState();
|
|
383
|
+
const channel = useMemo(() => {
|
|
384
|
+
var _a;
|
|
385
|
+
if (!isInContextEditingMode()) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const channel2 = createCanvasChannel({
|
|
389
|
+
broadcastTo: [(_a = window.opener) != null ? _a : window.top],
|
|
390
|
+
listenTo: [window]
|
|
391
|
+
});
|
|
392
|
+
return channel2;
|
|
393
|
+
}, []);
|
|
394
|
+
useEffect2(() => {
|
|
395
|
+
if (!channel) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const unsubscribe = channel.on("update-composition", async (message) => {
|
|
399
|
+
if (isUpdateCompositionMessage(message)) {
|
|
400
|
+
const composition = await enhance(message);
|
|
401
|
+
setContextualComposition(composition);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
return () => {
|
|
405
|
+
unsubscribe();
|
|
406
|
+
};
|
|
407
|
+
}, [channel, enhance]);
|
|
408
|
+
useEffect2(() => {
|
|
409
|
+
if (!isInContextEditingMode()) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const existingScript = document.getElementById(previewScriptId);
|
|
413
|
+
if (existingScript) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const script = document.createElement("script");
|
|
417
|
+
script.id = previewScriptId;
|
|
418
|
+
script.src = getCanvasInContextEmbedScriptUrl();
|
|
419
|
+
script.async = true;
|
|
420
|
+
document.head.appendChild(script);
|
|
421
|
+
}, []);
|
|
422
|
+
return {
|
|
423
|
+
composition: contextualComposition != null ? contextualComposition : initialCompositionValue
|
|
424
|
+
};
|
|
425
|
+
};
|
|
426
|
+
function getCanvasInContextEmbedScriptUrl() {
|
|
427
|
+
const scriptUrl = `${window.document.referrer}files/canvas-in-context-embed/index.js`;
|
|
428
|
+
return scriptUrl;
|
|
429
|
+
}
|
|
430
|
+
function isInContextEditingMode() {
|
|
431
|
+
if (typeof window === "undefined") {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
const isOpenedByInContextEditor = new URLSearchParams(window.location.search).has(
|
|
435
|
+
IN_CONTEXT_EDITOR_QUERY_STRING_PARAM
|
|
436
|
+
);
|
|
437
|
+
const isAllowlistedReferrer = Boolean(
|
|
438
|
+
window.document.referrer.match(/(^https:\/\/|\.)(uniform.app|uniform.wtf|localhost:\d{4})\//)
|
|
439
|
+
);
|
|
440
|
+
return isOpenedByInContextEditor && isAllowlistedReferrer;
|
|
441
|
+
}
|
|
442
|
+
export {
|
|
443
|
+
Composition,
|
|
444
|
+
DefaultNotImplementedComponent,
|
|
445
|
+
Slot,
|
|
446
|
+
componentStore,
|
|
447
|
+
componentStoreResolver,
|
|
448
|
+
createApiEnhancer,
|
|
449
|
+
createComponentStore,
|
|
450
|
+
createComponentStoreResolver,
|
|
451
|
+
registerUniformComponent,
|
|
452
|
+
useComposition,
|
|
453
|
+
useCompositionEventEffect,
|
|
454
|
+
useContextualEditing
|
|
455
|
+
};
|