@fgv/ts-sudoku-ui 5.0.1-10
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/.rush/temp/chunked-rush-logs/ts-sudoku-ui.build.chunks.jsonl +14 -0
- package/.rush/temp/operation/build/log-chunks.jsonl +14 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +1086 -0
- package/.test-failures-catalog.md +470 -0
- package/CSS_MODULES_MIGRATION_SUMMARY.md +189 -0
- package/dist/ts-sudoku-ui.d.ts +668 -0
- package/etc/ts-sudoku-ui.api.md +481 -0
- package/lib/components/CageOverlay.d.ts +8 -0
- package/lib/components/CageOverlay.d.ts.map +1 -0
- package/lib/components/CageOverlay.js +133 -0
- package/lib/components/CageOverlay.js.map +1 -0
- package/lib/components/CageSumIndicator.d.ts +8 -0
- package/lib/components/CageSumIndicator.d.ts.map +1 -0
- package/lib/components/CageSumIndicator.js +66 -0
- package/lib/components/CageSumIndicator.js.map +1 -0
- package/lib/components/CombinationCard.d.ts +8 -0
- package/lib/components/CombinationCard.d.ts.map +1 -0
- package/lib/components/CombinationCard.js +64 -0
- package/lib/components/CombinationCard.js.map +1 -0
- package/lib/components/CombinationGrid.d.ts +8 -0
- package/lib/components/CombinationGrid.d.ts.map +1 -0
- package/lib/components/CombinationGrid.js +51 -0
- package/lib/components/CombinationGrid.js.map +1 -0
- package/lib/components/CompactControlRibbon.d.ts +45 -0
- package/lib/components/CompactControlRibbon.d.ts.map +1 -0
- package/lib/components/CompactControlRibbon.js +141 -0
- package/lib/components/CompactControlRibbon.js.map +1 -0
- package/lib/components/DualKeypad.d.ts +39 -0
- package/lib/components/DualKeypad.d.ts.map +1 -0
- package/lib/components/DualKeypad.js +137 -0
- package/lib/components/DualKeypad.js.map +1 -0
- package/lib/components/KillerCombinationsExplorer.d.ts +9 -0
- package/lib/components/KillerCombinationsExplorer.d.ts.map +1 -0
- package/lib/components/KillerCombinationsExplorer.js +69 -0
- package/lib/components/KillerCombinationsExplorer.js.map +1 -0
- package/lib/components/KillerCombinationsModal.d.ts +20 -0
- package/lib/components/KillerCombinationsModal.d.ts.map +1 -0
- package/lib/components/KillerCombinationsModal.js +135 -0
- package/lib/components/KillerCombinationsModal.js.map +1 -0
- package/lib/components/KillerCombinationsPanel.d.ts +20 -0
- package/lib/components/KillerCombinationsPanel.d.ts.map +1 -0
- package/lib/components/KillerCombinationsPanel.js +79 -0
- package/lib/components/KillerCombinationsPanel.js.map +1 -0
- package/lib/components/NumberKeypad.d.ts +30 -0
- package/lib/components/NumberKeypad.d.ts.map +1 -0
- package/lib/components/NumberKeypad.js +181 -0
- package/lib/components/NumberKeypad.js.map +1 -0
- package/lib/components/SudokuCell.d.ts +8 -0
- package/lib/components/SudokuCell.d.ts.map +1 -0
- package/lib/components/SudokuCell.js +240 -0
- package/lib/components/SudokuCell.js.map +1 -0
- package/lib/components/SudokuControls.d.ts +8 -0
- package/lib/components/SudokuControls.d.ts.map +1 -0
- package/lib/components/SudokuControls.js +140 -0
- package/lib/components/SudokuControls.js.map +1 -0
- package/lib/components/SudokuGrid.d.ts +8 -0
- package/lib/components/SudokuGrid.d.ts.map +1 -0
- package/lib/components/SudokuGrid.js +177 -0
- package/lib/components/SudokuGrid.js.map +1 -0
- package/lib/components/SudokuGridEntry.d.ts +8 -0
- package/lib/components/SudokuGridEntry.d.ts.map +1 -0
- package/lib/components/SudokuGridEntry.js +373 -0
- package/lib/components/SudokuGridEntry.js.map +1 -0
- package/lib/components/ValidationDisplay.d.ts +8 -0
- package/lib/components/ValidationDisplay.d.ts.map +1 -0
- package/lib/components/ValidationDisplay.js +95 -0
- package/lib/components/ValidationDisplay.js.map +1 -0
- package/lib/contexts/DiagnosticLoggerContext.d.ts +81 -0
- package/lib/contexts/DiagnosticLoggerContext.d.ts.map +1 -0
- package/lib/contexts/DiagnosticLoggerContext.js +98 -0
- package/lib/contexts/DiagnosticLoggerContext.js.map +1 -0
- package/lib/contexts/index.d.ts +3 -0
- package/lib/contexts/index.d.ts.map +1 -0
- package/lib/contexts/index.js +25 -0
- package/lib/contexts/index.js.map +1 -0
- package/lib/hooks/useCombinationElimination.d.ts +10 -0
- package/lib/hooks/useCombinationElimination.d.ts.map +1 -0
- package/lib/hooks/useCombinationElimination.js +123 -0
- package/lib/hooks/useCombinationElimination.js.map +1 -0
- package/lib/hooks/useKeyboardShortcut.d.ts +19 -0
- package/lib/hooks/useKeyboardShortcut.d.ts.map +1 -0
- package/lib/hooks/useKeyboardShortcut.js +55 -0
- package/lib/hooks/useKeyboardShortcut.js.map +1 -0
- package/lib/hooks/useKillerCombinations.d.ts +11 -0
- package/lib/hooks/useKillerCombinations.d.ts.map +1 -0
- package/lib/hooks/useKillerCombinations.js +65 -0
- package/lib/hooks/useKillerCombinations.js.map +1 -0
- package/lib/hooks/useLongPress.d.ts +31 -0
- package/lib/hooks/useLongPress.d.ts.map +1 -0
- package/lib/hooks/useLongPress.js +69 -0
- package/lib/hooks/useLongPress.js.map +1 -0
- package/lib/hooks/usePuzzleSession.d.ts +32 -0
- package/lib/hooks/usePuzzleSession.d.ts.map +1 -0
- package/lib/hooks/usePuzzleSession.js +398 -0
- package/lib/hooks/usePuzzleSession.js.map +1 -0
- package/lib/hooks/useResponsiveLayout.d.ts +44 -0
- package/lib/hooks/useResponsiveLayout.d.ts.map +1 -0
- package/lib/hooks/useResponsiveLayout.js +139 -0
- package/lib/hooks/useResponsiveLayout.js.map +1 -0
- package/lib/index.browser.d.ts +2 -0
- package/lib/index.browser.d.ts.map +1 -0
- package/lib/index.browser.js +26 -0
- package/lib/index.browser.js.map +1 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +49 -0
- package/lib/index.js.map +1 -0
- package/lib/test/fixtures/killerSudokuPuzzles.d.ts +36 -0
- package/lib/test/fixtures/killerSudokuPuzzles.d.ts.map +1 -0
- package/lib/test/fixtures/killerSudokuPuzzles.js +57 -0
- package/lib/test/fixtures/killerSudokuPuzzles.js.map +1 -0
- package/lib/test/unit/components/SudokuGridEntry.testHelpers.d.ts +22 -0
- package/lib/test/unit/components/SudokuGridEntry.testHelpers.d.ts.map +1 -0
- package/lib/test/unit/components/SudokuGridEntry.testHelpers.js +116 -0
- package/lib/test/unit/components/SudokuGridEntry.testHelpers.js.map +1 -0
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/types/index.d.ts +234 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +25 -0
- package/lib/types/index.js.map +1 -0
- package/lib/utils/CageLookupManager.d.ts +74 -0
- package/lib/utils/CageLookupManager.d.ts.map +1 -0
- package/lib/utils/CageLookupManager.js +283 -0
- package/lib/utils/CageLookupManager.js.map +1 -0
- package/lib/utils/CagePatternManager.d.ts +82 -0
- package/lib/utils/CagePatternManager.d.ts.map +1 -0
- package/lib/utils/CagePatternManager.js +139 -0
- package/lib/utils/CagePatternManager.js.map +1 -0
- package/lib/utils/puzzleDefinitionHelper.d.ts +25 -0
- package/lib/utils/puzzleDefinitionHelper.d.ts.map +1 -0
- package/lib/utils/puzzleDefinitionHelper.js +99 -0
- package/lib/utils/puzzleDefinitionHelper.js.map +1 -0
- package/lib-commonjs/components/CageOverlay.js +138 -0
- package/lib-commonjs/components/CageOverlay.js.map +1 -0
- package/lib-commonjs/components/CageSumIndicator.js +71 -0
- package/lib-commonjs/components/CageSumIndicator.js.map +1 -0
- package/lib-commonjs/components/CombinationCard.js +68 -0
- package/lib-commonjs/components/CombinationCard.js.map +1 -0
- package/lib-commonjs/components/CombinationGrid.js +56 -0
- package/lib-commonjs/components/CombinationGrid.js.map +1 -0
- package/lib-commonjs/components/CompactControlRibbon.js +146 -0
- package/lib-commonjs/components/CompactControlRibbon.js.map +1 -0
- package/lib-commonjs/components/DualKeypad.js +142 -0
- package/lib-commonjs/components/DualKeypad.js.map +1 -0
- package/lib-commonjs/components/KillerCombinationsExplorer.js +74 -0
- package/lib-commonjs/components/KillerCombinationsExplorer.js.map +1 -0
- package/lib-commonjs/components/KillerCombinationsModal.js +140 -0
- package/lib-commonjs/components/KillerCombinationsModal.js.map +1 -0
- package/lib-commonjs/components/KillerCombinationsPanel.js +84 -0
- package/lib-commonjs/components/KillerCombinationsPanel.js.map +1 -0
- package/lib-commonjs/components/NumberKeypad.js +186 -0
- package/lib-commonjs/components/NumberKeypad.js.map +1 -0
- package/lib-commonjs/components/SudokuCell.js +245 -0
- package/lib-commonjs/components/SudokuCell.js.map +1 -0
- package/lib-commonjs/components/SudokuControls.js +145 -0
- package/lib-commonjs/components/SudokuControls.js.map +1 -0
- package/lib-commonjs/components/SudokuGrid.js +182 -0
- package/lib-commonjs/components/SudokuGrid.js.map +1 -0
- package/lib-commonjs/components/SudokuGridEntry.js +378 -0
- package/lib-commonjs/components/SudokuGridEntry.js.map +1 -0
- package/lib-commonjs/components/ValidationDisplay.js +100 -0
- package/lib-commonjs/components/ValidationDisplay.js.map +1 -0
- package/lib-commonjs/contexts/DiagnosticLoggerContext.js +104 -0
- package/lib-commonjs/contexts/DiagnosticLoggerContext.js.map +1 -0
- package/lib-commonjs/contexts/index.js +32 -0
- package/lib-commonjs/contexts/index.js.map +1 -0
- package/lib-commonjs/hooks/useCombinationElimination.js +126 -0
- package/lib-commonjs/hooks/useCombinationElimination.js.map +1 -0
- package/lib-commonjs/hooks/useKeyboardShortcut.js +58 -0
- package/lib-commonjs/hooks/useKeyboardShortcut.js.map +1 -0
- package/lib-commonjs/hooks/useKillerCombinations.js +68 -0
- package/lib-commonjs/hooks/useKillerCombinations.js.map +1 -0
- package/lib-commonjs/hooks/useLongPress.js +72 -0
- package/lib-commonjs/hooks/useLongPress.js.map +1 -0
- package/lib-commonjs/hooks/usePuzzleSession.js +401 -0
- package/lib-commonjs/hooks/usePuzzleSession.js.map +1 -0
- package/lib-commonjs/hooks/useResponsiveLayout.js +142 -0
- package/lib-commonjs/hooks/useResponsiveLayout.js.map +1 -0
- package/lib-commonjs/index.browser.js +29 -0
- package/lib-commonjs/index.browser.js.map +1 -0
- package/lib-commonjs/index.js +73 -0
- package/lib-commonjs/index.js.map +1 -0
- package/lib-commonjs/test/fixtures/killerSudokuPuzzles.js +60 -0
- package/lib-commonjs/test/fixtures/killerSudokuPuzzles.js.map +1 -0
- package/lib-commonjs/test/unit/components/SudokuGridEntry.testHelpers.js +125 -0
- package/lib-commonjs/test/unit/components/SudokuGridEntry.testHelpers.js.map +1 -0
- package/lib-commonjs/types/index.js +26 -0
- package/lib-commonjs/types/index.js.map +1 -0
- package/lib-commonjs/utils/CageLookupManager.js +287 -0
- package/lib-commonjs/utils/CageLookupManager.js.map +1 -0
- package/lib-commonjs/utils/CagePatternManager.js +143 -0
- package/lib-commonjs/utils/CagePatternManager.js.map +1 -0
- package/lib-commonjs/utils/puzzleDefinitionHelper.js +103 -0
- package/lib-commonjs/utils/puzzleDefinitionHelper.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
## API Report File for "@fgv/ts-sudoku-ui"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import { CellId } from '@fgv/ts-sudoku-lib';
|
|
8
|
+
import { ICage } from '@fgv/ts-sudoku-lib';
|
|
9
|
+
import { ICellContents } from '@fgv/ts-sudoku-lib';
|
|
10
|
+
import { IPuzzleDefinition } from '@fgv/ts-sudoku-lib';
|
|
11
|
+
import { Logging } from '@fgv/ts-utils';
|
|
12
|
+
import { NavigationDirection } from '@fgv/ts-sudoku-lib';
|
|
13
|
+
import { NavigationWrap } from '@fgv/ts-sudoku-lib';
|
|
14
|
+
import { PuzzleSession } from '@fgv/ts-sudoku-lib';
|
|
15
|
+
import { default as React_2 } from 'react';
|
|
16
|
+
import { ReactNode } from 'react';
|
|
17
|
+
import { Result } from '@fgv/ts-utils';
|
|
18
|
+
|
|
19
|
+
// @public
|
|
20
|
+
export const CageOverlay: React_2.FC<ICageOverlayProps>;
|
|
21
|
+
|
|
22
|
+
// @public
|
|
23
|
+
export const CageSumIndicator: React_2.FC<ICageSumIndicatorProps>;
|
|
24
|
+
|
|
25
|
+
// @public
|
|
26
|
+
export const CombinationCard: React_2.NamedExoticComponent<ICombinationCardProps>;
|
|
27
|
+
|
|
28
|
+
// @public
|
|
29
|
+
export const CombinationGrid: React_2.FC<ICombinationGridProps>;
|
|
30
|
+
|
|
31
|
+
// @public
|
|
32
|
+
export const CompactControlRibbon: React_2.FC<ICompactControlRibbonProps>;
|
|
33
|
+
|
|
34
|
+
// @public
|
|
35
|
+
export const DefaultDiagnosticLogger: Logging.LogReporter<unknown>;
|
|
36
|
+
|
|
37
|
+
// @public
|
|
38
|
+
export type DeviceType = 'mobile' | 'tablet' | 'desktop';
|
|
39
|
+
|
|
40
|
+
// @public
|
|
41
|
+
export const DiagnosticLoggerContext: React_2.Context<Logging.LogReporter<unknown>>;
|
|
42
|
+
|
|
43
|
+
// @public
|
|
44
|
+
export const DiagnosticLoggerProvider: React_2.FC<IDiagnosticLoggerProviderProps>;
|
|
45
|
+
|
|
46
|
+
// @public
|
|
47
|
+
export const DualKeypad: React_2.FC<IDualKeypadProps>;
|
|
48
|
+
|
|
49
|
+
// @public
|
|
50
|
+
export interface ICageDisplayInfo {
|
|
51
|
+
// (undocumented)
|
|
52
|
+
readonly cage: ICage;
|
|
53
|
+
// (undocumented)
|
|
54
|
+
readonly currentSum?: number;
|
|
55
|
+
// (undocumented)
|
|
56
|
+
readonly isComplete: boolean;
|
|
57
|
+
// (undocumented)
|
|
58
|
+
readonly isHighlighted: boolean;
|
|
59
|
+
// (undocumented)
|
|
60
|
+
readonly isValid: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// @public
|
|
64
|
+
export interface ICageOverlayProps {
|
|
65
|
+
// (undocumented)
|
|
66
|
+
readonly cages: ICageDisplayInfo[];
|
|
67
|
+
// (undocumented)
|
|
68
|
+
readonly cellSize: number;
|
|
69
|
+
// (undocumented)
|
|
70
|
+
readonly className?: string;
|
|
71
|
+
// (undocumented)
|
|
72
|
+
readonly gridSize: {
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
};
|
|
76
|
+
// (undocumented)
|
|
77
|
+
readonly numColumns?: number;
|
|
78
|
+
// (undocumented)
|
|
79
|
+
readonly numRows?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// @public
|
|
83
|
+
export interface ICageSumIndicatorProps {
|
|
84
|
+
// (undocumented)
|
|
85
|
+
readonly cage: ICage;
|
|
86
|
+
// (undocumented)
|
|
87
|
+
readonly className?: string;
|
|
88
|
+
// (undocumented)
|
|
89
|
+
readonly currentSum?: number;
|
|
90
|
+
// (undocumented)
|
|
91
|
+
readonly isComplete: boolean;
|
|
92
|
+
// (undocumented)
|
|
93
|
+
readonly isValid: boolean;
|
|
94
|
+
// (undocumented)
|
|
95
|
+
readonly position: {
|
|
96
|
+
top: number;
|
|
97
|
+
left: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// @public
|
|
102
|
+
export interface ICellDisplayInfo {
|
|
103
|
+
// (undocumented)
|
|
104
|
+
readonly column: number;
|
|
105
|
+
// (undocumented)
|
|
106
|
+
readonly contents: ICellContents;
|
|
107
|
+
// (undocumented)
|
|
108
|
+
readonly hasValidationError: boolean;
|
|
109
|
+
// (undocumented)
|
|
110
|
+
readonly id: CellId;
|
|
111
|
+
// (undocumented)
|
|
112
|
+
readonly isImmutable: boolean;
|
|
113
|
+
// (undocumented)
|
|
114
|
+
readonly row: number;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// @public
|
|
118
|
+
export interface ICombinationCardProps {
|
|
119
|
+
// (undocumented)
|
|
120
|
+
readonly className?: string;
|
|
121
|
+
// (undocumented)
|
|
122
|
+
readonly combination: ICombinationDisplayInfo;
|
|
123
|
+
// (undocumented)
|
|
124
|
+
readonly onToggle: (signature: string) => void;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// @public
|
|
128
|
+
export interface ICombinationDisplayInfo {
|
|
129
|
+
// (undocumented)
|
|
130
|
+
readonly combination: number[];
|
|
131
|
+
// (undocumented)
|
|
132
|
+
readonly isEliminated: boolean;
|
|
133
|
+
// (undocumented)
|
|
134
|
+
readonly signature: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// @public
|
|
138
|
+
export interface ICombinationGridProps {
|
|
139
|
+
// (undocumented)
|
|
140
|
+
readonly className?: string;
|
|
141
|
+
// (undocumented)
|
|
142
|
+
readonly combinations: ICombinationDisplayInfo[];
|
|
143
|
+
// (undocumented)
|
|
144
|
+
readonly mode: IKillerCombinationsMode;
|
|
145
|
+
// (undocumented)
|
|
146
|
+
readonly onToggle: (signature: string) => void;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// @public
|
|
150
|
+
export interface ICompactControlRibbonProps {
|
|
151
|
+
readonly canRedo: boolean;
|
|
152
|
+
readonly canReset: boolean;
|
|
153
|
+
readonly canShowCombinations?: boolean;
|
|
154
|
+
readonly canUndo: boolean;
|
|
155
|
+
readonly className?: string;
|
|
156
|
+
readonly isSolved: boolean;
|
|
157
|
+
readonly isValid: boolean;
|
|
158
|
+
readonly onCombinations?: () => void;
|
|
159
|
+
readonly onExport: () => void;
|
|
160
|
+
readonly onRedo: () => void;
|
|
161
|
+
readonly onReset: () => void;
|
|
162
|
+
readonly onUndo: () => void;
|
|
163
|
+
readonly showCombinations?: boolean;
|
|
164
|
+
readonly validationErrors: ReadonlyArray<{
|
|
165
|
+
readonly type: string;
|
|
166
|
+
readonly cellId: string;
|
|
167
|
+
readonly message: string;
|
|
168
|
+
}>;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// @public
|
|
172
|
+
export interface IDiagnosticLoggerProviderProps {
|
|
173
|
+
children: ReactNode;
|
|
174
|
+
logger?: Logging.LogReporter<unknown>;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// @public
|
|
178
|
+
export interface IDualKeypadProps {
|
|
179
|
+
readonly className?: string;
|
|
180
|
+
readonly disabled?: boolean;
|
|
181
|
+
readonly forceLayoutMode?: KeypadLayoutMode;
|
|
182
|
+
readonly hasCellSelection: boolean;
|
|
183
|
+
// Warning: (ae-forgotten-export) The symbol "InputMode" needs to be exported by the entry point index.d.ts
|
|
184
|
+
readonly inputMode: InputMode;
|
|
185
|
+
readonly onClearNotes: () => void;
|
|
186
|
+
readonly onClearValues: () => void;
|
|
187
|
+
readonly onInputModeChange: (mode: InputMode) => void;
|
|
188
|
+
readonly onNotePress: (number: number) => void;
|
|
189
|
+
readonly onValuePress: (number: number) => void;
|
|
190
|
+
readonly selectedCellCount: number;
|
|
191
|
+
readonly showOverlayToggle?: boolean;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// @public
|
|
195
|
+
export interface IEliminationState {
|
|
196
|
+
// (undocumented)
|
|
197
|
+
readonly clearAll: () => void;
|
|
198
|
+
// (undocumented)
|
|
199
|
+
readonly eliminatedSignatures: Set<string>;
|
|
200
|
+
// (undocumented)
|
|
201
|
+
readonly toggleElimination: (signature: string) => void;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// @public
|
|
205
|
+
export interface IKeyboardShortcutOptions {
|
|
206
|
+
// (undocumented)
|
|
207
|
+
readonly ctrl?: boolean;
|
|
208
|
+
// (undocumented)
|
|
209
|
+
readonly meta?: boolean;
|
|
210
|
+
// (undocumented)
|
|
211
|
+
readonly preventDefault?: boolean;
|
|
212
|
+
// (undocumented)
|
|
213
|
+
readonly shift?: boolean;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// @public
|
|
217
|
+
export interface IKillerCombinationsExplorerProps {
|
|
218
|
+
// (undocumented)
|
|
219
|
+
readonly className?: string;
|
|
220
|
+
// (undocumented)
|
|
221
|
+
readonly isOpen: boolean;
|
|
222
|
+
// (undocumented)
|
|
223
|
+
readonly mobileBreakpoint?: number;
|
|
224
|
+
// (undocumented)
|
|
225
|
+
readonly onClose: () => void;
|
|
226
|
+
// (undocumented)
|
|
227
|
+
readonly puzzleId?: string;
|
|
228
|
+
// (undocumented)
|
|
229
|
+
readonly selectedCage: ICage | null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// @public
|
|
233
|
+
export type IKillerCombinationsMode = 'panel' | 'modal';
|
|
234
|
+
|
|
235
|
+
// @public
|
|
236
|
+
export interface INumberKeypadProps {
|
|
237
|
+
readonly className?: string;
|
|
238
|
+
readonly compact?: boolean;
|
|
239
|
+
readonly disabled?: boolean;
|
|
240
|
+
readonly inputMode: InputMode;
|
|
241
|
+
readonly isActive: boolean;
|
|
242
|
+
readonly keypadType: 'notes' | 'values';
|
|
243
|
+
readonly onClear: () => void;
|
|
244
|
+
readonly onNumberPress: (number: number) => void;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// @public
|
|
248
|
+
export interface IResponsiveLayoutInfo {
|
|
249
|
+
readonly deviceType: DeviceType;
|
|
250
|
+
readonly hasSpaceForDualKeypads: boolean;
|
|
251
|
+
readonly isSmallScreen: boolean;
|
|
252
|
+
readonly isTouchDevice: boolean;
|
|
253
|
+
readonly keypadLayoutMode: KeypadLayoutMode;
|
|
254
|
+
readonly orientation: ScreenOrientation_2;
|
|
255
|
+
readonly screenHeight: number;
|
|
256
|
+
readonly screenWidth: number;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// @public
|
|
260
|
+
export interface ISudokuCellProps {
|
|
261
|
+
// (undocumented)
|
|
262
|
+
readonly cellInfo: ICellDisplayInfo;
|
|
263
|
+
// (undocumented)
|
|
264
|
+
readonly className?: string;
|
|
265
|
+
// (undocumented)
|
|
266
|
+
readonly inputMode: InputMode;
|
|
267
|
+
// (undocumented)
|
|
268
|
+
readonly isSelected: boolean;
|
|
269
|
+
// (undocumented)
|
|
270
|
+
readonly onClearAllNotes: () => void;
|
|
271
|
+
// (undocumented)
|
|
272
|
+
readonly onDragOver?: () => void;
|
|
273
|
+
// (undocumented)
|
|
274
|
+
readonly onLongPressToggle?: (event: React.TouchEvent | React.MouseEvent) => void;
|
|
275
|
+
// (undocumented)
|
|
276
|
+
readonly onNoteToggle: (note: number) => void;
|
|
277
|
+
// (undocumented)
|
|
278
|
+
readonly onSelect: (event?: React.MouseEvent) => void;
|
|
279
|
+
// (undocumented)
|
|
280
|
+
readonly onValueChange: (value: number | undefined) => void;
|
|
281
|
+
// (undocumented)
|
|
282
|
+
readonly puzzleDimensions?: {
|
|
283
|
+
readonly numRows: number;
|
|
284
|
+
readonly numColumns: number;
|
|
285
|
+
readonly cageHeight: number;
|
|
286
|
+
readonly cageWidth: number;
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// @public
|
|
291
|
+
export interface ISudokuControlsProps {
|
|
292
|
+
// (undocumented)
|
|
293
|
+
readonly canRedo: boolean;
|
|
294
|
+
// (undocumented)
|
|
295
|
+
readonly canReset: boolean;
|
|
296
|
+
// (undocumented)
|
|
297
|
+
readonly canUndo: boolean;
|
|
298
|
+
// (undocumented)
|
|
299
|
+
readonly className?: string;
|
|
300
|
+
// (undocumented)
|
|
301
|
+
readonly isSolved: boolean;
|
|
302
|
+
// (undocumented)
|
|
303
|
+
readonly isValid: boolean;
|
|
304
|
+
// (undocumented)
|
|
305
|
+
readonly onExport: () => void;
|
|
306
|
+
// (undocumented)
|
|
307
|
+
readonly onRedo: () => void;
|
|
308
|
+
// (undocumented)
|
|
309
|
+
readonly onReset: () => void;
|
|
310
|
+
// (undocumented)
|
|
311
|
+
readonly onUndo: () => void;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// @public
|
|
315
|
+
export interface ISudokuGridEntryProps {
|
|
316
|
+
readonly className?: string;
|
|
317
|
+
readonly forceLayoutMode?: KeypadLayoutMode;
|
|
318
|
+
readonly initialPuzzleDescription?: IPuzzleDefinition;
|
|
319
|
+
readonly onStateChange?: (isValid: boolean, isSolved: boolean) => void;
|
|
320
|
+
readonly onValidationErrors?: (errors: IValidationError[]) => void;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// @public
|
|
324
|
+
export interface ISudokuGridProps {
|
|
325
|
+
// (undocumented)
|
|
326
|
+
readonly cages?: ICageDisplayInfo[];
|
|
327
|
+
// (undocumented)
|
|
328
|
+
readonly cells: ICellDisplayInfo[];
|
|
329
|
+
// (undocumented)
|
|
330
|
+
readonly className?: string;
|
|
331
|
+
// (undocumented)
|
|
332
|
+
readonly inputMode: InputMode;
|
|
333
|
+
// (undocumented)
|
|
334
|
+
readonly isDragging?: boolean;
|
|
335
|
+
// (undocumented)
|
|
336
|
+
readonly numColumns: number;
|
|
337
|
+
// (undocumented)
|
|
338
|
+
readonly numRows: number;
|
|
339
|
+
// (undocumented)
|
|
340
|
+
readonly onCellSelect: (cellId: CellId, event?: React.MouseEvent) => void;
|
|
341
|
+
// (undocumented)
|
|
342
|
+
readonly onCellValueChange: (cellId: CellId, value: number | undefined) => void;
|
|
343
|
+
// (undocumented)
|
|
344
|
+
readonly onClearAllNotes: (cellId: CellId) => void;
|
|
345
|
+
// (undocumented)
|
|
346
|
+
readonly onDragEnd?: () => void;
|
|
347
|
+
// (undocumented)
|
|
348
|
+
readonly onDragOver?: (cellId: CellId) => void;
|
|
349
|
+
// (undocumented)
|
|
350
|
+
readonly onLongPressToggle?: (cellId: CellId, event: React.TouchEvent | React.MouseEvent) => void;
|
|
351
|
+
// (undocumented)
|
|
352
|
+
readonly onNavigate: (direction: NavigationDirection) => void;
|
|
353
|
+
// (undocumented)
|
|
354
|
+
readonly onNoteToggle: (cellId: CellId, note: number) => void;
|
|
355
|
+
// (undocumented)
|
|
356
|
+
readonly puzzleDimensions?: {
|
|
357
|
+
readonly cageHeightInCells: number;
|
|
358
|
+
readonly cageWidthInCells: number;
|
|
359
|
+
readonly boardWidthInCages: number;
|
|
360
|
+
readonly boardHeightInCages: number;
|
|
361
|
+
readonly totalRows: number;
|
|
362
|
+
readonly totalColumns: number;
|
|
363
|
+
readonly maxValue: number;
|
|
364
|
+
readonly totalCages: number;
|
|
365
|
+
readonly basicCageTotal: number;
|
|
366
|
+
};
|
|
367
|
+
// (undocumented)
|
|
368
|
+
readonly puzzleType?: string;
|
|
369
|
+
// (undocumented)
|
|
370
|
+
readonly selectedCell: CellId | null;
|
|
371
|
+
// (undocumented)
|
|
372
|
+
readonly selectedCells: CellId[];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// @public
|
|
376
|
+
export interface IValidationDisplayProps {
|
|
377
|
+
// (undocumented)
|
|
378
|
+
readonly className?: string;
|
|
379
|
+
// (undocumented)
|
|
380
|
+
readonly errors: IValidationError[];
|
|
381
|
+
// (undocumented)
|
|
382
|
+
readonly isSolved: boolean;
|
|
383
|
+
// (undocumented)
|
|
384
|
+
readonly isValid: boolean;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// @public
|
|
388
|
+
export interface IValidationError {
|
|
389
|
+
// (undocumented)
|
|
390
|
+
readonly cellId: CellId;
|
|
391
|
+
// (undocumented)
|
|
392
|
+
readonly conflictingCells: CellId[];
|
|
393
|
+
// (undocumented)
|
|
394
|
+
readonly message: string;
|
|
395
|
+
// (undocumented)
|
|
396
|
+
readonly type: 'duplicate-row' | 'duplicate-column' | 'duplicate-section' | 'duplicate-diagonal' | 'invalid-value';
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// @public
|
|
400
|
+
export type KeypadLayoutMode = 'side-by-side' | 'stacked' | 'overlay' | 'hidden';
|
|
401
|
+
|
|
402
|
+
// @public
|
|
403
|
+
export const KillerCombinationsExplorer: React_2.FC<IKillerCombinationsExplorerProps>;
|
|
404
|
+
|
|
405
|
+
// Warning: (ae-forgotten-export) The symbol "IKillerCombinationsModalProps" needs to be exported by the entry point index.d.ts
|
|
406
|
+
//
|
|
407
|
+
// @public
|
|
408
|
+
export const KillerCombinationsModal: React_2.FC<IKillerCombinationsModalProps>;
|
|
409
|
+
|
|
410
|
+
// Warning: (ae-forgotten-export) The symbol "IKillerCombinationsPanelProps" needs to be exported by the entry point index.d.ts
|
|
411
|
+
//
|
|
412
|
+
// @public
|
|
413
|
+
export const KillerCombinationsPanel: React_2.FC<IKillerCombinationsPanelProps>;
|
|
414
|
+
|
|
415
|
+
// @public
|
|
416
|
+
export const NumberKeypad: React_2.FC<INumberKeypadProps>;
|
|
417
|
+
|
|
418
|
+
// @public
|
|
419
|
+
type ScreenOrientation_2 = 'portrait' | 'landscape';
|
|
420
|
+
export { ScreenOrientation_2 as ScreenOrientation }
|
|
421
|
+
|
|
422
|
+
// @public
|
|
423
|
+
export const SudokuCell: React_2.FC<ISudokuCellProps>;
|
|
424
|
+
|
|
425
|
+
// @public
|
|
426
|
+
export const SudokuControls: React_2.FC<ISudokuControlsProps>;
|
|
427
|
+
|
|
428
|
+
// @public
|
|
429
|
+
export const SudokuGrid: React_2.FC<ISudokuGridProps>;
|
|
430
|
+
|
|
431
|
+
// @public
|
|
432
|
+
export const SudokuGridEntry: React_2.FC<ISudokuGridEntryProps>;
|
|
433
|
+
|
|
434
|
+
// @public
|
|
435
|
+
export function useCombinationElimination(puzzleId: string | undefined, cageId: string | undefined): IEliminationState;
|
|
436
|
+
|
|
437
|
+
// @public
|
|
438
|
+
export const useDiagnosticLogger: () => Logging.LogReporter<unknown>;
|
|
439
|
+
|
|
440
|
+
// @public
|
|
441
|
+
export function useKeyboardShortcut(key: string, callback: () => void, options?: IKeyboardShortcutOptions): void;
|
|
442
|
+
|
|
443
|
+
// @public
|
|
444
|
+
export function useKillerCombinations(cage: ICage | null): Result<ICombinationDisplayInfo[]>;
|
|
445
|
+
|
|
446
|
+
// @public
|
|
447
|
+
export function usePuzzleSession(initialPuzzleDescription?: IPuzzleDefinition): {
|
|
448
|
+
session: PuzzleSession | null;
|
|
449
|
+
selectedCell: CellId | null;
|
|
450
|
+
selectedCells: CellId[];
|
|
451
|
+
inputMode: InputMode;
|
|
452
|
+
setSelectedCell: (cell: CellId | null) => void;
|
|
453
|
+
setSelectedCells: (cells: CellId[]) => void;
|
|
454
|
+
setInputMode: (mode: InputMode) => void;
|
|
455
|
+
cellDisplayInfo: ICellDisplayInfo[];
|
|
456
|
+
cageDisplayInfo: ICageDisplayInfo[];
|
|
457
|
+
validationErrors: IValidationError[];
|
|
458
|
+
isValid: boolean;
|
|
459
|
+
isSolved: boolean;
|
|
460
|
+
canUndo: boolean;
|
|
461
|
+
canRedo: boolean;
|
|
462
|
+
error: string | null;
|
|
463
|
+
updateCellValue: (cellId: CellId, value: number | undefined) => void;
|
|
464
|
+
toggleCellNote: (cellId: CellId, note: number) => void;
|
|
465
|
+
clearCellNotes: (cellId: CellId) => void;
|
|
466
|
+
navigateToCell: (direction: NavigationDirection, wrap?: NavigationWrap) => void;
|
|
467
|
+
undo: () => void;
|
|
468
|
+
redo: () => void;
|
|
469
|
+
reset: () => void;
|
|
470
|
+
exportPuzzle: () => IPuzzleDefinition | null;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// @public
|
|
474
|
+
export function useResponsiveLayout(forceLayoutMode?: KeypadLayoutMode): IResponsiveLayoutInfo;
|
|
475
|
+
|
|
476
|
+
// @public
|
|
477
|
+
export const ValidationDisplay: React_2.FC<IValidationDisplayProps>;
|
|
478
|
+
|
|
479
|
+
// (No @packageDocumentation comment for this package)
|
|
480
|
+
|
|
481
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ICageOverlayProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Component for rendering cage boundaries and sum indicators in Killer Sudoku
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare const CageOverlay: React.FC<ICageOverlayProps>;
|
|
8
|
+
//# sourceMappingURL=CageOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CageOverlay.d.ts","sourceRoot":"","sources":["../../src/components/CageOverlay.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAiD7C;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAmInD,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* MIT License
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2023 Erik Fortune
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
import React, { useMemo, useEffect } from 'react';
|
|
25
|
+
import { parseCellId } from '@fgv/ts-sudoku-lib';
|
|
26
|
+
import { CageSumIndicator } from './CageSumIndicator';
|
|
27
|
+
import { CagePatternManager } from '../utils/CagePatternManager';
|
|
28
|
+
import { CageLookupManager } from '../utils/CageLookupManager';
|
|
29
|
+
import { useDiagnosticLogger } from '../contexts/DiagnosticLoggerContext';
|
|
30
|
+
/**
|
|
31
|
+
* Helper to get cell position from CellId
|
|
32
|
+
*/
|
|
33
|
+
function getTopLeftPosition(cellIds, log, numRows, numColumns) {
|
|
34
|
+
if (cellIds.length === 0)
|
|
35
|
+
return { top: 0, left: 0 };
|
|
36
|
+
const positions = cellIds.map((cellId) => {
|
|
37
|
+
const parsed = parseCellId(cellId);
|
|
38
|
+
if (parsed && parsed.row >= 0 && parsed.row < numRows && parsed.col >= 0 && parsed.col < numColumns) {
|
|
39
|
+
return parsed;
|
|
40
|
+
}
|
|
41
|
+
// Fallback - should not happen with valid CellIds
|
|
42
|
+
log.warn(`Invalid CellId format: ${cellId}`);
|
|
43
|
+
return { row: 0, col: 0 };
|
|
44
|
+
});
|
|
45
|
+
// Find the top-left most cell
|
|
46
|
+
let minRow = positions[0].row;
|
|
47
|
+
let minCol = positions[0].col;
|
|
48
|
+
positions.forEach(({ row, col }) => {
|
|
49
|
+
if (row < minRow || (row === minRow && col < minCol)) {
|
|
50
|
+
minRow = row;
|
|
51
|
+
minCol = col;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Convert grid coordinates to percentage-based positioning
|
|
55
|
+
const cellWidthPercent = 100 / numColumns;
|
|
56
|
+
const cellHeightPercent = 100 / numRows;
|
|
57
|
+
return {
|
|
58
|
+
top: minRow * cellHeightPercent + 0.5, // Small offset from corner
|
|
59
|
+
left: minCol * cellWidthPercent + 0.5 // Small offset from corner
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Component for rendering cage boundaries and sum indicators in Killer Sudoku
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export const CageOverlay = ({ cages, gridSize, cellSize, numRows = 9, numColumns = 9, className }) => {
|
|
67
|
+
const log = useDiagnosticLogger();
|
|
68
|
+
// Initialize managers once
|
|
69
|
+
const patternManager = useMemo(() => new CagePatternManager(), []);
|
|
70
|
+
const lookupManager = useMemo(() => CageLookupManager.getInstance(), []);
|
|
71
|
+
// Debug logging
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
log.info('CageOverlay rendered', {
|
|
74
|
+
cageCount: cages.length,
|
|
75
|
+
gridSize,
|
|
76
|
+
cellSize,
|
|
77
|
+
cages: cages.map((c) => ({ id: c.cage.id, cellIds: c.cage.cellIds }))
|
|
78
|
+
});
|
|
79
|
+
}, [cages, gridSize, cellSize, log]);
|
|
80
|
+
// Calculate SVG viewBox and class names
|
|
81
|
+
const viewBox = `0 0 ${gridSize.width} ${gridSize.height}`;
|
|
82
|
+
const overlayClasses = useMemo(() => {
|
|
83
|
+
const classes = ['cage-overlay'];
|
|
84
|
+
if (className)
|
|
85
|
+
classes.push(className);
|
|
86
|
+
return classes.join(' ');
|
|
87
|
+
}, [className]);
|
|
88
|
+
return (React.createElement("div", { className: `
|
|
89
|
+
${overlayClasses}
|
|
90
|
+
absolute inset-0 w-full h-full pointer-events-none
|
|
91
|
+
`, style: { zIndex: 1000 }, "data-testid": "cage-overlay" },
|
|
92
|
+
React.createElement("svg", { width: "100%", height: "100%", viewBox: viewBox, className: "absolute inset-0", preserveAspectRatio: "none" }, cages.map((cageInfo, index) => {
|
|
93
|
+
const { cage, isHighlighted, isValid } = cageInfo;
|
|
94
|
+
// Build occupied cells set for this cage
|
|
95
|
+
const occupiedCells = patternManager.buildOccupiedCellsSet(cage.cellIds);
|
|
96
|
+
// Render each cell with connected borders
|
|
97
|
+
return cage.cellIds.map((cellId, cellIndex) => {
|
|
98
|
+
// Parse cell position using centralized function
|
|
99
|
+
const parsed = parseCellId(cellId);
|
|
100
|
+
let row = 0, col = 0;
|
|
101
|
+
if (parsed &&
|
|
102
|
+
parsed.row >= 0 &&
|
|
103
|
+
parsed.row < numRows &&
|
|
104
|
+
parsed.col >= 0 &&
|
|
105
|
+
parsed.col < numColumns) {
|
|
106
|
+
row = parsed.row;
|
|
107
|
+
col = parsed.col;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
log.warn(`Invalid CellId format: ${cellId}`);
|
|
111
|
+
}
|
|
112
|
+
const x = col * cellSize;
|
|
113
|
+
const y = row * cellSize;
|
|
114
|
+
// Analyze neighbors and get pattern
|
|
115
|
+
const neighbors = patternManager.analyzeNeighbors(cellId, occupiedCells);
|
|
116
|
+
const neighborPattern = lookupManager.neighborsToPattern(neighbors);
|
|
117
|
+
const pathData = lookupManager.getPatternSVG(neighborPattern);
|
|
118
|
+
// Skip if no path data
|
|
119
|
+
if (!pathData) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
// Render connected border pattern
|
|
123
|
+
return (React.createElement("g", { key: /* c8 ignore next 1 - defense in depth */ `${cage.id ?? index}-${cellIndex}`, transform: `translate(${x}, ${y}) scale(${cellSize})` },
|
|
124
|
+
React.createElement("path", { d: pathData, stroke: isHighlighted ? '#1e40af' : isValid ? '#2563eb' : '#dc2626', strokeWidth: 0.8 / cellSize, strokeDasharray: "6 4", strokeLinecap: "round", strokeLinejoin: "round", fill: "none", opacity: "1.0", vectorEffect: "non-scaling-stroke" })));
|
|
125
|
+
});
|
|
126
|
+
})),
|
|
127
|
+
cages.map((cageInfo, index) => {
|
|
128
|
+
const { cage, currentSum, isComplete, isValid } = cageInfo;
|
|
129
|
+
const position = getTopLeftPosition(cage.cellIds, log, numRows, numColumns);
|
|
130
|
+
return (React.createElement(CageSumIndicator, { key: /* c8 ignore next 1 - defense in depth */ cage.id ?? index, cage: cage, currentSum: currentSum, isComplete: isComplete, isValid: isValid, position: position }));
|
|
131
|
+
})));
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=CageOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CageOverlay.js","sourceRoot":"","sources":["../../src/components/CageOverlay.tsx"],"names":[],"mappings":"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","sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2023 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { useMemo, useEffect } from 'react';\nimport { CellId, parseCellId } from '@fgv/ts-sudoku-lib';\nimport { ICageOverlayProps } from '../types';\nimport { CageSumIndicator } from './CageSumIndicator';\nimport { CagePatternManager } from '../utils/CagePatternManager';\nimport { CageLookupManager } from '../utils/CageLookupManager';\nimport { useDiagnosticLogger } from '../contexts/DiagnosticLoggerContext';\nimport { Logging } from '@fgv/ts-utils';\n\n/**\n * Helper to get cell position from CellId\n */\nfunction getTopLeftPosition(\n cellIds: CellId[],\n log: Logging.LogReporter<unknown, unknown>,\n numRows: number,\n numColumns: number\n): { top: number; left: number } {\n if (cellIds.length === 0) return { top: 0, left: 0 };\n\n const positions = cellIds.map((cellId) => {\n const parsed = parseCellId(cellId);\n if (parsed && parsed.row >= 0 && parsed.row < numRows && parsed.col >= 0 && parsed.col < numColumns) {\n return parsed;\n }\n // Fallback - should not happen with valid CellIds\n log.warn(`Invalid CellId format: ${cellId}`);\n return { row: 0, col: 0 };\n });\n\n // Find the top-left most cell\n let minRow = positions[0].row;\n let minCol = positions[0].col;\n\n positions.forEach(({ row, col }) => {\n if (row < minRow || (row === minRow && col < minCol)) {\n minRow = row;\n minCol = col;\n }\n });\n\n // Convert grid coordinates to percentage-based positioning\n const cellWidthPercent = 100 / numColumns;\n const cellHeightPercent = 100 / numRows;\n\n return {\n top: minRow * cellHeightPercent + 0.5, // Small offset from corner\n left: minCol * cellWidthPercent + 0.5 // Small offset from corner\n };\n}\n\n/**\n * Component for rendering cage boundaries and sum indicators in Killer Sudoku\n * @public\n */\nexport const CageOverlay: React.FC<ICageOverlayProps> = ({\n cages,\n gridSize,\n cellSize,\n numRows = 9,\n numColumns = 9,\n className\n}) => {\n const log = useDiagnosticLogger();\n\n // Initialize managers once\n const patternManager = useMemo(() => new CagePatternManager(), []);\n const lookupManager = useMemo(() => CageLookupManager.getInstance(), []);\n\n // Debug logging\n useEffect(() => {\n log.info('CageOverlay rendered', {\n cageCount: cages.length,\n gridSize,\n cellSize,\n cages: cages.map((c) => ({ id: c.cage.id, cellIds: c.cage.cellIds }))\n });\n }, [cages, gridSize, cellSize, log]);\n\n // Calculate SVG viewBox and class names\n const viewBox = `0 0 ${gridSize.width} ${gridSize.height}`;\n\n const overlayClasses = useMemo(() => {\n const classes = ['cage-overlay'];\n if (className) classes.push(className);\n return classes.join(' ');\n }, [className]);\n\n return (\n <div\n className={`\n ${overlayClasses}\n absolute inset-0 w-full h-full pointer-events-none\n `}\n style={{ zIndex: 1000 }}\n data-testid=\"cage-overlay\"\n >\n {/* SVG for cage boundaries using connected border system */}\n <svg\n width=\"100%\"\n height=\"100%\"\n viewBox={viewBox}\n className=\"absolute inset-0\"\n preserveAspectRatio=\"none\"\n >\n {/* Render connected cage borders using two-stage lookup */}\n {cages.map((cageInfo, index) => {\n const { cage, isHighlighted, isValid } = cageInfo;\n\n // Build occupied cells set for this cage\n const occupiedCells = patternManager.buildOccupiedCellsSet(cage.cellIds);\n\n // Render each cell with connected borders\n return cage.cellIds.map((cellId, cellIndex) => {\n // Parse cell position using centralized function\n const parsed = parseCellId(cellId);\n let row = 0,\n col = 0;\n\n if (\n parsed &&\n parsed.row >= 0 &&\n parsed.row < numRows &&\n parsed.col >= 0 &&\n parsed.col < numColumns\n ) {\n row = parsed.row;\n col = parsed.col;\n } else {\n log.warn(`Invalid CellId format: ${cellId}`);\n }\n\n const x = col * cellSize;\n const y = row * cellSize;\n\n // Analyze neighbors and get pattern\n const neighbors = patternManager.analyzeNeighbors(cellId, occupiedCells);\n const neighborPattern = lookupManager.neighborsToPattern(neighbors);\n const pathData = lookupManager.getPatternSVG(neighborPattern);\n\n // Skip if no path data\n if (!pathData) {\n return null;\n }\n\n // Render connected border pattern\n return (\n <g\n key={/* c8 ignore next 1 - defense in depth */ `${cage.id ?? index}-${cellIndex}`}\n transform={`translate(${x}, ${y}) scale(${cellSize})`}\n >\n <path\n d={pathData}\n stroke={isHighlighted ? '#1e40af' : isValid ? '#2563eb' : '#dc2626'}\n strokeWidth={0.8 / cellSize}\n strokeDasharray=\"6 4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n opacity=\"1.0\"\n vectorEffect=\"non-scaling-stroke\"\n />\n </g>\n );\n });\n })}\n </svg>\n\n {/* Sum indicators */}\n {cages.map((cageInfo, index) => {\n const { cage, currentSum, isComplete, isValid } = cageInfo;\n const position = getTopLeftPosition(cage.cellIds, log, numRows, numColumns);\n\n return (\n <CageSumIndicator\n key={/* c8 ignore next 1 - defense in depth */ cage.id ?? index}\n cage={cage}\n currentSum={currentSum}\n isComplete={isComplete}\n isValid={isValid}\n position={position}\n />\n );\n })}\n </div>\n );\n};\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ICageSumIndicatorProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Component for displaying the target sum of a cage in Killer Sudoku
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export declare const CageSumIndicator: React.FC<ICageSumIndicatorProps>;
|
|
8
|
+
//# sourceMappingURL=CageSumIndicator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CageSumIndicator.d.ts","sourceRoot":"","sources":["../../src/components/CageSumIndicator.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA0D7D,CAAC"}
|