board-game-engine-react 0.0.1 → 0.0.2

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.
@@ -1,20 +1,250 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
3
- typeof define === 'function' && define.amd ? define(['react'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.BoardGameEngineReact = factory(global.React));
5
- })(this, (function (React) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.BoardGameEngineReact = {}, global.React));
5
+ })(this, (function (exports, React) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
10
 
11
- function BoardGameEngineReact({}) {
11
+ const GameContext = /*#__PURE__*/React.createContext({
12
+ clickTarget: () => {}
13
+ });
14
+
15
+ // do we need isSpectator
16
+ function GameProvider({
17
+ gameConnection,
18
+ children,
19
+ isSpectator
20
+ }) {
21
+ React.useEffect(() => {
22
+ if (gameConnection.state._stateID === 0) {
23
+ gameConnection.reset();
24
+ }
25
+ }, [gameConnection.state._stateID]);
26
+ return /*#__PURE__*/React__default["default"].createElement(GameContext.Provider, {
27
+ value: {
28
+ clickTarget: target => {
29
+ if (!isSpectator) {
30
+ gameConnection.doStep(target);
31
+ }
32
+ },
33
+ undoStep: () => {
34
+ gameConnection.undoStep();
35
+ },
36
+ allClickable: gameConnection.optimisticWinner || isSpectator ? new Set() : gameConnection.allClickable,
37
+ currentMoveTargets: gameConnection.optimisticWinner || isSpectator ? [] : gameConnection.moveBuilder.targets
38
+ }
39
+ }, children);
40
+ }
41
+ const useGame = () => React.useContext(GameContext);
42
+
43
+ function Grid({
44
+ grid
45
+ }) {
46
+ const {
47
+ width,
48
+ height,
49
+ spaces
50
+ } = grid.attributes;
51
+ return /*#__PURE__*/React__default["default"].createElement("div", {
52
+ className: "grid",
53
+ style: {
54
+ display: 'inline-grid',
55
+ width: '100%',
56
+ gridTemplateColumns: `repeat(${width}, 1fr)`,
57
+ gridTemplateRows: `repeat(${height}, 1fr)`
58
+ }
59
+ }, spaces.map((space, index) => {
60
+ return /*#__PURE__*/React__default["default"].createElement("div", {
61
+ key: index,
62
+ className: "grid__cell"
63
+ }, /*#__PURE__*/React__default["default"].createElement(Entity, {
64
+ entity: space
65
+ }));
66
+ }));
67
+ }
68
+
69
+ function Space({
70
+ space
71
+ }) {
72
+ const {
73
+ clickTarget,
74
+ allClickable,
75
+ currentMoveTargets
76
+ } = useGame();
77
+ const {
78
+ entities,
79
+ entityId
80
+ } = space.attributes;
81
+ const clickable = [...allClickable].map(e => e.entityId).includes(entityId);
82
+ const targeted = currentMoveTargets?.map(e => e.entityId).includes(entityId);
83
+ return /*#__PURE__*/React__default["default"].createElement("a", {
84
+ className: ['space', clickable && 'space--clickable', targeted && 'space--targeted'].filter(Boolean).join(' '),
85
+ onClick: () => clickTarget(space),
86
+ style: {
87
+ display: 'inline-block',
88
+ flex: '1'
89
+ }
90
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
91
+ className: "space__entity-grid",
92
+ style: {
93
+ display: 'flex',
94
+ height: '100%',
95
+ width: '100%',
96
+ flexWrap: 'wrap'
97
+ }
98
+ }, Array.from({
99
+ length: entities.length
100
+ }, (_, i) => /*#__PURE__*/React__default["default"].createElement("div", {
101
+ className: "space__entity-grid__cell",
102
+ style: {
103
+ display: 'inline-block'
104
+ },
105
+ key: i
106
+ }, /*#__PURE__*/React__default["default"].createElement(Entity, {
107
+ entity: entities[i]
108
+ }))), !entities.length && space.attributes.name));
109
+ }
110
+
111
+ function Entity({
112
+ entity
113
+ }) {
114
+ const {
115
+ clickTarget,
116
+ allClickable
117
+ } = useGame();
118
+ const isClickable = allClickable.has(entity);
119
+ const attributes = entity.attributes;
120
+ switch (attributes.type) {
121
+ case 'Grid':
122
+ return /*#__PURE__*/React__default["default"].createElement(Grid, {
123
+ grid: entity,
124
+ isClickable: isClickable
125
+ });
126
+ case 'Space':
127
+ return /*#__PURE__*/React__default["default"].createElement(Space, {
128
+ space: entity,
129
+ isClickable: isClickable
130
+ });
131
+ default:
132
+ return /*#__PURE__*/React__default["default"].createElement("div", {
133
+ onClick: e => {
134
+ if (isClickable) {
135
+ e.stopPropagation();
136
+ clickTarget(entity);
137
+ }
138
+ },
139
+ className: ['entity', attributes.player && `player-${attributes.player}`, allClickable.has(entity) && 'entity--clickable'].filter(Boolean).join(' ')
140
+ }, entity.rule.displayProperties?.map((property, i) => /*#__PURE__*/React__default["default"].createElement("div", {
141
+ key: i
142
+ }, property, ": ", entity.attributes[property]?.toString())));
143
+ }
144
+ }
145
+
146
+ function AbstractChoices() {
147
+ const {
148
+ clickTarget,
149
+ allClickable,
150
+ undoStep,
151
+ currentMoveTargets
152
+ } = useGame();
153
+ const abstractChoices = [...allClickable].filter(c => c.abstract);
154
+
155
+ // spacer assumes only one row of choices.
156
+ // could save and store biggest height instead?
12
157
  return /*#__PURE__*/React__default["default"].createElement("div", {
13
- className: "board-game-engine-react"
14
- });
158
+ style: {
159
+ position: 'relative'
160
+ }
161
+ }, /*#__PURE__*/React__default["default"].createElement("button", {
162
+ style: {
163
+ visibility: 'hidden'
164
+ },
165
+ className: "button button--style-b button--x-small abstract-choices__choice"
166
+ }, "Spacer"), /*#__PURE__*/React__default["default"].createElement("div", {
167
+ style: {
168
+ position: 'absolute',
169
+ top: 0,
170
+ width: '100%'
171
+ }
172
+ }, !!currentMoveTargets.length && /*#__PURE__*/React__default["default"].createElement("button", {
173
+ className: "button button--style-c button--x-small abstract-choices__choice abstract-choices__choice--undo",
174
+ onClick: undoStep
175
+ }, "Undo"), abstractChoices.map((choice, i) => /*#__PURE__*/React__default["default"].createElement("button", {
176
+ key: i,
177
+ className: "button button--style-b button--x-small abstract-choices__choice",
178
+ onClick: () => clickTarget(choice)
179
+ }, choice.value))));
180
+ }
181
+
182
+ function GameStatus({
183
+ gameConnection
184
+ }) {
185
+ const players = gameConnection.client.matchData;
186
+ const winner = gameConnection.state.ctx.gameover?.winner;
187
+ const draw = gameConnection.state.ctx.gameover?.draw;
188
+ let winnerString = '';
189
+ if (draw) {
190
+ winnerString = 'Draw!';
191
+ } else if (players && winner) {
192
+ winnerString = `${players[winner].name} Wins!`;
193
+ } else if (winner) {
194
+ winnerString = `Player ${winner} Wins!`;
195
+ }
196
+ return gameConnection.state.ctx.gameover && /*#__PURE__*/React__default["default"].createElement("div", {
197
+ className: "game-status"
198
+ }, winnerString);
199
+ }
200
+
201
+ function Game({
202
+ gameConnection
203
+ }) {
204
+ console.log('555gameConnection', gameConnection);
205
+ const {
206
+ G
207
+ } = gameConnection.state;
208
+ return /*#__PURE__*/React__default["default"].createElement(GameProvider, {
209
+ gameConnection: gameConnection,
210
+ isSpectator: true
211
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
212
+ className: "game"
213
+ }, /*#__PURE__*/React__default["default"].createElement(AbstractChoices, null), /*#__PURE__*/React__default["default"].createElement("div", {
214
+ className: "shared-board",
215
+ style: {
216
+ width: '100%',
217
+ display: 'flex',
218
+ flexWrap: 'wrap',
219
+ justifyContent: 'center',
220
+ alignItems: 'center',
221
+ gap: '1em'
222
+ }
223
+ }, G.sharedBoard.entities.map((entity, i) => /*#__PURE__*/React__default["default"].createElement(Entity, {
224
+ key: i,
225
+ entity: entity
226
+ }))), G.personalBoards && /*#__PURE__*/React__default["default"].createElement("div", {
227
+ className: "personal-boards"
228
+ }, G.personalBoards.map((board, i) => /*#__PURE__*/React__default["default"].createElement("div", {
229
+ key: i,
230
+ className: "personal-board",
231
+ style: {
232
+ width: '100%',
233
+ display: 'grid',
234
+ gridAutoFlow: 'column',
235
+ gridAutoRows: '1fr',
236
+ gap: '1em'
237
+ }
238
+ }, board.entities.map((entity, j) => /*#__PURE__*/React__default["default"].createElement(Entity, {
239
+ key: j,
240
+ entity: entity
241
+ }))))), /*#__PURE__*/React__default["default"].createElement(GameStatus, {
242
+ gameConnection: gameConnection
243
+ })));
15
244
  }
16
- BoardGameEngineReact.propTypes = {};
17
245
 
18
- return BoardGameEngineReact;
246
+ exports.Game = Game;
247
+
248
+ Object.defineProperty(exports, '__esModule', { value: true });
19
249
 
20
250
  }));
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).BoardGameEngineReact=t(e.React)}(this,function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e);function o({}){return n.default.createElement("div",{className:"board-game-engine-react"})}return o.propTypes={},o});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).BoardGameEngineReact={},e.React)}(this,function(e,t){"use strict";function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var l=a(t);const n=t.createContext({clickTarget:()=>{}});function i({gameConnection:e,children:a,isSpectator:i}){return t.useEffect(()=>{0===e.state._stateID&&e.reset()},[e.state._stateID]),l.default.createElement(n.Provider,{value:{clickTarget:t=>{i||e.doStep(t)},undoStep:()=>{e.undoStep()},allClickable:e.optimisticWinner||i?new Set:e.allClickable,currentMoveTargets:e.optimisticWinner||i?[]:e.moveBuilder.targets}},a)}const c=()=>t.useContext(n);function r({grid:e}){const{width:t,height:a,spaces:n}=e.attributes;return l.default.createElement("div",{className:"grid",style:{display:"inline-grid",width:"100%",gridTemplateColumns:`repeat(${t}, 1fr)`,gridTemplateRows:`repeat(${a}, 1fr)`}},n.map((e,t)=>l.default.createElement("div",{key:t,className:"grid__cell"},l.default.createElement(o,{entity:e}))))}function s({space:e}){const{clickTarget:t,allClickable:a,currentMoveTargets:n}=c(),{entities:i,entityId:r}=e.attributes,s=[...a].map(e=>e.entityId).includes(r),d=n?.map(e=>e.entityId).includes(r);return l.default.createElement("a",{className:["space",s&&"space--clickable",d&&"space--targeted"].filter(Boolean).join(" "),onClick:()=>t(e),style:{display:"inline-block",flex:"1"}},l.default.createElement("div",{className:"space__entity-grid",style:{display:"flex",height:"100%",width:"100%",flexWrap:"wrap"}},Array.from({length:i.length},(e,t)=>l.default.createElement("div",{className:"space__entity-grid__cell",style:{display:"inline-block"},key:t},l.default.createElement(o,{entity:i[t]}))),!i.length&&e.attributes.name))}function o({entity:e}){const{clickTarget:t,allClickable:a}=c(),n=a.has(e),i=e.attributes;switch(i.type){case"Grid":return l.default.createElement(r,{grid:e,isClickable:n});case"Space":return l.default.createElement(s,{space:e,isClickable:n});default:return l.default.createElement("div",{onClick:a=>{n&&(a.stopPropagation(),t(e))},className:["entity",i.player&&`player-${i.player}`,a.has(e)&&"entity--clickable"].filter(Boolean).join(" ")},e.rule.displayProperties?.map((t,a)=>l.default.createElement("div",{key:a},t,": ",e.attributes[t]?.toString())))}}function d(){const{clickTarget:e,allClickable:t,undoStep:a,currentMoveTargets:n}=c(),i=[...t].filter(e=>e.abstract);return l.default.createElement("div",{style:{position:"relative"}},l.default.createElement("button",{style:{visibility:"hidden"},className:"button button--style-b button--x-small abstract-choices__choice"},"Spacer"),l.default.createElement("div",{style:{position:"absolute",top:0,width:"100%"}},!!n.length&&l.default.createElement("button",{className:"button button--style-c button--x-small abstract-choices__choice abstract-choices__choice--undo",onClick:a},"Undo"),i.map((t,a)=>l.default.createElement("button",{key:a,className:"button button--style-b button--x-small abstract-choices__choice",onClick:()=>e(t)},t.value))))}function u({gameConnection:e}){const t=e.client.matchData,a=e.state.ctx.gameover?.winner,n=e.state.ctx.gameover?.draw;let i="";return n?i="Draw!":t&&a?i=`${t[a].name} Wins!`:a&&(i=`Player ${a} Wins!`),e.state.ctx.gameover&&l.default.createElement("div",{className:"game-status"},i)}e.Game=function({gameConnection:e}){console.log("555gameConnection",e);const{G:t}=e.state;return l.default.createElement(i,{gameConnection:e,isSpectator:!0},l.default.createElement("div",{className:"game"},l.default.createElement(d,null),l.default.createElement("div",{className:"shared-board",style:{width:"100%",display:"flex",flexWrap:"wrap",justifyContent:"center",alignItems:"center",gap:"1em"}},t.sharedBoard.entities.map((e,t)=>l.default.createElement(o,{key:t,entity:e}))),t.personalBoards&&l.default.createElement("div",{className:"personal-boards"},t.personalBoards.map((e,t)=>l.default.createElement("div",{key:t,className:"personal-board",style:{width:"100%",display:"grid",gridAutoFlow:"column",gridAutoRows:"1fr",gap:"1em"}},e.entities.map((e,t)=>l.default.createElement(o,{key:t,entity:e}))))),l.default.createElement(u,{gameConnection:e})))},Object.defineProperty(e,"__esModule",{value:!0})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "board-game-engine-react",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "React library for using board-game-engine",
5
5
  "main": "dist/board-game-engine-react.js",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { useGame } from "../contexts/game-context.js";
2
+ import { useGame } from "../../contexts/game-context.js";
3
3
 
4
4
  export default function AbstractChoices () {
5
5
  const { clickTarget, allClickable, undoStep, currentMoveTargets } = useGame()
package/src/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import './styles.scss'
2
2
 
3
- export { default } from './BoardGameEngineReact.js'
3
+ export { default as Game } from './components/game/game.js'
@@ -1,12 +0,0 @@
1
- import React, { useRef } from 'react'
2
- import PropTypes from 'prop-types'
3
-
4
- export default function BoardGameEngineReact ({}) {
5
- return (
6
- <div className="board-game-engine-react">
7
- </div>
8
- )
9
- }
10
-
11
- BoardGameEngineReact.propTypes = {
12
- }
File without changes
File without changes
File without changes
File without changes