@dxos/react-ui-gameboard 0.8.4-main.5ea62a8 → 0.8.4-main.72ec0f3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-gameboard",
3
- "version": "0.8.4-main.5ea62a8",
3
+ "version": "0.8.4-main.72ec0f3",
4
4
  "description": "Game board.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -27,34 +27,34 @@
27
27
  "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
28
28
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
29
29
  "@preact-signals/safe-react": "^0.9.0",
30
- "@preact/signals-core": "^1.9.0",
30
+ "@preact/signals-core": "^1.12.1",
31
31
  "@radix-ui/react-context": "1.1.1",
32
32
  "chess.js": "^1.4.0",
33
33
  "react-resize-detector": "^11.0.1",
34
- "@dxos/debug": "0.8.4-main.5ea62a8",
35
- "@dxos/invariant": "0.8.4-main.5ea62a8",
36
- "@dxos/log": "0.8.4-main.5ea62a8",
37
- "@dxos/node-std": "0.8.4-main.5ea62a8",
38
- "@dxos/util": "0.8.4-main.5ea62a8"
34
+ "@dxos/debug": "0.8.4-main.72ec0f3",
35
+ "@dxos/invariant": "0.8.4-main.72ec0f3",
36
+ "@dxos/log": "0.8.4-main.72ec0f3",
37
+ "@dxos/node-std": "0.8.4-main.72ec0f3",
38
+ "@dxos/util": "0.8.4-main.72ec0f3"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@svgr/cli": "^8.1.0",
42
42
  "@types/lodash.defaultsdeep": "^4.6.6",
43
- "@types/react": "~18.2.0",
44
- "@types/react-dom": "~18.2.0",
43
+ "@types/react": "~19.2.2",
44
+ "@types/react-dom": "~19.2.2",
45
45
  "lodash.defaultsdeep": "^4.6.1",
46
- "react": "~18.2.0",
47
- "react-dom": "~18.2.0",
48
- "vite": "7.1.1",
49
- "@dxos/react-ui-theme": "0.8.4-main.5ea62a8",
50
- "@dxos/react-ui": "0.8.4-main.5ea62a8",
51
- "@dxos/storybook-utils": "0.8.4-main.5ea62a8"
46
+ "react": "~19.2.0",
47
+ "react-dom": "~19.2.0",
48
+ "vite": "7.1.9",
49
+ "@dxos/react-ui": "0.8.4-main.72ec0f3",
50
+ "@dxos/react-ui-theme": "0.8.4-main.72ec0f3",
51
+ "@dxos/storybook-utils": "0.8.4-main.72ec0f3"
52
52
  },
53
53
  "peerDependencies": {
54
- "react": "~18.2.0",
55
- "react-dom": "~18.2.0",
56
- "@dxos/react-ui": "0.8.4-main.5ea62a8",
57
- "@dxos/react-ui-theme": "0.8.4-main.5ea62a8"
54
+ "react": "^19.0.0",
55
+ "react-dom": "^19.0.0",
56
+ "@dxos/react-ui": "0.8.4-main.72ec0f3",
57
+ "@dxos/react-ui-theme": "0.8.4-main.72ec0f3"
58
58
  },
59
59
  "publishConfig": {
60
60
  "access": "public"
@@ -2,13 +2,11 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
9
7
 
10
8
  import { Button, Toolbar } from '@dxos/react-ui';
11
- import { withLayout, withTheme } from '@dxos/storybook-utils';
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
12
10
 
13
11
  import { Gameboard, type GameboardRootProps, type Move, type Player } from '../Gameboard';
14
12
 
@@ -64,7 +62,7 @@ const GridStory = () => {
64
62
  }, []);
65
63
 
66
64
  return (
67
- <div className='h-full aspect-square mx-auto'>
65
+ <div className='bs-full aspect-square mx-auto'>
68
66
  <div className='grid grid-cols-3 gap-2'>
69
67
  {models.map((model, i) => (
70
68
  <div key={i} className='aspect-square'>
@@ -82,7 +80,7 @@ const meta = {
82
80
  title: 'ui/react-ui-gameboard/Chessboard',
83
81
  component: Chessboard,
84
82
  render: DefaultStory,
85
- decorators: [withTheme, withLayout({ fullscreen: true, classNames: '' })],
83
+ decorators: [withTheme, withLayout({ container: 'column' })],
86
84
  } satisfies Meta<typeof Chessboard>;
87
85
 
88
86
  export default meta;
@@ -2,12 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { Fragment, type PropsWithChildren, memo, useEffect, useMemo, useRef, useState } from 'react';
5
+ import React, { type PropsWithChildren, forwardRef, memo, useEffect, useMemo, useRef, useState } from 'react';
6
6
  import { useResizeDetector } from 'react-resize-detector';
7
7
 
8
- import { type ThemedClassName, useTrackProps } from '@dxos/react-ui';
8
+ import { type ThemedClassName, useForwardedRef } from '@dxos/react-ui';
9
9
  import { mx } from '@dxos/react-ui-theme';
10
- import { isNotFalsy } from '@dxos/util';
10
+ import { isNonNullable } from '@dxos/util';
11
11
 
12
12
  import {
13
13
  type DOMRectBounds,
@@ -35,10 +35,10 @@ export type ChessboardProps = ThemedClassName<
35
35
  /**
36
36
  * Chessboard layout.
37
37
  */
38
- export const Chessboard = memo(
39
- ({ orientation, showLabels, debug, rows = 8, cols = 8, classNames }: ChessboardProps) => {
40
- useTrackProps({ orientation, showLabels, debug }, Chessboard.displayName, false);
41
- const { ref: containerRef, width, height } = useResizeDetector({ refreshRate: 200 });
38
+ const ChessboardComponent = forwardRef<HTMLDivElement, ChessboardProps>(
39
+ ({ classNames, orientation, showLabels, debug, rows = 8, cols = 8 }, forwardedRef) => {
40
+ const targetRef = useForwardedRef(forwardedRef);
41
+ const { width, height } = useResizeDetector({ targetRef, refreshRate: 200 });
42
42
  const { model, promoting, onPromotion } = useGameboardContext<ChessModel>(Chessboard.displayName!);
43
43
 
44
44
  // Board squares.
@@ -93,11 +93,11 @@ export const Chessboard = memo(
93
93
  const bounds = grid[locationToString(piece.location)];
94
94
  return { piece, bounds };
95
95
  })
96
- .filter(isNotFalsy);
96
+ .filter(isNonNullable);
97
97
  }, [grid, model?.pieces.value, promoting]);
98
98
 
99
99
  return (
100
- <div ref={containerRef} className={mx('relative', classNames)}>
100
+ <div ref={targetRef} tabIndex={0} className={mx('relative outline-none', classNames)}>
101
101
  {/* DOM Layout. */}
102
102
  <div ref={gridRef} className='grid grid-rows-8 grid-cols-8 aspect-square select-none'>
103
103
  {layout}
@@ -147,11 +147,9 @@ export const Chessboard = memo(
147
147
  },
148
148
  );
149
149
 
150
- Chessboard.displayName = 'Chessboard';
150
+ ChessboardComponent.displayName = 'Chessboard';
151
151
 
152
- const getSquareLocation = (container: HTMLElement, location: Location): HTMLElement | null => {
153
- return container.querySelector(`[data-location="${locationToString(location)}"]`);
154
- };
152
+ export const Chessboard = memo(ChessboardComponent);
155
153
 
156
154
  const PromotionSelector = ({
157
155
  grid,
@@ -184,13 +182,17 @@ const PromotionSelector = ({
184
182
  {positions.map(({ piece, bounds }) => (
185
183
  <Gameboard.Piece
186
184
  key={piece.id}
185
+ classNames={mx('border-2 border-neutral-700 rounded-full', boardStyles.promotion)}
187
186
  piece={piece}
188
187
  bounds={bounds}
189
188
  Component={ChessPieces[piece.type as ChessPiece]}
190
- classNames={mx('border-2 border-neutral-700 rounded-full', boardStyles.promotion)}
191
189
  onClick={() => handleSelect(piece)}
192
190
  />
193
191
  ))}
194
192
  </>
195
193
  );
196
194
  };
195
+
196
+ const getSquareLocation = (container: HTMLElement, location: Location): HTMLElement | null => {
197
+ return container.querySelector(`[data-location="${locationToString(location)}"]`);
198
+ };
@@ -34,6 +34,10 @@ export const locationToPos = ([row, col]: Location): string => {
34
34
  return String.fromCharCode(col + 'a'.charCodeAt(0)) + (row + 1);
35
35
  };
36
36
 
37
+ export const getRawPgn = (pgn: string) => {
38
+ return pgn.replace(/\[.*?\]/g, '').trim();
39
+ };
40
+
37
41
  const styles = {
38
42
  neutral: {
39
43
  black: 'bg-neutral-50',
@@ -108,6 +112,10 @@ export class ChessModel implements GameboardModel<ChessPiece> {
108
112
  return this._moveIndex;
109
113
  }
110
114
 
115
+ get fen() {
116
+ return this._chess.fen();
117
+ }
118
+
111
119
  /**
112
120
  * PGN with headers.
113
121
  *
@@ -121,7 +129,7 @@ export class ChessModel implements GameboardModel<ChessPiece> {
121
129
  */
122
130
  // TODO(burdon): Update headers.
123
131
  get pgn(): string {
124
- return this._chess.pgn();
132
+ return getRawPgn(this._chess.pgn());
125
133
  }
126
134
 
127
135
  setMoveIndex(index: number) {
@@ -10,7 +10,7 @@ import { createPortal } from 'react-dom';
10
10
 
11
11
  import { invariant } from '@dxos/invariant';
12
12
  import { log } from '@dxos/log';
13
- import { type ThemedClassName, useDynamicRef, useTrackProps } from '@dxos/react-ui';
13
+ import { type ThemedClassName, useDynamicRef } from '@dxos/react-ui';
14
14
  import { mx } from '@dxos/react-ui-theme';
15
15
 
16
16
  import { useGameboardContext } from './Gameboard';
@@ -26,8 +26,7 @@ export type PieceProps = ThemedClassName<{
26
26
  onClick?: () => void;
27
27
  }>;
28
28
 
29
- export const Piece = memo(({ classNames, Component, piece, orientation, bounds, label, onClick }: PieceProps) => {
30
- useTrackProps({ classNames, Component, piece, orientation, bounds, label }, Piece.displayName, false);
29
+ export const Piece = memo(({ classNames, Component, piece, bounds, label, onClick }: PieceProps) => {
31
30
  const { model, dragging: isDragging, promoting } = useGameboardContext(Piece.displayName!);
32
31
  const promotingRef = useDynamicRef(promoting);
33
32
  const [dragging, setDragging] = useState(false);