@connectorvol/tree 8.0.1 → 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/(components)/DrillBreadcrumbs.svelte +6 -8
- package/dist/(components)/DrillBreadcrumbs.svelte.d.ts +0 -3
- package/dist/(components)/DrillForkSanLabel.svelte +2 -5
- package/dist/(components)/DrillForkSanLabel.svelte.d.ts +0 -3
- package/dist/(components)/DrillVariationList.svelte +29 -15
- package/dist/(components)/DrillVariationList.svelte.d.ts +0 -3
- package/dist/(components)/Move.svelte +348 -349
- package/dist/(components)/Move.svelte.d.ts +0 -3
- package/dist/(components)/MoveComment.svelte +31 -24
- package/dist/(components)/MoveComment.svelte.d.ts +2 -0
- package/dist/(components)/MoveSanWithMenu.svelte +4 -7
- package/dist/(components)/MoveSanWithMenu.svelte.d.ts +0 -3
- package/dist/(components)/MoveWithIcon.svelte +60 -65
- package/dist/(components)/MoveWithIcon.svelte.d.ts +1 -4
- package/dist/(components)/PieceIcon.svelte +27 -44
- package/dist/(components)/PieceIcon.svelte.d.ts +3 -6
- package/dist/(components)/TreeViewer.svelte +957 -907
- package/dist/(components)/TreeViewer.svelte.d.ts +10 -3
- package/dist/(components)/VariantDropdownNavigator.svelte +22 -6
- package/dist/(components)/VariantDropdownNavigator.svelte.d.ts +8 -3
- package/dist/(components)/VariationGroup.svelte +85 -89
- package/dist/(constants)/treeViewerThemes.d.ts +12 -0
- package/dist/(constants)/treeViewerThemes.js +19 -0
- package/dist/(models)/treeViewerTheme.d.ts +17 -0
- package/dist/(models)/treeViewerTheme.js +1 -0
- package/dist/(utils)/treeViewerPanelNavigation.svelte.d.ts +2 -2
- package/dist/(utils)/treeViewerPanelNavigation.svelte.js +12 -5
- package/dist/components/ui/context-menu/context-menu-content.svelte +24 -20
- package/dist/components/ui/context-menu/context-menu-sub-content.svelte +14 -14
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +26 -22
- package/dist/components/ui/toggle/index.d.ts +1 -1
- package/dist/components/ui/toggle/index.js +1 -1
- package/dist/components/ui/toggle/toggle-variants.d.ts +35 -0
- package/dist/components/ui/toggle/toggle-variants.js +19 -0
- package/dist/components/ui/toggle/toggle.svelte +1 -27
- package/dist/components/ui/toggle/toggle.svelte.d.ts +1 -35
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/utils/overlayPortalTarget.d.ts +6 -0
- package/dist/utils/overlayPortalTarget.js +15 -0
- package/package.json +15 -14
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ChessTreeNode } from "../(models)/chessTreeNode.js";
|
|
2
2
|
import Move from "./Move.svelte";
|
|
3
|
-
import type { PieceSet } from "@connectorvol/shared";
|
|
4
3
|
type TMoveProps = {
|
|
5
4
|
/** Возвращает узел хода в дереве партии. */
|
|
6
5
|
chessNode: ChessTreeNode;
|
|
@@ -12,8 +11,6 @@ type TMoveProps = {
|
|
|
12
11
|
shouldReserveEmptyMoveCell: boolean;
|
|
13
12
|
/** Возвращает true, если нужно отрисовать соседние варианты у развилки. */
|
|
14
13
|
shouldRenderSiblingVariations?: boolean;
|
|
15
|
-
/** Возвращает набор фигур для иконок SAN. */
|
|
16
|
-
pieceSet: PieceSet;
|
|
17
14
|
};
|
|
18
15
|
declare const Move: import("svelte").Component<TMoveProps, {}, "">;
|
|
19
16
|
type Move = ReturnType<typeof Move>;
|
|
@@ -1,32 +1,39 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
type TMoveCommentProps = {
|
|
3
|
+
/** Возвращает текст комментария (возможны переводы строк). */
|
|
4
|
+
text: string;
|
|
5
|
+
/** Возвращает true, если строка в верхнем уровне сетки дерева. */
|
|
6
|
+
isHighestLevel: boolean;
|
|
7
|
+
/** Возвращает класс фона/отступов для уровня «верхняя строка». */
|
|
8
|
+
spaceBlockClass: string;
|
|
9
|
+
/** Возвращает true, если под комментарием нет следующей строки ходов — рисуем нижнюю границу. */
|
|
10
|
+
showBottomBorder?: boolean;
|
|
11
|
+
};
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const {
|
|
14
|
+
text,
|
|
15
|
+
isHighestLevel,
|
|
16
|
+
spaceBlockClass,
|
|
17
|
+
showBottomBorder = false,
|
|
18
|
+
}: TMoveCommentProps = $props();
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
/** Представляет строки комментария после разбиения по `\n`. */
|
|
21
|
+
const commentLines = $derived(text.split("\n"));
|
|
19
22
|
</script>
|
|
20
23
|
|
|
21
24
|
<div
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
class={{
|
|
26
|
+
"select-text": true,
|
|
27
|
+
"col-span-3 flex flex-col": isHighestLevel,
|
|
28
|
+
inline: !isHighestLevel,
|
|
29
|
+
[spaceBlockClass]: isHighestLevel,
|
|
30
|
+
"border-b": isHighestLevel && showBottomBorder,
|
|
31
|
+
"tree-viewer-overflow-tail-border": isHighestLevel && showBottomBorder,
|
|
32
|
+
}}
|
|
33
|
+
style:background-color={isHighestLevel ? "var(--tree-viewer-bg)" : undefined}
|
|
34
|
+
style:border-color="var(--tree-viewer-border)"
|
|
28
35
|
>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
{#each commentLines as line, index (index)}
|
|
37
|
+
{#if index > 0}<br />{/if}{line}
|
|
38
|
+
{/each}
|
|
32
39
|
</div>
|
|
@@ -5,6 +5,8 @@ type TMoveCommentProps = {
|
|
|
5
5
|
isHighestLevel: boolean;
|
|
6
6
|
/** Возвращает класс фона/отступов для уровня «верхняя строка». */
|
|
7
7
|
spaceBlockClass: string;
|
|
8
|
+
/** Возвращает true, если под комментарием нет следующей строки ходов — рисуем нижнюю границу. */
|
|
9
|
+
showBottomBorder?: boolean;
|
|
8
10
|
};
|
|
9
11
|
declare const MoveComment: import("svelte").Component<TMoveCommentProps, {}, "">;
|
|
10
12
|
type MoveComment = ReturnType<typeof MoveComment>;
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import NagBadges from "./NagBadges.svelte";
|
|
6
6
|
import MoveWithIcon from "./MoveWithIcon.svelte";
|
|
7
7
|
import MoveContextMenu from "./MoveContextMenu.svelte";
|
|
8
|
-
import type { PieceSet } from "@connectorvol/shared";
|
|
9
8
|
import { ACTIVE_MOVE_CLASS } from "../(utils)/scrollToActiveMove.js";
|
|
10
9
|
import type { ChessTree } from "../(classes)/chessTree.svelte.js";
|
|
11
10
|
|
|
@@ -21,8 +20,6 @@
|
|
|
21
20
|
chessNode: ChessTreeNode;
|
|
22
21
|
/** Возвращает родительский узел (для подписей полухода) или null. */
|
|
23
22
|
parentNode: ChessTreeNode | null;
|
|
24
|
-
/** Возвращает набор фигур для иконок SAN. */
|
|
25
|
-
pieceSet: PieceSet;
|
|
26
23
|
/** Возвращает true, если клик по ходу активен. */
|
|
27
24
|
selectable: boolean;
|
|
28
25
|
/** Возвращает true, если ход отображается в верхней строке сетки. */
|
|
@@ -50,7 +47,6 @@
|
|
|
50
47
|
const {
|
|
51
48
|
chessNode,
|
|
52
49
|
parentNode,
|
|
53
|
-
pieceSet,
|
|
54
50
|
selectable,
|
|
55
51
|
isHighestLevel,
|
|
56
52
|
isCurrentMove,
|
|
@@ -98,9 +94,10 @@
|
|
|
98
94
|
[`${spaceInlineBlockClass} text-center`]: isHighestLevel,
|
|
99
95
|
[`z-10 ${ACTIVE_MOVE_CLASS}`]: selectedOnHighestLevel,
|
|
100
96
|
[ACTIVE_MOVE_CLASS]: isCurrentMove && !isHighestLevel,
|
|
101
|
-
"border-b
|
|
97
|
+
"border-b": isHighestLevel && mainRowBottomEdge,
|
|
102
98
|
"tree-viewer-overflow-tail-border": isHighestLevel && mainRowBottomEdge,
|
|
103
99
|
}}
|
|
100
|
+
style:border-color="var(--tree-viewer-border)"
|
|
104
101
|
onmousedown={handleRowMouseDown}
|
|
105
102
|
>
|
|
106
103
|
<ContextMenu.Trigger
|
|
@@ -133,7 +130,7 @@
|
|
|
133
130
|
class="invisible col-start-1 row-start-1 font-bold"
|
|
134
131
|
aria-hidden="true"
|
|
135
132
|
>
|
|
136
|
-
<MoveWithIcon san={node.data.san} ply={node.data.ply}
|
|
133
|
+
<MoveWithIcon san={node.data.san} ply={node.data.ply} />
|
|
137
134
|
</span>
|
|
138
135
|
<span
|
|
139
136
|
class={{
|
|
@@ -141,7 +138,7 @@
|
|
|
141
138
|
"font-bold": isCurrentMove,
|
|
142
139
|
}}
|
|
143
140
|
>
|
|
144
|
-
<MoveWithIcon san={node.data.san} ply={node.data.ply}
|
|
141
|
+
<MoveWithIcon san={node.data.san} ply={node.data.ply} />
|
|
145
142
|
</span>
|
|
146
143
|
</span>
|
|
147
144
|
</span>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ChessTreeNode } from "../(models)/chessTreeNode.js";
|
|
2
|
-
import type { PieceSet } from "@connectorvol/shared";
|
|
3
2
|
import type { ChessTree } from "../(classes)/chessTree.svelte.js";
|
|
4
3
|
type TPreviewHoverHandlers = {
|
|
5
4
|
/** Возвращает обработчик `mouseenter` для превью FEN. */
|
|
@@ -12,8 +11,6 @@ type TMoveSanWithMenuProps = {
|
|
|
12
11
|
chessNode: ChessTreeNode;
|
|
13
12
|
/** Возвращает родительский узел (для подписей полухода) или null. */
|
|
14
13
|
parentNode: ChessTreeNode | null;
|
|
15
|
-
/** Возвращает набор фигур для иконок SAN. */
|
|
16
|
-
pieceSet: PieceSet;
|
|
17
14
|
/** Возвращает true, если клик по ходу активен. */
|
|
18
15
|
selectable: boolean;
|
|
19
16
|
/** Возвращает true, если ход отображается в верхней строке сетки. */
|
|
@@ -1,79 +1,74 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
import type { ParsedSanMove } from "../(utils)/parseSanMove.js";
|
|
2
|
+
import type { ParsedSanMove } from "../(utils)/parseSanMove.js";
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
import { PieceType } from "@connectorvol/shared";
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { parseSanMove } from "../(utils)/parseSanMove.js";
|
|
7
|
+
import PieceIcon from "./PieceIcon.svelte";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
pieceSet?: PieceSet;
|
|
19
|
-
}
|
|
9
|
+
interface Props {
|
|
10
|
+
/** SAN нотация хода */
|
|
11
|
+
san: string;
|
|
12
|
+
/** Номер полухода */
|
|
13
|
+
ply: number;
|
|
14
|
+
/** Размер глифа в пикселях */
|
|
15
|
+
iconSize?: number;
|
|
16
|
+
}
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
const { san, ply, iconSize = 16 }: Props = $props();
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
const sanParseCache = new Map<string, ParsedSanMove>();
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
function getParsedSanMove(san: string, ply: number): ParsedSanMove {
|
|
23
|
+
const key = `${san}|${ply}`;
|
|
24
|
+
const cached = sanParseCache.get(key);
|
|
25
|
+
if (cached) return cached;
|
|
26
|
+
const parsed = parseSanMove(san, ply);
|
|
27
|
+
sanParseCache.set(key, parsed);
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
const parsedMove: ParsedSanMove = $derived(getParsedSanMove(san, ply));
|
|
35
32
|
</script>
|
|
36
33
|
|
|
37
34
|
<span class="inline-flex items-baseline">
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{:else}
|
|
42
|
-
<span>{parsedMove.destination}</span>
|
|
43
|
-
{/if}
|
|
44
|
-
<PieceIcon
|
|
45
|
-
pieceType={parsedMove.promotionPieceType}
|
|
46
|
-
color={parsedMove.color}
|
|
47
|
-
size={iconSize}
|
|
48
|
-
{pieceSet}
|
|
49
|
-
/>
|
|
50
|
-
{#if parsedMove.isCheck}
|
|
51
|
-
<span>+</span>
|
|
52
|
-
{:else if parsedMove.isCheckmate}
|
|
53
|
-
<span>#</span>
|
|
54
|
-
{/if}
|
|
55
|
-
{:else if parsedMove.isCastling || parsedMove.pieceType === PieceType.PAWN}
|
|
56
|
-
<!-- Для рокировки и обычных ходов пешки показываем только текст -->
|
|
57
|
-
<span>{san}</span>
|
|
35
|
+
{#if parsedMove.promotionPieceType}
|
|
36
|
+
{#if parsedMove.isCapture}
|
|
37
|
+
<span>{parsedMove.pawnFile}x{parsedMove.destination}</span>
|
|
58
38
|
{:else}
|
|
59
|
-
|
|
60
|
-
<PieceIcon
|
|
61
|
-
pieceType={parsedMove.pieceType}
|
|
62
|
-
color={parsedMove.color}
|
|
63
|
-
size={iconSize}
|
|
64
|
-
{pieceSet}
|
|
65
|
-
/>
|
|
66
|
-
{#if parsedMove.disambiguation}
|
|
67
|
-
<span>{parsedMove.disambiguation}</span>
|
|
68
|
-
{/if}
|
|
69
|
-
{#if parsedMove.isCapture}
|
|
70
|
-
<span>x</span>
|
|
71
|
-
{/if}
|
|
72
|
-
<span>{parsedMove.destination}</span>
|
|
73
|
-
{#if parsedMove.isCheck}
|
|
74
|
-
<span>+</span>
|
|
75
|
-
{:else if parsedMove.isCheckmate}
|
|
76
|
-
<span>#</span>
|
|
77
|
-
{/if}
|
|
39
|
+
<span>{parsedMove.destination}</span>
|
|
78
40
|
{/if}
|
|
41
|
+
<PieceIcon
|
|
42
|
+
pieceType={parsedMove.promotionPieceType}
|
|
43
|
+
color={parsedMove.color}
|
|
44
|
+
size={iconSize}
|
|
45
|
+
/>
|
|
46
|
+
{#if parsedMove.isCheck}
|
|
47
|
+
<span>+</span>
|
|
48
|
+
{:else if parsedMove.isCheckmate}
|
|
49
|
+
<span>#</span>
|
|
50
|
+
{/if}
|
|
51
|
+
{:else if parsedMove.isCastling || parsedMove.pieceType === PieceType.PAWN}
|
|
52
|
+
<!-- Для рокировки и обычных ходов пешки показываем только текст -->
|
|
53
|
+
<span>{san}</span>
|
|
54
|
+
{:else}
|
|
55
|
+
<!-- Для фигур показываем глиф + уточнение + взятие + координаты -->
|
|
56
|
+
<PieceIcon
|
|
57
|
+
pieceType={parsedMove.pieceType}
|
|
58
|
+
color={parsedMove.color}
|
|
59
|
+
size={iconSize}
|
|
60
|
+
/>
|
|
61
|
+
{#if parsedMove.disambiguation}
|
|
62
|
+
<span>{parsedMove.disambiguation}</span>
|
|
63
|
+
{/if}
|
|
64
|
+
{#if parsedMove.isCapture}
|
|
65
|
+
<span>x</span>
|
|
66
|
+
{/if}
|
|
67
|
+
<span>{parsedMove.destination}</span>
|
|
68
|
+
{#if parsedMove.isCheck}
|
|
69
|
+
<span>+</span>
|
|
70
|
+
{:else if parsedMove.isCheckmate}
|
|
71
|
+
<span>#</span>
|
|
72
|
+
{/if}
|
|
73
|
+
{/if}
|
|
79
74
|
</span>
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { PieceSet } from "@connectorvol/shared";
|
|
2
1
|
interface Props {
|
|
3
2
|
/** SAN нотация хода */
|
|
4
3
|
san: string;
|
|
5
4
|
/** Номер полухода */
|
|
6
5
|
ply: number;
|
|
7
|
-
/** Размер
|
|
6
|
+
/** Размер глифа в пикселях */
|
|
8
7
|
iconSize?: number;
|
|
9
|
-
/** Набор фигур*/
|
|
10
|
-
pieceSet?: PieceSet;
|
|
11
8
|
}
|
|
12
9
|
declare const MoveWithIcon: import("svelte").Component<Props, {}, "">;
|
|
13
10
|
type MoveWithIcon = ReturnType<typeof MoveWithIcon>;
|
|
@@ -1,44 +1,27 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type
|
|
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
|
-
style="width: {size}px; height: {size}px;"
|
|
30
|
-
>
|
|
31
|
-
{#if pieceType === PieceType.PAWN}
|
|
32
|
-
{@render pieceSet.pawn(color)}
|
|
33
|
-
{:else if pieceType === PieceType.KNIGHT}
|
|
34
|
-
{@render pieceSet.knight(color)}
|
|
35
|
-
{:else if pieceType === PieceType.BISHOP}
|
|
36
|
-
{@render pieceSet.bishop(color)}
|
|
37
|
-
{:else if pieceType === PieceType.ROOK}
|
|
38
|
-
{@render pieceSet.rook(color)}
|
|
39
|
-
{:else if pieceType === PieceType.QUEEN}
|
|
40
|
-
{@render pieceSet.queen(color)}
|
|
41
|
-
{:else if pieceType === PieceType.KING}
|
|
42
|
-
{@render pieceSet.king(color)}
|
|
43
|
-
{/if}
|
|
44
|
-
</span>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { pieceGlyph, type Color, type PieceType } from "@connectorvol/shared";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Тип фигуры */
|
|
6
|
+
pieceType: PieceType;
|
|
7
|
+
/** Цвет фигуры (выбор залитого/контурного глифа) */
|
|
8
|
+
color: Color;
|
|
9
|
+
/** Размер глифа в пикселях */
|
|
10
|
+
size?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { pieceType, color, size = 16 }: Props = $props();
|
|
14
|
+
|
|
15
|
+
const glyph = $derived(pieceGlyph(pieceType, color));
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<!--
|
|
19
|
+
ponytail: рендерим глиф инлайновым span'ом и тянем его влево через
|
|
20
|
+
margin-right: -2px, чтобы компенсировать нативный правый padding,
|
|
21
|
+
который есть у шахматных символов в большинстве шрифтов. Без этого
|
|
22
|
+
между ♘ и ходом виден зазор ~2px.
|
|
23
|
+
-->
|
|
24
|
+
<span
|
|
25
|
+
class="tree-viewer-piece leading-none"
|
|
26
|
+
style="font-size: {size}px; margin-right: -2px;">{glyph}</span
|
|
27
|
+
>
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { Color, PieceType } from "@connectorvol/shared";
|
|
1
|
+
import { type Color, type PieceType } from "@connectorvol/shared";
|
|
3
2
|
interface Props {
|
|
4
3
|
/** Тип фигуры */
|
|
5
4
|
pieceType: PieceType;
|
|
6
|
-
/** Цвет фигуры */
|
|
5
|
+
/** Цвет фигуры (выбор залитого/контурного глифа) */
|
|
7
6
|
color: Color;
|
|
8
|
-
/** Размер
|
|
7
|
+
/** Размер глифа в пикселях */
|
|
9
8
|
size?: number;
|
|
10
|
-
/** Набор фигур*/
|
|
11
|
-
pieceSet?: PieceSet;
|
|
12
9
|
}
|
|
13
10
|
declare const PieceIcon: import("svelte").Component<Props, {}, "">;
|
|
14
11
|
type PieceIcon = ReturnType<typeof PieceIcon>;
|