@connectorvol/chess-widgets 9.0.0 → 9.0.1
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.
- package/dist/(components)/BoardSettingsTrigger.svelte +10 -0
- package/dist/(components)/BoardSettingsTrigger.svelte.d.ts +18 -0
- package/dist/game-analyzer/GameAnalyzer.svelte +88 -74
- package/dist/game-analyzer/gameAnalyzer.svelte.js +2 -7
- package/dist/game-analyzer/types.d.ts +3 -6
- package/dist/index.d.ts +1 -1
- package/dist/puzzle/puzzlePreviewPathNags.js +1 -1
- package/dist/puzzle-creation/PuzzleBoardTreeViewerPane.svelte +199 -171
- package/dist/puzzle-creation/PuzzleBoardTreeViewerPane.svelte.d.ts +7 -3
- package/dist/puzzle-creation/PuzzleCreationWizard.svelte +184 -180
- package/dist/puzzle-creation/PuzzlePgnBoardTreeEditor.svelte +906 -870
- package/dist/puzzle-creation/StepMoves.svelte +209 -207
- package/dist/puzzle-creation/StepMoves.svelte.d.ts +1 -2
- package/dist/puzzle-creation/StepPosition.svelte +22 -2
- package/dist/puzzle-creation/puzzleWizardState.js +1 -1
- package/dist/puzzle-creation/types.d.ts +0 -4
- package/package.json +12 -10
|
@@ -1,219 +1,221 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
chessboard:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
tree
|
|
42
|
-
chessboard,
|
|
43
|
-
chessboardDesign,
|
|
44
|
-
}: Props = $props();
|
|
45
|
-
|
|
46
|
-
const initialTurn = $derived(
|
|
47
|
-
puzzleData.initialFen.trim().split(/\s+/)[1] === "b"
|
|
48
|
-
? Color.BLACK
|
|
49
|
-
: Color.WHITE,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const mainLine = $derived(getMainLineFromTree(tree.rootNode));
|
|
53
|
-
|
|
54
|
-
function setChessFen(fen: string) {
|
|
55
|
-
chess.setFen(fen);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function setChessboardFen(_animationTime: number | undefined) {
|
|
59
|
-
chessboard.fen = chess.fen();
|
|
60
|
-
const side = chess.turn();
|
|
61
|
-
chessboard.draggable =
|
|
62
|
-
side === Color.WHITE ? Draggable.WHITE : Draggable.BLACK;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function onSelectNode() {
|
|
66
|
-
setChessFen(tree.currentNode.data.fen);
|
|
67
|
-
setChessboardFen(0);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function onDeleteVariant() {
|
|
71
|
-
setChessFen(tree.currentNode.data.fen);
|
|
72
|
-
setChessboardFen(0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const canGoNext = $derived(mainLine.length >= 1 && mainLine.length % 2 === 1);
|
|
76
|
-
|
|
77
|
-
const solverForkAnnotations = $derived(
|
|
78
|
-
validatePuzzleSolverForkAnnotations(tree, initialTurn),
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const canProceedToNextStep = $derived(canGoNext && solverForkAnnotations.ok);
|
|
82
|
-
|
|
83
|
-
/** Представляет автоматическую разметку ✓/✗ на развилках решателя после каждой правки дерева. */
|
|
84
|
-
$effect(() => {
|
|
85
|
-
void tree.mutationVersion;
|
|
86
|
-
untrack(() => {
|
|
87
|
-
syncPuzzleBranchNagsOnTree(tree, initialTurn);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
2
|
+
import type { BoardApi } from "@connectorvol/chessboard";
|
|
3
|
+
|
|
4
|
+
import { Draggable } from "@connectorvol/chessboard";
|
|
5
|
+
import type { ChessTree } from "@connectorvol/tree";
|
|
6
|
+
|
|
7
|
+
import { Color } from "@connectorvol/shared";
|
|
8
|
+
import { Popover } from "bits-ui";
|
|
9
|
+
|
|
10
|
+
import { buttonVariants } from "../button-variants.js";
|
|
11
|
+
import PuzzleBoardTreeViewerPane from "./PuzzleBoardTreeViewerPane.svelte";
|
|
12
|
+
import { cn } from "../utils.js";
|
|
13
|
+
|
|
14
|
+
import type { PgnOps } from "@connectorvol/chessops/pgnOps.svelte";
|
|
15
|
+
import {
|
|
16
|
+
getMainLineFromTree,
|
|
17
|
+
type PuzzleData,
|
|
18
|
+
} from "../puzzle/puzzleData.js";
|
|
19
|
+
import { validatePuzzleSolverForkAnnotations } from "../puzzle/puzzleSolverForkAnnotations.js";
|
|
20
|
+
import { syncPuzzleBranchNagsOnTree } from "../puzzle/syncPuzzleBranchNags.js";
|
|
21
|
+
import { untrack } from "svelte";
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
puzzleData: PuzzleData;
|
|
25
|
+
onBack: () => void;
|
|
26
|
+
onNext: (moves: string[]) => void;
|
|
27
|
+
chess: PgnOps;
|
|
28
|
+
tree: ChessTree;
|
|
29
|
+
chessboard: BoardApi;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { puzzleData, onBack, onNext, chess, tree, chessboard }: Props =
|
|
33
|
+
$props();
|
|
34
|
+
|
|
35
|
+
const initialTurn = $derived(
|
|
36
|
+
puzzleData.initialFen.trim().split(/\s+/)[1] === "b"
|
|
37
|
+
? Color.BLACK
|
|
38
|
+
: Color.WHITE,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const mainLine = $derived(getMainLineFromTree(tree.rootNode));
|
|
90
42
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!canGoNext && mainLine.length > 0) {
|
|
94
|
-
return `Последний ход должна сделать сторона, которая начинала. Добавьте ещё один ход за ${initialTurn === Color.WHITE ? "белых" : "чёрных"}.`;
|
|
43
|
+
function setChessFen(fen: string) {
|
|
44
|
+
chess.setFen(fen);
|
|
95
45
|
}
|
|
96
|
-
|
|
97
|
-
|
|
46
|
+
|
|
47
|
+
function setChessboardFen(_animationTime: number | undefined) {
|
|
48
|
+
chessboard.fen = chess.fen();
|
|
49
|
+
const side = chess.turn();
|
|
50
|
+
chessboard.draggable =
|
|
51
|
+
side === Color.WHITE ? Draggable.WHITE : Draggable.BLACK;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function onSelectNode() {
|
|
55
|
+
setChessFen(tree.currentNode.data.fen);
|
|
56
|
+
setChessboardFen(0);
|
|
98
57
|
}
|
|
99
|
-
return null;
|
|
100
|
-
});
|
|
101
58
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
59
|
+
function onDeleteVariant() {
|
|
60
|
+
setChessFen(tree.currentNode.data.fen);
|
|
61
|
+
setChessboardFen(0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const canGoNext = $derived(
|
|
65
|
+
mainLine.length >= 1 && mainLine.length % 2 === 1,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const solverForkAnnotations = $derived(
|
|
69
|
+
validatePuzzleSolverForkAnnotations(tree, initialTurn),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const canProceedToNextStep = $derived(
|
|
73
|
+
canGoNext && solverForkAnnotations.ok,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
/** Представляет автоматическую разметку ✓/✗ на развилках решателя после каждой правки дерева. */
|
|
77
|
+
$effect(() => {
|
|
78
|
+
void tree.mutationVersion;
|
|
79
|
+
untrack(() => {
|
|
80
|
+
syncPuzzleBranchNagsOnTree(tree, initialTurn);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/** Текст предупреждения по шагу для кнопки «!» (если пусто — предупреждений нет). */
|
|
85
|
+
const stepIssueMessage = $derived.by(() => {
|
|
86
|
+
if (!canGoNext && mainLine.length > 0) {
|
|
87
|
+
return `Последний ход должна сделать сторона, которая начинала. Добавьте ещё один ход за ${initialTurn === Color.WHITE ? "белых" : "чёрных"}.`;
|
|
88
|
+
}
|
|
89
|
+
if (canGoNext && !solverForkAnnotations.ok) {
|
|
90
|
+
return solverForkAnnotations.reason;
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
function handleNext() {
|
|
96
|
+
if (canProceedToNextStep) {
|
|
97
|
+
onNext(mainLine);
|
|
98
|
+
}
|
|
105
99
|
}
|
|
106
|
-
}
|
|
107
100
|
</script>
|
|
108
101
|
|
|
109
102
|
<div class="flex flex-col gap-3 pt-2 pb-0">
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
103
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
104
|
+
<h2 class="text-xl font-semibold">Шаг 2: Построение линии решения</h2>
|
|
105
|
+
<Popover.Root>
|
|
106
|
+
<Popover.Trigger type="button">
|
|
107
|
+
{#snippet child({ props })}
|
|
108
|
+
<button
|
|
109
|
+
{...props}
|
|
110
|
+
type="button"
|
|
111
|
+
class={cn(
|
|
112
|
+
buttonVariants({
|
|
113
|
+
variant: "outline",
|
|
114
|
+
size: "icon-sm",
|
|
115
|
+
}),
|
|
116
|
+
"size-7 shrink-0 rounded-full text-sm font-semibold",
|
|
117
|
+
)}
|
|
118
|
+
aria-label="Справка: построение линии решения"
|
|
119
|
+
>
|
|
120
|
+
?
|
|
121
|
+
</button>
|
|
122
|
+
{/snippet}
|
|
123
|
+
</Popover.Trigger>
|
|
124
|
+
<Popover.Portal>
|
|
125
|
+
<Popover.Content
|
|
126
|
+
side="bottom"
|
|
127
|
+
align="start"
|
|
128
|
+
sideOffset={8}
|
|
129
|
+
class={cn(
|
|
130
|
+
"bg-popover text-popover-foreground border-border z-50 max-h-[min(70vh,32rem)] w-[min(calc(100vw-2rem),28rem)] overflow-y-auto rounded-lg border p-4 text-sm shadow-md outline-none",
|
|
131
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
132
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
133
|
+
)}
|
|
134
|
+
>
|
|
135
|
+
<p class="text-muted-foreground leading-relaxed">
|
|
136
|
+
Делайте ходы за обе стороны. Последний ход должна
|
|
137
|
+
сделать сторона, которая начинала игру (ключевой ход). В
|
|
138
|
+
дереве можно выбирать ходы, добавлять комментарии и
|
|
139
|
+
символы оценки в режиме правки. Ходы главной линии
|
|
140
|
+
автоматически получают ✓ (верный ход), неверные ходы
|
|
141
|
+
решателя в вариациях — ✗; ходы соперника без этих меток.
|
|
142
|
+
Если от позиции решателя есть несколько вариантов хода,
|
|
143
|
+
главный вариант должен быть верным, остальные —
|
|
144
|
+
неверными. После ✓ главный вариант нужно довести до
|
|
145
|
+
позиции, где последним походил решатель. Если несколько
|
|
146
|
+
ответов соперника ведут из одной позиции, каждая такая
|
|
147
|
+
линия должна заканчиваться ходом решателя.
|
|
148
|
+
</p>
|
|
149
|
+
</Popover.Content>
|
|
150
|
+
</Popover.Portal>
|
|
151
|
+
</Popover.Root>
|
|
152
|
+
{#if stepIssueMessage}
|
|
153
|
+
<Popover.Root>
|
|
154
|
+
<Popover.Trigger type="button">
|
|
155
|
+
{#snippet child({ props })}
|
|
156
|
+
<button
|
|
157
|
+
{...props}
|
|
158
|
+
type="button"
|
|
159
|
+
class={cn(
|
|
160
|
+
buttonVariants({
|
|
161
|
+
variant: "outline",
|
|
162
|
+
size: "icon-sm",
|
|
163
|
+
}),
|
|
164
|
+
"size-7 shrink-0 rounded-full border-amber-600/60 text-sm font-semibold text-amber-600 dark:border-amber-400/60 dark:text-amber-400",
|
|
165
|
+
)}
|
|
166
|
+
aria-label="Предупреждение по условиям шага"
|
|
167
|
+
>
|
|
168
|
+
!
|
|
169
|
+
</button>
|
|
170
|
+
{/snippet}
|
|
171
|
+
</Popover.Trigger>
|
|
172
|
+
<Popover.Portal>
|
|
173
|
+
<Popover.Content
|
|
174
|
+
side="bottom"
|
|
175
|
+
align="start"
|
|
176
|
+
sideOffset={8}
|
|
177
|
+
class={cn(
|
|
178
|
+
"bg-popover text-popover-foreground border-border z-50 max-h-[min(70vh,32rem)] w-[min(calc(100vw-2rem),28rem)] overflow-y-auto rounded-lg border p-4 text-sm shadow-md outline-none",
|
|
179
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
180
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
<p
|
|
184
|
+
class="leading-relaxed text-amber-700 dark:text-amber-400"
|
|
185
|
+
>
|
|
186
|
+
{stepIssueMessage}
|
|
187
|
+
</p>
|
|
188
|
+
</Popover.Content>
|
|
189
|
+
</Popover.Portal>
|
|
190
|
+
</Popover.Root>
|
|
191
|
+
{/if}
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<PuzzleBoardTreeViewerPane
|
|
195
|
+
{chessboard}
|
|
196
|
+
chessTree={tree}
|
|
197
|
+
{onSelectNode}
|
|
198
|
+
{onDeleteVariant}
|
|
199
|
+
{setChessFen}
|
|
200
|
+
{setChessboardFen}
|
|
201
|
+
showPuzzleBranchNags={true}
|
|
202
|
+
/>
|
|
203
|
+
|
|
204
|
+
<div class="flex justify-between">
|
|
205
|
+
<button
|
|
206
|
+
type="button"
|
|
207
|
+
class={cn(buttonVariants({ variant: "outline" }))}
|
|
208
|
+
onclick={onBack}
|
|
209
|
+
>
|
|
210
|
+
Назад
|
|
211
|
+
</button>
|
|
212
|
+
<button
|
|
117
213
|
type="button"
|
|
118
|
-
class={cn(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
)}
|
|
122
|
-
aria-label="Справка: построение линии решения"
|
|
123
|
-
>
|
|
124
|
-
?
|
|
125
|
-
</button>
|
|
126
|
-
{/snippet}
|
|
127
|
-
</Popover.Trigger>
|
|
128
|
-
<Popover.Portal>
|
|
129
|
-
<Popover.Content
|
|
130
|
-
side="bottom"
|
|
131
|
-
align="start"
|
|
132
|
-
sideOffset={8}
|
|
133
|
-
class={cn(
|
|
134
|
-
"bg-popover text-popover-foreground border-border z-50 max-h-[min(70vh,32rem)] w-[min(calc(100vw-2rem),28rem)] overflow-y-auto rounded-lg border p-4 text-sm shadow-md outline-none",
|
|
135
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
136
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
137
|
-
)}
|
|
214
|
+
class={cn(buttonVariants({ variant: "default" }))}
|
|
215
|
+
onclick={handleNext}
|
|
216
|
+
disabled={!canProceedToNextStep}
|
|
138
217
|
>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
добавлять комментарии и символы оценки в режиме правки. Ходы главной
|
|
143
|
-
линии автоматически получают ✓ (верный ход), неверные ходы решателя
|
|
144
|
-
в вариациях — ✗; ходы соперника без этих меток. Если от позиции
|
|
145
|
-
решателя есть несколько вариантов хода, главный вариант должен быть
|
|
146
|
-
верным, остальные — неверными. После ✓ главный вариант нужно довести
|
|
147
|
-
до позиции, где последним походил решатель. Если несколько ответов
|
|
148
|
-
соперника ведут из одной позиции, каждая такая линия должна
|
|
149
|
-
заканчиваться ходом решателя.
|
|
150
|
-
</p>
|
|
151
|
-
</Popover.Content>
|
|
152
|
-
</Popover.Portal>
|
|
153
|
-
</Popover.Root>
|
|
154
|
-
{#if stepIssueMessage}
|
|
155
|
-
<Popover.Root>
|
|
156
|
-
<Popover.Trigger type="button">
|
|
157
|
-
{#snippet child({ props })}
|
|
158
|
-
<button
|
|
159
|
-
{...props}
|
|
160
|
-
type="button"
|
|
161
|
-
class={cn(
|
|
162
|
-
buttonVariants({ variant: "outline", size: "icon-sm" }),
|
|
163
|
-
"size-7 shrink-0 rounded-full border-amber-600/60 text-sm font-semibold text-amber-600 dark:border-amber-400/60 dark:text-amber-400",
|
|
164
|
-
)}
|
|
165
|
-
aria-label="Предупреждение по условиям шага"
|
|
166
|
-
>
|
|
167
|
-
!
|
|
168
|
-
</button>
|
|
169
|
-
{/snippet}
|
|
170
|
-
</Popover.Trigger>
|
|
171
|
-
<Popover.Portal>
|
|
172
|
-
<Popover.Content
|
|
173
|
-
side="bottom"
|
|
174
|
-
align="start"
|
|
175
|
-
sideOffset={8}
|
|
176
|
-
class={cn(
|
|
177
|
-
"bg-popover text-popover-foreground border-border z-50 max-h-[min(70vh,32rem)] w-[min(calc(100vw-2rem),28rem)] overflow-y-auto rounded-lg border p-4 text-sm shadow-md outline-none",
|
|
178
|
-
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
179
|
-
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
180
|
-
)}
|
|
181
|
-
>
|
|
182
|
-
<p class="leading-relaxed text-amber-700 dark:text-amber-400">
|
|
183
|
-
{stepIssueMessage}
|
|
184
|
-
</p>
|
|
185
|
-
</Popover.Content>
|
|
186
|
-
</Popover.Portal>
|
|
187
|
-
</Popover.Root>
|
|
188
|
-
{/if}
|
|
189
|
-
</div>
|
|
190
|
-
|
|
191
|
-
<PuzzleBoardTreeViewerPane
|
|
192
|
-
{chessboard}
|
|
193
|
-
{chessboardDesign}
|
|
194
|
-
chessTree={tree}
|
|
195
|
-
{onSelectNode}
|
|
196
|
-
{onDeleteVariant}
|
|
197
|
-
{setChessFen}
|
|
198
|
-
{setChessboardFen}
|
|
199
|
-
showPuzzleBranchNags={true}
|
|
200
|
-
/>
|
|
201
|
-
|
|
202
|
-
<div class="flex justify-between">
|
|
203
|
-
<button
|
|
204
|
-
type="button"
|
|
205
|
-
class={cn(buttonVariants({ variant: "outline" }))}
|
|
206
|
-
onclick={onBack}
|
|
207
|
-
>
|
|
208
|
-
Назад
|
|
209
|
-
</button>
|
|
210
|
-
<button
|
|
211
|
-
type="button"
|
|
212
|
-
class={cn(buttonVariants({ variant: "default" }))}
|
|
213
|
-
onclick={handleNext}
|
|
214
|
-
disabled={!canProceedToNextStep}
|
|
215
|
-
>
|
|
216
|
-
Далее
|
|
217
|
-
</button>
|
|
218
|
-
</div>
|
|
218
|
+
Далее
|
|
219
|
+
</button>
|
|
220
|
+
</div>
|
|
219
221
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BoardApi
|
|
1
|
+
import type { BoardApi } from "@connectorvol/chessboard";
|
|
2
2
|
import type { ChessTree } from "@connectorvol/tree";
|
|
3
3
|
import type { PgnOps } from "@connectorvol/chessops/pgnOps.svelte";
|
|
4
4
|
import { type PuzzleData } from "../puzzle/puzzleData.js";
|
|
@@ -9,7 +9,6 @@ interface Props {
|
|
|
9
9
|
chess: PgnOps;
|
|
10
10
|
tree: ChessTree;
|
|
11
11
|
chessboard: BoardApi;
|
|
12
|
-
chessboardDesign: TChessBoardDesignSettings;
|
|
13
12
|
}
|
|
14
13
|
declare const StepMoves: import("svelte").Component<Props, {}, "">;
|
|
15
14
|
type StepMoves = ReturnType<typeof StepMoves>;
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
Chessboard,
|
|
4
4
|
CHESSBOARD_THEMES,
|
|
5
5
|
createBoardApi,
|
|
6
|
+
DEFAULT_DESIGN_SETTINGS,
|
|
7
|
+
getBoardDesignSettingsContext,
|
|
6
8
|
type ChessboardTheme,
|
|
7
9
|
} from "@connectorvol/chessboard";
|
|
10
|
+
import { untrack } from "svelte";
|
|
8
11
|
|
|
9
12
|
import { DEFAULT_EDITABLE_BOARD_SETTINGS } from "../constants/editable-board-settings.js";
|
|
10
13
|
import EditFen from "../position-editor/EditFen.svelte";
|
|
@@ -49,6 +52,19 @@
|
|
|
49
52
|
}),
|
|
50
53
|
);
|
|
51
54
|
|
|
55
|
+
// ponytail: компонент только читает контекст дизайна. Если layout уже
|
|
56
|
+
// поднял его — Chessboard берёт дизайн из контекста сам, иначе
|
|
57
|
+
// используем дизайн из `puzzleStepBoardSettings.design`
|
|
58
|
+
// (`boardTheme` + `boardAppearanceSettings.design`).
|
|
59
|
+
const inheritedDesign = getBoardDesignSettingsContext();
|
|
60
|
+
const localDesign = $derived({
|
|
61
|
+
...DEFAULT_DESIGN_SETTINGS,
|
|
62
|
+
...puzzleStepBoardSettings.design,
|
|
63
|
+
});
|
|
64
|
+
const chessboardDesign = $derived(
|
|
65
|
+
inheritedDesign ? undefined : localDesign,
|
|
66
|
+
);
|
|
67
|
+
|
|
52
68
|
/** Один объект Fen на доску: создаём сразу с нужной начальной строкой. */
|
|
53
69
|
const fen = $derived.by(() => {
|
|
54
70
|
const f = new Fen(chessboard);
|
|
@@ -127,9 +143,13 @@
|
|
|
127
143
|
<!-- Явная ширина: при родителе с w-fit/min-content BoardContainer даёт min(100%, Nrem), и 100% может схлопнуться до нуля. -->
|
|
128
144
|
<div
|
|
129
145
|
class="shrink-0 max-w-full"
|
|
130
|
-
style="width: {puzzleStepBoardSettings.play
|
|
146
|
+
style="width: {puzzleStepBoardSettings.play
|
|
147
|
+
.boardSize}rem; max-width: 100%;"
|
|
131
148
|
>
|
|
132
|
-
<Chessboard
|
|
149
|
+
<Chessboard
|
|
150
|
+
facade={chessboard}
|
|
151
|
+
design={chessboardDesign}
|
|
152
|
+
/>
|
|
133
153
|
</div>
|
|
134
154
|
<div
|
|
135
155
|
class="hidden min-w-0 flex-1 flex-col gap-3 md:flex md:min-w-[280px]"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createInitialPuzzleData
|
|
1
|
+
import { createInitialPuzzleData } from "../puzzle/puzzleData.js";
|
|
2
2
|
/** Возвращает базовые шаги мастера: позиция, ходы, превью. */
|
|
3
3
|
export const PUZZLE_WIZARD_CORE_STEPS = [
|
|
4
4
|
{ id: "position", title: "Позиция" },
|
|
@@ -39,10 +39,6 @@ export interface TPuzzlePgnBoardTreeEditorProps {
|
|
|
39
39
|
* Возвращает признак «все линии превью пройдены» — полное дерево решения на экране, как перед «Готово» в мастере (двухсторонняя привязка).
|
|
40
40
|
*/
|
|
41
41
|
solved?: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* Возвращает тему оформления шахматной доски (по умолчанию `CHESSBOARD_THEMES.blue`).
|
|
44
|
-
*/
|
|
45
|
-
boardTheme?: ChessboardTheme;
|
|
46
42
|
/**
|
|
47
43
|
* Возвращает дополнительные визуальные настройки шахматной доски (кроме `boardSize`, `orientation`, `draggable`).
|
|
48
44
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@connectorvol/chess-widgets",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"test:e2e:ui": "node node_modules/@playwright/test/cli.js test --ui"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@connectorvol/chessboard": "9.0.
|
|
46
|
-
"@connectorvol/chessops": "9.0.
|
|
47
|
-
"@connectorvol/shared": "9.0.
|
|
48
|
-
"@connectorvol/tree": "9.0.
|
|
45
|
+
"@connectorvol/chessboard": "9.0.1",
|
|
46
|
+
"@connectorvol/chessops": "9.0.1",
|
|
47
|
+
"@connectorvol/shared": "9.0.1",
|
|
48
|
+
"@connectorvol/tree": "9.0.1",
|
|
49
49
|
"bits-ui": "2.16.4",
|
|
50
50
|
"clsx": "2.1.1",
|
|
51
51
|
"svelte-toolbelt": "0.10.6",
|
|
@@ -53,11 +53,10 @@
|
|
|
53
53
|
"tailwind-variants": "3.2.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@connectorvol/chess-shadcn": "9.0.
|
|
56
|
+
"@connectorvol/chess-shadcn": "9.0.1",
|
|
57
57
|
"@ianvs/prettier-plugin-sort-imports": "4.5.1",
|
|
58
58
|
"@lucide/svelte": "1.21.0",
|
|
59
|
-
"@
|
|
60
|
-
"@vitest/coverage-v8": "3.2.4",
|
|
59
|
+
"@playwright/test": "1.54.1",
|
|
61
60
|
"@sveltejs/kit": "2.49.1",
|
|
62
61
|
"@sveltejs/package": "2.4.0",
|
|
63
62
|
"@sveltejs/vite-plugin-svelte": "7.0.0",
|
|
@@ -65,19 +64,22 @@
|
|
|
65
64
|
"@tailwindcss/postcss": "4.1.11",
|
|
66
65
|
"@tailwindcss/typography": "0.5.16",
|
|
67
66
|
"@tailwindcss/vite": "4.1.11",
|
|
67
|
+
"@testing-library/svelte": "5.3.1",
|
|
68
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
68
69
|
"autoprefixer": "10.4.21",
|
|
69
70
|
"svelte-adapter-bun": "^1.0.1",
|
|
70
71
|
"svelte-check": "4.6.0",
|
|
71
72
|
"tailwindcss": "4.1.11",
|
|
72
73
|
"tw-animate-css": "1.4.0",
|
|
73
74
|
"typescript": "6.0.2",
|
|
74
|
-
"vitest": "4.0.17",
|
|
75
75
|
"vite": "8.0.7",
|
|
76
76
|
"vite-plugin-checker": "0.12.0",
|
|
77
|
-
"vite-plugin-svelte-checker": "0.1.2"
|
|
77
|
+
"vite-plugin-svelte-checker": "0.1.2",
|
|
78
|
+
"vitest": "4.0.17"
|
|
78
79
|
},
|
|
79
80
|
"peerDependencies": {
|
|
80
81
|
"@lucide/svelte": "1.21.0",
|
|
82
|
+
"mode-watcher": "1.1.0",
|
|
81
83
|
"svelte": "5.56.3"
|
|
82
84
|
}
|
|
83
85
|
}
|