@connectorvol/chess-widgets 8.0.1 → 9.0.0

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 (47) hide show
  1. package/dist/constants/default-board-appearance-settings.d.ts +9 -0
  2. package/dist/constants/default-board-appearance-settings.js +30 -0
  3. package/dist/constants/editable-board-settings.d.ts +3 -21
  4. package/dist/constants/editable-board-settings.js +24 -19
  5. package/dist/game-analyzer/GameAnalyzer.svelte +74 -70
  6. package/dist/game-analyzer/gameAnalyzer.svelte.js +8 -6
  7. package/dist/game-analyzer/types.d.ts +11 -3
  8. package/dist/index.d.ts +9 -1
  9. package/dist/index.js +6 -0
  10. package/dist/position-editor/EditPanel.svelte +9 -6
  11. package/dist/puzzle/puzzleCreatedPayload.d.ts +17 -0
  12. package/dist/puzzle/puzzleData.d.ts +4 -0
  13. package/dist/puzzle/puzzleData.js +10 -0
  14. package/dist/puzzle/puzzlePreviewConstants.d.ts +4 -0
  15. package/dist/puzzle/puzzlePreviewConstants.js +4 -0
  16. package/dist/puzzle/puzzlePreviewPathNags.d.ts +6 -0
  17. package/dist/puzzle/puzzlePreviewPathNags.js +35 -0
  18. package/dist/puzzle/puzzleSolverForkAnnotations.d.ts +2 -4
  19. package/dist/puzzle/puzzleSolverForkAnnotations.js +13 -22
  20. package/dist/puzzle/puzzleStepPreviewSolver.d.ts +13 -1
  21. package/dist/puzzle/puzzleStepPreviewSolver.js +69 -9
  22. package/dist/puzzle/syncPuzzleBranchNags.d.ts +14 -0
  23. package/dist/puzzle/syncPuzzleBranchNags.js +125 -0
  24. package/dist/puzzle-creation/OpeningTagHoverPreview.svelte +81 -0
  25. package/dist/puzzle-creation/OpeningTagHoverPreview.svelte.d.ts +11 -0
  26. package/dist/puzzle-creation/PuzzleBoardTreeViewerPane.svelte +104 -32
  27. package/dist/puzzle-creation/PuzzleBoardTreeViewerPane.svelte.d.ts +16 -2
  28. package/dist/puzzle-creation/PuzzleCreationWizard.svelte +192 -202
  29. package/dist/puzzle-creation/PuzzleCreationWizard.svelte.d.ts +47 -3
  30. package/dist/puzzle-creation/PuzzlePgnBoardTreeEditor.svelte +485 -74
  31. package/dist/puzzle-creation/PuzzleWizardTagsStep.svelte +36 -0
  32. package/dist/puzzle-creation/PuzzleWizardTagsStep.svelte.d.ts +12 -0
  33. package/dist/puzzle-creation/StepMoves.svelte +38 -18
  34. package/dist/puzzle-creation/StepMoves.svelte.d.ts +2 -1
  35. package/dist/puzzle-creation/StepPosition.svelte +15 -9
  36. package/dist/puzzle-creation/StepPreview.svelte +24 -11
  37. package/dist/puzzle-creation/StepPreview.svelte.d.ts +3 -1
  38. package/dist/puzzle-creation/StepTags.svelte +270 -0
  39. package/dist/puzzle-creation/StepTags.svelte.d.ts +19 -0
  40. package/dist/puzzle-creation/buildPuzzleWizardBoardSettings.d.ts +9 -0
  41. package/dist/puzzle-creation/buildPuzzleWizardBoardSettings.js +19 -0
  42. package/dist/puzzle-creation/createPuzzleLineEditingBoard.d.ts +10 -3
  43. package/dist/puzzle-creation/createPuzzleLineEditingBoard.js +14 -9
  44. package/dist/puzzle-creation/puzzleWizardState.d.ts +35 -0
  45. package/dist/puzzle-creation/puzzleWizardState.js +37 -0
  46. package/dist/puzzle-creation/types.d.ts +37 -7
  47. package/package.json +20 -17
@@ -1,212 +1,202 @@
1
1
  <script lang="ts" module>
2
- export type { TPuzzleCreationWizardProps } from "./types.js";
2
+ export type { TPuzzleCreationWizardProps } from "./types.js";
3
+ export type {
4
+ TPuzzleWizardCoreState,
5
+ TPuzzleWizardState,
6
+ } from "./puzzleWizardState.js";
3
7
  </script>
4
8
 
5
- <script lang="ts">
6
- import { untrack } from "svelte";
7
-
8
- import StepMoves from "./StepMoves.svelte";
9
- import StepPosition from "./StepPosition.svelte";
10
- import StepPreview from "./StepPreview.svelte";
11
- import type { TPuzzleCreationWizardProps } from "./types.js";
12
- import {
13
- createEmptyTreeFromFen,
14
- createInitialPuzzleData,
15
- type PuzzleData,
16
- } from "../puzzle/puzzleData.js";
17
- import { PgnOps } from "@connectorvol/chessops/pgnOps.svelte";
18
- import { ChessTree, createPgnFromTree } from "@connectorvol/tree";
19
- import {
20
- CHESSBOARD_THEMES,
21
- Draggable,
22
- type IChessBoardActions,
23
- } from "@connectorvol/chessboard";
24
- import { calculatePly, Color, Square } from "@connectorvol/shared";
25
-
26
- import { createPuzzleLineEditingBoardApi } from "./createPuzzleLineEditingBoard.js";
27
-
28
- const {
29
- onPuzzleCreated,
30
- fen: fenProp,
31
- boardTheme,
32
- boardAppearanceSettings,
33
- }: TPuzzleCreationWizardProps = $props();
34
-
35
- /**
36
- * Представляет нормализацию входного FEN из пропса (пустая строка трактуется как отсутствие значения).
37
- */
38
- function wizardSeedFen(prop: string | undefined): string | undefined {
39
- const t = prop?.trim();
40
- return t ? t : undefined;
41
- }
42
-
43
- let step = $state<1 | 2 | 3>(1);
44
- let puzzleData = $derived<PuzzleData>(
45
- createInitialPuzzleData(wizardSeedFen(fenProp)),
46
- );
47
-
48
- /** Возвращает PGN дерева решения для превью на шаге 3. */
49
- let solutionPgnForPreview = $state("");
50
-
51
- function handleMovesBack() {
52
- step = 1;
53
- }
54
-
55
- function handleMovesNext(moves: string[]) {
56
- puzzleData.moves = moves;
57
- solutionPgnForPreview = createPgnFromTree(tree.rootNode);
58
- step = 3;
59
- }
60
-
61
- function handlePreviewBack() {
62
- step = 2;
63
- }
64
-
65
- let chess = $derived(new PgnOps(puzzleData.initialFen, "chess"));
66
- let tree = $derived(
67
- new ChessTree(createEmptyTreeFromFen(puzzleData.initialFen)),
68
- );
69
- const addMoveToTree = (san: string) => {
70
- const move = chess.makeSanMove(san);
71
- if (!move) return;
9
+ <script lang="ts" generics="S extends TPuzzleWizardCoreState">
10
+ import type { Snippet } from "svelte";
11
+
12
+ import { Wizard } from "@connectorvol/shared";
13
+ import type { TWizardStep, TWizardStepContext } from "@connectorvol/shared";
14
+ import StepMoves from "./StepMoves.svelte";
15
+ import StepPosition from "./StepPosition.svelte";
16
+ import StepPreview from "./StepPreview.svelte";
17
+ import type { TPuzzleCreatedPayload } from "../puzzle/puzzleCreatedPayload.js";
18
+ import type { TPuzzleWizardCoreState } from "./puzzleWizardState.js";
19
+ import { PUZZLE_WIZARD_CORE_STEPS } from "./puzzleWizardState.js";
20
+ import { createEmptyTreeFromFen } from "../puzzle/puzzleData.js";
21
+ import { PgnOps } from "@connectorvol/chessops/pgnOps.svelte";
22
+ import { ChessTree, createPgnFromTree } from "@connectorvol/tree";
23
+ import {
24
+ CHESSBOARD_THEMES,
25
+ Draggable,
26
+ type ChessboardTheme,
27
+ type IChessBoardActions,
28
+ } from "@connectorvol/chessboard";
29
+ import { calculatePly, Color, Square } from "@connectorvol/shared";
30
+
31
+ import { createPuzzleLineEditingBoardApi } from "./createPuzzleLineEditingBoard.js";
32
+ import { syncPuzzleBranchNagsOnTree } from "../puzzle/syncPuzzleBranchNags.js";
33
+ import { DEFAULT_BOARD_APPEARANCE_SETTINGS } from "../constants/default-board-appearance-settings.js";
34
+ import type { TChessboardAppearanceSettings } from "./types.js";
35
+
36
+ interface Props {
37
+ /** Возвращает общий state визарда (двухсторонняя привязка). */
38
+ wizardState: S;
39
+ /** Возвращает колбэк завершения с шага превью без доп. шагов. */
40
+ onPuzzleCreated: (payload: TPuzzleCreatedPayload) => void;
41
+ /** Возвращает колбэк завершения с доп. шага (`wizard.done()`). */
42
+ onDone?: (state: S) => void;
43
+ /** Возвращает seed FEN для сброса шага визарда при изменении. */
44
+ fen?: string;
45
+ /** Возвращает тему оформления шахматной доски. */
46
+ boardTheme?: ChessboardTheme;
47
+ /** Возвращает визуальные настройки доски. */
48
+ boardAppearanceSettings?: TChessboardAppearanceSettings;
49
+ /** Возвращает дополнительные шаги после превью. */
50
+ additionalSteps?: readonly TWizardStep[];
51
+ /** Возвращает snippet дополнительных шагов. */
52
+ additionalStep?: Snippet<[TWizardStepContext<S>]>;
53
+ }
54
+
55
+ let {
56
+ wizardState = $bindable(),
57
+ onPuzzleCreated,
58
+ onDone,
59
+ fen: fenProp,
60
+ boardTheme,
61
+ boardAppearanceSettings = DEFAULT_BOARD_APPEARANCE_SETTINGS,
62
+ additionalSteps = [],
63
+ additionalStep,
64
+ }: Props = $props();
65
+
66
+ const hasAdditionalSteps = $derived(additionalSteps.length > 0);
67
+ const steps = $derived([...PUZZLE_WIZARD_CORE_STEPS, ...additionalSteps]);
68
+
69
+ let chess = $derived(
70
+ new PgnOps(wizardState.puzzleData.initialFen, "chess"),
71
+ );
72
+ let tree = $derived(
73
+ new ChessTree(createEmptyTreeFromFen(wizardState.puzzleData.initialFen)),
74
+ );
75
+
76
+ const addMoveToTree = (san: string) => {
77
+ const move = chess.makeSanMove(san);
78
+ if (!move) return;
79
+ const fen = chess.fen();
80
+ const { halfMoves, fullMoves } = calculatePly(fen);
81
+ tree.addNodeToCurrent({
82
+ id: "",
83
+ children: [],
84
+ data: {
85
+ fen,
86
+ san,
87
+ ply: halfMoves,
88
+ fullMoves,
89
+ },
90
+ });
91
+ return { move, fen, turn: chess.turn() };
92
+ };
93
+
94
+ const actions: IChessBoardActions = {
95
+ game: {
96
+ possibleMovesOnSquare: (square: Square) => chess.moves(square),
97
+ beforePieceMoveSan(san: string) {
98
+ const result = addMoveToTree(san);
99
+ return result;
100
+ },
101
+ afterPieceMoveSan: () => {},
102
+ beforePieceMove: (from, to, promotion) => {
103
+ const san = chess.getSanForMove({ from, to, promotion });
104
+ chess.makeMove({ from, to, promotion });
72
105
  const fen = chess.fen();
73
106
  const { halfMoves, fullMoves } = calculatePly(fen);
74
107
  tree.addNodeToCurrent({
75
- id: "",
76
- children: [],
77
- data: {
78
- fen,
79
- san,
80
- ply: halfMoves,
81
- fullMoves,
82
- },
83
- });
84
- return { move, fen, turn: chess.turn() };
85
- };
86
-
87
- const actions: IChessBoardActions = {
88
- game: {
89
- possibleMovesOnSquare: (square: Square) => chess.moves(square),
90
- beforePieceMoveSan(san: string) {
91
- const result = addMoveToTree(san);
92
- return result;
93
- },
94
- afterPieceMoveSan: () => {},
95
- beforePieceMove: (from, to, promotion) => {
96
- const san = chess.getSanForMove({ from, to, promotion });
97
- chess.makeMove({ from, to, promotion });
98
- const fen = chess.fen();
99
- const { halfMoves, fullMoves } = calculatePly(fen);
100
- tree.addNodeToCurrent({
101
- id: "",
102
- children: [],
103
- data: {
104
- fen,
105
- san,
106
- ply: halfMoves,
107
- fullMoves,
108
- },
109
- });
110
- return fen;
111
- },
112
- afterPieceMove: () => {
113
- const side = chess.turn();
114
- chessboard.draggable =
115
- side === Color.WHITE ? Draggable.WHITE : Draggable.BLACK;
116
- },
117
- },
118
- };
119
-
120
- /**
121
- * Представляет сборку доски для шага построения линии: позиция и ориентация по стороне хода в FEN.
122
- */
123
- function createMainChessboard(fullFen: string) {
124
- return createPuzzleLineEditingBoardApi(fullFen, actions, {
125
- boardTheme: boardTheme ?? CHESSBOARD_THEMES.blue,
126
- boardAppearanceSettings,
127
- });
128
- }
129
-
130
- let chessboard = $derived(createMainChessboard(puzzleData.initialFen));
131
-
132
- /**
133
- * Представляет сброс мастера при смене входного FEN извне (шаг 1 и черновик ходов обнуляются).
134
- */
135
- $effect(() => {
136
- const seed = wizardSeedFen(fenProp);
137
- const next = createInitialPuzzleData(seed);
138
- untrack(() => {
139
- puzzleData = next;
140
- step = 1;
141
- solutionPgnForPreview = "";
108
+ id: "",
109
+ children: [],
110
+ data: {
111
+ fen,
112
+ san,
113
+ ply: halfMoves,
114
+ fullMoves,
115
+ },
142
116
  });
117
+ return fen;
118
+ },
119
+ afterPieceMove: () => {
120
+ const side = chess.turn();
121
+ chessboardApi.draggable =
122
+ side === Color.WHITE ? Draggable.WHITE : Draggable.BLACK;
123
+ },
124
+ },
125
+ };
126
+
127
+ /**
128
+ * Представляет сборку доски для шага построения линии: позиция и ориентация по стороне хода в FEN.
129
+ */
130
+ function createMainChessboard(fullFen: string) {
131
+ return createPuzzleLineEditingBoardApi(fullFen, actions, {
132
+ boardTheme: boardTheme ?? CHESSBOARD_THEMES.blue,
133
+ boardAppearanceSettings,
143
134
  });
144
-
145
- function handlePositionNext(fen: string) {
146
- puzzleData.initialFen = fen;
147
- step = 2;
148
- }
135
+ }
136
+
137
+ let chessboard = $derived(
138
+ createMainChessboard(wizardState.puzzleData.initialFen),
139
+ );
140
+ let chessboardApi = $derived(chessboard.api);
141
+ let chessboardDesign = $derived(chessboard.design);
142
+
143
+ /**
144
+ * Представляет переход со шага построения линии на превью.
145
+ */
146
+ function handleMovesNext(moves: string[]) {
147
+ wizardState.puzzleData.moves = moves;
148
+ syncPuzzleBranchNagsOnTree(
149
+ tree,
150
+ wizardState.puzzleData.initialFen.trim().split(/\s+/)[1] === "b"
151
+ ? Color.BLACK
152
+ : Color.WHITE,
153
+ );
154
+ wizardState.solutionPgn = createPgnFromTree(tree.rootNode);
155
+ }
149
156
  </script>
150
157
 
151
- <div class="mx-4 lg:container lg:mx-auto">
152
- <div class="flex flex-col gap-4 pt-4 pb-0">
153
- <div class="flex items-center gap-2">
154
- <span
155
- class="flex h-8 w-8 items-center justify-center rounded-full text-sm font-medium"
156
- class:bg-primary={step >= 1}
157
- class:bg-muted={step < 1}
158
- class:text-primary-foreground={step >= 1}
159
- >
160
- 1
161
- </span>
162
- <span class="text-sm">Позиция</span>
163
- <span class="h-px flex-1 bg-border"></span>
164
- <span
165
- class="flex h-8 w-8 items-center justify-center rounded-full text-sm font-medium"
166
- class:bg-primary={step >= 2}
167
- class:bg-muted={step < 2}
168
- class:text-primary-foreground={step >= 2}
169
- >
170
- 2
171
- </span>
172
- <span class="text-sm">Ходы</span>
173
- <span class="h-px flex-1 bg-border"></span>
174
- <span
175
- class="flex h-8 w-8 items-center justify-center rounded-full text-sm font-medium"
176
- class:bg-primary={step >= 3}
177
- class:bg-muted={step < 3}
178
- class:text-primary-foreground={step >= 3}
179
- >
180
- 3
181
- </span>
182
- <span class="text-sm">Превью</span>
183
- </div>
184
-
185
- {#if step === 1}
186
- <StepPosition
187
- initialFen={puzzleData.initialFen}
188
- onNext={handlePositionNext}
189
- {boardTheme}
190
- {boardAppearanceSettings}
191
- />
192
- {:else if step === 2}
193
- <StepMoves
194
- {puzzleData}
195
- {chess}
196
- {tree}
197
- {chessboard}
198
- onBack={handleMovesBack}
199
- onNext={handleMovesNext}
200
- />
201
- {:else}
202
- <StepPreview
203
- {puzzleData}
204
- solutionPgn={solutionPgnForPreview}
205
- onBack={handlePreviewBack}
206
- {onPuzzleCreated}
207
- {boardTheme}
208
- {boardAppearanceSettings}
209
- />
210
- {/if}
211
- </div>
212
- </div>
158
+ <Wizard
159
+ bind:wizardState={wizardState}
160
+ {steps}
161
+ resetSignal={fenProp}
162
+ {onDone}
163
+ >
164
+ {#snippet children(w)}
165
+ {#if w.currentStep === 1}
166
+ <StepPosition
167
+ initialFen={w.state.puzzleData.initialFen}
168
+ onNext={(fen) => {
169
+ w.state.puzzleData.initialFen = fen;
170
+ w.next();
171
+ }}
172
+ {boardTheme}
173
+ {boardAppearanceSettings}
174
+ />
175
+ {:else if w.currentStep === 2}
176
+ <StepMoves
177
+ puzzleData={w.state.puzzleData}
178
+ {chess}
179
+ {tree}
180
+ chessboard={chessboardApi}
181
+ {chessboardDesign}
182
+ onBack={w.back}
183
+ onNext={(moves) => {
184
+ handleMovesNext(moves);
185
+ w.next();
186
+ }}
187
+ />
188
+ {:else if w.currentStep === 3}
189
+ <StepPreview
190
+ puzzleData={w.state.puzzleData}
191
+ solutionPgn={w.state.solutionPgn}
192
+ onBack={w.back}
193
+ onNext={hasAdditionalSteps ? w.next : undefined}
194
+ onPuzzleCreated={hasAdditionalSteps ? undefined : onPuzzleCreated}
195
+ {boardTheme}
196
+ {boardAppearanceSettings}
197
+ />
198
+ {:else if additionalStep}
199
+ {@render additionalStep(w)}
200
+ {/if}
201
+ {/snippet}
202
+ </Wizard>
@@ -1,5 +1,49 @@
1
1
  export type { TPuzzleCreationWizardProps } from "./types.js";
2
- import type { TPuzzleCreationWizardProps } from "./types.js";
3
- declare const PuzzleCreationWizard: import("svelte").Component<TPuzzleCreationWizardProps, {}, "">;
4
- type PuzzleCreationWizard = ReturnType<typeof PuzzleCreationWizard>;
2
+ export type { TPuzzleWizardCoreState, TPuzzleWizardState, } from "./puzzleWizardState.js";
3
+ import type { Snippet } from "svelte";
4
+ import type { TWizardStep, TWizardStepContext } from "@connectorvol/shared";
5
+ import type { TPuzzleCreatedPayload } from "../puzzle/puzzleCreatedPayload.js";
6
+ import type { TPuzzleWizardCoreState } from "./puzzleWizardState.js";
7
+ import { type ChessboardTheme } from "@connectorvol/chessboard";
8
+ import type { TChessboardAppearanceSettings } from "./types.js";
9
+ declare function $$render<S extends TPuzzleWizardCoreState>(): {
10
+ props: {
11
+ /** Возвращает общий state визарда (двухсторонняя привязка). */
12
+ wizardState: S;
13
+ /** Возвращает колбэк завершения с шага превью без доп. шагов. */
14
+ onPuzzleCreated: (payload: TPuzzleCreatedPayload) => void;
15
+ /** Возвращает колбэк завершения с доп. шага (`wizard.done()`). */
16
+ onDone?: (state: S) => void;
17
+ /** Возвращает seed FEN для сброса шага визарда при изменении. */
18
+ fen?: string;
19
+ /** Возвращает тему оформления шахматной доски. */
20
+ boardTheme?: ChessboardTheme;
21
+ /** Возвращает визуальные настройки доски. */
22
+ boardAppearanceSettings?: TChessboardAppearanceSettings;
23
+ /** Возвращает дополнительные шаги после превью. */
24
+ additionalSteps?: readonly TWizardStep[];
25
+ /** Возвращает snippet дополнительных шагов. */
26
+ additionalStep?: Snippet<[TWizardStepContext<S>]>;
27
+ };
28
+ exports: {};
29
+ bindings: "wizardState";
30
+ slots: {};
31
+ events: {};
32
+ };
33
+ declare class __sveltets_Render<S extends TPuzzleWizardCoreState> {
34
+ props(): ReturnType<typeof $$render<S>>['props'];
35
+ events(): ReturnType<typeof $$render<S>>['events'];
36
+ slots(): ReturnType<typeof $$render<S>>['slots'];
37
+ bindings(): "wizardState";
38
+ exports(): {};
39
+ }
40
+ interface $$IsomorphicComponent {
41
+ new <S extends TPuzzleWizardCoreState>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<S>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<S>['props']>, ReturnType<__sveltets_Render<S>['events']>, ReturnType<__sveltets_Render<S>['slots']>> & {
42
+ $$bindings?: ReturnType<__sveltets_Render<S>['bindings']>;
43
+ } & ReturnType<__sveltets_Render<S>['exports']>;
44
+ <S extends TPuzzleWizardCoreState>(internal: unknown, props: ReturnType<__sveltets_Render<S>['props']> & {}): ReturnType<__sveltets_Render<S>['exports']>;
45
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
46
+ }
47
+ declare const PuzzleCreationWizard: $$IsomorphicComponent;
48
+ type PuzzleCreationWizard<S extends TPuzzleWizardCoreState> = InstanceType<typeof PuzzleCreationWizard<S>>;
5
49
  export default PuzzleCreationWizard;