Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and reactive-config prop feature #190

Merged
merged 20 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,7 @@ module.exports = {
semi: true,
},
],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'vue/require-explicit-emits': ['off'],
},
};
18 changes: 18 additions & 0 deletions docs/.vitepress/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
max-width: 600px;
}

coords.files {
bottom: 5px !important;
}

.move-container {
min-height: 250px;
}
Expand Down Expand Up @@ -61,3 +65,17 @@ h1 {
background-position: center;
background-repeat: no-repeat;
}

.buttons {
padding: 5px;
text-align: center;
}
.buttons .activated {
background-color: #888;
}
.buttons button {
background-color: #555;
border-radius: 5px;
margin: 5px;
padding: 5px;
}
24 changes: 20 additions & 4 deletions docs/board-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Here is a list of all the available methods:

```ts
/**
* Resets the board to the initial starting position.
* Resets the board to the initial starting configuration.
*/
resetBoard(): void;

Expand Down Expand Up @@ -95,10 +95,12 @@ getOpeningName(): Promise<string | null>;

/**
* make a move programmatically on the board
* @param move the san move to make like 'e4', 'O-O' or 'e8=Q'
* @param move either a string in Standard Algebraic Notation (SAN), eg. 'e4', 'exd5', 'O-O', 'Nf3' or 'e8=Q'
* or an object of shape { from: string; to: string; promotion?: string; }, eg. { from: 'g8', to: 'f6' } or
* { from: 'e7', to: 'e8', promotion: 'q'}
* @returns true if the move was made, false if the move was illegal
*/
move(move: string): boolean;
move(move: string | { from: Key; to: Key; promotion?: Promotion; }): boolean;

/**
* returns the current turn color
Expand Down Expand Up @@ -192,7 +194,8 @@ getSquareColor(square: string): SquareColor | null;
getSquare(square: Square): Piece | null;

/**
* Returns the piece on the square or null if there is no piece
* loads a fen into the board
* Caution: this will erase the game history. To set position with history call loadPgn with a pgn instead
*/
setPosition(fen: string): void;

Expand Down Expand Up @@ -236,6 +239,19 @@ loadPgn(pgn: string): void;
getPgnInfo(): {
[key: string]: string | undefined;
};

/**
* Sets the config of the board.
* Caution: providing a config with a fen will erase the game history and change the starting position
* for resetBoard. To keep history and starting position: omit fen from the given config and call
* loadPgn with a pgn instead.
*
* @param config - a subset of config options, eg. `{ viewOnly: true, animation: { enabled: false } }`
* or `{ movable: { events: { after: afterFunc }, showDests: false }, drawable: { enabled: false } }`
* @param fillDefaults - if true unprovided config options will be substituted with default values, if
* false the unprovided options will remain unchanged.
*/
setConfig(config: BoardConfig, fillDefaults = false): void {
```

## Example Board API Usage
Expand Down
170 changes: 167 additions & 3 deletions docs/board-props.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
<script setup>
import { TheChessboard } from '../dist/vue3-chessboard';
import { reactive } from 'vue';

const boardConfig = {
coordinates: false,
autoCastle: false,
orientation: 'black',
};

const boardConfig2 = reactive({
coordinates: true,
viewOnly: false,
animation: { enabled: true },
draggable: { enabled: true },
});
</script>

# Board props

## Configure the chessboard
Available props:
- `board-config`
- `player-color`
- `reactive-config`

## `board-config`: Configure the chessboard

To edit the chessboard you can pass a configuration object to the component.
Here are all the available options:
Expand Down Expand Up @@ -150,7 +162,7 @@ max-width: 90%;
}
</style>

## Configure the board for multiplayer
## `player-color`: Configure the board for multiplayer

The board can accept a player-color prop to denote the color that the corresponding client should be allowed to play. Moves from a players opponent can be applied to the board with the `BoardApi`'s `move` method - the turns will switch once the `move` method is called with a valid sen string. If no value is provided, turns will switch locally.

Expand Down Expand Up @@ -179,4 +191,156 @@ function onRecieveMove(move: string) {
:player-color="playerColor"
/>
</template>
```
```


## `reactive-config`: Using a reactive config object

The `TheChessboard` component can accept a `reactive-config` prop to allow the `board-config` prop to be reactive to changes. Any mutations of the `board-config` prop will propagate to changes of the board config. This works with nested properties in a non-destructive way, ie. setting `boardConfig.draggable = { distance: 10, showGhost: false }` won't affect the other properties of `draggable` on the actual board config, such as `draggable.enabled`. However, it will change the "default state" of the board so that if `boardAPI.resetBoard()` is called the current state of the `board-config` prop is considered to be the provided config, as if it was passed at the time of instantiation of the `TheChessboard` component.

Note that prop mutation is a *one-way flow of data*, so the state of the `board-config` prop won't necessarily reflect the state of the actual board config. For example, as the game progresses the `fen` property of the `board-config` prop **will not** update.

See the following example for how one might make use of this feature:

::: code-group

```vue [TypeScript]
<script setup lang="ts">
import { reactive } from 'vue';
import { TheChessboard, type BoardConfig } from 'vue3-chessboard';
import 'vue3-chessboard/style.css';

const boardConfig: BoardConfig = reactive({
coordinates: true,
viewOnly: false,
animation: { enabled: true },
draggable: { enabled: true },
});
</script>

<template>
<TheChessboard
:board-config="boardConfig"
reactive-config
/>
<div class="buttons">
<button @click="boardConfig.coordinates = !boardConfig.coordinates">
Toggle coordinates
</button>
<button @click="boardConfig.viewOnly = !boardConfig.viewOnly">
Toggle view only
</button>
<button
@click="boardConfig.animation!.enabled = !boardConfig.animation!.enabled"
>
Toggle animations
</button>
<button
@click="boardConfig.draggable!.enabled = !boardConfig.draggable!.enabled"
>
Toggle draggable
</button>
</div>
</template>

<style scoped>
.buttons {
padding: 5px;
text-align: center;
}
.buttons button {
border-radius: 5px;
margin: 5px;
padding: 5px;
}
</style>
```

```vue [JavaScript]
<script setup>
import { reactive } from 'vue';
import { TheChessboard } from 'vue3-chessboard';
import 'vue3-chessboard/style.css';

const boardConfig = reactive({
coordinates: true,
viewOnly: false,
animation: { enabled: true },
draggable: { enabled: true },
});
</script>

<template>
<TheChessboard
:board-config="boardConfig"
reactive-config
/>
<div class="buttons">
<button @click="boardConfig.coordinates = !boardConfig.coordinates">
Toggle coordinates
</button>
<button @click="boardConfig.viewOnly = !boardConfig.viewOnly">
Toggle view only
</button>
<button
@click="boardConfig.animation.enabled = !boardConfig.animation.enabled"
>
Toggle animations
</button>
<button
@click="boardConfig.draggable.enabled = !boardConfig.draggable.enabled"
>
Toggle draggable
</button>
</div>
</template>

<style scoped>
.buttons {
padding: 5px;
text-align: center;
}
.buttons button {
border-radius: 5px;
margin: 5px;
padding: 5px;
}
</style>
```

:::

The board should then look like this:

<div>
<TheChessboard
:board-config="boardConfig2"
reactive-config
/>
<div class="buttons">
<button
@click="boardConfig2.coordinates = !boardConfig2.coordinates"
:class="{ activated: boardConfig2.coordinates }"
>
Toggle coordinates
</button>
<button
@click="boardConfig2.viewOnly = !boardConfig2.viewOnly"
:class="{ activated: !boardConfig2.viewOnly }"
>
Toggle view only
</button>
<button
@click="boardConfig2.animation.enabled = !boardConfig2.animation.enabled"
:class="{ activated: boardConfig2.animation.enabled }"
>
Toggle animations
</button>
<button
@click="boardConfig2.draggable.enabled = !boardConfig2.draggable.enabled"
:class="{ activated: boardConfig2.draggable.enabled }"
>
Toggle draggable
</button>
</div>
</div>
Loading