@playruo/embed 1.4.0 → 1.6.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/README.md +38 -0
- package/dist/index.cjs +40 -26
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +36 -25
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
React SDK to embed Playruo via iframe + postMessage.
|
|
4
4
|
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- Integrator overview and React/vanilla guides: [`docs/`](./docs/)
|
|
8
|
+
- Protocol reference for webapp ↔ SDK changes: [`DOCUMENTATION.md`](./DOCUMENTATION.md)
|
|
9
|
+
- Customer Notion pages are generated from `docs/` via `npm run docs:notion:dry-run` / `npm run docs:notion:publish`
|
|
10
|
+
|
|
5
11
|
## Windowed launch
|
|
6
12
|
|
|
7
13
|
`PlayruoEmbed` requests browser fullscreen on the iframe when the user starts a
|
|
@@ -33,6 +39,38 @@ Passing it inside `operation` (`"crypticalpath?op=..."`) still works and warns:
|
|
|
33
39
|
it was the only way before this prop existed. `operationKey` wins over it. Other
|
|
34
40
|
query parameters in `operation` are kept as they are.
|
|
35
41
|
|
|
42
|
+
## Host-owned visitor identity
|
|
43
|
+
|
|
44
|
+
By default the SDK stores a UUID in `localStorage["playruo_uuid"]` and answers
|
|
45
|
+
`playruo_uuid_request` with it. Pass `clientFingerprint` when the host already
|
|
46
|
+
has a stable visitor id (account id, CRM id, …): that value is answered as
|
|
47
|
+
`uuid` instead, and localStorage is left alone. Playruo derives the session
|
|
48
|
+
fingerprint from it.
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
<PlayruoEmbed
|
|
52
|
+
operation="crypticalpath"
|
|
53
|
+
clientFingerprint={visitorId}
|
|
54
|
+
/>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A vanilla host answers the same way, with no React:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
iframe.contentWindow.postMessage(
|
|
61
|
+
{
|
|
62
|
+
type: "playruo_uuid_response",
|
|
63
|
+
requestId,
|
|
64
|
+
uuid: visitorId,
|
|
65
|
+
},
|
|
66
|
+
"https://playruo.live",
|
|
67
|
+
);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`resolveVisitorUuid(visitorId)` from this package is the shared helper both
|
|
71
|
+
paths use. A blank or whitespace-only value is ignored and the SDK-managed UUID
|
|
72
|
+
is used.
|
|
73
|
+
|
|
36
74
|
## Password protected operations
|
|
37
75
|
|
|
38
76
|
A protected operation renders no form of its own: it announces the gate and the
|
package/dist/index.cjs
CHANGED
|
@@ -31,13 +31,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
EmbedTester: () => EmbedTester,
|
|
34
|
+
PLAYRUO_IFRAME_ALLOW: () => PLAYRUO_IFRAME_ALLOW,
|
|
35
|
+
PLAYRUO_UUID_STORAGE_KEY: () => PLAYRUO_UUID_STORAGE_KEY,
|
|
34
36
|
PlayruoEmbed: () => PlayruoEmbed,
|
|
35
37
|
buildEmbedUrl: () => buildEmbedUrl,
|
|
36
38
|
isPlayruoEmbedMessage: () => isPlayruoEmbedMessage,
|
|
37
|
-
isPlayruoInternalMessage: () => isPlayruoInternalMessage
|
|
39
|
+
isPlayruoInternalMessage: () => isPlayruoInternalMessage,
|
|
40
|
+
resolveVisitorUuid: () => resolveVisitorUuid
|
|
38
41
|
});
|
|
39
42
|
module.exports = __toCommonJS(index_exports);
|
|
40
43
|
|
|
44
|
+
// src/iframe-allow.ts
|
|
45
|
+
var PLAYRUO_IFRAME_ALLOW = "cross-origin-isolated; fullscreen *; autoplay *; gamepad *; clipboard-write *; web-share *; encrypted-media *; accelerometer *; gyroscope *; screen-wake-lock *";
|
|
46
|
+
|
|
41
47
|
// src/react/playruo-embed.tsx
|
|
42
48
|
var import_react = require("react");
|
|
43
49
|
|
|
@@ -81,6 +87,31 @@ var buildEmbedUrlWithOrigin = (origin, { operation, operationKey, storeUrl }) =>
|
|
|
81
87
|
return url.toString();
|
|
82
88
|
};
|
|
83
89
|
|
|
90
|
+
// src/visitor-uuid.ts
|
|
91
|
+
var PLAYRUO_UUID_STORAGE_KEY = "playruo_uuid";
|
|
92
|
+
var generateUUID = () => {
|
|
93
|
+
if (self.crypto.randomUUID) return self.crypto.randomUUID();
|
|
94
|
+
const bytes = new Uint8Array(16);
|
|
95
|
+
self.crypto.getRandomValues(bytes);
|
|
96
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
97
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
98
|
+
return [...bytes].map(
|
|
99
|
+
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
100
|
+
).join("");
|
|
101
|
+
};
|
|
102
|
+
var resolveVisitorUuid = (clientFingerprint) => {
|
|
103
|
+
const provided = clientFingerprint?.trim();
|
|
104
|
+
if (provided) {
|
|
105
|
+
return provided;
|
|
106
|
+
}
|
|
107
|
+
let uuid = localStorage.getItem(PLAYRUO_UUID_STORAGE_KEY);
|
|
108
|
+
if (!uuid) {
|
|
109
|
+
uuid = generateUUID();
|
|
110
|
+
localStorage.setItem(PLAYRUO_UUID_STORAGE_KEY, uuid);
|
|
111
|
+
}
|
|
112
|
+
return uuid;
|
|
113
|
+
};
|
|
114
|
+
|
|
84
115
|
// src/react/playruo-embed.tsx
|
|
85
116
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
86
117
|
var PlayruoEmbed = ({
|
|
@@ -88,6 +119,7 @@ var PlayruoEmbed = ({
|
|
|
88
119
|
operation,
|
|
89
120
|
operationKey,
|
|
90
121
|
storeUrl,
|
|
122
|
+
clientFingerprint,
|
|
91
123
|
showIframe = false,
|
|
92
124
|
className,
|
|
93
125
|
onReady,
|
|
@@ -573,16 +605,6 @@ var PlayruoEmbed = ({
|
|
|
573
605
|
postExitFullscreenAckToIframe,
|
|
574
606
|
storeUrl
|
|
575
607
|
]);
|
|
576
|
-
const generateUUID = () => {
|
|
577
|
-
if (self.crypto.randomUUID) return self.crypto.randomUUID();
|
|
578
|
-
const bytes = new Uint8Array(16);
|
|
579
|
-
self.crypto.getRandomValues(bytes);
|
|
580
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
581
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
582
|
-
return [...bytes].map(
|
|
583
|
-
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
584
|
-
).join("");
|
|
585
|
-
};
|
|
586
608
|
(0, import_react.useEffect)(() => {
|
|
587
609
|
const handleUUIDMessage = (event) => {
|
|
588
610
|
const iframe = iframeRef.current;
|
|
@@ -595,16 +617,11 @@ var PlayruoEmbed = ({
|
|
|
595
617
|
const { type, requestId } = event.data || {};
|
|
596
618
|
if (type === "playruo_uuid_request") {
|
|
597
619
|
try {
|
|
598
|
-
let storedUUID = localStorage.getItem("playruo_uuid");
|
|
599
|
-
if (!storedUUID) {
|
|
600
|
-
storedUUID = generateUUID();
|
|
601
|
-
localStorage.setItem("playruo_uuid", storedUUID);
|
|
602
|
-
}
|
|
603
620
|
iframe.contentWindow?.postMessage(
|
|
604
621
|
{
|
|
605
622
|
type: "playruo_uuid_response",
|
|
606
623
|
requestId,
|
|
607
|
-
uuid:
|
|
624
|
+
uuid: resolveVisitorUuid(clientFingerprint)
|
|
608
625
|
},
|
|
609
626
|
embedOrigin
|
|
610
627
|
);
|
|
@@ -614,7 +631,7 @@ var PlayruoEmbed = ({
|
|
|
614
631
|
};
|
|
615
632
|
window.addEventListener("message", handleUUIDMessage);
|
|
616
633
|
return () => window.removeEventListener("message", handleUUIDMessage);
|
|
617
|
-
}, [embedOrigin, iframeRef]);
|
|
634
|
+
}, [clientFingerprint, embedOrigin, iframeRef]);
|
|
618
635
|
(0, import_react.useEffect)(() => {
|
|
619
636
|
const handleFullscreenChange = () => {
|
|
620
637
|
const iframe = iframeRef.current;
|
|
@@ -823,7 +840,7 @@ var PlayruoEmbed = ({
|
|
|
823
840
|
{
|
|
824
841
|
ref: iframeRef,
|
|
825
842
|
src,
|
|
826
|
-
allow:
|
|
843
|
+
allow: PLAYRUO_IFRAME_ALLOW,
|
|
827
844
|
className: "w-full h-[70vh] rounded-lg border",
|
|
828
845
|
...{ credentialless: "true" },
|
|
829
846
|
sandbox: "allow-same-origin allow-scripts allow-popups allow-forms allow-presentation allow-top-navigation allow-modals allow-pointer-lock",
|
|
@@ -839,12 +856,6 @@ var PlayruoEmbed = ({
|
|
|
839
856
|
},
|
|
840
857
|
onLoad: () => {
|
|
841
858
|
setIsIframeLoaded(true);
|
|
842
|
-
setTimeout(() => {
|
|
843
|
-
if (iframeRef.current) {
|
|
844
|
-
iframeRef.current.focus();
|
|
845
|
-
iframeRef.current.contentWindow?.focus();
|
|
846
|
-
}
|
|
847
|
-
}, 500);
|
|
848
859
|
},
|
|
849
860
|
onError: () => {
|
|
850
861
|
console.error("[PlayruoEmbed] Iframe failed to load");
|
|
@@ -2138,8 +2149,11 @@ var isPlayruoInternalMessage = (data) => {
|
|
|
2138
2149
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2139
2150
|
0 && (module.exports = {
|
|
2140
2151
|
EmbedTester,
|
|
2152
|
+
PLAYRUO_IFRAME_ALLOW,
|
|
2153
|
+
PLAYRUO_UUID_STORAGE_KEY,
|
|
2141
2154
|
PlayruoEmbed,
|
|
2142
2155
|
buildEmbedUrl,
|
|
2143
2156
|
isPlayruoEmbedMessage,
|
|
2144
|
-
isPlayruoInternalMessage
|
|
2157
|
+
isPlayruoInternalMessage,
|
|
2158
|
+
resolveVisitorUuid
|
|
2145
2159
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { FC, ReactNode } from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* iframe `allow` feature policy delegated to the Playruo player.
|
|
6
|
+
* Must stay aligned with the webapp embed harness (`front/scripts/embed-host/host.js`)
|
|
7
|
+
* and `next.config.ts` Permissions-Policy. `screen-wake-lock` is required so the
|
|
8
|
+
* framed player can hold a Wake Lock while streaming.
|
|
9
|
+
*/
|
|
10
|
+
declare const PLAYRUO_IFRAME_ALLOW = "cross-origin-isolated; fullscreen *; autoplay *; gamepad *; clipboard-write *; web-share *; encrypted-media *; accelerometer *; gyroscope *; screen-wake-lock *";
|
|
11
|
+
|
|
4
12
|
interface PlayruoEmbedState {
|
|
5
13
|
hasPlayedOnce: boolean;
|
|
6
14
|
tryNow: {
|
|
@@ -180,6 +188,13 @@ interface PlayruoEmbedProps {
|
|
|
180
188
|
*/
|
|
181
189
|
operationKey?: string;
|
|
182
190
|
storeUrl?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Stable visitor identity the host already owns (account id, CRM id, …).
|
|
193
|
+
* When set, answers `playruo_uuid_request` with this value and skips
|
|
194
|
+
* `localStorage["playruo_uuid"]`. Omit to keep the SDK-managed UUID.
|
|
195
|
+
* Playruo derives the session fingerprint from the answered `uuid`.
|
|
196
|
+
*/
|
|
197
|
+
clientFingerprint?: string;
|
|
183
198
|
showIframe?: boolean;
|
|
184
199
|
className?: string;
|
|
185
200
|
onReady?: () => void;
|
|
@@ -250,4 +265,12 @@ interface BuildUrlParams {
|
|
|
250
265
|
*/
|
|
251
266
|
declare const buildEmbedUrl: ({ operation, operationKey, storeUrl, }: BuildUrlParams) => string;
|
|
252
267
|
|
|
253
|
-
|
|
268
|
+
declare const PLAYRUO_UUID_STORAGE_KEY = "playruo_uuid";
|
|
269
|
+
/**
|
|
270
|
+
* Visitor identity the host answers on `playruo_uuid_request`.
|
|
271
|
+
* Same rule as PlayruoEmbed `clientFingerprint`: a non-empty value is used as-is
|
|
272
|
+
* and is not written to localStorage. Otherwise the SDK-managed UUID is used.
|
|
273
|
+
*/
|
|
274
|
+
declare const resolveVisitorUuid: (clientFingerprint?: string) => string;
|
|
275
|
+
|
|
276
|
+
export { type DemoCompletedPayload, EmbedTester, type EmbedTesterProps, PLAYRUO_IFRAME_ALLOW, PLAYRUO_UUID_STORAGE_KEY, type PlayruoDemoCompletedMessage, PlayruoEmbed, type PlayruoEmbedActions, type PlayruoEmbedMessage, type PlayruoEmbedPasswordState, type PlayruoEmbedProps, type PlayruoEmbedRenderState, type PlayruoEmbedState, type PlayruoErrorMessage, type PlayruoEventMessage, type PlayruoEventPayload, type PlayruoInternalMessage, type PlayruoPasswordError, type PlayruoPasswordErrorCode, type PlayruoPasswordNotRequiredMessage, type PlayruoPasswordRequiredMessage, type PlayruoPasswordResultMessage, type PlayruoPurchaseRequestMessage, type PlayruoReadyMessage, type PlayruoRequestExitFullscreenMessage, type PlayruoSessionOverMessage, type PlayruoStateUpdateMessage, type PlayruoStreamStartMessage, type PlayruoStreamStopMessage, buildEmbedUrl, isPlayruoEmbedMessage, isPlayruoInternalMessage, resolveVisitorUuid };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { FC, ReactNode } from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* iframe `allow` feature policy delegated to the Playruo player.
|
|
6
|
+
* Must stay aligned with the webapp embed harness (`front/scripts/embed-host/host.js`)
|
|
7
|
+
* and `next.config.ts` Permissions-Policy. `screen-wake-lock` is required so the
|
|
8
|
+
* framed player can hold a Wake Lock while streaming.
|
|
9
|
+
*/
|
|
10
|
+
declare const PLAYRUO_IFRAME_ALLOW = "cross-origin-isolated; fullscreen *; autoplay *; gamepad *; clipboard-write *; web-share *; encrypted-media *; accelerometer *; gyroscope *; screen-wake-lock *";
|
|
11
|
+
|
|
4
12
|
interface PlayruoEmbedState {
|
|
5
13
|
hasPlayedOnce: boolean;
|
|
6
14
|
tryNow: {
|
|
@@ -180,6 +188,13 @@ interface PlayruoEmbedProps {
|
|
|
180
188
|
*/
|
|
181
189
|
operationKey?: string;
|
|
182
190
|
storeUrl?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Stable visitor identity the host already owns (account id, CRM id, …).
|
|
193
|
+
* When set, answers `playruo_uuid_request` with this value and skips
|
|
194
|
+
* `localStorage["playruo_uuid"]`. Omit to keep the SDK-managed UUID.
|
|
195
|
+
* Playruo derives the session fingerprint from the answered `uuid`.
|
|
196
|
+
*/
|
|
197
|
+
clientFingerprint?: string;
|
|
183
198
|
showIframe?: boolean;
|
|
184
199
|
className?: string;
|
|
185
200
|
onReady?: () => void;
|
|
@@ -250,4 +265,12 @@ interface BuildUrlParams {
|
|
|
250
265
|
*/
|
|
251
266
|
declare const buildEmbedUrl: ({ operation, operationKey, storeUrl, }: BuildUrlParams) => string;
|
|
252
267
|
|
|
253
|
-
|
|
268
|
+
declare const PLAYRUO_UUID_STORAGE_KEY = "playruo_uuid";
|
|
269
|
+
/**
|
|
270
|
+
* Visitor identity the host answers on `playruo_uuid_request`.
|
|
271
|
+
* Same rule as PlayruoEmbed `clientFingerprint`: a non-empty value is used as-is
|
|
272
|
+
* and is not written to localStorage. Otherwise the SDK-managed UUID is used.
|
|
273
|
+
*/
|
|
274
|
+
declare const resolveVisitorUuid: (clientFingerprint?: string) => string;
|
|
275
|
+
|
|
276
|
+
export { type DemoCompletedPayload, EmbedTester, type EmbedTesterProps, PLAYRUO_IFRAME_ALLOW, PLAYRUO_UUID_STORAGE_KEY, type PlayruoDemoCompletedMessage, PlayruoEmbed, type PlayruoEmbedActions, type PlayruoEmbedMessage, type PlayruoEmbedPasswordState, type PlayruoEmbedProps, type PlayruoEmbedRenderState, type PlayruoEmbedState, type PlayruoErrorMessage, type PlayruoEventMessage, type PlayruoEventPayload, type PlayruoInternalMessage, type PlayruoPasswordError, type PlayruoPasswordErrorCode, type PlayruoPasswordNotRequiredMessage, type PlayruoPasswordRequiredMessage, type PlayruoPasswordResultMessage, type PlayruoPurchaseRequestMessage, type PlayruoReadyMessage, type PlayruoRequestExitFullscreenMessage, type PlayruoSessionOverMessage, type PlayruoStateUpdateMessage, type PlayruoStreamStartMessage, type PlayruoStreamStopMessage, buildEmbedUrl, isPlayruoEmbedMessage, isPlayruoInternalMessage, resolveVisitorUuid };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/iframe-allow.ts
|
|
2
|
+
var PLAYRUO_IFRAME_ALLOW = "cross-origin-isolated; fullscreen *; autoplay *; gamepad *; clipboard-write *; web-share *; encrypted-media *; accelerometer *; gyroscope *; screen-wake-lock *";
|
|
3
|
+
|
|
1
4
|
// src/react/playruo-embed.tsx
|
|
2
5
|
import { useEffect, useMemo, useRef, useState, useCallback } from "react";
|
|
3
6
|
|
|
@@ -41,6 +44,31 @@ var buildEmbedUrlWithOrigin = (origin, { operation, operationKey, storeUrl }) =>
|
|
|
41
44
|
return url.toString();
|
|
42
45
|
};
|
|
43
46
|
|
|
47
|
+
// src/visitor-uuid.ts
|
|
48
|
+
var PLAYRUO_UUID_STORAGE_KEY = "playruo_uuid";
|
|
49
|
+
var generateUUID = () => {
|
|
50
|
+
if (self.crypto.randomUUID) return self.crypto.randomUUID();
|
|
51
|
+
const bytes = new Uint8Array(16);
|
|
52
|
+
self.crypto.getRandomValues(bytes);
|
|
53
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
54
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
55
|
+
return [...bytes].map(
|
|
56
|
+
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
57
|
+
).join("");
|
|
58
|
+
};
|
|
59
|
+
var resolveVisitorUuid = (clientFingerprint) => {
|
|
60
|
+
const provided = clientFingerprint?.trim();
|
|
61
|
+
if (provided) {
|
|
62
|
+
return provided;
|
|
63
|
+
}
|
|
64
|
+
let uuid = localStorage.getItem(PLAYRUO_UUID_STORAGE_KEY);
|
|
65
|
+
if (!uuid) {
|
|
66
|
+
uuid = generateUUID();
|
|
67
|
+
localStorage.setItem(PLAYRUO_UUID_STORAGE_KEY, uuid);
|
|
68
|
+
}
|
|
69
|
+
return uuid;
|
|
70
|
+
};
|
|
71
|
+
|
|
44
72
|
// src/react/playruo-embed.tsx
|
|
45
73
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
46
74
|
var PlayruoEmbed = ({
|
|
@@ -48,6 +76,7 @@ var PlayruoEmbed = ({
|
|
|
48
76
|
operation,
|
|
49
77
|
operationKey,
|
|
50
78
|
storeUrl,
|
|
79
|
+
clientFingerprint,
|
|
51
80
|
showIframe = false,
|
|
52
81
|
className,
|
|
53
82
|
onReady,
|
|
@@ -533,16 +562,6 @@ var PlayruoEmbed = ({
|
|
|
533
562
|
postExitFullscreenAckToIframe,
|
|
534
563
|
storeUrl
|
|
535
564
|
]);
|
|
536
|
-
const generateUUID = () => {
|
|
537
|
-
if (self.crypto.randomUUID) return self.crypto.randomUUID();
|
|
538
|
-
const bytes = new Uint8Array(16);
|
|
539
|
-
self.crypto.getRandomValues(bytes);
|
|
540
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
541
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
542
|
-
return [...bytes].map(
|
|
543
|
-
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
544
|
-
).join("");
|
|
545
|
-
};
|
|
546
565
|
useEffect(() => {
|
|
547
566
|
const handleUUIDMessage = (event) => {
|
|
548
567
|
const iframe = iframeRef.current;
|
|
@@ -555,16 +574,11 @@ var PlayruoEmbed = ({
|
|
|
555
574
|
const { type, requestId } = event.data || {};
|
|
556
575
|
if (type === "playruo_uuid_request") {
|
|
557
576
|
try {
|
|
558
|
-
let storedUUID = localStorage.getItem("playruo_uuid");
|
|
559
|
-
if (!storedUUID) {
|
|
560
|
-
storedUUID = generateUUID();
|
|
561
|
-
localStorage.setItem("playruo_uuid", storedUUID);
|
|
562
|
-
}
|
|
563
577
|
iframe.contentWindow?.postMessage(
|
|
564
578
|
{
|
|
565
579
|
type: "playruo_uuid_response",
|
|
566
580
|
requestId,
|
|
567
|
-
uuid:
|
|
581
|
+
uuid: resolveVisitorUuid(clientFingerprint)
|
|
568
582
|
},
|
|
569
583
|
embedOrigin
|
|
570
584
|
);
|
|
@@ -574,7 +588,7 @@ var PlayruoEmbed = ({
|
|
|
574
588
|
};
|
|
575
589
|
window.addEventListener("message", handleUUIDMessage);
|
|
576
590
|
return () => window.removeEventListener("message", handleUUIDMessage);
|
|
577
|
-
}, [embedOrigin, iframeRef]);
|
|
591
|
+
}, [clientFingerprint, embedOrigin, iframeRef]);
|
|
578
592
|
useEffect(() => {
|
|
579
593
|
const handleFullscreenChange = () => {
|
|
580
594
|
const iframe = iframeRef.current;
|
|
@@ -783,7 +797,7 @@ var PlayruoEmbed = ({
|
|
|
783
797
|
{
|
|
784
798
|
ref: iframeRef,
|
|
785
799
|
src,
|
|
786
|
-
allow:
|
|
800
|
+
allow: PLAYRUO_IFRAME_ALLOW,
|
|
787
801
|
className: "w-full h-[70vh] rounded-lg border",
|
|
788
802
|
...{ credentialless: "true" },
|
|
789
803
|
sandbox: "allow-same-origin allow-scripts allow-popups allow-forms allow-presentation allow-top-navigation allow-modals allow-pointer-lock",
|
|
@@ -799,12 +813,6 @@ var PlayruoEmbed = ({
|
|
|
799
813
|
},
|
|
800
814
|
onLoad: () => {
|
|
801
815
|
setIsIframeLoaded(true);
|
|
802
|
-
setTimeout(() => {
|
|
803
|
-
if (iframeRef.current) {
|
|
804
|
-
iframeRef.current.focus();
|
|
805
|
-
iframeRef.current.contentWindow?.focus();
|
|
806
|
-
}
|
|
807
|
-
}, 500);
|
|
808
816
|
},
|
|
809
817
|
onError: () => {
|
|
810
818
|
console.error("[PlayruoEmbed] Iframe failed to load");
|
|
@@ -2097,8 +2105,11 @@ var isPlayruoInternalMessage = (data) => {
|
|
|
2097
2105
|
};
|
|
2098
2106
|
export {
|
|
2099
2107
|
EmbedTester,
|
|
2108
|
+
PLAYRUO_IFRAME_ALLOW,
|
|
2109
|
+
PLAYRUO_UUID_STORAGE_KEY,
|
|
2100
2110
|
PlayruoEmbed,
|
|
2101
2111
|
buildEmbedUrl,
|
|
2102
2112
|
isPlayruoEmbedMessage,
|
|
2103
|
-
isPlayruoInternalMessage
|
|
2113
|
+
isPlayruoInternalMessage,
|
|
2114
|
+
resolveVisitorUuid
|
|
2104
2115
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playruo/embed",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "React SDK to embed Playruo with postMessage API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -53,6 +53,8 @@
|
|
|
53
53
|
"check:exports": "attw --pack .",
|
|
54
54
|
"test": "npm run build && vitest run --coverage",
|
|
55
55
|
"test:browser": "vitest run --config vitest.browser.config.ts",
|
|
56
|
-
"test:watch": "npm run build && vitest"
|
|
56
|
+
"test:watch": "npm run build && vitest",
|
|
57
|
+
"docs:notion:dry-run": "node scripts/sync-notion-docs.mjs",
|
|
58
|
+
"docs:notion:publish": "node scripts/sync-notion-docs.mjs --publish"
|
|
57
59
|
}
|
|
58
60
|
}
|