@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/dist/index.mjs CHANGED
@@ -1 +1,455 @@
1
- import{CANVAS_ENRICHMENT_TAG_PARAM as F}from"@uniformdev/canvas";import{Track as J,TrackFragment as X,useUniformContext as $}from"@uniformdev/context-react";import T,{createContext as j,useContext as K}from"react";function v(e){var n;let o=(n=e.parameters)!=null?n:{};return{...Object.keys(o).reduce((r,i)=>(r[i]=o[i].value,r),{}),...e.data,component:e}}var w=()=>{let e=new Map;return{register:({type:o,component:t})=>{e.set(o,t)},get:o=>e.get(o)}},S=e=>o=>e.store.get(o.type)||e.defaultComponent||null;var h=w(),ae=({type:e,component:o})=>{Array.isArray(e)?e.forEach(t=>{h.register({type:t,component:o})}):h.register({type:e,component:o})},me=S({store:h});import{CANVAS_PERSONALIZE_TYPE as M,CANVAS_TEST_TYPE as z,IN_CONTEXT_EDITOR_COMPONENT_START_ROLE as L,PLACEHOLDER_ID as B}from"@uniformdev/canvas";import C from"react";import{mapSlotToPersonalizedVariations as A,mapSlotToTestVariations as U}from"@uniformdev/canvas";import{Personalize as V,Test as D}from"@uniformdev/context-react";import*as P from"react";var x={test:(e,o,t)=>{var p,d,m,c,a;let n=e,r=(d=(p=n.slots)==null?void 0:p.test)!=null?d:[],i=(a=(c=(m=n.parameters)==null?void 0:m.test)==null?void 0:c.value)!=null?a:"Untitled Test",s=U(r);return P.createElement(D,{key:o,variations:s,name:i,component:l=>t(l,o)})},personalization:(e,o,t)=>{var i,s,p,d,m,c,a;let n=e,r=A((i=n==null?void 0:n.slots)==null?void 0:i.pz);return P.createElement(V,{key:o,variations:r,count:Number((d=(p=(s=n.parameters)==null?void 0:s.count)==null?void 0:p.value)!=null?d:1),name:(a=(c=(m=n.parameters)==null?void 0:m.trackingEventName)==null?void 0:c.value)!=null?a:"Untitled Personalization",component:l=>t(l,0)})}};function b({name:e,resolveRenderer:o,children:t,emptyPlaceholder:n}){var a;let r=E();if(!(r!=null&&r.composition))throw new Error("Slot must be rendered within a Composition");let{composition:i,resolveRenderer:s}=r;if(!i)throw new Error("Cannot use Slot without a Composition wrapper.");let p=(a=i.slots)==null?void 0:a[e];if(!p||!Array.isArray(p))return process.env.NODE_ENV==="development"&&console.warn(`[canvas-dev] slot '${e}' 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:`,i),null;let d=o!=null?o:s,m=x,c=p.map((l,u)=>{let f=g({component:l,resolveRenderer:d,resolveSystem:m,key:`inner-${u}`,indexInSlot:u,slotName:e,parentComponent:i,slotChildrenCount:p.length,emptyPlaceholder:n}),R=t?t({child:f,component:l,key:`wrapped-inner-${u}`}):f;return C.createElement(C.Fragment,{key:u},R)});return C.createElement(C.Fragment,void 0,c)}function g({component:e,resolveRenderer:o,resolveSystem:t,key:n=0,indexInSlot:r,slotName:i,parentComponent:s,slotChildrenCount:p,emptyPlaceholder:d}){var c,a,l;let m=o==null?void 0:o(e);if(e.type===z)return t.test(e,n,(u,f)=>g({component:u,resolveRenderer:o,resolveSystem:t,key:f}));if(e.type===M)return t.personalization(e,n,(u,f)=>g({component:u,resolveRenderer:o,resolveSystem:t,key:f}));if(m){let u=v(e),f=Boolean(e._id),R=e._id===B;return C.createElement(N,{key:n,data:e,resolveRenderer:o},f?C.createElement("script",{key:n,"data-role":L,"data-parent-id":s==null?void 0:s._id,"data-parent-type":s==null?void 0:s.type,"data-component-id":e._id,"data-slot-name":i!=null?i:"","data-component-index":r!=null?r:"","data-total-components":p!=null?p:"","data-component-name":e.type,"data-is-placeholder":R?"true":void 0,"data-component-title":(l=(a=(c=e.parameters)==null?void 0:c.title)==null?void 0:a.value)!=null?l:""}):null,R&&d!==void 0?d:C.createElement(m,{...u}),f?C.createElement("script",{"data-role":"component-end"}):null)}else process.env.NODE_ENV!=="production"&&console.warn(`[canvas] found component of type '${e.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.`,e);return null}var I=j(void 0);function E(){return K(I)}var Y=e=>h.get(e.type)||null;function N({data:e,resolveRenderer:o,children:t,behaviorTracking:n}){var c,a,l;let r=E(),i=$({throwOnMissingProvider:!1})!==void 0;if(!e)return process.env.NODE_ENV==="development"&&console.warn("[canvas-dev] Composition was rendered with no data, nothing will be output."),null;let s={composition:e,resolveRenderer:o||(r==null?void 0:r.resolveRenderer)||Y,behaviorTracking:(c=n!=null?n:r==null?void 0:r.behaviorTracking)!=null?c:"onView"},p=(l=(a=e.parameters)==null?void 0:a[F])==null?void 0:l.value,d=s.behaviorTracking==="onLoad"?X:J,m=G({children:t,data:e,hasParentLayout:Boolean(r)});return T.createElement(I.Provider,{value:s},i?T.createElement(d,{behavior:p},m):m)}function G({children:e,data:o,hasParentLayout:t}){var i;let n=e;if(!n&&!t){let s=h.get(o.type);s?n=T.createElement(s,v(o)):(Object.keys((i=o.slots)!=null?i:{}).length>1&&process.env.NODE_ENV==="development"&&console.warn(`[canvas-dev] All the slots in component '${o.type}' are rendered in no particular order. Use '<Slot name={slotName} />' to reliably render the slots.`),n=Object.keys(o.slots||{}).map(p=>T.createElement(b,{key:p,name:p})))}return typeof n=="function"?n(v(o)):n}import y from"react";function Ae(e){var t;let o=(t=e.component)==null?void 0:t.type;return o?y.createElement("div",{style:{borderLeft:"10px solid #e42535!important",padding:"0.01em 16px 16px",borderRadius:"16px",backgroundColor:"rgba(122, 215, 218, 0.3)",color:"#1d3557"}},y.createElement("h2",null,"Component: ",o),y.createElement("p",null,y.createElement("strong",null,o)," has no React implementation. It may need to be added to your"," ",y.createElement("code",null,"resolveRenderer()")," function."),y.createElement("details",null,y.createElement("summary",null,"Props"),y.createElement("pre",null,JSON.stringify(e,null,2)))):null}import{CANVAS_DRAFT_STATE as H,createEventBus as Q,subscribeToComposition as Z}from"@uniformdev/canvas";import{useEffect as q}from"react";function ze({enabled:e,projectId:o,compositionId:t,effect:n}){q(()=>{if(!e||!t||!o)return;let r;return(async()=>{let s=await Q();s&&(r=Z({eventBus:s,compositionId:t,compositionState:H,projectId:o,callback:n,event:"updated"}))})(),()=>{r&&r()}},[t,e,o,n])}import{createCanvasChannel as W,IN_CONTEXT_EDITOR_QUERY_STRING_PARAM as ee,isUpdateCompositionMessage as oe}from"@uniformdev/canvas";import{useEffect as _,useMemo as te,useState as ne}from"react";var O="uniform-canvas-preview-script",$e=({apiUrl:e})=>async o=>{let t=await fetch(e,{method:"post",body:JSON.stringify({composition:o.composition,hash:o.hash}),headers:{"Content-Type":"application/json"}}),n=await t.json();if(!t.ok)throw new Error("Error reading enhanced composition");return n.composition},je=({initialCompositionValue:e,enhance:o=t=>t.composition})=>{let[t,n]=ne(),r=te(()=>{var s;return k()?W({broadcastTo:[(s=window.opener)!=null?s:window.top],listenTo:[window]}):void 0},[]);return _(()=>{if(!r)return;let i=r.on("update-composition",async s=>{if(oe(s)){let p=await o(s);n(p)}});return()=>{i()}},[r,o]),_(()=>{if(!k()||document.getElementById(O))return;let s=document.createElement("script");s.id=O,s.src=re(),s.async=!0,document.head.appendChild(s)},[]),{composition:t!=null?t:e}};function re(){return`${window.document.referrer}files/canvas-in-context-embed/index.js`}function k(){if(typeof window=="undefined")return!1;let e=new URLSearchParams(window.location.search).has(ee),o=Boolean(window.document.referrer.match(/(^https:\/\/|\.)(uniform.app|uniform.wtf|localhost:\d{4})\//));return e&&o}export{N as Composition,Ae as DefaultNotImplementedComponent,b as Slot,h as componentStore,me as componentStoreResolver,$e as createApiEnhancer,w as createComponentStore,S as createComponentStoreResolver,ae as registerUniformComponent,E as useComposition,ze as useCompositionEventEffect,je as useContextualEditing};
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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/canvas-react",
3
- "version": "17.7.1-alpha.34+084da3172",
3
+ "version": "18.0.1-alpha.3+2267c1ac6",
4
4
  "description": "React SDK for Uniform Canvas",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "types": "./dist/index.d.ts",
16
16
  "sideEffects": false,
17
17
  "scripts": {
18
- "build": "tsup --minify",
18
+ "build": "tsup",
19
19
  "dev": "tsup --watch",
20
20
  "clean": "rimraf dist",
21
21
  "test": "jest --maxWorkers=1",
@@ -23,9 +23,9 @@
23
23
  "format": "prettier --write \"src/**/*.{js,ts,tsx}\""
24
24
  },
25
25
  "dependencies": {
26
- "@uniformdev/canvas": "^17.7.1-alpha.34+084da3172",
27
- "@uniformdev/context": "^17.7.1-alpha.34+084da3172",
28
- "@uniformdev/context-react": "^17.7.1-alpha.34+084da3172"
26
+ "@uniformdev/canvas": "18.0.1-alpha.3+2267c1ac6",
27
+ "@uniformdev/context": "18.0.1-alpha.3+2267c1ac6",
28
+ "@uniformdev/context-react": "18.0.1-alpha.3+2267c1ac6"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": ">= 16",
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "084da31729798e2c1a1f26ba38c764caabebc958"
45
+ "gitHead": "2267c1ac6f5f6929be6b12d0099905ab46848d0c"
46
46
  }