@uniformdev/next-app-router-client 20.7.1-alpha.118

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 ADDED
@@ -0,0 +1,521 @@
1
+ "use client";
2
+
3
+ // src/components/ClientContextTestTransfer.tsx
4
+ import { useEffect as useEffect3 } from "react";
5
+
6
+ // src/hooks/useStableValue.ts
7
+ import { useEffect, useRef, useState } from "react";
8
+ var useStableValue = (value, isValid) => {
9
+ const previousRef = useRef(null);
10
+ const [stableValue, setStableValue] = useState(void 0);
11
+ useEffect(() => {
12
+ const serialized = JSON.stringify(value);
13
+ const valid = isValid ? isValid(value) : true;
14
+ if (serialized !== previousRef.current && valid) {
15
+ previousRef.current = serialized;
16
+ setStableValue(value);
17
+ }
18
+ }, [value]);
19
+ return stableValue;
20
+ };
21
+
22
+ // src/hooks/useUniformContext.ts
23
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
24
+ var useUniformContext = () => {
25
+ const [context, setContext] = useState2(
26
+ typeof window !== "undefined" ? window.__UNIFORM_CONTEXT__ : void 0
27
+ );
28
+ useInterval(
29
+ () => {
30
+ if (context) {
31
+ return;
32
+ }
33
+ if (window.__UNIFORM_CONTEXT__) {
34
+ setContext(window.__UNIFORM_CONTEXT__);
35
+ }
36
+ },
37
+ 100,
38
+ !context
39
+ );
40
+ return {
41
+ context
42
+ };
43
+ };
44
+ var useInterval = (callback, delay, enabled) => {
45
+ const intervalRef = useRef2(null);
46
+ useEffect2(() => {
47
+ if (!enabled) {
48
+ if (intervalRef.current) {
49
+ clearInterval(intervalRef.current);
50
+ }
51
+ return;
52
+ }
53
+ const interval = setInterval(callback, delay);
54
+ return () => clearInterval(interval);
55
+ }, [callback, delay, enabled]);
56
+ };
57
+
58
+ // src/components/ClientContextTestTransfer.tsx
59
+ var hasVariantId = (event) => Boolean(event.variantId);
60
+ var ClientContextTestTransfer = ({ event }) => {
61
+ const { context } = useUniformContext();
62
+ const stableEvent = useStableValue(event, hasVariantId);
63
+ useEffect3(() => {
64
+ if (context && stableEvent) {
65
+ context.internal_processTestEvent(stableEvent);
66
+ }
67
+ }, [context, stableEvent]);
68
+ return null;
69
+ };
70
+
71
+ // src/components/ClientUniformText.tsx
72
+ import {
73
+ ATTRIBUTE_COMPONENT_ID,
74
+ ATTRIBUTE_MULTILINE,
75
+ ATTRIBUTE_PARAMETER_ID,
76
+ ATTRIBUTE_PARAMETER_TYPE,
77
+ ATTRIBUTE_PARAMETER_VALUE,
78
+ ATTRIBUTE_PLACEHOLDER,
79
+ createQuirksVisibilityRule,
80
+ evaluatePropertyCriteria
81
+ } from "@uniformdev/canvas";
82
+ import { useMemo } from "react";
83
+
84
+ // src/hooks/useQuirks.ts
85
+ import { useEffect as useEffect4, useState as useState3 } from "react";
86
+ function useQuirks() {
87
+ var _a;
88
+ const { context } = useUniformContext();
89
+ const [quirks, setQuirks] = useState3((_a = context == null ? void 0 : context.quirks) != null ? _a : {});
90
+ useEffect4(() => {
91
+ if (!context) {
92
+ return;
93
+ }
94
+ const quirkChangeListener = (updatedQuirks) => {
95
+ setQuirks(updatedQuirks);
96
+ };
97
+ setQuirks(context.quirks);
98
+ context == null ? void 0 : context.events.on("quirksUpdated", quirkChangeListener);
99
+ return () => {
100
+ context == null ? void 0 : context.events.off("quirksUpdated", quirkChangeListener);
101
+ };
102
+ }, [context]);
103
+ return quirks;
104
+ }
105
+
106
+ // src/components/ClientUniformText.tsx
107
+ import { jsx } from "react/jsx-runtime";
108
+ var ClientUniformText = ({
109
+ as,
110
+ component,
111
+ parameter: providedParameter,
112
+ isMultiline = false,
113
+ placeholder,
114
+ render = (value) => value != null ? value : "",
115
+ ...props
116
+ }) => {
117
+ const parameter = providedParameter;
118
+ const quirks = useQuirks();
119
+ const rules = useMemo(() => {
120
+ return {
121
+ ...createQuirksVisibilityRule(quirks)
122
+ };
123
+ }, [quirks]);
124
+ const currentValue = useMemo(() => {
125
+ var _a;
126
+ if (!parameter) {
127
+ return void 0;
128
+ }
129
+ if (!rules.length || !((_a = parameter.conditions) == null ? void 0 : _a.length)) {
130
+ return parameter.value;
131
+ }
132
+ const match = evaluatePropertyCriteria({
133
+ baseValue: parameter.value,
134
+ conditionalValues: parameter.conditions,
135
+ rules
136
+ });
137
+ if (typeof match.currentValue === "string") {
138
+ return match.currentValue;
139
+ }
140
+ return parameter.value;
141
+ }, [rules, parameter]);
142
+ if (!parameter || parameter.type !== "text") {
143
+ return null;
144
+ }
145
+ const Tag = as || "span";
146
+ const parameterId = parameter.parameterId;
147
+ const isContextualEditing = Boolean(parameter._contextualEditing);
148
+ if (!isContextualEditing) {
149
+ return /* @__PURE__ */ jsx(Tag, { style: isMultiline ? { whiteSpace: "pre-wrap" } : {}, ...props, children: render(currentValue) });
150
+ }
151
+ const computedPlaceholder = typeof placeholder === "function" ? placeholder({ id: parameterId }) : placeholder;
152
+ return /* @__PURE__ */ jsx(
153
+ Tag,
154
+ {
155
+ ...props,
156
+ ...getParameterAttributes({
157
+ component,
158
+ parameter,
159
+ placeholder: computedPlaceholder,
160
+ isMultiline
161
+ }),
162
+ "data-uniform-parameter-type": "text",
163
+ "data-uniform-placeholder": computedPlaceholder,
164
+ style: isMultiline ? { whiteSpace: "pre-wrap" } : {},
165
+ children: isContextualEditing ? currentValue : render(currentValue)
166
+ }
167
+ );
168
+ };
169
+ var getParameterAttributes = ({
170
+ component,
171
+ parameter,
172
+ placeholder,
173
+ isMultiline = false
174
+ }) => {
175
+ var _a, _b;
176
+ const value = parameter == null ? void 0 : parameter.value;
177
+ const type = parameter == null ? void 0 : parameter.type;
178
+ const isEditable = (_b = (_a = parameter == null ? void 0 : parameter._contextualEditing) == null ? void 0 : _a.isEditable) != null ? _b : false;
179
+ return {
180
+ [ATTRIBUTE_COMPONENT_ID]: component._id,
181
+ [ATTRIBUTE_PARAMETER_ID]: parameter.parameterId,
182
+ [ATTRIBUTE_PARAMETER_VALUE]: String(value != null ? value : ""),
183
+ [ATTRIBUTE_PARAMETER_TYPE]: type,
184
+ [ATTRIBUTE_PLACEHOLDER]: placeholder,
185
+ [ATTRIBUTE_MULTILINE]: isMultiline,
186
+ contentEditable: isEditable,
187
+ suppressContentEditableWarning: true
188
+ };
189
+ };
190
+
191
+ // src/components/ContextUpdateTransfer.tsx
192
+ import { useEffect as useEffect5 } from "react";
193
+ var hasKeys = (obj) => Object.keys(obj).length > 0;
194
+ var ContextUpdateTransfer = ({ update }) => {
195
+ const { context } = useUniformContext();
196
+ const stableUpdate = useStableValue(update, hasKeys);
197
+ useEffect5(() => {
198
+ if (context && stableUpdate) {
199
+ context.update(stableUpdate);
200
+ }
201
+ }, [context, stableUpdate]);
202
+ return null;
203
+ };
204
+
205
+ // src/components/DefaultUniformClientContext.tsx
206
+ import { enableContextDevTools } from "@uniformdev/context";
207
+ import { useRouter } from "next/navigation";
208
+
209
+ // src/context/createUniformContext.ts
210
+ import {
211
+ Context,
212
+ CookieTransitionDataStore
213
+ } from "@uniformdev/context";
214
+ var createUniformContext = ({
215
+ serverCookieValue,
216
+ quirkCookieValue,
217
+ experimental_quirksEnabled,
218
+ cookieAttributes,
219
+ ...rest
220
+ }) => {
221
+ const context = new Context({
222
+ ...rest,
223
+ transitionStore: new CookieTransitionDataStore({
224
+ serverCookieValue,
225
+ quirkCookieValue,
226
+ cookieAttributes,
227
+ experimental_quirksEnabled
228
+ })
229
+ });
230
+ return context;
231
+ };
232
+
233
+ // src/context/createClientUniformContext.ts
234
+ var createClientUniformContext = (options) => {
235
+ return createUniformContext({
236
+ ...options,
237
+ serverCookieValue: void 0
238
+ });
239
+ };
240
+
241
+ // src/hooks/useInitUniformContext.ts
242
+ import { parseScoreCookie } from "@uniformdev/context";
243
+ import {
244
+ UNIFORM_MIDDLEWARE_QUIRK_COOKIE_NAME,
245
+ UNIFORM_MIDDLEWARE_SCORE_COOKIE_NAME
246
+ } from "@uniformdev/next-app-router-shared";
247
+ import Cookies from "js-cookie";
248
+ import { usePathname, useSearchParams } from "next/navigation";
249
+ import { useEffect as useEffect6, useRef as useRef3 } from "react";
250
+ var useInitUniformContext = (callback, compositionMetadata) => {
251
+ const path = usePathname();
252
+ const searchParams = useSearchParams();
253
+ const context = useRef3(void 0);
254
+ if (typeof window !== "undefined" && context.current === void 0) {
255
+ context.current = callback();
256
+ }
257
+ useEffect6(() => {
258
+ var _a;
259
+ if (typeof window === "undefined" || typeof window.__UNIFORM_CONTEXT__ !== "undefined") {
260
+ return;
261
+ }
262
+ const url = new URL(path, "https://example.com");
263
+ searchParams.forEach((value, key) => {
264
+ url.searchParams.set(key, value);
265
+ });
266
+ const scoreCookie = Cookies.get(UNIFORM_MIDDLEWARE_SCORE_COOKIE_NAME);
267
+ const quirkCookie = Cookies.get(UNIFORM_MIDDLEWARE_QUIRK_COOKIE_NAME);
268
+ const scoreCookieData = parseScoreCookie(scoreCookie, quirkCookie);
269
+ Cookies.remove(UNIFORM_MIDDLEWARE_SCORE_COOKIE_NAME);
270
+ Cookies.remove(UNIFORM_MIDDLEWARE_QUIRK_COOKIE_NAME);
271
+ context.current.update({
272
+ url,
273
+ compositionMetadata,
274
+ quirks: (_a = scoreCookieData == null ? void 0 : scoreCookieData.quirks) != null ? _a : {}
275
+ });
276
+ if (!window.__UNIFORM_CONTEXT__) {
277
+ window.__UNIFORM_CONTEXT__ = context.current;
278
+ }
279
+ }, [path, searchParams, compositionMetadata]);
280
+ };
281
+
282
+ // src/components/DefaultUniformClientContext.tsx
283
+ var DefaultUniformClientContext = ({
284
+ manifest,
285
+ disableDevTools,
286
+ defaultConsent,
287
+ experimentalQuirkSerialization,
288
+ compositionMetadata
289
+ }) => {
290
+ const router = useRouter();
291
+ useInitUniformContext(() => {
292
+ const plugins = [];
293
+ if (!disableDevTools) {
294
+ plugins.push(
295
+ enableContextDevTools({
296
+ onAfterMessageReceived: () => {
297
+ router.refresh();
298
+ }
299
+ })
300
+ );
301
+ }
302
+ return createClientUniformContext({
303
+ manifest,
304
+ plugins,
305
+ defaultConsent,
306
+ experimental_quirksEnabled: experimentalQuirkSerialization
307
+ });
308
+ }, compositionMetadata);
309
+ return null;
310
+ };
311
+
312
+ // src/components/Personalize.tsx
313
+ import { CANVAS_PERSONALIZE_SLOT } from "@uniformdev/canvas";
314
+ import { evaluatePersonalization } from "@uniformdev/next-app-router-shared";
315
+ import { createElement, Fragment, useEffect as useEffect8, useMemo as useMemo2, useState as useState5 } from "react";
316
+
317
+ // src/hooks/useScores.ts
318
+ import { useEffect as useEffect7, useState as useState4 } from "react";
319
+ function useScores() {
320
+ const { context } = useUniformContext();
321
+ const [scores, setScores] = useState4(context == null ? void 0 : context.scores);
322
+ useEffect7(() => {
323
+ if (!context) {
324
+ return;
325
+ }
326
+ const scoringChangeListener = (updatedScores) => {
327
+ setScores(updatedScores);
328
+ };
329
+ setScores(context.scores);
330
+ context.events.on("scoresUpdated", scoringChangeListener);
331
+ return () => {
332
+ context.events.off("scoresUpdated", scoringChangeListener);
333
+ };
334
+ }, [context]);
335
+ return scores;
336
+ }
337
+
338
+ // src/components/Personalize.tsx
339
+ var Personalize = ({
340
+ parameters,
341
+ indexes,
342
+ slots,
343
+ context: compositionContext
344
+ }) => {
345
+ var _a, _b;
346
+ const trackingEventName = (_a = parameters.trackingEventName) == null ? void 0 : _a.value;
347
+ const algorithm = (_b = parameters.algorithm) == null ? void 0 : _b.value;
348
+ const personalizationSlot = slots[CANVAS_PERSONALIZE_SLOT];
349
+ const { context } = useUniformContext();
350
+ const scores = useScores();
351
+ const quirks = useQuirks();
352
+ const [indexesToShow, setIndexesToShow] = useState5(indexes);
353
+ useEffect8(() => {
354
+ if (typeof context === "undefined" || !personalizationSlot) {
355
+ return;
356
+ }
357
+ const result = evaluatePersonalization({
358
+ context,
359
+ compositionContext,
360
+ personalization: {
361
+ name: trackingEventName != null ? trackingEventName : "unknown",
362
+ algorithm,
363
+ variations: personalizationSlot.items.filter(Boolean).map((item, index) => {
364
+ var _a2;
365
+ return {
366
+ index,
367
+ id: (_a2 = item.variantId) != null ? _a2 : item._id,
368
+ pz: item.$pzCrit,
369
+ componentId: item._id
370
+ };
371
+ }),
372
+ compositionMetadata: {
373
+ compositionId: compositionContext._id,
374
+ matchedRoute: compositionContext.matchedRoute,
375
+ dynamicInputs: compositionContext.dynamicInputs
376
+ }
377
+ }
378
+ });
379
+ if (JSON.stringify(result.indexes) !== JSON.stringify(indexesToShow)) {
380
+ setIndexesToShow(result.indexes);
381
+ }
382
+ }, [
383
+ trackingEventName,
384
+ context,
385
+ personalizationSlot,
386
+ algorithm,
387
+ compositionContext,
388
+ scores,
389
+ quirks,
390
+ indexesToShow
391
+ ]);
392
+ const slotsToShow = useMemo2(() => {
393
+ return indexesToShow.map((key) => {
394
+ var _a2;
395
+ return (_a2 = personalizationSlot == null ? void 0 : personalizationSlot.items[key]) == null ? void 0 : _a2.component;
396
+ });
397
+ }, [indexesToShow, personalizationSlot]);
398
+ return createElement(Fragment, void 0, slotsToShow);
399
+ };
400
+
401
+ // src/components/UniformScript.tsx
402
+ import { createCanvasChannel, isAllowedReferrer } from "@uniformdev/canvas";
403
+ import { useRouter as useRouter2 } from "next/navigation";
404
+ import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef4 } from "react";
405
+ import { Fragment as Fragment2, jsx as jsx2 } from "react/jsx-runtime";
406
+ var UniformScript = () => {
407
+ const router = useRouter2();
408
+ const needsToRefreshRef = useRef4(false);
409
+ const channel = useMemo3(() => {
410
+ var _a;
411
+ if (typeof window === "undefined") {
412
+ return;
413
+ }
414
+ const instance = createCanvasChannel({
415
+ broadcastTo: [(_a = window.opener) != null ? _a : window.top],
416
+ listenTo: [window]
417
+ });
418
+ return instance;
419
+ }, []);
420
+ useEffect9(() => {
421
+ if (!channel) {
422
+ return;
423
+ }
424
+ const unsubscribeFromEditorUpdates = channel.on("editor-state-updated", () => {
425
+ const el = document.activeElement;
426
+ const isActiveElementEditable = el == null ? void 0 : el.isContentEditable;
427
+ if (!isActiveElementEditable) {
428
+ router.refresh();
429
+ } else {
430
+ needsToRefreshRef.current = true;
431
+ }
432
+ });
433
+ return () => {
434
+ unsubscribeFromEditorUpdates();
435
+ };
436
+ }, [channel, router]);
437
+ useEffect9(() => {
438
+ if (typeof window === "undefined") {
439
+ return;
440
+ }
441
+ const existing = document.getElementById("uniform-script");
442
+ if (!existing) {
443
+ const textHost = isAllowedReferrer(window.document.referrer) ? window.document.referrer : "https://uniform.app/";
444
+ window.__UNIFORM_CONTEXTUAL_EDITING__ = {
445
+ framework: "React",
446
+ version: 2
447
+ };
448
+ const bundleHost = new URL(textHost);
449
+ bundleHost.pathname = "/files/canvas-in-context-embed/index.js";
450
+ const script = document.createElement("script");
451
+ script.id = "uniform-script";
452
+ script.setAttribute("data-rsc", "true");
453
+ script.src = bundleHost.toString();
454
+ script.async = true;
455
+ document.head.appendChild(script);
456
+ }
457
+ }, []);
458
+ useEffect9(() => {
459
+ const handleBlurChange = () => {
460
+ if (needsToRefreshRef.current) {
461
+ router.refresh();
462
+ needsToRefreshRef.current = false;
463
+ }
464
+ };
465
+ document.addEventListener("blur", handleBlurChange, true);
466
+ return () => {
467
+ document.removeEventListener("focus", handleBlurChange, true);
468
+ };
469
+ }, [router]);
470
+ return /* @__PURE__ */ jsx2(Fragment2, {});
471
+ };
472
+
473
+ // src/components/VisibilityRulesWrapperClient.tsx
474
+ import {
475
+ createQuirksVisibilityRule as createQuirksVisibilityRule2,
476
+ evaluateNodeVisibilityParameter
477
+ } from "@uniformdev/canvas";
478
+ import { useEffect as useEffect10, useMemo as useMemo4, useState as useState6 } from "react";
479
+ import { Fragment as Fragment3, jsx as jsx3 } from "react/jsx-runtime";
480
+ var VisibilityRulesWrapperClient = ({
481
+ parameter,
482
+ initialIsVisible,
483
+ children
484
+ }) => {
485
+ const [isVisible, setIsVisible] = useState6(initialIsVisible);
486
+ const [visibleSource, setVisibleSource] = useState6(
487
+ initialIsVisible === null ? "unknown" : "server"
488
+ );
489
+ const quirks = useQuirks();
490
+ const rules = useMemo4(() => {
491
+ return {
492
+ ...createQuirksVisibilityRule2(quirks)
493
+ };
494
+ }, [quirks]);
495
+ useEffect10(() => {
496
+ const result = evaluateNodeVisibilityParameter({
497
+ rules,
498
+ parameter
499
+ });
500
+ if (visibleSource === "server" && initialIsVisible && !result) {
501
+ return;
502
+ }
503
+ setIsVisible(result);
504
+ setVisibleSource("client");
505
+ }, [initialIsVisible, visibleSource, parameter, rules]);
506
+ return isVisible ? /* @__PURE__ */ jsx3(Fragment3, { children }) : null;
507
+ };
508
+ export {
509
+ ClientContextTestTransfer,
510
+ ClientUniformText,
511
+ ContextUpdateTransfer,
512
+ DefaultUniformClientContext,
513
+ Personalize,
514
+ UniformScript,
515
+ VisibilityRulesWrapperClient,
516
+ createClientUniformContext,
517
+ useInitUniformContext,
518
+ useQuirks,
519
+ useScores,
520
+ useUniformContext
521
+ };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@uniformdev/next-app-router-client",
3
+ "version": "20.7.1-alpha.118+5483f1e4cc",
4
+ "license": "SEE LICENSE IN LICENSE.txt",
5
+ "scripts": {
6
+ "build": "tsup",
7
+ "dev": "tsup --watch",
8
+ "lint": "eslint \"src/**/*.{ts,tsx}\" --fix",
9
+ "test": "jest --maxWorkers=1 --passWithNoTests"
10
+ },
11
+ "sideEffects": false,
12
+ "main": "./dist/index.js",
13
+ "module": "./dist/index.esm.js",
14
+ "exports": {
15
+ "import": {
16
+ "types": "./dist/index.d.mts",
17
+ "node": "./dist/index.mjs",
18
+ "default": "./dist/index.esm.js"
19
+ },
20
+ "require": "./dist/index.js"
21
+ },
22
+ "types": "./dist/index.d.ts",
23
+ "files": [
24
+ "/dist"
25
+ ],
26
+ "devDependencies": {
27
+ "@types/js-cookie": "3.0.6",
28
+ "@types/node": "20.19.25",
29
+ "@types/react": "19.0.8",
30
+ "@types/react-dom": "19.0.3",
31
+ "next": "16.0.7",
32
+ "react": "19.2.0",
33
+ "react-dom": "19.2.0",
34
+ "typescript": "5.9.2"
35
+ },
36
+ "dependencies": {
37
+ "@uniformdev/canvas": "20.7.1-alpha.118+5483f1e4cc",
38
+ "@uniformdev/canvas-react": "20.7.1-alpha.118+5483f1e4cc",
39
+ "@uniformdev/context": "20.7.1-alpha.118+5483f1e4cc",
40
+ "@uniformdev/next-app-router-shared": "20.7.1-alpha.118+5483f1e4cc",
41
+ "js-cookie": "3.0.5"
42
+ },
43
+ "engines": {
44
+ "node": ">=20.9.0"
45
+ },
46
+ "peerDependencies": {
47
+ "next": ">=16.0.7",
48
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
49
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "gitHead": "5483f1e4ccb621d21848f58878cda17f14a86dea"
55
+ }