@mirasen/chessboard 1.1.5 → 1.2.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 (131) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +61 -13
  3. package/dist/animation/render/fade.d.ts +2 -3
  4. package/dist/animation/render/fade.js +6 -6
  5. package/dist/animation/render/move.d.ts +2 -3
  6. package/dist/animation/render/move.js +6 -6
  7. package/dist/animation/render/plan.d.ts +3 -4
  8. package/dist/animation/render/plan.js +5 -5
  9. package/dist/animation/render/static.d.ts +2 -3
  10. package/dist/animation/render/static.js +4 -4
  11. package/dist/animation/render/types.d.ts +10 -4
  12. package/dist/extensions/build/index.d.ts +1 -2
  13. package/dist/extensions/build/index.js +1 -1
  14. package/dist/extensions/factory/main.js +11 -7
  15. package/dist/extensions/factory/runtime.js +24 -1
  16. package/dist/extensions/first-party/active-target/factory.js +18 -11
  17. package/dist/extensions/first-party/annotations/api.d.ts +16 -0
  18. package/dist/extensions/first-party/annotations/api.js +79 -0
  19. package/dist/extensions/first-party/annotations/committed.d.ts +3 -0
  20. package/dist/extensions/first-party/annotations/committed.js +11 -0
  21. package/dist/extensions/first-party/annotations/constants.d.ts +3 -0
  22. package/dist/extensions/first-party/annotations/constants.js +54 -0
  23. package/dist/extensions/first-party/annotations/denormalize.d.ts +4 -0
  24. package/dist/extensions/first-party/annotations/denormalize.js +22 -0
  25. package/dist/extensions/first-party/annotations/factory.d.ts +3 -0
  26. package/dist/extensions/first-party/annotations/factory.js +143 -0
  27. package/dist/extensions/first-party/annotations/interaction.d.ts +8 -0
  28. package/dist/extensions/first-party/annotations/interaction.js +129 -0
  29. package/dist/extensions/first-party/annotations/invalidation.d.ts +3 -0
  30. package/dist/extensions/first-party/annotations/invalidation.js +7 -0
  31. package/dist/extensions/first-party/annotations/normalize.d.ts +12 -0
  32. package/dist/extensions/first-party/annotations/normalize.js +54 -0
  33. package/dist/extensions/first-party/annotations/render/committed.d.ts +3 -0
  34. package/dist/extensions/first-party/annotations/render/committed.js +123 -0
  35. package/dist/extensions/first-party/annotations/render/helpers/arrows.d.ts +33 -0
  36. package/dist/extensions/first-party/annotations/render/helpers/arrows.js +93 -0
  37. package/dist/extensions/first-party/annotations/render/helpers/circles.d.ts +18 -0
  38. package/dist/extensions/first-party/annotations/render/helpers/circles.js +30 -0
  39. package/dist/extensions/first-party/annotations/render/preview.d.ts +3 -0
  40. package/dist/extensions/first-party/annotations/render/preview.js +96 -0
  41. package/dist/extensions/first-party/annotations/types/internal.d.ts +77 -0
  42. package/dist/extensions/first-party/annotations/types/internal.js +1 -0
  43. package/dist/extensions/first-party/annotations/types/main.d.ts +40 -0
  44. package/dist/extensions/first-party/annotations/types/main.js +6 -0
  45. package/dist/extensions/first-party/annotations/types/public.d.ts +48 -0
  46. package/dist/extensions/first-party/annotations/types/public.js +1 -0
  47. package/dist/extensions/first-party/annotations/update.d.ts +3 -0
  48. package/dist/extensions/first-party/annotations/update.js +45 -0
  49. package/dist/extensions/first-party/auto-promote/factory.js +6 -6
  50. package/dist/extensions/first-party/board-events/factory.js +6 -6
  51. package/dist/extensions/first-party/common/helpers.d.ts +2 -1
  52. package/dist/extensions/first-party/common/helpers.js +6 -5
  53. package/dist/extensions/first-party/common/types.d.ts +2 -0
  54. package/dist/extensions/first-party/last-move/factory.js +9 -9
  55. package/dist/extensions/first-party/legal-moves/factory.js +8 -8
  56. package/dist/extensions/first-party/main-renderer/animation/factory.d.ts +2 -2
  57. package/dist/extensions/first-party/main-renderer/animation/factory.js +4 -4
  58. package/dist/extensions/first-party/main-renderer/animation/render.d.ts +1 -1
  59. package/dist/extensions/first-party/main-renderer/animation/render.js +2 -2
  60. package/dist/extensions/first-party/main-renderer/animation/types.d.ts +3 -3
  61. package/dist/extensions/first-party/main-renderer/board/factory.js +2 -2
  62. package/dist/extensions/first-party/main-renderer/board/render.d.ts +1 -1
  63. package/dist/extensions/first-party/main-renderer/board/render.js +4 -4
  64. package/dist/extensions/first-party/main-renderer/board/types.d.ts +1 -1
  65. package/dist/extensions/first-party/main-renderer/coordinates/factory.js +2 -2
  66. package/dist/extensions/first-party/main-renderer/coordinates/render.d.ts +1 -1
  67. package/dist/extensions/first-party/main-renderer/coordinates/render.js +5 -5
  68. package/dist/extensions/first-party/main-renderer/coordinates/types.d.ts +1 -1
  69. package/dist/extensions/first-party/main-renderer/drag/factory.d.ts +2 -2
  70. package/dist/extensions/first-party/main-renderer/drag/factory.js +11 -8
  71. package/dist/extensions/first-party/main-renderer/drag/render.d.ts +1 -1
  72. package/dist/extensions/first-party/main-renderer/drag/render.js +7 -6
  73. package/dist/extensions/first-party/main-renderer/drag/types.d.ts +6 -5
  74. package/dist/extensions/first-party/main-renderer/drag/update.js +2 -2
  75. package/dist/extensions/first-party/main-renderer/factory.js +9 -5
  76. package/dist/extensions/first-party/main-renderer/piece-symbols.d.ts +19 -0
  77. package/dist/extensions/first-party/main-renderer/piece-symbols.js +45 -0
  78. package/dist/extensions/first-party/main-renderer/pieces/factory.d.ts +2 -2
  79. package/dist/extensions/first-party/main-renderer/pieces/factory.js +4 -4
  80. package/dist/extensions/first-party/main-renderer/pieces/render.d.ts +1 -1
  81. package/dist/extensions/first-party/main-renderer/pieces/render.js +8 -8
  82. package/dist/extensions/first-party/main-renderer/pieces/types.d.ts +4 -4
  83. package/dist/extensions/first-party/main-renderer/types/extension.d.ts +1 -1
  84. package/dist/extensions/first-party/main-renderer/types/extension.js +8 -1
  85. package/dist/extensions/first-party/main-renderer/types/instance.d.ts +2 -0
  86. package/dist/extensions/first-party/promotion/factory.js +10 -10
  87. package/dist/extensions/first-party/selected-square/factory.js +8 -8
  88. package/dist/extensions/first-party/watermark/factory.js +8 -8
  89. package/dist/extensions/types/basic/events.d.ts +32 -3
  90. package/dist/extensions/types/basic/events.js +2 -1
  91. package/dist/extensions/types/basic/mount.d.ts +5 -2
  92. package/dist/extensions/types/basic/mount.js +0 -2
  93. package/dist/extensions/types/basic/transient-visuals.d.ts +1 -1
  94. package/dist/extensions/types/context/animation.d.ts +3 -3
  95. package/dist/extensions/types/context/events.d.ts +2 -1
  96. package/dist/extensions/types/context/update.d.ts +6 -7
  97. package/dist/extensions/types/extension.d.ts +3 -0
  98. package/dist/extensions/types/main.d.ts +1 -0
  99. package/dist/extensions/types/surface/commands.d.ts +1 -1
  100. package/dist/extensions/types/surface/main.d.ts +6 -4
  101. package/dist/extensions/types/wrapper.d.ts +3 -1
  102. package/dist/extensions/types/wrapper.js +6 -2
  103. package/dist/extensions/update.js +6 -10
  104. package/dist/index.d.ts +1 -1
  105. package/dist/render/mount.js +3 -3
  106. package/dist/render/rendering/state.js +2 -2
  107. package/dist/render/svg/factory.js +40 -25
  108. package/dist/render/svg/helpers.d.ts +8 -4
  109. package/dist/render/svg/helpers.js +27 -12
  110. package/dist/render/svg/ids.d.ts +6 -0
  111. package/dist/render/svg/ids.js +11 -0
  112. package/dist/render/types.d.ts +4 -3
  113. package/dist/render/types.js +2 -1
  114. package/dist/runtime/factory/input.d.ts +3 -1
  115. package/dist/runtime/factory/input.js +11 -2
  116. package/dist/runtime/factory/main.js +10 -4
  117. package/dist/runtime/input/adapter/event.js +2 -2
  118. package/dist/runtime/input/adapter/pointer.d.ts +2 -2
  119. package/dist/runtime/input/controller/factory.d.ts +1 -1
  120. package/dist/runtime/input/controller/factory.js +35 -15
  121. package/dist/runtime/input/controller/helpers.d.ts +1 -1
  122. package/dist/runtime/input/controller/interaction.d.ts +3 -0
  123. package/dist/runtime/input/controller/interaction.js +14 -0
  124. package/dist/runtime/input/controller/pointer.d.ts +6 -6
  125. package/dist/runtime/input/controller/pointer.js +53 -27
  126. package/dist/runtime/input/controller/transient-visuals.d.ts +2 -3
  127. package/dist/runtime/input/controller/types.d.ts +6 -5
  128. package/dist/runtime/types/main.d.ts +1 -1
  129. package/dist/wrapper/factory.js +2 -7
  130. package/dist/wrapper/types.d.ts +3 -11
  131. package/package.json +1 -2
@@ -0,0 +1,79 @@
1
+ import { normalizeSquare } from '../../../state/board/normalize.js';
2
+ import { denormalizeArrows, denormalizeCircles } from './denormalize.js';
3
+ import { markCommittedDirtyAndRequestRender } from './invalidation.js';
4
+ import { arrowAnnotationKey, normalizeArrowAnnotation, normalizeCircleAnnotation } from './normalize.js';
5
+ export function annotationsGetCircles(state) {
6
+ return denormalizeCircles(state.annotations.circles);
7
+ }
8
+ export function annotationsGetArrows(state) {
9
+ return denormalizeArrows(state.annotations.arrows);
10
+ }
11
+ export function annotationsSetCircles(state, circles) {
12
+ state.annotations.circles.clear();
13
+ for (const pub of circles) {
14
+ const circle = normalizeCircleAnnotation(pub);
15
+ state.annotations.circles.set(circle.key, circle);
16
+ }
17
+ markCommittedDirtyAndRequestRender(state);
18
+ }
19
+ export function annotationsSetArrows(state, arrows) {
20
+ // Validate all entries before mutating state (atomic behavior)
21
+ const normalized = arrows.map((pub) => normalizeArrowAnnotation(pub));
22
+ state.annotations.arrows.clear();
23
+ for (const arrow of normalized) {
24
+ state.annotations.arrows.set(arrow.key, arrow);
25
+ }
26
+ markCommittedDirtyAndRequestRender(state);
27
+ }
28
+ export function annotationsSetCircle(state, square, annotation) {
29
+ const key = normalizeSquare(square);
30
+ if (annotation === null) {
31
+ state.annotations.circles.delete(key);
32
+ }
33
+ else {
34
+ const normalizedAnnotation = normalizeCircleAnnotation({
35
+ square,
36
+ color: annotation.color
37
+ });
38
+ state.annotations.circles.set(key, normalizedAnnotation);
39
+ }
40
+ markCommittedDirtyAndRequestRender(state);
41
+ }
42
+ export function annotationsSetArrow(state, from, to, annotation) {
43
+ const key = arrowAnnotationKey(from, to);
44
+ if (annotation === null) {
45
+ state.annotations.arrows.delete(key);
46
+ }
47
+ else {
48
+ const normalizedArrow = normalizeArrowAnnotation({
49
+ from,
50
+ to,
51
+ color: annotation.color
52
+ });
53
+ state.annotations.arrows.set(key, normalizedArrow);
54
+ }
55
+ markCommittedDirtyAndRequestRender(state);
56
+ }
57
+ export function annotationsClear(state) {
58
+ state.annotations.circles.clear();
59
+ state.annotations.arrows.clear();
60
+ markCommittedDirtyAndRequestRender(state);
61
+ }
62
+ export function annotationsSetClearOnCoreInteraction(state, value) {
63
+ state.config.clearOnCoreInteraction = value;
64
+ }
65
+ export function annotationsGetClearOnCoreInteraction(state) {
66
+ return state.config.clearOnCoreInteraction;
67
+ }
68
+ export function annotationsSetDrawButton(state, value) {
69
+ state.config.drawButton = value;
70
+ }
71
+ export function annotationsGetDrawButton(state) {
72
+ return state.config.drawButton;
73
+ }
74
+ export function annotationsSetDrawModifier(state, value) {
75
+ state.config.drawModifier = value;
76
+ }
77
+ export function annotationsGetDrawModifier(state) {
78
+ return state.config.drawModifier;
79
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnnotationsStateInternal } from './types/main.js';
2
+ export declare function hasCommittedAnnotations(state: AnnotationsStateInternal): boolean;
3
+ export declare function clearCommittedAnnotations(state: AnnotationsStateInternal): boolean;
@@ -0,0 +1,11 @@
1
+ export function hasCommittedAnnotations(state) {
2
+ return state.annotations.circles.size > 0 || state.annotations.arrows.size > 0;
3
+ }
4
+ export function clearCommittedAnnotations(state) {
5
+ if (state.annotations.circles.size === 0 && state.annotations.arrows.size === 0) {
6
+ return false;
7
+ }
8
+ state.annotations.circles.clear();
9
+ state.annotations.arrows.clear();
10
+ return true;
11
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnnotationsConfig, VisualConfig } from './types/internal.js';
2
+ export declare const DEFAULT_CONFIG: AnnotationsConfig;
3
+ export declare const VISUAL_CONFIG: VisualConfig;
@@ -0,0 +1,54 @@
1
+ export const DEFAULT_CONFIG = {
2
+ clearOnCoreInteraction: true,
3
+ colors: {
4
+ none: '#15781B',
5
+ ctrl: '#882020',
6
+ shift: '#e68f00',
7
+ alt: '#003088',
8
+ meta: '#6f2da8'
9
+ },
10
+ drawButton: 2,
11
+ drawModifier: null
12
+ };
13
+ export const VISUAL_CONFIG = {
14
+ circle: {
15
+ committed: {
16
+ strokeWidth: 0.0625,
17
+ radius: 0.46875,
18
+ opacity: 1
19
+ },
20
+ previewAdd: {
21
+ strokeWidth: 0.05,
22
+ radius: 0.46875,
23
+ opacity: 0.8
24
+ },
25
+ previewRemoveOpacity: 0.25
26
+ },
27
+ arrow: {
28
+ committed: {
29
+ strokeWidth: 0.15625,
30
+ startOffset: 0,
31
+ endOffset: 0.15625,
32
+ opacity: 0.75,
33
+ markerWidth: 4,
34
+ markerHeight: 4,
35
+ markerRefX: 2.05,
36
+ markerRefY: 2,
37
+ markerViewBox: '0 0 4 4',
38
+ markerPathD: 'M0,0 V4 L3,2 Z'
39
+ },
40
+ previewAdd: {
41
+ strokeWidth: 0.11,
42
+ startOffset: 0,
43
+ endOffset: 0.15625,
44
+ opacity: 0.55,
45
+ markerWidth: 4,
46
+ markerHeight: 4,
47
+ markerRefX: 2.05,
48
+ markerRefY: 2,
49
+ markerViewBox: '0 0 4 4',
50
+ markerPathD: 'M0,0 V4 L3,2 Z'
51
+ },
52
+ previewRemoveOpacity: 0.25
53
+ }
54
+ };
@@ -0,0 +1,4 @@
1
+ import type { ArrowAnnotation, ArrowAnnotationKey, CircleAnnotation, CircleAnnotationKey } from './types/internal.js';
2
+ import type { ArrowAnnotationPublic, CircleAnnotationPublic } from './types/public.js';
3
+ export declare function denormalizeCircles(circles: Map<CircleAnnotationKey, CircleAnnotation>): CircleAnnotationPublic[];
4
+ export declare function denormalizeArrows(arrows: Map<ArrowAnnotationKey, ArrowAnnotation>): ArrowAnnotationPublic[];
@@ -0,0 +1,22 @@
1
+ import { denormalizeSquare } from '../../../state/board/denormalize.js';
2
+ export function denormalizeCircles(circles) {
3
+ const result = [];
4
+ for (const circle of circles.values()) {
5
+ result.push({
6
+ square: denormalizeSquare(circle.square),
7
+ color: circle.color
8
+ });
9
+ }
10
+ return result;
11
+ }
12
+ export function denormalizeArrows(arrows) {
13
+ const result = [];
14
+ for (const arrow of arrows.values()) {
15
+ result.push({
16
+ from: denormalizeSquare(arrow.from),
17
+ to: denormalizeSquare(arrow.to),
18
+ color: arrow.color
19
+ });
20
+ }
21
+ return result;
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnnotationsDefinition } from './types/main.js';
2
+ import type { AnnotationsInitOptions } from './types/public.js';
3
+ export declare function createAnnotations(options?: AnnotationsInitOptions): AnnotationsDefinition;
@@ -0,0 +1,143 @@
1
+ import { cloneDeep } from 'es-toolkit';
2
+ import { extensionCreateInternalBase, extensionDestroyBase, extensionMountBase, extensionUnmountBase } from '../common/helpers.js';
3
+ import { annotationsClear, annotationsGetArrows, annotationsGetCircles, annotationsGetClearOnCoreInteraction, annotationsGetDrawButton, annotationsGetDrawModifier, annotationsSetArrow, annotationsSetArrows, annotationsSetCircle, annotationsSetCircles, annotationsSetClearOnCoreInteraction, annotationsSetDrawButton, annotationsSetDrawModifier } from './api.js';
4
+ import { cancelAnnotationsDrag, completeAnnotationsDrag, handleAnnotationsEvent } from './interaction.js';
5
+ import { normalizeAnnotationsConfig, normalizeInitialAnnotations } from './normalize.js';
6
+ import { renderCommittedAnnotations } from './render/committed.js';
7
+ import { renderPreviewAnnotations } from './render/preview.js';
8
+ import { EXTENSION_ID, EXTENSION_SLOTS } from './types/main.js';
9
+ import { annotationsOnUpdate } from './update.js';
10
+ export function createAnnotations(options = {}) {
11
+ const normalizedConfig = normalizeAnnotationsConfig(options.config);
12
+ const normalizedAnnotations = normalizeInitialAnnotations(options.annotations);
13
+ return {
14
+ id: EXTENSION_ID,
15
+ slots: EXTENSION_SLOTS,
16
+ createInstance(runtimeOptions) {
17
+ return createAnnotationsInstance(normalizedConfig, normalizedAnnotations, runtimeOptions);
18
+ }
19
+ };
20
+ }
21
+ function createAnnotationsInternal(normalizedConfig, normalizedAnnotations, runtimeOptions) {
22
+ // Clone to ensure each instance has independent mutable state
23
+ const config = cloneDeep(normalizedConfig);
24
+ const annotations = {
25
+ circles: new Map(normalizedAnnotations.circles),
26
+ arrows: new Map(normalizedAnnotations.arrows)
27
+ };
28
+ return {
29
+ ...extensionCreateInternalBase(runtimeOptions),
30
+ runtimeSurface: runtimeOptions.runtimeSurface,
31
+ svg: {
32
+ svgCircles: new Map(),
33
+ svgArrows: new Map()
34
+ },
35
+ annotations,
36
+ config,
37
+ activeDrawGesture: null,
38
+ activeDrawPreviewTarget: null,
39
+ previewSvg: { circle: null, arrow: null }
40
+ };
41
+ }
42
+ function extensionCleanSvg(state) {
43
+ state.svg.svgCircles.clear();
44
+ state.svg.svgArrows.clear();
45
+ if (state.previewSvg.arrow) {
46
+ state.previewSvg.arrow.marker.remove();
47
+ }
48
+ state.previewSvg.circle = null;
49
+ state.previewSvg.arrow = null;
50
+ }
51
+ function extensionClean(state) {
52
+ state.runtimeSurface.events.unsubscribeEvent('pointerdown');
53
+ state.runtimeSurface.events.unsubscribeEvent('contextmenu');
54
+ state.activeDrawGesture = null;
55
+ state.activeDrawPreviewTarget = null;
56
+ extensionCleanSvg(state);
57
+ }
58
+ function createAnnotationsPublicAPI(state) {
59
+ return {
60
+ getCircles() {
61
+ return annotationsGetCircles(state);
62
+ },
63
+ getArrows() {
64
+ return annotationsGetArrows(state);
65
+ },
66
+ setCircles(circles) {
67
+ annotationsSetCircles(state, circles);
68
+ },
69
+ setArrows(arrows) {
70
+ annotationsSetArrows(state, arrows);
71
+ },
72
+ circle(square, annotation) {
73
+ annotationsSetCircle(state, square, annotation);
74
+ },
75
+ arrow(from, to, annotation) {
76
+ annotationsSetArrow(state, from, to, annotation);
77
+ },
78
+ clear() {
79
+ annotationsClear(state);
80
+ },
81
+ get clearOnCoreInteraction() {
82
+ return annotationsGetClearOnCoreInteraction(state);
83
+ },
84
+ set clearOnCoreInteraction(value) {
85
+ annotationsSetClearOnCoreInteraction(state, value);
86
+ },
87
+ get drawButton() {
88
+ return annotationsGetDrawButton(state);
89
+ },
90
+ set drawButton(value) {
91
+ annotationsSetDrawButton(state, value);
92
+ },
93
+ get drawModifier() {
94
+ return annotationsGetDrawModifier(state);
95
+ },
96
+ set drawModifier(value) {
97
+ annotationsSetDrawModifier(state, value);
98
+ }
99
+ };
100
+ }
101
+ function createAnnotationsInstance(normalizedConfig, normalizedAnnotations, runtimeOptions) {
102
+ const internalState = createAnnotationsInternal(normalizedConfig, normalizedAnnotations, runtimeOptions);
103
+ const publicAPI = createAnnotationsPublicAPI(internalState);
104
+ return {
105
+ id: EXTENSION_ID,
106
+ mount(env) {
107
+ extensionMountBase(internalState, env.slotRoots);
108
+ internalState.runtimeSurface.events.subscribeEvent('pointerdown');
109
+ internalState.runtimeSurface.events.subscribeEvent('contextmenu');
110
+ },
111
+ onUpdate(context) {
112
+ annotationsOnUpdate(internalState, context);
113
+ },
114
+ render(context) {
115
+ if (context.invalidation.dirtyLayers & 1 /* DirtyLayer.COMMITTED */) {
116
+ renderCommittedAnnotations(internalState, context.currentFrame.layout.geometry);
117
+ }
118
+ if (context.invalidation.dirtyLayers & 2 /* DirtyLayer.PREVIEW */) {
119
+ renderPreviewAnnotations(internalState, context.currentFrame.layout.geometry);
120
+ }
121
+ },
122
+ onEvent(context) {
123
+ handleAnnotationsEvent(internalState, context);
124
+ },
125
+ completeDrag(session) {
126
+ completeAnnotationsDrag(internalState, session);
127
+ },
128
+ cancelDrag(session) {
129
+ cancelAnnotationsDrag(internalState, session);
130
+ },
131
+ unmount() {
132
+ extensionClean(internalState);
133
+ extensionUnmountBase(internalState);
134
+ },
135
+ destroy() {
136
+ extensionClean(internalState);
137
+ extensionDestroyBase(internalState);
138
+ },
139
+ getPublic() {
140
+ return publicAPI;
141
+ }
142
+ };
143
+ }
@@ -0,0 +1,8 @@
1
+ import type { ExtensionDragSessionSnapshot } from '../../types/basic/interaction.js';
2
+ import type { ExtensionOnEventContext } from '../../types/context/events.js';
3
+ import type { AnnotationColor, AnnotationsConfig } from './types/internal.js';
4
+ import type { AnnotationsStateInternal } from './types/main.js';
5
+ export declare function resolveAnnotationColor(config: AnnotationsConfig, rawEvent: PointerEvent): AnnotationColor;
6
+ export declare function handleAnnotationsEvent(state: AnnotationsStateInternal, context: ExtensionOnEventContext): void;
7
+ export declare function completeAnnotationsDrag(state: AnnotationsStateInternal, session: ExtensionDragSessionSnapshot): void;
8
+ export declare function cancelAnnotationsDrag(state: AnnotationsStateInternal, session: ExtensionDragSessionSnapshot): void;
@@ -0,0 +1,129 @@
1
+ import assert from '@ktarmyshov/assert';
2
+ import { clearCommittedAnnotations, hasCommittedAnnotations } from './committed.js';
3
+ import { markCommittedDirtyAndRequestRender } from './invalidation.js';
4
+ import { arrowAnnotationKeyNormalized } from './normalize.js';
5
+ const ANNOTATIONS_IDLE_CLEAR_DRAG_TYPE = 'ext:idle-clear';
6
+ const ANNOTATIONS_DRAW_DRAG_TYPE = 'ext:draw';
7
+ export function resolveAnnotationColor(config, rawEvent) {
8
+ if (config.drawModifier != null) {
9
+ return config.colors[config.drawModifier];
10
+ }
11
+ if (rawEvent.ctrlKey)
12
+ return config.colors.ctrl;
13
+ if (rawEvent.shiftKey)
14
+ return config.colors.shift;
15
+ if (rawEvent.altKey)
16
+ return config.colors.alt;
17
+ if (rawEvent.metaKey)
18
+ return config.colors.meta;
19
+ return config.colors.none;
20
+ }
21
+ export function handleAnnotationsEvent(state, context) {
22
+ assert(context.rawEvent.type === 'pointerdown' || context.rawEvent.type === 'contextmenu');
23
+ if (context.rawEvent.type === 'contextmenu') {
24
+ // Browser context menus are separate from the pointer drag lifecycle.
25
+ // The board owns secondary-button interaction, so suppress the browser menu.
26
+ context.rawEvent.preventDefault();
27
+ return;
28
+ }
29
+ const rawEvent = context.rawEvent;
30
+ // The configured draw button owns annotation drawing gestures.
31
+ // If configured as primary, drawing intentionally takes precedence over idle-clear.
32
+ if (rawEvent.button === state.config.drawButton) {
33
+ const targetSquare = context.sceneEvent?.targetSquare;
34
+ if (targetSquare === undefined || targetSquare === null)
35
+ return;
36
+ state.activeDrawGesture = {
37
+ sourceSquare: targetSquare,
38
+ color: resolveAnnotationColor(state.config, rawEvent)
39
+ };
40
+ const success = state.runtimeSurface.commands.startDrag({
41
+ type: ANNOTATIONS_DRAW_DRAG_TYPE,
42
+ sourceSquare: targetSquare,
43
+ sourcePieceCode: null,
44
+ targetSquare: targetSquare
45
+ });
46
+ if (success) {
47
+ rawEvent.preventDefault();
48
+ }
49
+ else {
50
+ state.activeDrawGesture = null;
51
+ }
52
+ return;
53
+ }
54
+ // Drawing uses the configured draw button above.
55
+ // The remaining primary-button path is reserved for idle-clear.
56
+ if (rawEvent.button !== 0)
57
+ return;
58
+ const targetSquare = context.sceneEvent?.targetSquare;
59
+ if (targetSquare === undefined || targetSquare === null)
60
+ return;
61
+ if (context.runtimeInteractionActionPreview !== null)
62
+ return;
63
+ if (!state.config.clearOnCoreInteraction)
64
+ return;
65
+ if (!hasCommittedAnnotations(state))
66
+ return;
67
+ const success = state.runtimeSurface.commands.startDrag({
68
+ type: ANNOTATIONS_IDLE_CLEAR_DRAG_TYPE,
69
+ sourceSquare: targetSquare,
70
+ sourcePieceCode: null,
71
+ targetSquare: targetSquare
72
+ });
73
+ if (success) {
74
+ rawEvent.preventDefault();
75
+ }
76
+ }
77
+ export function completeAnnotationsDrag(state, session) {
78
+ if (session.type === ANNOTATIONS_DRAW_DRAG_TYPE) {
79
+ const gesture = state.activeDrawGesture;
80
+ state.activeDrawGesture = null;
81
+ state.activeDrawPreviewTarget = null;
82
+ if (!gesture)
83
+ return;
84
+ if (session.targetSquare === null)
85
+ return;
86
+ if (gesture.sourceSquare === session.targetSquare) {
87
+ commitCircleToggle(state, gesture.sourceSquare, gesture.color);
88
+ }
89
+ else {
90
+ commitArrowToggle(state, gesture.sourceSquare, session.targetSquare, gesture.color);
91
+ }
92
+ return;
93
+ }
94
+ if (session.type !== ANNOTATIONS_IDLE_CLEAR_DRAG_TYPE)
95
+ return;
96
+ if (session.targetSquare === null)
97
+ return;
98
+ if (!hasCommittedAnnotations(state))
99
+ return;
100
+ clearCommittedAnnotations(state);
101
+ markCommittedDirtyAndRequestRender(state);
102
+ }
103
+ export function cancelAnnotationsDrag(state, session) {
104
+ if (session.type === ANNOTATIONS_DRAW_DRAG_TYPE) {
105
+ state.activeDrawGesture = null;
106
+ state.activeDrawPreviewTarget = null;
107
+ }
108
+ }
109
+ function commitCircleToggle(state, square, color) {
110
+ const existing = state.annotations.circles.get(square);
111
+ if (existing && existing.color === color) {
112
+ state.annotations.circles.delete(square);
113
+ }
114
+ else {
115
+ state.annotations.circles.set(square, { key: square, square, color });
116
+ }
117
+ markCommittedDirtyAndRequestRender(state);
118
+ }
119
+ function commitArrowToggle(state, from, to, color) {
120
+ const key = arrowAnnotationKeyNormalized(from, to);
121
+ const existing = state.annotations.arrows.get(key);
122
+ if (existing && existing.color === color) {
123
+ state.annotations.arrows.delete(key);
124
+ }
125
+ else {
126
+ state.annotations.arrows.set(key, { key, from, to, color });
127
+ }
128
+ markCommittedDirtyAndRequestRender(state);
129
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnnotationsStateInternal } from './types/main.js';
2
+ export declare function markDirtyAndRequestRender(state: AnnotationsStateInternal, layers: number): void;
3
+ export declare function markCommittedDirtyAndRequestRender(state: AnnotationsStateInternal): void;
@@ -0,0 +1,7 @@
1
+ export function markDirtyAndRequestRender(state, layers) {
2
+ state.runtimeSurface.invalidation.markDirty(layers);
3
+ state.runtimeSurface.commands.requestRender({ state: true });
4
+ }
5
+ export function markCommittedDirtyAndRequestRender(state) {
6
+ markDirtyAndRequestRender(state, 1 /* DirtyLayer.COMMITTED */);
7
+ }
@@ -0,0 +1,12 @@
1
+ import type { SquareString } from '../../../state/board/types/input.js';
2
+ import type { Square } from '../../../state/board/types/internal.js';
3
+ import type { AnnotationsConfig, ArrowAnnotation, ArrowAnnotationKey, CircleAnnotation, CircleAnnotationKey } from './types/internal.js';
4
+ import type { AnnotationsStateInternalAnnotations } from './types/main.js';
5
+ import type { AnnotationsInitOptionsAnnotations, AnnotationsInitOptionsConfig, ArrowAnnotationPublic, CircleAnnotationPublic } from './types/public.js';
6
+ export declare function normalizeAnnotationsConfig(input?: AnnotationsInitOptionsConfig): AnnotationsConfig;
7
+ export declare function circleAnnotationKey(square: SquareString): CircleAnnotationKey;
8
+ export declare function normalizeCircleAnnotation(pub: CircleAnnotationPublic): CircleAnnotation;
9
+ export declare function arrowAnnotationKeyNormalized(from: Square, to: Square): ArrowAnnotationKey;
10
+ export declare function arrowAnnotationKey(from: SquareString, to: SquareString): ArrowAnnotationKey;
11
+ export declare function normalizeArrowAnnotation(pub: ArrowAnnotationPublic): ArrowAnnotation;
12
+ export declare function normalizeInitialAnnotations(input?: AnnotationsInitOptionsAnnotations): AnnotationsStateInternalAnnotations;
@@ -0,0 +1,54 @@
1
+ import { cloneDeep, toMerged } from 'es-toolkit';
2
+ import { normalizeSquare } from '../../../state/board/normalize.js';
3
+ import { DEFAULT_CONFIG } from './constants.js';
4
+ export function normalizeAnnotationsConfig(input) {
5
+ if (!input) {
6
+ return cloneDeep(DEFAULT_CONFIG);
7
+ }
8
+ return toMerged(DEFAULT_CONFIG, input);
9
+ }
10
+ export function circleAnnotationKey(square) {
11
+ return normalizeSquare(square);
12
+ }
13
+ export function normalizeCircleAnnotation(pub) {
14
+ const square = normalizeSquare(pub.square);
15
+ return {
16
+ key: square,
17
+ square,
18
+ color: pub.color
19
+ };
20
+ }
21
+ export function arrowAnnotationKeyNormalized(from, to) {
22
+ if (from === to) {
23
+ throw new Error("Invalid arrow: 'from' and 'to' must be different squares");
24
+ }
25
+ return from * 64 + to;
26
+ }
27
+ export function arrowAnnotationKey(from, to) {
28
+ const fromKey = normalizeSquare(from);
29
+ const toKey = normalizeSquare(to);
30
+ return arrowAnnotationKeyNormalized(fromKey, toKey);
31
+ }
32
+ export function normalizeArrowAnnotation(pub) {
33
+ const from = normalizeSquare(pub.from);
34
+ const to = normalizeSquare(pub.to);
35
+ const key = arrowAnnotationKeyNormalized(from, to);
36
+ return { key, from, to, color: pub.color };
37
+ }
38
+ export function normalizeInitialAnnotations(input) {
39
+ const circles = new Map();
40
+ const arrows = new Map();
41
+ if (input?.circles) {
42
+ for (const pub of input.circles) {
43
+ const circle = normalizeCircleAnnotation(pub);
44
+ circles.set(circle.key, circle);
45
+ }
46
+ }
47
+ if (input?.arrows) {
48
+ for (const pub of input.arrows) {
49
+ const arrow = normalizeArrowAnnotation(pub);
50
+ arrows.set(arrow.key, arrow);
51
+ }
52
+ }
53
+ return { circles, arrows };
54
+ }
@@ -0,0 +1,3 @@
1
+ import type { SceneRenderGeometry } from '../../../../layout/geometry/types.js';
2
+ import type { AnnotationsStateInternal } from '../types/main.js';
3
+ export declare function renderCommittedAnnotations(state: AnnotationsStateInternal, geometry: SceneRenderGeometry): void;