@littlepartytime/dev-kit 1.10.0 → 1.12.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.
@@ -14,15 +14,25 @@ export default function App() {
14
14
  });
15
15
 
16
16
  return (
17
- <div className="min-h-screen flex flex-col">
17
+ <div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
18
18
  {/* Nav */}
19
- <nav className="bg-zinc-900 border-b border-zinc-800 px-4 py-2 flex gap-4">
20
- <span className="text-amber-500 font-bold mr-4">LPT Dev Kit</span>
19
+ <nav style={{ background: '#18181b', borderBottom: '1px solid #27272a', padding: '8px 16px', display: 'flex', gap: 16, alignItems: 'center' }}>
20
+ <span style={{ color: '#f59e0b', fontWeight: 700, marginRight: 16 }}>LPT Dev Kit</span>
21
21
  {(['preview', 'play', 'debug'] as Page[]).map((p) => (
22
22
  <button
23
23
  key={p}
24
24
  onClick={() => { setPage(p); history.pushState(null, '', `/${p}`); }}
25
- className={`px-3 py-1 rounded ${page === p ? 'bg-amber-600 text-white' : 'text-zinc-400 hover:text-white'}`}
25
+ className="dk-nav-btn"
26
+ style={{
27
+ padding: '4px 12px',
28
+ borderRadius: 4,
29
+ border: 'none',
30
+ cursor: 'pointer',
31
+ fontSize: 14,
32
+ ...(page === p
33
+ ? { background: '#d97706', color: '#fff' }
34
+ : { background: 'transparent', color: '#a1a1aa' }),
35
+ }}
26
36
  >
27
37
  {p.charAt(0).toUpperCase() + p.slice(1)}
28
38
  </button>
@@ -30,7 +40,7 @@ export default function App() {
30
40
  </nav>
31
41
 
32
42
  {/* Content */}
33
- <main className="flex-1 p-4">
43
+ <main style={{ flex: 1, padding: 16 }}>
34
44
  {page === 'preview' && <Preview />}
35
45
  {page === 'play' && <Play />}
36
46
  {page === 'debug' && <Debug />}
@@ -40,15 +40,14 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
40
40
  return (
41
41
  <div
42
42
  ref={containerRef}
43
- className="flex items-center justify-center h-full overflow-hidden"
44
- style={{ flex: 1, minWidth: 0, minHeight: 0 }}
43
+ style={{ flex: 1, minWidth: 0, minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', overflow: 'hidden' }}
45
44
  >
46
45
  {/* Wrapper sized to the scaled phone for correct layout flow */}
47
46
  <div style={{ width: BODY_W * scale, height: BODY_H * scale, flexShrink: 0 }}>
48
47
  {/* Phone body at original pixel size, visually scaled */}
49
48
  <div
50
- className="relative"
51
49
  style={{
50
+ position: 'relative',
52
51
  width: BODY_W,
53
52
  height: BODY_H,
54
53
  transform: `scale(${scale})`,
@@ -57,8 +56,9 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
57
56
  >
58
57
  {/* Frame / bezel */}
59
58
  <div
60
- className="absolute inset-0"
61
59
  style={{
60
+ position: 'absolute',
61
+ inset: 0,
62
62
  borderRadius: OUTER_R,
63
63
  background: '#1c1c1e',
64
64
  boxShadow:
@@ -68,8 +68,10 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
68
68
 
69
69
  {/* Screen */}
70
70
  <div
71
- className="absolute overflow-hidden bg-black"
72
71
  style={{
72
+ position: 'absolute',
73
+ overflow: 'hidden',
74
+ background: '#000',
73
75
  top: BEZEL,
74
76
  left: BEZEL,
75
77
  width: SCREEN_W,
@@ -82,8 +84,9 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
82
84
  contain:paint makes this the containing block for
83
85
  position:fixed elements inside the game. */}
84
86
  <div
85
- className="absolute overflow-hidden"
86
87
  style={{
88
+ position: 'absolute',
89
+ overflow: 'hidden',
87
90
  top: SAFE_AREA_TOP,
88
91
  left: 0,
89
92
  right: 0,
@@ -97,14 +100,26 @@ export default function PhoneFrame({ children }: { children: React.ReactNode })
97
100
 
98
101
  {/* Dynamic Island */}
99
102
  <div
100
- className="absolute left-1/2 -translate-x-1/2 bg-black rounded-full"
101
- style={{ top: BEZEL + 11, width: 126, height: 37, zIndex: 10 }}
103
+ style={{
104
+ position: 'absolute',
105
+ left: '50%',
106
+ transform: 'translateX(-50%)',
107
+ background: '#000',
108
+ borderRadius: 9999,
109
+ top: BEZEL + 11,
110
+ width: 126,
111
+ height: 37,
112
+ zIndex: 10,
113
+ }}
102
114
  />
103
115
 
104
116
  {/* Home Indicator */}
105
117
  <div
106
- className="absolute left-1/2 -translate-x-1/2 rounded-full"
107
118
  style={{
119
+ position: 'absolute',
120
+ left: '50%',
121
+ transform: 'translateX(-50%)',
122
+ borderRadius: 9999,
108
123
  bottom: BEZEL + 8,
109
124
  width: 134,
110
125
  height: 5,
@@ -4,9 +4,22 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>LPT Dev Kit</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
7
  <style>
9
- body { background: #0a0a0a; color: #e5e5e5; }
8
+ /* ── Dev-Kit UI base ── */
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+ body { background: #0a0a0a; color: #e5e5e5; font-family: system-ui, -apple-system, sans-serif; }
11
+
12
+ /* ── Interactive states (can't be expressed as inline styles) ── */
13
+ .dk-nav-btn:hover { color: #fff; }
14
+ .dk-btn-amber:hover { background: #f59e0b; }
15
+ .dk-btn-zinc:hover { background: #52525b; }
16
+ .dk-btn-green:hover { background: #16a34a; }
17
+ .dk-player-btn { transition: background 0.15s; }
18
+ .dk-player-btn:hover { background: #3f3f46; }
19
+ .dk-resize-bar .dk-resize-line { transition: background 0.15s; }
20
+ .dk-resize-bar:hover .dk-resize-line { background: #71717a; }
21
+ .dk-input:focus { outline: none; border-color: #71717a; }
22
+ .dk-btn-amber:disabled, .dk-btn-green:disabled { opacity: 0.5; }
10
23
  </style>
11
24
  </head>
12
25
  <body>
@@ -18,20 +18,22 @@ export default function Debug() {
18
18
  return () => { sock.disconnect(); };
19
19
  }, []);
20
20
 
21
+ const panelStyle: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 16, overflow: 'auto' };
22
+
21
23
  return (
22
- <div className="grid grid-cols-2 gap-4 h-[calc(100vh-80px)]">
24
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, height: 'calc(100vh - 80px)' }}>
23
25
  {/* Room State */}
24
- <div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
25
- <h2 className="text-lg font-bold mb-4 text-amber-400">Room State</h2>
26
- <pre className="text-xs font-mono whitespace-pre-wrap">
26
+ <div style={panelStyle}>
27
+ <h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 16, color: '#fbbf24' }}>Room State</h2>
28
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
27
29
  {JSON.stringify(room, null, 2)}
28
30
  </pre>
29
31
  </div>
30
32
 
31
33
  {/* Game State */}
32
- <div className="bg-zinc-900 rounded-lg p-4 overflow-auto">
33
- <h2 className="text-lg font-bold mb-4 text-amber-400">Full Game State</h2>
34
- <pre className="text-xs font-mono whitespace-pre-wrap">
34
+ <div style={panelStyle}>
35
+ <h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 16, color: '#fbbf24' }}>Full Game State</h2>
36
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', whiteSpace: 'pre-wrap' }}>
35
37
  {fullState ? JSON.stringify(fullState, null, 2) : 'No game in progress'}
36
38
  </pre>
37
39
  </div>
@@ -2,6 +2,10 @@ import React, { useState, useEffect, useCallback } from 'react';
2
2
  import { io, Socket } from 'socket.io-client';
3
3
  import PhoneFrame from '../components/PhoneFrame';
4
4
 
5
+ const card: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 24 };
6
+ const inputStyle: React.CSSProperties = { width: '100%', background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: '8px 12px', marginBottom: 16, color: '#e5e5e5', fontSize: 14 };
7
+ const btnAmber: React.CSSProperties = { width: '100%', background: '#d97706', color: '#fff', border: 'none', padding: '8px 0', borderRadius: 4, fontWeight: 600, cursor: 'pointer', fontSize: 14 };
8
+
5
9
  export default function Play() {
6
10
  const [socket, setSocket] = useState<Socket | null>(null);
7
11
  const [nickname, setNickname] = useState('');
@@ -53,24 +57,30 @@ export default function Play() {
53
57
  },
54
58
  reportResult: () => {},
55
59
  getAssetUrl: (assetPath: string) => `/assets/${assetPath}`,
60
+ getDeviceCapabilities: () => ({ haptics: false, motion: false }),
61
+ haptic: () => {},
62
+ onShake: () => () => {},
63
+ onTilt: () => () => {},
56
64
  } : null;
57
65
 
58
66
  if (!joined) {
59
67
  return (
60
- <div className="flex items-center justify-center h-[60vh]">
61
- <div className="bg-zinc-900 rounded-lg p-6 w-80">
62
- <h2 className="text-xl font-bold mb-4">Join Game</h2>
68
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '60vh' }}>
69
+ <div style={{ ...card, width: 320 }}>
70
+ <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 16 }}>Join Game</h2>
63
71
  <input
64
72
  type="text"
65
73
  placeholder="Your nickname"
66
74
  value={nickname}
67
75
  onChange={(e) => setNickname(e.target.value)}
68
76
  onKeyDown={(e) => e.key === 'Enter' && join()}
69
- className="w-full bg-zinc-800 border border-zinc-700 rounded px-3 py-2 mb-4"
77
+ className="dk-input"
78
+ style={inputStyle}
70
79
  />
71
80
  <button
72
81
  onClick={join}
73
- className="w-full bg-amber-600 hover:bg-amber-500 text-white py-2 rounded font-semibold"
82
+ className="dk-btn-amber"
83
+ style={btnAmber}
74
84
  >
75
85
  Join
76
86
  </button>
@@ -81,23 +91,35 @@ export default function Play() {
81
91
 
82
92
  if (room.phase === 'lobby' || room.phase === 'ready') {
83
93
  return (
84
- <div className="max-w-md mx-auto mt-8">
85
- <div className="bg-zinc-900 rounded-lg p-6">
86
- <h2 className="text-xl font-bold mb-4">Lobby</h2>
87
- <div className="space-y-2 mb-6">
94
+ <div style={{ maxWidth: 448, margin: '32px auto 0' }}>
95
+ <div style={card}>
96
+ <h2 style={{ fontSize: 20, fontWeight: 700, marginBottom: 16 }}>Lobby</h2>
97
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 24 }}>
88
98
  {room.players.map((p: any) => (
89
- <div key={p.id} className="flex items-center justify-between bg-zinc-800 rounded px-3 py-2">
99
+ <div key={p.id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: '#27272a', borderRadius: 4, padding: '8px 12px' }}>
90
100
  <span>{p.nickname} {p.isHost && '(Host)'}</span>
91
- <span className={p.ready ? 'text-green-400' : 'text-zinc-500'}>
101
+ <span style={{ color: p.ready ? '#4ade80' : '#71717a' }}>
92
102
  {p.ready ? 'Ready' : 'Not Ready'}
93
103
  </span>
94
104
  </div>
95
105
  ))}
96
106
  </div>
97
- <div className="flex gap-2">
107
+ <div style={{ display: 'flex', gap: 8 }}>
98
108
  <button
99
109
  onClick={() => socket?.emit('player:ready', !isReady)}
100
- className={`flex-1 py-2 rounded font-semibold ${isReady ? 'bg-zinc-700 text-zinc-300' : 'bg-green-600 text-white'}`}
110
+ className={isReady ? 'dk-btn-zinc' : 'dk-btn-green'}
111
+ style={{
112
+ flex: 1,
113
+ padding: '8px 0',
114
+ borderRadius: 4,
115
+ fontWeight: 600,
116
+ border: 'none',
117
+ cursor: 'pointer',
118
+ fontSize: 14,
119
+ ...(isReady
120
+ ? { background: '#3f3f46', color: '#d4d4d8' }
121
+ : { background: '#16a34a', color: '#fff' }),
122
+ }}
101
123
  >
102
124
  {isReady ? 'Cancel Ready' : 'Ready'}
103
125
  </button>
@@ -105,7 +127,8 @@ export default function Play() {
105
127
  <button
106
128
  onClick={() => socket?.emit('game:start')}
107
129
  disabled={!room.players.every((p: any) => p.ready) || room.players.length < 2}
108
- className="flex-1 bg-amber-600 hover:bg-amber-500 disabled:opacity-50 text-white py-2 rounded font-semibold"
130
+ className="dk-btn-amber"
131
+ style={{ ...btnAmber, flex: 1, width: 'auto' }}
109
132
  >
110
133
  Start Game
111
134
  </button>
@@ -118,19 +141,20 @@ export default function Play() {
118
141
 
119
142
  // Playing or ended
120
143
  return (
121
- <div className="h-[calc(100vh-80px)] relative">
144
+ <div style={{ height: 'calc(100vh - 80px)', position: 'relative' }}>
122
145
  <PhoneFrame>
123
146
  {GameRenderer && platform && gameState ? (
124
147
  <GameRenderer platform={platform} state={gameState} />
125
148
  ) : (
126
- <div className="p-4 text-zinc-500">Loading game...</div>
149
+ <div style={{ padding: 16, color: '#71717a' }}>Loading game...</div>
127
150
  )}
128
151
  </PhoneFrame>
129
152
  {room.phase === 'ended' && isHost && (
130
- <div className="absolute bottom-4 left-1/2 -translate-x-1/2 z-[9999]">
153
+ <div style={{ position: 'absolute', bottom: 16, left: '50%', transform: 'translateX(-50%)', zIndex: 9999 }}>
131
154
  <button
132
155
  onClick={() => socket?.emit('game:playAgain')}
133
- className="bg-amber-600 hover:bg-amber-500 text-white px-6 py-2 rounded-full font-semibold"
156
+ className="dk-btn-amber"
157
+ style={{ ...btnAmber, width: 'auto', padding: '8px 24px', borderRadius: 9999 }}
134
158
  >
135
159
  Play Again
136
160
  </button>
@@ -3,6 +3,13 @@ import PhoneFrame from '../components/PhoneFrame';
3
3
 
4
4
  const PLAYER_NAMES = ['Alice', 'Bob', 'Carol', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi'];
5
5
 
6
+ /* ── shared inline-style helpers ── */
7
+ const card: React.CSSProperties = { background: '#18181b', borderRadius: 8, padding: 12 };
8
+ const label: React.CSSProperties = { fontSize: 13, fontWeight: 700, color: '#a1a1aa', marginBottom: 8 };
9
+ const inputBase: React.CSSProperties = { width: '100%', background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: '4px 8px', fontSize: 13, color: '#e5e5e5' };
10
+ const btnAmber: React.CSSProperties = { background: '#d97706', color: '#fff', border: 'none', padding: '4px 12px', borderRadius: 4, fontSize: 13, cursor: 'pointer' };
11
+ const btnZinc: React.CSSProperties = { background: '#3f3f46', color: '#fff', border: 'none', padding: '4px 12px', borderRadius: 4, fontSize: 13, cursor: 'pointer', width: '100%' };
12
+
6
13
  export default function Preview() {
7
14
  const [playerCount, setPlayerCount] = useState(3);
8
15
  const [playerIndex, setPlayerIndex] = useState(0);
@@ -122,6 +129,10 @@ export default function Preview() {
122
129
  console.log('Game result reported:', result);
123
130
  },
124
131
  getAssetUrl: (assetPath: string) => `/assets/${assetPath}`,
132
+ getDeviceCapabilities: () => ({ haptics: false, motion: false }),
133
+ haptic: () => {},
134
+ onShake: () => () => {},
135
+ onTilt: () => () => {},
125
136
  };
126
137
  }, [engine]);
127
138
 
@@ -179,14 +190,14 @@ export default function Preview() {
179
190
  }, []);
180
191
 
181
192
  return (
182
- <div className="flex gap-4 h-[calc(100vh-80px)]">
193
+ <div style={{ display: 'flex', gap: 16, height: 'calc(100vh - 80px)' }}>
183
194
  {/* Renderer — half the screen width */}
184
- <div className="h-full" style={{ width: '50%' }}>
195
+ <div style={{ width: '50%', height: '100%' }}>
185
196
  <PhoneFrame>
186
197
  {GameRenderer && platform && viewState ? (
187
198
  <GameRenderer platform={platform} state={viewState} />
188
199
  ) : (
189
- <div className="p-4 text-zinc-500">
200
+ <div style={{ padding: 16, color: '#71717a' }}>
190
201
  {!engine ? 'Loading engine...' : 'Initializing game...'}
191
202
  </div>
192
203
  )}
@@ -194,26 +205,27 @@ export default function Preview() {
194
205
  </div>
195
206
 
196
207
  {/* Control Panel — fills remaining width, resizable two-column */}
197
- <div ref={panelRef} className="flex-1 min-w-0 flex h-full">
208
+ <div ref={panelRef} style={{ flex: 1, minWidth: 0, display: 'flex', height: '100%' }}>
198
209
  {/* Left column: Players & Controls */}
199
- <div className="flex flex-col gap-4 overflow-auto pr-1" style={{ width: `${splitRatio * 100}%` }}>
210
+ <div style={{ width: `${splitRatio * 100}%`, display: 'flex', flexDirection: 'column', gap: 16, overflow: 'auto', paddingRight: 4 }}>
200
211
  {/* Player Count */}
201
- <div className="bg-zinc-900 rounded-lg p-3">
202
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Player Count</h3>
212
+ <div style={card}>
213
+ <h3 style={label}>Player Count</h3>
203
214
  <input
204
215
  type="number"
205
216
  min={2}
206
217
  max={32}
207
218
  value={playerCount}
208
219
  onChange={(e) => setPlayerCount(Math.max(2, Math.min(32, Number(e.target.value))))}
209
- className="w-full bg-zinc-800 border border-zinc-700 rounded px-2 py-1 text-sm"
220
+ className="dk-input"
221
+ style={inputBase}
210
222
  />
211
223
  </div>
212
224
 
213
225
  {/* Player Switcher */}
214
- <div className="bg-zinc-900 rounded-lg p-3 flex-1 overflow-auto">
215
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Current Player</h3>
216
- <div className="space-y-1">
226
+ <div style={{ ...card, flex: 1, overflow: 'auto' }}>
227
+ <h3 style={label}>Current Player</h3>
228
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
217
229
  {mockPlayers.map((p, i) => {
218
230
  const isActive = i === playerIndex;
219
231
  const hue = (i * 137) % 360; // deterministic color per player
@@ -241,28 +253,49 @@ export default function Preview() {
241
253
  <button
242
254
  key={p.id}
243
255
  onClick={() => setPlayerIndex(i)}
244
- className={`w-full flex items-center gap-2 px-2 py-1.5 rounded text-sm text-left transition-colors ${
245
- isActive
246
- ? 'bg-amber-600/20 ring-1 ring-amber-500 text-white'
247
- : 'bg-zinc-800 hover:bg-zinc-700 text-zinc-300'
248
- }`}
256
+ className={isActive ? '' : 'dk-player-btn'}
257
+ style={{
258
+ width: '100%',
259
+ display: 'flex',
260
+ alignItems: 'center',
261
+ gap: 8,
262
+ padding: '6px 8px',
263
+ borderRadius: 4,
264
+ fontSize: 13,
265
+ textAlign: 'left' as const,
266
+ border: 'none',
267
+ cursor: 'pointer',
268
+ ...(isActive
269
+ ? { background: 'rgba(217, 119, 6, 0.2)', boxShadow: 'inset 0 0 0 1px #f59e0b', color: '#fff' }
270
+ : { background: '#27272a', color: '#d4d4d8' }),
271
+ }}
249
272
  >
250
273
  {/* Avatar */}
251
274
  <div
252
- className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold shrink-0"
253
- style={{ background: `hsl(${hue}, 55%, 45%)` }}
275
+ style={{
276
+ width: 24,
277
+ height: 24,
278
+ borderRadius: '50%',
279
+ display: 'flex',
280
+ alignItems: 'center',
281
+ justifyContent: 'center',
282
+ fontSize: 11,
283
+ fontWeight: 700,
284
+ flexShrink: 0,
285
+ background: `hsl(${hue}, 55%, 45%)`,
286
+ }}
254
287
  >
255
288
  {p.nickname[0]}
256
289
  </div>
257
- <div className="min-w-0 flex-1">
258
- <div className="flex items-center gap-1">
259
- <span className="truncate">{p.nickname}</span>
290
+ <div style={{ minWidth: 0, flex: 1 }}>
291
+ <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
292
+ <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.nickname}</span>
260
293
  {p.isHost && (
261
- <span className="text-[10px] text-amber-400 shrink-0">HOST</span>
294
+ <span style={{ fontSize: 10, color: '#fbbf24', flexShrink: 0 }}>HOST</span>
262
295
  )}
263
296
  </div>
264
297
  {roleLabel && (
265
- <div className="text-[10px] text-zinc-500 truncate">
298
+ <div style={{ fontSize: 10, color: '#71717a', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
266
299
  {roleLabel}
267
300
  </div>
268
301
  )}
@@ -275,14 +308,15 @@ export default function Preview() {
275
308
 
276
309
  {/* Game Result */}
277
310
  {gameOver && gameResult && (
278
- <div className="bg-zinc-900 rounded-lg p-3">
279
- <h3 className="text-sm font-bold text-green-400 mb-2">Game Over</h3>
280
- <pre className="text-xs font-mono bg-zinc-800 rounded p-2 overflow-auto max-h-32 whitespace-pre-wrap">
311
+ <div style={card}>
312
+ <h3 style={{ ...label, color: '#4ade80' }}>Game Over</h3>
313
+ <pre style={{ fontSize: 11, fontFamily: 'monospace', background: '#27272a', borderRadius: 4, padding: 8, overflow: 'auto', maxHeight: 128, whiteSpace: 'pre-wrap' }}>
281
314
  {JSON.stringify(gameResult, null, 2)}
282
315
  </pre>
283
316
  <button
284
317
  onClick={resetGame}
285
- className="mt-2 w-full bg-amber-600 hover:bg-amber-500 text-white px-3 py-1 rounded text-sm"
318
+ className="dk-btn-amber"
319
+ style={{ ...btnAmber, marginTop: 8, width: '100%' }}
286
320
  >
287
321
  Reset Game
288
322
  </button>
@@ -291,10 +325,11 @@ export default function Preview() {
291
325
 
292
326
  {/* Reset button (when game is not over) */}
293
327
  {!gameOver && engine && (
294
- <div className="bg-zinc-900 rounded-lg p-3">
328
+ <div style={card}>
295
329
  <button
296
330
  onClick={resetGame}
297
- className="w-full bg-zinc-700 hover:bg-zinc-600 text-white px-3 py-1 rounded text-sm"
331
+ className="dk-btn-zinc"
332
+ style={btnZinc}
298
333
  >
299
334
  Reset Game
300
335
  </button>
@@ -304,40 +339,43 @@ export default function Preview() {
304
339
 
305
340
  {/* Drag handle */}
306
341
  <div
307
- className="shrink-0 w-2 cursor-col-resize flex items-center justify-center group"
342
+ className="dk-resize-bar"
343
+ style={{ flexShrink: 0, width: 8, cursor: 'col-resize', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
308
344
  onMouseDown={() => { dragging.current = true; document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; }}
309
345
  >
310
- <div className="w-0.5 h-8 bg-zinc-700 rounded group-hover:bg-zinc-500 transition-colors" />
346
+ <div className="dk-resize-line" style={{ width: 2, height: 32, background: '#3f3f46', borderRadius: 2 }} />
311
347
  </div>
312
348
 
313
349
  {/* Right column: State & Logs */}
314
- <div className="flex flex-col gap-4 overflow-auto pl-1" style={{ width: `${(1 - splitRatio) * 100}%` }}>
350
+ <div style={{ width: `${(1 - splitRatio) * 100}%`, display: 'flex', flexDirection: 'column', gap: 16, overflow: 'auto', paddingLeft: 4 }}>
315
351
  {/* State Editor */}
316
- <div className="bg-zinc-900 rounded-lg p-3 flex-1 flex flex-col min-h-0">
317
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Game State (Full)</h3>
352
+ <div style={{ ...card, flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
353
+ <h3 style={label}>Game State (Full)</h3>
318
354
  <textarea
319
355
  value={stateJson}
320
356
  onChange={(e) => setStateJson(e.target.value)}
321
- className="flex-1 bg-zinc-800 border border-zinc-700 rounded p-2 font-mono text-xs resize-none min-h-[120px]"
357
+ className="dk-input"
358
+ style={{ flex: 1, background: '#27272a', border: '1px solid #3f3f46', borderRadius: 4, padding: 8, fontFamily: 'monospace', fontSize: 11, resize: 'none', minHeight: 120, color: '#e5e5e5' }}
322
359
  />
323
360
  <button
324
361
  onClick={applyState}
325
- className="mt-2 bg-amber-600 hover:bg-amber-500 text-white px-3 py-1 rounded text-sm"
362
+ className="dk-btn-amber"
363
+ style={{ ...btnAmber, marginTop: 8 }}
326
364
  >
327
365
  Apply State
328
366
  </button>
329
367
  </div>
330
368
 
331
369
  {/* Action Log */}
332
- <div className="bg-zinc-900 rounded-lg p-3 h-48 overflow-auto">
333
- <h3 className="text-sm font-bold text-zinc-400 mb-2">Action Log</h3>
370
+ <div style={{ ...card, height: 192, overflow: 'auto' }}>
371
+ <h3 style={label}>Action Log</h3>
334
372
  {actions.length === 0 ? (
335
- <p className="text-zinc-500 text-xs">No actions yet</p>
373
+ <p style={{ color: '#71717a', fontSize: 11 }}>No actions yet</p>
336
374
  ) : (
337
- <div className="space-y-1">
375
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
338
376
  {actions.map((a, i) => (
339
- <div key={i} className="text-xs font-mono bg-zinc-800 rounded p-1">
340
- <span className="text-amber-400">{a.player}</span>: {JSON.stringify(a.action)}
377
+ <div key={i} style={{ fontSize: 11, fontFamily: 'monospace', background: '#27272a', borderRadius: 4, padding: 4 }}>
378
+ <span style={{ color: '#fbbf24' }}>{a.player}</span>: {JSON.stringify(a.action)}
341
379
  </div>
342
380
  ))}
343
381
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@littlepartytime/dev-kit",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "Development toolkit CLI for Little Party Time game developers",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",