@fgv/ts-sudoku-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.rush/temp/chunked-rush-logs/ts-sudoku-ui.build.chunks.jsonl +14 -0
  2. package/.rush/temp/operation/build/log-chunks.jsonl +14 -0
  3. package/.rush/temp/operation/build/state.json +3 -0
  4. package/.rush/temp/shrinkwrap-deps.json +1086 -0
  5. package/.test-failures-catalog.md +470 -0
  6. package/CSS_MODULES_MIGRATION_SUMMARY.md +189 -0
  7. package/dist/ts-sudoku-ui.d.ts +668 -0
  8. package/etc/ts-sudoku-ui.api.md +481 -0
  9. package/lib/components/CageOverlay.d.ts +8 -0
  10. package/lib/components/CageOverlay.d.ts.map +1 -0
  11. package/lib/components/CageOverlay.js +133 -0
  12. package/lib/components/CageOverlay.js.map +1 -0
  13. package/lib/components/CageSumIndicator.d.ts +8 -0
  14. package/lib/components/CageSumIndicator.d.ts.map +1 -0
  15. package/lib/components/CageSumIndicator.js +66 -0
  16. package/lib/components/CageSumIndicator.js.map +1 -0
  17. package/lib/components/CombinationCard.d.ts +8 -0
  18. package/lib/components/CombinationCard.d.ts.map +1 -0
  19. package/lib/components/CombinationCard.js +64 -0
  20. package/lib/components/CombinationCard.js.map +1 -0
  21. package/lib/components/CombinationGrid.d.ts +8 -0
  22. package/lib/components/CombinationGrid.d.ts.map +1 -0
  23. package/lib/components/CombinationGrid.js +51 -0
  24. package/lib/components/CombinationGrid.js.map +1 -0
  25. package/lib/components/CompactControlRibbon.d.ts +45 -0
  26. package/lib/components/CompactControlRibbon.d.ts.map +1 -0
  27. package/lib/components/CompactControlRibbon.js +141 -0
  28. package/lib/components/CompactControlRibbon.js.map +1 -0
  29. package/lib/components/DualKeypad.d.ts +39 -0
  30. package/lib/components/DualKeypad.d.ts.map +1 -0
  31. package/lib/components/DualKeypad.js +137 -0
  32. package/lib/components/DualKeypad.js.map +1 -0
  33. package/lib/components/KillerCombinationsExplorer.d.ts +9 -0
  34. package/lib/components/KillerCombinationsExplorer.d.ts.map +1 -0
  35. package/lib/components/KillerCombinationsExplorer.js +69 -0
  36. package/lib/components/KillerCombinationsExplorer.js.map +1 -0
  37. package/lib/components/KillerCombinationsModal.d.ts +20 -0
  38. package/lib/components/KillerCombinationsModal.d.ts.map +1 -0
  39. package/lib/components/KillerCombinationsModal.js +135 -0
  40. package/lib/components/KillerCombinationsModal.js.map +1 -0
  41. package/lib/components/KillerCombinationsPanel.d.ts +20 -0
  42. package/lib/components/KillerCombinationsPanel.d.ts.map +1 -0
  43. package/lib/components/KillerCombinationsPanel.js +79 -0
  44. package/lib/components/KillerCombinationsPanel.js.map +1 -0
  45. package/lib/components/NumberKeypad.d.ts +30 -0
  46. package/lib/components/NumberKeypad.d.ts.map +1 -0
  47. package/lib/components/NumberKeypad.js +181 -0
  48. package/lib/components/NumberKeypad.js.map +1 -0
  49. package/lib/components/SudokuCell.d.ts +8 -0
  50. package/lib/components/SudokuCell.d.ts.map +1 -0
  51. package/lib/components/SudokuCell.js +240 -0
  52. package/lib/components/SudokuCell.js.map +1 -0
  53. package/lib/components/SudokuControls.d.ts +8 -0
  54. package/lib/components/SudokuControls.d.ts.map +1 -0
  55. package/lib/components/SudokuControls.js +140 -0
  56. package/lib/components/SudokuControls.js.map +1 -0
  57. package/lib/components/SudokuGrid.d.ts +8 -0
  58. package/lib/components/SudokuGrid.d.ts.map +1 -0
  59. package/lib/components/SudokuGrid.js +177 -0
  60. package/lib/components/SudokuGrid.js.map +1 -0
  61. package/lib/components/SudokuGridEntry.d.ts +8 -0
  62. package/lib/components/SudokuGridEntry.d.ts.map +1 -0
  63. package/lib/components/SudokuGridEntry.js +373 -0
  64. package/lib/components/SudokuGridEntry.js.map +1 -0
  65. package/lib/components/ValidationDisplay.d.ts +8 -0
  66. package/lib/components/ValidationDisplay.d.ts.map +1 -0
  67. package/lib/components/ValidationDisplay.js +95 -0
  68. package/lib/components/ValidationDisplay.js.map +1 -0
  69. package/lib/contexts/DiagnosticLoggerContext.d.ts +81 -0
  70. package/lib/contexts/DiagnosticLoggerContext.d.ts.map +1 -0
  71. package/lib/contexts/DiagnosticLoggerContext.js +98 -0
  72. package/lib/contexts/DiagnosticLoggerContext.js.map +1 -0
  73. package/lib/contexts/index.d.ts +3 -0
  74. package/lib/contexts/index.d.ts.map +1 -0
  75. package/lib/contexts/index.js +25 -0
  76. package/lib/contexts/index.js.map +1 -0
  77. package/lib/hooks/useCombinationElimination.d.ts +10 -0
  78. package/lib/hooks/useCombinationElimination.d.ts.map +1 -0
  79. package/lib/hooks/useCombinationElimination.js +123 -0
  80. package/lib/hooks/useCombinationElimination.js.map +1 -0
  81. package/lib/hooks/useKeyboardShortcut.d.ts +19 -0
  82. package/lib/hooks/useKeyboardShortcut.d.ts.map +1 -0
  83. package/lib/hooks/useKeyboardShortcut.js +55 -0
  84. package/lib/hooks/useKeyboardShortcut.js.map +1 -0
  85. package/lib/hooks/useKillerCombinations.d.ts +11 -0
  86. package/lib/hooks/useKillerCombinations.d.ts.map +1 -0
  87. package/lib/hooks/useKillerCombinations.js +65 -0
  88. package/lib/hooks/useKillerCombinations.js.map +1 -0
  89. package/lib/hooks/useLongPress.d.ts +31 -0
  90. package/lib/hooks/useLongPress.d.ts.map +1 -0
  91. package/lib/hooks/useLongPress.js +69 -0
  92. package/lib/hooks/useLongPress.js.map +1 -0
  93. package/lib/hooks/usePuzzleSession.d.ts +32 -0
  94. package/lib/hooks/usePuzzleSession.d.ts.map +1 -0
  95. package/lib/hooks/usePuzzleSession.js +398 -0
  96. package/lib/hooks/usePuzzleSession.js.map +1 -0
  97. package/lib/hooks/useResponsiveLayout.d.ts +44 -0
  98. package/lib/hooks/useResponsiveLayout.d.ts.map +1 -0
  99. package/lib/hooks/useResponsiveLayout.js +139 -0
  100. package/lib/hooks/useResponsiveLayout.js.map +1 -0
  101. package/lib/index.browser.d.ts +2 -0
  102. package/lib/index.browser.d.ts.map +1 -0
  103. package/lib/index.browser.js +26 -0
  104. package/lib/index.browser.js.map +1 -0
  105. package/lib/index.d.ts +28 -0
  106. package/lib/index.d.ts.map +1 -0
  107. package/lib/index.js +49 -0
  108. package/lib/index.js.map +1 -0
  109. package/lib/test/fixtures/killerSudokuPuzzles.d.ts +36 -0
  110. package/lib/test/fixtures/killerSudokuPuzzles.d.ts.map +1 -0
  111. package/lib/test/fixtures/killerSudokuPuzzles.js +57 -0
  112. package/lib/test/fixtures/killerSudokuPuzzles.js.map +1 -0
  113. package/lib/test/unit/components/SudokuGridEntry.testHelpers.d.ts +22 -0
  114. package/lib/test/unit/components/SudokuGridEntry.testHelpers.d.ts.map +1 -0
  115. package/lib/test/unit/components/SudokuGridEntry.testHelpers.js +116 -0
  116. package/lib/test/unit/components/SudokuGridEntry.testHelpers.js.map +1 -0
  117. package/lib/tsdoc-metadata.json +11 -0
  118. package/lib/types/index.d.ts +234 -0
  119. package/lib/types/index.d.ts.map +1 -0
  120. package/lib/types/index.js +25 -0
  121. package/lib/types/index.js.map +1 -0
  122. package/lib/utils/CageLookupManager.d.ts +74 -0
  123. package/lib/utils/CageLookupManager.d.ts.map +1 -0
  124. package/lib/utils/CageLookupManager.js +283 -0
  125. package/lib/utils/CageLookupManager.js.map +1 -0
  126. package/lib/utils/CagePatternManager.d.ts +82 -0
  127. package/lib/utils/CagePatternManager.d.ts.map +1 -0
  128. package/lib/utils/CagePatternManager.js +139 -0
  129. package/lib/utils/CagePatternManager.js.map +1 -0
  130. package/lib/utils/puzzleDefinitionHelper.d.ts +25 -0
  131. package/lib/utils/puzzleDefinitionHelper.d.ts.map +1 -0
  132. package/lib/utils/puzzleDefinitionHelper.js +99 -0
  133. package/lib/utils/puzzleDefinitionHelper.js.map +1 -0
  134. package/lib-commonjs/components/CageOverlay.js +138 -0
  135. package/lib-commonjs/components/CageOverlay.js.map +1 -0
  136. package/lib-commonjs/components/CageSumIndicator.js +71 -0
  137. package/lib-commonjs/components/CageSumIndicator.js.map +1 -0
  138. package/lib-commonjs/components/CombinationCard.js +68 -0
  139. package/lib-commonjs/components/CombinationCard.js.map +1 -0
  140. package/lib-commonjs/components/CombinationGrid.js +56 -0
  141. package/lib-commonjs/components/CombinationGrid.js.map +1 -0
  142. package/lib-commonjs/components/CompactControlRibbon.js +146 -0
  143. package/lib-commonjs/components/CompactControlRibbon.js.map +1 -0
  144. package/lib-commonjs/components/DualKeypad.js +142 -0
  145. package/lib-commonjs/components/DualKeypad.js.map +1 -0
  146. package/lib-commonjs/components/KillerCombinationsExplorer.js +74 -0
  147. package/lib-commonjs/components/KillerCombinationsExplorer.js.map +1 -0
  148. package/lib-commonjs/components/KillerCombinationsModal.js +140 -0
  149. package/lib-commonjs/components/KillerCombinationsModal.js.map +1 -0
  150. package/lib-commonjs/components/KillerCombinationsPanel.js +84 -0
  151. package/lib-commonjs/components/KillerCombinationsPanel.js.map +1 -0
  152. package/lib-commonjs/components/NumberKeypad.js +186 -0
  153. package/lib-commonjs/components/NumberKeypad.js.map +1 -0
  154. package/lib-commonjs/components/SudokuCell.js +245 -0
  155. package/lib-commonjs/components/SudokuCell.js.map +1 -0
  156. package/lib-commonjs/components/SudokuControls.js +145 -0
  157. package/lib-commonjs/components/SudokuControls.js.map +1 -0
  158. package/lib-commonjs/components/SudokuGrid.js +182 -0
  159. package/lib-commonjs/components/SudokuGrid.js.map +1 -0
  160. package/lib-commonjs/components/SudokuGridEntry.js +378 -0
  161. package/lib-commonjs/components/SudokuGridEntry.js.map +1 -0
  162. package/lib-commonjs/components/ValidationDisplay.js +100 -0
  163. package/lib-commonjs/components/ValidationDisplay.js.map +1 -0
  164. package/lib-commonjs/contexts/DiagnosticLoggerContext.js +104 -0
  165. package/lib-commonjs/contexts/DiagnosticLoggerContext.js.map +1 -0
  166. package/lib-commonjs/contexts/index.js +32 -0
  167. package/lib-commonjs/contexts/index.js.map +1 -0
  168. package/lib-commonjs/hooks/useCombinationElimination.js +126 -0
  169. package/lib-commonjs/hooks/useCombinationElimination.js.map +1 -0
  170. package/lib-commonjs/hooks/useKeyboardShortcut.js +58 -0
  171. package/lib-commonjs/hooks/useKeyboardShortcut.js.map +1 -0
  172. package/lib-commonjs/hooks/useKillerCombinations.js +68 -0
  173. package/lib-commonjs/hooks/useKillerCombinations.js.map +1 -0
  174. package/lib-commonjs/hooks/useLongPress.js +72 -0
  175. package/lib-commonjs/hooks/useLongPress.js.map +1 -0
  176. package/lib-commonjs/hooks/usePuzzleSession.js +401 -0
  177. package/lib-commonjs/hooks/usePuzzleSession.js.map +1 -0
  178. package/lib-commonjs/hooks/useResponsiveLayout.js +142 -0
  179. package/lib-commonjs/hooks/useResponsiveLayout.js.map +1 -0
  180. package/lib-commonjs/index.browser.js +29 -0
  181. package/lib-commonjs/index.browser.js.map +1 -0
  182. package/lib-commonjs/index.js +73 -0
  183. package/lib-commonjs/index.js.map +1 -0
  184. package/lib-commonjs/test/fixtures/killerSudokuPuzzles.js +60 -0
  185. package/lib-commonjs/test/fixtures/killerSudokuPuzzles.js.map +1 -0
  186. package/lib-commonjs/test/unit/components/SudokuGridEntry.testHelpers.js +125 -0
  187. package/lib-commonjs/test/unit/components/SudokuGridEntry.testHelpers.js.map +1 -0
  188. package/lib-commonjs/types/index.js +26 -0
  189. package/lib-commonjs/types/index.js.map +1 -0
  190. package/lib-commonjs/utils/CageLookupManager.js +287 -0
  191. package/lib-commonjs/utils/CageLookupManager.js.map +1 -0
  192. package/lib-commonjs/utils/CagePatternManager.js +143 -0
  193. package/lib-commonjs/utils/CagePatternManager.js.map +1 -0
  194. package/lib-commonjs/utils/puzzleDefinitionHelper.js +103 -0
  195. package/lib-commonjs/utils/puzzleDefinitionHelper.js.map +1 -0
  196. package/package.json +91 -0
@@ -0,0 +1,81 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { Logging } from '@fgv/ts-utils';
3
+ /**
4
+ * Default diagnostic logger (no-op for production).
5
+ * @public
6
+ */
7
+ export declare const DefaultDiagnosticLogger: Logging.LogReporter<unknown>;
8
+ /**
9
+ * React context for diagnostic logging.
10
+ * Provides access to diagnostic logger throughout the component tree.
11
+ * @public
12
+ */
13
+ export declare const DiagnosticLoggerContext: React.Context<Logging.LogReporter<unknown>>;
14
+ /**
15
+ * Props for the DiagnosticLoggerProvider component.
16
+ * @public
17
+ */
18
+ export interface IDiagnosticLoggerProviderProps {
19
+ /** Child components that will have access to the diagnostic logger */
20
+ children: ReactNode;
21
+ /** Optional logger to provide (defaults to no-op logger) */
22
+ logger?: Logging.LogReporter<unknown>;
23
+ }
24
+ /**
25
+ * Provider component that makes diagnostic logger available to all child components.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * // Basic usage with default no-op logger
30
+ * <DiagnosticLoggerProvider>
31
+ * <SudokuGrid />
32
+ * </DiagnosticLoggerProvider>
33
+ *
34
+ * // Console logging for development
35
+ * const consoleLogger = new Logging.LogReporter({
36
+ * logger: new Logging.ConsoleLogger('info')
37
+ * });
38
+ * <DiagnosticLoggerProvider logger={consoleLogger}>
39
+ * <SudokuGrid />
40
+ * </DiagnosticLoggerProvider>
41
+ *
42
+ * // In-memory logger for tests
43
+ * const testLogger = new Logging.LogReporter({
44
+ * logger: new Logging.InMemoryLogger('detail')
45
+ * });
46
+ * <DiagnosticLoggerProvider logger={testLogger}>
47
+ * <SudokuGrid />
48
+ * </DiagnosticLoggerProvider>
49
+ * ```
50
+ *
51
+ * @param props - Provider configuration
52
+ * @returns JSX provider element
53
+ * @public
54
+ */
55
+ export declare const DiagnosticLoggerProvider: React.FC<IDiagnosticLoggerProviderProps>;
56
+ /**
57
+ * Hook to access the current diagnostic logger.
58
+ *
59
+ * Provides access to diagnostic logging for development and debugging.
60
+ *
61
+ * @example
62
+ * ```tsx
63
+ * function CageOverlay({ cages }: ICageOverlayProps) {
64
+ * const log = useDiagnosticLogger();
65
+ *
66
+ * useEffect(() => {
67
+ * log.info('CageOverlay rendered', {
68
+ * cageCount: cages.length,
69
+ * cages: cages.map((c) => ({ id: c.cage.id, cellIds: c.cage.cellIds }))
70
+ * });
71
+ * }, [cages, log]);
72
+ *
73
+ * return <div>...</div>;
74
+ * }
75
+ * ```
76
+ *
77
+ * @returns The current diagnostic logger
78
+ * @public
79
+ */
80
+ export declare const useDiagnosticLogger: () => Logging.LogReporter<unknown>;
81
+ //# sourceMappingURL=DiagnosticLoggerContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiagnosticLoggerContext.d.ts","sourceRoot":"","sources":["../../src/contexts/DiagnosticLoggerContext.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,EAA6B,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO,CAE/D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CACV,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,sEAAsE;IACtE,QAAQ,EAAE,SAAS,CAAC;IACpB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,8BAA8B,CAGsB,CAAC;AAErG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,mBAAmB,QAAO,OAAO,CAAC,WAAW,CAAC,OAAO,CAEjE,CAAC"}
@@ -0,0 +1,98 @@
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, { createContext, useContext } from 'react';
25
+ import { Logging } from '@fgv/ts-utils';
26
+ /**
27
+ * Default diagnostic logger (no-op for production).
28
+ * @public
29
+ */
30
+ export const DefaultDiagnosticLogger = new Logging.LogReporter({
31
+ logger: new Logging.NoOpLogger()
32
+ });
33
+ /**
34
+ * React context for diagnostic logging.
35
+ * Provides access to diagnostic logger throughout the component tree.
36
+ * @public
37
+ */
38
+ export const DiagnosticLoggerContext = createContext(DefaultDiagnosticLogger);
39
+ /**
40
+ * Provider component that makes diagnostic logger available to all child components.
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * // Basic usage with default no-op logger
45
+ * <DiagnosticLoggerProvider>
46
+ * <SudokuGrid />
47
+ * </DiagnosticLoggerProvider>
48
+ *
49
+ * // Console logging for development
50
+ * const consoleLogger = new Logging.LogReporter({
51
+ * logger: new Logging.ConsoleLogger('info')
52
+ * });
53
+ * <DiagnosticLoggerProvider logger={consoleLogger}>
54
+ * <SudokuGrid />
55
+ * </DiagnosticLoggerProvider>
56
+ *
57
+ * // In-memory logger for tests
58
+ * const testLogger = new Logging.LogReporter({
59
+ * logger: new Logging.InMemoryLogger('detail')
60
+ * });
61
+ * <DiagnosticLoggerProvider logger={testLogger}>
62
+ * <SudokuGrid />
63
+ * </DiagnosticLoggerProvider>
64
+ * ```
65
+ *
66
+ * @param props - Provider configuration
67
+ * @returns JSX provider element
68
+ * @public
69
+ */
70
+ export const DiagnosticLoggerProvider = ({ children, logger = DefaultDiagnosticLogger }) => React.createElement(DiagnosticLoggerContext.Provider, { value: logger }, children);
71
+ /**
72
+ * Hook to access the current diagnostic logger.
73
+ *
74
+ * Provides access to diagnostic logging for development and debugging.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * function CageOverlay({ cages }: ICageOverlayProps) {
79
+ * const log = useDiagnosticLogger();
80
+ *
81
+ * useEffect(() => {
82
+ * log.info('CageOverlay rendered', {
83
+ * cageCount: cages.length,
84
+ * cages: cages.map((c) => ({ id: c.cage.id, cellIds: c.cage.cellIds }))
85
+ * });
86
+ * }, [cages, log]);
87
+ *
88
+ * return <div>...</div>;
89
+ * }
90
+ * ```
91
+ *
92
+ * @returns The current diagnostic logger
93
+ * @public
94
+ */
95
+ export const useDiagnosticLogger = () => {
96
+ return useContext(DiagnosticLoggerContext);
97
+ };
98
+ //# sourceMappingURL=DiagnosticLoggerContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiagnosticLoggerContext.js","sourceRoot":"","sources":["../../src/contexts/DiagnosticLoggerContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAa,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAiC,IAAI,OAAO,CAAC,WAAW,CAAC;IAC3F,MAAM,EAAE,IAAI,OAAO,CAAC,UAAU,EAAE;CACjC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAClC,aAAa,CAA+B,uBAAuB,CAAC,CAAC;AAavE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAA6C,CAAC,EACjF,QAAQ,EACR,MAAM,GAAG,uBAAuB,EACjC,EAAE,EAAE,CAAC,oBAAC,uBAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IAAG,QAAQ,CAAoC,CAAC;AAErG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAiC,EAAE;IACpE,OAAO,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAC7C,CAAC,CAAC","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, { createContext, useContext, ReactNode } from 'react';\nimport { Logging } from '@fgv/ts-utils';\n\n/**\n * Default diagnostic logger (no-op for production).\n * @public\n */\nexport const DefaultDiagnosticLogger: Logging.LogReporter<unknown> = new Logging.LogReporter({\n logger: new Logging.NoOpLogger()\n});\n\n/**\n * React context for diagnostic logging.\n * Provides access to diagnostic logger throughout the component tree.\n * @public\n */\nexport const DiagnosticLoggerContext: React.Context<Logging.LogReporter<unknown>> =\n createContext<Logging.LogReporter<unknown>>(DefaultDiagnosticLogger);\n\n/**\n * Props for the DiagnosticLoggerProvider component.\n * @public\n */\nexport interface IDiagnosticLoggerProviderProps {\n /** Child components that will have access to the diagnostic logger */\n children: ReactNode;\n /** Optional logger to provide (defaults to no-op logger) */\n logger?: Logging.LogReporter<unknown>;\n}\n\n/**\n * Provider component that makes diagnostic logger available to all child components.\n *\n * @example\n * ```tsx\n * // Basic usage with default no-op logger\n * <DiagnosticLoggerProvider>\n * <SudokuGrid />\n * </DiagnosticLoggerProvider>\n *\n * // Console logging for development\n * const consoleLogger = new Logging.LogReporter({\n * logger: new Logging.ConsoleLogger('info')\n * });\n * <DiagnosticLoggerProvider logger={consoleLogger}>\n * <SudokuGrid />\n * </DiagnosticLoggerProvider>\n *\n * // In-memory logger for tests\n * const testLogger = new Logging.LogReporter({\n * logger: new Logging.InMemoryLogger('detail')\n * });\n * <DiagnosticLoggerProvider logger={testLogger}>\n * <SudokuGrid />\n * </DiagnosticLoggerProvider>\n * ```\n *\n * @param props - Provider configuration\n * @returns JSX provider element\n * @public\n */\nexport const DiagnosticLoggerProvider: React.FC<IDiagnosticLoggerProviderProps> = ({\n children,\n logger = DefaultDiagnosticLogger\n}) => <DiagnosticLoggerContext.Provider value={logger}>{children}</DiagnosticLoggerContext.Provider>;\n\n/**\n * Hook to access the current diagnostic logger.\n *\n * Provides access to diagnostic logging for development and debugging.\n *\n * @example\n * ```tsx\n * function CageOverlay({ cages }: ICageOverlayProps) {\n * const log = useDiagnosticLogger();\n *\n * useEffect(() => {\n * log.info('CageOverlay rendered', {\n * cageCount: cages.length,\n * cages: cages.map((c) => ({ id: c.cage.id, cellIds: c.cage.cellIds }))\n * });\n * }, [cages, log]);\n *\n * return <div>...</div>;\n * }\n * ```\n *\n * @returns The current diagnostic logger\n * @public\n */\nexport const useDiagnosticLogger = (): Logging.LogReporter<unknown> => {\n return useContext(DiagnosticLoggerContext);\n};\n"]}
@@ -0,0 +1,3 @@
1
+ export { DiagnosticLoggerContext, DiagnosticLoggerProvider, useDiagnosticLogger, DefaultDiagnosticLogger } from './DiagnosticLoggerContext';
2
+ export type { IDiagnosticLoggerProviderProps } from './DiagnosticLoggerContext';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AAwBA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,25 @@
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
+ export { DiagnosticLoggerContext, DiagnosticLoggerProvider, useDiagnosticLogger, DefaultDiagnosticLogger } from './DiagnosticLoggerContext';
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,2BAA2B,CAAC","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\nexport {\n DiagnosticLoggerContext,\n DiagnosticLoggerProvider,\n useDiagnosticLogger,\n DefaultDiagnosticLogger\n} from './DiagnosticLoggerContext';\nexport type { IDiagnosticLoggerProviderProps } from './DiagnosticLoggerContext';\n"]}
@@ -0,0 +1,10 @@
1
+ import { IEliminationState } from '../types';
2
+ /**
3
+ * Hook for managing combination elimination state with session storage persistence
4
+ * @param puzzleId - Unique identifier for the puzzle
5
+ * @param cageId - Unique identifier for the cage
6
+ * @returns Elimination state with toggle and clear operations
7
+ * @public
8
+ */
9
+ export declare function useCombinationElimination(puzzleId: string | undefined, cageId: string | undefined): IEliminationState;
10
+ //# sourceMappingURL=useCombinationElimination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCombinationElimination.d.ts","sourceRoot":"","sources":["../../src/hooks/useCombinationElimination.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAmD7C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,iBAAiB,CAkDnB"}
@@ -0,0 +1,123 @@
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 { useState, useCallback, useEffect } from 'react';
25
+ /**
26
+ * Generate session storage key for a cage's eliminated combinations
27
+ */
28
+ function getStorageKey(puzzleId, cageId) {
29
+ return `killer-combinations-${puzzleId}-${cageId}`;
30
+ }
31
+ /**
32
+ * Load eliminated combinations from session storage
33
+ */
34
+ function loadFromSessionStorage(puzzleId, cageId) {
35
+ try {
36
+ const key = getStorageKey(puzzleId, cageId);
37
+ const stored = sessionStorage.getItem(key);
38
+ if (stored) {
39
+ const parsed = JSON.parse(stored);
40
+ return new Set(parsed);
41
+ }
42
+ }
43
+ catch {
44
+ // Ignore parse errors
45
+ }
46
+ return new Set();
47
+ }
48
+ /**
49
+ * Save eliminated combinations to session storage
50
+ */
51
+ function saveToSessionStorage(puzzleId, cageId, eliminated) {
52
+ try {
53
+ const key = getStorageKey(puzzleId, cageId);
54
+ const array = Array.from(eliminated);
55
+ sessionStorage.setItem(key, JSON.stringify(array));
56
+ }
57
+ catch {
58
+ // Ignore storage errors
59
+ }
60
+ }
61
+ /**
62
+ * Clear eliminated combinations from session storage
63
+ */
64
+ function clearFromSessionStorage(puzzleId, cageId) {
65
+ try {
66
+ const key = getStorageKey(puzzleId, cageId);
67
+ sessionStorage.removeItem(key);
68
+ }
69
+ catch {
70
+ // Ignore storage errors
71
+ }
72
+ }
73
+ /**
74
+ * Hook for managing combination elimination state with session storage persistence
75
+ * @param puzzleId - Unique identifier for the puzzle
76
+ * @param cageId - Unique identifier for the cage
77
+ * @returns Elimination state with toggle and clear operations
78
+ * @public
79
+ */
80
+ export function useCombinationElimination(puzzleId, cageId) {
81
+ const [eliminated, setEliminated] = useState(() => {
82
+ if (!puzzleId || !cageId) {
83
+ return new Set();
84
+ }
85
+ return loadFromSessionStorage(puzzleId, cageId);
86
+ });
87
+ // Update state when puzzleId or cageId changes
88
+ useEffect(() => {
89
+ if (!puzzleId || !cageId) {
90
+ setEliminated(new Set());
91
+ return;
92
+ }
93
+ setEliminated(loadFromSessionStorage(puzzleId, cageId));
94
+ }, [puzzleId, cageId]);
95
+ const toggleElimination = useCallback((signature) => {
96
+ setEliminated((prev) => {
97
+ const next = new Set(prev);
98
+ if (next.has(signature)) {
99
+ next.delete(signature);
100
+ }
101
+ else {
102
+ next.add(signature);
103
+ }
104
+ // Persist to session storage
105
+ if (puzzleId && cageId) {
106
+ saveToSessionStorage(puzzleId, cageId, next);
107
+ }
108
+ return next;
109
+ });
110
+ }, [puzzleId, cageId]);
111
+ const clearAll = useCallback(() => {
112
+ setEliminated(new Set());
113
+ if (puzzleId && cageId) {
114
+ clearFromSessionStorage(puzzleId, cageId);
115
+ }
116
+ }, [puzzleId, cageId]);
117
+ return {
118
+ eliminatedSignatures: eliminated,
119
+ toggleElimination,
120
+ clearAll
121
+ };
122
+ }
123
+ //# sourceMappingURL=useCombinationElimination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCombinationElimination.js","sourceRoot":"","sources":["../../src/hooks/useCombinationElimination.ts"],"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 { useState, useCallback, useEffect } from 'react';\nimport { IEliminationState } from '../types';\n\n/**\n * Generate session storage key for a cage's eliminated combinations\n */\nfunction getStorageKey(puzzleId: string, cageId: string): string {\n return `killer-combinations-${puzzleId}-${cageId}`;\n}\n\n/**\n * Load eliminated combinations from session storage\n */\nfunction loadFromSessionStorage(puzzleId: string, cageId: string): Set<string> {\n try {\n const key = getStorageKey(puzzleId, cageId);\n const stored = sessionStorage.getItem(key);\n if (stored) {\n const parsed = JSON.parse(stored) as string[];\n return new Set(parsed);\n }\n } catch {\n // Ignore parse errors\n }\n return new Set();\n}\n\n/**\n * Save eliminated combinations to session storage\n */\nfunction saveToSessionStorage(puzzleId: string, cageId: string, eliminated: Set<string>): void {\n try {\n const key = getStorageKey(puzzleId, cageId);\n const array = Array.from(eliminated);\n sessionStorage.setItem(key, JSON.stringify(array));\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Clear eliminated combinations from session storage\n */\nfunction clearFromSessionStorage(puzzleId: string, cageId: string): void {\n try {\n const key = getStorageKey(puzzleId, cageId);\n sessionStorage.removeItem(key);\n } catch {\n // Ignore storage errors\n }\n}\n\n/**\n * Hook for managing combination elimination state with session storage persistence\n * @param puzzleId - Unique identifier for the puzzle\n * @param cageId - Unique identifier for the cage\n * @returns Elimination state with toggle and clear operations\n * @public\n */\nexport function useCombinationElimination(\n puzzleId: string | undefined,\n cageId: string | undefined\n): IEliminationState {\n const [eliminated, setEliminated] = useState<Set<string>>(() => {\n if (!puzzleId || !cageId) {\n return new Set();\n }\n return loadFromSessionStorage(puzzleId, cageId);\n });\n\n // Update state when puzzleId or cageId changes\n useEffect(() => {\n if (!puzzleId || !cageId) {\n setEliminated(new Set());\n return;\n }\n setEliminated(loadFromSessionStorage(puzzleId, cageId));\n }, [puzzleId, cageId]);\n\n const toggleElimination = useCallback(\n (signature: string) => {\n setEliminated((prev) => {\n const next = new Set(prev);\n if (next.has(signature)) {\n next.delete(signature);\n } else {\n next.add(signature);\n }\n\n // Persist to session storage\n if (puzzleId && cageId) {\n saveToSessionStorage(puzzleId, cageId, next);\n }\n\n return next;\n });\n },\n [puzzleId, cageId]\n );\n\n const clearAll = useCallback(() => {\n setEliminated(new Set());\n if (puzzleId && cageId) {\n clearFromSessionStorage(puzzleId, cageId);\n }\n }, [puzzleId, cageId]);\n\n return {\n eliminatedSignatures: eliminated,\n toggleElimination,\n clearAll\n };\n}\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Options for keyboard shortcut configuration
3
+ * @public
4
+ */
5
+ export interface IKeyboardShortcutOptions {
6
+ readonly ctrl?: boolean;
7
+ readonly meta?: boolean;
8
+ readonly shift?: boolean;
9
+ readonly preventDefault?: boolean;
10
+ }
11
+ /**
12
+ * Hook for registering global keyboard shortcuts
13
+ * @param key - The key to listen for (e.g., 'k', 'Escape')
14
+ * @param callback - Function to call when shortcut is activated
15
+ * @param options - Optional modifier keys and behavior
16
+ * @public
17
+ */
18
+ export declare function useKeyboardShortcut(key: string, callback: () => void, options?: IKeyboardShortcutOptions): void;
19
+ //# sourceMappingURL=useKeyboardShortcut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeyboardShortcut.d.ts","sourceRoot":"","sources":["../../src/hooks/useKeyboardShortcut.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,IAAI,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,IAAI,CA2BN"}
@@ -0,0 +1,55 @@
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 { useEffect } from 'react';
25
+ /**
26
+ * Hook for registering global keyboard shortcuts
27
+ * @param key - The key to listen for (e.g., 'k', 'Escape')
28
+ * @param callback - Function to call when shortcut is activated
29
+ * @param options - Optional modifier keys and behavior
30
+ * @public
31
+ */
32
+ export function useKeyboardShortcut(key, callback, options) {
33
+ useEffect(() => {
34
+ function handleKeyDown(event) {
35
+ const matchesKey = event.key.toLowerCase() === key.toLowerCase();
36
+ // Check modifier keys if specified
37
+ const matchesCtrl = options?.ctrl ? event.ctrlKey : !event.ctrlKey;
38
+ const matchesMeta = options?.meta ? event.metaKey : !event.metaKey;
39
+ const matchesShift = options?.shift ? event.shiftKey : !event.shiftKey;
40
+ // For cross-platform support, treat Ctrl+K on Windows/Linux as Cmd+K on Mac
41
+ const isPlatformShortcut = options?.ctrl && options?.meta
42
+ ? (event.ctrlKey || event.metaKey) && !event.shiftKey
43
+ : matchesCtrl && matchesMeta && matchesShift;
44
+ if (matchesKey && isPlatformShortcut) {
45
+ if (options?.preventDefault) {
46
+ event.preventDefault();
47
+ }
48
+ callback();
49
+ }
50
+ }
51
+ window.addEventListener('keydown', handleKeyDown);
52
+ return () => window.removeEventListener('keydown', handleKeyDown);
53
+ }, [key, callback, options]);
54
+ }
55
+ //# sourceMappingURL=useKeyboardShortcut.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeyboardShortcut.js","sourceRoot":"","sources":["../../src/hooks/useKeyboardShortcut.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAalC;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAW,EACX,QAAoB,EACpB,OAAkC;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,aAAa,CAAC,KAAoB;YACzC,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC;YAEjE,mCAAmC;YACnC,MAAM,WAAW,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;YACnE,MAAM,WAAW,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;YACnE,MAAM,YAAY,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;YAEvE,4EAA4E;YAC5E,MAAM,kBAAkB,GACtB,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI;gBAC5B,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;gBACrD,CAAC,CAAC,WAAW,IAAI,WAAW,IAAI,YAAY,CAAC;YAEjD,IAAI,UAAU,IAAI,kBAAkB,EAAE,CAAC;gBACrC,IAAI,OAAO,EAAE,cAAc,EAAE,CAAC;oBAC5B,KAAK,CAAC,cAAc,EAAE,CAAC;gBACzB,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC;QAED,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/B,CAAC","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 { useEffect } from 'react';\n\n/**\n * Options for keyboard shortcut configuration\n * @public\n */\nexport interface IKeyboardShortcutOptions {\n readonly ctrl?: boolean;\n readonly meta?: boolean;\n readonly shift?: boolean;\n readonly preventDefault?: boolean;\n}\n\n/**\n * Hook for registering global keyboard shortcuts\n * @param key - The key to listen for (e.g., 'k', 'Escape')\n * @param callback - Function to call when shortcut is activated\n * @param options - Optional modifier keys and behavior\n * @public\n */\nexport function useKeyboardShortcut(\n key: string,\n callback: () => void,\n options?: IKeyboardShortcutOptions\n): void {\n useEffect(() => {\n function handleKeyDown(event: KeyboardEvent): void {\n const matchesKey = event.key.toLowerCase() === key.toLowerCase();\n\n // Check modifier keys if specified\n const matchesCtrl = options?.ctrl ? event.ctrlKey : !event.ctrlKey;\n const matchesMeta = options?.meta ? event.metaKey : !event.metaKey;\n const matchesShift = options?.shift ? event.shiftKey : !event.shiftKey;\n\n // For cross-platform support, treat Ctrl+K on Windows/Linux as Cmd+K on Mac\n const isPlatformShortcut =\n options?.ctrl && options?.meta\n ? (event.ctrlKey || event.metaKey) && !event.shiftKey\n : matchesCtrl && matchesMeta && matchesShift;\n\n if (matchesKey && isPlatformShortcut) {\n if (options?.preventDefault) {\n event.preventDefault();\n }\n callback();\n }\n }\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [key, callback, options]);\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { ICage } from '@fgv/ts-sudoku-lib';
3
+ import { ICombinationDisplayInfo } from '../types';
4
+ /**
5
+ * Hook to get all valid killer cage combinations for a selected cage
6
+ * @param cage - The selected killer cage
7
+ * @returns Result containing combination display information
8
+ * @public
9
+ */
10
+ export declare function useKillerCombinations(cage: ICage | null): Result<ICombinationDisplayInfo[]>;
11
+ //# sourceMappingURL=useKillerCombinations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKillerCombinations.d.ts","sourceRoot":"","sources":["../../src/hooks/useKillerCombinations.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,KAAK,EAAW,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AASnD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC,uBAAuB,EAAE,CAAC,CA+B3F"}
@@ -0,0 +1,65 @@
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 { useMemo } from 'react';
25
+ import { fail, succeed } from '@fgv/ts-utils';
26
+ import { Puzzles } from '@fgv/ts-sudoku-lib';
27
+ /**
28
+ * Generate signature for a combination (sorted numbers joined by commas)
29
+ */
30
+ function getCombinationSignature(combination) {
31
+ return [...combination].sort((a, b) => a - b).join(',');
32
+ }
33
+ /**
34
+ * Hook to get all valid killer cage combinations for a selected cage
35
+ * @param cage - The selected killer cage
36
+ * @returns Result containing combination display information
37
+ * @public
38
+ */
39
+ export function useKillerCombinations(cage) {
40
+ return useMemo(() => {
41
+ if (!cage) {
42
+ return fail('No cage selected');
43
+ }
44
+ if (cage.cageType !== 'killer') {
45
+ return fail('Cage is not a killer cage');
46
+ }
47
+ if (!cage.total) {
48
+ return fail('Killer cage does not have a total');
49
+ }
50
+ // For now, we don't apply constraints based on current values
51
+ // This can be enhanced later to exclude numbers already in the cage
52
+ const constraints = {
53
+ excludedNumbers: []
54
+ };
55
+ return Puzzles.KillerCombinations.getCombinations(cage.numCells, cage.total, constraints).onSuccess((combinations) => {
56
+ const displayInfo = combinations.map((combo) => ({
57
+ combination: combo,
58
+ signature: getCombinationSignature(combo),
59
+ isEliminated: false
60
+ }));
61
+ return succeed(displayInfo);
62
+ });
63
+ }, [cage]);
64
+ }
65
+ //# sourceMappingURL=useKillerCombinations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKillerCombinations.js","sourceRoot":"","sources":["../../src/hooks/useKillerCombinations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAU,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAS,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGpD;;GAEG;AACH,SAAS,uBAAuB,CAAC,WAAqB;IACpD,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAkB;IACtD,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACnD,CAAC;QAED,8DAA8D;QAC9D,oEAAoE;QACpE,MAAM,WAAW,GAAG;YAClB,eAAe,EAAE,EAAE;SACpB,CAAC;QAEF,OAAO,OAAO,CAAC,kBAAkB,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,SAAS,CACjG,CAAC,YAAwB,EAAE,EAAE;YAC3B,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;gBACzD,WAAW,EAAE,KAAK;gBAClB,SAAS,EAAE,uBAAuB,CAAC,KAAK,CAAC;gBACzC,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC,CAAC;YACJ,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9B,CAAC,CACF,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACb,CAAC","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 { useMemo } from 'react';\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport { ICage, Puzzles } from '@fgv/ts-sudoku-lib';\nimport { ICombinationDisplayInfo } from '../types';\n\n/**\n * Generate signature for a combination (sorted numbers joined by commas)\n */\nfunction getCombinationSignature(combination: number[]): string {\n return [...combination].sort((a, b) => a - b).join(',');\n}\n\n/**\n * Hook to get all valid killer cage combinations for a selected cage\n * @param cage - The selected killer cage\n * @returns Result containing combination display information\n * @public\n */\nexport function useKillerCombinations(cage: ICage | null): Result<ICombinationDisplayInfo[]> {\n return useMemo(() => {\n if (!cage) {\n return fail('No cage selected');\n }\n\n if (cage.cageType !== 'killer') {\n return fail('Cage is not a killer cage');\n }\n\n if (!cage.total) {\n return fail('Killer cage does not have a total');\n }\n\n // For now, we don't apply constraints based on current values\n // This can be enhanced later to exclude numbers already in the cage\n const constraints = {\n excludedNumbers: []\n };\n\n return Puzzles.KillerCombinations.getCombinations(cage.numCells, cage.total, constraints).onSuccess(\n (combinations: number[][]) => {\n const displayInfo = combinations.map((combo: number[]) => ({\n combination: combo,\n signature: getCombinationSignature(combo),\n isEliminated: false\n }));\n return succeed(displayInfo);\n }\n );\n }, [cage]);\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Options for the useLongPress hook
3
+ * @public
4
+ */
5
+ export interface IUseLongPressOptions {
6
+ /** Callback to execute on long press */
7
+ readonly onLongPress: (event: React.TouchEvent | React.MouseEvent) => void;
8
+ /** Delay before long press is triggered (ms) */
9
+ readonly delay?: number;
10
+ /** Whether to prevent default behavior during long press */
11
+ readonly shouldPreventDefault?: boolean;
12
+ }
13
+ /**
14
+ * Result of the useLongPress hook
15
+ * @public
16
+ */
17
+ export interface ILongPressHandlers {
18
+ readonly onMouseDown: (event: React.MouseEvent) => void;
19
+ readonly onMouseUp: (event: React.MouseEvent) => boolean;
20
+ readonly onMouseLeave: (event: React.MouseEvent) => void;
21
+ readonly onTouchStart: (event: React.TouchEvent) => void;
22
+ readonly onTouchEnd: (event: React.TouchEvent) => boolean;
23
+ }
24
+ /**
25
+ * Hook to detect long press gestures on touch and mouse devices
26
+ * @param options - Configuration options for long press detection
27
+ * @returns Event handlers to spread on target element
28
+ * @public
29
+ */
30
+ export declare function useLongPress(options: IUseLongPressOptions): ILongPressHandlers;
31
+ //# sourceMappingURL=useLongPress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLongPress.d.ts","sourceRoot":"","sources":["../../src/hooks/useLongPress.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAE3E,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,4DAA4D;IAC5D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,OAAO,CAAC;IACzD,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzD,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,OAAO,CAAC;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CA+C9E"}