@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.
Files changed (43) hide show
  1. package/dist/(components)/BoardSettingsTrigger.svelte +10 -0
  2. package/dist/(components)/BoardSettingsTrigger.svelte.d.ts +18 -0
  3. package/dist/(components)/DrillBreadcrumbs.svelte +6 -8
  4. package/dist/(components)/DrillBreadcrumbs.svelte.d.ts +0 -3
  5. package/dist/(components)/DrillForkSanLabel.svelte +2 -5
  6. package/dist/(components)/DrillForkSanLabel.svelte.d.ts +0 -3
  7. package/dist/(components)/DrillVariationList.svelte +29 -15
  8. package/dist/(components)/DrillVariationList.svelte.d.ts +0 -3
  9. package/dist/(components)/Move.svelte +348 -349
  10. package/dist/(components)/Move.svelte.d.ts +0 -3
  11. package/dist/(components)/MoveComment.svelte +31 -24
  12. package/dist/(components)/MoveComment.svelte.d.ts +2 -0
  13. package/dist/(components)/MoveSanWithMenu.svelte +4 -7
  14. package/dist/(components)/MoveSanWithMenu.svelte.d.ts +0 -3
  15. package/dist/(components)/MoveWithIcon.svelte +60 -65
  16. package/dist/(components)/MoveWithIcon.svelte.d.ts +1 -4
  17. package/dist/(components)/PieceIcon.svelte +27 -44
  18. package/dist/(components)/PieceIcon.svelte.d.ts +3 -6
  19. package/dist/(components)/TreeViewer.svelte +957 -907
  20. package/dist/(components)/TreeViewer.svelte.d.ts +10 -3
  21. package/dist/(components)/VariantDropdownNavigator.svelte +22 -6
  22. package/dist/(components)/VariantDropdownNavigator.svelte.d.ts +8 -3
  23. package/dist/(components)/VariationGroup.svelte +85 -89
  24. package/dist/(constants)/treeViewerThemes.d.ts +12 -0
  25. package/dist/(constants)/treeViewerThemes.js +19 -0
  26. package/dist/(models)/treeViewerTheme.d.ts +17 -0
  27. package/dist/(models)/treeViewerTheme.js +1 -0
  28. package/dist/(utils)/treeViewerPanelNavigation.svelte.d.ts +2 -2
  29. package/dist/(utils)/treeViewerPanelNavigation.svelte.js +12 -5
  30. package/dist/components/ui/context-menu/context-menu-content.svelte +24 -20
  31. package/dist/components/ui/context-menu/context-menu-sub-content.svelte +14 -14
  32. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +26 -22
  33. package/dist/components/ui/toggle/index.d.ts +1 -1
  34. package/dist/components/ui/toggle/index.js +1 -1
  35. package/dist/components/ui/toggle/toggle-variants.d.ts +35 -0
  36. package/dist/components/ui/toggle/toggle-variants.js +19 -0
  37. package/dist/components/ui/toggle/toggle.svelte +1 -27
  38. package/dist/components/ui/toggle/toggle.svelte.d.ts +1 -35
  39. package/dist/index.d.ts +3 -1
  40. package/dist/index.js +2 -1
  41. package/dist/utils/overlayPortalTarget.d.ts +6 -0
  42. package/dist/utils/overlayPortalTarget.js +15 -0
  43. 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
- type TMoveCommentProps = {
3
- /** Возвращает текст комментария (возможны переводы строк). */
4
- text: string;
5
- /** Возвращает true, если строка в верхнем уровне сетки дерева. */
6
- isHighestLevel: boolean;
7
- /** Возвращает класс фона/отступов для уровня «верхняя строка». */
8
- spaceBlockClass: string;
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
- const {
12
- text,
13
- isHighestLevel,
14
- spaceBlockClass,
15
- }: TMoveCommentProps = $props();
13
+ const {
14
+ text,
15
+ isHighestLevel,
16
+ spaceBlockClass,
17
+ showBottomBorder = false,
18
+ }: TMoveCommentProps = $props();
16
19
 
17
- /** Представляет строки комментария после разбиения по `\n`. */
18
- const commentLines = $derived(text.split("\n"));
20
+ /** Представляет строки комментария после разбиения по `\n`. */
21
+ const commentLines = $derived(text.split("\n"));
19
22
  </script>
20
23
 
21
24
  <div
22
- class={{
23
- "select-text": true,
24
- "col-span-3 flex flex-col": isHighestLevel,
25
- inline: !isHighestLevel,
26
- [spaceBlockClass]: isHighestLevel,
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
- {#each commentLines as line, index (index)}
30
- {#if index > 0}<br />{/if}{line}
31
- {/each}
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 border-gray-300": isHighestLevel && mainRowBottomEdge,
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} {pieceSet} />
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} {pieceSet} />
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
- import type { PieceSet } from "@connectorvol/shared";
3
- import type { ParsedSanMove } from "../(utils)/parseSanMove.js";
2
+ import type { ParsedSanMove } from "../(utils)/parseSanMove.js";
4
3
 
5
- import { PieceType } from "@connectorvol/shared";
4
+ import { PieceType } from "@connectorvol/shared";
6
5
 
7
- import { parseSanMove } from "../(utils)/parseSanMove.js";
8
- import PieceIcon from "./PieceIcon.svelte";
6
+ import { parseSanMove } from "../(utils)/parseSanMove.js";
7
+ import PieceIcon from "./PieceIcon.svelte";
9
8
 
10
- interface Props {
11
- /** SAN нотация хода */
12
- san: string;
13
- /** Номер полухода */
14
- ply: number;
15
- /** Размер иконки в пикселях */
16
- iconSize?: number;
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
- const { san, ply, iconSize = 16, pieceSet }: Props = $props();
18
+ const { san, ply, iconSize = 16 }: Props = $props();
22
19
 
23
- const sanParseCache = new Map<string, ParsedSanMove>();
20
+ const sanParseCache = new Map<string, ParsedSanMove>();
24
21
 
25
- function getParsedSanMove(san: string, ply: number): ParsedSanMove {
26
- const key = `${san}|${ply}`;
27
- const cached = sanParseCache.get(key);
28
- if (cached) return cached;
29
- const parsed = parseSanMove(san, ply);
30
- sanParseCache.set(key, parsed);
31
- return parsed;
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
- const parsedMove: ParsedSanMove = $derived(getParsedSanMove(san, ply));
31
+ const parsedMove: ParsedSanMove = $derived(getParsedSanMove(san, ply));
35
32
  </script>
36
33
 
37
34
  <span class="inline-flex items-baseline">
38
- {#if parsedMove.promotionPieceType}
39
- {#if parsedMove.isCapture}
40
- <span>{parsedMove.pawnFile}x{parsedMove.destination}</span>
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 { PieceSet } from "@connectorvol/shared";
3
-
4
- import { Color, DEFAULT_PIECE_SET, PieceType } from "@connectorvol/shared";
5
-
6
- interface Props {
7
- /** Тип фигуры */
8
- pieceType: PieceType;
9
- /** Цвет фигуры */
10
- color: Color;
11
- /** Размер иконки в пикселях */
12
- size?: number;
13
- /** Набор фигур*/
14
- pieceSet?: PieceSet;
15
- }
16
-
17
- const {
18
- pieceType,
19
- color,
20
- size = 16,
21
- pieceSet = DEFAULT_PIECE_SET,
22
- }: Props = $props();
23
- </script>
24
-
25
- <span
26
- class={{
27
- "inline-block translate-x-[1px] translate-y-[2px] self-baseline": true,
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 { PieceSet } from "@connectorvol/shared";
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>;