@minicode-dev/chat 0.0.0-stage → 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.
Files changed (45) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +123 -2
  3. package/assets/sounds/battleship_audio_pack/assets/cannon_fire.ogg +0 -0
  4. package/assets/sounds/battleship_audio_pack/assets/cruiser_damage_alarm.ogg +0 -0
  5. package/assets/sounds/battleship_audio_pack/assets/defeat.ogg +0 -0
  6. package/assets/sounds/battleship_audio_pack/assets/ocean_ambient_loop.ogg +0 -0
  7. package/assets/sounds/battleship_audio_pack/assets/projectile_flyby.ogg +0 -0
  8. package/assets/sounds/battleship_audio_pack/assets/ship_heavy_hit.ogg +0 -0
  9. package/assets/sounds/battleship_audio_pack/assets/ship_hit.ogg +0 -0
  10. package/assets/sounds/battleship_audio_pack/assets/ship_place.ogg +0 -0
  11. package/assets/sounds/battleship_audio_pack/assets/ship_rotate.ogg +0 -0
  12. package/assets/sounds/battleship_audio_pack/assets/ship_sinking.ogg +0 -0
  13. package/assets/sounds/battleship_audio_pack/assets/sonar_ping.ogg +0 -0
  14. package/assets/sounds/battleship_audio_pack/assets/ui_click.ogg +0 -0
  15. package/assets/sounds/battleship_audio_pack/assets/victory.ogg +0 -0
  16. package/assets/sounds/battleship_audio_pack/assets/water_splash.ogg +0 -0
  17. package/assets/sounds/connect4/close.ogg +0 -0
  18. package/assets/sounds/connect4/draw.ogg +0 -0
  19. package/assets/sounds/connect4/drop.ogg +0 -0
  20. package/assets/sounds/connect4/invite.ogg +0 -0
  21. package/assets/sounds/connect4/lose.ogg +0 -0
  22. package/assets/sounds/connect4/start.ogg +0 -0
  23. package/assets/sounds/connect4/turn.ogg +0 -0
  24. package/assets/sounds/connect4/win.ogg +0 -0
  25. package/assets/sounds/notification.mp3 +0 -0
  26. package/assets/sounds/notification.ogg +0 -0
  27. package/assets/sounds/ting.mp3 +0 -0
  28. package/assets/sounds/ting.ogg +0 -0
  29. package/dist/chunks/BattleshipGameCard-CW_A8Nim.js +958 -0
  30. package/dist/chunks/BattleshipGameCard-CW_A8Nim.js.map +1 -0
  31. package/dist/chunks/BattleshipPrototype-Duz-S1JE.js +373 -0
  32. package/dist/chunks/BattleshipPrototype-Duz-S1JE.js.map +1 -0
  33. package/dist/chunks/battleship-DXKuIZ1I.js +124 -0
  34. package/dist/chunks/battleship-DXKuIZ1I.js.map +1 -0
  35. package/dist/chunks/connect4Sounds-Do3nvVFx.js +1847 -0
  36. package/dist/chunks/connect4Sounds-Do3nvVFx.js.map +1 -0
  37. package/dist/chunks/createBattleScene-HIAvjixn.js +1621 -0
  38. package/dist/chunks/createBattleScene-HIAvjixn.js.map +1 -0
  39. package/dist/chunks/webglSupport-2WjPEPZ_.js +16 -0
  40. package/dist/chunks/webglSupport-2WjPEPZ_.js.map +1 -0
  41. package/dist/index.js +9519 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/styles.css +2 -0
  44. package/index.d.ts +470 -0
  45. package/package.json +66 -4
@@ -0,0 +1,958 @@
1
+ import { S as e, _ as t, a as n, m as r, o as i, p as a, s as o, t as s, u as c, v as l } from "./connect4Sounds-Do3nvVFx.js";
2
+ import { l as u, n as d, s as f, t as p } from "./battleship-DXKuIZ1I.js";
3
+ import { t as ee } from "./webglSupport-2WjPEPZ_.js";
4
+ import { memo as m, useCallback as h, useEffect as g, useId as te, useMemo as _, useRef as v, useState as y } from "react";
5
+ import { Fragment as ne, jsx as b, jsxs as x } from "react/jsx-runtime";
6
+ import { Anchor as re, Check as ie, ChevronDown as ae, Crosshair as oe, LocateFixed as se, Maximize2 as ce, Minimize2 as le, Radar as ue, RotateCw as de, ShieldCheck as S, Shuffle as fe, TriangleAlert as pe, Waves as me, X as he } from "lucide-react";
7
+ // src/games/battleship/sound/battleshipSounds.js
8
+ var C = "ocean_ambient_loop", w = n({
9
+ id: "battleship",
10
+ baseUrl: () => l("battleship_audio_pack/assets"),
11
+ settingsFrom: s,
12
+ sounds: Object.fromEntries([
13
+ "cannon_fire",
14
+ "projectile_flyby",
15
+ "water_splash",
16
+ "ship_hit",
17
+ "ship_heavy_hit",
18
+ "ship_sinking",
19
+ "sonar_ping",
20
+ "cruiser_damage_alarm",
21
+ "ship_place",
22
+ "ship_rotate",
23
+ "ui_click",
24
+ "victory",
25
+ "defeat",
26
+ C
27
+ ].map((e) => [e, `${e}.ogg`])),
28
+ levels: {
29
+ cannon_fire: .7,
30
+ projectile_flyby: .3,
31
+ water_splash: .9,
32
+ ship_hit: .9,
33
+ ship_heavy_hit: 1,
34
+ ship_sinking: .4,
35
+ sonar_ping: .35,
36
+ cruiser_damage_alarm: .3,
37
+ ship_place: .4,
38
+ ship_rotate: .4,
39
+ ui_click: .3,
40
+ victory: .55,
41
+ defeat: .4,
42
+ [C]: .22
43
+ }
44
+ }), ge = () => typeof document < "u" && document.hidden;
45
+ function T(e) {
46
+ ge() || w.play(e);
47
+ }
48
+ function _e(e, t, n) {
49
+ e.forEach(({ name: e, at: r }) => {
50
+ let i = () => {
51
+ ge() || w.play(e, { key: t(e) });
52
+ };
53
+ if (r <= 0) {
54
+ i();
55
+ return;
56
+ }
57
+ let a = setTimeout(() => {
58
+ n.delete(a), i();
59
+ }, r);
60
+ n.add(a);
61
+ });
62
+ }
63
+ var E = 0, D = () => {
64
+ E > 0 && !ge() ? w.startLoop(C) : w.stopLoop(C);
65
+ };
66
+ function ve() {
67
+ E += 1, E === 1 && document.addEventListener("visibilitychange", D), D();
68
+ let e = !1;
69
+ return () => {
70
+ e || (e = !0, --E, E === 0 && document.removeEventListener("visibilitychange", D), D());
71
+ };
72
+ }
73
+ // src/games/battleship/sound/cues.js
74
+ var ye = "cruiser", be = (e, t) => e.row === t.row && e.col === t.col, O = (e, t, n) => e.cells.filter((e) => t?.[e.row]?.[e.col] === "hit" && !(n && be(e, n))).length;
75
+ function xe(e, t, n) {
76
+ if (n?.result !== "hit") return !1;
77
+ let r = (e || []).find((e) => e.id === ye);
78
+ if (!r?.cells?.some((e) => be(e, n))) return !1;
79
+ let i = O(r, t, n), a = O(r, t);
80
+ return i < 2 && a >= 2;
81
+ }
82
+ function Se({ incoming: e }) {
83
+ return e ? [{
84
+ name: "projectile_flyby",
85
+ at: 0
86
+ }] : [{
87
+ name: "cannon_fire",
88
+ at: 0
89
+ }, {
90
+ name: "projectile_flyby",
91
+ at: 180
92
+ }];
93
+ }
94
+ function Ce({ result: e, sunk: t, defeated: n, won: r, cruiserAlarm: i }) {
95
+ let a = e === "hit" ? t ? [{
96
+ name: "ship_heavy_hit",
97
+ at: 0
98
+ }, {
99
+ name: "ship_sinking",
100
+ at: 350
101
+ }] : [{
102
+ name: "ship_hit",
103
+ at: 0
104
+ }] : [{
105
+ name: "water_splash",
106
+ at: 0
107
+ }];
108
+ return i && a.push({
109
+ name: "cruiser_damage_alarm",
110
+ at: 500
111
+ }), n && a.push({
112
+ name: r ? "victory" : "defeat",
113
+ at: t ? 1600 : 600
114
+ }), a;
115
+ }
116
+ // src/games/battleship/BattleshipGameCard.jsx
117
+ var k = "ABCDEFGHIJ", we = {
118
+ carrier: "portaaviones",
119
+ battleship: "acorazado",
120
+ cruiser: "crucero",
121
+ submarine: "submarino",
122
+ destroyer: "destructor"
123
+ }, Te = [
124
+ "placement",
125
+ "active",
126
+ "won",
127
+ "conflict",
128
+ "closed"
129
+ ], Ee = 400, De = Array.from({ length: 10 }, () => Array(10).fill(null)), A = (e) => e ? `${k[e.row]}${e.col + 1}` : "—", Oe = (e, t) => !!(e && t && e.row === t.row && e.col === t.col), j = (e) => !!e && Number.isInteger(e.row) && Number.isInteger(e.col) && e.row >= 0 && e.row < 10 && e.col >= 0 && e.col < 10, ke = (e) => we[e] || "barco", Ae = (e, t) => e?.[t.row]?.[t.col] ?? null, je = (e, t) => e.find((e) => e.cells?.some((e) => Oe(e, t))), Me = (e) => e.charAt(0).toUpperCase() + e.slice(1), Ne = () => typeof window < "u" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches, M = (t, ...n) => Promise.resolve().then(() => e.getState()[t]?.(...n)).catch(() => {});
130
+ function Pe(e) {
131
+ let t = d();
132
+ for (let n of e || []) {
133
+ let e = n.cells?.[0];
134
+ if (!e) continue;
135
+ let r = f(t, {
136
+ shipId: n.id,
137
+ row: e.row,
138
+ col: e.col,
139
+ orientation: n.orientation
140
+ });
141
+ r.ok && (t = r.board);
142
+ }
143
+ return t;
144
+ }
145
+ function Fe(e, t, n) {
146
+ return Array.from({ length: t }, (t, r) => ({
147
+ row: e.row + (n === "vertical" ? r : 0),
148
+ col: e.col + (n === "horizontal" ? r : 0)
149
+ })).filter(j);
150
+ }
151
+ function Ie(e) {
152
+ let t = 0, n = 0;
153
+ for (let r of e || []) for (let e of r || []) e && (t += 1), e === "hit" && (n += 1);
154
+ return {
155
+ total: t,
156
+ hits: n
157
+ };
158
+ }
159
+ function Le({ sync: e, connected: t, onResync: n, onAdoptOffer: r }) {
160
+ return e?.status === "requesting" ? /* @__PURE__ */ b("div", {
161
+ className: "chat-game-sync",
162
+ role: "status",
163
+ children: "Sincronizando partida…"
164
+ }) : /* @__PURE__ */ x("div", {
165
+ className: "chat-game-sync",
166
+ role: "alert",
167
+ children: [
168
+ e?.message && /* @__PURE__ */ b("span", { children: e.message }),
169
+ e?.status === "incompatible" && e.offer && /* @__PURE__ */ b("button", {
170
+ type: "button",
171
+ className: "chat-game-action chat-game-action--primary",
172
+ disabled: !t,
173
+ onClick: r,
174
+ children: "Usar estado del anfitrión"
175
+ }),
176
+ /* @__PURE__ */ b("button", {
177
+ type: "button",
178
+ className: "chat-game-action",
179
+ disabled: !t,
180
+ onClick: n,
181
+ children: "Reintentar sincronización"
182
+ })
183
+ ]
184
+ });
185
+ }
186
+ function Re({ game: e }) {
187
+ let t = c(e);
188
+ return t ? /* @__PURE__ */ x("span", {
189
+ className: `bs-badge bs-badge--${e.verification}`,
190
+ children: [
191
+ e.verification === "ok" && /* @__PURE__ */ b(S, {
192
+ size: 12,
193
+ "aria-hidden": "true"
194
+ }),
195
+ e.verification === "mismatch" && /* @__PURE__ */ b(pe, {
196
+ size: 12,
197
+ "aria-hidden": "true"
198
+ }),
199
+ t
200
+ ]
201
+ }) : null;
202
+ }
203
+ function ze({ view: e, selected: t, cursor: n, onSelect: r, onHover: i }) {
204
+ let a = /* @__PURE__ */ new Map();
205
+ e.ships.forEach((e) => e.cells.forEach((t) => a.set(`${t.row}-${t.col}`, e)));
206
+ let o = new Set((e.preview?.cells || []).map((e) => `${e.row}-${e.col}`));
207
+ return /* @__PURE__ */ b("div", {
208
+ className: "bs-grid",
209
+ role: "grid",
210
+ "aria-label": e.mode === "target" ? "Tablero objetivo" : "Mi flota",
211
+ onMouseLeave: () => i(null),
212
+ children: Array.from({ length: 10 }, (s, c) => /* @__PURE__ */ b("div", {
213
+ role: "row",
214
+ className: "bs-grid__row",
215
+ children: Array.from({ length: 10 }, (s, l) => {
216
+ let u = `${c}-${l}`, d = a.get(u), f = e.shots?.[c]?.[l], p = [
217
+ "bs-grid__cell",
218
+ d && "is-ship",
219
+ d?.sunk && "is-sunk",
220
+ f && `is-${f}`,
221
+ o.has(u) && (e.preview.valid ? "is-preview" : "is-invalid"),
222
+ Oe(t, {
223
+ row: c,
224
+ col: l
225
+ }) && "is-selected",
226
+ Oe(n, {
227
+ row: c,
228
+ col: l
229
+ }) && "is-cursor"
230
+ ].filter(Boolean).join(" ");
231
+ return /* @__PURE__ */ b("button", {
232
+ type: "button",
233
+ role: "gridcell",
234
+ tabIndex: -1,
235
+ className: p,
236
+ disabled: !e.interactive,
237
+ "aria-label": `${k[c]}${l + 1}${f === "hit" ? ", impacto" : f === "miss" ? ", agua" : ""}${d ? ", barco" : ""}`,
238
+ onMouseEnter: () => i({
239
+ row: c,
240
+ col: l
241
+ }),
242
+ onClick: () => r({
243
+ row: c,
244
+ col: l
245
+ })
246
+ }, u);
247
+ })
248
+ }, c))
249
+ });
250
+ }
251
+ function N({ game: e, currentUserId: t, status: n }) {
252
+ let { total: i, hits: a } = Ie(e.targetShots), o = e.sunkEnemyShips?.length || 0, s = [
253
+ "active",
254
+ "won",
255
+ "closed",
256
+ "conflict"
257
+ ].includes(e.status) && i > 0, c = e.status === "won" && r(t, e.winnerId);
258
+ return /* @__PURE__ */ x("section", {
259
+ className: "chat-game-card chat-game-card--history bs-card bs-card--history",
260
+ "aria-label": "Partida de Batalla Naval",
261
+ children: [
262
+ /* @__PURE__ */ b("header", {
263
+ className: "chat-game-header",
264
+ children: /* @__PURE__ */ x("div", {
265
+ className: "chat-game-heading",
266
+ children: [/* @__PURE__ */ b("span", {
267
+ className: "chat-game-eyebrow",
268
+ children: "MINIJUEGOS · 2 JUGADORES"
269
+ }), /* @__PURE__ */ x("h3", { children: ["Batalla Naval ", /* @__PURE__ */ b(re, {
270
+ size: 13,
271
+ "aria-hidden": "true",
272
+ className: "bs-title-icon"
273
+ })] })]
274
+ })
275
+ }),
276
+ /* @__PURE__ */ b("p", {
277
+ className: `chat-game-status${c ? " bs-status--win" : ""}`,
278
+ children: n
279
+ }),
280
+ s && /* @__PURE__ */ x("p", {
281
+ className: "bs-history-stats",
282
+ children: [
283
+ "Disparos ",
284
+ i,
285
+ " · Impactos ",
286
+ a,
287
+ " · Hundidos ",
288
+ o,
289
+ "/",
290
+ p.length
291
+ ]
292
+ }),
293
+ /* @__PURE__ */ b(Re, { game: e })
294
+ ]
295
+ });
296
+ }
297
+ function P({ gameKey: n, currentUserId: r, variant: i = "panel", onMinimize: a, onDismiss: s }) {
298
+ let c = e((e) => e.games[n]), l = t() === "connected";
299
+ if (!c) return null;
300
+ let u = o(c, r);
301
+ return i === "history" ? /* @__PURE__ */ b(N, {
302
+ game: c,
303
+ currentUserId: r,
304
+ status: u
305
+ }) : /* @__PURE__ */ b(Be, {
306
+ game: c,
307
+ gameKey: n,
308
+ currentUserId: r,
309
+ connected: l,
310
+ status: u,
311
+ variant: i,
312
+ onMinimize: a,
313
+ onDismiss: s
314
+ });
315
+ }
316
+ function Be({ game: e, gameKey: t, currentUserId: n, connected: o, status: s, variant: c, onMinimize: l, onDismiss: d }) {
317
+ let f = v(null), m = v(null), S = v(!1), C = v(void 0), ge = v({
318
+ cell: null,
319
+ time: 0
320
+ }), E = v({}), D = v(/* @__PURE__ */ new Set()), ye = v(e.status), be = te(), [O, k] = y("idle"), [we, N] = y("own"), [P, Be] = y(null), [F, Ve] = y(null), [I, He] = y(null), [L, Ue] = y("horizontal"), [We, Ge] = y(null), [Ke, qe] = y(!1), [R, Je] = y(!1), [Ye, Xe] = y(!1), [Ze, Qe] = y(null), $e = r(n, e.hostId), et = r(n, e.guestId), tt = $e || et, nt = a(e), z = e.status === "placement", rt = e.status === "active" || e.status === "won", it = e.status === "active" && r(n, e.turnId), at = !o || !!e.pending || !!e.pendingEvent, B = it && !e.pendingShot && !at && !e.error && !Ye, V = z && !e.myReady && !at, H = Te.includes(e.status) && (e.status !== "closed" || (e.myFleet?.length ?? 0) > 0), U = O === "ready", W = _(() => e.myFleet || [], [e.myFleet]), G = e.incomingShots || De, K = e.targetShots || De, ot = _(() => Pe(W), [W]), q = _(() => new Set(W.map((e) => e.id)), [W]), st = p.every((e) => q.has(e.id)), J = p.find((e) => e.id === We && !q.has(e.id)) || p.find((e) => !q.has(e.id)) || null, ct = _(() => W.map((e) => ({
321
+ ...e,
322
+ sunk: !!e.cells?.length && e.cells.every((e) => Ae(G, e) === "hit")
323
+ })), [W, G]), lt = _(() => (e.sunkEnemyShips || []).filter((e) => e?.cells?.length).map((e) => ({
324
+ ...e,
325
+ size: e.size ?? e.cells.length,
326
+ sunk: !0
327
+ })), [e.sunkEnemyShips]), { total: ut, hits: dt } = _(() => Ie(K), [K]), ft = _(() => {
328
+ let e = [];
329
+ return K.forEach((t, n) => t?.forEach((t, r) => {
330
+ t === "hit" && e.push({
331
+ row: n,
332
+ col: r
333
+ });
334
+ })), e;
335
+ }, [K]), Y = z ? "own" : we, X = P || F, pt = _(() => {
336
+ if (!V || !J || !X) return null;
337
+ let e = u(ot, {
338
+ shipId: J.id,
339
+ row: X.row,
340
+ col: X.col,
341
+ orientation: L
342
+ });
343
+ return {
344
+ cells: e.ok ? e.ship.cells : Fe(X, J.size, L),
345
+ valid: e.ok
346
+ };
347
+ }, [
348
+ V,
349
+ J,
350
+ X,
351
+ ot,
352
+ L
353
+ ]), mt = h((e, t) => {
354
+ if (e === "target") {
355
+ let e = t ? K.map((e, n) => e.map((e, r) => n === t.row && r === t.col ? null : e)) : K;
356
+ return {
357
+ mode: "target",
358
+ ships: t ? lt.map((e) => je([e], t) ? {
359
+ ...e,
360
+ sunk: !1
361
+ } : e) : lt,
362
+ shots: e,
363
+ preview: null,
364
+ interactive: B
365
+ };
366
+ }
367
+ let n = t ? G.map((e, n) => e.map((e, r) => n === t.row && r === t.col ? null : e)) : G;
368
+ return {
369
+ mode: "own",
370
+ ships: t ? ct.map((e) => je([e], t) ? {
371
+ ...e,
372
+ sunk: !1
373
+ } : e) : ct,
374
+ shots: n,
375
+ preview: z ? pt : null,
376
+ interactive: V
377
+ };
378
+ }, [
379
+ K,
380
+ lt,
381
+ G,
382
+ ct,
383
+ z,
384
+ pt,
385
+ B,
386
+ V
387
+ ]), ht = _(() => mt(Y), [mt, Y]), Z = h((e, t = "info") => Qe({
388
+ text: e,
389
+ kind: t,
390
+ id: Date.now()
391
+ }), []), gt = h((e = I) => {
392
+ B && j(e) && (Ae(K, e) ? Z(`Ya disparaste en ${A(e)}`) : (He(null), m.current?.selectCell?.(null), T("ui_click"), M("bsFire", t, {
393
+ row: e.row,
394
+ col: e.col
395
+ })));
396
+ }, [
397
+ B,
398
+ I,
399
+ K,
400
+ t,
401
+ Z
402
+ ]), _t = h((e) => {
403
+ if (!V || !j(e)) return;
404
+ let n = je(W, e);
405
+ if (n) {
406
+ Ge(n.id), n.orientation && Ue(n.orientation), T("ui_click"), M("bsRemoveShip", t, n.id);
407
+ return;
408
+ }
409
+ if (!J) return;
410
+ let r = u(ot, {
411
+ shipId: J.id,
412
+ row: e.row,
413
+ col: e.col,
414
+ orientation: L
415
+ });
416
+ r.ok ? (Ge(null), T("ship_place"), M("bsPlaceShip", t, {
417
+ shipId: J.id,
418
+ row: e.row,
419
+ col: e.col,
420
+ orientation: L
421
+ })) : Z(r.reason === "overlap" ? "Se superpone con otro barco" : "No cabe en esa posición", "miss");
422
+ }, [
423
+ V,
424
+ W,
425
+ J,
426
+ ot,
427
+ L,
428
+ t,
429
+ Z
430
+ ]), vt = h((e) => {
431
+ if (!j(e)) return;
432
+ if (Ve(e), z) {
433
+ _t(e);
434
+ return;
435
+ }
436
+ if (Y !== "target" || !B) return;
437
+ let t = Date.now(), n = ge.current;
438
+ ge.current = {
439
+ cell: e,
440
+ time: t
441
+ }, Oe(n.cell, e) && t - n.time < Ee ? gt(e) : Ae(K, e) ? Z(`Ya disparaste en ${A(e)}`) : (He(e), m.current?.selectCell?.(e));
442
+ }, [
443
+ z,
444
+ _t,
445
+ Y,
446
+ B,
447
+ gt,
448
+ K,
449
+ Z
450
+ ]);
451
+ E.current = {
452
+ selectCell: vt,
453
+ setHovered: Be
454
+ }, g(() => {
455
+ let e = f.current;
456
+ if (!H || !e) return;
457
+ if (!ee()) {
458
+ k("fallback");
459
+ return;
460
+ }
461
+ let t = !1, n = null;
462
+ return k("loading"), import("./createBattleScene-HIAvjixn.js").then(({ createBattleScene: r }) => {
463
+ t || (n = r(e, {
464
+ quality: "auto",
465
+ reducedMotion: Ne(),
466
+ onCellHover: (e) => {
467
+ t || E.current.setHovered(j(e) ? {
468
+ row: e.row,
469
+ col: e.col
470
+ } : null);
471
+ },
472
+ onCellSelect: (e) => {
473
+ t || E.current.selectCell(j(e) ? {
474
+ row: e.row,
475
+ col: e.col
476
+ } : null);
477
+ }
478
+ }), m.current = n, k("ready"));
479
+ }).catch((e) => {
480
+ t || (console.error("[battleship] No se pudo iniciar la escena", e), k("fallback"));
481
+ }), () => {
482
+ t = !0, m.current = null;
483
+ try {
484
+ n?.dispose();
485
+ } catch (e) {
486
+ console.error("[battleship] Error al liberar la escena", e);
487
+ }
488
+ };
489
+ }, [H]), g(() => {
490
+ w.preload();
491
+ let e = D.current;
492
+ return () => {
493
+ e.forEach(clearTimeout), e.clear();
494
+ };
495
+ }, []);
496
+ let yt = H && !nt;
497
+ g(() => yt ? ve() : void 0, [yt]), g(() => {
498
+ let t = ye.current;
499
+ ye.current = e.status, t === "placement" && e.status === "active" && _e([{
500
+ name: "sonar_ping",
501
+ at: 0
502
+ }], () => `${e.gameId}:start`, D.current);
503
+ }, [e.status, e.gameId]);
504
+ let Q = e.lastShot;
505
+ g(() => {
506
+ if (!U && O !== "fallback") return;
507
+ let t = Q?.eventId ?? null;
508
+ if (C.current === void 0) {
509
+ C.current = t;
510
+ return;
511
+ }
512
+ if (!t || t === C.current) return;
513
+ C.current = t;
514
+ let i = !r(Q.by, n), a = {
515
+ row: Q.row,
516
+ col: Q.col
517
+ }, o = A(a), s = typeof Q.sunk == "string" ? Q.sunk : Q.sunk ? je(i ? W : e.sunkEnemyShips || [], a)?.id : null, c = i ? Q.sunk ? `Te hundieron el ${ke(s)}` : Q.result === "hit" ? `El rival impactó en ${o}` : `El rival falló: agua en ${o}` : Q.sunk ? `¡Hundiste el ${ke(s)}!` : Q.result === "hit" ? `¡Impacto en ${o}!` : `Agua en ${o}`, l = Q.result === "hit" ? "hit" : "miss", u = i ? "own" : "target", d = i && xe(W, e.incomingShots, Q), f = Ce({
518
+ result: Q.result,
519
+ sunk: !!Q.sunk,
520
+ defeated: !!Q.defeated,
521
+ won: !i,
522
+ cruiserAlarm: d
523
+ }), p = (n) => n === "cruiser_damage_alarm" ? `${e.gameId}:cruiser` : n === "victory" || n === "defeat" ? `${e.gameId}:end` : t, ee = D.current;
524
+ N(u);
525
+ let h = m.current;
526
+ if (!h?.playShot) {
527
+ _e(f, p, ee), Z(c, l);
528
+ return;
529
+ }
530
+ _e(Se({ incoming: i }), p, ee), S.current = !0, Xe(!0);
531
+ let g = !1;
532
+ try {
533
+ h.setView(mt(u, a));
534
+ } catch {}
535
+ let te = Ne() ? 0 : 600;
536
+ return Promise.resolve(h.playShot({
537
+ row: a.row,
538
+ col: a.col,
539
+ result: Q.result,
540
+ sunk: !!Q.sunk,
541
+ incoming: i
542
+ })).catch(() => {}).then(() => (_e(f, p, ee), g || Z(c, l), new Promise((e) => setTimeout(e, te)))).then(() => {
543
+ g || (S.current = !1, Xe(!1));
544
+ }), () => {
545
+ g = !0, S.current = !1, Xe(!1);
546
+ };
547
+ }, [
548
+ U,
549
+ O,
550
+ Q?.eventId
551
+ ]), g(() => {
552
+ Ye || e.status !== "active" || N(it ? "target" : "own");
553
+ }, [
554
+ it,
555
+ e.status,
556
+ Ye
557
+ ]), g(() => {
558
+ B || He(null);
559
+ }, [B]), g(() => {
560
+ if (U && !S.current) try {
561
+ m.current?.setView(ht);
562
+ } catch (e) {
563
+ console.error("[battleship] setView", e);
564
+ }
565
+ }, [
566
+ U,
567
+ ht,
568
+ Ye
569
+ ]), g(() => {
570
+ U && m.current?.selectCell?.(Y === "target" ? I : null);
571
+ }, [
572
+ U,
573
+ I,
574
+ Y
575
+ ]), g(() => {
576
+ if (!U) return;
577
+ let e = m.current;
578
+ e?.setRadarVisible?.(Ke && Y === "target"), e?.setRadarContacts?.(ft);
579
+ }, [
580
+ U,
581
+ Ke,
582
+ Y,
583
+ ft
584
+ ]);
585
+ let bt = () => {
586
+ T("ship_rotate"), Ue((e) => e === "horizontal" ? "vertical" : "horizontal");
587
+ }, xt = () => {
588
+ st && V && (T("ui_click"), M("bsReady", t));
589
+ }, $ = (e) => (...t) => {
590
+ T("ui_click"), e(...t);
591
+ }, St = () => {
592
+ T(Ke ? "ui_click" : "sonar_ping"), qe((e) => !e);
593
+ }, Ct = (e) => {
594
+ if (e.target !== e.currentTarget || e.altKey || e.ctrlKey || e.metaKey) return;
595
+ let t = {
596
+ ArrowUp: [-1, 0],
597
+ ArrowDown: [1, 0],
598
+ ArrowLeft: [0, -1],
599
+ ArrowRight: [0, 1]
600
+ };
601
+ if (t[e.key]) {
602
+ e.preventDefault();
603
+ let [n, r] = t[e.key], i = (Y === "target" ? I : null) || F || P, a = i ? {
604
+ row: Math.min(9, Math.max(0, i.row + n)),
605
+ col: Math.min(9, Math.max(0, i.col + r))
606
+ } : {
607
+ row: 0,
608
+ col: 0
609
+ };
610
+ Ve(a), Be(null), Y === "target" && B && (He(a), m.current?.selectCell?.(a));
611
+ } else (e.key === "Enter" || e.key === " ") && (e.preventDefault(), z ? _t(F || P) : gt(I || F));
612
+ }, wt = (e) => {
613
+ e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || /^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName) || e.target.isContentEditable || (e.key === "r" || e.key === "R" ? (e.preventDefault(), z ? bt() : m.current?.resetCamera?.()) : e.key === "Escape" && R && (e.preventDefault(), e.stopPropagation(), Je(!1)));
614
+ }, Tt = /* @__PURE__ */ b(Re, { game: e }), Et = e.status === "won" && r(n, e.winnerId), Dt = !o && !nt ? "Sin conexión · esperando reconexión" : e.pending ? "Sincronizando…" : s, Ot = lt.length;
615
+ return /* @__PURE__ */ x("section", {
616
+ className: `chat-game-card bs-card${it ? " chat-game-card--my-turn" : ""}${c ? ` chat-game-card--${c}` : ""}${R ? " bs-card--expanded" : ""}`,
617
+ "aria-label": "Partida de Batalla Naval",
618
+ onKeyDown: wt,
619
+ children: [
620
+ /* @__PURE__ */ x("header", {
621
+ className: "chat-game-header",
622
+ children: [
623
+ /* @__PURE__ */ x("div", {
624
+ className: "chat-game-heading",
625
+ children: [/* @__PURE__ */ b("span", {
626
+ className: "chat-game-eyebrow",
627
+ children: "MINIJUEGOS · 2 JUGADORES"
628
+ }), /* @__PURE__ */ x("h3", { children: ["Batalla Naval ", /* @__PURE__ */ b(re, {
629
+ size: 13,
630
+ "aria-hidden": "true",
631
+ className: "bs-title-icon"
632
+ })] })]
633
+ }),
634
+ c === "panel" && /* @__PURE__ */ b(i, { manager: w }),
635
+ H && /* @__PURE__ */ b("button", {
636
+ className: "chat-game-close bs-expand",
637
+ type: "button",
638
+ "aria-pressed": R,
639
+ "aria-label": R ? "Reducir tablero" : "Ampliar tablero",
640
+ title: R ? "Reducir (Esc)" : "Ampliar",
641
+ onClick: $(() => Je((e) => !e)),
642
+ children: b(R ? le : ce, {
643
+ size: 15,
644
+ "aria-hidden": "true"
645
+ })
646
+ }),
647
+ l && /* @__PURE__ */ b("button", {
648
+ className: "chat-game-close",
649
+ type: "button",
650
+ "aria-label": "Minimizar tablero",
651
+ title: "Minimizar tablero",
652
+ onClick: () => {
653
+ Je(!1), l();
654
+ },
655
+ children: /* @__PURE__ */ b(ae, {
656
+ size: 16,
657
+ "aria-hidden": "true"
658
+ })
659
+ }),
660
+ tt && !nt && /* @__PURE__ */ b("button", {
661
+ className: "chat-game-close",
662
+ type: "button",
663
+ "aria-label": "Finalizar partida para ambos jugadores",
664
+ title: "Finalizar partida para ambos",
665
+ onClick: () => void M("act", t, "game_end"),
666
+ disabled: !o,
667
+ children: /* @__PURE__ */ b(he, {
668
+ size: 16,
669
+ "aria-hidden": "true"
670
+ })
671
+ }),
672
+ d && /* @__PURE__ */ b("button", {
673
+ className: "chat-game-close",
674
+ type: "button",
675
+ "aria-label": "Cerrar tablero y volver al chat",
676
+ title: "Cerrar tablero",
677
+ onClick: d,
678
+ children: /* @__PURE__ */ b(he, {
679
+ size: 16,
680
+ "aria-hidden": "true"
681
+ })
682
+ })
683
+ ]
684
+ }),
685
+ /* @__PURE__ */ x("div", {
686
+ className: "bs-statusline",
687
+ children: [/* @__PURE__ */ b("p", {
688
+ className: `chat-game-status${Et ? " bs-status--win" : ""}`,
689
+ role: "status",
690
+ children: Dt
691
+ }), Tt]
692
+ }),
693
+ e.status === "invited" && /* @__PURE__ */ x("div", {
694
+ className: "bs-invite",
695
+ children: [/* @__PURE__ */ b("p", { children: "Coloca 5 barcos en un tablero de 10×10 y hunde la flota rival por turnos." }), et && /* @__PURE__ */ x("div", {
696
+ className: "chat-game-actions",
697
+ children: [/* @__PURE__ */ b("button", {
698
+ type: "button",
699
+ className: "chat-game-action chat-game-action--primary",
700
+ disabled: at,
701
+ onClick: $(() => void M("act", t, "game_accept")),
702
+ children: "Aceptar partida"
703
+ }), /* @__PURE__ */ b("button", {
704
+ type: "button",
705
+ className: "chat-game-action",
706
+ disabled: at,
707
+ onClick: $(() => void M("act", t, "game_decline")),
708
+ children: "Rechazar"
709
+ })]
710
+ })]
711
+ }),
712
+ H && /* @__PURE__ */ x(ne, { children: [
713
+ rt && /* @__PURE__ */ x("div", {
714
+ className: "bs-hud",
715
+ role: "toolbar",
716
+ "aria-label": "Vista del tablero",
717
+ children: [/* @__PURE__ */ x("div", {
718
+ className: "bs-segment",
719
+ children: [/* @__PURE__ */ x("button", {
720
+ type: "button",
721
+ "aria-pressed": we === "target",
722
+ onClick: $(() => N("target")),
723
+ children: [/* @__PURE__ */ b(oe, {
724
+ size: 14,
725
+ "aria-hidden": "true"
726
+ }), "Objetivo"]
727
+ }), /* @__PURE__ */ x("button", {
728
+ type: "button",
729
+ "aria-pressed": we === "own",
730
+ onClick: $(() => N("own")),
731
+ children: [/* @__PURE__ */ b(re, {
732
+ size: 14,
733
+ "aria-hidden": "true"
734
+ }), "Mi flota"]
735
+ })]
736
+ }), /* @__PURE__ */ x("dl", {
737
+ className: "bs-stats",
738
+ children: [
739
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", { children: "Disparos" }), /* @__PURE__ */ b("dd", { children: ut })] }),
740
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", { children: "Impactos" }), /* @__PURE__ */ b("dd", { children: dt })] }),
741
+ /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", { children: "Hundidos" }), /* @__PURE__ */ x("dd", { children: [
742
+ Ot,
743
+ "/",
744
+ p.length
745
+ ] })] })
746
+ ]
747
+ })]
748
+ }),
749
+ /* @__PURE__ */ x("div", {
750
+ className: "bs-stage-wrap",
751
+ children: [
752
+ /* @__PURE__ */ b("div", {
753
+ ref: f,
754
+ className: `bs-stage${O === "fallback" ? " bs-stage--fallback" : ""}`,
755
+ tabIndex: 0,
756
+ role: "application",
757
+ "aria-label": z ? "Tablero 3D de tu flota. Flechas para mover, Enter para colocar o quitar un barco, R para rotar." : "Tablero 3D de Batalla Naval. Flechas para mover la selección, Enter para disparar, R para centrar la cámara.",
758
+ "aria-describedby": be,
759
+ "aria-busy": O === "loading",
760
+ onKeyDown: Ct,
761
+ children: O === "fallback" && /* @__PURE__ */ b(ze, {
762
+ view: ht,
763
+ selected: Y === "target" ? I : null,
764
+ cursor: F,
765
+ onSelect: vt,
766
+ onHover: Be
767
+ })
768
+ }),
769
+ O === "loading" && /* @__PURE__ */ x("div", {
770
+ className: "bs-stage-state",
771
+ role: "status",
772
+ children: [/* @__PURE__ */ b(me, {
773
+ size: 16,
774
+ "aria-hidden": "true"
775
+ }), " Preparando el océano…"]
776
+ }),
777
+ O === "fallback" && /* @__PURE__ */ x("p", {
778
+ className: "bs-fallback-note",
779
+ children: [/* @__PURE__ */ b(pe, {
780
+ size: 12,
781
+ "aria-hidden": "true"
782
+ }), " Vista 3D no disponible · modo 2D"]
783
+ }),
784
+ /* @__PURE__ */ b("div", {
785
+ className: "bs-cell-chip",
786
+ "aria-hidden": "true",
787
+ children: A(z ? X : Y === "target" && I || P)
788
+ }),
789
+ /* @__PURE__ */ b("div", {
790
+ className: "bs-live",
791
+ "aria-live": "polite",
792
+ "aria-atomic": "true",
793
+ children: Ze && /* @__PURE__ */ b("span", {
794
+ className: `bs-toast bs-toast--${Ze.kind}`,
795
+ children: Ze.text
796
+ }, Ze.id)
797
+ })
798
+ ]
799
+ }),
800
+ /* @__PURE__ */ b("p", {
801
+ id: be,
802
+ className: "bs-hint",
803
+ children: z ? "Clic para colocar · clic en un barco para quitarlo · R para rotar" : "Arrastra para rotar · doble clic o Enter para disparar"
804
+ }),
805
+ z && /* @__PURE__ */ x("div", {
806
+ className: "bs-placement",
807
+ children: [
808
+ /* @__PURE__ */ b("ul", {
809
+ className: "bs-fleet",
810
+ "aria-label": "Tu flota",
811
+ children: p.map((e) => {
812
+ let n = q.has(e.id), r = J?.id === e.id;
813
+ return /* @__PURE__ */ b("li", { children: /* @__PURE__ */ x("button", {
814
+ type: "button",
815
+ className: `bs-ship${n ? " is-placed" : ""}${r ? " is-active" : ""}`,
816
+ "aria-pressed": r,
817
+ disabled: !V,
818
+ title: n ? "Quitar y volver a colocar" : "Seleccionar barco",
819
+ onClick: $(() => {
820
+ n && M("bsRemoveShip", t, e.id), Ge(e.id);
821
+ }),
822
+ children: [
823
+ /* @__PURE__ */ b("span", {
824
+ className: "bs-ship__name",
825
+ children: Me(ke(e.id))
826
+ }),
827
+ /* @__PURE__ */ b("span", {
828
+ className: "bs-ship__pips",
829
+ "aria-label": `${e.size} casillas`,
830
+ children: Array.from({ length: e.size }, (e, t) => /* @__PURE__ */ b("i", {}, t))
831
+ }),
832
+ n && /* @__PURE__ */ b(ie, {
833
+ size: 13,
834
+ "aria-label": "colocado"
835
+ })
836
+ ]
837
+ }) }, e.id);
838
+ })
839
+ }),
840
+ /* @__PURE__ */ x("div", {
841
+ className: "chat-game-actions bs-actions",
842
+ children: [
843
+ /* @__PURE__ */ x("button", {
844
+ type: "button",
845
+ className: "chat-game-action bs-btn",
846
+ disabled: !V,
847
+ onClick: bt,
848
+ title: "Rotar (R)",
849
+ children: [/* @__PURE__ */ b(de, {
850
+ size: 15,
851
+ "aria-hidden": "true"
852
+ }), L === "horizontal" ? "Horizontal" : "Vertical"]
853
+ }),
854
+ /* @__PURE__ */ x("button", {
855
+ type: "button",
856
+ className: "chat-game-action bs-btn",
857
+ disabled: !V,
858
+ onClick: () => {
859
+ T("ship_place"), M("bsRandomFleet", t);
860
+ },
861
+ children: [/* @__PURE__ */ b(fe, {
862
+ size: 15,
863
+ "aria-hidden": "true"
864
+ }), "Aleatorio"]
865
+ }),
866
+ /* @__PURE__ */ x("button", {
867
+ type: "button",
868
+ className: "chat-game-action chat-game-action--primary bs-btn",
869
+ disabled: !V || !st,
870
+ onClick: xt,
871
+ children: [/* @__PURE__ */ b(ie, {
872
+ size: 15,
873
+ "aria-hidden": "true"
874
+ }), e.myReady ? "Flota lista" : `Listo (${q.size}/${p.length})`]
875
+ })
876
+ ]
877
+ }),
878
+ e.myReady && /* @__PURE__ */ b("p", {
879
+ className: "bs-waiting",
880
+ children: e.opponentReady ? "Ambas flotas listas · iniciando…" : "Flota lista. Esperando a que el rival coloque su flota…"
881
+ })
882
+ ]
883
+ }),
884
+ rt && /* @__PURE__ */ x("div", {
885
+ className: "chat-game-actions bs-actions",
886
+ children: [
887
+ /* @__PURE__ */ x("button", {
888
+ type: "button",
889
+ className: "chat-game-action chat-game-action--primary bs-btn bs-btn--fire",
890
+ disabled: !B || !I || Y !== "target",
891
+ onClick: () => gt(),
892
+ title: I ? `Disparar en ${A(I)} (Enter)` : "Selecciona una casilla",
893
+ children: [
894
+ /* @__PURE__ */ b(oe, {
895
+ size: 15,
896
+ "aria-hidden": "true"
897
+ }),
898
+ "Disparar",
899
+ I ? ` · ${A(I)}` : ""
900
+ ]
901
+ }),
902
+ /* @__PURE__ */ x("button", {
903
+ type: "button",
904
+ className: "chat-game-action bs-btn",
905
+ "aria-pressed": Ke,
906
+ disabled: Y !== "target" || !U,
907
+ onClick: St,
908
+ title: "Radar de impactos",
909
+ children: [/* @__PURE__ */ b(ue, {
910
+ size: 15,
911
+ "aria-hidden": "true"
912
+ }), "Radar"]
913
+ }),
914
+ /* @__PURE__ */ x("button", {
915
+ type: "button",
916
+ className: "chat-game-action bs-btn",
917
+ disabled: !U,
918
+ onClick: $(() => m.current?.resetCamera?.()),
919
+ title: "Centrar cámara (R)",
920
+ children: [/* @__PURE__ */ b(se, {
921
+ size: 15,
922
+ "aria-hidden": "true"
923
+ }), /* @__PURE__ */ b("span", {
924
+ className: "bs-btn-label",
925
+ children: "Centrar"
926
+ })]
927
+ })
928
+ ]
929
+ })
930
+ ] }),
931
+ e.status === "conflict" && tt && /* @__PURE__ */ b(Le, {
932
+ sync: e.sync,
933
+ connected: o,
934
+ onResync: () => void M("requestResync", t),
935
+ onAdoptOffer: () => void M("adoptResyncOffer", t)
936
+ }),
937
+ e.error && /* @__PURE__ */ x("div", {
938
+ className: "chat-game-error",
939
+ role: "alert",
940
+ children: [/* @__PURE__ */ b("span", { children: e.error }), e.pendingEvent && /* @__PURE__ */ b("button", {
941
+ type: "button",
942
+ className: "chat-game-action",
943
+ disabled: !o || e.pending,
944
+ onClick: () => void M("retry", t),
945
+ children: "Reintentar"
946
+ })]
947
+ }),
948
+ /* @__PURE__ */ b("footer", {
949
+ className: "chat-game-footer",
950
+ children: nt ? "Puedes seguir conversando o invitar a otra partida." : "Hunde los 5 barcos rivales. El chat sigue disponible."
951
+ })
952
+ ]
953
+ });
954
+ }
955
+ var F = m(P);
956
+ export { F as default };
957
+
958
+ //# sourceMappingURL=BattleshipGameCard-CW_A8Nim.js.map