@dxos/plugin-chess 0.8.4-main.1068cf700f → 0.8.4-main.1c7ec43d41

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 (229) hide show
  1. package/dist/lib/browser/blueprints/index.mjs +9 -6
  2. package/dist/lib/browser/chunk-5FHUZILG.mjs +63 -0
  3. package/dist/lib/browser/chunk-5FHUZILG.mjs.map +7 -0
  4. package/dist/lib/browser/chunk-BCTL5GYK.mjs +88 -0
  5. package/dist/lib/browser/chunk-BCTL5GYK.mjs.map +7 -0
  6. package/dist/lib/browser/chunk-ORLWKOYE.mjs +26 -0
  7. package/dist/lib/browser/chunk-ORLWKOYE.mjs.map +7 -0
  8. package/dist/lib/browser/chunk-YER5TC5N.mjs +35 -0
  9. package/dist/lib/browser/chunk-YER5TC5N.mjs.map +7 -0
  10. package/dist/lib/browser/index.mjs +27 -85
  11. package/dist/lib/browser/index.mjs.map +4 -4
  12. package/dist/lib/browser/meta.json +1 -1
  13. package/dist/lib/browser/move-BH3WZUJH.mjs +39 -0
  14. package/dist/lib/browser/move-BH3WZUJH.mjs.map +7 -0
  15. package/dist/lib/browser/operations/index.mjs +17 -0
  16. package/dist/lib/browser/operations/index.mjs.map +7 -0
  17. package/dist/lib/browser/play-IM4BDFSY.mjs +48 -0
  18. package/dist/lib/browser/play-IM4BDFSY.mjs.map +7 -0
  19. package/dist/lib/browser/print-M3ZO2XZT.mjs +30 -0
  20. package/dist/lib/browser/print-M3ZO2XZT.mjs.map +7 -0
  21. package/dist/lib/browser/translations.mjs +34 -0
  22. package/dist/lib/browser/translations.mjs.map +7 -0
  23. package/dist/lib/browser/types/index.mjs +1 -1
  24. package/dist/lib/node-esm/blueprints/index.mjs +9 -6
  25. package/dist/lib/node-esm/chunk-A3P4HC7O.mjs +89 -0
  26. package/dist/lib/node-esm/chunk-A3P4HC7O.mjs.map +7 -0
  27. package/dist/lib/node-esm/chunk-B42KRPBJ.mjs +37 -0
  28. package/dist/lib/node-esm/chunk-B42KRPBJ.mjs.map +7 -0
  29. package/dist/lib/node-esm/chunk-WSHXDK3W.mjs +27 -0
  30. package/dist/lib/node-esm/chunk-WSHXDK3W.mjs.map +7 -0
  31. package/dist/lib/node-esm/chunk-YRW4LYGF.mjs +64 -0
  32. package/dist/lib/node-esm/chunk-YRW4LYGF.mjs.map +7 -0
  33. package/dist/lib/node-esm/index.mjs +27 -85
  34. package/dist/lib/node-esm/index.mjs.map +4 -4
  35. package/dist/lib/node-esm/meta.json +1 -1
  36. package/dist/lib/node-esm/move-53HLCSAL.mjs +40 -0
  37. package/dist/lib/node-esm/move-53HLCSAL.mjs.map +7 -0
  38. package/dist/lib/node-esm/operations/index.mjs +18 -0
  39. package/dist/lib/node-esm/operations/index.mjs.map +7 -0
  40. package/dist/lib/node-esm/play-YXXPG5SO.mjs +49 -0
  41. package/dist/lib/node-esm/play-YXXPG5SO.mjs.map +7 -0
  42. package/dist/lib/node-esm/print-L2LUM3IW.mjs +31 -0
  43. package/dist/lib/node-esm/print-L2LUM3IW.mjs.map +7 -0
  44. package/dist/lib/node-esm/translations.mjs +35 -0
  45. package/dist/lib/node-esm/translations.mjs.map +7 -0
  46. package/dist/lib/node-esm/types/index.mjs +1 -1
  47. package/dist/types/src/ChessPlugin.d.ts +1 -0
  48. package/dist/types/src/ChessPlugin.d.ts.map +1 -1
  49. package/dist/types/src/ChessPlugin.node.d.ts +8 -0
  50. package/dist/types/src/ChessPlugin.node.d.ts.map +1 -0
  51. package/dist/types/src/ChessPlugin.test.d.ts +2 -0
  52. package/dist/types/src/ChessPlugin.test.d.ts.map +1 -0
  53. package/dist/types/src/blueprints/chess-blueprint.d.ts +3 -20
  54. package/dist/types/src/blueprints/chess-blueprint.d.ts.map +1 -1
  55. package/dist/types/src/blueprints/index.d.ts +2 -2
  56. package/dist/types/src/blueprints/index.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/blueprint-definition.d.ts +6 -0
  58. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  59. package/dist/types/src/capabilities/game-variant.d.ts +6 -0
  60. package/dist/types/src/capabilities/game-variant.d.ts.map +1 -0
  61. package/dist/types/src/capabilities/index.d.ts +5 -2
  62. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  63. package/dist/types/src/capabilities/node.d.ts +10 -0
  64. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  65. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  66. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  67. package/dist/types/src/components/{Chessboard.d.ts → Chessboard/Chessboard.d.ts} +10 -11
  68. package/dist/types/src/components/Chessboard/Chessboard.d.ts.map +1 -0
  69. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts +57 -0
  70. package/dist/types/src/components/Chessboard/Chessboard.stories.d.ts.map +1 -0
  71. package/dist/types/src/components/{Info.d.ts → Chessboard/Info.d.ts} +5 -6
  72. package/dist/types/src/components/Chessboard/Info.d.ts.map +1 -0
  73. package/dist/types/src/components/Chessboard/index.d.ts +2 -0
  74. package/dist/types/src/components/Chessboard/index.d.ts.map +1 -0
  75. package/dist/types/src/components/Chessboard/types.d.ts +8 -0
  76. package/dist/types/src/components/Chessboard/types.d.ts.map +1 -0
  77. package/dist/types/src/components/index.d.ts +0 -1
  78. package/dist/types/src/components/index.d.ts.map +1 -1
  79. package/dist/types/src/containers/ChessArticle/ChessArticle.d.ts +5 -0
  80. package/dist/types/src/containers/ChessArticle/ChessArticle.d.ts.map +1 -0
  81. package/dist/types/src/containers/ChessArticle/ChessArticle.stories.d.ts +56 -0
  82. package/dist/types/src/containers/ChessArticle/ChessArticle.stories.d.ts.map +1 -0
  83. package/dist/types/src/containers/ChessArticle/index.d.ts +2 -0
  84. package/dist/types/src/containers/ChessArticle/index.d.ts.map +1 -0
  85. package/dist/types/src/containers/ChessCard/ChessCard.d.ts +5 -0
  86. package/dist/types/src/containers/ChessCard/ChessCard.d.ts.map +1 -0
  87. package/dist/types/src/{components/Card.stories.d.ts → containers/ChessCard/ChessCard.stories.d.ts} +1 -1
  88. package/dist/types/src/containers/ChessCard/ChessCard.stories.d.ts.map +1 -0
  89. package/dist/types/src/containers/ChessCard/index.d.ts +2 -0
  90. package/dist/types/src/containers/ChessCard/index.d.ts.map +1 -0
  91. package/dist/types/src/containers/index.d.ts +4 -0
  92. package/dist/types/src/containers/index.d.ts.map +1 -0
  93. package/dist/types/src/index.d.ts +2 -3
  94. package/dist/types/src/index.d.ts.map +1 -1
  95. package/dist/types/src/operations/definitions.d.ts +24 -0
  96. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  97. package/dist/types/src/operations/index.d.ts +4 -0
  98. package/dist/types/src/operations/index.d.ts.map +1 -0
  99. package/dist/types/src/operations/move.d.ts +5 -0
  100. package/dist/types/src/operations/move.d.ts.map +1 -0
  101. package/dist/types/src/operations/play.d.ts +5 -0
  102. package/dist/types/src/operations/play.d.ts.map +1 -0
  103. package/dist/types/src/operations/print.d.ts +5 -0
  104. package/dist/types/src/operations/print.d.ts.map +1 -0
  105. package/dist/types/src/translations.d.ts +32 -23
  106. package/dist/types/src/translations.d.ts.map +1 -1
  107. package/dist/types/src/types/Chess.d.ts +10 -19
  108. package/dist/types/src/types/Chess.d.ts.map +1 -1
  109. package/dist/types/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +66 -48
  111. package/src/ChessPlugin.node.ts +23 -0
  112. package/src/ChessPlugin.test.ts +49 -0
  113. package/src/ChessPlugin.tsx +14 -23
  114. package/src/blueprints/chess-blueprint.ts +14 -9
  115. package/src/blueprints/index.ts +2 -2
  116. package/src/capabilities/blueprint-definition.ts +19 -0
  117. package/src/capabilities/game-variant.ts +42 -0
  118. package/src/capabilities/index.ts +10 -2
  119. package/src/capabilities/node.ts +18 -0
  120. package/src/capabilities/operation-handler.ts +14 -0
  121. package/src/components/Chessboard/Chessboard.stories.tsx +94 -0
  122. package/src/components/{Chessboard.tsx → Chessboard/Chessboard.tsx} +21 -31
  123. package/src/components/{Info.tsx → Chessboard/Info.tsx} +24 -77
  124. package/src/components/Chessboard/index.ts +5 -0
  125. package/src/components/Chessboard/types.ts +18 -0
  126. package/src/components/index.ts +1 -5
  127. package/src/{components/Chessboard.stories.tsx → containers/ChessArticle/ChessArticle.stories.tsx} +16 -10
  128. package/src/containers/ChessArticle/ChessArticle.tsx +108 -0
  129. package/src/containers/ChessArticle/index.ts +5 -0
  130. package/src/containers/ChessCard/ChessCard.stories.tsx +47 -0
  131. package/src/containers/ChessCard/ChessCard.tsx +27 -0
  132. package/src/containers/ChessCard/index.ts +5 -0
  133. package/src/containers/index.ts +8 -0
  134. package/src/index.ts +5 -3
  135. package/src/meta.ts +1 -1
  136. package/src/operations/definitions.ts +83 -0
  137. package/src/operations/index.ts +15 -0
  138. package/src/operations/move.ts +37 -0
  139. package/src/operations/play.ts +46 -0
  140. package/src/operations/print.ts +28 -0
  141. package/src/translations.ts +18 -21
  142. package/src/types/Chess.ts +25 -24
  143. package/dist/lib/browser/ChessboardContainer-GNSIZKY7.mjs +0 -80
  144. package/dist/lib/browser/ChessboardContainer-GNSIZKY7.mjs.map +0 -7
  145. package/dist/lib/browser/blueprint-definition-YUKJZPOL.mjs +0 -19
  146. package/dist/lib/browser/blueprint-definition-YUKJZPOL.mjs.map +0 -7
  147. package/dist/lib/browser/chunk-66H3V2YV.mjs +0 -64
  148. package/dist/lib/browser/chunk-66H3V2YV.mjs.map +0 -7
  149. package/dist/lib/browser/chunk-H3NUMCQ6.mjs +0 -21
  150. package/dist/lib/browser/chunk-H3NUMCQ6.mjs.map +0 -7
  151. package/dist/lib/browser/chunk-MABHE5SS.mjs +0 -277
  152. package/dist/lib/browser/chunk-MABHE5SS.mjs.map +0 -7
  153. package/dist/lib/browser/chunk-PBRN5Q4R.mjs +0 -227
  154. package/dist/lib/browser/chunk-PBRN5Q4R.mjs.map +0 -7
  155. package/dist/lib/browser/chunk-QGVMZ4PK.mjs +0 -8
  156. package/dist/lib/browser/chunk-QGVMZ4PK.mjs.map +0 -7
  157. package/dist/lib/browser/cli/index.mjs +0 -29
  158. package/dist/lib/browser/cli/index.mjs.map +0 -7
  159. package/dist/lib/browser/react-surface-C52R6BRL.mjs +0 -38
  160. package/dist/lib/browser/react-surface-C52R6BRL.mjs.map +0 -7
  161. package/dist/lib/node-esm/ChessboardContainer-5OVYZMIW.mjs +0 -81
  162. package/dist/lib/node-esm/ChessboardContainer-5OVYZMIW.mjs.map +0 -7
  163. package/dist/lib/node-esm/blueprint-definition-4HZ2HWWC.mjs +0 -20
  164. package/dist/lib/node-esm/blueprint-definition-4HZ2HWWC.mjs.map +0 -7
  165. package/dist/lib/node-esm/chunk-3MAU6WHB.mjs +0 -228
  166. package/dist/lib/node-esm/chunk-3MAU6WHB.mjs.map +0 -7
  167. package/dist/lib/node-esm/chunk-F5OMIM4F.mjs +0 -23
  168. package/dist/lib/node-esm/chunk-F5OMIM4F.mjs.map +0 -7
  169. package/dist/lib/node-esm/chunk-IFK6UAKF.mjs +0 -10
  170. package/dist/lib/node-esm/chunk-IFK6UAKF.mjs.map +0 -7
  171. package/dist/lib/node-esm/chunk-OUNGNJFP.mjs +0 -65
  172. package/dist/lib/node-esm/chunk-OUNGNJFP.mjs.map +0 -7
  173. package/dist/lib/node-esm/chunk-V6MKXXPO.mjs +0 -278
  174. package/dist/lib/node-esm/chunk-V6MKXXPO.mjs.map +0 -7
  175. package/dist/lib/node-esm/cli/index.mjs +0 -30
  176. package/dist/lib/node-esm/cli/index.mjs.map +0 -7
  177. package/dist/lib/node-esm/react-surface-NW33JZ6J.mjs +0 -39
  178. package/dist/lib/node-esm/react-surface-NW33JZ6J.mjs.map +0 -7
  179. package/dist/types/src/blueprints/functions/create.d.ts +0 -15
  180. package/dist/types/src/blueprints/functions/create.d.ts.map +0 -1
  181. package/dist/types/src/blueprints/functions/index.d.ts +0 -5
  182. package/dist/types/src/blueprints/functions/index.d.ts.map +0 -1
  183. package/dist/types/src/blueprints/functions/move.d.ts +0 -16
  184. package/dist/types/src/blueprints/functions/move.d.ts.map +0 -1
  185. package/dist/types/src/blueprints/functions/play.d.ts +0 -17
  186. package/dist/types/src/blueprints/functions/play.d.ts.map +0 -1
  187. package/dist/types/src/blueprints/functions/print.d.ts +0 -8
  188. package/dist/types/src/blueprints/functions/print.d.ts.map +0 -1
  189. package/dist/types/src/capabilities/artifact-definition/artifact-definition.d.ts +0 -12
  190. package/dist/types/src/capabilities/artifact-definition/artifact-definition.d.ts.map +0 -1
  191. package/dist/types/src/capabilities/artifact-definition/index.d.ts +0 -3
  192. package/dist/types/src/capabilities/artifact-definition/index.d.ts.map +0 -1
  193. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts +0 -10
  194. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts.map +0 -1
  195. package/dist/types/src/capabilities/blueprint-definition/index.d.ts +0 -3
  196. package/dist/types/src/capabilities/blueprint-definition/index.d.ts.map +0 -1
  197. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  198. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  199. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  200. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  201. package/dist/types/src/cli/index.d.ts +0 -2
  202. package/dist/types/src/cli/index.d.ts.map +0 -1
  203. package/dist/types/src/cli/plugin.d.ts +0 -3
  204. package/dist/types/src/cli/plugin.d.ts.map +0 -1
  205. package/dist/types/src/components/Card.stories.d.ts.map +0 -1
  206. package/dist/types/src/components/Chessboard.d.ts.map +0 -1
  207. package/dist/types/src/components/Chessboard.stories.d.ts +0 -46
  208. package/dist/types/src/components/Chessboard.stories.d.ts.map +0 -1
  209. package/dist/types/src/components/ChessboardArticle.d.ts +0 -6
  210. package/dist/types/src/components/ChessboardArticle.d.ts.map +0 -1
  211. package/dist/types/src/components/ChessboardContainer.d.ts +0 -7
  212. package/dist/types/src/components/ChessboardContainer.d.ts.map +0 -1
  213. package/dist/types/src/components/Info.d.ts.map +0 -1
  214. package/src/blueprints/functions/create.ts +0 -38
  215. package/src/blueprints/functions/index.ts +0 -8
  216. package/src/blueprints/functions/move.ts +0 -48
  217. package/src/blueprints/functions/play.ts +0 -58
  218. package/src/blueprints/functions/print.ts +0 -42
  219. package/src/capabilities/artifact-definition/artifact-definition.ts +0 -135
  220. package/src/capabilities/artifact-definition/index.ts +0 -7
  221. package/src/capabilities/blueprint-definition/blueprint-definition.ts +0 -24
  222. package/src/capabilities/blueprint-definition/index.ts +0 -7
  223. package/src/capabilities/react-surface/index.ts +0 -7
  224. package/src/capabilities/react-surface/react-surface.tsx +0 -28
  225. package/src/cli/index.ts +0 -5
  226. package/src/cli/plugin.ts +0 -27
  227. package/src/components/Card.stories.tsx +0 -47
  228. package/src/components/ChessboardArticle.tsx +0 -70
  229. package/src/components/ChessboardContainer.tsx +0 -40
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { type Registry, RegistryContext } from '@effect-atom/atom-react';
5
+ import { RegistryContext } from '@effect-atom/atom-react';
6
6
  import React, {
7
7
  type PropsWithChildren,
8
8
  forwardRef,
@@ -15,10 +15,10 @@ import React, {
15
15
  } from 'react';
16
16
 
17
17
  import { addEventListener } from '@dxos/async';
18
- import { Obj } from '@dxos/echo';
18
+ import { useObject } from '@dxos/echo-react';
19
19
  import { type ThemedClassName } from '@dxos/react-ui';
20
20
  import {
21
- ChessModel,
21
+ type ChessModel,
22
22
  Gameboard,
23
23
  type GameboardRootProps,
24
24
  Chessboard as NaturalChessboard,
@@ -27,37 +27,29 @@ import {
27
27
  useGameboardContext,
28
28
  } from '@dxos/react-ui-gameboard';
29
29
  import { useSoundEffect } from '@dxos/react-ui-sfx';
30
- import { mx } from '@dxos/ui-theme';
31
30
 
32
- import { type Chess } from '../types';
31
+ import { type Chess } from '#types';
33
32
 
34
33
  import { Info, type InfoProps } from './Info';
34
+ import { ExtendedChessModel } from './types';
35
35
 
36
36
  export interface ChessboardController {
37
37
  setMoveNumber(index: number): void;
38
38
  }
39
39
 
40
- export class ExtendedChessModel extends ChessModel {
41
- constructor(
42
- registry: Registry.Registry,
43
- readonly object: Chess.Game,
44
- ) {
45
- super(registry);
46
- }
47
- }
48
-
49
40
  //
50
41
  // Root
51
42
  //
52
43
 
53
44
  type RootProps = PropsWithChildren<{
54
- game: Chess.Game;
45
+ state: Chess.State;
55
46
  }>;
56
47
 
57
- const Root = forwardRef<ChessboardController, RootProps>(({ game, children }, forwardedRef) => {
48
+ const Root = forwardRef<ChessboardController, RootProps>(({ state, children }, forwardedRef) => {
58
49
  const registry = useContext(RegistryContext);
59
- const model = useMemo(() => new ExtendedChessModel(registry, game), [registry]);
50
+ const model = useMemo(() => new ExtendedChessModel(registry, state), [registry]);
60
51
  const click = useSoundEffect('Click');
52
+ const [pgn, updatePgn] = useObject(state, 'pgn');
61
53
 
62
54
  // Controller.
63
55
  useImperativeHandle(forwardedRef, () => {
@@ -66,17 +58,21 @@ const Root = forwardRef<ChessboardController, RootProps>(({ game, children }, fo
66
58
  };
67
59
  }, [model]);
68
60
 
61
+ // TODO(wittjosiah): Rather than useEffect to sync ECHO object to model, create an alternative model implementation.
62
+ // This model would take the ECHO object and derive game state directly from that.
63
+ // Mutation methods would mutate the ECHO object and other state would be derived from that.
64
+
69
65
  // External change.
70
66
  // NOTE: Warning if user has not interacted with the board.
71
67
  useEffect(() => {
72
- if (model.pgn !== getRawPgn(game.pgn ?? '')) {
68
+ if (model.pgn !== getRawPgn(pgn ?? '')) {
73
69
  const silent = model.pgn === '*';
74
- model.update(game.pgn);
70
+ model.update(pgn);
75
71
  if (!silent) {
76
72
  void click.play();
77
73
  }
78
74
  }
79
- }, [game.pgn]);
75
+ }, [pgn]);
80
76
 
81
77
  // Move.
82
78
  const handleDrop = useCallback<NonNullable<GameboardRootProps<ChessModel>['onDrop']>>(
@@ -86,9 +82,7 @@ const Root = forwardRef<ChessboardController, RootProps>(({ game, children }, fo
86
82
  }
87
83
 
88
84
  void click.play();
89
- Obj.change(game, (g) => {
90
- g.pgn = model.pgn;
91
- });
85
+ updatePgn(() => model.pgn);
92
86
  return true;
93
87
  },
94
88
  [model],
@@ -105,17 +99,13 @@ const Root = forwardRef<ChessboardController, RootProps>(({ game, children }, fo
105
99
  // Content
106
100
  //
107
101
 
108
- type Role = 'card--popover' | 'card--intrinsic' | 'card--extrinsic';
102
+ type Role = 'card--content';
109
103
 
110
104
  type ContentProps = ThemedClassName<PropsWithChildren<{ role?: Role }>>;
111
105
 
112
- const Content = ({ classNames, children, role }: ContentProps) => {
106
+ const Content = ({ classNames, children }: ContentProps) => {
113
107
  return (
114
- <Gameboard.Content
115
- classNames={mx(classNames, role === 'card--popover' && 'size-container card-square')}
116
- grow={!role || role === 'card--extrinsic'}
117
- contain={!role || role === 'card--extrinsic' || role === 'card--popover'}
118
- >
108
+ <Gameboard.Content grow contain classNames={classNames}>
119
109
  {children}
120
110
  </Gameboard.Content>
121
111
  );
@@ -166,7 +156,7 @@ const Board = (props: BoardProps) => {
166
156
  });
167
157
  }, [registry, model]);
168
158
 
169
- return <NaturalChessboard ref={ref} {...props} />;
159
+ return <NaturalChessboard {...props} ref={ref} />;
170
160
  };
171
161
 
172
162
  Board.displayName = BOARD_NAME;
@@ -5,16 +5,13 @@
5
5
  import { useAtomValue } from '@effect-atom/atom-react';
6
6
  import React, { type JSX, type PropsWithChildren, useEffect, useMemo, useRef } from 'react';
7
7
 
8
- import { generateName } from '@dxos/display-name';
9
- import { Obj } from '@dxos/echo';
10
- import { type SpaceMember, useMembers } from '@dxos/react-client/echo';
11
- import { Icon, IconButton, Select, type ThemedClassName, useTranslation } from '@dxos/react-ui';
8
+ import { Icon, IconButton, type ThemedClassName, useTranslation } from '@dxos/react-ui';
12
9
  import { type Player, useGameboardContext } from '@dxos/react-ui-gameboard';
13
10
  import { mx } from '@dxos/ui-theme';
14
11
 
15
- import { meta } from '../meta';
12
+ import { meta } from '#meta';
16
13
 
17
- import { type ExtendedChessModel } from './Chessboard';
14
+ import { type ExtendedChessModel } from './types';
18
15
 
19
16
  const INFO_NAME = 'Chessboard.Info';
20
17
 
@@ -29,13 +26,11 @@ export type InfoProps = ThemedClassName<
29
26
  export const Info = ({ classNames, orientation = 'white', onOrientationChange, onClose, ...props }: InfoProps) => {
30
27
  const { t } = useTranslation(meta.id);
31
28
  const { model } = useGameboardContext<ExtendedChessModel>(INFO_NAME);
32
- const db = Obj.getDatabase(model.object);
33
- const members = useMembers(db?.spaceId);
34
29
 
35
30
  return (
36
31
  <div
37
32
  className={mx(
38
- 'grid grid-rows-[min-content_1fr_min-content] is-full min-is-[18rem] p-2 overflow-hidden bg-groupSurface rounded-sm',
33
+ 'grid grid-rows-[min-content_1fr_min-content] w-full min-w-[18rem] p-2 overflow-hidden bg-group-surface rounded-xs',
39
34
  classNames,
40
35
  )}
41
36
  >
@@ -44,20 +39,17 @@ export const Info = ({ classNames, orientation = 'white', onOrientationChange, o
44
39
  player={orientation === 'white' ? 'black' : 'white'}
45
40
  icon={
46
41
  onClose && (
47
- <IconButton icon='ph--x--regular' iconOnly label={t('close info button')} size={4} onClick={onClose} />
42
+ <IconButton
43
+ variant='ghost'
44
+ icon='ph--x--regular'
45
+ iconOnly
46
+ label={t('close-info.button')}
47
+ size={4}
48
+ onClick={onClose}
49
+ />
48
50
  )
49
51
  }
50
- >
51
- <PlayerSelector
52
- value={model.object.players?.[orientation === 'white' ? 'black' : 'white']}
53
- onValueChange={(value) => {
54
- Obj.change(model.object, (obj) => {
55
- obj.players![orientation === 'white' ? 'black' : 'white'] = value;
56
- });
57
- }}
58
- members={members}
59
- />
60
- </PlayerIndicator>
52
+ />
61
53
 
62
54
  <History model={model} {...props} />
63
55
 
@@ -70,23 +62,13 @@ export const Info = ({ classNames, orientation = 'white', onOrientationChange, o
70
62
  classNames={mx('transition duration-200 ease-linear', orientation === 'white' && 'rotate-180')}
71
63
  icon='ph--arrows-clockwise--regular'
72
64
  iconOnly
73
- label={t('flip board button')}
65
+ label={t('flip-board.button')}
74
66
  size={4}
75
67
  onClick={() => onOrientationChange(orientation === 'white' ? 'black' : 'white')}
76
68
  />
77
69
  )
78
70
  }
79
- >
80
- <PlayerSelector
81
- value={model.object.players?.[orientation]}
82
- onValueChange={(value) => {
83
- Obj.change(model.object, (obj) => {
84
- obj.players![orientation] = value;
85
- });
86
- }}
87
- members={members}
88
- />
89
- </PlayerIndicator>
71
+ />
90
72
  </div>
91
73
  );
92
74
  };
@@ -109,12 +91,12 @@ const History = ({ classNames, model, min, max, onSelect }: HistoryProps) => {
109
91
  const moveIndex = useAtomValue(model.moveIndex);
110
92
  const label = model.game.isGameOver()
111
93
  ? model.game.isCheckmate()
112
- ? t('game.checkmate label')
94
+ ? t('game.checkmate.label')
113
95
  : model.game.isStalemate()
114
- ? t('game.stalemate label')
115
- : t('game.draw label')
96
+ ? t('game.stalemate.label')
97
+ : t('game.draw.label')
116
98
  : model.game.isCheck()
117
- ? t('game.check label')
99
+ ? t('game.check.label')
118
100
  : undefined;
119
101
 
120
102
  const history = model.game.history();
@@ -156,12 +138,12 @@ const History = ({ classNames, model, min, max, onSelect }: HistoryProps) => {
156
138
  }}
157
139
  >
158
140
  {moves.map(([a, b], index) => (
159
- <div key={index} className='grid grid-cols-[3rem_1fr_1fr_1rem] gap-2 pis-4 leading-1'>
141
+ <div key={index} className='grid grid-cols-[3rem_1fr_1fr_1rem] gap-2 ps-4'>
160
142
  <div className='content-center text-xs text-subdued'>{index + 1}</div>
161
143
  {a && (
162
144
  <div
163
145
  data-index={a.index}
164
- className={mx('pis-2 cursor-pointer', a.index === moveIndex - 1 && 'bg-primary-500')}
146
+ className={mx('ps-2 text-sm cursor-pointer', a.index === moveIndex - 1 && 'bg-primary-500')}
165
147
  onClick={() => onSelect?.(a.index + 1)}
166
148
  >
167
149
  {a.move}
@@ -170,7 +152,7 @@ const History = ({ classNames, model, min, max, onSelect }: HistoryProps) => {
170
152
  {b && (
171
153
  <div
172
154
  data-index={b.index}
173
- className={mx('pis-2 cursor-pointer', b.index === moveIndex - 1 && 'bg-primary-500')}
155
+ className={mx('ps-2 text-sm cursor-pointer', b.index === moveIndex - 1 && 'bg-primary-500')}
174
156
  onClick={() => onSelect?.(b.index + 1)}
175
157
  >
176
158
  {b.move}
@@ -196,12 +178,12 @@ type PlayerIndicatorProps = PropsWithChildren<{
196
178
  const PlayerIndicator = ({ children, model, player, icon }: PlayerIndicatorProps) => {
197
179
  const turn = player === (model.game.turn() === 'w' ? 'white' : 'black');
198
180
  return (
199
- <div className='grid grid-cols-[2rem_1fr_2rem] gap-2 bs-[--rail-size] pli-1 flex items-center overflow-hidden'>
181
+ <div className='grid grid-cols-[2rem_1fr_2rem] gap-2 h-(--dx-rail-size) px-1 flex items-center overflow-hidden'>
200
182
  <div className='place-items-center'>
201
183
  <Icon
202
184
  icon={turn ? 'ph--circle--fill' : 'ph--circle--thin'}
203
185
  size={6}
204
- classNames={mx(turn && (model.game.isCheckmate() ? 'text-red-500' : 'text-green-500'))}
186
+ classNames={mx(turn && (model.game.isCheckmate() ? 'text-error-500' : 'text-success-text'))}
205
187
  />
206
188
  </div>
207
189
  <div className='truncate overflow-hidden items-center'>{children}</div>
@@ -209,38 +191,3 @@ const PlayerIndicator = ({ children, model, player, icon }: PlayerIndicatorProps
209
191
  </div>
210
192
  );
211
193
  };
212
-
213
- //
214
- // PlayerSelector
215
- //
216
-
217
- type PlayerSelectorProps = {
218
- value?: string;
219
- onValueChange: (player: string) => void;
220
- members: SpaceMember[];
221
- };
222
-
223
- const PlayerSelector = ({ value, onValueChange, members }: PlayerSelectorProps) => {
224
- const { t } = useTranslation(meta.id);
225
- return (
226
- <Select.Root value={value} onValueChange={onValueChange}>
227
- <Select.TriggerButton placeholder={t('select player button')} />
228
- <Select.Portal>
229
- <Select.Content>
230
- <Select.Viewport>
231
- {members.map((member) => {
232
- const memberKey = member.identity.identityKey.toHex();
233
- const displayName = member.identity?.profile?.displayName || generateName(memberKey);
234
- return (
235
- <Select.Option key={memberKey} value={memberKey}>
236
- {displayName}
237
- </Select.Option>
238
- );
239
- })}
240
- </Select.Viewport>
241
- <Select.Arrow />
242
- </Select.Content>
243
- </Select.Portal>
244
- </Select.Root>
245
- );
246
- };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './Chessboard';
@@ -0,0 +1,18 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Registry } from '@effect-atom/atom-react';
6
+
7
+ import { ChessModel } from '@dxos/react-ui-gameboard';
8
+
9
+ import { type Chess } from '#types';
10
+
11
+ export class ExtendedChessModel extends ChessModel {
12
+ constructor(
13
+ registry: Registry.Registry,
14
+ readonly object: Chess.State,
15
+ ) {
16
+ super(registry);
17
+ }
18
+ }
@@ -1,9 +1,5 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2026 DXOS.org
3
3
  //
4
4
 
5
- import { lazy } from 'react';
6
-
7
5
  export * from './Chessboard';
8
-
9
- export const ChessboardContainer = lazy(() => import('./ChessboardContainer'));
@@ -5,27 +5,33 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
+ import { type Obj } from '@dxos/echo';
9
+ import { make as makeGame } from '@dxos/plugin-game/types';
8
10
  import { withClientProvider } from '@dxos/react-client/testing';
9
- import { withTheme } from '@dxos/react-ui/testing';
11
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
12
 
11
- import { translations } from '../translations';
12
- import { Chess } from '../types';
13
+ import { translations } from '#translations';
14
+ import { Chess } from '#types';
13
15
 
14
- import { ChessboardArticle } from './ChessboardArticle';
16
+ import { ChessArticle } from './ChessArticle';
15
17
 
16
- type StoryProps = {
18
+ type DefaultStoryProps = {
17
19
  pgn?: string;
18
20
  };
19
21
 
20
- const DefaultStory = ({ pgn }: StoryProps) => {
21
- const game = useMemo(() => Chess.make(pgn ? { pgn } : undefined), [pgn]);
22
- return <ChessboardArticle subject={game} />;
22
+ const DefaultStory = ({ pgn }: DefaultStoryProps) => {
23
+ const { game, state } = useMemo(() => {
24
+ const state = Chess.make(pgn ? { pgn } : undefined);
25
+ const game = makeGame({ name: 'Story game', variant: state as Obj.Unknown });
26
+ return { game, state };
27
+ }, [pgn]);
28
+ return <ChessArticle role='article' attendableId='story' game={game} variant={state} />;
23
29
  };
24
30
 
25
31
  const meta = {
26
- title: 'plugins/plugin-chess/Chessboard',
32
+ title: 'plugins/plugin-chess/containers/ChessArticle',
27
33
  component: DefaultStory,
28
- decorators: [withTheme(), withClientProvider({ createIdentity: true })],
34
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withClientProvider({ createIdentity: true })],
29
35
  parameters: {
30
36
  layout: 'fullscreen',
31
37
  translations,
@@ -0,0 +1,108 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { Chess as ChessJS } from 'chess.js';
6
+ import React, { useCallback, useRef, useState } from 'react';
7
+
8
+ import { Obj } from '@dxos/echo';
9
+ import { type GameVariantSurfaceProps } from '@dxos/plugin-game/types';
10
+ import { Panel, Toolbar, useTranslation } from '@dxos/react-ui';
11
+ import { type Player } from '@dxos/react-ui-gameboard';
12
+ import { mx } from '@dxos/ui-theme';
13
+
14
+ import { Chessboard, type ChessboardController, type ChessboardInfoProps } from '#components';
15
+ import { meta } from '#meta';
16
+ import { Chess } from '#types';
17
+
18
+ export type ChessArticleProps = GameVariantSurfaceProps;
19
+
20
+ export const ChessArticle = ({ role, variant }: ChessArticleProps) => {
21
+ const { t } = useTranslation(meta.id);
22
+ const [orientation, setOrientation] = useState<Player>('white');
23
+ const [showInfo, setShowInfo] = useState(true);
24
+ const controller = useRef<ChessboardController>(null);
25
+
26
+ const handleSelect = useCallback<NonNullable<ChessboardInfoProps['onSelect']>>((index) => {
27
+ controller.current?.setMoveNumber(index);
28
+ }, []);
29
+
30
+ const isGameOver = (() => {
31
+ if (!Obj.instanceOf(Chess.State, variant) || (!variant.pgn && !variant.fen)) {
32
+ return false;
33
+ }
34
+ try {
35
+ const chess = new ChessJS();
36
+ if (variant.pgn) {
37
+ chess.loadPgn(variant.pgn);
38
+ } else if (variant.fen) {
39
+ chess.load(variant.fen);
40
+ }
41
+ return chess.isGameOver();
42
+ } catch {
43
+ return false;
44
+ }
45
+ })();
46
+
47
+ const handleNewGame = useCallback(() => {
48
+ if (!Obj.instanceOf(Chess.State, variant)) {
49
+ return;
50
+ }
51
+ Obj.update(variant, (variant) => {
52
+ const mutable = variant as Obj.Mutable<typeof variant>;
53
+ mutable.pgn = undefined;
54
+ mutable.fen = undefined;
55
+ });
56
+ }, [variant]);
57
+
58
+ if (!Obj.instanceOf(Chess.State, variant)) {
59
+ return null;
60
+ }
61
+
62
+ return (
63
+ <Chessboard.Root state={variant} ref={controller}>
64
+ <Panel.Root role={role} classNames='@container'>
65
+ <Panel.Toolbar asChild>
66
+ <Toolbar.Root>
67
+ {isGameOver && <Toolbar.Button onClick={handleNewGame}>{t('new-game.button')}</Toolbar.Button>}
68
+ <div className='grow' />
69
+ <Toolbar.IconButton
70
+ icon='ph--info--regular'
71
+ iconOnly
72
+ label={t('toggle-info.button')}
73
+ classNames={mx('invisible @4xl:visible')}
74
+ onClick={() => setShowInfo((open) => !open)}
75
+ />
76
+ </Toolbar.Root>
77
+ </Panel.Toolbar>
78
+ <Panel.Content>
79
+ <div
80
+ className={mx(
81
+ 'grid h-full w-full',
82
+ showInfo && '@4xl:grid-cols-[1fr_320px] gap-8',
83
+ role === 'article' && 'p-4',
84
+ role === 'section' && 'aspect-square',
85
+ role === 'section' && showInfo && '@4xl:aspect-auto',
86
+ )}
87
+ >
88
+ <Chessboard.Content>
89
+ <Chessboard.Board classNames='border rounded-xs' orientation={orientation} />
90
+ </Chessboard.Content>
91
+ {showInfo && (
92
+ <div className='hidden @4xl:flex flex-col justify-center items-center overflow-hidden'>
93
+ <Chessboard.Info
94
+ orientation={orientation}
95
+ min={8}
96
+ max={8}
97
+ onOrientationChange={setOrientation}
98
+ onClose={() => setShowInfo(false)}
99
+ onSelect={handleSelect}
100
+ />
101
+ </div>
102
+ )}
103
+ </div>
104
+ </Panel.Content>
105
+ </Panel.Root>
106
+ </Chessboard.Root>
107
+ );
108
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export { ChessArticle as default } from './ChessArticle';
@@ -0,0 +1,47 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useMemo } from 'react';
7
+
8
+ import { make as makeGame } from '@dxos/plugin-game/types';
9
+ import { CardContainer } from '@dxos/react-ui-mosaic/testing';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+
12
+ import { meta as pluginMeta } from '#meta';
13
+ import { Chess } from '#types';
14
+
15
+ import { ChessCard } from './ChessCard';
16
+
17
+ const SAMPLE_PGN =
18
+ '1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 d5 8. exd5 Nxd5 9. O-O Be6 10. Qb3 Na5 11. Qa4+ c6 12. Bxd5 Bxc3 13. Bxe6 fxe6 14. d5 Qg5 15. dxe6 Qg4 16. e7 Kf7 17. bxc3 Kg6 *';
19
+
20
+ const CardStory = () => {
21
+ const { game, state } = useMemo(() => {
22
+ const state = Chess.make({ pgn: SAMPLE_PGN });
23
+ const game = makeGame({ name: 'Story game', variant: state });
24
+ return { game, state };
25
+ }, []);
26
+ return (
27
+ <CardContainer role='popover' icon={pluginMeta.icon}>
28
+ <ChessCard role='card--content' game={game} variant={state} />
29
+ </CardContainer>
30
+ );
31
+ };
32
+
33
+ const meta = {
34
+ title: 'plugins/plugin-chess/containers/ChessCard',
35
+ render: () => <CardStory />,
36
+ decorators: [withTheme(), withLayout({ layout: 'column' })],
37
+ parameters: {
38
+ layout: 'fullscreen',
39
+ },
40
+ tags: ['cards'],
41
+ } satisfies Meta;
42
+
43
+ export default meta;
44
+
45
+ type Story = StoryObj<typeof meta>;
46
+
47
+ export const Popover: Story = {};
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Obj } from '@dxos/echo';
8
+ import { type GameVariantSurfaceProps } from '@dxos/plugin-game/types';
9
+
10
+ import { Chessboard } from '#components';
11
+ import { Chess } from '#types';
12
+
13
+ export type ChessCardProps = GameVariantSurfaceProps;
14
+
15
+ export const ChessCard = ({ variant }: ChessCardProps) => {
16
+ if (!Obj.instanceOf(Chess.State, variant)) {
17
+ return null;
18
+ }
19
+
20
+ return (
21
+ <Chessboard.Root state={variant}>
22
+ <Chessboard.Content>
23
+ <Chessboard.Board />
24
+ </Chessboard.Content>
25
+ </Chessboard.Root>
26
+ );
27
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export { ChessCard as default } from './ChessCard';
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type ComponentType, lazy } from 'react';
6
+
7
+ export const ChessArticle: ComponentType<any> = lazy(() => import('./ChessArticle'));
8
+ export const ChessCard: ComponentType<any> = lazy(() => import('./ChessCard'));
package/src/index.ts CHANGED
@@ -2,10 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Plugin } from '@dxos/app-framework';
6
+
7
+ import { meta } from './meta';
8
+
5
9
  export * from './blueprints';
6
- export * from './capabilities';
7
- export * from './components';
8
10
  export * from './meta';
9
11
  export * from './types';
10
12
 
11
- export * from './ChessPlugin';
13
+ export const ChessPlugin = Plugin.lazy(meta, () => import('#plugin'));
package/src/meta.ts CHANGED
@@ -6,7 +6,7 @@ import { type Plugin } from '@dxos/app-framework';
6
6
  import { trim } from '@dxos/util';
7
7
 
8
8
  export const meta: Plugin.Meta = {
9
- id: 'dxos.org/plugin/chess',
9
+ id: 'org.dxos.plugin.chess',
10
10
  name: 'Chess',
11
11
  description: trim`
12
12
  Full-featured chess game supporting multiplayer matches with friends or practice sessions against AI opponents.