@sudobility/sudojo_lib 0.0.201 → 0.0.204

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 (263) hide show
  1. package/dist/admin/adminApi.d.ts +34 -0
  2. package/dist/admin/adminApi.d.ts.map +1 -0
  3. package/dist/admin/adminApi.js +59 -0
  4. package/dist/admin/adminApi.js.map +1 -0
  5. package/dist/admin/boardRules.d.ts +75 -0
  6. package/dist/admin/boardRules.d.ts.map +1 -0
  7. package/dist/admin/boardRules.js +127 -0
  8. package/dist/admin/boardRules.js.map +1 -0
  9. package/dist/admin/boardStrings.d.ts +55 -0
  10. package/dist/admin/boardStrings.d.ts.map +1 -0
  11. package/dist/admin/boardStrings.js +99 -0
  12. package/dist/admin/boardStrings.js.map +1 -0
  13. package/dist/admin/examples.d.ts +58 -0
  14. package/dist/admin/examples.d.ts.map +1 -0
  15. package/dist/admin/examples.js +104 -0
  16. package/dist/admin/examples.js.map +1 -0
  17. package/dist/admin/extraction.d.ts +87 -0
  18. package/dist/admin/extraction.d.ts.map +1 -0
  19. package/dist/admin/extraction.js +141 -0
  20. package/dist/admin/extraction.js.map +1 -0
  21. package/dist/admin/index.d.ts +32 -0
  22. package/dist/admin/index.d.ts.map +1 -0
  23. package/dist/admin/index.js +22 -0
  24. package/dist/admin/index.js.map +1 -0
  25. package/dist/admin/jobs.d.ts +108 -0
  26. package/dist/admin/jobs.d.ts.map +1 -0
  27. package/dist/admin/jobs.js +435 -0
  28. package/dist/admin/jobs.js.map +1 -0
  29. package/dist/admin/regenerateHints.d.ts +16 -0
  30. package/dist/admin/regenerateHints.d.ts.map +1 -0
  31. package/dist/admin/regenerateHints.js +43 -0
  32. package/dist/admin/regenerateHints.js.map +1 -0
  33. package/dist/admin/types.d.ts +42 -0
  34. package/dist/admin/types.d.ts.map +1 -0
  35. package/dist/admin/types.js +21 -0
  36. package/dist/admin/types.js.map +1 -0
  37. package/dist/admin/useAdminJob.d.ts +28 -0
  38. package/dist/admin/useAdminJob.d.ts.map +1 -0
  39. package/dist/admin/useAdminJob.js +99 -0
  40. package/dist/admin/useAdminJob.js.map +1 -0
  41. package/dist/admin/useAdminStats.d.ts +46 -0
  42. package/dist/admin/useAdminStats.d.ts.map +1 -0
  43. package/dist/admin/useAdminStats.js +91 -0
  44. package/dist/admin/useAdminStats.js.map +1 -0
  45. package/dist/admin/useBoardGenerator.d.ts +29 -0
  46. package/dist/admin/useBoardGenerator.d.ts.map +1 -0
  47. package/dist/admin/useBoardGenerator.js +38 -0
  48. package/dist/admin/useBoardGenerator.js.map +1 -0
  49. package/dist/admin/useBoardTechniquesUpdater.d.ts +14 -0
  50. package/dist/admin/useBoardTechniquesUpdater.d.ts.map +1 -0
  51. package/dist/admin/useBoardTechniquesUpdater.js +28 -0
  52. package/dist/admin/useBoardTechniquesUpdater.js.map +1 -0
  53. package/dist/admin/useExampleCreator.d.ts +29 -0
  54. package/dist/admin/useExampleCreator.d.ts.map +1 -0
  55. package/dist/admin/useExampleCreator.js +58 -0
  56. package/dist/admin/useExampleCreator.js.map +1 -0
  57. package/dist/admin/useSingleBoardExtractor.d.ts +18 -0
  58. package/dist/admin/useSingleBoardExtractor.d.ts.map +1 -0
  59. package/dist/admin/useSingleBoardExtractor.js +19 -0
  60. package/dist/admin/useSingleBoardExtractor.js.map +1 -0
  61. package/dist/admin/useTechniqueExtractor.d.ts +26 -0
  62. package/dist/admin/useTechniqueExtractor.d.ts.map +1 -0
  63. package/dist/admin/useTechniqueExtractor.js +37 -0
  64. package/dist/admin/useTechniqueExtractor.js.map +1 -0
  65. package/dist/context/SudojoApiContext.d.ts +58 -0
  66. package/dist/context/SudojoApiContext.d.ts.map +1 -0
  67. package/dist/context/SudojoApiContext.js +52 -0
  68. package/dist/context/SudojoApiContext.js.map +1 -0
  69. package/dist/context/SudojoApiProvider.d.ts +21 -0
  70. package/dist/context/SudojoApiProvider.d.ts.map +1 -0
  71. package/dist/context/SudojoApiProvider.js +15 -0
  72. package/dist/context/SudojoApiProvider.js.map +1 -0
  73. package/dist/context/index.d.ts +3 -0
  74. package/dist/context/index.d.ts.map +1 -1
  75. package/dist/context/index.js +2 -0
  76. package/dist/context/index.js.map +1 -1
  77. package/dist/hooks/index.d.ts +24 -1
  78. package/dist/hooks/index.d.ts.map +1 -1
  79. package/dist/hooks/index.js +22 -0
  80. package/dist/hooks/index.js.map +1 -1
  81. package/dist/hooks/useBoardEntry.d.ts +68 -5
  82. package/dist/hooks/useBoardEntry.d.ts.map +1 -1
  83. package/dist/hooks/useBoardEntry.js +113 -27
  84. package/dist/hooks/useBoardEntry.js.map +1 -1
  85. package/dist/hooks/useBoardScan.d.ts +27 -0
  86. package/dist/hooks/useBoardScan.d.ts.map +1 -0
  87. package/dist/hooks/useBoardScan.js +27 -0
  88. package/dist/hooks/useBoardScan.js.map +1 -0
  89. package/dist/hooks/useCommunities.d.ts +6 -4
  90. package/dist/hooks/useCommunities.d.ts.map +1 -1
  91. package/dist/hooks/useCommunities.js +6 -1
  92. package/dist/hooks/useCommunities.js.map +1 -1
  93. package/dist/hooks/useCompletionTrigger.d.ts +23 -0
  94. package/dist/hooks/useCompletionTrigger.d.ts.map +1 -0
  95. package/dist/hooks/useCompletionTrigger.js +39 -0
  96. package/dist/hooks/useCompletionTrigger.js.map +1 -0
  97. package/dist/hooks/useDailyGame.d.ts +11 -6
  98. package/dist/hooks/useDailyGame.d.ts.map +1 -1
  99. package/dist/hooks/useDailyGame.js +20 -61
  100. package/dist/hooks/useDailyGame.js.map +1 -1
  101. package/dist/hooks/useDeleteAccount.d.ts +72 -0
  102. package/dist/hooks/useDeleteAccount.d.ts.map +1 -0
  103. package/dist/hooks/useDeleteAccount.js +71 -0
  104. package/dist/hooks/useDeleteAccount.js.map +1 -0
  105. package/dist/hooks/useEnteredGameSession.d.ts +73 -0
  106. package/dist/hooks/useEnteredGameSession.d.ts.map +1 -0
  107. package/dist/hooks/useEnteredGameSession.js +155 -0
  108. package/dist/hooks/useEnteredGameSession.js.map +1 -0
  109. package/dist/hooks/useGameSession.d.ts +8 -4
  110. package/dist/hooks/useGameSession.d.ts.map +1 -1
  111. package/dist/hooks/useGameSession.js +4 -1
  112. package/dist/hooks/useGameSession.js.map +1 -1
  113. package/dist/hooks/useGameTeaching.d.ts.map +1 -1
  114. package/dist/hooks/useGameTeaching.js +11 -13
  115. package/dist/hooks/useGameTeaching.js.map +1 -1
  116. package/dist/hooks/useHint.d.ts +7 -7
  117. package/dist/hooks/useHint.d.ts.map +1 -1
  118. package/dist/hooks/useHint.js +18 -9
  119. package/dist/hooks/useHint.js.map +1 -1
  120. package/dist/hooks/useIsSiteAdmin.d.ts +39 -0
  121. package/dist/hooks/useIsSiteAdmin.d.ts.map +1 -0
  122. package/dist/hooks/useIsSiteAdmin.js +31 -0
  123. package/dist/hooks/useIsSiteAdmin.js.map +1 -0
  124. package/dist/hooks/useLearning.d.ts +8 -8
  125. package/dist/hooks/useLearning.d.ts.map +1 -1
  126. package/dist/hooks/useLearning.js +5 -2
  127. package/dist/hooks/useLearning.js.map +1 -1
  128. package/dist/hooks/useLevelGame.d.ts +7 -7
  129. package/dist/hooks/useLevelGame.d.ts.map +1 -1
  130. package/dist/hooks/useLevelGame.js +13 -49
  131. package/dist/hooks/useLevelGame.js.map +1 -1
  132. package/dist/hooks/useLevels.d.ts +8 -8
  133. package/dist/hooks/useLevels.d.ts.map +1 -1
  134. package/dist/hooks/useLevels.js +7 -3
  135. package/dist/hooks/useLevels.js.map +1 -1
  136. package/dist/hooks/usePracticeGame.d.ts +53 -0
  137. package/dist/hooks/usePracticeGame.d.ts.map +1 -0
  138. package/dist/hooks/usePracticeGame.js +72 -0
  139. package/dist/hooks/usePracticeGame.js.map +1 -0
  140. package/dist/hooks/usePuzzleDistribution.d.ts +2 -0
  141. package/dist/hooks/usePuzzleDistribution.d.ts.map +1 -1
  142. package/dist/hooks/usePuzzleDistribution.js +4 -14
  143. package/dist/hooks/usePuzzleDistribution.js.map +1 -1
  144. package/dist/hooks/usePuzzleProgress.d.ts +37 -0
  145. package/dist/hooks/usePuzzleProgress.d.ts.map +1 -0
  146. package/dist/hooks/usePuzzleProgress.js +48 -0
  147. package/dist/hooks/usePuzzleProgress.js.map +1 -0
  148. package/dist/hooks/usePuzzleSession.d.ts +215 -0
  149. package/dist/hooks/usePuzzleSession.d.ts.map +1 -0
  150. package/dist/hooks/usePuzzleSession.js +358 -0
  151. package/dist/hooks/usePuzzleSession.js.map +1 -0
  152. package/dist/hooks/useResumeGame.d.ts +70 -0
  153. package/dist/hooks/useResumeGame.d.ts.map +1 -0
  154. package/dist/hooks/useResumeGame.js +123 -0
  155. package/dist/hooks/useResumeGame.js.map +1 -0
  156. package/dist/hooks/useStrategies.d.ts +39 -0
  157. package/dist/hooks/useStrategies.d.ts.map +1 -0
  158. package/dist/hooks/useStrategies.js +34 -0
  159. package/dist/hooks/useStrategies.js.map +1 -0
  160. package/dist/hooks/useSudoku.d.ts +5 -0
  161. package/dist/hooks/useSudoku.d.ts.map +1 -1
  162. package/dist/hooks/useSudoku.js +7 -1
  163. package/dist/hooks/useSudoku.js.map +1 -1
  164. package/dist/hooks/useTechniqueByPath.d.ts +46 -0
  165. package/dist/hooks/useTechniqueByPath.d.ts.map +1 -0
  166. package/dist/hooks/useTechniqueByPath.js +47 -0
  167. package/dist/hooks/useTechniqueByPath.js.map +1 -0
  168. package/dist/hooks/useTechniqueExample.d.ts +60 -0
  169. package/dist/hooks/useTechniqueExample.d.ts.map +1 -0
  170. package/dist/hooks/useTechniqueExample.js +63 -0
  171. package/dist/hooks/useTechniqueExample.js.map +1 -0
  172. package/dist/hooks/useTechniques.d.ts +8 -8
  173. package/dist/hooks/useTechniques.d.ts.map +1 -1
  174. package/dist/hooks/useTechniques.js +9 -21
  175. package/dist/hooks/useTechniques.js.map +1 -1
  176. package/dist/index.d.ts +418 -11
  177. package/dist/index.d.ts.map +1 -1
  178. package/dist/index.js +276 -10
  179. package/dist/index.js.map +1 -1
  180. package/dist/types/currentGame.d.ts +9 -1
  181. package/dist/types/currentGame.d.ts.map +1 -1
  182. package/dist/types/currentGame.js.map +1 -1
  183. package/dist/utils/auth.d.ts +6 -0
  184. package/dist/utils/auth.d.ts.map +1 -1
  185. package/dist/utils/auth.js +8 -0
  186. package/dist/utils/auth.js.map +1 -1
  187. package/dist/utils/community.d.ts +64 -0
  188. package/dist/utils/community.d.ts.map +1 -0
  189. package/dist/utils/community.js +66 -0
  190. package/dist/utils/community.js.map +1 -0
  191. package/dist/utils/date.d.ts +37 -0
  192. package/dist/utils/date.d.ts.map +1 -0
  193. package/dist/utils/date.js +68 -0
  194. package/dist/utils/date.js.map +1 -0
  195. package/dist/utils/entityTranslate.d.ts +120 -0
  196. package/dist/utils/entityTranslate.d.ts.map +1 -0
  197. package/dist/utils/entityTranslate.js +146 -0
  198. package/dist/utils/entityTranslate.js.map +1 -0
  199. package/dist/utils/gameFetchStatus.d.ts +74 -0
  200. package/dist/utils/gameFetchStatus.d.ts.map +1 -0
  201. package/dist/utils/gameFetchStatus.js +118 -0
  202. package/dist/utils/gameFetchStatus.js.map +1 -0
  203. package/dist/utils/gamification.d.ts +36 -0
  204. package/dist/utils/gamification.d.ts.map +1 -0
  205. package/dist/utils/gamification.js +33 -0
  206. package/dist/utils/gamification.js.map +1 -0
  207. package/dist/utils/hintAccess.d.ts +64 -0
  208. package/dist/utils/hintAccess.d.ts.map +1 -0
  209. package/dist/utils/hintAccess.js +57 -0
  210. package/dist/utils/hintAccess.js.map +1 -0
  211. package/dist/utils/index.d.ts +31 -10
  212. package/dist/utils/index.d.ts.map +1 -1
  213. package/dist/utils/index.js +20 -9
  214. package/dist/utils/index.js.map +1 -1
  215. package/dist/utils/language.d.ts +123 -0
  216. package/dist/utils/language.d.ts.map +1 -0
  217. package/dist/utils/language.js +95 -0
  218. package/dist/utils/language.js.map +1 -0
  219. package/dist/utils/localizedHint.d.ts +60 -0
  220. package/dist/utils/localizedHint.d.ts.map +1 -1
  221. package/dist/utils/localizedHint.js +90 -0
  222. package/dist/utils/localizedHint.js.map +1 -1
  223. package/dist/utils/progress.d.ts +10 -1
  224. package/dist/utils/progress.d.ts.map +1 -1
  225. package/dist/utils/progress.js +24 -0
  226. package/dist/utils/progress.js.map +1 -1
  227. package/dist/utils/scannedBoard.d.ts +88 -0
  228. package/dist/utils/scannedBoard.d.ts.map +1 -0
  229. package/dist/utils/scannedBoard.js +101 -0
  230. package/dist/utils/scannedBoard.js.map +1 -0
  231. package/dist/utils/shareUrl.d.ts +38 -15
  232. package/dist/utils/shareUrl.d.ts.map +1 -1
  233. package/dist/utils/shareUrl.js +75 -26
  234. package/dist/utils/shareUrl.js.map +1 -1
  235. package/dist/utils/subscription.d.ts +118 -0
  236. package/dist/utils/subscription.d.ts.map +1 -1
  237. package/dist/utils/subscription.js +212 -0
  238. package/dist/utils/subscription.js.map +1 -1
  239. package/dist/utils/sudokuPresenter.d.ts +42 -0
  240. package/dist/utils/sudokuPresenter.d.ts.map +1 -1
  241. package/dist/utils/sudokuPresenter.js +114 -1
  242. package/dist/utils/sudokuPresenter.js.map +1 -1
  243. package/dist/utils/sudokuScrambler.d.ts +8 -0
  244. package/dist/utils/sudokuScrambler.d.ts.map +1 -1
  245. package/dist/utils/sudokuScrambler.js +12 -0
  246. package/dist/utils/sudokuScrambler.js.map +1 -1
  247. package/dist/utils/technique.d.ts +112 -1
  248. package/dist/utils/technique.d.ts.map +1 -1
  249. package/dist/utils/technique.js +293 -1
  250. package/dist/utils/technique.js.map +1 -1
  251. package/dist/utils/techniqueBitmask.d.ts +31 -0
  252. package/dist/utils/techniqueBitmask.d.ts.map +1 -0
  253. package/dist/utils/techniqueBitmask.js +53 -0
  254. package/dist/utils/techniqueBitmask.js.map +1 -0
  255. package/dist/utils/techniqueExample.d.ts +42 -0
  256. package/dist/utils/techniqueExample.d.ts.map +1 -0
  257. package/dist/utils/techniqueExample.js +57 -0
  258. package/dist/utils/techniqueExample.js.map +1 -0
  259. package/dist/utils/theme.d.ts +2 -0
  260. package/dist/utils/theme.d.ts.map +1 -1
  261. package/dist/utils/theme.js +2 -0
  262. package/dist/utils/theme.js.map +1 -1
  263. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"useSudoku.js","sourceRoot":"","sources":["../../src/hooks/useSudoku.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * useSudoku hook - Main game state management\n *\n * Ported from renderable/sudokuschool/interactors/sudoku/SudokuInteractor.kt\n *\n * Handles:\n * - Board initialization with scrambling\n * - Cell selection\n * - Value input (normal and pencil modes)\n * - Error detection\n * - Game completion detection\n * - Undo functionality\n * - Auto pencilmarks generation\n */\n\nimport { useCallback, useMemo, useReducer } from 'react';\nimport {\n blockOf,\n cellHasError,\n columnOf,\n DEFAULT_APP_SETTINGS,\n DEFAULT_PLAY_SETTINGS,\n PlayingSource,\n rowOf,\n SudokuAppSettings,\n SudokuBoard,\n SudokuCell,\n SudokuPlay,\n} from '../types/sudoku';\nimport {\n cellsToInputString,\n cellsToPencilmarksString,\n cellsToPuzzleString,\n cellsToStateString,\n NonScrambler,\n parsePuzzleString,\n scrambleBoard,\n Scrambler,\n ScramblerProtocol,\n} from '../utils/sudokuScrambler';\n\n// =============================================================================\n// State Types\n// =============================================================================\n\ninterface SudokuState {\n /** Current play state */\n play: SudokuPlay | null;\n /** Original puzzle string (before scrambling) */\n originalPuzzle: string;\n /** Original solution string (before scrambling) */\n originalSolution: string;\n /** Puzzle source */\n source: PlayingSource;\n /** Level UUID if from a level */\n levelUuid: string | null;\n /** Board UUID if applicable */\n boardUuid: string | null;\n /** Undo history stack */\n history: SudokuPlay[];\n /** App settings */\n appSettings: SudokuAppSettings;\n /** Digit mapping from original (1-9) to scrambled (1-9) */\n digitMapping: Map<number, number>;\n /** Reverse digit mapping (scrambled -> original) */\n reverseDigitMapping: Map<number, number>;\n}\n\n// =============================================================================\n// Actions\n// =============================================================================\n\ntype SudokuAction =\n | {\n type: 'LOAD_BOARD';\n puzzle: string;\n solution: string;\n scramble: boolean;\n symmetrical: boolean;\n source: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n | { type: 'SELECT_CELL'; index: number }\n | { type: 'DESELECT_CELL' }\n | { type: 'INPUT'; value: number | null }\n | { type: 'TOGGLE_PENCIL_MODE' }\n | { type: 'SET_PENCIL_MODE'; enabled: boolean }\n | { type: 'UNDO' }\n | { type: 'ERASE' }\n | { type: 'AUTO_PENCILMARKS' }\n | { type: 'UPDATE_APP_SETTINGS'; settings: Partial<SudokuAppSettings> }\n | { type: 'RESET' }\n | {\n type: 'APPLY_HINT_DATA';\n userInput: string;\n pencilmarks: string | null;\n autoPencilmarks: boolean;\n };\n\n// =============================================================================\n// Initial State\n// =============================================================================\n\nfunction createInitialState(\n appSettings?: Partial<SudokuAppSettings>\n): SudokuState {\n return {\n play: null,\n originalPuzzle: '',\n originalSolution: '',\n source: 'LEVEL',\n levelUuid: null,\n boardUuid: null,\n history: [],\n appSettings: { ...DEFAULT_APP_SETTINGS, ...appSettings },\n digitMapping: new Map(),\n reverseDigitMapping: new Map(),\n };\n}\n\n// =============================================================================\n// Reducer\n// =============================================================================\n\nfunction sudokuReducer(state: SudokuState, action: SudokuAction): SudokuState {\n switch (action.type) {\n case 'LOAD_BOARD': {\n const {\n puzzle,\n solution,\n scramble,\n symmetrical,\n source,\n levelUuid,\n boardUuid,\n } = action;\n\n // Parse puzzle and solution into cells\n const cells = parsePuzzleString(puzzle, solution);\n\n // Apply scrambling if requested\n const scrambler: ScramblerProtocol = scramble ? Scrambler : NonScrambler;\n const scrambleResult = scrambleBoard(scrambler, cells, symmetrical);\n\n // Check if puzzle is already complete (all cells are clues, or all inputs match solution)\n const isComplete = scrambleResult.cells.every(cell => {\n if (cell.given !== null) return true; // Clue cells are always correct\n // Non-clue cells need input to match solution\n return cell.input !== null && cell.input === cell.solution;\n });\n\n // Create initial board\n const board: SudokuBoard = {\n cells: scrambleResult.cells,\n completed: isComplete,\n entering: false,\n enteringError: null,\n };\n\n // Create initial play state\n const play: SudokuPlay = {\n board,\n settings: { ...DEFAULT_PLAY_SETTINGS },\n selectedIndex: null,\n };\n\n return {\n ...createInitialState(state.appSettings),\n play,\n originalPuzzle: puzzle,\n originalSolution: solution,\n source,\n levelUuid: levelUuid ?? null,\n boardUuid: boardUuid ?? null,\n digitMapping: scrambleResult.digitMapping,\n reverseDigitMapping: scrambleResult.reverseDigitMapping,\n appSettings: state.appSettings,\n };\n }\n\n case 'SELECT_CELL': {\n if (!state.play) return state;\n if (state.play.board.completed) return state; // Can't select when completed\n\n return {\n ...state,\n play: {\n ...state.play,\n selectedIndex:\n state.play.selectedIndex === action.index ? null : action.index,\n },\n };\n }\n\n case 'DESELECT_CELL': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n selectedIndex: null,\n },\n };\n }\n\n case 'INPUT': {\n if (!state.play) return state;\n const { selectedIndex, board, settings } = state.play;\n if (selectedIndex === null) return state;\n if (board.completed) return state;\n\n const cell = board.cells[selectedIndex];\n if (!cell) return state;\n\n // Can't modify given (clue) cells\n if (cell.given !== null) return state;\n\n const { value } = action;\n\n // Handle pencil marking mode\n // Matches Kotlin: if (cell.given == null && value != null)\n if (settings.pencilmarking) {\n if (value === null) return state; // Can't erase in pencil mode with null\n\n // Toggle pencilmark - matches Kotlin exactly\n const currentPencilmarks = cell.pencilmarks ?? [];\n const newPencilmarks = currentPencilmarks.includes(value)\n ? currentPencilmarks.filter(p => p !== value)\n : [...currentPencilmarks, value].sort((a, b) => a - b);\n\n const newCell: SudokuCell = {\n ...cell,\n input: null, // Clear input when setting pencilmarks\n pencilmarks: newPencilmarks,\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n // Normal input mode\n const row = rowOf(selectedIndex);\n const column = columnOf(selectedIndex);\n const block = blockOf(selectedIndex);\n\n let completed = true;\n const newCells = board.cells.map((c, i) => {\n if (c.given !== null) return c; // Skip clue cells\n\n if (i === selectedIndex) {\n // Update the selected cell\n // Matches Kotlin: pencilmarks = if (value != null) null else cell.pencilmarks\n const modified: SudokuCell = {\n ...c,\n input: value,\n pencilmarks: value !== null ? null : c.pencilmarks,\n };\n\n // Check completion\n if (modified.input !== modified.solution) {\n completed = false;\n }\n return modified;\n }\n\n // Remove pencilmark from related cells\n // Matches Kotlin: cell.pencilmarks?.filter { it != value }?.toTypedArray()\n if (value !== null) {\n const cellRow = rowOf(i);\n const cellColumn = columnOf(i);\n const cellBlock = blockOf(i);\n\n if (cellRow === row || cellColumn === column || cellBlock === block) {\n const modified: SudokuCell = {\n ...c,\n pencilmarks: c.pencilmarks?.filter(p => p !== value) ?? null,\n };\n // Check completion\n if (modified.input !== modified.solution) {\n completed = false;\n }\n return modified;\n }\n }\n\n // Check completion for unmodified cells\n if (c.input !== c.solution) {\n completed = false;\n }\n return c;\n });\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: {\n ...board,\n cells: newCells,\n completed,\n },\n selectedIndex: null, // Deselect after input\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'TOGGLE_PENCIL_MODE': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n settings: {\n ...state.play.settings,\n pencilmarking: !state.play.settings.pencilmarking,\n },\n },\n };\n }\n\n case 'SET_PENCIL_MODE': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n settings: {\n ...state.play.settings,\n pencilmarking: action.enabled,\n },\n },\n };\n }\n\n case 'UNDO': {\n if (state.history.length === 0) return state;\n\n const newHistory = [...state.history];\n const previousPlay = newHistory.pop();\n if (!previousPlay) return state;\n\n return {\n ...state,\n history: newHistory,\n play: previousPlay,\n };\n }\n\n case 'ERASE': {\n if (!state.play) return state;\n const { selectedIndex, board, settings } = state.play;\n if (selectedIndex === null) return state;\n if (board.completed) return state;\n\n const cell = board.cells[selectedIndex];\n if (!cell || cell.given !== null) return state;\n\n // In pencil mode, clear pencilmarks\n if (settings.pencilmarking) {\n if (!cell.pencilmarks || cell.pencilmarks.length === 0) return state;\n\n const newCell: SudokuCell = {\n ...cell,\n pencilmarks: [],\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n // In normal mode, clear input\n if (cell.input === null) return state;\n\n const newCell: SudokuCell = {\n ...cell,\n input: null,\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'AUTO_PENCILMARKS': {\n // Matches Kotlin: fun autoPencilmarks()\n if (!state.play) return state;\n const { board } = state.play;\n if (board.completed) return state;\n\n // Calculate potentials for each row, column, and block\n // Matches Kotlin: Array(9) { CellPotentials((1..9).toMutableSet()) }\n const rowPotentials: Map<number, Set<number>> = new Map();\n const colPotentials: Map<number, Set<number>> = new Map();\n const blockPotentials: Map<number, Set<number>> = new Map();\n for (let i = 0; i < 9; i++) {\n rowPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n colPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n blockPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n }\n\n // Remove values that are already placed\n board.cells.forEach((cell, index) => {\n const value = cell.given ?? cell.input;\n if (value !== null) {\n rowPotentials.get(rowOf(index))?.delete(value);\n colPotentials.get(columnOf(index))?.delete(value);\n blockPotentials.get(blockOf(index))?.delete(value);\n }\n });\n\n // Calculate pencilmarks for each empty cell\n const newCells = board.cells.map((cell, index) => {\n const value = cell.given ?? cell.input;\n if (value !== null) {\n // Cell has a value - matches Kotlin: pencilmarks = null\n return { ...cell, pencilmarks: null };\n }\n\n // Intersect row, column, and block potentials\n const row = rowPotentials.get(rowOf(index)) ?? new Set<number>();\n const col = colPotentials.get(columnOf(index)) ?? new Set<number>();\n const block = blockPotentials.get(blockOf(index)) ?? new Set<number>();\n\n const pencilmarks = Array.from(row)\n .filter(v => col.has(v) && block.has(v))\n .sort((a, b) => a - b);\n\n return { ...cell, pencilmarks };\n });\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n settings: { ...state.play.settings, autoPencilmarks: true },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'UPDATE_APP_SETTINGS': {\n return {\n ...state,\n appSettings: { ...state.appSettings, ...action.settings },\n };\n }\n\n case 'RESET': {\n if (!state.play) return state;\n\n // Reset to initial board state (keep original puzzle but clear all inputs)\n const cells = parsePuzzleString(\n state.originalPuzzle,\n state.originalSolution\n );\n const scrambler: ScramblerProtocol = NonScrambler; // Don't re-scramble on reset\n\n // Re-apply the same scrambling\n let newCells = cells;\n if (state.digitMapping.size > 0) {\n // Use the stored digit mapping to recreate scrambled cells\n const scrambleResult = scrambleBoard(scrambler, cells, false);\n newCells = scrambleResult.cells;\n }\n\n const board: SudokuBoard = {\n cells: newCells,\n completed: false,\n entering: false,\n enteringError: null,\n };\n\n const play: SudokuPlay = {\n board,\n settings: { ...DEFAULT_PLAY_SETTINGS },\n selectedIndex: null,\n };\n\n return {\n ...state,\n play,\n history: [],\n };\n }\n\n case 'APPLY_HINT_DATA': {\n // Matches Kotlin HintInteractor.apply() - applies board data from hint API response\n if (!state.play) return state;\n const { board } = state.play;\n\n const { userInput, pencilmarks, autoPencilmarks } = action;\n\n // Parse pencilmarks string (comma-separated, 81 entries)\n // Each entry is a string of digits (e.g., \"123\" for pencilmarks 1,2,3)\n const pencilmarksArray: (number[] | null)[] = pencilmarks\n ? pencilmarks.split(',').map(entry => {\n if (!entry || entry === '') return null;\n return entry\n .split('')\n .map(d => parseInt(d, 10))\n .filter(n => !isNaN(n) && n > 0);\n })\n : Array(81).fill(null);\n\n // Apply user input and pencilmarks to each cell\n let isComplete = true;\n const newCells = board.cells.map((cell, index) => {\n // Get input value from userInput string (0 means no input)\n const inputChar = userInput.charAt(index);\n const inputValue =\n inputChar >= '1' && inputChar <= '9' ? parseInt(inputChar, 10) : null;\n\n // Get pencilmarks for this cell\n const cellPencilmarks = pencilmarksArray[index];\n\n // Check completion - matches Kotlin: if (cell.given == null && cell.solution != cell.input)\n if (cell.given === null && inputValue !== cell.solution) {\n isComplete = false;\n }\n\n // If cell has a given value, don't modify it\n if (cell.given !== null) {\n return cell;\n }\n\n // Apply input and pencilmarks - matches Kotlin: input = if (input != 0) input else null\n return {\n ...cell,\n input: inputValue,\n pencilmarks:\n cellPencilmarks && cellPencilmarks.length > 0\n ? cellPencilmarks\n : null,\n };\n });\n\n const newBoard: SudokuBoard = {\n ...board,\n cells: newCells,\n completed: isComplete,\n };\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: newBoard,\n settings: {\n ...state.play.settings,\n autoPencilmarks,\n },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n default:\n return state;\n }\n}\n\n// =============================================================================\n// Hook Options and Result Types\n// =============================================================================\n\nexport interface UseSudokuOptions {\n /** Initial app settings */\n appSettings?: Partial<SudokuAppSettings>;\n}\n\nexport interface UseSudokuResult {\n // State\n /** Current play state (null if no board loaded) */\n play: SudokuPlay | null;\n /** Current board (shortcut to play.board) */\n board: SudokuBoard | null;\n /** Currently selected cell */\n selectedCell: SudokuCell | null;\n /** Selected cell index */\n selectedIndex: number | null;\n /** Whether pencil mode is active */\n isPencilMode: boolean;\n /** Whether game is completed */\n isCompleted: boolean;\n /** Whether undo is available */\n canUndo: boolean;\n /** App settings */\n appSettings: SudokuAppSettings;\n /** Digit mapping (original -> scrambled) */\n digitMapping: Map<number, number>;\n /** Reverse digit mapping (scrambled -> original) */\n reverseDigitMapping: Map<number, number>;\n\n // Computed values\n /** Cells with errors (when showErrors is enabled) */\n errorCells: SudokuCell[];\n /** Count of errors */\n errorCount: number;\n /** Progress percentage (0-100) */\n progress: number;\n /** Cells with the same value as selected cell */\n sameValueCells: SudokuCell[];\n /** Related cells (same row, column, block) */\n relatedCells: SudokuCell[];\n\n // Actions\n /** Load a new board */\n loadBoard: (\n puzzle: string,\n solution: string,\n options?: {\n scramble?: boolean;\n symmetrical?: boolean;\n source?: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n ) => void;\n /** Select a cell by index */\n selectCell: (index: number) => void;\n /** Select a cell by row and column */\n selectCellAt: (row: number, column: number) => void;\n /** Deselect the current cell */\n deselectCell: () => void;\n /** Input a value (1-9) into the selected cell */\n input: (value: number) => void;\n /** Erase the selected cell */\n erase: () => void;\n /** Toggle pencil mode */\n togglePencilMode: () => void;\n /** Set pencil mode */\n setPencilMode: (enabled: boolean) => void;\n /** Undo the last action */\n undo: () => void;\n /** Generate auto pencilmarks */\n autoPencilmarks: () => void;\n /** Update app settings */\n updateSettings: (settings: Partial<SudokuAppSettings>) => void;\n /** Reset the game to initial state */\n reset: () => void;\n /** Apply hint data from solver API response */\n applyHintData: (\n userInput: string,\n pencilmarks: string | null,\n autoPencilmarks: boolean\n ) => void;\n\n // Utility functions\n /** Get board state as string */\n getBoardString: () => string;\n /** Get original puzzle string (before scrambling) */\n getOriginalPuzzle: () => string;\n /** Get scrambled puzzle string (what the user is playing) - use this for solver API */\n getScrambledPuzzle: () => string;\n /** Get input string (user entries only) */\n getInputString: () => string;\n /** Get pencilmarks string */\n getPencilmarksString: () => string;\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Main Sudoku game hook\n *\n * @example\n * ```tsx\n * const {\n * play,\n * board,\n * selectedCell,\n * isPencilMode,\n * isCompleted,\n * loadBoard,\n * selectCell,\n * input,\n * togglePencilMode,\n * undo,\n * } = useSudoku();\n *\n * // Load a puzzle\n * loadBoard(puzzleString, solutionString, { scramble: true });\n *\n * // Select a cell and enter a value\n * selectCell(0);\n * input(5);\n *\n * // Toggle pencil mode\n * togglePencilMode();\n * input(1); // Adds 1 as pencilmark\n * input(2); // Adds 2 as pencilmark\n * input(1); // Removes 1 from pencilmarks\n * ```\n */\nexport function useSudoku(options: UseSudokuOptions = {}): UseSudokuResult {\n const [state, dispatch] = useReducer(\n sudokuReducer,\n options.appSettings,\n createInitialState\n );\n\n // Computed values\n const board = state.play?.board ?? null;\n const selectedIndex = state.play?.selectedIndex ?? null;\n const selectedCell =\n selectedIndex !== null && board\n ? (board.cells[selectedIndex] ?? null)\n : null;\n const isPencilMode = state.play?.settings.pencilmarking ?? false;\n const isCompleted = board?.completed ?? false;\n const canUndo = state.history.length > 0;\n\n const errorCells = useMemo(() => {\n if (!board || !state.appSettings.showErrors) return [];\n return board.cells.filter(cellHasError);\n }, [board, state.appSettings.showErrors]);\n\n const errorCount = errorCells.length;\n\n const progress = useMemo(() => {\n if (!board) return 0;\n const totalEmpty = board.cells.filter(c => c.given === null).length;\n if (totalEmpty === 0) return 100;\n const filled = board.cells.filter(\n c => c.given === null && c.input !== null\n ).length;\n return Math.round((filled / totalEmpty) * 100);\n }, [board]);\n\n const sameValueCells = useMemo(() => {\n if (!board || selectedIndex === null) return [];\n const selectedCell = board.cells[selectedIndex];\n if (!selectedCell) return [];\n const value = selectedCell.given ?? selectedCell.input;\n if (value === null) return [];\n return board.cells.filter((c, i) => {\n if (i === selectedIndex) return false;\n return (c.given ?? c.input) === value;\n });\n }, [board, selectedIndex]);\n\n const relatedCells = useMemo(() => {\n if (!board || selectedIndex === null) return [];\n const row = rowOf(selectedIndex);\n const col = columnOf(selectedIndex);\n const block = blockOf(selectedIndex);\n return board.cells.filter((_, i) => {\n if (i === selectedIndex) return false;\n return rowOf(i) === row || columnOf(i) === col || blockOf(i) === block;\n });\n }, [board, selectedIndex]);\n\n // Actions\n const loadBoard = useCallback(\n (\n puzzle: string,\n solution: string,\n options?: {\n scramble?: boolean;\n symmetrical?: boolean;\n source?: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n ) => {\n const action: SudokuAction = {\n type: 'LOAD_BOARD',\n puzzle,\n solution,\n scramble: options?.scramble ?? true,\n symmetrical: options?.symmetrical ?? false,\n source: options?.source ?? 'LEVEL',\n };\n if (options?.levelUuid !== undefined) {\n (action as { levelUuid?: string }).levelUuid = options.levelUuid;\n }\n if (options?.boardUuid !== undefined) {\n (action as { boardUuid?: string }).boardUuid = options.boardUuid;\n }\n dispatch(action);\n },\n []\n );\n\n const selectCell = useCallback((index: number) => {\n dispatch({ type: 'SELECT_CELL', index });\n }, []);\n\n const selectCellAt = useCallback((row: number, column: number) => {\n dispatch({ type: 'SELECT_CELL', index: row * 9 + column });\n }, []);\n\n const deselectCell = useCallback(() => {\n dispatch({ type: 'DESELECT_CELL' });\n }, []);\n\n const input = useCallback((value: number) => {\n dispatch({ type: 'INPUT', value });\n }, []);\n\n const erase = useCallback(() => {\n dispatch({ type: 'ERASE' });\n }, []);\n\n const togglePencilMode = useCallback(() => {\n dispatch({ type: 'TOGGLE_PENCIL_MODE' });\n }, []);\n\n const setPencilMode = useCallback((enabled: boolean) => {\n dispatch({ type: 'SET_PENCIL_MODE', enabled });\n }, []);\n\n const undo = useCallback(() => {\n dispatch({ type: 'UNDO' });\n }, []);\n\n const autoPencilmarks = useCallback(() => {\n dispatch({ type: 'AUTO_PENCILMARKS' });\n }, []);\n\n const updateSettings = useCallback((settings: Partial<SudokuAppSettings>) => {\n dispatch({ type: 'UPDATE_APP_SETTINGS', settings });\n }, []);\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' });\n }, []);\n\n const applyHintData = useCallback(\n (\n userInput: string,\n pencilmarks: string | null,\n autoPencilmarks: boolean\n ) => {\n dispatch({\n type: 'APPLY_HINT_DATA',\n userInput,\n pencilmarks,\n autoPencilmarks,\n });\n },\n []\n );\n\n // Utility functions\n const getBoardString = useCallback(() => {\n if (!board) return '';\n return cellsToStateString(board.cells);\n }, [board]);\n\n const getOriginalPuzzle = useCallback(() => {\n return state.originalPuzzle;\n }, [state.originalPuzzle]);\n\n const getScrambledPuzzle = useCallback(() => {\n if (!board) return '';\n return cellsToPuzzleString(board.cells);\n }, [board]);\n\n const getInputString = useCallback(() => {\n if (!board) return '';\n return cellsToInputString(board.cells);\n }, [board]);\n\n const getPencilmarksString = useCallback(() => {\n if (!board) return '';\n return cellsToPencilmarksString(board.cells);\n }, [board]);\n\n return {\n // State\n play: state.play,\n board,\n selectedCell,\n selectedIndex,\n isPencilMode,\n isCompleted,\n canUndo,\n appSettings: state.appSettings,\n digitMapping: state.digitMapping,\n reverseDigitMapping: state.reverseDigitMapping,\n\n // Computed\n errorCells,\n errorCount,\n progress,\n sameValueCells,\n relatedCells,\n\n // Actions\n loadBoard,\n selectCell,\n selectCellAt,\n deselectCell,\n input,\n erase,\n togglePencilMode,\n setPencilMode,\n undo,\n autoPencilmarks,\n updateSettings,\n reset,\n applyHintData,\n\n // Utilities\n getBoardString,\n getOriginalPuzzle,\n getScrambledPuzzle,\n getInputString,\n getPencilmarksString,\n };\n}\n"]}
1
+ {"version":3,"file":"useSudoku.js","sourceRoot":"","sources":["../../src/hooks/useSudoku.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * useSudoku hook - Main game state management\n *\n * Ported from renderable/sudokuschool/interactors/sudoku/SudokuInteractor.kt\n *\n * Handles:\n * - Board initialization with scrambling\n * - Cell selection\n * - Value input (normal and pencil modes)\n * - Error detection\n * - Game completion detection\n * - Undo functionality\n * - Auto pencilmarks generation\n */\n\nimport { useCallback, useMemo, useReducer } from 'react';\nimport {\n blockOf,\n cellHasError,\n columnOf,\n DEFAULT_APP_SETTINGS,\n DEFAULT_PLAY_SETTINGS,\n PlayingSource,\n rowOf,\n SudokuAppSettings,\n SudokuBoard,\n SudokuCell,\n SudokuPlay,\n} from '../types/sudoku';\nimport {\n cellsToInputString,\n cellsToPencilmarksString,\n cellsToPuzzleString,\n cellsToSolutionString,\n cellsToStateString,\n NonScrambler,\n parsePuzzleString,\n scrambleBoard,\n Scrambler,\n ScramblerProtocol,\n} from '../utils/sudokuScrambler';\n\n// =============================================================================\n// State Types\n// =============================================================================\n\ninterface SudokuState {\n /** Current play state */\n play: SudokuPlay | null;\n /** Original puzzle string (before scrambling) */\n originalPuzzle: string;\n /** Original solution string (before scrambling) */\n originalSolution: string;\n /** Puzzle source */\n source: PlayingSource;\n /** Level UUID if from a level */\n levelUuid: string | null;\n /** Board UUID if applicable */\n boardUuid: string | null;\n /** Undo history stack */\n history: SudokuPlay[];\n /** App settings */\n appSettings: SudokuAppSettings;\n /** Digit mapping from original (1-9) to scrambled (1-9) */\n digitMapping: Map<number, number>;\n /** Reverse digit mapping (scrambled -> original) */\n reverseDigitMapping: Map<number, number>;\n}\n\n// =============================================================================\n// Actions\n// =============================================================================\n\ntype SudokuAction =\n | {\n type: 'LOAD_BOARD';\n puzzle: string;\n solution: string;\n scramble: boolean;\n symmetrical: boolean;\n source: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n | { type: 'SELECT_CELL'; index: number }\n | { type: 'DESELECT_CELL' }\n | { type: 'INPUT'; value: number | null }\n | { type: 'TOGGLE_PENCIL_MODE' }\n | { type: 'SET_PENCIL_MODE'; enabled: boolean }\n | { type: 'UNDO' }\n | { type: 'ERASE' }\n | { type: 'AUTO_PENCILMARKS' }\n | { type: 'UPDATE_APP_SETTINGS'; settings: Partial<SudokuAppSettings> }\n | { type: 'RESET' }\n | {\n type: 'APPLY_HINT_DATA';\n userInput: string;\n pencilmarks: string | null;\n autoPencilmarks: boolean;\n };\n\n// =============================================================================\n// Initial State\n// =============================================================================\n\nfunction createInitialState(\n appSettings?: Partial<SudokuAppSettings>\n): SudokuState {\n return {\n play: null,\n originalPuzzle: '',\n originalSolution: '',\n source: 'LEVEL',\n levelUuid: null,\n boardUuid: null,\n history: [],\n appSettings: { ...DEFAULT_APP_SETTINGS, ...appSettings },\n digitMapping: new Map(),\n reverseDigitMapping: new Map(),\n };\n}\n\n// =============================================================================\n// Reducer\n// =============================================================================\n\nfunction sudokuReducer(state: SudokuState, action: SudokuAction): SudokuState {\n switch (action.type) {\n case 'LOAD_BOARD': {\n const {\n puzzle,\n solution,\n scramble,\n symmetrical,\n source,\n levelUuid,\n boardUuid,\n } = action;\n\n // Parse puzzle and solution into cells\n const cells = parsePuzzleString(puzzle, solution);\n\n // Apply scrambling if requested\n const scrambler: ScramblerProtocol = scramble ? Scrambler : NonScrambler;\n const scrambleResult = scrambleBoard(scrambler, cells, symmetrical);\n\n // Check if puzzle is already complete (all cells are clues, or all inputs match solution)\n const isComplete = scrambleResult.cells.every(cell => {\n if (cell.given !== null) return true; // Clue cells are always correct\n // Non-clue cells need input to match solution\n return cell.input !== null && cell.input === cell.solution;\n });\n\n // Create initial board\n const board: SudokuBoard = {\n cells: scrambleResult.cells,\n completed: isComplete,\n entering: false,\n enteringError: null,\n };\n\n // Create initial play state\n const play: SudokuPlay = {\n board,\n settings: { ...DEFAULT_PLAY_SETTINGS },\n selectedIndex: null,\n };\n\n return {\n ...createInitialState(state.appSettings),\n play,\n originalPuzzle: puzzle,\n originalSolution: solution,\n source,\n levelUuid: levelUuid ?? null,\n boardUuid: boardUuid ?? null,\n digitMapping: scrambleResult.digitMapping,\n reverseDigitMapping: scrambleResult.reverseDigitMapping,\n appSettings: state.appSettings,\n };\n }\n\n case 'SELECT_CELL': {\n if (!state.play) return state;\n if (state.play.board.completed) return state; // Can't select when completed\n\n return {\n ...state,\n play: {\n ...state.play,\n selectedIndex:\n state.play.selectedIndex === action.index ? null : action.index,\n },\n };\n }\n\n case 'DESELECT_CELL': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n selectedIndex: null,\n },\n };\n }\n\n case 'INPUT': {\n if (!state.play) return state;\n const { selectedIndex, board, settings } = state.play;\n if (selectedIndex === null) return state;\n if (board.completed) return state;\n\n const cell = board.cells[selectedIndex];\n if (!cell) return state;\n\n // Can't modify given (clue) cells\n if (cell.given !== null) return state;\n\n const { value } = action;\n\n // Handle pencil marking mode\n // Matches Kotlin: if (cell.given == null && value != null)\n if (settings.pencilmarking) {\n if (value === null) return state; // Can't erase in pencil mode with null\n\n // Toggle pencilmark - matches Kotlin exactly\n const currentPencilmarks = cell.pencilmarks ?? [];\n const newPencilmarks = currentPencilmarks.includes(value)\n ? currentPencilmarks.filter(p => p !== value)\n : [...currentPencilmarks, value].sort((a, b) => a - b);\n\n const newCell: SudokuCell = {\n ...cell,\n input: null, // Clear input when setting pencilmarks\n pencilmarks: newPencilmarks,\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n // Normal input mode\n const row = rowOf(selectedIndex);\n const column = columnOf(selectedIndex);\n const block = blockOf(selectedIndex);\n\n let completed = true;\n const newCells = board.cells.map((c, i) => {\n if (c.given !== null) return c; // Skip clue cells\n\n if (i === selectedIndex) {\n // Update the selected cell\n // Matches Kotlin: pencilmarks = if (value != null) null else cell.pencilmarks\n const modified: SudokuCell = {\n ...c,\n input: value,\n pencilmarks: value !== null ? null : c.pencilmarks,\n };\n\n // Check completion\n if (modified.input !== modified.solution) {\n completed = false;\n }\n return modified;\n }\n\n // Remove pencilmark from related cells\n // Matches Kotlin: cell.pencilmarks?.filter { it != value }?.toTypedArray()\n if (value !== null) {\n const cellRow = rowOf(i);\n const cellColumn = columnOf(i);\n const cellBlock = blockOf(i);\n\n if (cellRow === row || cellColumn === column || cellBlock === block) {\n const modified: SudokuCell = {\n ...c,\n pencilmarks: c.pencilmarks?.filter(p => p !== value) ?? null,\n };\n // Check completion\n if (modified.input !== modified.solution) {\n completed = false;\n }\n return modified;\n }\n }\n\n // Check completion for unmodified cells\n if (c.input !== c.solution) {\n completed = false;\n }\n return c;\n });\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: {\n ...board,\n cells: newCells,\n completed,\n },\n selectedIndex: null, // Deselect after input\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'TOGGLE_PENCIL_MODE': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n settings: {\n ...state.play.settings,\n pencilmarking: !state.play.settings.pencilmarking,\n },\n },\n };\n }\n\n case 'SET_PENCIL_MODE': {\n if (!state.play) return state;\n\n return {\n ...state,\n play: {\n ...state.play,\n settings: {\n ...state.play.settings,\n pencilmarking: action.enabled,\n },\n },\n };\n }\n\n case 'UNDO': {\n if (state.history.length === 0) return state;\n\n const newHistory = [...state.history];\n const previousPlay = newHistory.pop();\n if (!previousPlay) return state;\n\n return {\n ...state,\n history: newHistory,\n play: previousPlay,\n };\n }\n\n case 'ERASE': {\n if (!state.play) return state;\n const { selectedIndex, board, settings } = state.play;\n if (selectedIndex === null) return state;\n if (board.completed) return state;\n\n const cell = board.cells[selectedIndex];\n if (!cell || cell.given !== null) return state;\n\n // In pencil mode, clear pencilmarks\n if (settings.pencilmarking) {\n if (!cell.pencilmarks || cell.pencilmarks.length === 0) return state;\n\n const newCell: SudokuCell = {\n ...cell,\n pencilmarks: [],\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n // In normal mode, clear input\n if (cell.input === null) return state;\n\n const newCell: SudokuCell = {\n ...cell,\n input: null,\n };\n\n const newCells = board.cells.map((c, i) =>\n i === selectedIndex ? newCell : c\n );\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'AUTO_PENCILMARKS': {\n // Matches Kotlin: fun autoPencilmarks()\n if (!state.play) return state;\n const { board } = state.play;\n if (board.completed) return state;\n\n // Calculate potentials for each row, column, and block\n // Matches Kotlin: Array(9) { CellPotentials((1..9).toMutableSet()) }\n const rowPotentials: Map<number, Set<number>> = new Map();\n const colPotentials: Map<number, Set<number>> = new Map();\n const blockPotentials: Map<number, Set<number>> = new Map();\n for (let i = 0; i < 9; i++) {\n rowPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n colPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n blockPotentials.set(i, new Set([1, 2, 3, 4, 5, 6, 7, 8, 9]));\n }\n\n // Remove values that are already placed\n board.cells.forEach((cell, index) => {\n const value = cell.given ?? cell.input;\n if (value !== null) {\n rowPotentials.get(rowOf(index))?.delete(value);\n colPotentials.get(columnOf(index))?.delete(value);\n blockPotentials.get(blockOf(index))?.delete(value);\n }\n });\n\n // Calculate pencilmarks for each empty cell\n const newCells = board.cells.map((cell, index) => {\n const value = cell.given ?? cell.input;\n if (value !== null) {\n // Cell has a value - matches Kotlin: pencilmarks = null\n return { ...cell, pencilmarks: null };\n }\n\n // Intersect row, column, and block potentials\n const row = rowPotentials.get(rowOf(index)) ?? new Set<number>();\n const col = colPotentials.get(columnOf(index)) ?? new Set<number>();\n const block = blockPotentials.get(blockOf(index)) ?? new Set<number>();\n\n const pencilmarks = Array.from(row)\n .filter(v => col.has(v) && block.has(v))\n .sort((a, b) => a - b);\n\n return { ...cell, pencilmarks };\n });\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: { ...board, cells: newCells },\n settings: { ...state.play.settings, autoPencilmarks: true },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n case 'UPDATE_APP_SETTINGS': {\n return {\n ...state,\n appSettings: { ...state.appSettings, ...action.settings },\n };\n }\n\n case 'RESET': {\n if (!state.play) return state;\n\n // Reset to initial board state (keep original puzzle but clear all inputs)\n const cells = parsePuzzleString(\n state.originalPuzzle,\n state.originalSolution\n );\n const scrambler: ScramblerProtocol = NonScrambler; // Don't re-scramble on reset\n\n // Re-apply the same scrambling\n let newCells = cells;\n if (state.digitMapping.size > 0) {\n // Use the stored digit mapping to recreate scrambled cells\n const scrambleResult = scrambleBoard(scrambler, cells, false);\n newCells = scrambleResult.cells;\n }\n\n const board: SudokuBoard = {\n cells: newCells,\n completed: false,\n entering: false,\n enteringError: null,\n };\n\n const play: SudokuPlay = {\n board,\n settings: { ...DEFAULT_PLAY_SETTINGS },\n selectedIndex: null,\n };\n\n return {\n ...state,\n play,\n history: [],\n };\n }\n\n case 'APPLY_HINT_DATA': {\n // Matches Kotlin HintInteractor.apply() - applies board data from hint API response\n if (!state.play) return state;\n const { board } = state.play;\n\n const { userInput, pencilmarks, autoPencilmarks } = action;\n\n // Parse pencilmarks string (comma-separated, 81 entries)\n // Each entry is a string of digits (e.g., \"123\" for pencilmarks 1,2,3)\n const pencilmarksArray: (number[] | null)[] = pencilmarks\n ? pencilmarks.split(',').map(entry => {\n if (!entry || entry === '') return null;\n return entry\n .split('')\n .map(d => parseInt(d, 10))\n .filter(n => !isNaN(n) && n > 0);\n })\n : Array(81).fill(null);\n\n // Apply user input and pencilmarks to each cell\n let isComplete = true;\n const newCells = board.cells.map((cell, index) => {\n // Get input value from userInput string (0 means no input)\n const inputChar = userInput.charAt(index);\n const inputValue =\n inputChar >= '1' && inputChar <= '9' ? parseInt(inputChar, 10) : null;\n\n // Get pencilmarks for this cell\n const cellPencilmarks = pencilmarksArray[index];\n\n // Check completion - matches Kotlin: if (cell.given == null && cell.solution != cell.input)\n if (cell.given === null && inputValue !== cell.solution) {\n isComplete = false;\n }\n\n // If cell has a given value, don't modify it\n if (cell.given !== null) {\n return cell;\n }\n\n // Apply input and pencilmarks - matches Kotlin: input = if (input != 0) input else null\n return {\n ...cell,\n input: inputValue,\n pencilmarks:\n cellPencilmarks && cellPencilmarks.length > 0\n ? cellPencilmarks\n : null,\n };\n });\n\n const newBoard: SudokuBoard = {\n ...board,\n cells: newCells,\n completed: isComplete,\n };\n\n const newPlay: SudokuPlay = {\n ...state.play,\n board: newBoard,\n settings: {\n ...state.play.settings,\n autoPencilmarks,\n },\n };\n\n return {\n ...state,\n history: [...state.history, state.play],\n play: newPlay,\n };\n }\n\n default:\n return state;\n }\n}\n\n// =============================================================================\n// Hook Options and Result Types\n// =============================================================================\n\nexport interface UseSudokuOptions {\n /** Initial app settings */\n appSettings?: Partial<SudokuAppSettings>;\n}\n\nexport interface UseSudokuResult {\n // State\n /** Current play state (null if no board loaded) */\n play: SudokuPlay | null;\n /** Current board (shortcut to play.board) */\n board: SudokuBoard | null;\n /** Currently selected cell */\n selectedCell: SudokuCell | null;\n /** Selected cell index */\n selectedIndex: number | null;\n /** Whether pencil mode is active */\n isPencilMode: boolean;\n /** Whether game is completed */\n isCompleted: boolean;\n /** Whether undo is available */\n canUndo: boolean;\n /** App settings */\n appSettings: SudokuAppSettings;\n /** Digit mapping (original -> scrambled) */\n digitMapping: Map<number, number>;\n /** Reverse digit mapping (scrambled -> original) */\n reverseDigitMapping: Map<number, number>;\n\n // Computed values\n /** Cells with errors (when showErrors is enabled) */\n errorCells: SudokuCell[];\n /** Count of errors */\n errorCount: number;\n /** Progress percentage (0-100) */\n progress: number;\n /** Cells with the same value as selected cell */\n sameValueCells: SudokuCell[];\n /** Related cells (same row, column, block) */\n relatedCells: SudokuCell[];\n\n // Actions\n /** Load a new board */\n loadBoard: (\n puzzle: string,\n solution: string,\n options?: {\n scramble?: boolean;\n symmetrical?: boolean;\n source?: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n ) => void;\n /** Select a cell by index */\n selectCell: (index: number) => void;\n /** Select a cell by row and column */\n selectCellAt: (row: number, column: number) => void;\n /** Deselect the current cell */\n deselectCell: () => void;\n /** Input a value (1-9) into the selected cell */\n input: (value: number) => void;\n /** Erase the selected cell */\n erase: () => void;\n /** Toggle pencil mode */\n togglePencilMode: () => void;\n /** Set pencil mode */\n setPencilMode: (enabled: boolean) => void;\n /** Undo the last action */\n undo: () => void;\n /** Generate auto pencilmarks */\n autoPencilmarks: () => void;\n /** Update app settings */\n updateSettings: (settings: Partial<SudokuAppSettings>) => void;\n /** Reset the game to initial state */\n reset: () => void;\n /** Apply hint data from solver API response */\n applyHintData: (\n userInput: string,\n pencilmarks: string | null,\n autoPencilmarks: boolean\n ) => void;\n\n // Utility functions\n /** Get board state as string */\n getBoardString: () => string;\n /** Get original puzzle string (before scrambling) */\n getOriginalPuzzle: () => string;\n /** Get scrambled puzzle string (what the user is playing) - use this for solver API */\n getScrambledPuzzle: () => string;\n /**\n * Get scrambled solution string (same digit space as getScrambledPuzzle;\n * '0' where unknown) - pair it with getScrambledPuzzle when saving a game\n */\n getScrambledSolution: () => string;\n /** Get input string (user entries only) */\n getInputString: () => string;\n /** Get pencilmarks string */\n getPencilmarksString: () => string;\n}\n\n// =============================================================================\n// Hook Implementation\n// =============================================================================\n\n/**\n * Main Sudoku game hook\n *\n * @example\n * ```tsx\n * const {\n * play,\n * board,\n * selectedCell,\n * isPencilMode,\n * isCompleted,\n * loadBoard,\n * selectCell,\n * input,\n * togglePencilMode,\n * undo,\n * } = useSudoku();\n *\n * // Load a puzzle\n * loadBoard(puzzleString, solutionString, { scramble: true });\n *\n * // Select a cell and enter a value\n * selectCell(0);\n * input(5);\n *\n * // Toggle pencil mode\n * togglePencilMode();\n * input(1); // Adds 1 as pencilmark\n * input(2); // Adds 2 as pencilmark\n * input(1); // Removes 1 from pencilmarks\n * ```\n */\nexport function useSudoku(options: UseSudokuOptions = {}): UseSudokuResult {\n const [state, dispatch] = useReducer(\n sudokuReducer,\n options.appSettings,\n createInitialState\n );\n\n // Computed values\n const board = state.play?.board ?? null;\n const selectedIndex = state.play?.selectedIndex ?? null;\n const selectedCell =\n selectedIndex !== null && board\n ? (board.cells[selectedIndex] ?? null)\n : null;\n const isPencilMode = state.play?.settings.pencilmarking ?? false;\n const isCompleted = board?.completed ?? false;\n const canUndo = state.history.length > 0;\n\n const errorCells = useMemo(() => {\n if (!board || !state.appSettings.showErrors) return [];\n return board.cells.filter(cellHasError);\n }, [board, state.appSettings.showErrors]);\n\n const errorCount = errorCells.length;\n\n const progress = useMemo(() => {\n if (!board) return 0;\n const totalEmpty = board.cells.filter(c => c.given === null).length;\n if (totalEmpty === 0) return 100;\n const filled = board.cells.filter(\n c => c.given === null && c.input !== null\n ).length;\n return Math.round((filled / totalEmpty) * 100);\n }, [board]);\n\n const sameValueCells = useMemo(() => {\n if (!board || selectedIndex === null) return [];\n const selectedCell = board.cells[selectedIndex];\n if (!selectedCell) return [];\n const value = selectedCell.given ?? selectedCell.input;\n if (value === null) return [];\n return board.cells.filter((c, i) => {\n if (i === selectedIndex) return false;\n return (c.given ?? c.input) === value;\n });\n }, [board, selectedIndex]);\n\n const relatedCells = useMemo(() => {\n if (!board || selectedIndex === null) return [];\n const row = rowOf(selectedIndex);\n const col = columnOf(selectedIndex);\n const block = blockOf(selectedIndex);\n return board.cells.filter((_, i) => {\n if (i === selectedIndex) return false;\n return rowOf(i) === row || columnOf(i) === col || blockOf(i) === block;\n });\n }, [board, selectedIndex]);\n\n // Actions\n const loadBoard = useCallback(\n (\n puzzle: string,\n solution: string,\n options?: {\n scramble?: boolean;\n symmetrical?: boolean;\n source?: PlayingSource;\n levelUuid?: string;\n boardUuid?: string;\n }\n ) => {\n const action: SudokuAction = {\n type: 'LOAD_BOARD',\n puzzle,\n solution,\n scramble: options?.scramble ?? true,\n symmetrical: options?.symmetrical ?? false,\n source: options?.source ?? 'LEVEL',\n };\n if (options?.levelUuid !== undefined) {\n (action as { levelUuid?: string }).levelUuid = options.levelUuid;\n }\n if (options?.boardUuid !== undefined) {\n (action as { boardUuid?: string }).boardUuid = options.boardUuid;\n }\n dispatch(action);\n },\n []\n );\n\n const selectCell = useCallback((index: number) => {\n dispatch({ type: 'SELECT_CELL', index });\n }, []);\n\n const selectCellAt = useCallback((row: number, column: number) => {\n dispatch({ type: 'SELECT_CELL', index: row * 9 + column });\n }, []);\n\n const deselectCell = useCallback(() => {\n dispatch({ type: 'DESELECT_CELL' });\n }, []);\n\n const input = useCallback((value: number) => {\n dispatch({ type: 'INPUT', value });\n }, []);\n\n const erase = useCallback(() => {\n dispatch({ type: 'ERASE' });\n }, []);\n\n const togglePencilMode = useCallback(() => {\n dispatch({ type: 'TOGGLE_PENCIL_MODE' });\n }, []);\n\n const setPencilMode = useCallback((enabled: boolean) => {\n dispatch({ type: 'SET_PENCIL_MODE', enabled });\n }, []);\n\n const undo = useCallback(() => {\n dispatch({ type: 'UNDO' });\n }, []);\n\n const autoPencilmarks = useCallback(() => {\n dispatch({ type: 'AUTO_PENCILMARKS' });\n }, []);\n\n const updateSettings = useCallback((settings: Partial<SudokuAppSettings>) => {\n dispatch({ type: 'UPDATE_APP_SETTINGS', settings });\n }, []);\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' });\n }, []);\n\n const applyHintData = useCallback(\n (\n userInput: string,\n pencilmarks: string | null,\n autoPencilmarks: boolean\n ) => {\n dispatch({\n type: 'APPLY_HINT_DATA',\n userInput,\n pencilmarks,\n autoPencilmarks,\n });\n },\n []\n );\n\n // Utility functions\n const getBoardString = useCallback(() => {\n if (!board) return '';\n return cellsToStateString(board.cells);\n }, [board]);\n\n const getOriginalPuzzle = useCallback(() => {\n return state.originalPuzzle;\n }, [state.originalPuzzle]);\n\n const getScrambledPuzzle = useCallback(() => {\n if (!board) return '';\n return cellsToPuzzleString(board.cells);\n }, [board]);\n\n const getScrambledSolution = useCallback(() => {\n if (!board) return '';\n return cellsToSolutionString(board.cells);\n }, [board]);\n\n const getInputString = useCallback(() => {\n if (!board) return '';\n return cellsToInputString(board.cells);\n }, [board]);\n\n const getPencilmarksString = useCallback(() => {\n if (!board) return '';\n return cellsToPencilmarksString(board.cells);\n }, [board]);\n\n return {\n // State\n play: state.play,\n board,\n selectedCell,\n selectedIndex,\n isPencilMode,\n isCompleted,\n canUndo,\n appSettings: state.appSettings,\n digitMapping: state.digitMapping,\n reverseDigitMapping: state.reverseDigitMapping,\n\n // Computed\n errorCells,\n errorCount,\n progress,\n sameValueCells,\n relatedCells,\n\n // Actions\n loadBoard,\n selectCell,\n selectCellAt,\n deselectCell,\n input,\n erase,\n togglePencilMode,\n setPencilMode,\n undo,\n autoPencilmarks,\n updateSettings,\n reset,\n applyHintData,\n\n // Utilities\n getBoardString,\n getOriginalPuzzle,\n getScrambledPuzzle,\n getScrambledSolution,\n getInputString,\n getPencilmarksString,\n };\n}\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Hook for looking up a technique by its URL path, aliases included.
3
+ */
4
+ import type { Technique } from '@sudobility/sudojo_types';
5
+ import type { NetworkClient } from '@sudobility/types';
6
+ export interface UseTechniqueByPathOptions {
7
+ /** Network client for API calls (default: SudojoApiProvider) */
8
+ networkClient?: NetworkClient | undefined;
9
+ /** Base URL for the Sudojo API (default: SudojoApiProvider) */
10
+ baseUrl?: string | undefined;
11
+ /** Access token (optional for this public endpoint) */
12
+ token?: string | null | undefined;
13
+ /** API path or public slug (e.g. '3d-medusa' or 'medusa-coloring') */
14
+ path: string | null | undefined;
15
+ /** Whether to enable the queries (default true) */
16
+ enabled?: boolean;
17
+ }
18
+ export interface UseTechniqueByPathResult {
19
+ /** The technique, once found */
20
+ technique: Technique | null;
21
+ /** All techniques (from useTechniques; for dependencies and navigation) */
22
+ techniques: Technique[];
23
+ /** Public slug for the path ('3d-medusa' -> 'medusa-coloring') */
24
+ canonicalPath: string | undefined;
25
+ /** API path for the path ('medusa-coloring' -> '3d-medusa') */
26
+ apiPath: string | undefined;
27
+ /** Whether the lookup is still loading */
28
+ isLoading: boolean;
29
+ /** True once loading finished without finding the technique */
30
+ notFound: boolean;
31
+ /** Error from the technique list, if any */
32
+ error: Error | null;
33
+ }
34
+ /**
35
+ * Find a technique by path or alias. It is looked up in the cached technique
36
+ * list (useTechniques, which the technique screens load anyway, as both apps
37
+ * did); only when the list has loaded without it does it ask
38
+ * `GET /techniques/path/:apiPath` (useSudojoTechniqueByPath).
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * const { technique, notFound } = useTechniqueByPath({ networkClient, baseUrl, path: slug });
43
+ * ```
44
+ */
45
+ export declare function useTechniqueByPath(options: UseTechniqueByPathOptions): UseTechniqueByPathResult;
46
+ //# sourceMappingURL=useTechniqueByPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTechniqueByPath.d.ts","sourceRoot":"","sources":["../../src/hooks/useTechniqueByPath.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWvD,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChC,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,gCAAgC;IAChC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,2EAA2E;IAC3E,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,kEAAkE;IAClE,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,yBAAyB,GACjC,wBAAwB,CAkD1B"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Hook for looking up a technique by its URL path, aliases included.
3
+ */
4
+ import { useMemo } from 'react';
5
+ import { useSudojoTechniqueByPath } from '@sudobility/sudojo_client';
6
+ import { useResolvedSudojoApi } from '../context/SudojoApiContext';
7
+ import { findTechniqueByPath, isSameTechniquePath, toApiTechniquePath, toCanonicalTechniquePath, } from '../utils/technique';
8
+ import { useTechniques } from './useTechniques';
9
+ /**
10
+ * Find a technique by path or alias. It is looked up in the cached technique
11
+ * list (useTechniques, which the technique screens load anyway, as both apps
12
+ * did); only when the list has loaded without it does it ask
13
+ * `GET /techniques/path/:apiPath` (useSudojoTechniqueByPath).
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * const { technique, notFound } = useTechniqueByPath({ networkClient, baseUrl, path: slug });
18
+ * ```
19
+ */
20
+ export function useTechniqueByPath(options) {
21
+ const { path, enabled = true } = options;
22
+ const { networkClient, baseUrl, token } = useResolvedSudojoApi(options, 'useTechniqueByPath');
23
+ const apiPath = toApiTechniquePath(path);
24
+ const canonicalPath = toCanonicalTechniquePath(path);
25
+ const { techniques, isLoading: listLoading, error, } = useTechniques({ networkClient, baseUrl, token, enabled });
26
+ const fromList = useMemo(() => findTechniqueByPath(techniques, path) ?? null, [techniques, path]);
27
+ const needFallback = enabled && !!apiPath && !listLoading && fromList === null;
28
+ const { data, isLoading: pathLoading } = useSudojoTechniqueByPath(networkClient, baseUrl, token, apiPath ?? '', { enabled: needFallback, retry: false });
29
+ const fromPath = useMemo(() => {
30
+ const technique = data?.success ? data.data : undefined;
31
+ return technique && isSameTechniquePath(technique.path, path)
32
+ ? technique
33
+ : null;
34
+ }, [data, path]);
35
+ const technique = fromList ?? fromPath;
36
+ const isLoading = enabled && !!path && (listLoading || (needFallback && pathLoading));
37
+ return {
38
+ technique,
39
+ techniques,
40
+ canonicalPath,
41
+ apiPath,
42
+ isLoading,
43
+ notFound: enabled && !!path && !isLoading && technique === null,
44
+ error,
45
+ };
46
+ }
47
+ //# sourceMappingURL=useTechniqueByPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTechniqueByPath.js","sourceRoot":"","sources":["../../src/hooks/useTechniqueByPath.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAgChD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAkC;IAElC,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACzC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,oBAAoB,CAC5D,OAAO,EACP,oBAAoB,CACrB,CAAC;IACF,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,aAAa,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAErD,MAAM,EACJ,UAAU,EACV,SAAS,EAAE,WAAW,EACtB,KAAK,GACN,GAAG,aAAa,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,EACnD,CAAC,UAAU,EAAE,IAAI,CAAC,CACnB,CAAC;IAEF,MAAM,YAAY,GAChB,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,QAAQ,KAAK,IAAI,CAAC;IAC5D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,wBAAwB,CAC/D,aAAa,EACb,OAAO,EACP,KAAK,EACL,OAAO,IAAI,EAAE,EACb,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,CACxC,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAqB,EAAE;QAC9C,MAAM,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACxD,OAAO,SAAS,IAAI,mBAAmB,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;YAC3D,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,IAAI,CAAC;IACX,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjB,MAAM,SAAS,GAAG,QAAQ,IAAI,QAAQ,CAAC;IACvC,MAAM,SAAS,GACb,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,IAAI,WAAW,CAAC,CAAC,CAAC;IAEtE,OAAO;QACL,SAAS;QACT,UAAU;QACV,aAAa;QACb,OAAO;QACP,SAAS;QACT,QAAQ,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI;QAC/D,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Hook for looking up a technique by its URL path, aliases included.\n */\n\nimport { useMemo } from 'react';\nimport type { Technique } from '@sudobility/sudojo_types';\nimport type { NetworkClient } from '@sudobility/types';\nimport { useSudojoTechniqueByPath } from '@sudobility/sudojo_client';\nimport { useResolvedSudojoApi } from '../context/SudojoApiContext';\nimport {\n findTechniqueByPath,\n isSameTechniquePath,\n toApiTechniquePath,\n toCanonicalTechniquePath,\n} from '../utils/technique';\nimport { useTechniques } from './useTechniques';\n\nexport interface UseTechniqueByPathOptions {\n /** Network client for API calls (default: SudojoApiProvider) */\n networkClient?: NetworkClient | undefined;\n /** Base URL for the Sudojo API (default: SudojoApiProvider) */\n baseUrl?: string | undefined;\n /** Access token (optional for this public endpoint) */\n token?: string | null | undefined;\n /** API path or public slug (e.g. '3d-medusa' or 'medusa-coloring') */\n path: string | null | undefined;\n /** Whether to enable the queries (default true) */\n enabled?: boolean;\n}\n\nexport interface UseTechniqueByPathResult {\n /** The technique, once found */\n technique: Technique | null;\n /** All techniques (from useTechniques; for dependencies and navigation) */\n techniques: Technique[];\n /** Public slug for the path ('3d-medusa' -> 'medusa-coloring') */\n canonicalPath: string | undefined;\n /** API path for the path ('medusa-coloring' -> '3d-medusa') */\n apiPath: string | undefined;\n /** Whether the lookup is still loading */\n isLoading: boolean;\n /** True once loading finished without finding the technique */\n notFound: boolean;\n /** Error from the technique list, if any */\n error: Error | null;\n}\n\n/**\n * Find a technique by path or alias. It is looked up in the cached technique\n * list (useTechniques, which the technique screens load anyway, as both apps\n * did); only when the list has loaded without it does it ask\n * `GET /techniques/path/:apiPath` (useSudojoTechniqueByPath).\n *\n * @example\n * ```tsx\n * const { technique, notFound } = useTechniqueByPath({ networkClient, baseUrl, path: slug });\n * ```\n */\nexport function useTechniqueByPath(\n options: UseTechniqueByPathOptions\n): UseTechniqueByPathResult {\n const { path, enabled = true } = options;\n const { networkClient, baseUrl, token } = useResolvedSudojoApi(\n options,\n 'useTechniqueByPath'\n );\n const apiPath = toApiTechniquePath(path);\n const canonicalPath = toCanonicalTechniquePath(path);\n\n const {\n techniques,\n isLoading: listLoading,\n error,\n } = useTechniques({ networkClient, baseUrl, token, enabled });\n\n const fromList = useMemo(\n () => findTechniqueByPath(techniques, path) ?? null,\n [techniques, path]\n );\n\n const needFallback =\n enabled && !!apiPath && !listLoading && fromList === null;\n const { data, isLoading: pathLoading } = useSudojoTechniqueByPath(\n networkClient,\n baseUrl,\n token,\n apiPath ?? '',\n { enabled: needFallback, retry: false }\n );\n\n const fromPath = useMemo((): Technique | null => {\n const technique = data?.success ? data.data : undefined;\n return technique && isSameTechniquePath(technique.path, path)\n ? technique\n : null;\n }, [data, path]);\n\n const technique = fromList ?? fromPath;\n const isLoading =\n enabled && !!path && (listLoading || (needFallback && pathLoading));\n\n return {\n technique,\n techniques,\n canonicalPath,\n apiPath,\n isLoading,\n notFound: enabled && !!path && !isLoading && technique === null,\n error,\n };\n}\n"]}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Hooks for a technique's worked example: fetch it (deterministic example
3
+ * or random practice) and build its step-by-step walkthrough.
4
+ */
5
+ import type { NetworkClient } from '@sudobility/types';
6
+ import { type TechniqueExampleSource, type TechniqueWalkthrough, type TechniqueWalkthroughTranslations } from '../utils/techniqueExample';
7
+ /**
8
+ * Build (and memoize) the walkthrough for a stored example.
9
+ * Pass stable translation functions (i18next `t`s are).
10
+ */
11
+ export declare function useTechniqueWalkthrough(source: TechniqueExampleSource | null | undefined, translations: TechniqueWalkthroughTranslations, techniquePath?: string): TechniqueWalkthrough;
12
+ /**
13
+ * Where the example comes from:
14
+ * - 'example': the first of `GET /examples?technique=` (deterministic, the
15
+ * same example every visit; web, and its build-time prerender)
16
+ * - 'practice': a random practice (`GET /practices/technique/:id/random`; RN)
17
+ */
18
+ export type TechniqueExampleSourceKind = 'example' | 'practice';
19
+ export interface UseTechniqueExampleOptions extends TechniqueWalkthroughTranslations {
20
+ /** Network client for API calls (default: SudojoApiProvider) */
21
+ networkClient?: NetworkClient | undefined;
22
+ /** Base URL for the Sudojo API (default: SudojoApiProvider) */
23
+ baseUrl?: string | undefined;
24
+ /** Access token (default: SudojoApiProvider) */
25
+ token?: string | null | undefined;
26
+ /** Technique number (1-60); idle below 1 */
27
+ techniqueId: number;
28
+ /** Technique path slug, for the technique's localized title */
29
+ techniquePath?: string | undefined;
30
+ /** Example source (default 'example') */
31
+ source?: TechniqueExampleSourceKind;
32
+ /** Whether to enable the query (default true) */
33
+ enabled?: boolean;
34
+ }
35
+ export interface UseTechniqueExampleResult extends TechniqueWalkthrough {
36
+ /** The stored example, once loaded */
37
+ example: TechniqueExampleSource | null;
38
+ /** 'loading' | 'ready' (has an example) | 'empty' (none for this technique) */
39
+ status: 'loading' | 'ready' | 'empty';
40
+ /** Whether the request is in flight */
41
+ isLoading: boolean;
42
+ /** Fetch again (with source 'practice': another random practice) */
43
+ refetch: () => void;
44
+ }
45
+ /**
46
+ * Fetch a technique's worked example and build its walkthrough cards.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * const { t: tHints } = useTranslation('hints');
51
+ * const { t: tTechniques } = useTranslation('techniques');
52
+ * const { t: tCommon } = useTranslation();
53
+ * const { status, steps, stepHeadings } = useTechniqueExample({
54
+ * techniqueId, techniquePath, tHints, tTechniques, tCommon,
55
+ * });
56
+ * steps.map((step, i) => <Card heading={stepHeadings[i]} board={step.board} hint={step.hint} text={step.text} />)
57
+ * ```
58
+ */
59
+ export declare function useTechniqueExample(options: UseTechniqueExampleOptions): UseTechniqueExampleResult;
60
+ //# sourceMappingURL=useTechniqueExample.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTechniqueExample.d.ts","sourceRoot":"","sources":["../../src/hooks/useTechniqueExample.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAMvD,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,EACtC,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,sBAAsB,GAAG,IAAI,GAAG,SAAS,EACjD,YAAY,EAAE,gCAAgC,EAC9C,aAAa,CAAC,EAAE,MAAM,GACrB,oBAAoB,CAWtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,SAAS,GAAG,UAAU,CAAC;AAEhE,MAAM,WAAW,0BAA2B,SAAQ,gCAAgC;IAClF,gEAAgE;IAChE,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,yCAAyC;IACzC,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,sCAAsC;IACtC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACvC,+EAA+E;IAC/E,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACtC,uCAAuC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,GAClC,yBAAyB,CA+D3B"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Hooks for a technique's worked example: fetch it (deterministic example
3
+ * or random practice) and build its step-by-step walkthrough.
4
+ */
5
+ import { useMemo } from 'react';
6
+ import { useSudojoExamples, useSudojoRandomPractice, } from '@sudobility/sudojo_client';
7
+ import { useResolvedSudojoApi } from '../context/SudojoApiContext';
8
+ import { buildTechniqueWalkthrough, } from '../utils/techniqueExample';
9
+ /**
10
+ * Build (and memoize) the walkthrough for a stored example.
11
+ * Pass stable translation functions (i18next `t`s are).
12
+ */
13
+ export function useTechniqueWalkthrough(source, translations, techniquePath) {
14
+ const { tHints, tTechniques, tCommon } = translations;
15
+ return useMemo(() => buildTechniqueWalkthrough(source, { tHints, tTechniques, tCommon }, techniquePath), [source, tHints, tTechniques, tCommon, techniquePath]);
16
+ }
17
+ /**
18
+ * Fetch a technique's worked example and build its walkthrough cards.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * const { t: tHints } = useTranslation('hints');
23
+ * const { t: tTechniques } = useTranslation('techniques');
24
+ * const { t: tCommon } = useTranslation();
25
+ * const { status, steps, stepHeadings } = useTechniqueExample({
26
+ * techniqueId, techniquePath, tHints, tTechniques, tCommon,
27
+ * });
28
+ * steps.map((step, i) => <Card heading={stepHeadings[i]} board={step.board} hint={step.hint} text={step.text} />)
29
+ * ```
30
+ */
31
+ export function useTechniqueExample(options) {
32
+ const { techniqueId, techniquePath, source = 'example', enabled = true, tHints, tTechniques, tCommon, } = options;
33
+ const { networkClient, baseUrl, token } = useResolvedSudojoApi(options, 'useTechniqueExample');
34
+ const active = enabled && techniqueId >= 1;
35
+ const examplesQuery = useSudojoExamples(networkClient, baseUrl, token, { technique: techniqueId }, {
36
+ enabled: active && source === 'example',
37
+ staleTime: Infinity,
38
+ refetchOnWindowFocus: false,
39
+ retry: false,
40
+ });
41
+ const practiceQuery = useSudojoRandomPractice(networkClient, baseUrl, token, techniqueId, { enabled: active && source === 'practice' });
42
+ const query = source === 'example' ? examplesQuery : practiceQuery;
43
+ const example = useMemo(() => {
44
+ if (source === 'example') {
45
+ // Deterministic: the first example of the stable, ordered list.
46
+ return examplesQuery.data?.data?.[0] ?? null;
47
+ }
48
+ return practiceQuery.data?.data ?? null;
49
+ }, [source, examplesQuery.data, practiceQuery.data]);
50
+ const walkthrough = useTechniqueWalkthrough(example, { tHints, tTechniques, tCommon }, techniquePath);
51
+ const isLoading = active && query.isLoading;
52
+ const refetch = query.refetch;
53
+ return {
54
+ ...walkthrough,
55
+ example,
56
+ status: isLoading ? 'loading' : example ? 'ready' : 'empty',
57
+ isLoading,
58
+ refetch: () => {
59
+ refetch();
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=useTechniqueExample.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTechniqueExample.js","sourceRoot":"","sources":["../../src/hooks/useTechniqueExample.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,yBAAyB,GAI1B,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAiD,EACjD,YAA8C,EAC9C,aAAsB;IAEtB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IACtD,OAAO,OAAO,CACZ,GAAG,EAAE,CACH,yBAAyB,CACvB,MAAM,EACN,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAChC,aAAa,CACd,EACH,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CACtD,CAAC;AACJ,CAAC;AAsCD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAmC;IAEnC,MAAM,EACJ,WAAW,EACX,aAAa,EACb,MAAM,GAAG,SAAS,EAClB,OAAO,GAAG,IAAI,EACd,MAAM,EACN,WAAW,EACX,OAAO,GACR,GAAG,OAAO,CAAC;IACZ,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,oBAAoB,CAC5D,OAAO,EACP,qBAAqB,CACtB,CAAC;IACF,MAAM,MAAM,GAAG,OAAO,IAAI,WAAW,IAAI,CAAC,CAAC;IAE3C,MAAM,aAAa,GAAG,iBAAiB,CACrC,aAAa,EACb,OAAO,EACP,KAAK,EACL,EAAE,SAAS,EAAE,WAAW,EAAE,EAC1B;QACE,OAAO,EAAE,MAAM,IAAI,MAAM,KAAK,SAAS;QACvC,SAAS,EAAE,QAAQ;QACnB,oBAAoB,EAAE,KAAK;QAC3B,KAAK,EAAE,KAAK;KACb,CACF,CAAC;IACF,MAAM,aAAa,GAAG,uBAAuB,CAC3C,aAAa,EACb,OAAO,EACP,KAAK,EACL,WAAW,EACX,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM,KAAK,UAAU,EAAE,CAC7C,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;IACnE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAkC,EAAE;QAC1D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,gEAAgE;YAChE,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC/C,CAAC;QACD,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC;IAC1C,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAErD,MAAM,WAAW,GAAG,uBAAuB,CACzC,OAAO,EACP,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAChC,aAAa,CACd,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAE9B,OAAO;QACL,GAAG,WAAW;QACd,OAAO;QACP,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QAC3D,SAAS;QACT,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Hooks for a technique's worked example: fetch it (deterministic example\n * or random practice) and build its step-by-step walkthrough.\n */\n\nimport { useMemo } from 'react';\nimport type { NetworkClient } from '@sudobility/types';\nimport {\n useSudojoExamples,\n useSudojoRandomPractice,\n} from '@sudobility/sudojo_client';\nimport { useResolvedSudojoApi } from '../context/SudojoApiContext';\nimport {\n buildTechniqueWalkthrough,\n type TechniqueExampleSource,\n type TechniqueWalkthrough,\n type TechniqueWalkthroughTranslations,\n} from '../utils/techniqueExample';\n\n/**\n * Build (and memoize) the walkthrough for a stored example.\n * Pass stable translation functions (i18next `t`s are).\n */\nexport function useTechniqueWalkthrough(\n source: TechniqueExampleSource | null | undefined,\n translations: TechniqueWalkthroughTranslations,\n techniquePath?: string\n): TechniqueWalkthrough {\n const { tHints, tTechniques, tCommon } = translations;\n return useMemo(\n () =>\n buildTechniqueWalkthrough(\n source,\n { tHints, tTechniques, tCommon },\n techniquePath\n ),\n [source, tHints, tTechniques, tCommon, techniquePath]\n );\n}\n\n/**\n * Where the example comes from:\n * - 'example': the first of `GET /examples?technique=` (deterministic, the\n * same example every visit; web, and its build-time prerender)\n * - 'practice': a random practice (`GET /practices/technique/:id/random`; RN)\n */\nexport type TechniqueExampleSourceKind = 'example' | 'practice';\n\nexport interface UseTechniqueExampleOptions extends TechniqueWalkthroughTranslations {\n /** Network client for API calls (default: SudojoApiProvider) */\n networkClient?: NetworkClient | undefined;\n /** Base URL for the Sudojo API (default: SudojoApiProvider) */\n baseUrl?: string | undefined;\n /** Access token (default: SudojoApiProvider) */\n token?: string | null | undefined;\n /** Technique number (1-60); idle below 1 */\n techniqueId: number;\n /** Technique path slug, for the technique's localized title */\n techniquePath?: string | undefined;\n /** Example source (default 'example') */\n source?: TechniqueExampleSourceKind;\n /** Whether to enable the query (default true) */\n enabled?: boolean;\n}\n\nexport interface UseTechniqueExampleResult extends TechniqueWalkthrough {\n /** The stored example, once loaded */\n example: TechniqueExampleSource | null;\n /** 'loading' | 'ready' (has an example) | 'empty' (none for this technique) */\n status: 'loading' | 'ready' | 'empty';\n /** Whether the request is in flight */\n isLoading: boolean;\n /** Fetch again (with source 'practice': another random practice) */\n refetch: () => void;\n}\n\n/**\n * Fetch a technique's worked example and build its walkthrough cards.\n *\n * @example\n * ```tsx\n * const { t: tHints } = useTranslation('hints');\n * const { t: tTechniques } = useTranslation('techniques');\n * const { t: tCommon } = useTranslation();\n * const { status, steps, stepHeadings } = useTechniqueExample({\n * techniqueId, techniquePath, tHints, tTechniques, tCommon,\n * });\n * steps.map((step, i) => <Card heading={stepHeadings[i]} board={step.board} hint={step.hint} text={step.text} />)\n * ```\n */\nexport function useTechniqueExample(\n options: UseTechniqueExampleOptions\n): UseTechniqueExampleResult {\n const {\n techniqueId,\n techniquePath,\n source = 'example',\n enabled = true,\n tHints,\n tTechniques,\n tCommon,\n } = options;\n const { networkClient, baseUrl, token } = useResolvedSudojoApi(\n options,\n 'useTechniqueExample'\n );\n const active = enabled && techniqueId >= 1;\n\n const examplesQuery = useSudojoExamples(\n networkClient,\n baseUrl,\n token,\n { technique: techniqueId },\n {\n enabled: active && source === 'example',\n staleTime: Infinity,\n refetchOnWindowFocus: false,\n retry: false,\n }\n );\n const practiceQuery = useSudojoRandomPractice(\n networkClient,\n baseUrl,\n token,\n techniqueId,\n { enabled: active && source === 'practice' }\n );\n\n const query = source === 'example' ? examplesQuery : practiceQuery;\n const example = useMemo((): TechniqueExampleSource | null => {\n if (source === 'example') {\n // Deterministic: the first example of the stable, ordered list.\n return examplesQuery.data?.data?.[0] ?? null;\n }\n return practiceQuery.data?.data ?? null;\n }, [source, examplesQuery.data, practiceQuery.data]);\n\n const walkthrough = useTechniqueWalkthrough(\n example,\n { tHints, tTechniques, tCommon },\n techniquePath\n );\n\n const isLoading = active && query.isLoading;\n const refetch = query.refetch;\n\n return {\n ...walkthrough,\n example,\n status: isLoading ? 'loading' : example ? 'ready' : 'empty',\n isLoading,\n refetch: () => {\n refetch();\n },\n };\n}\n"]}
@@ -4,10 +4,10 @@
4
4
  import type { Technique } from '@sudobility/sudojo_types';
5
5
  import type { NetworkClient } from '@sudobility/types';
6
6
  export interface UseTechniquesOptions {
7
- /** Network client for API calls */
8
- networkClient: NetworkClient;
9
- /** Base URL for the Sudojo API */
10
- baseUrl: string;
7
+ /** Network client for API calls (default: SudojoApiProvider) */
8
+ networkClient?: NetworkClient | undefined;
9
+ /** Base URL for the Sudojo API (default: SudojoApiProvider) */
10
+ baseUrl?: string | undefined;
11
11
  /** Access token for authentication (optional for public data) */
12
12
  token?: string;
13
13
  /** Optional level number (1-12) to filter techniques */
@@ -60,10 +60,10 @@ export interface UseTechniquesResult {
60
60
  */
61
61
  export declare function useTechniques(options: UseTechniquesOptions): UseTechniquesResult;
62
62
  export interface UseTechniqueOptions {
63
- /** Network client for API calls */
64
- networkClient: NetworkClient;
65
- /** Base URL for the Sudojo API */
66
- baseUrl: string;
63
+ /** Network client for API calls (default: SudojoApiProvider) */
64
+ networkClient?: NetworkClient | undefined;
65
+ /** Base URL for the Sudojo API (default: SudojoApiProvider) */
66
+ baseUrl?: string | undefined;
67
67
  /** Access token for authentication (optional for public data) */
68
68
  token?: string;
69
69
  /** Technique number to fetch */
@@ -1 +1 @@
1
- {"version":3,"file":"useTechniques.d.ts","sourceRoot":"","sources":["../../src/hooks/useTechniques.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAMvD,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,yBAAyB;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kCAAkC;IAClC,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IACnE,4CAA4C;IAC5C,gBAAgB,EAAE,SAAS,EAAE,CAAC;IAC9B,uCAAuC;IACvC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CA0DrB;AAED,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,wBAAwB;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAgC7E"}
1
+ {"version":3,"file":"useTechniques.d.ts","sourceRoot":"","sources":["../../src/hooks/useTechniques.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWvD,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,yBAAyB;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kCAAkC;IAClC,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IACnE,4CAA4C;IAC5C,gBAAgB,EAAE,SAAS,EAAE,CAAC;IAC9B,uCAAuC;IACvC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CAoDrB;AAED,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,wBAAwB;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CA8B7E"}
@@ -2,7 +2,9 @@
2
2
  * Hook for fetching and managing Sudoku solving techniques
3
3
  */
4
4
  import { useMemo } from 'react';
5
+ import { useResolvedSudojoApi } from '../context/SudojoApiContext';
5
6
  import { useSudojoTechnique, useSudojoTechniques, } from '@sudobility/sudojo_client';
7
+ import { groupTechniquesByLevel, sortTechniquesByLevel, } from '../utils/technique';
6
8
  /**
7
9
  * Hook for fetching and managing solving techniques
8
10
  *
@@ -31,7 +33,8 @@ import { useSudojoTechnique, useSudojoTechniques, } from '@sudobility/sudojo_cli
31
33
  * ```
32
34
  */
33
35
  export function useTechniques(options) {
34
- const { networkClient, baseUrl, token = '', level, enabled = true } = options;
36
+ const { level, enabled = true } = options;
37
+ const { networkClient, baseUrl, token } = useResolvedSudojoApi(options, 'useTechniques');
35
38
  const queryParams = useMemo(() => {
36
39
  if (level === undefined)
37
40
  return undefined;
@@ -43,29 +46,13 @@ export function useTechniques(options) {
43
46
  return [];
44
47
  return data.data;
45
48
  }, [data]);
46
- const sortedTechniques = useMemo(() => {
47
- return [...techniques].sort((a, b) => {
48
- // First sort by level, then by technique number
49
- if (a.level !== b.level) {
50
- return (a.level ?? 0) - (b.level ?? 0);
51
- }
52
- return a.technique - b.technique;
53
- });
54
- }, [techniques]);
49
+ // First sort by level, then by technique number
50
+ const sortedTechniques = useMemo(() => sortTechniquesByLevel(techniques), [techniques]);
55
51
  const getTechniqueByNumber = useMemo(() => {
56
52
  const techniqueMap = new Map(techniques.map(t => [t.technique, t]));
57
53
  return (technique) => techniqueMap.get(technique);
58
54
  }, [techniques]);
59
- const techniquesByLevel = useMemo(() => {
60
- const byLevel = new Map();
61
- for (const technique of sortedTechniques) {
62
- const key = technique.level ?? 0;
63
- const existing = byLevel.get(key) ?? [];
64
- existing.push(technique);
65
- byLevel.set(key, existing);
66
- }
67
- return byLevel;
68
- }, [sortedTechniques]);
55
+ const techniquesByLevel = useMemo(() => groupTechniquesByLevel(sortedTechniques), [sortedTechniques]);
69
56
  return {
70
57
  techniques,
71
58
  isLoading,
@@ -85,7 +72,8 @@ export function useTechniques(options) {
85
72
  * @returns Technique data
86
73
  */
87
74
  export function useTechnique(options) {
88
- const { networkClient, baseUrl, token = '', technique, enabled = true, } = options;
75
+ const { technique, enabled = true } = options;
76
+ const { networkClient, baseUrl, token } = useResolvedSudojoApi(options, 'useTechnique');
89
77
  const { data, isLoading, error, refetch } = useSudojoTechnique(networkClient, baseUrl, token, technique, {
90
78
  enabled: enabled && technique >= 1,
91
79
  });