castle-web-sdk 0.4.9 → 0.4.10
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 +36 -0
- package/dist/castle.d.ts +2 -0
- package/dist/castle.js +1 -0
- package/dist/commands.d.ts +9 -0
- package/dist/haptics.d.ts +6 -0
- package/dist/haptics.js +36 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ import { setup, initCard, Storage, Leaderboard } from "castle-web-sdk";
|
|
|
20
20
|
- [User](#user)
|
|
21
21
|
- [Pass](#pass)
|
|
22
22
|
- [Portal](#portal)
|
|
23
|
+
- [Haptics](#haptics)
|
|
23
24
|
- [Lifecycle](#lifecycle)
|
|
24
25
|
- [Setup](#setup)
|
|
25
26
|
- [CastleError](#castleerror)
|
|
@@ -269,6 +270,41 @@ link.addEventListener("pointerenter", () => {
|
|
|
269
270
|
});
|
|
270
271
|
```
|
|
271
272
|
|
|
273
|
+
## Haptics
|
|
274
|
+
|
|
275
|
+
`Haptics` plays a short device vibration ("buzz") for tactile feedback —
|
|
276
|
+
a tap confirmation, a success chime, an error shake. The host owns the
|
|
277
|
+
effect: the Castle mobile app plays a native haptic, the website uses the
|
|
278
|
+
browser's vibration API where available, and the dev server or an
|
|
279
|
+
unsupported device does nothing.
|
|
280
|
+
|
|
281
|
+
### `Haptics.play(style): Promise<HapticsResult>`
|
|
282
|
+
|
|
283
|
+
Plays a haptic in one of seven styles:
|
|
284
|
+
|
|
285
|
+
- `'light'`, `'medium'`, `'heavy'` — impact taps of increasing strength.
|
|
286
|
+
- `'selection'` — a light tick, e.g. moving through options.
|
|
287
|
+
- `'success'`, `'warning'`, `'error'` — notification patterns.
|
|
288
|
+
|
|
289
|
+
Usually you don't await it — fire it and move on:
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
button.onclick = () => {
|
|
293
|
+
Haptics.play("light");
|
|
294
|
+
doTheThing();
|
|
295
|
+
};
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The returned `HapticsResult` has a `status`, if you want to branch on it:
|
|
299
|
+
|
|
300
|
+
- `'triggered'` — the host played (or accepted) the haptic.
|
|
301
|
+
- `'unavailable'` — this host or device can't play haptics (e.g. the dev
|
|
302
|
+
server, or a browser with no vibration support). Nothing was played.
|
|
303
|
+
|
|
304
|
+
Haptics respect the player's settings — if a player has muted haptics,
|
|
305
|
+
`play` does nothing and resolves `'unavailable'`. Rapid repeated calls may
|
|
306
|
+
be coalesced, so it's safe to call on frequent events.
|
|
307
|
+
|
|
272
308
|
## Lifecycle
|
|
273
309
|
|
|
274
310
|
`Lifecycle` tells the host when the deck has painted its first frame, so
|
package/dist/castle.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { isEdit } from "./context";
|
|
2
2
|
export { CastleError } from "./errors";
|
|
3
|
+
export { Haptics } from "./haptics";
|
|
4
|
+
export type { CastleHapticsApi, HapticsResult, HapticsStatus, HapticStyle } from "./haptics";
|
|
3
5
|
export { Leaderboard } from "./leaderboard";
|
|
4
6
|
export type { LeaderboardData, LeaderboardEntry, LeaderboardOptions, LeaderboardScope, LeaderboardSort, } from "./leaderboard";
|
|
5
7
|
export { Lifecycle } from "./lifecycle";
|
package/dist/castle.js
CHANGED
package/dist/commands.d.ts
CHANGED
|
@@ -32,6 +32,11 @@ export type PortalPrefetchStatus = "prefetching" | "rejected" | "unavailable";
|
|
|
32
32
|
export interface PortalPrefetchResult {
|
|
33
33
|
status: PortalPrefetchStatus;
|
|
34
34
|
}
|
|
35
|
+
export type HapticStyle = "light" | "medium" | "heavy" | "selection" | "success" | "warning" | "error";
|
|
36
|
+
export type HapticsStatus = "triggered" | "unavailable";
|
|
37
|
+
export interface HapticsResult {
|
|
38
|
+
status: HapticsStatus;
|
|
39
|
+
}
|
|
35
40
|
export interface CommandParams {
|
|
36
41
|
"deckStorage.load": Record<string, never>;
|
|
37
42
|
"deckStorage.update": {
|
|
@@ -71,6 +76,9 @@ export interface CommandParams {
|
|
|
71
76
|
"portal.prefetch": {
|
|
72
77
|
targetDeckId: string;
|
|
73
78
|
};
|
|
79
|
+
"haptics.play": {
|
|
80
|
+
style: HapticStyle;
|
|
81
|
+
};
|
|
74
82
|
}
|
|
75
83
|
export interface CommandResult {
|
|
76
84
|
"deckStorage.load": {
|
|
@@ -109,6 +117,7 @@ export interface CommandResult {
|
|
|
109
117
|
"pass.offer": PassOfferResult;
|
|
110
118
|
"portal.open": PortalOpenResult;
|
|
111
119
|
"portal.prefetch": PortalPrefetchResult;
|
|
120
|
+
"haptics.play": HapticsResult;
|
|
112
121
|
}
|
|
113
122
|
export type CommandName = keyof CommandParams;
|
|
114
123
|
export interface SerializedCommandError {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HapticStyle, HapticsResult } from "./commands";
|
|
2
|
+
export type { HapticStyle, HapticsResult, HapticsStatus } from "./commands";
|
|
3
|
+
export interface CastleHapticsApi {
|
|
4
|
+
play(style: HapticStyle): Promise<HapticsResult>;
|
|
5
|
+
}
|
|
6
|
+
export declare const Haptics: CastleHapticsApi;
|
package/dist/haptics.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Haptics — a deck-facing capability for playing a device haptic (a "buzz").
|
|
2
|
+
// Like pass and portal, the deck stays capability-AGNOSTIC: it asks for a
|
|
3
|
+
// haptic and gets back one normalized outcome regardless of platform. The host
|
|
4
|
+
// owns the effect:
|
|
5
|
+
// - mobile app : plays a native haptic (Taptic Engine / VibrationEffect),
|
|
6
|
+
// subject to the host's own rate-limiting and device support
|
|
7
|
+
// - web player : best-effort navigator.vibrate; `unavailable` where the
|
|
8
|
+
// browser has no vibration API (e.g. iOS Safari)
|
|
9
|
+
// - dev CLI : no host handler, so `unavailable`
|
|
10
|
+
// A haptic is a fleeting device effect, not deck-scoped state, so unlike
|
|
11
|
+
// pass/portal the host requires no deckId. Decks usually fire-and-forget (don't
|
|
12
|
+
// await); the returned status just says whether the host could play it.
|
|
13
|
+
import { CastleError } from "./errors";
|
|
14
|
+
import { hostRequest } from "./transport";
|
|
15
|
+
const HAPTIC_STYLES = [
|
|
16
|
+
"light",
|
|
17
|
+
"medium",
|
|
18
|
+
"heavy",
|
|
19
|
+
"selection",
|
|
20
|
+
"success",
|
|
21
|
+
"warning",
|
|
22
|
+
"error",
|
|
23
|
+
];
|
|
24
|
+
export const Haptics = {
|
|
25
|
+
play,
|
|
26
|
+
};
|
|
27
|
+
async function play(style) {
|
|
28
|
+
if (!HAPTIC_STYLES.includes(style)) {
|
|
29
|
+
throw new CastleError({
|
|
30
|
+
code: "INVALID_ARGUMENT",
|
|
31
|
+
message: `Haptics.play style must be one of: ${HAPTIC_STYLES.join(", ")}.`,
|
|
32
|
+
operation: "Haptics.play",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return hostRequest("haptics.play", { style });
|
|
36
|
+
}
|