p2p-lockstep-kit-ui 0.1.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 +170 -0
- package/dist/_headers +8 -0
- package/dist/app-shell.d.ts +11 -0
- package/dist/components/action-bar.d.ts +9 -0
- package/dist/components/confirm-dialog.d.ts +9 -0
- package/dist/components/share-panel.d.ts +9 -0
- package/dist/components/status-panel.d.ts +8 -0
- package/dist/components/toast-message.d.ts +8 -0
- package/dist/config.d.ts +1 -0
- package/dist/game/board-host.d.ts +7 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +3953 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/game-page.d.ts +9 -0
- package/dist/pages/lobby-page.d.ts +9 -0
- package/dist/style.css +3 -0
- package/dist/types.d.ts +76 -0
- package/dist/utils/dom.d.ts +3 -0
- package/dist/utils/events.d.ts +1 -0
- package/dist/utils/share.d.ts +10 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# p2p-lockstep-kit-ui
|
|
2
|
+
|
|
3
|
+
Web Components UI shell for `p2p-lockstep-kit-network` and `p2p-lockstep-kit-session`.
|
|
4
|
+
|
|
5
|
+
The UI package owns the generic app surface:
|
|
6
|
+
|
|
7
|
+
- lobby page
|
|
8
|
+
- signaling registration
|
|
9
|
+
- peer connection
|
|
10
|
+
- share link and QR code
|
|
11
|
+
- game page shell
|
|
12
|
+
- ready / start / undo / restart controls
|
|
13
|
+
- request dialogs and toast messages
|
|
14
|
+
- board host container
|
|
15
|
+
|
|
16
|
+
Game projects mount their actual board into the board host and talk to the session through the runtime exposed by the UI element.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install p2p-lockstep-kit-ui
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The UI package depends on:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
p2p-lockstep-kit-network
|
|
28
|
+
p2p-lockstep-kit-session
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Game projects do not need to instantiate those packages directly for the common lobby/game flow.
|
|
32
|
+
|
|
33
|
+
## Basic Usage
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import "p2p-lockstep-kit-ui";
|
|
37
|
+
import "p2p-lockstep-kit-ui/style.css";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<p2p-lockstep-app
|
|
42
|
+
game-title="Gomoku"
|
|
43
|
+
session-id="gomoku"
|
|
44
|
+
></p2p-lockstep-app>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The default signaling server is `wss://signal.jiahengli.xyz`. Override it only when you
|
|
48
|
+
run your own signaling endpoint:
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<p2p-lockstep-app
|
|
52
|
+
game-title="Gomoku"
|
|
53
|
+
session-id="gomoku"
|
|
54
|
+
signal-url="wss://signal.example.com"
|
|
55
|
+
></p2p-lockstep-app>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Mounting A Game Board
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import "p2p-lockstep-kit-ui";
|
|
62
|
+
import "p2p-lockstep-kit-ui/style.css";
|
|
63
|
+
import type { GameRuntime, P2PLockstepAppElement } from "p2p-lockstep-kit-ui";
|
|
64
|
+
|
|
65
|
+
const app = document.querySelector("p2p-lockstep-app") as P2PLockstepAppElement | null;
|
|
66
|
+
|
|
67
|
+
if (!app) {
|
|
68
|
+
throw new Error("Missing p2p-lockstep-app");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
await customElements.whenDefined("p2p-lockstep-app");
|
|
72
|
+
|
|
73
|
+
const runtime = app.getRuntime() as GameRuntime | null;
|
|
74
|
+
const boardHost = app.getBoardHost();
|
|
75
|
+
|
|
76
|
+
if (!runtime || !boardHost) {
|
|
77
|
+
throw new Error("Lockstep UI is not ready");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const board = document.createElement("div");
|
|
81
|
+
board.className = "h-full";
|
|
82
|
+
boardHost.append(board);
|
|
83
|
+
|
|
84
|
+
runtime.observer.subscribe({
|
|
85
|
+
onStateChange(snapshot) {
|
|
86
|
+
// Render board state from snapshot.history, snapshot.turn, and local/remote states.
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
board.addEventListener("click", () => {
|
|
91
|
+
runtime.actions.move({
|
|
92
|
+
// Game-specific move payload.
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Runtime Boundary
|
|
98
|
+
|
|
99
|
+
The UI exposes the runtime from the app element:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
const runtime = app.getRuntime();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Game runtime actions:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
runtime.actions.move(move);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Ready, start, undo, restart, approve, and reject are owned by the UI shell
|
|
112
|
+
controls. Game packages should not drive those controls directly.
|
|
113
|
+
|
|
114
|
+
Runtime state:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
runtime.observer.subscribe({
|
|
118
|
+
onStateChange(snapshot) {},
|
|
119
|
+
onConnectionChange(connected) {},
|
|
120
|
+
onGameEvent(event) {},
|
|
121
|
+
onError(error) {},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Network details are intentionally kept private to the UI shell for the standard flow.
|
|
126
|
+
|
|
127
|
+
## Package Design
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
game project
|
|
131
|
+
-> imports p2p-lockstep-kit-ui
|
|
132
|
+
-> mounts board into p2p-lockstep-app.getBoardHost()
|
|
133
|
+
-> sends moves through p2p-lockstep-app.getRuntime().actions
|
|
134
|
+
|
|
135
|
+
p2p-lockstep-kit-ui
|
|
136
|
+
-> owns lobby/game pages and common controls
|
|
137
|
+
-> creates NetworkClient
|
|
138
|
+
-> creates session
|
|
139
|
+
-> maps session snapshots into UI state
|
|
140
|
+
|
|
141
|
+
p2p-lockstep-kit-network / p2p-lockstep-kit-session
|
|
142
|
+
-> provide transport and lockstep state
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
pnpm install
|
|
149
|
+
pnpm dev
|
|
150
|
+
pnpm typecheck
|
|
151
|
+
pnpm build
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The local Vite config aliases `p2p-lockstep-kit-ui`, `p2p-lockstep-kit-network`, and `p2p-lockstep-kit-session` to local source folders for development. Published consumers resolve the package dependencies normally.
|
|
155
|
+
|
|
156
|
+
## Cloudflare Pages Demo
|
|
157
|
+
|
|
158
|
+
`pnpm build` builds the npm library package and does not emit an `index.html`.
|
|
159
|
+
Use the Pages build when deploying the demo site:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pnpm build:pages
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Cloudflare Pages settings:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
Build command: pnpm build:pages
|
|
169
|
+
Build output directory: dist-pages
|
|
170
|
+
```
|
package/dist/_headers
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GameRuntime } from "./types";
|
|
2
|
+
export declare class P2PLockstepAppElement extends HTMLElement {
|
|
3
|
+
#private;
|
|
4
|
+
static get observedAttributes(): string[];
|
|
5
|
+
connectedCallback(): void;
|
|
6
|
+
disconnectedCallback(): void;
|
|
7
|
+
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
8
|
+
getRuntime(): GameRuntime | null;
|
|
9
|
+
getBoardHost(): HTMLDivElement | null;
|
|
10
|
+
render(): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ActionBarState } from "../types";
|
|
2
|
+
export declare class P2PLockstepActionBarElement extends HTMLElement {
|
|
3
|
+
#private;
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
disconnectedCallback(): void;
|
|
6
|
+
set state(value: ActionBarState);
|
|
7
|
+
get state(): ActionBarState;
|
|
8
|
+
render(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DialogState } from "../types";
|
|
2
|
+
export declare class P2PLockstepConfirmDialogElement extends HTMLElement {
|
|
3
|
+
#private;
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
disconnectedCallback(): void;
|
|
6
|
+
set state(value: DialogState);
|
|
7
|
+
get state(): DialogState;
|
|
8
|
+
render(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SharePanelState } from "../types";
|
|
2
|
+
export declare class P2PLockstepSharePanelElement extends HTMLElement {
|
|
3
|
+
#private;
|
|
4
|
+
connectedCallback(): void;
|
|
5
|
+
disconnectedCallback(): void;
|
|
6
|
+
set state(value: SharePanelState);
|
|
7
|
+
get state(): SharePanelState;
|
|
8
|
+
render(): Promise<void>;
|
|
9
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_SIGNAL_URL = "wss://signal.jiahengli.xyz";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { DEFAULT_SIGNAL_URL } from "./config";
|
|
2
|
+
export declare const defineP2PLockstepUi: () => void;
|
|
3
|
+
export * from "./types";
|
|
4
|
+
export { P2PLockstepActionBarElement } from "./components/action-bar";
|
|
5
|
+
export { P2PLockstepConfirmDialogElement } from "./components/confirm-dialog";
|
|
6
|
+
export { P2PLockstepSharePanelElement } from "./components/share-panel";
|
|
7
|
+
export { P2PLockstepStatusPanelElement } from "./components/status-panel";
|
|
8
|
+
export { P2PLockstepToastMessageElement } from "./components/toast-message";
|
|
9
|
+
export { P2PLockstepBoardHostElement } from "./game/board-host";
|
|
10
|
+
export { P2PLockstepLobbyPageElement } from "./pages/lobby-page";
|
|
11
|
+
export { P2PLockstepGamePageElement } from "./pages/game-page";
|
|
12
|
+
export { P2PLockstepAppElement } from "./app-shell";
|