@ankhorage/zora 25.11.0 → 26.0.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 (106) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -4
  3. package/dist/capabilities/index.js +65 -41
  4. package/dist/capabilities/index.js.map +3 -3
  5. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts +1 -1
  6. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts.map +1 -1
  7. package/dist/features/chess/adapters/inbound/ChessBoard.js +130 -83
  8. package/dist/features/chess/adapters/inbound/ChessBoard.js.map +1 -1
  9. package/dist/features/chess/meta.d.ts +97 -72
  10. package/dist/features/chess/meta.d.ts.map +1 -1
  11. package/dist/features/chess/meta.js +64 -40
  12. package/dist/features/chess/meta.js.map +1 -1
  13. package/dist/features/chess/public.d.ts +1 -7
  14. package/dist/features/chess/public.d.ts.map +1 -1
  15. package/dist/features/chess/public.js +0 -6
  16. package/dist/features/chess/public.js.map +1 -1
  17. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts +6 -0
  18. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts.map +1 -0
  19. package/dist/features/chess/utils/createChessBoardCellPressHandler.js +17 -0
  20. package/dist/features/chess/utils/createChessBoardCellPressHandler.js.map +1 -0
  21. package/dist/features/chess/utils/createChessBoardCells.d.ts +12 -0
  22. package/dist/features/chess/utils/createChessBoardCells.d.ts.map +1 -0
  23. package/dist/features/chess/utils/createChessBoardCells.js +28 -0
  24. package/dist/features/chess/utils/createChessBoardCells.js.map +1 -0
  25. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.d.ts +2 -0
  26. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.d.ts.map +1 -1
  27. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js +68 -4
  28. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js.map +1 -1
  29. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.d.ts +3 -1
  30. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.d.ts.map +1 -1
  31. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.js +41 -8
  32. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.js.map +1 -1
  33. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.d.ts.map +1 -1
  34. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.js +6 -2
  35. package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.js.map +1 -1
  36. package/dist/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.d.ts +2 -2
  37. package/dist/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.d.ts.map +1 -1
  38. package/dist/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.js +3 -3
  39. package/dist/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.js.map +1 -1
  40. package/dist/readerFree.d.ts +2 -2
  41. package/dist/readerFree.d.ts.map +1 -1
  42. package/dist/readerFree.js +1 -1
  43. package/dist/readerFree.js.map +1 -1
  44. package/dist/types/authoring.d.ts +2 -1
  45. package/dist/types/authoring.d.ts.map +1 -1
  46. package/dist/types/authoring.js.map +1 -1
  47. package/dist/types/chess.d.ts +27 -20
  48. package/dist/types/chess.d.ts.map +1 -1
  49. package/dist/types/chess.js.map +1 -1
  50. package/package.json +31 -92
  51. package/src/features/chess/adapters/inbound/ChessBoard.tsx +263 -112
  52. package/src/features/chess/meta.ts +64 -40
  53. package/src/features/chess/public.test.tsx +77 -228
  54. package/src/features/chess/public.ts +2 -9
  55. package/src/features/chess/utils/createChessBoardCellPressHandler.ts +30 -0
  56. package/src/features/chess/utils/createChessBoardCells.ts +54 -0
  57. package/src/features/chessTabletopOwnership.test.ts +3 -7
  58. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphController.test.ts +145 -1
  59. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts +86 -5
  60. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.test.ts +163 -6
  61. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphResizeObserver.ts +57 -8
  62. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.test.ts +42 -0
  63. package/src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts +7 -1
  64. package/src/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.test.ts +7 -3
  65. package/src/features/graph-view/adapters/inbound/web-artifact/shouldFitGraphAfterLayout.ts +7 -3
  66. package/src/features/registry/componentMeta.test.ts +12 -1
  67. package/src/readerFree.ts +3 -15
  68. package/src/types/authoring.ts +2 -1
  69. package/src/types/chess.ts +28 -21
  70. package/web-dist/chunks/Accordion-91sjb3zh.js +453 -0
  71. package/web-dist/components/chess-board/ChessBoard.js +2 -1
  72. package/web-dist/components/graph-view/GraphView.js +107 -17
  73. package/web-dist/components/opening-book/OpeningBook.js +2 -1
  74. package/web-dist/manifest.json +8 -4
  75. package/dist/features/chess/utils/chessEngine.d.ts +0 -8
  76. package/dist/features/chess/utils/chessEngine.d.ts.map +0 -1
  77. package/dist/features/chess/utils/chessEngine.js +0 -71
  78. package/dist/features/chess/utils/chessEngine.js.map +0 -1
  79. package/dist/features/chess/utils/chessSquares.d.ts +0 -4
  80. package/dist/features/chess/utils/chessSquares.d.ts.map +0 -1
  81. package/dist/features/chess/utils/chessSquares.js +0 -3
  82. package/dist/features/chess/utils/chessSquares.js.map +0 -1
  83. package/dist/features/chess/utils/createBoardSquares.d.ts +0 -4
  84. package/dist/features/chess/utils/createBoardSquares.d.ts.map +0 -1
  85. package/dist/features/chess/utils/createBoardSquares.js +0 -9
  86. package/dist/features/chess/utils/createBoardSquares.js.map +0 -1
  87. package/dist/features/chess/utils/getSquareFile.d.ts +0 -4
  88. package/dist/features/chess/utils/getSquareFile.d.ts.map +0 -1
  89. package/dist/features/chess/utils/getSquareFile.js +0 -5
  90. package/dist/features/chess/utils/getSquareFile.js.map +0 -1
  91. package/dist/features/chess/utils/getSquareRank.d.ts +0 -4
  92. package/dist/features/chess/utils/getSquareRank.d.ts.map +0 -1
  93. package/dist/features/chess/utils/getSquareRank.js +0 -5
  94. package/dist/features/chess/utils/getSquareRank.js.map +0 -1
  95. package/dist/features/chess/utils/isLightSquare.d.ts +0 -4
  96. package/dist/features/chess/utils/isLightSquare.d.ts.map +0 -1
  97. package/dist/features/chess/utils/isLightSquare.js +0 -6
  98. package/dist/features/chess/utils/isLightSquare.js.map +0 -1
  99. package/src/features/chess/utils/chessEngine.test.ts +0 -35
  100. package/src/features/chess/utils/chessEngine.ts +0 -83
  101. package/src/features/chess/utils/chessSquares.ts +0 -6
  102. package/src/features/chess/utils/createBoardSquares.ts +0 -13
  103. package/src/features/chess/utils/getSquareFile.ts +0 -6
  104. package/src/features/chess/utils/getSquareRank.ts +0 -6
  105. package/src/features/chess/utils/isLightSquare.ts +0 -8
  106. package/web-dist/chunks/Accordion-xcm1qc39.js +0 -3813
@@ -4,33 +4,36 @@ import type { ZoraBaseProps } from './base';
4
4
 
5
5
  export type ChessBoardOrientation = 'white' | 'black';
6
6
  export type ChessPieceCode = string;
7
- export type ChessSquareId =
8
- `${'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h'}${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8}`;
9
- export type ChessPromotionPiece = 'q' | 'r' | 'b' | 'n';
10
7
 
11
- export interface ChessMoveAttempt {
12
- readonly from: ChessSquareId;
13
- readonly to: ChessSquareId;
14
- readonly promotion?: ChessPromotionPiece;
8
+ /** A caller-owned cell location in a rectangular chess presentation board. */
9
+ export interface ChessBoardCell {
10
+ readonly column: number;
11
+ readonly row: number;
15
12
  }
16
13
 
17
- export interface ChessMoveResult extends Omit<ChessMoveAttempt, 'promotion'> {
18
- readonly fen: string;
19
- readonly lan: string;
20
- readonly promotion?: ChessPromotionPiece;
21
- readonly san: string;
14
+ /** The bounded presentation dimensions supported by ChessBoard. */
15
+ export interface ChessBoardDimensions {
16
+ readonly columns: number;
17
+ readonly rows: number;
18
+ }
19
+
20
+ export interface ChessMoveAttempt {
21
+ readonly from: ChessBoardCell;
22
+ readonly to: ChessBoardCell;
22
23
  }
23
24
 
24
25
  export interface ChessPieceState {
25
26
  readonly color: 'black' | 'white';
26
27
  readonly piece: ChessPieceCode;
27
- readonly square: ChessSquareId;
28
+ readonly cell: ChessBoardCell;
28
29
  }
29
30
 
30
31
  export interface ChessPieceRenderContext {
31
32
  readonly color: string;
32
33
  readonly piece: ChessPieceCode;
33
- readonly square: ChessSquareId;
34
+ readonly cell: ChessBoardCell;
35
+ /** Available cell edge length in pixels. */
36
+ readonly size: number;
34
37
  }
35
38
 
36
39
  export type ChessPieceRenderer = (context: ChessPieceRenderContext) => React.ReactNode;
@@ -65,20 +68,24 @@ export interface OpeningBookColorScheme {
65
68
  export type OpeningBookColorOverrides = Partial<OpeningBookColorScheme>;
66
69
 
67
70
  export interface ChessBoardProps extends ZoraBaseProps {
68
- readonly fen?: string;
71
+ /** Number of displayed columns, from 2 through 24. */
72
+ readonly columns?: number;
73
+ /** Number of displayed rows, from 2 through 24. */
74
+ readonly rows?: number;
69
75
  readonly pieces?: readonly ChessPieceState[];
70
76
  readonly orientation?: ChessBoardOrientation;
71
- readonly selectedSquare?: ChessSquareId | null;
72
- readonly legalTargets?: readonly ChessSquareId[];
77
+ readonly selectedCell?: ChessBoardCell | null;
78
+ readonly legalTargets?: readonly ChessBoardCell[];
73
79
  readonly lastMove?: ChessMoveAttempt | null;
74
80
  readonly disabled?: boolean;
75
81
  readonly showCoordinates?: boolean;
76
- readonly validateMoves?: boolean;
82
+ /** Enables explicit editor resize controls when a dimensions callback is supplied. */
83
+ readonly resizable?: boolean;
77
84
  readonly colorScheme?: ChessBoardColorOverrides;
78
- readonly onSquarePress?: (square: ChessSquareId) => void;
85
+ readonly onCellPress?: (cell: ChessBoardCell) => void;
79
86
  readonly onMoveAttempt?: (move: ChessMoveAttempt) => void;
80
- readonly onLegalMove?: (move: ChessMoveResult) => void;
81
- readonly onInvalidMove?: (move: ChessMoveAttempt) => void;
87
+ /** Receives a caller-owned resize proposal; ZORA never mutates board dimensions. */
88
+ readonly onDimensionsChange?: (dimensions: ChessBoardDimensions) => void;
82
89
  readonly renderPiece?: ChessPieceRenderer;
83
90
  }
84
91
 
@@ -0,0 +1,453 @@
1
+ 'use client';
2
+ import {
3
+ GridView2
4
+ } from "./Accordion-t0k1cjca.js";
5
+ import {
6
+ withZoraThemeScope
7
+ } from "./Accordion-vj1m2wck.js";
8
+ import {
9
+ useZoraTheme2
10
+ } from "./Accordion-srjya6dz.js";
11
+ import {
12
+ require_cjs
13
+ } from "./Accordion-xgpzh4wq.js";
14
+ import {
15
+ __toESM
16
+ } from "./Accordion-nh0cs9hq.js";
17
+
18
+ // src/features/chess/adapters/inbound/ChessBoard.tsx
19
+ var import_react_native = __toESM(require_cjs(), 1);
20
+ import React from "react";
21
+
22
+ // src/features/chess/utils/createChessBoardCellPressHandler.ts
23
+ function createChessBoardCellPressHandler({
24
+ disabled,
25
+ interactionPolicy,
26
+ onCellPress,
27
+ onMoveAttempt,
28
+ selectedCell
29
+ }) {
30
+ return (cell) => {
31
+ if (disabled || interactionPolicy === "passive")
32
+ return;
33
+ onCellPress?.(cell);
34
+ if (selectedCell === null || selectedCell === undefined || cellsEqual(selectedCell, cell)) {
35
+ return;
36
+ }
37
+ onMoveAttempt?.({ from: selectedCell, to: cell });
38
+ };
39
+ }
40
+ function cellsEqual(left, right) {
41
+ return left.column === right.column && left.row === right.row;
42
+ }
43
+
44
+ // src/features/chess/utils/createChessBoardCells.ts
45
+ var minimumDimension = 2;
46
+ var maximumDimension = 24;
47
+ function createChessBoardCells(columns, rows, orientation) {
48
+ validateChessBoardDimensions(columns, rows);
49
+ return Array.from({ length: rows }, (_, rowIndex) => Array.from({ length: columns }, (_, columnIndex) => {
50
+ const column = columnIndex + 1;
51
+ const row = rowIndex + 1;
52
+ return {
53
+ column,
54
+ height: 1,
55
+ id: `${column}:${row}`,
56
+ row,
57
+ width: 1,
58
+ x: orientation === "white" ? columnIndex : columns - column,
59
+ y: orientation === "white" ? rows - row : rowIndex
60
+ };
61
+ })).flat();
62
+ }
63
+ function validateChessBoardDimensions(columns, rows) {
64
+ if (![columns, rows].every((dimension) => Number.isInteger(dimension) && dimension >= minimumDimension && dimension <= maximumDimension)) {
65
+ throw new RangeError(`ChessBoard dimensions must be whole numbers from ${minimumDimension} through ${maximumDimension}.`);
66
+ }
67
+ }
68
+
69
+ // src/features/chess/utils/createChessBoardColorScheme.ts
70
+ function createChessBoardColorScheme(theme, overrides) {
71
+ return {
72
+ border: theme.semantics.neutral.divider,
73
+ coordinateText: theme.semantics.content.muted,
74
+ darkPiece: theme.semantics.content.default,
75
+ darkSquare: theme.semantics.neutral.surfaceHover,
76
+ darkSquareText: theme.semantics.content.muted,
77
+ lastMoveFrom: theme.semantics.warning.softBg,
78
+ lastMoveTo: theme.semantics.warning.softBg,
79
+ legalTarget: theme.semantics.success.softBg,
80
+ lightPiece: theme.semantics.content.default,
81
+ lightSquare: theme.semantics.neutral.surface,
82
+ lightSquareText: theme.semantics.content.muted,
83
+ selectedSquare: theme.semantics.action.primary.softBg,
84
+ ...overrides
85
+ };
86
+ }
87
+
88
+ // src/features/chess/adapters/inbound/ChessBoard.tsx
89
+ import { jsx, jsxs } from "react/jsx-runtime";
90
+ var symbols = new Map([
91
+ ["white:p", "♙"],
92
+ ["white:n", "♘"],
93
+ ["white:b", "♗"],
94
+ ["white:r", "♖"],
95
+ ["white:q", "♕"],
96
+ ["white:k", "♔"],
97
+ ["black:p", "♟"],
98
+ ["black:n", "♞"],
99
+ ["black:b", "♝"],
100
+ ["black:r", "♜"],
101
+ ["black:q", "♛"],
102
+ ["black:k", "♚"]
103
+ ]);
104
+ var minimumDimension2 = 2;
105
+ var maximumDimension2 = 24;
106
+ var ChessBoard2 = withZoraThemeScope(ChessBoardInner);
107
+ function ChessBoardInner({
108
+ columns = 8,
109
+ rows = 8,
110
+ pieces,
111
+ orientation = "white",
112
+ selectedCell = null,
113
+ legalTargets = [],
114
+ lastMove = null,
115
+ disabled = false,
116
+ showCoordinates = false,
117
+ resizable = false,
118
+ colorScheme,
119
+ onCellPress,
120
+ onMoveAttempt,
121
+ onDimensionsChange,
122
+ renderPiece,
123
+ interactionPolicy,
124
+ testID
125
+ }) {
126
+ const { theme } = useZoraTheme2();
127
+ const colors = createChessBoardColorScheme(theme, colorScheme);
128
+ const dimensions = React.useMemo(() => ({ columns, rows }), [columns, rows]);
129
+ const [width, setWidth] = React.useState(0);
130
+ const cells = React.useMemo(() => createChessBoardCells(columns, rows, orientation), [columns, orientation, rows]);
131
+ const piecesByCell = React.useMemo(() => new Map((pieces ?? []).map((piece) => [getCellKey(piece.cell), piece])), [pieces]);
132
+ const cellById = React.useMemo(() => new Map(cells.map((cell) => [cell.id, cell])), [cells]);
133
+ const legalTargetSet = React.useMemo(() => new Set(legalTargets.map(getCellKey)), [legalTargets]);
134
+ const pressCell = createChessBoardCellPressHandler({
135
+ disabled,
136
+ interactionPolicy,
137
+ onCellPress,
138
+ onMoveAttempt,
139
+ selectedCell
140
+ });
141
+ const canResize = resizable && onDimensionsChange !== undefined && !disabled && interactionPolicy !== "passive";
142
+ const height = width * (dimensions.rows / dimensions.columns);
143
+ const cellSize = width / dimensions.columns;
144
+ return /* @__PURE__ */ jsxs(import_react_native.View, {
145
+ accessibilityLabel: "Chess board",
146
+ onLayout: (event) => setWidth(event.nativeEvent.layout.width),
147
+ style: [
148
+ styles.board,
149
+ {
150
+ aspectRatio: dimensions.columns / dimensions.rows,
151
+ borderColor: colors.border,
152
+ opacity: disabled ? 0.56 : 1
153
+ }
154
+ ],
155
+ testID,
156
+ children: [
157
+ width > 0 ? /* @__PURE__ */ jsx(GridView2, {
158
+ contentHeight: dimensions.rows,
159
+ contentWidth: dimensions.columns,
160
+ defaultViewport: { pixelsPerUnitX: cellSize, pixelsPerUnitY: cellSize },
161
+ height,
162
+ interactionPolicy: "passive",
163
+ items: cells,
164
+ overscanPixels: 0,
165
+ renderItem: (item) => {
166
+ const cell = cellById.get(item.id);
167
+ return cell === undefined ? null : renderChessBoardCell({
168
+ cell,
169
+ cellSize,
170
+ colors,
171
+ disabled: disabled || interactionPolicy === "passive",
172
+ lastMove,
173
+ legalTargetSet,
174
+ onPress: pressCell,
175
+ piece: piecesByCell.get(item.id),
176
+ renderPiece,
177
+ selectedCell,
178
+ showCoordinates,
179
+ testID
180
+ });
181
+ },
182
+ width
183
+ }) : null,
184
+ canResize ? renderChessBoardResizeActions(dimensions, onDimensionsChange, testID) : null
185
+ ]
186
+ });
187
+ }
188
+ function renderChessBoardCell({
189
+ cell,
190
+ cellSize,
191
+ colors,
192
+ disabled,
193
+ lastMove,
194
+ legalTargetSet,
195
+ onPress,
196
+ piece,
197
+ renderPiece,
198
+ selectedCell,
199
+ showCoordinates,
200
+ testID
201
+ }) {
202
+ const light = (cell.column + cell.row) % 2 === 1;
203
+ const key = getCellKey(cell);
204
+ const backgroundColor = cellsEqual2(selectedCell, cell) ? colors.selectedSquare : legalTargetSet.has(key) ? colors.legalTarget : cellsEqual2(lastMove?.from, cell) ? colors.lastMoveFrom : cellsEqual2(lastMove?.to, cell) ? colors.lastMoveTo : light ? colors.lightSquare : colors.darkSquare;
205
+ const pieceContent = piece === undefined ? null : renderPiece ? renderPiece({
206
+ cell,
207
+ color: piece.color === "white" ? colors.lightPiece : colors.darkPiece,
208
+ piece: piece.piece,
209
+ size: cellSize
210
+ }) : symbols.get(`${piece.color}:${piece.piece.toLowerCase()}`) ?? piece.piece;
211
+ const coordinate = formatCellCoordinate(cell);
212
+ return /* @__PURE__ */ jsxs(import_react_native.Pressable, {
213
+ accessibilityLabel: coordinate,
214
+ accessibilityRole: "button",
215
+ accessibilityState: { disabled },
216
+ disabled,
217
+ onPress: () => onPress(cell),
218
+ style: [styles.square, { backgroundColor }],
219
+ testID: testID === undefined ? undefined : `${testID}-cell-${coordinate}`,
220
+ children: [
221
+ showCoordinates ? /* @__PURE__ */ jsx(import_react_native.Text, {
222
+ style: [
223
+ styles.coordinate,
224
+ { color: light ? colors.lightSquareText : colors.darkSquareText }
225
+ ],
226
+ children: coordinate
227
+ }) : null,
228
+ piece === undefined ? null : /* @__PURE__ */ jsx(import_react_native.View, {
229
+ pointerEvents: "none",
230
+ style: styles.pieceContainer,
231
+ children: renderPiece ? pieceContent : /* @__PURE__ */ jsx(import_react_native.Text, {
232
+ style: [
233
+ styles.piece,
234
+ {
235
+ color: piece.color === "white" ? colors.lightPiece : colors.darkPiece,
236
+ fontSize: cellSize * 0.58,
237
+ lineHeight: cellSize * 0.7
238
+ }
239
+ ],
240
+ children: pieceContent
241
+ })
242
+ })
243
+ ]
244
+ }, key);
245
+ }
246
+ function renderChessBoardResizeActions(dimensions, onDimensionsChange, testID) {
247
+ return /* @__PURE__ */ jsxs(import_react_native.View, {
248
+ accessibilityLabel: "Chess board dimensions",
249
+ style: styles.resizeActions,
250
+ children: [
251
+ renderResizeAction("Add row", { ...dimensions, rows: dimensions.rows + 1 }, onDimensionsChange, dimensions.rows < maximumDimension2, testID),
252
+ renderResizeAction("Remove row", { ...dimensions, rows: dimensions.rows - 1 }, onDimensionsChange, dimensions.rows > minimumDimension2, testID),
253
+ renderResizeAction("Add column", { ...dimensions, columns: dimensions.columns + 1 }, onDimensionsChange, dimensions.columns < maximumDimension2, testID),
254
+ renderResizeAction("Remove column", { ...dimensions, columns: dimensions.columns - 1 }, onDimensionsChange, dimensions.columns > minimumDimension2, testID)
255
+ ]
256
+ });
257
+ }
258
+ function renderResizeAction(label, dimensions, onDimensionsChange, enabled, testID) {
259
+ return /* @__PURE__ */ jsx(import_react_native.Pressable, {
260
+ accessibilityLabel: label,
261
+ accessibilityRole: "button",
262
+ disabled: !enabled,
263
+ onPress: () => onDimensionsChange(dimensions),
264
+ testID: testID === undefined ? undefined : `${testID}-${label.toLowerCase().replace(" ", "-")}`,
265
+ children: /* @__PURE__ */ jsx(import_react_native.Text, {
266
+ children: label
267
+ })
268
+ });
269
+ }
270
+ function cellsEqual2(left, right) {
271
+ if (!left || !right)
272
+ return false;
273
+ return left.column === right.column && left.row === right.row;
274
+ }
275
+ function formatCellCoordinate(cell) {
276
+ return `${String.fromCharCode(96 + cell.column)}${cell.row}`;
277
+ }
278
+ function getCellKey(cell) {
279
+ return `${cell.column}:${cell.row}`;
280
+ }
281
+ var styles = import_react_native.StyleSheet.create({
282
+ board: {
283
+ borderRadius: 12,
284
+ borderWidth: import_react_native.StyleSheet.hairlineWidth,
285
+ overflow: "hidden",
286
+ width: "100%"
287
+ },
288
+ coordinate: {
289
+ fontSize: 9,
290
+ fontWeight: "600",
291
+ left: 3,
292
+ opacity: 0.72,
293
+ position: "absolute",
294
+ top: 2,
295
+ zIndex: 2
296
+ },
297
+ piece: { fontWeight: "600" },
298
+ pieceContainer: {
299
+ alignItems: "center",
300
+ bottom: 0,
301
+ justifyContent: "center",
302
+ left: 0,
303
+ position: "absolute",
304
+ right: 0,
305
+ top: 0
306
+ },
307
+ resizeActions: { flexDirection: "row", gap: 8, padding: 8 },
308
+ square: { alignItems: "center", justifyContent: "center", position: "relative" }
309
+ });
310
+
311
+ // src/features/chess/adapters/inbound/OpeningBook.tsx
312
+ var import_react_native2 = __toESM(require_cjs(), 1);
313
+
314
+ // src/features/chess/utils/createOpeningBookColorScheme.ts
315
+ function createOpeningBookColorScheme(theme, overrides) {
316
+ return {
317
+ border: theme.semantics.neutral.divider,
318
+ metricSurface: theme.semantics.neutral.surface,
319
+ primaryText: theme.semantics.content.default,
320
+ secondaryText: theme.semantics.content.muted,
321
+ selectedSurface: theme.semantics.action.primary.softBg,
322
+ surface: theme.semantics.neutral.surface,
323
+ surfaceHover: theme.semantics.neutral.surfaceHover,
324
+ titleText: theme.semantics.content.default,
325
+ ...overrides
326
+ };
327
+ }
328
+
329
+ // src/features/chess/adapters/inbound/OpeningBook.tsx
330
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
331
+ var OpeningBook2 = withZoraThemeScope(OpeningBookInner);
332
+ function rate(label, value) {
333
+ if (value === undefined || !Number.isFinite(value))
334
+ return;
335
+ return `${label} ${Math.round(value <= 1 ? value * 100 : value)}%`;
336
+ }
337
+ function moveKey(move) {
338
+ return move.uci ?? move.fen ?? move.san;
339
+ }
340
+ function OpeningBookInner({
341
+ moves = [],
342
+ title = "Opening book",
343
+ loading = false,
344
+ errorText,
345
+ emptyText = "No book moves for this position.",
346
+ selectedMove = null,
347
+ colorScheme,
348
+ onMovePress,
349
+ interactionPolicy,
350
+ testID
351
+ }) {
352
+ const { theme } = useZoraTheme2();
353
+ const colors = createOpeningBookColorScheme(theme, colorScheme);
354
+ const stateText = loading ? "Loading opening moves…" : errorText ?? emptyText;
355
+ const showState = loading || errorText !== undefined || moves.length === 0;
356
+ return /* @__PURE__ */ jsxs2(import_react_native2.View, {
357
+ accessibilityLabel: title,
358
+ style: [
359
+ styles2.root,
360
+ {
361
+ borderColor: colors.border,
362
+ backgroundColor: colors.surface
363
+ }
364
+ ],
365
+ testID,
366
+ children: [
367
+ /* @__PURE__ */ jsx2(import_react_native2.Text, {
368
+ style: [styles2.title, { color: colors.titleText }],
369
+ children: title
370
+ }),
371
+ !showState ? /* @__PURE__ */ jsx2(import_react_native2.View, {
372
+ style: styles2.moves,
373
+ children: moves.map((move) => {
374
+ const selected = selectedMove !== null && (selectedMove === move.san || selectedMove === move.uci || selectedMove === move.fen);
375
+ const details = [
376
+ move.eco,
377
+ move.name,
378
+ move.games === undefined ? undefined : `${move.games} games`
379
+ ].filter((part) => typeof part === "string" && part.length > 0);
380
+ const stats = [
381
+ rate("W", move.whiteWinRate),
382
+ rate("D", move.drawRate),
383
+ rate("B", move.blackWinRate)
384
+ ].filter((part) => part !== undefined);
385
+ return /* @__PURE__ */ jsxs2(import_react_native2.Pressable, {
386
+ accessibilityRole: "button",
387
+ disabled: onMovePress === undefined || interactionPolicy === "passive",
388
+ onPress: () => {
389
+ if (interactionPolicy === "passive")
390
+ return;
391
+ onMovePress?.(move);
392
+ },
393
+ style: [
394
+ styles2.move,
395
+ {
396
+ backgroundColor: selected ? colors.selectedSurface : colors.surfaceHover,
397
+ borderColor: colors.border
398
+ }
399
+ ],
400
+ testID: testID ? `${testID}-move-${move.san}` : undefined,
401
+ children: [
402
+ /* @__PURE__ */ jsxs2(import_react_native2.View, {
403
+ style: styles2.moveMain,
404
+ children: [
405
+ /* @__PURE__ */ jsx2(import_react_native2.Text, {
406
+ style: [styles2.san, { color: colors.primaryText }],
407
+ children: move.san
408
+ }),
409
+ /* @__PURE__ */ jsx2(import_react_native2.Text, {
410
+ style: [styles2.meta, { color: colors.secondaryText }],
411
+ children: details.length > 0 ? details.join(" · ") : "Book move"
412
+ })
413
+ ]
414
+ }),
415
+ stats.length > 0 ? /* @__PURE__ */ jsx2(import_react_native2.View, {
416
+ style: [styles2.metric, { backgroundColor: colors.metricSurface }],
417
+ children: /* @__PURE__ */ jsx2(import_react_native2.Text, {
418
+ style: [styles2.metricText, { color: colors.secondaryText }],
419
+ children: stats.join(" ")
420
+ })
421
+ }) : null
422
+ ]
423
+ }, moveKey(move));
424
+ })
425
+ }) : /* @__PURE__ */ jsx2(import_react_native2.Text, {
426
+ style: [styles2.stateText, { color: colors.secondaryText }],
427
+ children: stateText
428
+ })
429
+ ]
430
+ });
431
+ }
432
+ var styles2 = import_react_native2.StyleSheet.create({
433
+ root: { borderRadius: 12, borderWidth: import_react_native2.StyleSheet.hairlineWidth, gap: 10, padding: 12 },
434
+ title: { fontSize: 15, fontWeight: "700", lineHeight: 20 },
435
+ stateText: { fontSize: 13, lineHeight: 18 },
436
+ moves: { gap: 8 },
437
+ move: {
438
+ alignItems: "center",
439
+ borderRadius: 10,
440
+ borderWidth: import_react_native2.StyleSheet.hairlineWidth,
441
+ flexDirection: "row",
442
+ gap: 10,
443
+ justifyContent: "space-between",
444
+ paddingHorizontal: 10,
445
+ paddingVertical: 8
446
+ },
447
+ moveMain: { flex: 1, gap: 2 },
448
+ san: { fontSize: 16, fontWeight: "700", lineHeight: 20 },
449
+ meta: { fontSize: 12, lineHeight: 16 },
450
+ metric: { borderRadius: 999, paddingHorizontal: 8, paddingVertical: 4 },
451
+ metricText: { fontSize: 11, fontWeight: "600" }
452
+ });
453
+ export { ChessBoard2, OpeningBook2 };
@@ -1,10 +1,11 @@
1
1
  'use client';
2
+ import"../../chunks/Accordion-t0k1cjca.js";
2
3
  import"../../chunks/Accordion-6wrr910w.js";
3
4
  import"../../chunks/Accordion-vj1m2wck.js";
4
5
  import {
5
6
  ChessBoard2,
6
7
  OpeningBook2
7
- } from "../../chunks/Accordion-xcm1qc39.js";
8
+ } from "../../chunks/Accordion-91sjb3zh.js";
8
9
  import"../../chunks/Accordion-srjya6dz.js";
9
10
  import"../../chunks/Accordion-xgpzh4wq.js";
10
11
  export {