@connectorvol/chess-widgets 9.0.1 → 9.0.3
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/puzzle-creation/PuzzleBoardTreeViewerPane.svelte +2 -15
- package/dist/puzzle-creation/PuzzleBoardTreeViewerPane.svelte.d.ts +1 -8
- package/dist/puzzle-creation/PuzzleCreationWizard.svelte +13 -6
- package/dist/puzzle-creation/PuzzlePgnBoardTreeEditor.svelte +2 -0
- package/dist/puzzle-creation/StepPosition.svelte +4 -8
- package/dist/puzzle-creation/StepPosition.svelte.d.ts +0 -2
- package/dist/puzzle-creation/StepPreview.svelte +171 -162
- package/dist/puzzle-creation/StepPreview.svelte.d.ts +0 -3
- package/dist/puzzle-creation/types.d.ts +6 -0
- package/package.json +6 -6
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
import { MediaQuery } from "svelte/reactivity";
|
|
4
4
|
import { mode } from "mode-watcher";
|
|
5
5
|
|
|
6
|
-
import type {
|
|
7
|
-
BoardApi,
|
|
8
|
-
TChessBoardDesignSettings,
|
|
9
|
-
} from "@connectorvol/chessboard";
|
|
6
|
+
import type { BoardApi } from "@connectorvol/chessboard";
|
|
10
7
|
import {
|
|
11
8
|
Chessboard,
|
|
12
9
|
getBoardDesignSettingsContext,
|
|
@@ -28,13 +25,6 @@
|
|
|
28
25
|
* Возвращает API шахматной доски для компонента `Chessboard`.
|
|
29
26
|
*/
|
|
30
27
|
chessboard: BoardApi;
|
|
31
|
-
/**
|
|
32
|
-
* Возвращает снимок дизайна, передаваемый в `<Chessboard design={...} />`.
|
|
33
|
-
* Опционально: если не передан, доска читает дизайн из контекста
|
|
34
|
-
* (`setBoardDesignSettingsContext`), что позволяет реактивно подхватывать
|
|
35
|
-
* изменения из `<BoardSettings />`.
|
|
36
|
-
*/
|
|
37
|
-
chessboardDesign?: TChessBoardDesignSettings;
|
|
38
28
|
/**
|
|
39
29
|
* Возвращает экземпляр дерева ходов для `TreeViewer`.
|
|
40
30
|
*/
|
|
@@ -86,7 +76,6 @@
|
|
|
86
76
|
|
|
87
77
|
const {
|
|
88
78
|
chessboard,
|
|
89
|
-
chessboardDesign,
|
|
90
79
|
chessTree,
|
|
91
80
|
onSelectNode,
|
|
92
81
|
onDeleteVariant,
|
|
@@ -174,9 +163,7 @@
|
|
|
174
163
|
>
|
|
175
164
|
<Chessboard
|
|
176
165
|
facade={chessboard}
|
|
177
|
-
design={
|
|
178
|
-
getBoardDesignSettingsContext() ??
|
|
179
|
-
undefined}
|
|
166
|
+
design={getBoardDesignSettingsContext() ?? undefined}
|
|
180
167
|
/>
|
|
181
168
|
</div>
|
|
182
169
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type { BoardApi
|
|
2
|
+
import type { BoardApi } from "@connectorvol/chessboard";
|
|
3
3
|
import type { ChessTree, TTreeViewerTheme } from "@connectorvol/tree";
|
|
4
4
|
/**
|
|
5
5
|
* Представляет свойства панели разметки «доска и просмотр дерева партии».
|
|
@@ -9,13 +9,6 @@ interface Props {
|
|
|
9
9
|
* Возвращает API шахматной доски для компонента `Chessboard`.
|
|
10
10
|
*/
|
|
11
11
|
chessboard: BoardApi;
|
|
12
|
-
/**
|
|
13
|
-
* Возвращает снимок дизайна, передаваемый в `<Chessboard design={...} />`.
|
|
14
|
-
* Опционально: если не передан, доска читает дизайн из контекста
|
|
15
|
-
* (`setBoardDesignSettingsContext`), что позволяет реактивно подхватывать
|
|
16
|
-
* изменения из `<BoardSettings />`.
|
|
17
|
-
*/
|
|
18
|
-
chessboardDesign?: TChessBoardDesignSettings;
|
|
19
12
|
/**
|
|
20
13
|
* Возвращает экземпляр дерева ходов для `TreeViewer`.
|
|
21
14
|
*/
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<script lang="ts" generics="S extends TPuzzleWizardCoreState">
|
|
10
10
|
import type { Snippet } from "svelte";
|
|
11
|
+
import { untrack } from "svelte";
|
|
11
12
|
|
|
12
13
|
import { Wizard } from "@connectorvol/shared";
|
|
13
14
|
import type { TWizardStep, TWizardStepContext } from "@connectorvol/shared";
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
import {
|
|
24
25
|
CHESSBOARD_THEMES,
|
|
25
26
|
Draggable,
|
|
27
|
+
setBoardDesignSettingsContext,
|
|
26
28
|
type ChessboardTheme,
|
|
27
29
|
type IChessBoardActions,
|
|
28
30
|
} from "@connectorvol/chessboard";
|
|
@@ -142,10 +144,18 @@
|
|
|
142
144
|
);
|
|
143
145
|
let chessboardApi = $derived(chessboard.api);
|
|
144
146
|
|
|
145
|
-
// ponytail:
|
|
146
|
-
//
|
|
147
|
-
//
|
|
147
|
+
// ponytail: дизайн доски шага 2 (включает `boardTheme` через
|
|
148
|
+
// `createPuzzleLineEditingBoardApi`) разделяется со всеми <Chessboard /> мастера
|
|
149
|
+
// через `setBoardDesignSettingsContext`. `untrack` для начального значения
|
|
150
|
+
// подавляет `state_referenced_locally` — `$effect` ниже держит контекстный стор
|
|
151
|
+
// в синхронизации с реактивными `boardTheme` / `boardAppearanceSettings`.
|
|
148
152
|
const chessboardDesign = $derived(chessboard.design);
|
|
153
|
+
const designState = untrack(() =>
|
|
154
|
+
setBoardDesignSettingsContext($state.snapshot(chessboardDesign)),
|
|
155
|
+
);
|
|
156
|
+
$effect(() => {
|
|
157
|
+
Object.assign(designState, chessboardDesign);
|
|
158
|
+
});
|
|
149
159
|
|
|
150
160
|
/**
|
|
151
161
|
* Представляет переход со шага построения линии на превью.
|
|
@@ -171,7 +181,6 @@
|
|
|
171
181
|
w.state.puzzleData.initialFen = fen;
|
|
172
182
|
w.next();
|
|
173
183
|
}}
|
|
174
|
-
{boardTheme}
|
|
175
184
|
{boardAppearanceSettings}
|
|
176
185
|
/>
|
|
177
186
|
{:else if w.currentStep === 2}
|
|
@@ -180,7 +189,6 @@
|
|
|
180
189
|
{chess}
|
|
181
190
|
{tree}
|
|
182
191
|
chessboard={chessboardApi}
|
|
183
|
-
{chessboardDesign}
|
|
184
192
|
onBack={w.back}
|
|
185
193
|
onNext={(moves) => {
|
|
186
194
|
handleMovesNext(moves);
|
|
@@ -196,7 +204,6 @@
|
|
|
196
204
|
onPuzzleCreated={hasAdditionalSteps
|
|
197
205
|
? undefined
|
|
198
206
|
: onPuzzleCreated}
|
|
199
|
-
{boardTheme}
|
|
200
207
|
{boardAppearanceSettings}
|
|
201
208
|
/>
|
|
202
209
|
{:else if additionalStep}
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
boardAppearanceSettings = DEFAULT_BOARD_APPEARANCE_SETTINGS,
|
|
66
66
|
boardSize,
|
|
67
67
|
onResizeAction,
|
|
68
|
+
theme,
|
|
68
69
|
class: className,
|
|
69
70
|
wrongFeedback = $bindable<string | null>(null),
|
|
70
71
|
solved = $bindable(false),
|
|
@@ -977,6 +978,7 @@
|
|
|
977
978
|
setChessboardFen={treeSetChessboardFen}
|
|
978
979
|
editMode={false}
|
|
979
980
|
selectable={solved}
|
|
981
|
+
{theme}
|
|
980
982
|
>
|
|
981
983
|
{#snippet belowChessboard()}
|
|
982
984
|
{#if wrongFeedback && wrongFeedback !== PREVIEW_WRONG_NO_VARIANT_MESSAGE}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {
|
|
3
3
|
Chessboard,
|
|
4
|
-
CHESSBOARD_THEMES,
|
|
5
4
|
createBoardApi,
|
|
6
5
|
DEFAULT_DESIGN_SETTINGS,
|
|
7
6
|
getBoardDesignSettingsContext,
|
|
8
|
-
type ChessboardTheme,
|
|
9
7
|
} from "@connectorvol/chessboard";
|
|
10
8
|
import { untrack } from "svelte";
|
|
11
9
|
|
|
@@ -23,7 +21,6 @@
|
|
|
23
21
|
interface Props {
|
|
24
22
|
initialFen: string;
|
|
25
23
|
onNext: (fen: string) => void;
|
|
26
|
-
boardTheme?: ChessboardTheme;
|
|
27
24
|
boardAppearanceSettings?: TChessboardAppearanceSettings;
|
|
28
25
|
}
|
|
29
26
|
|
|
@@ -41,7 +38,6 @@
|
|
|
41
38
|
design: {
|
|
42
39
|
...DEFAULT_EDITABLE_BOARD_SETTINGS.design,
|
|
43
40
|
...(props.boardAppearanceSettings?.design ?? {}),
|
|
44
|
-
theme: props.boardTheme ?? CHESSBOARD_THEMES.blue,
|
|
45
41
|
},
|
|
46
42
|
});
|
|
47
43
|
|
|
@@ -52,10 +48,10 @@
|
|
|
52
48
|
}),
|
|
53
49
|
);
|
|
54
50
|
|
|
55
|
-
// ponytail: компонент только читает контекст дизайна. Если
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
51
|
+
// ponytail: компонент только читает контекст дизайна. Если контекст
|
|
52
|
+
// уже поднят (в т.ч. через `setBoardDesignSettingsContext` в
|
|
53
|
+
// `PuzzleCreationWizard`) — Chessboard берёт дизайн из контекста сам,
|
|
54
|
+
// иначе используем дизайн из `puzzleStepBoardSettings.design`.
|
|
59
55
|
const inheritedDesign = getBoardDesignSettingsContext();
|
|
60
56
|
const localDesign = $derived({
|
|
61
57
|
...DEFAULT_DESIGN_SETTINGS,
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { type ChessboardTheme } from "@connectorvol/chessboard";
|
|
2
1
|
import type { TChessboardAppearanceSettings } from "./types.js";
|
|
3
2
|
interface Props {
|
|
4
3
|
initialFen: string;
|
|
5
4
|
onNext: (fen: string) => void;
|
|
6
|
-
boardTheme?: ChessboardTheme;
|
|
7
5
|
boardAppearanceSettings?: TChessboardAppearanceSettings;
|
|
8
6
|
}
|
|
9
7
|
declare const StepPosition: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,178 +1,187 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
import { Popover } from "bits-ui";
|
|
3
|
+
import { buttonVariants } from "../button-variants.js";
|
|
4
|
+
import { cn } from "../utils.js";
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
import { buttonVariants } from "../button-variants.js";
|
|
6
|
-
import { cn } from "../utils.js";
|
|
6
|
+
import { Color } from "@connectorvol/shared";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import type { PuzzleData } from "../puzzle/puzzleData.js";
|
|
9
|
+
import {
|
|
10
|
+
puzzlePartsFromFullPgn,
|
|
11
|
+
type TPuzzleCreatedPayload,
|
|
12
|
+
} from "../puzzle/puzzleCreatedPayload.js";
|
|
13
|
+
import { PREVIEW_WRONG_NO_VARIANT_MESSAGE } from "../puzzle/puzzlePreviewConstants.js";
|
|
14
|
+
import PuzzlePgnBoardTreeEditor from "./PuzzlePgnBoardTreeEditor.svelte";
|
|
15
|
+
import type { TChessboardAppearanceSettings } from "./types.js";
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
interface Props {
|
|
18
|
+
/** Возвращает данные задачи (стартовый FEN и главная линия SAN для совместимости). */
|
|
19
|
+
puzzleData: PuzzleData;
|
|
20
|
+
/** Возвращает полное дерево задачи в виде строки PGN после шага 2. */
|
|
21
|
+
solutionPgn: string;
|
|
22
|
+
/** Возвращает переход назад на шаг построения линии. */
|
|
23
|
+
onBack: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Возвращает колбэк сохранения задачи с FEN и строкой ходов (кнопка «Готово» показывается после решения превью).
|
|
26
|
+
*/
|
|
27
|
+
onPuzzleCreated?: (payload: TPuzzleCreatedPayload) => void;
|
|
28
|
+
/** Возвращает переход на шаг выбора тегов вместо немедленного завершения. */
|
|
29
|
+
onNext?: () => void;
|
|
30
|
+
/** Возвращает дополнительные визуальные настройки шахматной доски (кроме `boardSize`, `orientation`, `draggable`). */
|
|
31
|
+
boardAppearanceSettings?: TChessboardAppearanceSettings;
|
|
32
|
+
}
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
/** Возвращает данные задачи (стартовый FEN и главная линия SAN для совместимости). */
|
|
21
|
-
puzzleData: PuzzleData;
|
|
22
|
-
/** Возвращает полное дерево задачи в виде строки PGN после шага 2. */
|
|
23
|
-
solutionPgn: string;
|
|
24
|
-
/** Возвращает переход назад на шаг построения линии. */
|
|
25
|
-
onBack: () => void;
|
|
26
|
-
/**
|
|
27
|
-
* Возвращает колбэк сохранения задачи с FEN и строкой ходов (кнопка «Готово» показывается после решения превью).
|
|
28
|
-
*/
|
|
29
|
-
onPuzzleCreated?: (payload: TPuzzleCreatedPayload) => void;
|
|
30
|
-
/** Возвращает переход на шаг выбора тегов вместо немедленного завершения. */
|
|
31
|
-
onNext?: () => void;
|
|
32
|
-
/** Возвращает тему оформления шахматной доски (по умолчанию `CHESSBOARD_THEMES.blue`). */
|
|
33
|
-
boardTheme?: ChessboardTheme;
|
|
34
|
-
/** Возвращает дополнительные визуальные настройки шахматной доски (кроме `boardSize`, `orientation`, `draggable`). */
|
|
35
|
-
boardAppearanceSettings?: TChessboardAppearanceSettings;
|
|
36
|
-
}
|
|
34
|
+
const props: Props = $props();
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
const solverColor = $derived(
|
|
37
|
+
props.puzzleData.initialFen.trim().split(/\s+/)[1] === "b"
|
|
38
|
+
? Color.BLACK
|
|
39
|
+
: Color.WHITE,
|
|
40
|
+
);
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
? Color.BLACK
|
|
43
|
-
: Color.WHITE,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
let wrongFeedback = $state<string | null>(null);
|
|
47
|
-
let solved = $state(false);
|
|
42
|
+
let wrongFeedback = $state<string | null>(null);
|
|
43
|
+
let solved = $state(false);
|
|
48
44
|
</script>
|
|
49
45
|
|
|
50
46
|
<div class="flex flex-col gap-3 pt-2 pb-0">
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
47
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
48
|
+
<h2 class="text-xl font-semibold">Шаг 3: Превью для ученика</h2>
|
|
49
|
+
<Popover.Root>
|
|
50
|
+
<Popover.Trigger type="button">
|
|
51
|
+
{#snippet child({ props })}
|
|
52
|
+
<button
|
|
53
|
+
{...props}
|
|
54
|
+
type="button"
|
|
55
|
+
class={cn(
|
|
56
|
+
buttonVariants({
|
|
57
|
+
variant: "outline",
|
|
58
|
+
size: "icon-sm",
|
|
59
|
+
}),
|
|
60
|
+
"size-7 shrink-0 rounded-full text-sm font-semibold",
|
|
61
|
+
)}
|
|
62
|
+
aria-label="Справка: превью для ученика"
|
|
63
|
+
>
|
|
64
|
+
?
|
|
65
|
+
</button>
|
|
66
|
+
{/snippet}
|
|
67
|
+
</Popover.Trigger>
|
|
68
|
+
<Popover.Portal>
|
|
69
|
+
<Popover.Content
|
|
70
|
+
side="bottom"
|
|
71
|
+
align="start"
|
|
72
|
+
sideOffset={8}
|
|
73
|
+
class={cn(
|
|
74
|
+
"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",
|
|
75
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
76
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
77
|
+
)}
|
|
78
|
+
>
|
|
79
|
+
<div
|
|
80
|
+
class="space-y-3 text-muted-foreground leading-relaxed"
|
|
81
|
+
>
|
|
82
|
+
<p>
|
|
83
|
+
Так puzzle будет выглядеть для ученика. Делайте ходы
|
|
84
|
+
за
|
|
85
|
+
{solverColor === Color.WHITE ? "белых" : "чёрных"}.
|
|
86
|
+
При правильном ходе соперник ответит автоматически
|
|
87
|
+
(первый вариант на развилках соперника). На развилке
|
|
88
|
+
решателя достаточно одного верного продолжения.
|
|
89
|
+
</p>
|
|
90
|
+
<p>
|
|
91
|
+
Сначала в дереве отображается только стартовая
|
|
92
|
+
позиция; по мере верных ходов появляются линии; при
|
|
93
|
+
неверном отмеченном ответе кратко показывается
|
|
94
|
+
введённый неверный вариант.
|
|
95
|
+
</p>
|
|
96
|
+
<p>
|
|
97
|
+
После решения показывается всё дерево ходов из PGN,
|
|
98
|
+
введённое на шаге 2.
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</Popover.Content>
|
|
102
|
+
</Popover.Portal>
|
|
103
|
+
</Popover.Root>
|
|
104
|
+
{#if wrongFeedback === PREVIEW_WRONG_NO_VARIANT_MESSAGE}
|
|
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 border-amber-600/60 text-sm font-semibold text-amber-600 dark:border-amber-400/60 dark:text-amber-400",
|
|
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
|
|
136
|
+
class="leading-relaxed text-amber-700 dark:text-amber-400"
|
|
137
|
+
>
|
|
138
|
+
{PREVIEW_WRONG_NO_VARIANT_MESSAGE}
|
|
139
|
+
</p>
|
|
140
|
+
</Popover.Content>
|
|
141
|
+
</Popover.Portal>
|
|
142
|
+
</Popover.Root>
|
|
143
|
+
{/if}
|
|
144
|
+
</div>
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
/>
|
|
146
|
+
<PuzzlePgnBoardTreeEditor
|
|
147
|
+
bind:wrongFeedback
|
|
148
|
+
bind:solved
|
|
149
|
+
pgn={props.solutionPgn}
|
|
150
|
+
fen={props.puzzleData.initialFen}
|
|
151
|
+
boardAppearanceSettings={props.boardAppearanceSettings}
|
|
152
|
+
/>
|
|
146
153
|
|
|
147
|
-
|
|
148
|
-
<button
|
|
149
|
-
type="button"
|
|
150
|
-
class={cn(buttonVariants({ variant: "outline" }))}
|
|
151
|
-
onclick={props.onBack}
|
|
152
|
-
>
|
|
153
|
-
Назад
|
|
154
|
-
</button>
|
|
155
|
-
{#if solved}
|
|
156
|
-
{#if props.onNext}
|
|
154
|
+
<div class="flex justify-between gap-2">
|
|
157
155
|
<button
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
disabled={!props.solutionPgn.trim()}
|
|
162
|
-
>
|
|
163
|
-
Далее
|
|
164
|
-
</button>
|
|
165
|
-
{:else if props.onPuzzleCreated}
|
|
166
|
-
<button
|
|
167
|
-
type="button"
|
|
168
|
-
class={cn(buttonVariants({ variant: "default" }))}
|
|
169
|
-
onclick={() =>
|
|
170
|
-
props.onPuzzleCreated?.(puzzlePartsFromFullPgn(props.solutionPgn))}
|
|
171
|
-
disabled={!props.solutionPgn.trim()}
|
|
156
|
+
type="button"
|
|
157
|
+
class={cn(buttonVariants({ variant: "outline" }))}
|
|
158
|
+
onclick={props.onBack}
|
|
172
159
|
>
|
|
173
|
-
|
|
160
|
+
Назад
|
|
174
161
|
</button>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
162
|
+
{#if solved}
|
|
163
|
+
{#if props.onNext}
|
|
164
|
+
<button
|
|
165
|
+
type="button"
|
|
166
|
+
class={cn(buttonVariants({ variant: "default" }))}
|
|
167
|
+
onclick={props.onNext}
|
|
168
|
+
disabled={!props.solutionPgn.trim()}
|
|
169
|
+
>
|
|
170
|
+
Далее
|
|
171
|
+
</button>
|
|
172
|
+
{:else if props.onPuzzleCreated}
|
|
173
|
+
<button
|
|
174
|
+
type="button"
|
|
175
|
+
class={cn(buttonVariants({ variant: "default" }))}
|
|
176
|
+
onclick={() =>
|
|
177
|
+
props.onPuzzleCreated?.(
|
|
178
|
+
puzzlePartsFromFullPgn(props.solutionPgn),
|
|
179
|
+
)}
|
|
180
|
+
disabled={!props.solutionPgn.trim()}
|
|
181
|
+
>
|
|
182
|
+
Готово
|
|
183
|
+
</button>
|
|
184
|
+
{/if}
|
|
185
|
+
{/if}
|
|
186
|
+
</div>
|
|
178
187
|
</div>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ChessboardTheme } from "@connectorvol/chessboard";
|
|
2
1
|
import type { PuzzleData } from "../puzzle/puzzleData.js";
|
|
3
2
|
import { type TPuzzleCreatedPayload } from "../puzzle/puzzleCreatedPayload.js";
|
|
4
3
|
import type { TChessboardAppearanceSettings } from "./types.js";
|
|
@@ -15,8 +14,6 @@ interface Props {
|
|
|
15
14
|
onPuzzleCreated?: (payload: TPuzzleCreatedPayload) => void;
|
|
16
15
|
/** Возвращает переход на шаг выбора тегов вместо немедленного завершения. */
|
|
17
16
|
onNext?: () => void;
|
|
18
|
-
/** Возвращает тему оформления шахматной доски (по умолчанию `CHESSBOARD_THEMES.blue`). */
|
|
19
|
-
boardTheme?: ChessboardTheme;
|
|
20
17
|
/** Возвращает дополнительные визуальные настройки шахматной доски (кроме `boardSize`, `orientation`, `draggable`). */
|
|
21
18
|
boardAppearanceSettings?: TChessboardAppearanceSettings;
|
|
22
19
|
}
|
|
@@ -3,6 +3,7 @@ import type { TPuzzleCreatedPayload } from "../puzzle/puzzleCreatedPayload.js";
|
|
|
3
3
|
import type { TWizardStep, TWizardStepContext } from "@connectorvol/shared";
|
|
4
4
|
import type { TPuzzleWizardCoreState } from "./puzzleWizardState.js";
|
|
5
5
|
import type { ChessboardTheme, TChessBoardDesignSettings, TChessBoardPlaySettings } from "@connectorvol/chessboard";
|
|
6
|
+
import type { TTreeViewerTheme } from "@connectorvol/tree";
|
|
6
7
|
/**
|
|
7
8
|
* Представляет тип визуальных настроек шахматной доски для мастера создания задачи.
|
|
8
9
|
*/
|
|
@@ -51,6 +52,11 @@ export interface TPuzzlePgnBoardTreeEditorProps {
|
|
|
51
52
|
* Возвращает колбэк после завершения изменения размера доски перетаскиванием ручки resize.
|
|
52
53
|
*/
|
|
53
54
|
onResizeAction?: (size: number) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Возвращает тему `TreeViewer` (фон, границы, текст). По умолчанию подстраивается под `mode-watcher` (dark → `TREE_VIEWER_DARK_THEME`, иначе `TREE_VIEWER_LIGHT_THEME`).
|
|
57
|
+
* Позволяет прокидывать явную тему из родителя (например, чтобы фон совпадал с `--background` приложения).
|
|
58
|
+
*/
|
|
59
|
+
theme?: TTreeViewerTheme;
|
|
54
60
|
/**
|
|
55
61
|
* Возвращает дополнительные классы Tailwind для корневого контейнера раскладки.
|
|
56
62
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@connectorvol/chess-widgets",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.3",
|
|
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.3",
|
|
46
|
+
"@connectorvol/chessops": "9.0.3",
|
|
47
|
+
"@connectorvol/shared": "9.0.3",
|
|
48
|
+
"@connectorvol/tree": "9.0.3",
|
|
49
49
|
"bits-ui": "2.16.4",
|
|
50
50
|
"clsx": "2.1.1",
|
|
51
51
|
"svelte-toolbelt": "0.10.6",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"tailwind-variants": "3.2.2"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@connectorvol/chess-shadcn": "9.0.
|
|
56
|
+
"@connectorvol/chess-shadcn": "9.0.3",
|
|
57
57
|
"@ianvs/prettier-plugin-sort-imports": "4.5.1",
|
|
58
58
|
"@lucide/svelte": "1.21.0",
|
|
59
59
|
"@playwright/test": "1.54.1",
|