@connectorvol/tree 4.0.0 → 4.2.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.
- package/dist/(classes)/chessTree.svelte.d.ts +2 -0
- package/dist/(classes)/chessTree.svelte.js +7 -1
- package/dist/(components)/Move.svelte +347 -318
- package/dist/(components)/MoveWithIcon.svelte +59 -48
- package/dist/(components)/NagBadges.svelte +30 -30
- package/dist/(components)/TreeViewer.svelte +877 -824
- package/dist/(components)/TreeViewerPanelManager.svelte +99 -98
- package/dist/components/ui/checkbox/checkbox.svelte +39 -0
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +4 -0
- package/dist/components/ui/checkbox/index.d.ts +2 -0
- package/dist/components/ui/checkbox/index.js +4 -0
- package/dist/components/ui/popover/index.d.ts +9 -0
- package/dist/components/ui/popover/index.js +11 -0
- package/dist/components/ui/popover/popover-close.svelte +7 -0
- package/dist/components/ui/popover/popover-close.svelte.d.ts +4 -0
- package/dist/components/ui/popover/popover-content.svelte +31 -0
- package/dist/components/ui/popover/popover-content.svelte.d.ts +10 -0
- package/dist/components/ui/popover/popover-description.svelte +20 -0
- package/dist/components/ui/popover/popover-description.svelte.d.ts +5 -0
- package/dist/components/ui/popover/popover-header.svelte +20 -0
- package/dist/components/ui/popover/popover-header.svelte.d.ts +5 -0
- package/dist/components/ui/popover/popover-portal.svelte +7 -0
- package/dist/components/ui/popover/popover-portal.svelte.d.ts +3 -0
- package/dist/components/ui/popover/popover-title.svelte +20 -0
- package/dist/components/ui/popover/popover-title.svelte.d.ts +5 -0
- package/dist/components/ui/popover/popover-trigger.svelte +17 -0
- package/dist/components/ui/popover/popover-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/popover/popover.svelte +7 -0
- package/dist/components/ui/popover/popover.svelte.d.ts +3 -0
- package/dist/components/ui/toggle/index.d.ts +3 -0
- package/dist/components/ui/toggle/index.js +5 -0
- package/dist/components/ui/toggle/toggle.svelte +51 -0
- package/dist/components/ui/toggle/toggle.svelte.d.ts +43 -0
- package/package.json +11 -9
|
@@ -1,361 +1,390 @@
|
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
2
|
+
import type { ChessTreeNode } from "../(models)/chessTreeNode.js";
|
|
3
|
+
|
|
4
|
+
import { parseComment } from "@connectorvol/chessops/pgn";
|
|
5
|
+
|
|
6
|
+
import { createPreviewHover } from "../(utils)/createPreviewHover.js";
|
|
7
|
+
import { getGameContext } from "../(utils)/context.js";
|
|
8
|
+
import Move from "./Move.svelte";
|
|
9
|
+
import MoveComment from "./MoveComment.svelte";
|
|
10
|
+
import MoveSanWithMenu from "./MoveSanWithMenu.svelte";
|
|
11
|
+
import VariationGroup from "./VariationGroup.svelte";
|
|
12
|
+
import type { PieceSet } from "@connectorvol/shared";
|
|
13
|
+
|
|
14
|
+
const HIGHEST_LEVEL = 1;
|
|
15
|
+
|
|
16
|
+
type TMoveProps = {
|
|
17
|
+
/** Возвращает узел хода в дереве партии. */
|
|
18
|
+
chessNode: ChessTreeNode;
|
|
19
|
+
/** Возвращает глубину вложенности относительно корня отображения. */
|
|
20
|
+
depth: number;
|
|
21
|
+
/** Возвращает родительский узел или null для корня. */
|
|
22
|
+
parentNode: ChessTreeNode | null;
|
|
23
|
+
/** Возвращает true, если нужна пустая ячейка хода (сетка верхнего уровня). */
|
|
24
|
+
shouldReserveEmptyMoveCell: boolean;
|
|
25
|
+
/** Возвращает true, если нужно отрисовать соседние варианты у развилки. */
|
|
26
|
+
shouldRenderSiblingVariations?: boolean;
|
|
27
|
+
/** Возвращает набор фигур для иконок SAN. */
|
|
28
|
+
pieceSet: PieceSet;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
chessNode,
|
|
33
|
+
depth,
|
|
34
|
+
parentNode,
|
|
35
|
+
shouldReserveEmptyMoveCell,
|
|
36
|
+
shouldRenderSiblingVariations = true,
|
|
37
|
+
pieceSet,
|
|
38
|
+
}: TMoveProps = $props();
|
|
39
|
+
|
|
40
|
+
/** Контекст игры без деструктуризации — иначе selectable и chessTree «замораживаются» при первом рендере TreeViewer. */
|
|
41
|
+
const game = getGameContext();
|
|
42
|
+
|
|
43
|
+
/** Представляет обработчик выбора текущего узла по `mousedown`. */
|
|
44
|
+
function handleMoveMouseDown() {
|
|
45
|
+
if (!game.selectable || !moveNode) return;
|
|
46
|
+
game.chessTree.currentNode = chessNode;
|
|
47
|
+
|
|
48
|
+
game.onSelectNode();
|
|
49
|
+
game.onChessNodeSelected?.(game.chessTree.currentNode);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const moveNode = $derived(chessNode);
|
|
53
|
+
const previewHover = createPreviewHover({
|
|
54
|
+
setPreviewFen: game.setPreviewFen,
|
|
55
|
+
getFen: () => moveNode.data.fen,
|
|
56
|
+
getLastMove: () => moveNode.data.lastMove ?? null,
|
|
57
|
+
getDelayMs: () => game.previewHoverDelayMs,
|
|
58
|
+
});
|
|
59
|
+
const isCurrentMove = $derived(
|
|
60
|
+
chessNode.id === game.chessTree.currentNode.id,
|
|
61
|
+
);
|
|
62
|
+
/** Представляет текст первого PGN-комментария узла после разбора `comments[0]`, синхронно с правкой строки под деревом. */
|
|
63
|
+
const commentParseCache = new Map<
|
|
64
|
+
string,
|
|
65
|
+
ReturnType<typeof parseComment>
|
|
66
|
+
>();
|
|
67
|
+
|
|
68
|
+
function getParsedComment(raw: string | undefined) {
|
|
69
|
+
if (raw === undefined) return null;
|
|
70
|
+
const cached = commentParseCache.get(raw);
|
|
71
|
+
if (cached) return cached;
|
|
72
|
+
const parsed = parseComment(raw);
|
|
73
|
+
commentParseCache.set(raw, parsed);
|
|
74
|
+
return parsed;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const firstCommentParsed = $derived(
|
|
78
|
+
getParsedComment(moveNode.data.comments?.[0]),
|
|
79
|
+
);
|
|
80
|
+
const firstCommentText = $derived(firstCommentParsed?.text);
|
|
81
|
+
const childMoves = $derived(chessNode.children);
|
|
82
|
+
const isForcedLineStart = $derived(
|
|
83
|
+
chessNode.id === game.chessTree.forcedNodeId,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
/** Представляет признак активного drill-down «варианты отдельно». */
|
|
87
|
+
const variationDrillDownActive = $derived(
|
|
88
|
+
game.chessTree.isVariationDrillDownActive(),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Представляет признак: развилка на этом уровне совпадает с узлом, для которого
|
|
93
|
+
* `ChessTree` рассчитывает акцент направляющих при текущем выборе.
|
|
94
|
+
*/
|
|
95
|
+
const isActiveForkForSelection = $derived(
|
|
96
|
+
shouldRenderSiblingVariations &&
|
|
97
|
+
parentNode !== null &&
|
|
98
|
+
(parentNode.children?.length ?? 0) > 1 &&
|
|
99
|
+
game.chessTree.currentGuideHighlightForkParent?.id ===
|
|
100
|
+
parentNode.id,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const spaceBlockClass = "px-3 py-2 !bg-gray-50/95";
|
|
104
|
+
const spaceInlineBlockClass = "p-2";
|
|
105
|
+
|
|
106
|
+
const isHighestLevel = $derived(depth === HIGHEST_LEVEL);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Представляет признак: в верхней сетке после белого полухода показывается пустая ячейка чёрных
|
|
110
|
+
* без ноды (партия оборвалась на ходе белых) — нижнюю границу рисуем только под двумя первыми колонками.
|
|
111
|
+
*/
|
|
112
|
+
const addsEmptyMainLineBlackCell = $derived(
|
|
113
|
+
isHighestLevel &&
|
|
114
|
+
moveNode.data.ply % 2 === 1 &&
|
|
115
|
+
!isForcedLineStart &&
|
|
116
|
+
(parentNode === null || parentNode.children.length <= 1) &&
|
|
117
|
+
!firstCommentText &&
|
|
118
|
+
(childMoves?.length ?? 0) === 0,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Представляет признак: верхняя строка — первый полуход чёрных от корня партии (нотация «1... SAN»).
|
|
123
|
+
*/
|
|
124
|
+
const isLeadingBlackHalfMoveFromRoot = $derived(
|
|
125
|
+
isHighestLevel &&
|
|
126
|
+
parentNode !== null &&
|
|
127
|
+
parentNode.data.ply === 0 &&
|
|
128
|
+
moveNode.data.ply % 2 === 0,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
/** Представляет true, если в контекстном меню показывать «Поднять приоритет». */
|
|
132
|
+
const showUpPriorityItem = $derived(depth > HIGHEST_LEVEL + 1);
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Представляет признак: SAN главного варианта (children[0]) переносится в блок списка веток,
|
|
136
|
+
* чтобы не дублировать его перед группой (например «8. g3» только среди g3 / f3 / a3).
|
|
137
|
+
*/
|
|
138
|
+
const shouldRenderSanInsideVariationGroup = $derived(
|
|
139
|
+
!isHighestLevel &&
|
|
140
|
+
shouldRenderSiblingVariations &&
|
|
141
|
+
parentNode !== null &&
|
|
142
|
+
parentNode.children.length > 1 &&
|
|
143
|
+
parentNode.children[0]?.id === chessNode.id,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Представляет обработчик клика по зоне линий ветвления, открывающий режим «варианты отдельно».
|
|
148
|
+
*/
|
|
149
|
+
function onVariationLinesHit(e: MouseEvent) {
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
if (parentNode === null) return;
|
|
152
|
+
const selectFork =
|
|
153
|
+
!game.chessTree.isCurrentNodeWithinForkSubtree(parentNode);
|
|
154
|
+
game.chessTree.openVariationDrillDown(parentNode, { selectFork });
|
|
155
|
+
game.onSelectNode();
|
|
156
|
+
game.onChessNodeSelected?.(game.chessTree.currentNode);
|
|
157
|
+
}
|
|
147
158
|
</script>
|
|
148
159
|
|
|
149
160
|
{#snippet emptyMove()}
|
|
150
|
-
|
|
161
|
+
<div class="flex items-center justify-center text-center">...</div>
|
|
151
162
|
{/snippet}
|
|
152
163
|
|
|
153
164
|
{#snippet emptyMainLineBlackCell()}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
165
|
+
<div
|
|
166
|
+
class="tree-viewer-tail-no-node-cell flex min-w-0 items-center justify-center border-b-0 p-2 text-center"
|
|
167
|
+
></div>
|
|
157
168
|
{/snippet}
|
|
158
169
|
|
|
159
170
|
{#snippet fullMovesCounter(minus: number = 0)}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
<span
|
|
172
|
+
class={{
|
|
173
|
+
"flex items-center justify-center text-center": isHighestLevel,
|
|
174
|
+
inline: !isHighestLevel,
|
|
175
|
+
"border-b border-gray-300":
|
|
176
|
+
addsEmptyMainLineBlackCell && isHighestLevel,
|
|
177
|
+
"tree-viewer-overflow-tail-border":
|
|
178
|
+
addsEmptyMainLineBlackCell && isHighestLevel,
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
{moveNode.data.fullMoves - minus}{!isHighestLevel &&
|
|
182
|
+
moveNode.data.ply % 2 === 1
|
|
183
|
+
? "..."
|
|
184
|
+
: !isHighestLevel && moveNode.data.ply % 2 === 0
|
|
185
|
+
? "..."
|
|
186
|
+
: ""}
|
|
187
|
+
</span>
|
|
176
188
|
{/snippet}
|
|
177
189
|
|
|
178
190
|
{#snippet variationMoveRow(child: ChessTreeNode)}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
<Move
|
|
192
|
+
{pieceSet}
|
|
193
|
+
chessNode={child}
|
|
194
|
+
shouldReserveEmptyMoveCell={parentNode !== null &&
|
|
195
|
+
parentNode.children.length > 1}
|
|
196
|
+
depth={depth + 1}
|
|
197
|
+
shouldRenderSiblingVariations={false}
|
|
198
|
+
{parentNode}
|
|
199
|
+
/>
|
|
188
200
|
{/snippet}
|
|
189
201
|
|
|
190
202
|
{#if isHighestLevel}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
{#if variationDrillDownActive && moveNode.data.ply % 2 === 0 && chessTree.drillForkParent !== null && chessTree.drillForkParent.children[0]?.id === chessNode.id && moveNode.parentId}
|
|
196
|
-
<span
|
|
197
|
-
class={{
|
|
198
|
-
"flex items-center justify-center text-center": isHighestLevel,
|
|
199
|
-
}}
|
|
200
|
-
>
|
|
201
|
-
{moveNode.data.fullMoves}
|
|
202
|
-
</span>
|
|
203
|
-
{@render emptyMove()}
|
|
204
|
-
{/if}
|
|
203
|
+
{#if moveNode.data.ply % 2 === 1}
|
|
204
|
+
{@render fullMovesCounter()}
|
|
205
|
+
{/if}
|
|
205
206
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
{/if}
|
|
216
|
-
|
|
217
|
-
{#if moveNode.parentId}
|
|
218
|
-
<MoveSanWithMenu
|
|
219
|
-
{chessNode}
|
|
220
|
-
{parentNode}
|
|
221
|
-
{pieceSet}
|
|
222
|
-
{selectable}
|
|
223
|
-
{isHighestLevel}
|
|
224
|
-
{isCurrentMove}
|
|
225
|
-
previewHover={{
|
|
226
|
-
onmouseenter: previewHover.onmouseenter,
|
|
227
|
-
onmouseleave: previewHover.onmouseleave,
|
|
228
|
-
}}
|
|
229
|
-
onMoveMouseDown={handleMoveMouseDown}
|
|
230
|
-
{spaceInlineBlockClass}
|
|
231
|
-
nags={moveNode.data.nags}
|
|
232
|
-
{chessTree}
|
|
233
|
-
{showUpPriorityItem}
|
|
234
|
-
{onDeleteVariant}
|
|
235
|
-
mainRowBottomEdge={addsEmptyMainLineBlackCell}
|
|
236
|
-
/>
|
|
237
|
-
{/if}
|
|
238
|
-
{#if isHighestLevel && moveNode.data.ply % 2 === 1}
|
|
239
|
-
{#if isForcedLineStart || (parentNode != null && parentNode.children.length > 1) || !!firstCommentText}
|
|
240
|
-
{@render emptyMove()}
|
|
241
|
-
{:else if (childMoves?.length ?? 0) === 0}
|
|
242
|
-
{@render emptyMainLineBlackCell()}
|
|
207
|
+
{#if variationDrillDownActive && moveNode.data.ply % 2 === 0 && game.chessTree.drillForkParent !== null && game.chessTree.drillForkParent.children[0]?.id === chessNode.id && moveNode.parentId}
|
|
208
|
+
<span
|
|
209
|
+
class={{
|
|
210
|
+
"flex items-center justify-center text-center": isHighestLevel,
|
|
211
|
+
}}
|
|
212
|
+
>
|
|
213
|
+
{moveNode.data.fullMoves}
|
|
214
|
+
</span>
|
|
215
|
+
{@render emptyMove()}
|
|
243
216
|
{/if}
|
|
244
|
-
{/if}
|
|
245
217
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
218
|
+
{#if isLeadingBlackHalfMoveFromRoot}
|
|
219
|
+
<span
|
|
220
|
+
class={{
|
|
221
|
+
"flex items-center justify-center text-center": isHighestLevel,
|
|
222
|
+
}}
|
|
223
|
+
>
|
|
224
|
+
{Math.max(1, moveNode.data.fullMoves - 1)}
|
|
225
|
+
</span>
|
|
251
226
|
{@render emptyMove()}
|
|
252
|
-
{/if}
|
|
253
227
|
{/if}
|
|
254
228
|
|
|
255
|
-
{#if moveNode.
|
|
256
|
-
|
|
229
|
+
{#if moveNode.parentId}
|
|
230
|
+
<MoveSanWithMenu
|
|
231
|
+
{chessNode}
|
|
232
|
+
{parentNode}
|
|
233
|
+
{pieceSet}
|
|
234
|
+
selectable={game.selectable}
|
|
235
|
+
{isHighestLevel}
|
|
236
|
+
{isCurrentMove}
|
|
237
|
+
previewHover={{
|
|
238
|
+
onmouseenter: previewHover.onmouseenter,
|
|
239
|
+
onmouseleave: previewHover.onmouseleave,
|
|
240
|
+
}}
|
|
241
|
+
onMoveMouseDown={handleMoveMouseDown}
|
|
242
|
+
{spaceInlineBlockClass}
|
|
243
|
+
nags={moveNode.data.nags}
|
|
244
|
+
chessTree={game.chessTree}
|
|
245
|
+
{showUpPriorityItem}
|
|
246
|
+
onDeleteVariant={game.onDeleteVariant}
|
|
247
|
+
mainRowBottomEdge={addsEmptyMainLineBlackCell}
|
|
248
|
+
/>
|
|
249
|
+
{/if}
|
|
250
|
+
{#if isHighestLevel && moveNode.data.ply % 2 === 1}
|
|
251
|
+
{#if isForcedLineStart || (parentNode != null && parentNode.children.length > 1) || !!firstCommentText}
|
|
252
|
+
{@render emptyMove()}
|
|
253
|
+
{:else if (childMoves?.length ?? 0) === 0}
|
|
254
|
+
{@render emptyMainLineBlackCell()}
|
|
255
|
+
{/if}
|
|
256
|
+
{/if}
|
|
257
|
+
|
|
258
|
+
{#if firstCommentText}
|
|
259
|
+
{#if moveNode.data.ply % 2 === 1}
|
|
260
|
+
<MoveComment
|
|
261
|
+
text={firstCommentText}
|
|
262
|
+
{isHighestLevel}
|
|
263
|
+
{spaceBlockClass}
|
|
264
|
+
/>
|
|
265
|
+
{#if !shouldReserveEmptyMoveCell && childMoves?.[0] && !isForcedLineStart}
|
|
266
|
+
{@render fullMovesCounter()}
|
|
267
|
+
{@render emptyMove()}
|
|
268
|
+
{/if}
|
|
269
|
+
{/if}
|
|
270
|
+
|
|
271
|
+
{#if moveNode.data.ply % 2 === 0}
|
|
272
|
+
<MoveComment
|
|
273
|
+
text={firstCommentText}
|
|
274
|
+
{isHighestLevel}
|
|
275
|
+
{spaceBlockClass}
|
|
276
|
+
/>
|
|
277
|
+
{/if}
|
|
257
278
|
{/if}
|
|
258
|
-
{/if}
|
|
259
279
|
{:else}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
{/if}
|
|
263
|
-
|
|
264
|
-
{#if !shouldRenderSanInsideVariationGroup}
|
|
265
|
-
<MoveSanWithMenu
|
|
266
|
-
{chessNode}
|
|
267
|
-
{parentNode}
|
|
268
|
-
{pieceSet}
|
|
269
|
-
{selectable}
|
|
270
|
-
{isHighestLevel}
|
|
271
|
-
{isCurrentMove}
|
|
272
|
-
previewHover={{
|
|
273
|
-
onmouseenter: previewHover.onmouseenter,
|
|
274
|
-
onmouseleave: previewHover.onmouseleave,
|
|
275
|
-
}}
|
|
276
|
-
onMoveMouseDown={handleMoveMouseDown}
|
|
277
|
-
{spaceInlineBlockClass}
|
|
278
|
-
nags={moveNode.data.nags}
|
|
279
|
-
{chessTree}
|
|
280
|
-
{showUpPriorityItem}
|
|
281
|
-
{onDeleteVariant}
|
|
282
|
-
/>
|
|
283
|
-
{/if}
|
|
284
|
-
{#if firstCommentText}
|
|
285
|
-
{#if moveNode.data.ply % 2 === 1}
|
|
286
|
-
<MoveComment text={firstCommentText} {isHighestLevel} {spaceBlockClass} />
|
|
287
|
-
{#if !shouldReserveEmptyMoveCell && childMoves?.[0] && !shouldRenderSanInsideVariationGroup}
|
|
288
|
-
{@render fullMovesCounter()}
|
|
289
|
-
{/if}
|
|
280
|
+
{#if moveNode.data.ply % 2 === 0 && game.chessTree.forcedNodeId === moveNode.parentId && parentNode?.children[0].id === moveNode.id}
|
|
281
|
+
{@render fullMovesCounter(1)}
|
|
290
282
|
{/if}
|
|
291
283
|
|
|
292
|
-
{#if
|
|
293
|
-
|
|
284
|
+
{#if !shouldRenderSanInsideVariationGroup}
|
|
285
|
+
<MoveSanWithMenu
|
|
286
|
+
{chessNode}
|
|
287
|
+
{parentNode}
|
|
288
|
+
{pieceSet}
|
|
289
|
+
selectable={game.selectable}
|
|
290
|
+
{isHighestLevel}
|
|
291
|
+
{isCurrentMove}
|
|
292
|
+
previewHover={{
|
|
293
|
+
onmouseenter: previewHover.onmouseenter,
|
|
294
|
+
onmouseleave: previewHover.onmouseleave,
|
|
295
|
+
}}
|
|
296
|
+
onMoveMouseDown={handleMoveMouseDown}
|
|
297
|
+
{spaceInlineBlockClass}
|
|
298
|
+
nags={moveNode.data.nags}
|
|
299
|
+
chessTree={game.chessTree}
|
|
300
|
+
{showUpPriorityItem}
|
|
301
|
+
onDeleteVariant={game.onDeleteVariant}
|
|
302
|
+
/>
|
|
303
|
+
{/if}
|
|
304
|
+
{#if firstCommentText}
|
|
305
|
+
{#if moveNode.data.ply % 2 === 1}
|
|
306
|
+
<MoveComment
|
|
307
|
+
text={firstCommentText}
|
|
308
|
+
{isHighestLevel}
|
|
309
|
+
{spaceBlockClass}
|
|
310
|
+
/>
|
|
311
|
+
{#if !shouldReserveEmptyMoveCell && childMoves?.[0] && !shouldRenderSanInsideVariationGroup}
|
|
312
|
+
{@render fullMovesCounter()}
|
|
313
|
+
{/if}
|
|
314
|
+
{/if}
|
|
315
|
+
|
|
316
|
+
{#if moveNode.data.ply % 2 === 0}
|
|
317
|
+
<MoveComment
|
|
318
|
+
text={firstCommentText}
|
|
319
|
+
{isHighestLevel}
|
|
320
|
+
{spaceBlockClass}
|
|
321
|
+
/>
|
|
322
|
+
{/if}
|
|
294
323
|
{/if}
|
|
295
|
-
{/if}
|
|
296
324
|
{/if}
|
|
297
325
|
|
|
298
326
|
{#if parentNode && parentNode?.children.length > 1 && shouldRenderSiblingVariations}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
327
|
+
{@const showVariationDrillExpand =
|
|
328
|
+
!game.chessTree.isNodeOnMainLine(chessNode)}
|
|
329
|
+
<VariationGroup
|
|
330
|
+
{parentNode}
|
|
331
|
+
{isHighestLevel}
|
|
332
|
+
{isActiveForkForSelection}
|
|
333
|
+
{showVariationDrillExpand}
|
|
334
|
+
{onVariationLinesHit}
|
|
335
|
+
{variationMoveRow}
|
|
336
|
+
isBranchOnCurrentPath={(n) => game.chessTree.isCurrentOnPathFromNode(n)}
|
|
337
|
+
/>
|
|
309
338
|
{/if}
|
|
310
339
|
|
|
311
340
|
{#if isForcedLineStart}
|
|
312
|
-
<div
|
|
313
|
-
class={{
|
|
314
|
-
"col-span-3 col-start-1 w-full min-w-0": isHighestLevel,
|
|
315
|
-
"block w-full min-w-0 basis-full shrink-0": !isHighestLevel,
|
|
316
|
-
}}
|
|
317
|
-
>
|
|
318
341
|
<div
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}}
|
|
342
|
+
class={{
|
|
343
|
+
"col-span-3 col-start-1 w-full min-w-0": isHighestLevel,
|
|
344
|
+
"block w-full min-w-0 basis-full shrink-0": !isHighestLevel,
|
|
345
|
+
}}
|
|
324
346
|
>
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
347
|
+
<div
|
|
348
|
+
class={{
|
|
349
|
+
"block w-full min-w-0": !isHighestLevel,
|
|
350
|
+
[spaceBlockClass]: isHighestLevel,
|
|
351
|
+
"tracking-tight": true,
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
<Move
|
|
355
|
+
{pieceSet}
|
|
356
|
+
chessNode={chessNode.children[0]}
|
|
357
|
+
shouldReserveEmptyMoveCell={chessNode.children.length > 1}
|
|
358
|
+
depth={depth + 1}
|
|
359
|
+
shouldRenderSiblingVariations={true}
|
|
360
|
+
parentNode={chessNode}
|
|
361
|
+
></Move>
|
|
362
|
+
</div>
|
|
333
363
|
</div>
|
|
334
|
-
</div>
|
|
335
364
|
{/if}
|
|
336
365
|
|
|
337
366
|
{#if shouldReserveEmptyMoveCell && moveNode.data.ply % 2 === 1 && isHighestLevel && !isForcedLineStart && childMoves?.[0]}
|
|
338
|
-
|
|
339
|
-
|
|
367
|
+
{@render fullMovesCounter()}
|
|
368
|
+
{@render emptyMove()}
|
|
340
369
|
{/if}
|
|
341
|
-
{#if variationDrillDownActive && isHighestLevel && moveNode.data.ply % 2 === 1 && !shouldReserveEmptyMoveCell && childMoves?.[0] && !isForcedLineStart && chessTree.drillForkParent !== null && chessTree.drillForkParent.children[0]?.id === chessNode.id}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
370
|
+
{#if variationDrillDownActive && isHighestLevel && moveNode.data.ply % 2 === 1 && !shouldReserveEmptyMoveCell && childMoves?.[0] && !isForcedLineStart && game.chessTree.drillForkParent !== null && game.chessTree.drillForkParent.children[0]?.id === chessNode.id}
|
|
371
|
+
<span
|
|
372
|
+
class={{
|
|
373
|
+
"flex items-center justify-center text-center": isHighestLevel,
|
|
374
|
+
}}
|
|
375
|
+
>
|
|
376
|
+
{moveNode.data.fullMoves}
|
|
377
|
+
</span>
|
|
378
|
+
{@render emptyMove()}
|
|
350
379
|
{/if}
|
|
351
380
|
{#if childMoves?.[0] && !shouldRenderSanInsideVariationGroup}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
381
|
+
{#if !isForcedLineStart}
|
|
382
|
+
<Move
|
|
383
|
+
{pieceSet}
|
|
384
|
+
chessNode={chessNode.children[0]}
|
|
385
|
+
shouldReserveEmptyMoveCell={childMoves?.length > 1}
|
|
386
|
+
{depth}
|
|
387
|
+
parentNode={chessNode}
|
|
388
|
+
></Move>
|
|
389
|
+
{/if}
|
|
361
390
|
{/if}
|