@playruo/embed 1.2.1 → 1.2.2
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 +0 -299
- package/dist/index.cjs +497 -27
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +486 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,302 +1,3 @@
|
|
|
1
1
|
# @playruo/embed
|
|
2
2
|
|
|
3
3
|
React SDK to embed Playruo via iframe + postMessage.
|
|
4
|
-
|
|
5
|
-
See the official docs: [Playruo Embed Documentation](https://playruo.notion.site/Playruo-Embed-Documentation-268a5e7d674180dd901ae0753187d7c1?pvs=74).
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm i @playruo/embed
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Quick start (Next.js / React)
|
|
14
|
-
|
|
15
|
-
```tsx
|
|
16
|
-
"use client";
|
|
17
|
-
import { PlayruoEmbed } from "@playruo/embed";
|
|
18
|
-
|
|
19
|
-
export const Demo = () => (
|
|
20
|
-
<PlayruoEmbed
|
|
21
|
-
operation="iframe"
|
|
22
|
-
storeUrl="https://store.steampowered.com/app/2751000/..."
|
|
23
|
-
showIframe
|
|
24
|
-
onReady={() => console.log("ready")}
|
|
25
|
-
onStateChange={(state) => console.log("state", state)}
|
|
26
|
-
onDemoCompleted={(data) => console.log("completed", data)}
|
|
27
|
-
onPurchaseRequest={({ storeUrl }) => {
|
|
28
|
-
// Example: open the store page in a new tab
|
|
29
|
-
window.open(storeUrl, "_blank", "noopener,noreferrer");
|
|
30
|
-
}}
|
|
31
|
-
onError={(message) => console.error(message)}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Headless mode (with renderState)
|
|
37
|
-
|
|
38
|
-
```tsx
|
|
39
|
-
"use client";
|
|
40
|
-
import { PlayruoEmbed } from "@playruo/embed";
|
|
41
|
-
import { useState } from "react";
|
|
42
|
-
|
|
43
|
-
export const Demo = () => {
|
|
44
|
-
const [showIframe, setShowIframe] = useState(false);
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<PlayruoEmbed
|
|
48
|
-
operation="iframe"
|
|
49
|
-
storeUrl="https://store.steampowered.com/app/2751000/..."
|
|
50
|
-
showIframe={showIframe}
|
|
51
|
-
renderState={({ status, message, actions }) => {
|
|
52
|
-
if (status === "loading") return <div>Loading demo…</div>;
|
|
53
|
-
if (status === "error") return <div>Error: {message}</div>;
|
|
54
|
-
|
|
55
|
-
if (status === "available") {
|
|
56
|
-
return (
|
|
57
|
-
<div className="flex gap-3">
|
|
58
|
-
<button
|
|
59
|
-
onClick={() => {
|
|
60
|
-
setShowIframe(true);
|
|
61
|
-
actions.tryNow();
|
|
62
|
-
}}
|
|
63
|
-
disabled={!actions.canTryNow}
|
|
64
|
-
>
|
|
65
|
-
Try Now
|
|
66
|
-
</button>
|
|
67
|
-
<button
|
|
68
|
-
onClick={actions.buyNow}
|
|
69
|
-
disabled={!actions.canBuyNow}
|
|
70
|
-
>
|
|
71
|
-
Buy Now
|
|
72
|
-
</button>
|
|
73
|
-
</div>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// unavailable
|
|
78
|
-
return (
|
|
79
|
-
<div className="flex gap-3">
|
|
80
|
-
<span>{message ?? "Unavailable"}</span>
|
|
81
|
-
<button
|
|
82
|
-
onClick={actions.buyNow}
|
|
83
|
-
disabled={!actions.canBuyNow}
|
|
84
|
-
>
|
|
85
|
-
Buy Now
|
|
86
|
-
</button>
|
|
87
|
-
</div>
|
|
88
|
-
);
|
|
89
|
-
}}
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Props
|
|
96
|
-
|
|
97
|
-
- **operation**: string (optional, default: "iframe")
|
|
98
|
-
- **storeUrl**: string (optional)
|
|
99
|
-
- **showIframe**: boolean (optional)
|
|
100
|
-
- **className**: string (optional)
|
|
101
|
-
- **onReady()**: callback when the iframe signals readiness
|
|
102
|
-
- **onStateChange(state)**: receives live availability state
|
|
103
|
-
- **onDemoCompleted(data)**: fired when the demo session completes
|
|
104
|
-
- **onPurchaseRequest({ storeUrl })**: fired when purchase is requested
|
|
105
|
-
- **onError(message)**: fired on error
|
|
106
|
-
|
|
107
|
-
#### Render API
|
|
108
|
-
|
|
109
|
-
- **renderState({ status, message, actions })**: single render entry point
|
|
110
|
-
- `status`: "loading" | "available" | "unavailable" | "error"
|
|
111
|
-
- `message?`: optional status message (e.g. availability reason)
|
|
112
|
-
- `actions`: object with `tryNow()`, `buyNow()`, `canTryNow`, `canBuyNow`
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
### Events
|
|
116
|
-
|
|
117
|
-
- **onReady()**
|
|
118
|
-
- **onStateChange(state)**
|
|
119
|
-
- **onDemoCompleted(data)**
|
|
120
|
-
- **onPurchaseRequest({ storeUrl })**
|
|
121
|
-
- **onError(error)**
|
|
122
|
-
|
|
123
|
-
## State shape
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
export interface PlayruoEmbedState {
|
|
127
|
-
hasPlayedOnce: boolean;
|
|
128
|
-
tryNow: { available: boolean; status?: string };
|
|
129
|
-
buyNow: { available: boolean; status?: string };
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Actions API
|
|
134
|
-
|
|
135
|
-
The `renderState` callback receives an `actions` object with:
|
|
136
|
-
|
|
137
|
-
- **`actions.tryNow()`** → sends `try_now` command to the iframe
|
|
138
|
-
- **`actions.buyNow()`** → sends `buy_now` command to the iframe
|
|
139
|
-
- **`actions.canTryNow`** → boolean indicating if try now is available
|
|
140
|
-
- **`actions.canBuyNow`** → boolean indicating if buy now is available
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
renderState={({ actions }) => (
|
|
144
|
-
<button onClick={actions.tryNow} disabled={!actions.canTryNow}>
|
|
145
|
-
Try Now
|
|
146
|
-
</button>
|
|
147
|
-
)}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Incoming messages (from iframe)
|
|
151
|
-
|
|
152
|
-
The component listens to Playruo postMessage events and triggers the corresponding callbacks:
|
|
153
|
-
|
|
154
|
-
- `"playruo_ready"` → `onReady()`
|
|
155
|
-
- `"playruo_state_update"` → `onStateChange(state)`
|
|
156
|
-
- `"playruo_demo_completed"` → `onDemoCompleted(data)`
|
|
157
|
-
- `"playruo_purchase_request"` → `onPurchaseRequest({ storeUrl })`
|
|
158
|
-
- `"playruo_error"` → `onError(message)`
|
|
159
|
-
|
|
160
|
-
## URL builder (Advanced)
|
|
161
|
-
|
|
162
|
-
For advanced use cases, you can build the iframe URL manually:
|
|
163
|
-
|
|
164
|
-
```ts
|
|
165
|
-
import { buildEmbedUrl } from "@playruo/embed";
|
|
166
|
-
|
|
167
|
-
const url = buildEmbedUrl({
|
|
168
|
-
baseUrl: "https://playruo.example.com",
|
|
169
|
-
operation: "iframe", // optional, default: "iframe"
|
|
170
|
-
storeUrl: "https://store.steampowered.com/app/2751000/...", // optional
|
|
171
|
-
});
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
The URL points to `{baseUrl}/embed` with query params:
|
|
175
|
-
- `operation` (optional)
|
|
176
|
-
- `storeUrl` (optional)
|
|
177
|
-
|
|
178
|
-
## Iframe behavior
|
|
179
|
-
|
|
180
|
-
- The iframe is always present in the DOM. Set `showIframe` to control visibility.
|
|
181
|
-
- The iframe has `allow="fullscreen *; autoplay *; gamepad *"`.
|
|
182
|
-
|
|
183
|
-
## TypeScript Types
|
|
184
|
-
|
|
185
|
-
### Component Types
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import type {
|
|
189
|
-
PlayruoEmbedProps,
|
|
190
|
-
PlayruoEmbedState,
|
|
191
|
-
PlayruoEmbedActions,
|
|
192
|
-
PlayruoEmbedRenderState,
|
|
193
|
-
DemoCompletedPayload,
|
|
194
|
-
} from "@playruo/embed";
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### PostMessage Communication Types
|
|
198
|
-
|
|
199
|
-
For advanced use cases where you need to handle communication with the embed iframe directly:
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
import type {
|
|
203
|
-
PlayruoEmbedMessage,
|
|
204
|
-
PlayruoEmbedCommand,
|
|
205
|
-
PlayruoReadyMessage,
|
|
206
|
-
PlayruoStateUpdateMessage,
|
|
207
|
-
PlayruoPurchaseRequestMessage,
|
|
208
|
-
PlayruoDemoCompletedMessage,
|
|
209
|
-
PlayruoErrorMessage,
|
|
210
|
-
TryNowCommand,
|
|
211
|
-
BuyNowCommand,
|
|
212
|
-
GetStateCommand,
|
|
213
|
-
} from "@playruo/embed";
|
|
214
|
-
import { isPlayruoEmbedMessage, isPlayruoEmbedCommand } from "@playruo/embed";
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
#### Example: Custom Message Handler
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
"use client";
|
|
221
|
-
import { useEffect } from "react";
|
|
222
|
-
import type { PlayruoEmbedMessage } from "@playruo/embed";
|
|
223
|
-
import { isPlayruoEmbedMessage } from "@playruo/embed";
|
|
224
|
-
|
|
225
|
-
export const MyComponent = () => {
|
|
226
|
-
useEffect(() => {
|
|
227
|
-
const handleMessage = (event: MessageEvent) => {
|
|
228
|
-
if (isPlayruoEmbedMessage(event.data)) {
|
|
229
|
-
const message = event.data as PlayruoEmbedMessage;
|
|
230
|
-
|
|
231
|
-
switch (message.type) {
|
|
232
|
-
case 'playruo_ready':
|
|
233
|
-
console.log("Embed is ready!");
|
|
234
|
-
break;
|
|
235
|
-
case 'playruo_state_update':
|
|
236
|
-
console.log("State updated:", message.data);
|
|
237
|
-
break;
|
|
238
|
-
case 'playruo_purchase_request':
|
|
239
|
-
window.open(message.data.storeUrl, "_blank");
|
|
240
|
-
break;
|
|
241
|
-
case 'playruo_demo_completed':
|
|
242
|
-
console.log("Demo completed:", message.data.reason);
|
|
243
|
-
break;
|
|
244
|
-
case 'playruo_error':
|
|
245
|
-
console.error("Embed error:", message.data);
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
window.addEventListener('message', handleMessage);
|
|
252
|
-
return () => window.removeEventListener('message', handleMessage);
|
|
253
|
-
}, []);
|
|
254
|
-
|
|
255
|
-
// ...
|
|
256
|
-
};
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
#### Example: Sending Commands
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import type { PlayruoEmbedCommand } from "@playruo/embed";
|
|
263
|
-
|
|
264
|
-
const sendCommandToEmbed = (command: PlayruoEmbedCommand) => {
|
|
265
|
-
const iframe = document.querySelector('iframe');
|
|
266
|
-
iframe?.contentWindow?.postMessage(command, '*');
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
// Send commands
|
|
270
|
-
sendCommandToEmbed({ type: 'try_now' });
|
|
271
|
-
sendCommandToEmbed({ type: 'buy_now' });
|
|
272
|
-
sendCommandToEmbed({ type: 'get_state' });
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### Exported Types
|
|
276
|
-
|
|
277
|
-
**Component:**
|
|
278
|
-
- `PlayruoEmbed` - Main React component
|
|
279
|
-
- `PlayruoEmbedProps` - Component props
|
|
280
|
-
- `PlayruoEmbedActions` - Actions API
|
|
281
|
-
- `PlayruoEmbedRenderState` - Render state API
|
|
282
|
-
- `PlayruoEmbedState` - Embed state
|
|
283
|
-
- `DemoCompletedPayload` - Demo completion data
|
|
284
|
-
|
|
285
|
-
**Messages (Embed → Host):**
|
|
286
|
-
- `PlayruoEmbedMessage` - Union of all message types
|
|
287
|
-
- `PlayruoReadyMessage`
|
|
288
|
-
- `PlayruoStateUpdateMessage`
|
|
289
|
-
- `PlayruoPurchaseRequestMessage`
|
|
290
|
-
- `PlayruoDemoCompletedMessage`
|
|
291
|
-
- `PlayruoErrorMessage`
|
|
292
|
-
|
|
293
|
-
**Commands (Host → Embed):**
|
|
294
|
-
- `PlayruoEmbedCommand` - Union of all command types
|
|
295
|
-
- `TryNowCommand`
|
|
296
|
-
- `BuyNowCommand`
|
|
297
|
-
- `GetStateCommand`
|
|
298
|
-
|
|
299
|
-
**Utilities:**
|
|
300
|
-
- `buildEmbedUrl` - URL builder function
|
|
301
|
-
- `isPlayruoEmbedMessage` - Type guard for messages
|
|
302
|
-
- `isPlayruoEmbedCommand` - Type guard for commands
|