@scriptonita/chess-football-ui 0.5.0 → 0.6.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/dist/index.cjs +204 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +204 -180
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -149,6 +149,7 @@ var Football = ({ className }) => {
|
|
|
149
149
|
var STATIC_I18N_KEYS = [
|
|
150
150
|
"actionPointsAriaLabel",
|
|
151
151
|
"actionPointsShort",
|
|
152
|
+
"ballHolder",
|
|
152
153
|
"endTurn",
|
|
153
154
|
"endTurnConfirm",
|
|
154
155
|
"endTurnConfirmDescription",
|
|
@@ -293,6 +294,7 @@ function GameBoard({ userSide, showCoordinates = false, keyboardNav = true }) {
|
|
|
293
294
|
return [];
|
|
294
295
|
}, [boardState, selectedPieceId]);
|
|
295
296
|
if (!boardState) return null;
|
|
297
|
+
const ballHolderPiece = boardState.pieces.find((p) => p.id === boardState.ball.holderId) ?? null;
|
|
296
298
|
const lastMove = boardState.lastMove;
|
|
297
299
|
const ball = boardState.ball;
|
|
298
300
|
const ballMoved = !!prevBall && (prevBall.pos.x !== ball.pos.x || prevBall.pos.y !== ball.pos.y);
|
|
@@ -529,7 +531,7 @@ function GameBoard({ userSide, showCoordinates = false, keyboardNav = true }) {
|
|
|
529
531
|
}
|
|
530
532
|
return squares;
|
|
531
533
|
};
|
|
532
|
-
const board = /* @__PURE__ */ jsxRuntime.
|
|
534
|
+
const board = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
533
535
|
"div",
|
|
534
536
|
{
|
|
535
537
|
className: cn(
|
|
@@ -546,198 +548,220 @@ function GameBoard({ userSide, showCoordinates = false, keyboardNav = true }) {
|
|
|
546
548
|
"aria-label": "Game board \u2014 arrow keys to move the cursor, Enter to act",
|
|
547
549
|
onKeyDown: handleKeyDown
|
|
548
550
|
} : {},
|
|
549
|
-
children:
|
|
550
|
-
/* @__PURE__ */ jsxRuntime.
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
viewBox: "0 0 9 12",
|
|
555
|
-
preserveAspectRatio: "none",
|
|
556
|
-
className: "absolute inset-0 w-full h-full pointer-events-none",
|
|
557
|
-
"aria-hidden": "true",
|
|
558
|
-
children: [
|
|
559
|
-
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "0", width: "5", height: "2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
560
|
-
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "10", width: "5", height: "2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
561
|
-
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "0", y1: "6", x2: "9", y2: "6", stroke: "white", strokeOpacity: "0.35", strokeWidth: "0.05" }),
|
|
562
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "6", r: "1.5", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
563
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "6", r: "0.12", fill: "white", fillOpacity: "0.5" }),
|
|
564
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "1.5", r: "0.1", fill: "white", fillOpacity: "0.5" }),
|
|
565
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "10.5", r: "0.1", fill: "white", fillOpacity: "0.5" }),
|
|
566
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 3.086,2 A 1.5,1.5 0 0 0 5.914,2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
567
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 3.086,10 A 1.5,1.5 0 0 1 5.914,10", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
568
|
-
hoveredPassAt && passCarrier && /* @__PURE__ */ jsxRuntime.jsx(
|
|
569
|
-
"line",
|
|
570
|
-
{
|
|
571
|
-
"data-testid": "pass-trajectory-line",
|
|
572
|
-
x1: passCarrier.pos.x + 0.5,
|
|
573
|
-
y1: ROWS - 1 - passCarrier.pos.y + 0.5,
|
|
574
|
-
x2: hoveredPassAt.x + 0.5,
|
|
575
|
-
y2: ROWS - 1 - hoveredPassAt.y + 0.5,
|
|
576
|
-
stroke: trajectoryIntercepted ? "var(--danger)" : "var(--pass-highlight)",
|
|
577
|
-
strokeWidth: "0.08",
|
|
578
|
-
strokeDasharray: "0.15 0.1",
|
|
579
|
-
strokeLinecap: "round"
|
|
580
|
-
}
|
|
581
|
-
)
|
|
582
|
-
]
|
|
583
|
-
}
|
|
584
|
-
),
|
|
585
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", children: [
|
|
586
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "sync", children: boardState.pieces.map((piece) => {
|
|
587
|
-
const isPickupCarrier = pickupCarrierId === piece.id;
|
|
588
|
-
const pieceTransition = isPickupCarrier ? { duration: PICKUP_DURATION, ease: "linear" } : { type: "spring", stiffness: 200, damping: 25, mass: 1 };
|
|
589
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
590
|
-
framerMotion.motion.div,
|
|
551
|
+
children: [
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden md:flex items-center justify-between gap-2 px-2.5 py-1", children: [
|
|
553
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5 min-h-[1.75rem]", "aria-live": "polite", children: ballHolderPiece && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
554
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
555
|
+
"div",
|
|
591
556
|
{
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
557
|
+
style: ballHolderPiece.side === "white" ? WHITE_PIECE_STYLE : BLACK_PIECE_STYLE,
|
|
558
|
+
className: "relative w-7 h-7 flex items-center justify-center rounded-full shrink-0",
|
|
559
|
+
children: [
|
|
560
|
+
/* @__PURE__ */ jsxRuntime.jsx(PieceIcon, { type: ballHolderPiece.type, side: ballHolderPiece.side }),
|
|
561
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -bottom-1 -right-1 w-3.5 h-3.5 flex items-center justify-center rounded-full bg-bg-secondary border border-border-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2.5 h-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(Football, {}) }) })
|
|
562
|
+
]
|
|
563
|
+
}
|
|
564
|
+
),
|
|
565
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-inter text-[11px] text-fg-secondary", children: [
|
|
566
|
+
t("ballHolder"),
|
|
567
|
+
": ",
|
|
568
|
+
t(`pieces.${ballHolderPiece.type}`)
|
|
569
|
+
] })
|
|
570
|
+
] }) }),
|
|
571
|
+
keyboardNav && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
572
|
+
"div",
|
|
573
|
+
{
|
|
574
|
+
ref: shortcutsRef,
|
|
575
|
+
className: "relative",
|
|
576
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
577
|
+
children: [
|
|
578
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
579
|
+
"button",
|
|
607
580
|
{
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
581
|
+
type: "button",
|
|
582
|
+
onClick: (e) => {
|
|
583
|
+
e.stopPropagation();
|
|
584
|
+
setShortcutsOpen((o) => !o);
|
|
585
|
+
},
|
|
586
|
+
"aria-label": t("shortcuts.buttonLabel"),
|
|
587
|
+
"aria-expanded": shortcutsOpen,
|
|
588
|
+
className: "w-8 h-8 flex items-center justify-center rounded-full bg-bg-secondary/80 border border-border-subtle text-fg-muted hover:text-fg-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-green",
|
|
589
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HelpCircle, { size: 16, strokeWidth: 2, "aria-hidden": "true" })
|
|
590
|
+
}
|
|
591
|
+
),
|
|
592
|
+
shortcutsOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
593
|
+
"div",
|
|
594
|
+
{
|
|
595
|
+
className: "absolute top-full right-0 mt-1 z-50 w-max max-w-[220px] bg-bg-secondary border border-border-subtle rounded-md shadow-xl p-2.5 pointer-events-auto",
|
|
596
|
+
onClick: (e) => e.stopPropagation(),
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-inter text-[11px] font-semibold text-fg-primary mb-1.5", children: t("shortcuts.title") }),
|
|
599
|
+
/* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "font-mono text-[10px] text-fg-secondary leading-relaxed", children: [
|
|
600
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
601
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "\u2191\u2193\u2190\u2192" }),
|
|
602
|
+
" ",
|
|
603
|
+
t("shortcuts.arrows")
|
|
604
|
+
] }),
|
|
605
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
606
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "Enter" }),
|
|
607
|
+
" ",
|
|
608
|
+
t("shortcuts.select")
|
|
609
|
+
] }),
|
|
610
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
611
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "M" }),
|
|
612
|
+
" ",
|
|
613
|
+
t("shortcuts.move")
|
|
614
|
+
] }),
|
|
615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
616
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "P" }),
|
|
617
|
+
" ",
|
|
618
|
+
t("shortcuts.pass")
|
|
619
|
+
] }),
|
|
620
|
+
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
621
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "Esc" }),
|
|
622
|
+
" ",
|
|
623
|
+
t("shortcuts.cancel")
|
|
624
|
+
] })
|
|
625
|
+
] })
|
|
626
|
+
]
|
|
612
627
|
}
|
|
613
628
|
)
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
629
|
+
]
|
|
630
|
+
}
|
|
631
|
+
)
|
|
632
|
+
] }),
|
|
633
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", style: { containerType: "inline-size" }, children: [
|
|
634
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-9 gap-[1px]", children: renderSquares() }),
|
|
635
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
636
|
+
"svg",
|
|
637
|
+
{
|
|
638
|
+
viewBox: "0 0 9 12",
|
|
639
|
+
preserveAspectRatio: "none",
|
|
640
|
+
className: "absolute inset-0 w-full h-full pointer-events-none",
|
|
641
|
+
"aria-hidden": "true",
|
|
642
|
+
children: [
|
|
643
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "0", width: "5", height: "2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
644
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "10", width: "5", height: "2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
645
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "0", y1: "6", x2: "9", y2: "6", stroke: "white", strokeOpacity: "0.35", strokeWidth: "0.05" }),
|
|
646
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "6", r: "1.5", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
647
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "6", r: "0.12", fill: "white", fillOpacity: "0.5" }),
|
|
648
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "1.5", r: "0.1", fill: "white", fillOpacity: "0.5" }),
|
|
649
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "4.5", cy: "10.5", r: "0.1", fill: "white", fillOpacity: "0.5" }),
|
|
650
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 3.086,2 A 1.5,1.5 0 0 0 5.914,2", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
651
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 3.086,10 A 1.5,1.5 0 0 1 5.914,10", fill: "none", stroke: "white", strokeOpacity: "0.3", strokeWidth: "0.05" }),
|
|
652
|
+
hoveredPassAt && passCarrier && /* @__PURE__ */ jsxRuntime.jsx(
|
|
653
|
+
"line",
|
|
654
|
+
{
|
|
655
|
+
"data-testid": "pass-trajectory-line",
|
|
656
|
+
x1: passCarrier.pos.x + 0.5,
|
|
657
|
+
y1: ROWS - 1 - passCarrier.pos.y + 0.5,
|
|
658
|
+
x2: hoveredPassAt.x + 0.5,
|
|
659
|
+
y2: ROWS - 1 - hoveredPassAt.y + 0.5,
|
|
660
|
+
stroke: trajectoryIntercepted ? "var(--danger)" : "var(--pass-highlight)",
|
|
661
|
+
strokeWidth: "0.08",
|
|
662
|
+
strokeDasharray: "0.15 0.1",
|
|
663
|
+
strokeLinecap: "round"
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
]
|
|
636
667
|
}
|
|
637
|
-
|
|
668
|
+
),
|
|
669
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none", children: [
|
|
670
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "sync", children: boardState.pieces.map((piece) => {
|
|
671
|
+
const isPickupCarrier = pickupCarrierId === piece.id;
|
|
672
|
+
const pieceTransition = isPickupCarrier ? { duration: PICKUP_DURATION, ease: "linear" } : { type: "spring", stiffness: 200, damping: 25, mass: 1 };
|
|
673
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
674
|
+
framerMotion.motion.div,
|
|
675
|
+
{
|
|
676
|
+
layout: true,
|
|
677
|
+
initial: false,
|
|
678
|
+
animate: {
|
|
679
|
+
left: `${piece.pos.x / COLS * 100}%`,
|
|
680
|
+
top: `${(ROWS - 1 - piece.pos.y) / ROWS * 100}%`
|
|
681
|
+
},
|
|
682
|
+
transition: pieceTransition,
|
|
683
|
+
style: {
|
|
684
|
+
position: "absolute",
|
|
685
|
+
width: `${100 / COLS}%`,
|
|
686
|
+
height: `${100 / ROWS}%`
|
|
687
|
+
},
|
|
688
|
+
className: "flex items-center justify-center pointer-events-auto",
|
|
689
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
690
|
+
GamePiece,
|
|
691
|
+
{
|
|
692
|
+
piece,
|
|
693
|
+
isSelected: selectedPieceId === piece.id,
|
|
694
|
+
hasBall: boardState.ball.holderId === piece.id,
|
|
695
|
+
onClick: (e) => handlePieceClick(piece.id, piece.pos.x, piece.pos.y, e)
|
|
696
|
+
}
|
|
697
|
+
)
|
|
698
|
+
},
|
|
699
|
+
piece.id
|
|
700
|
+
);
|
|
701
|
+
}) }),
|
|
702
|
+
(() => {
|
|
703
|
+
const targetX = ball.pos.x / COLS * 100;
|
|
704
|
+
const targetY = (ROWS - 1 - ball.pos.y) / ROWS * 100;
|
|
705
|
+
let animate;
|
|
706
|
+
let transition;
|
|
707
|
+
if (isPickupOnMove && prevBall) {
|
|
708
|
+
const prevX = prevBall.pos.x / COLS * 100;
|
|
709
|
+
const prevY = (ROWS - 1 - prevBall.pos.y) / ROWS * 100;
|
|
710
|
+
const pulseStart = Math.max(0.05, pickupProportion - 0.06);
|
|
711
|
+
animate = {
|
|
712
|
+
left: [`${prevX}%`, `${prevX}%`, `${prevX}%`, `${targetX}%`],
|
|
713
|
+
top: [`${prevY}%`, `${prevY}%`, `${prevY}%`, `${targetY}%`],
|
|
714
|
+
scale: [1, 1, 1.35, 1]
|
|
715
|
+
};
|
|
716
|
+
transition = { duration: PICKUP_DURATION, times: [0, pulseStart, pickupProportion, 1], ease: "linear" };
|
|
717
|
+
} else {
|
|
718
|
+
animate = { left: `${targetX}%`, top: `${targetY}%`, scale: 1 };
|
|
719
|
+
transition = { type: "spring", stiffness: 300, damping: 30, mass: 0.5 };
|
|
720
|
+
}
|
|
721
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
722
|
+
framerMotion.motion.div,
|
|
723
|
+
{
|
|
724
|
+
initial: false,
|
|
725
|
+
animate,
|
|
726
|
+
transition,
|
|
727
|
+
style: {
|
|
728
|
+
position: "absolute",
|
|
729
|
+
width: `${100 / COLS}%`,
|
|
730
|
+
height: `${100 / ROWS}%`,
|
|
731
|
+
zIndex: 50
|
|
732
|
+
},
|
|
733
|
+
className: "flex items-center justify-center pointer-events-none",
|
|
734
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[60%] h-[60%]", children: /* @__PURE__ */ jsxRuntime.jsx(Football, {}) })
|
|
735
|
+
},
|
|
736
|
+
"ball"
|
|
737
|
+
);
|
|
738
|
+
})(),
|
|
739
|
+
invalidClickAt && /* @__PURE__ */ jsxRuntime.jsx(
|
|
638
740
|
framerMotion.motion.div,
|
|
639
741
|
{
|
|
742
|
+
"data-testid": "invalid-action-shake",
|
|
743
|
+
"aria-hidden": "true",
|
|
640
744
|
initial: false,
|
|
641
|
-
animate,
|
|
642
|
-
transition,
|
|
745
|
+
animate: prefersReducedMotion ? { opacity: [0.9, 0] } : { x: [0, -3, 3, -3, 3, 0] },
|
|
746
|
+
transition: { duration: 0.08 },
|
|
643
747
|
style: {
|
|
644
748
|
position: "absolute",
|
|
749
|
+
left: `${invalidClickAt.x / COLS * 100}%`,
|
|
750
|
+
top: `${(ROWS - 1 - invalidClickAt.y) / ROWS * 100}%`,
|
|
645
751
|
width: `${100 / COLS}%`,
|
|
646
|
-
height: `${100 / ROWS}
|
|
647
|
-
zIndex: 50
|
|
752
|
+
height: `${100 / ROWS}%`
|
|
648
753
|
},
|
|
649
|
-
className: "
|
|
650
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[60%] h-[60%]", children: /* @__PURE__ */ jsxRuntime.jsx(Football, {}) })
|
|
651
|
-
},
|
|
652
|
-
"ball"
|
|
653
|
-
);
|
|
654
|
-
})(),
|
|
655
|
-
invalidClickAt && /* @__PURE__ */ jsxRuntime.jsx(
|
|
656
|
-
framerMotion.motion.div,
|
|
657
|
-
{
|
|
658
|
-
"data-testid": "invalid-action-shake",
|
|
659
|
-
"aria-hidden": "true",
|
|
660
|
-
initial: false,
|
|
661
|
-
animate: prefersReducedMotion ? { opacity: [0.9, 0] } : { x: [0, -3, 3, -3, 3, 0] },
|
|
662
|
-
transition: { duration: 0.08 },
|
|
663
|
-
style: {
|
|
664
|
-
position: "absolute",
|
|
665
|
-
left: `${invalidClickAt.x / COLS * 100}%`,
|
|
666
|
-
top: `${(ROWS - 1 - invalidClickAt.y) / ROWS * 100}%`,
|
|
667
|
-
width: `${100 / COLS}%`,
|
|
668
|
-
height: `${100 / ROWS}%`
|
|
754
|
+
className: "ring-2 ring-inset ring-danger/70 rounded-sm"
|
|
669
755
|
},
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
keyboardNav && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
680
|
-
"div",
|
|
681
|
-
{
|
|
682
|
-
ref: shortcutsRef,
|
|
683
|
-
className: "hidden md:block absolute top-2 right-2 z-40",
|
|
684
|
-
onKeyDown: (e) => e.stopPropagation(),
|
|
685
|
-
children: [
|
|
686
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
687
|
-
"button",
|
|
688
|
-
{
|
|
689
|
-
type: "button",
|
|
690
|
-
onClick: (e) => {
|
|
691
|
-
e.stopPropagation();
|
|
692
|
-
setShortcutsOpen((o) => !o);
|
|
693
|
-
},
|
|
694
|
-
"aria-label": t("shortcuts.buttonLabel"),
|
|
695
|
-
"aria-expanded": shortcutsOpen,
|
|
696
|
-
className: "w-11 h-11 flex items-center justify-center rounded-full bg-bg-secondary/80 border border-border-subtle text-fg-muted hover:text-fg-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-green backdrop-blur-sm",
|
|
697
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HelpCircle, { size: 16, strokeWidth: 2, "aria-hidden": "true" })
|
|
698
|
-
}
|
|
699
|
-
),
|
|
700
|
-
shortcutsOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
701
|
-
"div",
|
|
702
|
-
{
|
|
703
|
-
className: "absolute top-full right-0 mt-1 z-50 w-max max-w-[220px] bg-bg-secondary border border-border-subtle rounded-md shadow-xl p-2.5 pointer-events-auto",
|
|
704
|
-
onClick: (e) => e.stopPropagation(),
|
|
705
|
-
children: [
|
|
706
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-inter text-[11px] font-semibold text-fg-primary mb-1.5", children: t("shortcuts.title") }),
|
|
707
|
-
/* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "font-mono text-[10px] text-fg-secondary leading-relaxed", children: [
|
|
708
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
709
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "\u2191\u2193\u2190\u2192" }),
|
|
710
|
-
" ",
|
|
711
|
-
t("shortcuts.arrows")
|
|
712
|
-
] }),
|
|
713
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
714
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "Enter" }),
|
|
715
|
-
" ",
|
|
716
|
-
t("shortcuts.select")
|
|
717
|
-
] }),
|
|
718
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
719
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "M" }),
|
|
720
|
-
" ",
|
|
721
|
-
t("shortcuts.move")
|
|
722
|
-
] }),
|
|
723
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
724
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "P" }),
|
|
725
|
-
" ",
|
|
726
|
-
t("shortcuts.pass")
|
|
727
|
-
] }),
|
|
728
|
-
/* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
729
|
-
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "text-fg-primary", children: "Esc" }),
|
|
730
|
-
" ",
|
|
731
|
-
t("shortcuts.cancel")
|
|
732
|
-
] })
|
|
733
|
-
] })
|
|
734
|
-
]
|
|
735
|
-
}
|
|
736
|
-
)
|
|
737
|
-
]
|
|
738
|
-
}
|
|
739
|
-
)
|
|
740
|
-
] })
|
|
756
|
+
invalidClickAt.nonce
|
|
757
|
+
)
|
|
758
|
+
] }),
|
|
759
|
+
isOffsideRisk && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-2 left-1/2 -translate-x-1/2 z-30 flex items-center gap-1.5 px-3 py-1.5 bg-warning/20 border border-warning/50 rounded-full font-inter text-xs font-semibold text-warning pointer-events-none whitespace-nowrap backdrop-blur-sm", children: [
|
|
760
|
+
"\u26A0 ",
|
|
761
|
+
t("offsideWarning")
|
|
762
|
+
] })
|
|
763
|
+
] })
|
|
764
|
+
]
|
|
741
765
|
}
|
|
742
766
|
);
|
|
743
767
|
if (!showCoordinates) return board;
|