@dxos/plugin-chess 0.8.4-main.b97322e → 0.8.4-main.bc674ce

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 (198) hide show
  1. package/dist/lib/browser/ChessboardContainer-JZ4ANG4O.mjs +81 -0
  2. package/dist/lib/browser/ChessboardContainer-JZ4ANG4O.mjs.map +7 -0
  3. package/dist/lib/browser/blueprint-definition-P7TYXWMF.mjs +18 -0
  4. package/dist/lib/browser/blueprint-definition-P7TYXWMF.mjs.map +7 -0
  5. package/dist/lib/browser/blueprints/index.mjs +11 -0
  6. package/dist/lib/browser/blueprints/index.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-66H3V2YV.mjs +64 -0
  8. package/dist/lib/browser/chunk-66H3V2YV.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-73BDP7UV.mjs +275 -0
  10. package/dist/lib/browser/chunk-73BDP7UV.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-FO4ZNFN6.mjs +229 -0
  12. package/dist/lib/browser/chunk-FO4ZNFN6.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-H3NUMCQ6.mjs +21 -0
  14. package/dist/lib/browser/chunk-H3NUMCQ6.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  16. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-OW6S2SRG.mjs +8 -0
  18. package/dist/lib/browser/chunk-OW6S2SRG.mjs.map +7 -0
  19. package/dist/lib/browser/cli/index.mjs +28 -0
  20. package/dist/lib/browser/cli/index.mjs.map +7 -0
  21. package/dist/lib/browser/index.mjs +67 -66
  22. package/dist/lib/browser/index.mjs.map +4 -4
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/react-surface-VNOWFKC6.mjs +37 -0
  25. package/dist/lib/browser/react-surface-VNOWFKC6.mjs.map +7 -0
  26. package/dist/lib/browser/types/index.mjs +4 -7
  27. package/dist/lib/node-esm/ChessboardContainer-7ONFYN7L.mjs +82 -0
  28. package/dist/lib/node-esm/ChessboardContainer-7ONFYN7L.mjs.map +7 -0
  29. package/dist/lib/node-esm/blueprint-definition-SL4LBVV5.mjs +19 -0
  30. package/dist/lib/node-esm/blueprint-definition-SL4LBVV5.mjs.map +7 -0
  31. package/dist/lib/node-esm/blueprints/index.mjs +12 -0
  32. package/dist/lib/node-esm/blueprints/index.mjs.map +7 -0
  33. package/dist/lib/node-esm/{chunk-QFINI7CC.mjs → chunk-24GJHLHM.mjs} +3 -3
  34. package/dist/lib/node-esm/chunk-24GJHLHM.mjs.map +7 -0
  35. package/dist/lib/node-esm/chunk-C7IWIXCJ.mjs +230 -0
  36. package/dist/lib/node-esm/chunk-C7IWIXCJ.mjs.map +7 -0
  37. package/dist/lib/node-esm/chunk-F5OMIM4F.mjs +23 -0
  38. package/dist/lib/node-esm/chunk-F5OMIM4F.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  40. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  41. package/dist/lib/node-esm/chunk-OUNGNJFP.mjs +65 -0
  42. package/dist/lib/node-esm/chunk-OUNGNJFP.mjs.map +7 -0
  43. package/dist/lib/node-esm/chunk-WXEPWOHT.mjs +276 -0
  44. package/dist/lib/node-esm/chunk-WXEPWOHT.mjs.map +7 -0
  45. package/dist/lib/node-esm/cli/index.mjs +29 -0
  46. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  47. package/dist/lib/node-esm/index.mjs +67 -66
  48. package/dist/lib/node-esm/index.mjs.map +4 -4
  49. package/dist/lib/node-esm/meta.json +1 -1
  50. package/dist/lib/node-esm/react-surface-HSHCIOAS.mjs +38 -0
  51. package/dist/lib/node-esm/react-surface-HSHCIOAS.mjs.map +7 -0
  52. package/dist/lib/node-esm/types/index.mjs +4 -7
  53. package/dist/types/src/ChessPlugin.d.ts +2 -1
  54. package/dist/types/src/ChessPlugin.d.ts.map +1 -1
  55. package/dist/types/src/blueprints/chess-blueprint.d.ts +21 -0
  56. package/dist/types/src/blueprints/chess-blueprint.d.ts.map +1 -0
  57. package/dist/types/src/blueprints/functions/create.d.ts +15 -0
  58. package/dist/types/src/blueprints/functions/create.d.ts.map +1 -0
  59. package/dist/types/src/blueprints/functions/index.d.ts +5 -0
  60. package/dist/types/src/blueprints/functions/index.d.ts.map +1 -0
  61. package/dist/types/src/blueprints/functions/move.d.ts +8 -0
  62. package/dist/types/src/blueprints/functions/move.d.ts.map +1 -0
  63. package/dist/types/src/blueprints/functions/play.d.ts +9 -0
  64. package/dist/types/src/blueprints/functions/play.d.ts.map +1 -0
  65. package/dist/types/src/blueprints/functions/print.d.ts +8 -0
  66. package/dist/types/src/blueprints/functions/print.d.ts.map +1 -0
  67. package/dist/types/src/blueprints/index.d.ts +3 -0
  68. package/dist/types/src/blueprints/index.d.ts.map +1 -0
  69. package/dist/types/src/capabilities/artifact-definition/artifact-definition.d.ts +12 -0
  70. package/dist/types/src/capabilities/artifact-definition/artifact-definition.d.ts.map +1 -0
  71. package/dist/types/src/capabilities/artifact-definition/index.d.ts +3 -0
  72. package/dist/types/src/capabilities/artifact-definition/index.d.ts.map +1 -0
  73. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts +9 -0
  74. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts.map +1 -0
  75. package/dist/types/src/capabilities/blueprint-definition/index.d.ts +3 -0
  76. package/dist/types/src/capabilities/blueprint-definition/index.d.ts.map +1 -0
  77. package/dist/types/src/capabilities/index.d.ts +2 -3
  78. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  79. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  80. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  81. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  82. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  83. package/dist/types/src/cli/index.d.ts +2 -0
  84. package/dist/types/src/cli/index.d.ts.map +1 -0
  85. package/dist/types/src/cli/plugin.d.ts +3 -0
  86. package/dist/types/src/cli/plugin.d.ts.map +1 -0
  87. package/dist/types/src/components/Card.stories.d.ts +15 -0
  88. package/dist/types/src/components/Card.stories.d.ts.map +1 -0
  89. package/dist/types/src/components/Chessboard.d.ts +39 -0
  90. package/dist/types/src/components/Chessboard.d.ts.map +1 -0
  91. package/dist/types/src/components/Chessboard.stories.d.ts +43 -5
  92. package/dist/types/src/components/Chessboard.stories.d.ts.map +1 -1
  93. package/dist/types/src/components/ChessboardArticle.d.ts +6 -0
  94. package/dist/types/src/components/ChessboardArticle.d.ts.map +1 -0
  95. package/dist/types/src/components/ChessboardContainer.d.ts +7 -0
  96. package/dist/types/src/components/ChessboardContainer.d.ts.map +1 -0
  97. package/dist/types/src/components/Info.d.ts +21 -0
  98. package/dist/types/src/components/Info.d.ts.map +1 -0
  99. package/dist/types/src/components/index.d.ts +2 -5
  100. package/dist/types/src/components/index.d.ts.map +1 -1
  101. package/dist/types/src/index.d.ts +2 -0
  102. package/dist/types/src/index.d.ts.map +1 -1
  103. package/dist/types/src/meta.d.ts +2 -3
  104. package/dist/types/src/meta.d.ts.map +1 -1
  105. package/dist/types/src/translations.d.ts +11 -2
  106. package/dist/types/src/translations.d.ts.map +1 -1
  107. package/dist/types/src/types/Chess.d.ts +27 -0
  108. package/dist/types/src/types/Chess.d.ts.map +1 -0
  109. package/dist/types/src/types/index.d.ts +1 -2
  110. package/dist/types/src/types/index.d.ts.map +1 -1
  111. package/dist/types/tsconfig.tsbuildinfo +1 -1
  112. package/package.json +60 -34
  113. package/src/ChessPlugin.tsx +26 -52
  114. package/src/blueprints/chess-blueprint.ts +28 -0
  115. package/src/blueprints/functions/create.ts +38 -0
  116. package/src/blueprints/functions/index.ts +8 -0
  117. package/src/blueprints/functions/move.ts +49 -0
  118. package/src/blueprints/functions/play.ts +59 -0
  119. package/src/blueprints/functions/print.ts +42 -0
  120. package/src/blueprints/index.ts +6 -0
  121. package/src/capabilities/artifact-definition/artifact-definition.ts +135 -0
  122. package/src/capabilities/artifact-definition/index.ts +7 -0
  123. package/src/capabilities/blueprint-definition/blueprint-definition.ts +23 -0
  124. package/src/capabilities/blueprint-definition/index.ts +7 -0
  125. package/src/capabilities/index.ts +2 -5
  126. package/src/capabilities/react-surface/index.ts +7 -0
  127. package/src/capabilities/react-surface/react-surface.tsx +27 -0
  128. package/src/cli/index.ts +5 -0
  129. package/src/cli/plugin.ts +26 -0
  130. package/src/components/Card.stories.tsx +47 -0
  131. package/src/components/Chessboard.stories.tsx +36 -24
  132. package/src/components/Chessboard.tsx +188 -0
  133. package/src/components/ChessboardArticle.tsx +71 -0
  134. package/src/components/ChessboardContainer.tsx +40 -0
  135. package/src/components/Info.tsx +244 -0
  136. package/src/components/index.ts +2 -2
  137. package/src/index.ts +2 -0
  138. package/src/meta.ts +9 -7
  139. package/src/translations.ts +11 -2
  140. package/src/types/Chess.ts +58 -0
  141. package/src/types/index.ts +1 -2
  142. package/dist/lib/browser/ChessContainer-SC4ZV6XZ.mjs +0 -129
  143. package/dist/lib/browser/ChessContainer-SC4ZV6XZ.mjs.map +0 -7
  144. package/dist/lib/browser/artifact-definition-A2FSM255.mjs +0 -182
  145. package/dist/lib/browser/artifact-definition-A2FSM255.mjs.map +0 -7
  146. package/dist/lib/browser/chunk-A3WEUKPK.mjs +0 -61
  147. package/dist/lib/browser/chunk-A3WEUKPK.mjs.map +0 -7
  148. package/dist/lib/browser/chunk-KDADGLPC.mjs +0 -8
  149. package/dist/lib/browser/chunk-KDADGLPC.mjs.map +0 -7
  150. package/dist/lib/browser/chunk-ZXH3N4NA.mjs +0 -66
  151. package/dist/lib/browser/chunk-ZXH3N4NA.mjs.map +0 -7
  152. package/dist/lib/browser/intent-resolver-KQYYX44R.mjs +0 -28
  153. package/dist/lib/browser/intent-resolver-KQYYX44R.mjs.map +0 -7
  154. package/dist/lib/browser/react-surface-PLUCWIYP.mjs +0 -36
  155. package/dist/lib/browser/react-surface-PLUCWIYP.mjs.map +0 -7
  156. package/dist/lib/node-esm/ChessContainer-7GLY5KLY.mjs +0 -130
  157. package/dist/lib/node-esm/ChessContainer-7GLY5KLY.mjs.map +0 -7
  158. package/dist/lib/node-esm/artifact-definition-2H7OUBZO.mjs +0 -183
  159. package/dist/lib/node-esm/artifact-definition-2H7OUBZO.mjs.map +0 -7
  160. package/dist/lib/node-esm/chunk-27D3JA3K.mjs +0 -68
  161. package/dist/lib/node-esm/chunk-27D3JA3K.mjs.map +0 -7
  162. package/dist/lib/node-esm/chunk-IS3Y25PL.mjs +0 -63
  163. package/dist/lib/node-esm/chunk-IS3Y25PL.mjs.map +0 -7
  164. package/dist/lib/node-esm/chunk-QFINI7CC.mjs.map +0 -7
  165. package/dist/lib/node-esm/intent-resolver-GXK2JROQ.mjs +0 -29
  166. package/dist/lib/node-esm/intent-resolver-GXK2JROQ.mjs.map +0 -7
  167. package/dist/lib/node-esm/react-surface-NGLNIWN3.mjs +0 -37
  168. package/dist/lib/node-esm/react-surface-NGLNIWN3.mjs.map +0 -7
  169. package/dist/types/src/capabilities/artifact-definition.d.ts +0 -11
  170. package/dist/types/src/capabilities/artifact-definition.d.ts.map +0 -1
  171. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  172. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  173. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  174. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  175. package/dist/types/src/components/Chess.d.ts +0 -14
  176. package/dist/types/src/components/Chess.d.ts.map +0 -1
  177. package/dist/types/src/components/ChessContainer.d.ts +0 -8
  178. package/dist/types/src/components/ChessContainer.d.ts.map +0 -1
  179. package/dist/types/src/components/ChessContainer.stories.d.ts +0 -23
  180. package/dist/types/src/components/ChessContainer.stories.d.ts.map +0 -1
  181. package/dist/types/src/components/ChessPanel.d.ts +0 -11
  182. package/dist/types/src/components/ChessPanel.d.ts.map +0 -1
  183. package/dist/types/src/components/PlayerSelector.d.ts +0 -8
  184. package/dist/types/src/components/PlayerSelector.d.ts.map +0 -1
  185. package/dist/types/src/types/schema.d.ts +0 -29
  186. package/dist/types/src/types/schema.d.ts.map +0 -1
  187. package/dist/types/src/types/types.d.ts +0 -32
  188. package/dist/types/src/types/types.d.ts.map +0 -1
  189. package/src/capabilities/artifact-definition.ts +0 -124
  190. package/src/capabilities/intent-resolver.ts +0 -26
  191. package/src/capabilities/react-surface.tsx +0 -23
  192. package/src/components/Chess.tsx +0 -60
  193. package/src/components/ChessContainer.stories.tsx +0 -110
  194. package/src/components/ChessContainer.tsx +0 -71
  195. package/src/components/ChessPanel.tsx +0 -67
  196. package/src/components/PlayerSelector.tsx +0 -82
  197. package/src/types/schema.ts +0 -34
  198. package/src/types/types.ts +0 -20
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+
8
+ import { Capability, Common } from '@dxos/app-framework';
9
+ import { Obj } from '@dxos/echo';
10
+
11
+ import { ChessboardContainer } from '../../components';
12
+ import { meta } from '../../meta';
13
+ import { Chess } from '../../types';
14
+
15
+ export default Capability.makeModule(() =>
16
+ Effect.succeed(
17
+ Capability.contributes(Common.Capability.ReactSurface, [
18
+ Common.createSurface({
19
+ id: meta.id,
20
+ role: ['article', 'section', 'card--content'],
21
+ // TODO(burdon): Could this be standardized so that we don't require a subject property.
22
+ filter: (data): data is { subject: Chess.Game } => Obj.instanceOf(Chess.Game, data.subject),
23
+ component: ({ data, role }) => <ChessboardContainer role={role} subject={data.subject} />,
24
+ }),
25
+ ]),
26
+ ),
27
+ );
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './plugin';
@@ -0,0 +1,26 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Common, Plugin } from '@dxos/app-framework';
8
+ import { type CreateObject } from '@dxos/plugin-space/types';
9
+
10
+ import { meta } from '../meta';
11
+ import { Chess } from '../types';
12
+
13
+ // TODO(wittjosiah): Factor out shared modules.
14
+ export const ChessPlugin = Plugin.define(meta).pipe(
15
+ Common.Plugin.addSchemaModule({ schema: [Chess.Game] }),
16
+ Common.Plugin.addMetadataModule({
17
+ metadata: {
18
+ id: Chess.Game.typename,
19
+ metadata: {
20
+ createObject: ((props) => Effect.sync(() => Chess.make(props))) satisfies CreateObject,
21
+ addToCollectionOnCreate: true,
22
+ },
23
+ },
24
+ }),
25
+ Plugin.make,
26
+ );
@@ -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 { withTheme } from '@dxos/react-ui/testing';
9
+ import { CardContainer } from '@dxos/react-ui-mosaic/testing';
10
+
11
+ import { meta as pluginMeta } from '../meta';
12
+ import { Chess } from '../types';
13
+
14
+ import { Chessboard } from './Chessboard';
15
+
16
+ const SAMPLE_PGN =
17
+ '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 *';
18
+
19
+ // TODO(wittjosiah): ECHO objects don't work when passed via Storybook args.
20
+ const CardStory = () => {
21
+ const game = useMemo(() => Chess.make({ pgn: SAMPLE_PGN }), []);
22
+ return (
23
+ <CardContainer icon={pluginMeta.icon}>
24
+ <Chessboard.Root game={game}>
25
+ <Chessboard.Content>
26
+ <Chessboard.Board />
27
+ </Chessboard.Content>
28
+ </Chessboard.Root>
29
+ </CardContainer>
30
+ );
31
+ };
32
+
33
+ const meta = {
34
+ title: 'plugins/plugin-chess/Card',
35
+ render: () => <CardStory />,
36
+ decorators: [withTheme],
37
+ parameters: {
38
+ layout: 'centered',
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 = {};
@@ -2,40 +2,52 @@
2
2
  // Copyright 2023 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, { useMemo } from 'react';
9
7
 
10
- import { Gameboard, Chessboard, ChessModel } from '@dxos/react-ui-gameboard';
11
- import { withLayout, withTheme } from '@dxos/storybook-utils';
8
+ import { withClientProvider } from '@dxos/react-client/testing';
9
+ import { withTheme } from '@dxos/react-ui/testing';
12
10
 
13
- import { ChessPanel } from './ChessPanel';
11
+ import { translations } from '../translations';
12
+ import { Chess } from '../types';
14
13
 
15
- const DefaultStory = () => {
16
- const model = useMemo(() => new ChessModel(), []);
14
+ import { ChessboardArticle } from './ChessboardArticle';
17
15
 
18
- return (
19
- <div className='flex grow mx-8 gap-8 items-center overflow-hidden'>
20
- <Gameboard.Root model={model} onDrop={(move) => model.makeMove(move)}>
21
- <Gameboard.Content>
22
- <Chessboard />
23
- </Gameboard.Content>
24
- </Gameboard.Root>
25
- <ChessPanel model={model} classNames='w-[200px]' />
26
- </div>
27
- );
16
+ type StoryProps = {
17
+ pgn?: string;
28
18
  };
29
19
 
30
- const meta: Meta<typeof Chessboard> = {
31
- title: 'plugins/plugin-chess/Chessboard',
32
- component: Chessboard,
33
- render: DefaultStory,
34
- decorators: [withTheme, withLayout({ fullscreen: true })],
20
+ const DefaultStory = ({ pgn }: StoryProps) => {
21
+ const game = useMemo(() => Chess.make(pgn ? { pgn } : undefined), [pgn]);
22
+ return <ChessboardArticle subject={game} />;
35
23
  };
36
24
 
37
- type Story = StoryObj<typeof Chessboard>;
25
+ const meta = {
26
+ title: 'plugins/plugin-chess/Chessboard',
27
+ component: DefaultStory,
28
+ decorators: [withTheme, withClientProvider({ createIdentity: true })],
29
+ parameters: {
30
+ layout: 'fullscreen',
31
+ translations,
32
+ },
33
+ } satisfies Meta<typeof DefaultStory>;
38
34
 
39
35
  export default meta;
40
36
 
41
- export const Default: Story = {};
37
+ type Story = StoryObj<typeof meta>;
38
+
39
+ export const Default: Story = {
40
+ args: {},
41
+ };
42
+
43
+ export const EndGame: Story = {
44
+ args: {
45
+ pgn: '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 *',
46
+ },
47
+ };
48
+
49
+ export const Promption: Story = {
50
+ args: {
51
+ pgn: '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 *',
52
+ },
53
+ };
@@ -0,0 +1,188 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Registry, RegistryContext } from '@effect-atom/atom-react';
6
+ import React, {
7
+ type PropsWithChildren,
8
+ forwardRef,
9
+ useCallback,
10
+ useContext,
11
+ useEffect,
12
+ useImperativeHandle,
13
+ useMemo,
14
+ useRef,
15
+ } from 'react';
16
+
17
+ import { addEventListener } from '@dxos/async';
18
+ import { Obj } from '@dxos/echo';
19
+ import { type ThemedClassName } from '@dxos/react-ui';
20
+ import {
21
+ ChessModel,
22
+ Gameboard,
23
+ type GameboardRootProps,
24
+ Chessboard as NaturalChessboard,
25
+ type ChessboardProps as NaturalChessboardProps,
26
+ getRawPgn,
27
+ useGameboardContext,
28
+ } from '@dxos/react-ui-gameboard';
29
+ import { useSoundEffect } from '@dxos/react-ui-sfx';
30
+ import { mx } from '@dxos/ui-theme';
31
+
32
+ import { type Chess } from '../types';
33
+
34
+ import { Info, type InfoProps } from './Info';
35
+
36
+ export interface ChessboardController {
37
+ setMoveNumber(index: number): void;
38
+ }
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
+ //
50
+ // Root
51
+ //
52
+
53
+ type RootProps = PropsWithChildren<{
54
+ game: Chess.Game;
55
+ }>;
56
+
57
+ const Root = forwardRef<ChessboardController, RootProps>(({ game, children }, forwardedRef) => {
58
+ const registry = useContext(RegistryContext);
59
+ const model = useMemo(() => new ExtendedChessModel(registry, game), [registry]);
60
+ const click = useSoundEffect('Click');
61
+
62
+ // Controller.
63
+ useImperativeHandle(forwardedRef, () => {
64
+ return {
65
+ setMoveNumber: (index) => model.setMoveIndex(index),
66
+ };
67
+ }, [model]);
68
+
69
+ // External change.
70
+ // NOTE: Warning if user has not interacted with the board.
71
+ useEffect(() => {
72
+ if (model.pgn !== getRawPgn(game.pgn ?? '')) {
73
+ const silent = model.pgn === '*';
74
+ model.update(game.pgn);
75
+ if (!silent) {
76
+ void click.play();
77
+ }
78
+ }
79
+ }, [game.pgn]);
80
+
81
+ // Move.
82
+ const handleDrop = useCallback<NonNullable<GameboardRootProps<ChessModel>['onDrop']>>(
83
+ (move) => {
84
+ if (!model.makeMove(move)) {
85
+ return false;
86
+ }
87
+
88
+ void click.play();
89
+ Obj.change(game, (g) => {
90
+ g.pgn = model.pgn;
91
+ });
92
+ return true;
93
+ },
94
+ [model],
95
+ );
96
+
97
+ return (
98
+ <Gameboard.Root model={model} onDrop={handleDrop}>
99
+ {children}
100
+ </Gameboard.Root>
101
+ );
102
+ });
103
+
104
+ //
105
+ // Content
106
+ //
107
+
108
+ type Role = 'card--popover' | 'card--intrinsic' | 'card--extrinsic';
109
+
110
+ type ContentProps = ThemedClassName<PropsWithChildren<{ role?: Role }>>;
111
+
112
+ const Content = ({ classNames, children, role }: ContentProps) => {
113
+ return (
114
+ <Gameboard.Content
115
+ classNames={mx(classNames, role === 'card--popover' && 'size-container popover-square')}
116
+ grow={!role || role === 'card--extrinsic'}
117
+ contain={!role || role === 'card--extrinsic' || role === 'card--popover'}
118
+ >
119
+ {children}
120
+ </Gameboard.Content>
121
+ );
122
+ };
123
+
124
+ //
125
+ // Board
126
+ //
127
+
128
+ type BoardProps = NaturalChessboardProps;
129
+
130
+ const Board = (props: BoardProps) => {
131
+ const registry = useContext(RegistryContext);
132
+ const { model } = useGameboardContext<ChessModel>(Board.displayName);
133
+
134
+ // Keyboard navigation.
135
+ const ref = useRef<HTMLDivElement>(null);
136
+ useEffect(() => {
137
+ if (!ref.current) {
138
+ return;
139
+ }
140
+
141
+ // Participate in keyboard navigation (set tabIndex={0})
142
+ ref.current.setAttribute('data-arrow-keys', 'all');
143
+
144
+ return addEventListener(ref.current, 'keydown', (ev) => {
145
+ const moveIndex = registry.get(model.moveIndex);
146
+ switch (ev.key) {
147
+ case 'ArrowUp':
148
+ model.setMoveIndex(0);
149
+ break;
150
+ case 'ArrowDown':
151
+ model.setMoveIndex(model.game.history().length);
152
+ break;
153
+ case 'ArrowLeft':
154
+ if (moveIndex > 0) {
155
+ model.setMoveIndex(moveIndex - 1);
156
+ }
157
+ break;
158
+ case 'ArrowRight':
159
+ if (moveIndex < model.game.history().length) {
160
+ model.setMoveIndex(moveIndex + 1);
161
+ }
162
+ break;
163
+ }
164
+ });
165
+ }, [registry, model]);
166
+
167
+ return <NaturalChessboard ref={ref} {...props} />;
168
+ };
169
+
170
+ Board.displayName = 'Chessboard.Board';
171
+
172
+ //
173
+ // Chessboard
174
+ //
175
+
176
+ export const Chessboard = {
177
+ Root: Root,
178
+ Content: Content,
179
+ Board: Board,
180
+ Info: Info,
181
+ };
182
+
183
+ export type {
184
+ RootProps as ChessboardRootProps,
185
+ ContentProps as ChessboardContentProps,
186
+ BoardProps as ChessboardBoardProps,
187
+ InfoProps as ChessboardInfoProps,
188
+ };
@@ -0,0 +1,71 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback, useRef, useState } from 'react';
6
+
7
+ import { type SurfaceComponentProps } from '@dxos/app-framework/react';
8
+ import { Toolbar, useTranslation } from '@dxos/react-ui';
9
+ import { type Player } from '@dxos/react-ui-gameboard';
10
+ import { Layout } from '@dxos/react-ui-mosaic';
11
+ import { mx } from '@dxos/ui-theme';
12
+
13
+ import { meta } from '../meta';
14
+ import { type Chess } from '../types';
15
+
16
+ import { Chessboard, type ChessboardController, type ChessboardInfoProps } from './Chessboard';
17
+
18
+ export type ChessboardArticleProps = SurfaceComponentProps<Chess.Game>;
19
+
20
+ export const ChessboardArticle = ({ role, subject: game }: ChessboardArticleProps) => {
21
+ const { t } = useTranslation(meta.id);
22
+ const [orientation, setOrientation] = useState<Player>('white');
23
+ const [open, setOpen] = useState(true);
24
+ const controller = useRef<ChessboardController>(null);
25
+
26
+ // TODO(burdon): Keyboard handler.
27
+ const handleSelect = useCallback<NonNullable<ChessboardInfoProps['onSelect']>>((index) => {
28
+ controller.current?.setMoveNumber(index);
29
+ }, []);
30
+
31
+ return (
32
+ <Layout.Main toolbar classNames='@container'>
33
+ <Chessboard.Root game={game} ref={controller}>
34
+ <Toolbar.Root>
35
+ <Toolbar.IconButton
36
+ icon='ph--info--regular'
37
+ iconOnly
38
+ label={t('toggle info button')}
39
+ disabled={open}
40
+ classNames={mx('invisible @3xl:visible')}
41
+ onClick={() => setOpen((open) => !open)}
42
+ />
43
+ </Toolbar.Root>
44
+ <div
45
+ className={mx(
46
+ 'grid bs-full is-full gap-2',
47
+ open && '@3xl:grid-cols-[1fr_320px]',
48
+ role === 'section' && 'aspect-square',
49
+ role === 'section' && open && '@3xl:aspect-auto',
50
+ )}
51
+ >
52
+ <Chessboard.Content>
53
+ <Chessboard.Board classNames='m-4 rounded-sm overflow-hidden' orientation={orientation} />
54
+ </Chessboard.Content>
55
+ {open && (
56
+ <div className='hidden @3xl:flex flex-col p-8 justify-center items-center overflow-hidden'>
57
+ <Chessboard.Info
58
+ orientation={orientation}
59
+ min={8}
60
+ max={8}
61
+ onOrientationChange={setOrientation}
62
+ onClose={() => setOpen(false)}
63
+ onSelect={handleSelect}
64
+ />
65
+ </div>
66
+ )}
67
+ </div>
68
+ </Chessboard.Root>
69
+ </Layout.Main>
70
+ );
71
+ };
@@ -0,0 +1,40 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { type SurfaceComponentProps } from '@dxos/app-framework/react';
8
+ import { Obj } from '@dxos/echo';
9
+
10
+ import { type Chess } from '../types';
11
+
12
+ import { Chessboard } from './Chessboard';
13
+ import { ChessboardArticle } from './ChessboardArticle';
14
+
15
+ export type ChessboardContainerProps = SurfaceComponentProps<Chess.Game>;
16
+
17
+ export const ChessboardContainer = ({ role, subject: game }: ChessboardContainerProps) => {
18
+ const db = Obj.getDatabase(game);
19
+ if (!db) {
20
+ return null;
21
+ }
22
+
23
+ switch (role) {
24
+ case 'card--content': {
25
+ return (
26
+ <Chessboard.Root game={game}>
27
+ <Chessboard.Content>
28
+ <Chessboard.Board />
29
+ </Chessboard.Content>
30
+ </Chessboard.Root>
31
+ );
32
+ }
33
+
34
+ default: {
35
+ return <ChessboardArticle role={role} subject={game} />;
36
+ }
37
+ }
38
+ };
39
+
40
+ export default ChessboardContainer;