@sudobility/sudojo_lib 0.0.104 → 0.0.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useHint.d.ts +13 -1
- package/dist/hooks/useHint.d.ts.map +1 -1
- package/dist/hooks/useHint.js +38 -5
- package/dist/hooks/useHint.js.map +1 -1
- package/dist/hooks/useLevelGame.d.ts +7 -1
- package/dist/hooks/useLevelGame.d.ts.map +1 -1
- package/dist/hooks/useLevelGame.js +9 -3
- package/dist/hooks/useLevelGame.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/hooks/useHint.d.ts
CHANGED
|
@@ -69,6 +69,16 @@ export interface UseHintOptions {
|
|
|
69
69
|
* Called before state is updated.
|
|
70
70
|
*/
|
|
71
71
|
onHintReceived?: (data: HintReceivedData) => void;
|
|
72
|
+
/**
|
|
73
|
+
* The user's active entitlement IDs (e.g., ['blue_belt'] or ['red_belt']).
|
|
74
|
+
* Used for client-side hint step gating.
|
|
75
|
+
*/
|
|
76
|
+
userEntitlements?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* The entitlement field from the current level (e.g., "blue_belt,red_belt").
|
|
79
|
+
* If null/empty, the level is free and all hint steps are visible.
|
|
80
|
+
*/
|
|
81
|
+
levelEntitlement?: string | null;
|
|
72
82
|
}
|
|
73
83
|
export interface UseHintResult {
|
|
74
84
|
/** Current hint step being displayed */
|
|
@@ -103,6 +113,8 @@ export interface UseHintResult {
|
|
|
103
113
|
canApply: boolean;
|
|
104
114
|
/** Whether the current hint matches the techniqueFilter (if one was set) */
|
|
105
115
|
isTargetTechnique: boolean;
|
|
116
|
+
/** Whether the hint has steps gated behind a paywall */
|
|
117
|
+
isHintGated: boolean;
|
|
106
118
|
}
|
|
107
119
|
/**
|
|
108
120
|
* Hook for getting hints from the solver API
|
|
@@ -143,5 +155,5 @@ export interface UseHintResult {
|
|
|
143
155
|
* };
|
|
144
156
|
* ```
|
|
145
157
|
*/
|
|
146
|
-
export declare function useHint({ networkClient, baseUrl, token, puzzle, userInput, pencilmarks, autoPencilmarks, techniqueFilter, onHintReceived, }: UseHintOptions): UseHintResult;
|
|
158
|
+
export declare function useHint({ networkClient, baseUrl, token, puzzle, userInput, pencilmarks, autoPencilmarks, techniqueFilter, onHintReceived, userEntitlements, levelEntitlement, }: UseHintOptions): UseHintResult;
|
|
147
159
|
//# sourceMappingURL=useHint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHint.d.ts","sourceRoot":"","sources":["../../src/hooks/useHint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAEV,mBAAmB,EACnB,eAAe,EAGf,cAAc,EACf,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"useHint.d.ts","sourceRoot":"","sources":["../../src/hooks/useHint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAEV,mBAAmB,EACnB,eAAe,EAGf,cAAc,EACf,MAAM,0BAA0B,CAAC;AASlC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAKvD,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,2CAA2C;IAC3C,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,6CAA6C;AAC7C,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,qBAAqB;IACrB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,sCAAsC;IACtC,SAAS,EAAE,aAAa,CAAC;IACzB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,mBAAmB,EAAE,eAAe,CAAC;IACrC,+BAA+B;IAC/B,SAAS,EAAE,mBAAmB,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,+DAA+D;IAC/D,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;IAC/B,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yEAAyE;IACzE,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,4CAA4C;IAC5C,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,sBAAsB;IACtB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,uEAAuE;IACvE,SAAS,EAAE,MAAM,aAAa,GAAG,IAAI,CAAC;IACtC,iDAAiD;IACjD,WAAW,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,iBAAiB,EAAE,OAAO,CAAC;IAC3B,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,OAAO,CAAC,EACtB,aAAa,EACb,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,WAAW,EACX,eAAuB,EACvB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,cAAc,GAAG,aAAa,CA8QhC"}
|
package/dist/hooks/useHint.js
CHANGED
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
* - previous() goes back to previous step
|
|
9
9
|
* - getHint() fetches new hints OR advances to next step if hints exist
|
|
10
10
|
*/
|
|
11
|
-
import { useCallback, useRef, useState } from 'react';
|
|
11
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
12
|
+
import { hasRequiredEntitlement, parseEntitlements, } from '@sudobility/sudojo_types';
|
|
12
13
|
import { createSudojoClient, HintAccessDeniedError, } from '@sudobility/sudojo_client';
|
|
14
|
+
/** Number of hint steps shown for free before paywall */
|
|
15
|
+
const FREE_HINT_STEP_LIMIT = 2;
|
|
13
16
|
/**
|
|
14
17
|
* Hook for getting hints from the solver API
|
|
15
18
|
*
|
|
@@ -49,7 +52,7 @@ import { createSudojoClient, HintAccessDeniedError, } from '@sudobility/sudojo_c
|
|
|
49
52
|
* };
|
|
50
53
|
* ```
|
|
51
54
|
*/
|
|
52
|
-
export function useHint({ networkClient, baseUrl, token, puzzle, userInput, pencilmarks, autoPencilmarks = false, techniqueFilter, onHintReceived, }) {
|
|
55
|
+
export function useHint({ networkClient, baseUrl, token, puzzle, userInput, pencilmarks, autoPencilmarks = false, techniqueFilter, onHintReceived, userEntitlements, levelEntitlement, }) {
|
|
53
56
|
const [hints, setHints] = useState(null);
|
|
54
57
|
const [stepIndex, setStepIndex] = useState(0);
|
|
55
58
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -60,14 +63,21 @@ export function useHint({ networkClient, baseUrl, token, puzzle, userInput, penc
|
|
|
60
63
|
const lastPuzzleStateRef = useRef('');
|
|
61
64
|
// Store board data from API response for applying hint
|
|
62
65
|
const boardDataRef = useRef(null);
|
|
66
|
+
// Store the hint level from the API response for entitlement checking
|
|
67
|
+
const hintLevelRef = useRef(0);
|
|
68
|
+
// Client-side entitlement check: does the user have access to this hint's level?
|
|
69
|
+
const hasAccess = useMemo(() => hasRequiredEntitlement(levelEntitlement, userEntitlements ?? []), [levelEntitlement, userEntitlements]);
|
|
63
70
|
// Compute current hint step
|
|
64
71
|
const hint = hints?.[stepIndex] ?? null;
|
|
65
72
|
const totalSteps = hints?.length ?? 0;
|
|
66
|
-
const
|
|
73
|
+
const isHintGated = !hasAccess && totalSteps > FREE_HINT_STEP_LIMIT;
|
|
74
|
+
const maxVisibleStep = hasAccess ? totalSteps - 1 : FREE_HINT_STEP_LIMIT - 1;
|
|
75
|
+
const hasNextStep = stepIndex < Math.min(totalSteps - 1, maxVisibleStep);
|
|
67
76
|
const hasPreviousStep = stepIndex > 0;
|
|
68
|
-
// Can apply when on last step and have board data
|
|
77
|
+
// Can apply when on last step (of all steps) and have board data and have access
|
|
69
78
|
const canApply = hints !== null &&
|
|
70
79
|
stepIndex === totalSteps - 1 &&
|
|
80
|
+
hasAccess &&
|
|
71
81
|
boardDataRef.current !== null;
|
|
72
82
|
// Helper to process a successful hint response
|
|
73
83
|
const processHintResponse = useCallback((response, isTarget) => {
|
|
@@ -96,12 +106,34 @@ export function useHint({ networkClient, baseUrl, token, puzzle, userInput, penc
|
|
|
96
106
|
setIsTargetTechnique(isTarget);
|
|
97
107
|
// Store board data for applying hint later
|
|
98
108
|
boardDataRef.current = board;
|
|
109
|
+
// Store hint level for entitlement checking
|
|
110
|
+
hintLevelRef.current = response.data.hints.level;
|
|
99
111
|
// Track the puzzle state we fetched for
|
|
100
112
|
lastPuzzleStateRef.current = `${puzzle}|${userInput}|${pencilmarks ?? ''}`;
|
|
113
|
+
// If user doesn't have access and there are more than FREE_HINT_STEP_LIMIT steps,
|
|
114
|
+
// set access error so UI can show paywall after the free steps
|
|
115
|
+
if (!hasAccess && hintSteps.length > FREE_HINT_STEP_LIMIT) {
|
|
116
|
+
const required = parseEntitlements(levelEntitlement);
|
|
117
|
+
setAccessError({
|
|
118
|
+
hintLevel: response.data.hints.level,
|
|
119
|
+
requiredEntitlement: required[0] ?? 'blue_belt',
|
|
120
|
+
userState: (userEntitlements?.length ?? 0) > 0
|
|
121
|
+
? 'insufficient_tier'
|
|
122
|
+
: 'no_subscription',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
101
125
|
return true;
|
|
102
126
|
}
|
|
103
127
|
return false;
|
|
104
|
-
}, [
|
|
128
|
+
}, [
|
|
129
|
+
onHintReceived,
|
|
130
|
+
puzzle,
|
|
131
|
+
userInput,
|
|
132
|
+
pencilmarks,
|
|
133
|
+
hasAccess,
|
|
134
|
+
levelEntitlement,
|
|
135
|
+
userEntitlements,
|
|
136
|
+
]);
|
|
105
137
|
// Fetch hints from API
|
|
106
138
|
const fetchHints = useCallback(async () => {
|
|
107
139
|
setIsLoading(true);
|
|
@@ -251,6 +283,7 @@ export function useHint({ networkClient, baseUrl, token, puzzle, userInput, penc
|
|
|
251
283
|
hasPreviousStep,
|
|
252
284
|
canApply,
|
|
253
285
|
isTargetTechnique,
|
|
286
|
+
isHintGated,
|
|
254
287
|
};
|
|
255
288
|
}
|
|
256
289
|
//# sourceMappingURL=useHint.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHint.js","sourceRoot":"","sources":["../../src/hooks/useHint.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for getting hints from the Sudoku solver\n *\n * Matches Kotlin HintInteractor behavior:\n * - Stores all hint steps from the API response\n * - Tracks current step index\n * - next() advances to next step (if available)\n * - previous() goes back to previous step\n * - getHint() fetches new hints OR advances to next step if hints exist\n */\n\nimport { useCallback, useRef, useState } from 'react';\nimport type {\n BaseResponse,\n HintAccessUserState,\n HintEntitlement,\n SolveData,\n SolverBoard,\n SolverHintStep,\n} from '@sudobility/sudojo_types';\nimport {\n createSudojoClient,\n HintAccessDeniedError,\n} from '@sudobility/sudojo_client';\nimport type { NetworkClient } from '@sudobility/types';\n\n/** Board data returned when applying a hint */\nexport interface HintBoardData {\n /** 81-character user input string */\n user: string;\n /** Pencilmarks string (comma-separated) */\n pencilmarks: string | null;\n /** Whether auto-pencilmarks are enabled */\n autoPencilmarks: boolean;\n}\n\n/** Data passed to onHintReceived callback */\nexport interface HintReceivedData {\n /** The first hint step */\n hint: SolverHintStep;\n /** All hint steps */\n hints: SolverHintStep[];\n /** Board data that will be applied */\n boardData: HintBoardData;\n /** Difficulty level for this hint (from SolverHints.level) */\n hintLevel: number;\n /** Technique ID for this hint (from SolverHints.technique) */\n hintTechnique: number;\n}\n\n/** Access denied error info when hint level exceeds subscription tier */\nexport interface HintAccessError {\n /** The difficulty level of the requested hint */\n hintLevel: number;\n /** The entitlement required to access this hint level */\n requiredEntitlement: HintEntitlement;\n /** The user's current state */\n userState: HintAccessUserState;\n}\n\nexport interface UseHintOptions {\n /** Network client for API calls */\n networkClient: NetworkClient;\n /** Base URL for the Sudojo API */\n baseUrl: string;\n /** Access token for authentication */\n token: string;\n /** Original puzzle string (81 chars) */\n puzzle: string;\n /** Current user input string (81 chars) */\n userInput: string;\n /** Current pencilmarks (comma-separated or empty) */\n pencilmarks?: string;\n /** Whether auto-pencilmarks were generated */\n autoPencilmarks?: boolean;\n /**\n * Optional technique number to filter for.\n * When set, will first try to find hints for this specific technique.\n * If no hints found for the target technique, will retry without filter\n * to get the next available hint (allowing puzzle progression).\n */\n techniqueFilter?: number;\n /**\n * Callback fired when hints are received from the API.\n * Use this to intercept hints for logging, saving examples, etc.\n * Called before state is updated.\n */\n onHintReceived?: (data: HintReceivedData) => void;\n}\n\nexport interface UseHintResult {\n /** Current hint step being displayed */\n hint: SolverHintStep | null;\n /** All hint steps (for showing progress like \"Step 1 of 3\") */\n hints: SolverHintStep[] | null;\n /** Current step index (0-based) */\n stepIndex: number;\n /** Total number of steps */\n totalSteps: number;\n /** Whether a hint request is in progress */\n isLoading: boolean;\n /** Error message if hint request failed */\n error: string | null;\n /** Access denied error info when hint level exceeds subscription tier */\n accessError: HintAccessError | null;\n /** Request hints or advance to next step */\n getHint: () => Promise<void>;\n /** Go to next hint step */\n nextStep: () => void;\n /** Go to previous hint step */\n previousStep: () => void;\n /** Clear all hints */\n clearHint: () => void;\n /** Apply the hint to the board - returns board data and clears hint */\n applyHint: () => HintBoardData | null;\n /** Whether there are more steps after current */\n hasNextStep: boolean;\n /** Whether there are steps before current */\n hasPreviousStep: boolean;\n /** Whether the hint can be applied (on last step) */\n canApply: boolean;\n /** Whether the current hint matches the techniqueFilter (if one was set) */\n isTargetTechnique: boolean;\n}\n\n/**\n * Hook for getting hints from the solver API\n *\n * Matches Kotlin HintInteractor behavior:\n * - First call to getHint() fetches hints from API\n * - Subsequent calls advance to next step (if available)\n * - Use nextStep()/previousStep() to navigate manually\n * - clearHint() resets everything\n *\n * @param options - Puzzle state for hint generation\n * @returns Hint state and controls\n *\n * @example\n * ```tsx\n * const { hint, isLoading, getHint, nextStep, clearHint, applyHint } = useHint({\n * networkClient,\n * baseUrl: 'https://api.sudojo.com',\n * token: 'user-access-token',\n * puzzle: originalPuzzle,\n * userInput: currentInput,\n * pencilmarks: currentPencilmarks,\n * });\n *\n * // Get hint button\n * <Button onClick={getHint} disabled={isLoading}>Get Hint</Button>\n *\n * // Display hint\n * {hint && <HintDisplay step={hint} />}\n *\n * // Apply hint to board\n * const handleApply = () => {\n * const boardData = applyHint();\n * if (boardData) {\n * setUserInput(boardData.user);\n * setPencilmarks(boardData.pencilmarks);\n * }\n * };\n * ```\n */\nexport function useHint({\n networkClient,\n baseUrl,\n token,\n puzzle,\n userInput,\n pencilmarks,\n autoPencilmarks = false,\n techniqueFilter,\n onHintReceived,\n}: UseHintOptions): UseHintResult {\n const [hints, setHints] = useState<SolverHintStep[] | null>(null);\n const [stepIndex, setStepIndex] = useState(0);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [accessError, setAccessError] = useState<HintAccessError | null>(null);\n const [isTargetTechnique, setIsTargetTechnique] = useState(false);\n\n // Track puzzle state to detect when we need to re-fetch\n const lastPuzzleStateRef = useRef<string>('');\n\n // Store board data from API response for applying hint\n const boardDataRef = useRef<SolverBoard | null>(null);\n\n // Compute current hint step\n const hint = hints?.[stepIndex] ?? null;\n const totalSteps = hints?.length ?? 0;\n const hasNextStep = stepIndex < totalSteps - 1;\n const hasPreviousStep = stepIndex > 0;\n // Can apply when on last step and have board data\n const canApply =\n hints !== null &&\n stepIndex === totalSteps - 1 &&\n boardDataRef.current !== null;\n\n // Helper to process a successful hint response\n const processHintResponse = useCallback(\n (response: BaseResponse<SolveData>, isTarget: boolean): boolean => {\n if (response.success && response.data?.hints?.steps?.length) {\n const hintSteps = response.data.hints.steps;\n const board = response.data.board ?? null;\n\n // Call onHintReceived callback if provided (for interception/logging)\n if (\n onHintReceived &&\n hintSteps[0] &&\n board?.user !== null &&\n board?.user !== undefined\n ) {\n onHintReceived({\n hint: hintSteps[0],\n hints: hintSteps,\n boardData: {\n user: board.user,\n pencilmarks: board.pencilmark?.numbers ?? null,\n autoPencilmarks: board.pencilmark?.autopencil ?? false,\n },\n hintLevel: response.data.hints.level,\n hintTechnique: response.data.hints.technique,\n });\n }\n\n setHints(hintSteps);\n setStepIndex(0);\n setIsTargetTechnique(isTarget);\n // Store board data for applying hint later\n boardDataRef.current = board;\n // Track the puzzle state we fetched for\n lastPuzzleStateRef.current = `${puzzle}|${userInput}|${pencilmarks ?? ''}`;\n return true;\n }\n return false;\n },\n [onHintReceived, puzzle, userInput, pencilmarks]\n );\n\n // Fetch hints from API\n const fetchHints = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n setAccessError(null);\n setIsTargetTechnique(false);\n\n try {\n const client = createSudojoClient(networkClient, baseUrl);\n\n // Phase 1: If techniqueFilter is set, first try to find that specific technique\n if (techniqueFilter !== undefined) {\n const filteredOptions = {\n original: puzzle,\n user: userInput,\n autoPencilmarks,\n ...(pencilmarks !== undefined && { pencilmarks }),\n techniques: techniqueFilter.toString(),\n };\n\n const filteredResponse = await client.solverSolve(\n token,\n filteredOptions\n );\n\n // If we found hints for the target technique, use them\n if (processHintResponse(filteredResponse, true)) {\n setIsLoading(false);\n return;\n }\n // No hints for target technique, fall through to Phase 2\n }\n\n // Phase 2: Regular (unfiltered) call to get next available hint\n const solveOptions = {\n original: puzzle,\n user: userInput,\n autoPencilmarks,\n ...(pencilmarks !== undefined && { pencilmarks }),\n };\n const response: BaseResponse<SolveData> = await client.solverSolve(\n token,\n solveOptions\n );\n\n if (processHintResponse(response, false)) {\n // Successfully got hints (not the target technique)\n } else if (response.error) {\n setError(response.error);\n setHints(null);\n boardDataRef.current = null;\n } else {\n setError('No hints available');\n setHints(null);\n boardDataRef.current = null;\n }\n } catch (err) {\n // Handle hint access denied error (402)\n if (HintAccessDeniedError.isHintAccessDeniedError(err)) {\n setAccessError({\n hintLevel: err.hintLevel,\n requiredEntitlement: err.requiredEntitlement,\n userState: err.userState,\n });\n setError(null);\n } else {\n setError(err instanceof Error ? err.message : 'Failed to get hint');\n }\n setHints(null);\n boardDataRef.current = null;\n } finally {\n setIsLoading(false);\n }\n }, [\n networkClient,\n baseUrl,\n token,\n puzzle,\n userInput,\n pencilmarks,\n autoPencilmarks,\n techniqueFilter,\n processHintResponse,\n ]);\n\n // Get hint: fetch if no hints or puzzle changed, otherwise advance\n const getHint = useCallback(async () => {\n const currentPuzzleState = `${puzzle}|${userInput}|${pencilmarks ?? ''}`;\n\n if (hints === null || lastPuzzleStateRef.current !== currentPuzzleState) {\n // No hints or puzzle state changed - fetch new hints\n await fetchHints();\n } else if (hasNextStep) {\n // Have hints and more steps - advance to next\n setStepIndex(prev => prev + 1);\n }\n // If at last step and hints exist, do nothing (stay on last step)\n }, [hints, hasNextStep, fetchHints, puzzle, userInput, pencilmarks]);\n\n // Navigate to next step\n const nextStep = useCallback(() => {\n if (hasNextStep) {\n setStepIndex(prev => prev + 1);\n }\n }, [hasNextStep]);\n\n // Navigate to previous step\n const previousStep = useCallback(() => {\n if (hasPreviousStep) {\n setStepIndex(prev => prev - 1);\n }\n }, [hasPreviousStep]);\n\n // Clear all hints\n const clearHint = useCallback(() => {\n setHints(null);\n setStepIndex(0);\n setError(null);\n setAccessError(null);\n setIsTargetTechnique(false);\n lastPuzzleStateRef.current = '';\n boardDataRef.current = null;\n }, []);\n\n // Apply the hint to the board - returns board data and clears hint\n const applyHint = useCallback((): HintBoardData | null => {\n const board = boardDataRef.current;\n // Check for null/undefined board or user, but allow empty string user\n if (!board || board.user === null || board.user === undefined) {\n return null;\n }\n\n const result: HintBoardData = {\n user: board.user,\n pencilmarks: board.pencilmark?.numbers ?? null,\n autoPencilmarks: board.pencilmark?.autopencil ?? false,\n };\n\n // Clear hints after applying (matches Kotlin: result = null)\n setHints(null);\n setStepIndex(0);\n setError(null);\n lastPuzzleStateRef.current = '';\n boardDataRef.current = null;\n\n return result;\n }, []);\n\n return {\n hint,\n hints,\n stepIndex,\n totalSteps,\n isLoading,\n error,\n accessError,\n getHint,\n nextStep,\n previousStep,\n clearHint,\n applyHint,\n hasNextStep,\n hasPreviousStep,\n canApply,\n isTargetTechnique,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useHint.js","sourceRoot":"","sources":["../../src/hooks/useHint.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for getting hints from the Sudoku solver\n *\n * Matches Kotlin HintInteractor behavior:\n * - Stores all hint steps from the API response\n * - Tracks current step index\n * - next() advances to next step (if available)\n * - previous() goes back to previous step\n * - getHint() fetches new hints OR advances to next step if hints exist\n */\n\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport type {\n BaseResponse,\n HintAccessUserState,\n HintEntitlement,\n SolveData,\n SolverBoard,\n SolverHintStep,\n} from '@sudobility/sudojo_types';\nimport {\n hasRequiredEntitlement,\n parseEntitlements,\n} from '@sudobility/sudojo_types';\nimport {\n createSudojoClient,\n HintAccessDeniedError,\n} from '@sudobility/sudojo_client';\nimport type { NetworkClient } from '@sudobility/types';\n\n/** Number of hint steps shown for free before paywall */\nconst FREE_HINT_STEP_LIMIT = 2;\n\n/** Board data returned when applying a hint */\nexport interface HintBoardData {\n /** 81-character user input string */\n user: string;\n /** Pencilmarks string (comma-separated) */\n pencilmarks: string | null;\n /** Whether auto-pencilmarks are enabled */\n autoPencilmarks: boolean;\n}\n\n/** Data passed to onHintReceived callback */\nexport interface HintReceivedData {\n /** The first hint step */\n hint: SolverHintStep;\n /** All hint steps */\n hints: SolverHintStep[];\n /** Board data that will be applied */\n boardData: HintBoardData;\n /** Difficulty level for this hint (from SolverHints.level) */\n hintLevel: number;\n /** Technique ID for this hint (from SolverHints.technique) */\n hintTechnique: number;\n}\n\n/** Access denied error info when hint level exceeds subscription tier */\nexport interface HintAccessError {\n /** The difficulty level of the requested hint */\n hintLevel: number;\n /** The entitlement required to access this hint level */\n requiredEntitlement: HintEntitlement;\n /** The user's current state */\n userState: HintAccessUserState;\n}\n\nexport interface UseHintOptions {\n /** Network client for API calls */\n networkClient: NetworkClient;\n /** Base URL for the Sudojo API */\n baseUrl: string;\n /** Access token for authentication */\n token: string;\n /** Original puzzle string (81 chars) */\n puzzle: string;\n /** Current user input string (81 chars) */\n userInput: string;\n /** Current pencilmarks (comma-separated or empty) */\n pencilmarks?: string;\n /** Whether auto-pencilmarks were generated */\n autoPencilmarks?: boolean;\n /**\n * Optional technique number to filter for.\n * When set, will first try to find hints for this specific technique.\n * If no hints found for the target technique, will retry without filter\n * to get the next available hint (allowing puzzle progression).\n */\n techniqueFilter?: number;\n /**\n * Callback fired when hints are received from the API.\n * Use this to intercept hints for logging, saving examples, etc.\n * Called before state is updated.\n */\n onHintReceived?: (data: HintReceivedData) => void;\n /**\n * The user's active entitlement IDs (e.g., ['blue_belt'] or ['red_belt']).\n * Used for client-side hint step gating.\n */\n userEntitlements?: string[];\n /**\n * The entitlement field from the current level (e.g., \"blue_belt,red_belt\").\n * If null/empty, the level is free and all hint steps are visible.\n */\n levelEntitlement?: string | null;\n}\n\nexport interface UseHintResult {\n /** Current hint step being displayed */\n hint: SolverHintStep | null;\n /** All hint steps (for showing progress like \"Step 1 of 3\") */\n hints: SolverHintStep[] | null;\n /** Current step index (0-based) */\n stepIndex: number;\n /** Total number of steps */\n totalSteps: number;\n /** Whether a hint request is in progress */\n isLoading: boolean;\n /** Error message if hint request failed */\n error: string | null;\n /** Access denied error info when hint level exceeds subscription tier */\n accessError: HintAccessError | null;\n /** Request hints or advance to next step */\n getHint: () => Promise<void>;\n /** Go to next hint step */\n nextStep: () => void;\n /** Go to previous hint step */\n previousStep: () => void;\n /** Clear all hints */\n clearHint: () => void;\n /** Apply the hint to the board - returns board data and clears hint */\n applyHint: () => HintBoardData | null;\n /** Whether there are more steps after current */\n hasNextStep: boolean;\n /** Whether there are steps before current */\n hasPreviousStep: boolean;\n /** Whether the hint can be applied (on last step) */\n canApply: boolean;\n /** Whether the current hint matches the techniqueFilter (if one was set) */\n isTargetTechnique: boolean;\n /** Whether the hint has steps gated behind a paywall */\n isHintGated: boolean;\n}\n\n/**\n * Hook for getting hints from the solver API\n *\n * Matches Kotlin HintInteractor behavior:\n * - First call to getHint() fetches hints from API\n * - Subsequent calls advance to next step (if available)\n * - Use nextStep()/previousStep() to navigate manually\n * - clearHint() resets everything\n *\n * @param options - Puzzle state for hint generation\n * @returns Hint state and controls\n *\n * @example\n * ```tsx\n * const { hint, isLoading, getHint, nextStep, clearHint, applyHint } = useHint({\n * networkClient,\n * baseUrl: 'https://api.sudojo.com',\n * token: 'user-access-token',\n * puzzle: originalPuzzle,\n * userInput: currentInput,\n * pencilmarks: currentPencilmarks,\n * });\n *\n * // Get hint button\n * <Button onClick={getHint} disabled={isLoading}>Get Hint</Button>\n *\n * // Display hint\n * {hint && <HintDisplay step={hint} />}\n *\n * // Apply hint to board\n * const handleApply = () => {\n * const boardData = applyHint();\n * if (boardData) {\n * setUserInput(boardData.user);\n * setPencilmarks(boardData.pencilmarks);\n * }\n * };\n * ```\n */\nexport function useHint({\n networkClient,\n baseUrl,\n token,\n puzzle,\n userInput,\n pencilmarks,\n autoPencilmarks = false,\n techniqueFilter,\n onHintReceived,\n userEntitlements,\n levelEntitlement,\n}: UseHintOptions): UseHintResult {\n const [hints, setHints] = useState<SolverHintStep[] | null>(null);\n const [stepIndex, setStepIndex] = useState(0);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [accessError, setAccessError] = useState<HintAccessError | null>(null);\n const [isTargetTechnique, setIsTargetTechnique] = useState(false);\n\n // Track puzzle state to detect when we need to re-fetch\n const lastPuzzleStateRef = useRef<string>('');\n\n // Store board data from API response for applying hint\n const boardDataRef = useRef<SolverBoard | null>(null);\n\n // Store the hint level from the API response for entitlement checking\n const hintLevelRef = useRef<number>(0);\n\n // Client-side entitlement check: does the user have access to this hint's level?\n const hasAccess = useMemo(\n () => hasRequiredEntitlement(levelEntitlement, userEntitlements ?? []),\n [levelEntitlement, userEntitlements]\n );\n\n // Compute current hint step\n const hint = hints?.[stepIndex] ?? null;\n const totalSteps = hints?.length ?? 0;\n const isHintGated = !hasAccess && totalSteps > FREE_HINT_STEP_LIMIT;\n const maxVisibleStep = hasAccess ? totalSteps - 1 : FREE_HINT_STEP_LIMIT - 1;\n const hasNextStep = stepIndex < Math.min(totalSteps - 1, maxVisibleStep);\n const hasPreviousStep = stepIndex > 0;\n // Can apply when on last step (of all steps) and have board data and have access\n const canApply =\n hints !== null &&\n stepIndex === totalSteps - 1 &&\n hasAccess &&\n boardDataRef.current !== null;\n\n // Helper to process a successful hint response\n const processHintResponse = useCallback(\n (response: BaseResponse<SolveData>, isTarget: boolean): boolean => {\n if (response.success && response.data?.hints?.steps?.length) {\n const hintSteps = response.data.hints.steps;\n const board = response.data.board ?? null;\n\n // Call onHintReceived callback if provided (for interception/logging)\n if (\n onHintReceived &&\n hintSteps[0] &&\n board?.user !== null &&\n board?.user !== undefined\n ) {\n onHintReceived({\n hint: hintSteps[0],\n hints: hintSteps,\n boardData: {\n user: board.user,\n pencilmarks: board.pencilmark?.numbers ?? null,\n autoPencilmarks: board.pencilmark?.autopencil ?? false,\n },\n hintLevel: response.data.hints.level,\n hintTechnique: response.data.hints.technique,\n });\n }\n\n setHints(hintSteps);\n setStepIndex(0);\n setIsTargetTechnique(isTarget);\n // Store board data for applying hint later\n boardDataRef.current = board;\n // Store hint level for entitlement checking\n hintLevelRef.current = response.data.hints.level;\n // Track the puzzle state we fetched for\n lastPuzzleStateRef.current = `${puzzle}|${userInput}|${pencilmarks ?? ''}`;\n\n // If user doesn't have access and there are more than FREE_HINT_STEP_LIMIT steps,\n // set access error so UI can show paywall after the free steps\n if (!hasAccess && hintSteps.length > FREE_HINT_STEP_LIMIT) {\n const required = parseEntitlements(levelEntitlement);\n setAccessError({\n hintLevel: response.data.hints.level,\n requiredEntitlement: required[0] ?? 'blue_belt',\n userState:\n (userEntitlements?.length ?? 0) > 0\n ? 'insufficient_tier'\n : 'no_subscription',\n });\n }\n\n return true;\n }\n return false;\n },\n [\n onHintReceived,\n puzzle,\n userInput,\n pencilmarks,\n hasAccess,\n levelEntitlement,\n userEntitlements,\n ]\n );\n\n // Fetch hints from API\n const fetchHints = useCallback(async () => {\n setIsLoading(true);\n setError(null);\n setAccessError(null);\n setIsTargetTechnique(false);\n\n try {\n const client = createSudojoClient(networkClient, baseUrl);\n\n // Phase 1: If techniqueFilter is set, first try to find that specific technique\n if (techniqueFilter !== undefined) {\n const filteredOptions = {\n original: puzzle,\n user: userInput,\n autoPencilmarks,\n ...(pencilmarks !== undefined && { pencilmarks }),\n techniques: techniqueFilter.toString(),\n };\n\n const filteredResponse = await client.solverSolve(\n token,\n filteredOptions\n );\n\n // If we found hints for the target technique, use them\n if (processHintResponse(filteredResponse, true)) {\n setIsLoading(false);\n return;\n }\n // No hints for target technique, fall through to Phase 2\n }\n\n // Phase 2: Regular (unfiltered) call to get next available hint\n const solveOptions = {\n original: puzzle,\n user: userInput,\n autoPencilmarks,\n ...(pencilmarks !== undefined && { pencilmarks }),\n };\n const response: BaseResponse<SolveData> = await client.solverSolve(\n token,\n solveOptions\n );\n\n if (processHintResponse(response, false)) {\n // Successfully got hints (not the target technique)\n } else if (response.error) {\n setError(response.error);\n setHints(null);\n boardDataRef.current = null;\n } else {\n setError('No hints available');\n setHints(null);\n boardDataRef.current = null;\n }\n } catch (err) {\n // Handle hint access denied error (402)\n if (HintAccessDeniedError.isHintAccessDeniedError(err)) {\n setAccessError({\n hintLevel: err.hintLevel,\n requiredEntitlement: err.requiredEntitlement,\n userState: err.userState,\n });\n setError(null);\n } else {\n setError(err instanceof Error ? err.message : 'Failed to get hint');\n }\n setHints(null);\n boardDataRef.current = null;\n } finally {\n setIsLoading(false);\n }\n }, [\n networkClient,\n baseUrl,\n token,\n puzzle,\n userInput,\n pencilmarks,\n autoPencilmarks,\n techniqueFilter,\n processHintResponse,\n ]);\n\n // Get hint: fetch if no hints or puzzle changed, otherwise advance\n const getHint = useCallback(async () => {\n const currentPuzzleState = `${puzzle}|${userInput}|${pencilmarks ?? ''}`;\n\n if (hints === null || lastPuzzleStateRef.current !== currentPuzzleState) {\n // No hints or puzzle state changed - fetch new hints\n await fetchHints();\n } else if (hasNextStep) {\n // Have hints and more steps - advance to next\n setStepIndex(prev => prev + 1);\n }\n // If at last step and hints exist, do nothing (stay on last step)\n }, [hints, hasNextStep, fetchHints, puzzle, userInput, pencilmarks]);\n\n // Navigate to next step\n const nextStep = useCallback(() => {\n if (hasNextStep) {\n setStepIndex(prev => prev + 1);\n }\n }, [hasNextStep]);\n\n // Navigate to previous step\n const previousStep = useCallback(() => {\n if (hasPreviousStep) {\n setStepIndex(prev => prev - 1);\n }\n }, [hasPreviousStep]);\n\n // Clear all hints\n const clearHint = useCallback(() => {\n setHints(null);\n setStepIndex(0);\n setError(null);\n setAccessError(null);\n setIsTargetTechnique(false);\n lastPuzzleStateRef.current = '';\n boardDataRef.current = null;\n }, []);\n\n // Apply the hint to the board - returns board data and clears hint\n const applyHint = useCallback((): HintBoardData | null => {\n const board = boardDataRef.current;\n // Check for null/undefined board or user, but allow empty string user\n if (!board || board.user === null || board.user === undefined) {\n return null;\n }\n\n const result: HintBoardData = {\n user: board.user,\n pencilmarks: board.pencilmark?.numbers ?? null,\n autoPencilmarks: board.pencilmark?.autopencil ?? false,\n };\n\n // Clear hints after applying (matches Kotlin: result = null)\n setHints(null);\n setStepIndex(0);\n setError(null);\n lastPuzzleStateRef.current = '';\n boardDataRef.current = null;\n\n return result;\n }, []);\n\n return {\n hint,\n hints,\n stepIndex,\n totalSteps,\n isLoading,\n error,\n accessError,\n getHint,\n nextStep,\n previousStep,\n clearHint,\n applyHint,\n hasNextStep,\n hasPreviousStep,\n canApply,\n isTargetTechnique,\n isHintGated,\n };\n}\n"]}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import type { Board } from '@sudobility/sudojo_types';
|
|
6
6
|
import type { NetworkClient } from '@sudobility/types';
|
|
7
7
|
/** Game fetch status indicating what screen to show */
|
|
8
|
-
export type GameFetchStatus = 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'error';
|
|
8
|
+
export type GameFetchStatus = 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'entitlement_required' | 'error';
|
|
9
9
|
export interface UseLevelGameOptions {
|
|
10
10
|
/** Network client for API calls */
|
|
11
11
|
networkClient: NetworkClient;
|
|
@@ -19,6 +19,10 @@ export interface UseLevelGameOptions {
|
|
|
19
19
|
symmetrical?: boolean;
|
|
20
20
|
/** Whether subscription is currently active */
|
|
21
21
|
subscriptionActive?: boolean;
|
|
22
|
+
/** The user's active entitlement IDs (e.g., ['blue_belt'] or ['red_belt']) */
|
|
23
|
+
userEntitlements?: string[];
|
|
24
|
+
/** The entitlement field from the current level (e.g., "blue_belt,red_belt") */
|
|
25
|
+
levelEntitlement?: string | null;
|
|
22
26
|
/** Whether to enable the query */
|
|
23
27
|
enabled?: boolean;
|
|
24
28
|
}
|
|
@@ -35,6 +39,8 @@ export interface UseLevelGameResult {
|
|
|
35
39
|
refetch: () => void;
|
|
36
40
|
/** Fetch a new random board for this level */
|
|
37
41
|
nextPuzzle: () => void;
|
|
42
|
+
/** The entitlement string required for this level (for paywall display) */
|
|
43
|
+
requiredEntitlement: string | null;
|
|
38
44
|
}
|
|
39
45
|
/**
|
|
40
46
|
* Hook for fetching a game board for a specific level
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLevelGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"useLevelGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,uDAAuD;AACvD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,SAAS,GACT,eAAe,GACf,uBAAuB,GACvB,sBAAsB,GACtB,OAAO,CAAC;AAuDZ,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,2EAA2E;IAC3E,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAgF7E"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Handles auth and subscription status with automatic refresh
|
|
4
4
|
*/
|
|
5
5
|
import { useMemo } from 'react';
|
|
6
|
+
import { hasRequiredEntitlement } from '@sudobility/sudojo_types';
|
|
6
7
|
import { useSudojoRandomBoard } from '@sudobility/sudojo_client';
|
|
7
8
|
import { useQueryClient } from '@tanstack/react-query';
|
|
8
9
|
/** Check if response indicates auth is required */
|
|
@@ -63,7 +64,9 @@ function isSubscriptionRequired(response, error) {
|
|
|
63
64
|
* ```
|
|
64
65
|
*/
|
|
65
66
|
export function useLevelGame(options) {
|
|
66
|
-
const { networkClient, baseUrl, token, level, symmetrical, enabled = true, } = options;
|
|
67
|
+
const { networkClient, baseUrl, token, level, symmetrical, userEntitlements, levelEntitlement, enabled = true, } = options;
|
|
68
|
+
// Client-side entitlement check before making API call
|
|
69
|
+
const entitlementDenied = useMemo(() => !hasRequiredEntitlement(levelEntitlement, userEntitlements ?? []), [levelEntitlement, userEntitlements]);
|
|
67
70
|
const queryClient = useQueryClient();
|
|
68
71
|
const queryParams = useMemo(() => ({
|
|
69
72
|
level,
|
|
@@ -73,11 +76,13 @@ export function useLevelGame(options) {
|
|
|
73
76
|
techniques: undefined,
|
|
74
77
|
technique_bit: undefined,
|
|
75
78
|
}), [level, symmetrical]);
|
|
76
|
-
const { data, isLoading, error, refetch } = useSudojoRandomBoard(networkClient, baseUrl, token, queryParams, { enabled: enabled && level >= 1 && level <= 12 });
|
|
79
|
+
const { data, isLoading, error, refetch } = useSudojoRandomBoard(networkClient, baseUrl, token, queryParams, { enabled: enabled && level >= 1 && level <= 12 && !entitlementDenied });
|
|
77
80
|
// Determine status based on response
|
|
78
81
|
// Cast to SudojoApiResponse to check for action field
|
|
79
82
|
const apiResponse = data;
|
|
80
83
|
const status = useMemo(() => {
|
|
84
|
+
if (entitlementDenied)
|
|
85
|
+
return 'entitlement_required';
|
|
81
86
|
if (isLoading)
|
|
82
87
|
return 'loading';
|
|
83
88
|
if (isAuthRequired(apiResponse, error))
|
|
@@ -89,7 +94,7 @@ export function useLevelGame(options) {
|
|
|
89
94
|
if (apiResponse?.success && apiResponse.data)
|
|
90
95
|
return 'success';
|
|
91
96
|
return 'loading';
|
|
92
|
-
}, [isLoading, apiResponse, error]);
|
|
97
|
+
}, [entitlementDenied, isLoading, apiResponse, error]);
|
|
93
98
|
const board = useMemo(() => {
|
|
94
99
|
if (data?.success && data.data) {
|
|
95
100
|
return data.data;
|
|
@@ -111,6 +116,7 @@ export function useLevelGame(options) {
|
|
|
111
116
|
error: error ?? null,
|
|
112
117
|
refetch: () => refetch(),
|
|
113
118
|
nextPuzzle,
|
|
119
|
+
requiredEntitlement: levelEntitlement ?? null,
|
|
114
120
|
};
|
|
115
121
|
}
|
|
116
122
|
//# sourceMappingURL=useLevelGame.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLevelGame.js","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useLevelGame.js","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for fetching and managing game board for a specific level\n * Handles auth and subscription status with automatic refresh\n */\n\nimport { useMemo } from 'react';\nimport type { Board } from '@sudobility/sudojo_types';\nimport { hasRequiredEntitlement } from '@sudobility/sudojo_types';\nimport type { NetworkClient } from '@sudobility/types';\nimport { useSudojoRandomBoard } from '@sudobility/sudojo_client';\nimport { useQueryClient } from '@tanstack/react-query';\n\n/** Game fetch status indicating what screen to show */\nexport type GameFetchStatus =\n | 'loading'\n | 'success'\n | 'auth_required'\n | 'subscription_required'\n | 'entitlement_required'\n | 'error';\n\n/** Extended API response with action field from Sudojo API */\ninterface SudojoApiResponse<T> {\n success: boolean;\n data?: T;\n error?: string | null;\n message?: string;\n action?: {\n type: string;\n options?: string[];\n };\n}\n\n/** Check if response indicates auth is required */\nfunction isAuthRequired(\n response: SudojoApiResponse<unknown> | undefined,\n error: unknown\n): boolean {\n if (\n response?.success === false &&\n response.action?.type === 'auth_required'\n ) {\n return true;\n }\n if (error && typeof error === 'object') {\n const err = error as { message?: string };\n if (err.message?.includes('Account required')) return true;\n }\n return false;\n}\n\n/** Check if response indicates subscription is required */\nfunction isSubscriptionRequired(\n response: SudojoApiResponse<unknown> | undefined,\n error: unknown\n): boolean {\n if (\n response?.success === false &&\n response.action?.type === 'subscription_required'\n ) {\n return true;\n }\n if (error && typeof error === 'object') {\n const err = error as { message?: string };\n if (\n err.message?.includes('Daily limit reached') ||\n err.message?.includes('subscription')\n ) {\n return true;\n }\n }\n return false;\n}\n\nexport interface UseLevelGameOptions {\n /** Network client for API calls */\n networkClient: NetworkClient;\n /** Base URL for the Sudojo API */\n baseUrl: string;\n /** Access token for authentication */\n token: string;\n /** Level number (1-12) to fetch game for */\n level: number;\n /** Whether to fetch only symmetrical puzzles */\n symmetrical?: boolean;\n /** Whether subscription is currently active */\n subscriptionActive?: boolean;\n /** The user's active entitlement IDs (e.g., ['blue_belt'] or ['red_belt']) */\n userEntitlements?: string[];\n /** The entitlement field from the current level (e.g., \"blue_belt,red_belt\") */\n levelEntitlement?: string | null;\n /** Whether to enable the query */\n enabled?: boolean;\n}\n\nexport interface UseLevelGameResult {\n /** The game board data */\n board: Board | null;\n /** Current status of the game fetch */\n status: GameFetchStatus;\n /** Whether data is loading */\n isLoading: boolean;\n /** Error if fetch failed */\n error: Error | null;\n /** Refetch the game board */\n refetch: () => void;\n /** Fetch a new random board for this level */\n nextPuzzle: () => void;\n /** The entitlement string required for this level (for paywall display) */\n requiredEntitlement: string | null;\n}\n\n/**\n * Hook for fetching a game board for a specific level\n *\n * Automatically refetches when auth token or subscription status changes.\n * Returns status indicating whether auth or subscription is required.\n *\n * @param options - Hook options\n * @returns Game board data and status\n *\n * @example\n * ```tsx\n * function LevelPlayPage({ level }: { level: number }) {\n * const { board, status, refetch, nextPuzzle } = useLevelGame({\n * networkClient,\n * config,\n * auth,\n * level,\n * subscriptionActive: subscription.isActive,\n * });\n *\n * if (status === 'loading') return <Loading />;\n * if (status === 'auth_required') return <AuthRequired onLogin={openAuthModal} />;\n * if (status === 'subscription_required') return <SubscriptionPaywall onSuccess={refetch} />;\n * if (status === 'error') return <Error />;\n *\n * return <SudokuGame puzzle={board.board} solution={board.solution} />;\n * }\n * ```\n */\nexport function useLevelGame(options: UseLevelGameOptions): UseLevelGameResult {\n const {\n networkClient,\n baseUrl,\n token,\n level,\n symmetrical,\n userEntitlements,\n levelEntitlement,\n enabled = true,\n } = options;\n\n // Client-side entitlement check before making API call\n const entitlementDenied = useMemo(\n () => !hasRequiredEntitlement(levelEntitlement, userEntitlements ?? []),\n [levelEntitlement, userEntitlements]\n );\n\n const queryClient = useQueryClient();\n\n const queryParams = useMemo(\n () => ({\n level,\n symmetrical: symmetrical || undefined,\n limit: undefined,\n offset: undefined,\n techniques: undefined,\n technique_bit: undefined,\n }),\n [level, symmetrical]\n );\n\n const { data, isLoading, error, refetch } = useSudojoRandomBoard(\n networkClient,\n baseUrl,\n token,\n queryParams,\n { enabled: enabled && level >= 1 && level <= 12 && !entitlementDenied }\n );\n\n // Determine status based on response\n // Cast to SudojoApiResponse to check for action field\n const apiResponse = data as SudojoApiResponse<Board> | undefined;\n\n const status = useMemo((): GameFetchStatus => {\n if (entitlementDenied) return 'entitlement_required';\n if (isLoading) return 'loading';\n if (isAuthRequired(apiResponse, error)) return 'auth_required';\n if (isSubscriptionRequired(apiResponse, error))\n return 'subscription_required';\n if (error) return 'error';\n if (apiResponse?.success && apiResponse.data) return 'success';\n return 'loading';\n }, [entitlementDenied, isLoading, apiResponse, error]);\n\n const board = useMemo(() => {\n if (data?.success && data.data) {\n return data.data;\n }\n return null;\n }, [data]);\n\n const nextPuzzle = useMemo(() => {\n return () => {\n queryClient.invalidateQueries({\n queryKey: ['sudojo', 'boards', 'random'],\n });\n refetch();\n };\n }, [queryClient, refetch]);\n\n return {\n board,\n status,\n isLoading,\n error: error ?? null,\n refetch: () => refetch(),\n nextPuzzle,\n requiredEntitlement: levelEntitlement ?? null,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -451,7 +451,7 @@ UseLevelGameResult,
|
|
|
451
451
|
UseDailyGameOptions,
|
|
452
452
|
/** Result type for useDailyGame hook (daily data, fetch status). */
|
|
453
453
|
UseDailyGameResult,
|
|
454
|
-
/** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'error'. */
|
|
454
|
+
/** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'entitlement_required' | 'error'. */
|
|
455
455
|
GameFetchStatus,
|
|
456
456
|
/** Options for useGameTimer hook (autoStart, initialTime). */
|
|
457
457
|
UseGameTimerOptions,
|
|
@@ -499,4 +499,8 @@ AuthProviderType,
|
|
|
499
499
|
AuthProvidersConfig, } from './config';
|
|
500
500
|
/** Default auth providers configuration (Google + Email, anonymous fallback). */
|
|
501
501
|
export { DEFAULT_AUTH_PROVIDERS } from './config';
|
|
502
|
+
/** Parse a comma-delimited entitlement string into an array. */
|
|
503
|
+
export { parseEntitlements } from '@sudobility/sudojo_types';
|
|
504
|
+
/** Check if a user has the required entitlement for a level. */
|
|
505
|
+
export { hasRequiredEntitlement } from '@sudobility/sudojo_types';
|
|
502
506
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -341,4 +341,11 @@ useGameSession, } from './hooks';
|
|
|
341
341
|
export { useGamePlayStore } from './stores/gamePlayStore';
|
|
342
342
|
/** Default auth providers configuration (Google + Email, anonymous fallback). */
|
|
343
343
|
export { DEFAULT_AUTH_PROVIDERS } from './config';
|
|
344
|
+
// ============================================================================
|
|
345
|
+
// Entitlement Utilities (re-exported from sudojo_types)
|
|
346
|
+
// ============================================================================
|
|
347
|
+
/** Parse a comma-delimited entitlement string into an array. */
|
|
348
|
+
export { parseEntitlements } from '@sudobility/sudojo_types';
|
|
349
|
+
/** Check if a user has the required entitlement for a level. */
|
|
350
|
+
export { hasRequiredEntitlement } from '@sudobility/sudojo_types';
|
|
344
351
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @sudobility/sudojo_lib - Business logic library for Sudojo app\n *\n * This library provides:\n * - Game state management with useSudoku hook (ported from renderable)\n * - Board scrambling utilities\n * - Game validation (mistakes, completion)\n * - Level, technique, and learning data hooks\n * - Teaching/hint integration with solver\n * - Legacy useGame hook for backward compatibility\n *\n * ## Hook Architecture\n *\n * The hooks form a layered composition pattern:\n *\n * **Data hooks** (fetch and cache server data):\n * - `useLevels` / `useLevel` - Difficulty level data\n * - `useTechniques` / `useTechnique` - Solving technique data\n * - `useLearning` / `useLearningItem` - Learning material data\n *\n * **Game fetching hooks** (handle auth, subscription, and puzzle loading):\n * - `useLevelGame` - Fetch a random board for a specific level\n * - `useDailyGame` - Fetch today's daily puzzle\n *\n * **Game state hooks** (manage board state and user interaction):\n * - `useSudoku` - Primary game state (flat 81-cell array, modern API)\n * - `useGame` - Legacy game state (2D array, deprecated)\n * - `useBoardEntry` - Manual puzzle entry mode\n *\n * **Feature hooks** (provide specific game features):\n * - `useHint` - Solver integration for hints (matches Kotlin HintInteractor)\n * - `useGameTeaching` - Step-by-step teaching with solver\n * - `useGameTimer` - Elapsed time tracking via ref (no re-renders)\n * - `useGamePersistence` / `useAutoSave` - localStorage game save/restore\n * - `useLocalStorage` - Generic typed localStorage hook\n *\n * **Orchestration hooks** (combine multiple hooks for app-level features):\n * - `useGamePlay` - Current game management with Zustand store (daily/play slots)\n * - `useGameSession` - Server-side gamification (start/finish, points, badges)\n *\n * ## Migration Guide\n *\n * Legacy exports (prefixed with \"Legacy\" comments) use the 2D `GameBoard` type\n * from `useGame`. New code should use `useSudoku` with its flat 81-cell\n * `SudokuBoard` type. See `@deprecated` tags on legacy exports.\n */\n\n// ============================================================================\n// Legacy Types (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated Use `SudokuCell` instead. Part of the legacy `useGame` 2D board API.\n */\nexport type {\n CellPosition,\n CellState,\n GameBoard,\n GameHint,\n GameMove,\n GameSettings,\n GameState,\n GameStatus,\n TeachingState,\n} from './types';\n\n/** @deprecated Use `DEFAULT_APP_SETTINGS` / `DEFAULT_PLAY_SETTINGS` instead. */\nexport { DEFAULT_GAME_SETTINGS } from './types';\n\n// ============================================================================\n// Sudoku Types (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Core Sudoku cell and board types using flat 81-cell array representation. */\nexport type {\n /** A single cell in the Sudoku board (indexed 0-80). */\n SudokuCell,\n /** The Sudoku board containing all 81 cells. */\n SudokuBoard,\n /** Current play state including board, settings, and selection. */\n SudokuPlay,\n /** Session settings that can change during play (pencilmarking, auto-pencilmarks). */\n SudokuPlaySettings,\n /** App-level settings persisted across sessions (showErrors, display format). */\n SudokuAppSettings,\n /** Full game state including source, history, and digit mapping. */\n SudokuGameState,\n /** Display modes for Sudoku digits ('NUMERIC' | 'KANJI' | 'COLORS' | 'EMOJIS'). */\n SudokuDisplay,\n /** Source of the puzzle ('DAILY' | 'CHALLENGE' | 'LEVEL' | 'ENTERED'). */\n PlayingSource,\n} from './types';\n\n/** Default settings and cell/board helper functions for the modern Sudoku API. */\nexport {\n /** Default session play settings (pencilmarking off, auto-pencilmarks off). */\n DEFAULT_PLAY_SETTINGS,\n /** Default app settings (showErrors on, animations on, numeric display). */\n DEFAULT_APP_SETTINGS,\n /** Create an empty SudokuCell at the given index. */\n createEmptyCell,\n /** Create an empty 81-cell SudokuBoard. */\n createEmptyBoard,\n /** Check if a cell has an error (input does not match solution). */\n cellHasError,\n /** Get row index (0-8) from cell index (0-80). */\n rowOf,\n /** Get column index (0-8) from cell index (0-80). */\n columnOf,\n /** Get block index (0-8) from cell index (0-80). */\n blockOf,\n /** Get cell index (0-80) from row and column. */\n cellIndex,\n /** Get all cell indices in the same row as the given index. */\n getRowIndices,\n /** Get all cell indices in the same column as the given index. */\n getColumnIndices,\n /** Get all cell indices in the same block as the given index. */\n getBlockIndices,\n /** Get all related cell indices (same row, column, or block) excluding the cell itself. */\n getRelatedIndices,\n} from './types';\n\n// ============================================================================\n// Display types (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Display and hint visualization types matching the Kotlin renderable layer. */\nexport type {\n /** Highlighted area in a hint (row, column, or block). */\n HintArea,\n /** Cell display information in a hint step. */\n HintCell,\n /** Actions to perform on a cell during hint visualization. */\n HintCellActions,\n /** A single hint step with title, text, areas, cells, links, and groups. */\n DisplayHintStep,\n /** Complete display state for a single cell (colors, digit, pencilmarks). */\n CellDisplayState,\n /** Display state for a single pencilmark (digit and color). */\n PencilmarkDisplayState,\n /** UI color palette with system colors for light or dark mode. */\n UIColorPalette,\n /** Link type for chain visualization ('strong' | 'weak'). */\n LinkType,\n /** A link between two cells in a chain (display format). */\n DisplayLink,\n /** A group of cells for pattern visualization (display format). */\n DisplayCellGroup,\n} from './types';\n\n/** Theme and color enums plus predefined light/dark palettes. */\nexport { ThemeColor, SudokuColor, UIColorLight, UIColorDark } from './types';\n\n// ============================================================================\n// Progress Types (for user progress tracking)\n// ============================================================================\n\n/** Types for tracking user puzzle completion and statistics. */\nexport type {\n /** Record of a completed puzzle (id, type, time). */\n CompletedPuzzle,\n /** Computed game statistics (best times, averages). */\n GameStats,\n /** Full user progress data (completed puzzles, streak, stats). */\n UserProgress,\n} from './types';\n\nexport {\n /** Default empty user progress state. */\n DEFAULT_PROGRESS,\n /** localStorage key for progress data ('sudojo-progress'). */\n PROGRESS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Settings Types (for app settings)\n// ============================================================================\n\n/** Types for application settings. */\nexport type {\n /** Digit display format ('numeric' | 'kanji' | 'emojis'). */\n DigitDisplay,\n /** Application settings (showErrors, symmetrical, display). */\n AppSettings,\n} from './types';\n\nexport {\n /** Default application settings. */\n DEFAULT_SETTINGS,\n /** localStorage key for settings ('sudojo-settings'). */\n SETTINGS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Subscription Types (for subscription management)\n// ============================================================================\n\n/** Types for RevenueCat subscription management. */\nexport type {\n /** Subscription product information (price, period, trial). */\n Product,\n /** User subscription status (active, expiration, renewal). */\n Subscription,\n} from './types';\n\n/** Default inactive subscription state. */\nexport { DEFAULT_SUBSCRIPTION } from './types';\n\n// ============================================================================\n// Game Persistence Types (for saving/loading game state)\n// ============================================================================\n\n/** Types for saving and restoring game progress to localStorage. */\nexport type {\n /** Saved game state (input, pencilmarks, mode, timestamp). */\n SavedGameState,\n /** Key identifying a game to persist (type + id). */\n GamePersistenceKey,\n} from './types';\n\nexport {\n /** localStorage key prefix for game saves ('sudojo_game_'). */\n GAME_STORAGE_PREFIX,\n /** Generate a localStorage key from a GamePersistenceKey. */\n getGameStorageKey,\n} from './types';\n\n// ============================================================================\n// Current Game Types (for current game feature)\n// ============================================================================\n\n/** Types for the Zustand-backed current game store. */\nexport type {\n /** Source of the current game ('daily' | 'level' | 'entered'). */\n GameSource,\n /** Navigation metadata for resuming a game (date, level, board info). */\n CurrentGameMeta,\n /** Full current game state stored in Zustand (puzzle, progress, timing). */\n CurrentGame,\n /** Which store slot a game lives in ('daily' | 'play'). */\n GameSlot,\n} from './types';\n\n// ============================================================================\n// Legacy Utilities (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated These utilities work with the legacy 2D `GameBoard` type.\n * For new code, use `useSudoku` with its flat 81-cell board and the\n * scrambler/presenter utilities below.\n */\nexport {\n /** @deprecated Clone a 2D GameBoard. Use useSudoku's immutable state instead. */\n cloneBoard,\n /** @deprecated Count filled cells in a 2D GameBoard. */\n countFilledCells,\n /** @deprecated Create a 2D GameBoard from puzzle/solution strings. */\n createGameBoard,\n /** @deprecated Get cells in a block by block index (2D API). */\n getBlockCells,\n /** @deprecated Get block index from row/col (2D API). Use blockOf() instead. */\n getBlockIndex,\n /** @deprecated Get 2D board state as string. Use cellsToStateString() instead. */\n getBoardStateString,\n /** @deprecated Get cells in a column (2D API). Use getColumnIndices() instead. */\n getColumnCells,\n /** @deprecated Get empty cells from a 2D GameBoard. */\n getEmptyCells,\n /** @deprecated Get pencilmarks string from 2D GameBoard. Use cellsToPencilmarksString() instead. */\n getPencilmarksString,\n /** @deprecated Get related cells (2D API). Use getRelatedIndices() instead. */\n getRelatedCells,\n /** @deprecated Get cells in a row (2D API). Use getRowIndices() instead. */\n getRowCells,\n /** @deprecated Check if placement is valid (2D API). */\n isValidPlacement,\n /** @deprecated Auto-remove pencilmarks (2D API). useSudoku handles this internally. */\n autoRemovePencilmarks,\n /** @deprecated Clear highlights (2D API). useSudoku handles this via presentBoard(). */\n clearHighlights,\n /** @deprecated Count mistakes (2D API). Use useSudoku's errorCount instead. */\n countMistakes,\n /** @deprecated Get incorrect cells (2D API). Use useSudoku's errorCells instead. */\n getIncorrectCells,\n /** @deprecated Get progress percentage (2D API). Use useSudoku's progress instead. */\n getProgressPercentage,\n /** @deprecated Check if board is filled (2D API). */\n isBoardFilled,\n /** @deprecated Check if cell is correct (2D API). Use cellHasError() instead. */\n isCellCorrect,\n /** @deprecated Check if game is complete (2D API). Use useSudoku's isCompleted instead. */\n isGameComplete,\n /** @deprecated Check if value is correct (2D API). */\n isValueCorrect,\n /** @deprecated Update cell errors (2D API). useSudoku handles this automatically. */\n updateCellErrors,\n /** @deprecated Update cell highlights (2D API). Use presentBoard() instead. */\n updateCellHighlights,\n /** @deprecated Validate entire game state (2D API). */\n validateGameState,\n} from './utils';\n\n// ============================================================================\n// Sudoku Utilities (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Types for board scrambling. */\nexport type {\n /** Protocol for board scramblers (Scrambler and NonScrambler implement this). */\n ScramblerProtocol,\n /** Result of scrambling a board (cells + digit mappings). */\n SudokuScrambleResult,\n} from './utils';\n\n/** Board scrambling and puzzle string conversion utilities. */\nexport {\n /** Scrambler that permutes rows, columns, and digits to create unique puzzles. */\n Scrambler,\n /** Identity scrambler that returns the board unchanged. */\n NonScrambler,\n /** Scramble a board using a ScramblerProtocol implementation. */\n scrambleSudokuBoard,\n /** Parse an 81-character puzzle string into SudokuCell array. */\n parsePuzzleString,\n /** Convert SudokuCell array to puzzle string (given values only). */\n cellsToPuzzleString,\n /** Convert SudokuCell array to state string (given + input values). */\n cellsToStateString,\n /** Convert SudokuCell array to input-only string. */\n cellsToInputString,\n /** Convert SudokuCell array to comma-separated pencilmarks string. */\n cellsToPencilmarksString,\n} from './utils';\n\n// ============================================================================\n// Presenter utilities (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Options type for the presentBoard function. */\nexport type {\n /** Options for generating cell display states (cells, selection, errors, hints). */\n PresentBoardOptions,\n} from './utils';\n\n/** Board presentation and color utilities matching the Kotlin renderable layer. */\nexport {\n /** Generate display states for all 81 cells (colors, digits, pencilmarks, hints). */\n presentBoard,\n /** Process hint step areas and cells into a map of cell hints by index. */\n calculateCellHints,\n /** Convert a ThemeColor to an actual CSS color string using a palette. */\n themeColorToCSS,\n /** Get the UIColorPalette for light or dark mode. */\n getColorPalette,\n /** Get indices of cells containing a specific digit (given or input). */\n getCellsWithDigit,\n /** Get the digit to highlight based on the selected cell (given or correct input). */\n getSelectedDigit,\n /** Compute the set of cell indices with the same digit as the selected cell. */\n computeSelectedDigitCells,\n /** Convert a solver link (row/col pairs) to display format (flat indices). */\n convertSolverLink,\n /** Convert a solver cell group to display format with ThemeColor. */\n convertSolverCellGroup,\n /** Convert SudokuColor enum to ThemeColor enum. */\n sudokuColorToTheme,\n} from './utils';\n\n// ============================================================================\n// Time Utilities\n// ============================================================================\n\n/** Time formatting and parsing utilities. */\nexport {\n /** Format seconds into MM:SS or HH:MM:SS string. */\n formatTime,\n /** Parse a MM:SS or HH:MM:SS string back to total seconds. */\n parseTime,\n} from './utils';\n\n// ============================================================================\n// Progress Utilities\n// ============================================================================\n\n/** User progress calculation utilities. */\nexport {\n /** Calculate game statistics (best times, averages) from completed puzzles. */\n calculateStats,\n /** Calculate current daily streak from completion history. */\n calculateStreak,\n /** Check if a specific puzzle (by type and id) has been completed. */\n isPuzzleCompleted,\n /** Get all completed level IDs from completion history. */\n getCompletedLevelIds,\n /** Get all completed daily dates (YYYY-MM-DD) from completion history. */\n getCompletedDailyDates,\n} from './utils';\n\n// ============================================================================\n// Theme Utilities\n// ============================================================================\n\n/** Types for theme preference management. */\nexport type {\n /** Theme preference: 'light' | 'dark' | 'system'. */\n ThemePreference,\n /** Resolved theme without system option: 'light' | 'dark'. */\n ResolvedTheme,\n} from './utils';\n\n/** Theme detection and resolution utilities. */\nexport {\n /** localStorage key for theme preference ('sudojo-theme'). */\n THEME_STORAGE_KEY,\n /** Detect the system color scheme preference (light/dark). */\n getSystemTheme,\n /** Resolve a ThemePreference to an actual theme using the system theme. */\n resolveTheme,\n /** Type guard: check if a value is a valid ThemePreference. */\n isValidThemePreference,\n} from './utils';\n\n// ============================================================================\n// Subscription Utilities\n// ============================================================================\n\n/** RevenueCat subscription conversion and display utilities. */\nexport {\n /** Convert a RevenueCat package to a Product domain model. */\n convertPackageToProduct,\n /** Parse RevenueCat CustomerInfo into a Subscription domain model. */\n parseCustomerInfo,\n /** Get human-readable name for an ISO 8601 subscription period (e.g., 'P1M' -> 'Monthly'). */\n getPeriodDisplayName,\n /** Check if a subscription period is the \"best value\" option (annual plans). */\n isBestValuePlan,\n /** Get a user-friendly error message for a RevenueCat error code. */\n getRevenueCatErrorMessage,\n} from './utils';\n\n// ============================================================================\n// Technique Utilities\n// ============================================================================\n\n/** Technique display utilities. */\nexport {\n /** Get the icon URL for a solving technique by its path slug. */\n getTechniqueIconUrl,\n} from './utils';\n\n// ============================================================================\n// Hint Explanation Utilities\n// ============================================================================\n\n/** Hint explanation generation utilities for teaching users solving techniques. */\nexport {\n /** Generate a detailed explanation for a hint step based on the technique. */\n generateDetailedExplanation,\n /** Get a short action summary for a hint step (e.g., 'Place 5 in R1C3'). */\n getHintActionSummary,\n} from './utils';\n\n// ============================================================================\n// Localized Hint Utilities\n// ============================================================================\n\n/** Types for hint text localization. */\nexport type {\n /** Translation function compatible with i18next's `t` function. */\n TranslateFunction,\n} from './utils';\n\n/** Hint localization utilities. */\nexport {\n /** Get localized text for a hint step using a translation function. */\n getLocalizedHintText,\n} from './utils';\n\n// ============================================================================\n// i18n Key Utilities\n// ============================================================================\n\n/** Internationalization key generation and localization utilities. */\nexport {\n /** Get i18n key for a belt name (e.g., 'belts.1.name'). */\n getBeltKey,\n /** Get localized belt name using a translation function. */\n getLocalizedBeltName,\n /** Get i18n key for a belt label (e.g., 'belts.1.label'). */\n getBeltLabelKey,\n /** Get localized belt label (e.g., 'White Belt'). */\n getLocalizedBeltLabel,\n /** Get i18n key for a level title (e.g., 'levels.3'). */\n getLevelKey,\n /** Get localized level title using a translation function. */\n getLocalizedLevelTitle,\n /** Get i18n key for a technique name (e.g., 'techniques.full-house.title'). */\n getTechniqueKey,\n /** Get localized technique name using a translation function. */\n getLocalizedTechniqueName,\n} from './utils';\n\n// ============================================================================\n// Digit Display Utilities\n// ============================================================================\n\n/** Digit display format conversion. */\nexport {\n /** Convert a digit (1-9) to its display string based on the format (numeric, kanji, emojis). */\n displayDigit,\n} from './utils';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n // Data hooks\n /** Fetch a single difficulty level by number. */\n useLevel,\n /** Fetch all difficulty levels with sorting and filtering utilities. */\n useLevels,\n /** Fetch a single solving technique by number. */\n useTechnique,\n /** Fetch all solving techniques with grouping utilities. */\n useTechniques,\n /** Fetch learning materials with filtering by technique and language. */\n useLearning,\n /** Fetch a single learning item by UUID. */\n useLearningItem,\n\n /**\n * @deprecated Use `useSudoku` instead. `useGame` uses a legacy 2D array board\n * representation, while `useSudoku` uses a flat 81-cell array consistent with\n * the Kotlin renderable layer and the rest of the codebase.\n */\n useGame,\n\n /** Primary game state hook with flat 81-cell board, pencil mode, and scrambling. */\n useSudoku,\n\n /** Teaching/hint integration with the solver API (legacy GameHint format). */\n useGameTeaching,\n\n /** Fetch a random board for a specific level with auth/subscription handling. */\n useLevelGame,\n /** Fetch today's daily puzzle with auth/subscription handling. */\n useDailyGame,\n\n /** Game timer using refs to avoid re-renders every second. */\n useGameTimer,\n\n /** Persist individual game progress to localStorage. */\n useGamePersistence,\n /** Auto-save game state with debouncing. */\n useAutoSave,\n\n /** Generic typed localStorage hook with SSR safety. */\n useLocalStorage,\n\n /** Solver hint integration matching Kotlin HintInteractor behavior. */\n useHint,\n\n /** Current game management with Zustand store (daily/play slots). */\n useGamePlay,\n\n /** Manual puzzle entry mode with solver validation. */\n useBoardEntry,\n\n /** Server-side game session management for gamification (points, badges). */\n useGameSession,\n} from './hooks';\n\nexport type {\n // Data hook types\n /** Options for useLevel hook. */\n UseLevelOptions,\n /** Result type for useLevel hook. */\n UseLevelResult,\n /** Options for useLevels hook. */\n UseLevelsOptions,\n /** Result type for useLevels hook. */\n UseLevelsResult,\n /** Options for useTechnique hook. */\n UseTechniqueOptions,\n /** Result type for useTechnique hook. */\n UseTechniqueResult,\n /** Options for useTechniques hook. */\n UseTechniquesOptions,\n /** Result type for useTechniques hook. */\n UseTechniquesResult,\n /** Options for useLearningItem hook. */\n UseLearningItemOptions,\n /** Result type for useLearningItem hook. */\n UseLearningItemResult,\n /** Options for useLearning hook. */\n UseLearningOptions,\n /** Result type for useLearning hook. */\n UseLearningResult,\n\n // Game hook types (legacy)\n /** @deprecated Options for legacy useGame hook. Use UseSudokuOptions instead. */\n UseGameOptions,\n /** @deprecated Result type for legacy useGame hook. Use UseSudokuResult instead. */\n UseGameResult,\n\n // Sudoku hook types\n /** Options for useSudoku hook (initial app settings). */\n UseSudokuOptions,\n /** Result type for useSudoku hook (state, computed values, actions, utilities). */\n UseSudokuResult,\n\n // Teaching hook types\n /** Options for useGameTeaching hook (network client, URL, token). */\n UseGameTeachingOptions,\n /** Result type for useGameTeaching hook (teaching state, hint actions). */\n UseGameTeachingResult,\n\n // Game fetching hook types\n /** Options for useLevelGame hook (network, auth, level number). */\n UseLevelGameOptions,\n /** Result type for useLevelGame hook (board data, fetch status). */\n UseLevelGameResult,\n /** Options for useDailyGame hook (network, auth). */\n UseDailyGameOptions,\n /** Result type for useDailyGame hook (daily data, fetch status). */\n UseDailyGameResult,\n /** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'error'. */\n GameFetchStatus,\n\n // Timer hook types\n /** Options for useGameTimer hook (autoStart, initialTime). */\n UseGameTimerOptions,\n /** Result type for useGameTimer hook (elapsedRef, controls). */\n UseGameTimerResult,\n\n // Persistence hook types\n /** Options for useGamePersistence hook (puzzleKey, autoSave). */\n UseGamePersistenceOptions,\n /** Result type for useGamePersistence hook (load, save, clear, hasSaved). */\n UseGamePersistenceResult,\n\n // Hint hook types\n /** Options for useHint hook (network, puzzle state, technique filter). */\n UseHintOptions,\n /** Result type for useHint hook (hint steps, navigation, apply). */\n UseHintResult,\n /** Board data returned when applying a hint (user input, pencilmarks). */\n HintBoardData,\n /** Data passed to onHintReceived callback (hint, board data, technique info). */\n HintReceivedData,\n /** Access denied error info when hint level exceeds subscription tier. */\n HintAccessError,\n\n // Game play hook types\n /** Options for useGamePlay hook (slot selection, auto-save delay). */\n UseGamePlayOptions,\n /** Result type for useGamePlay hook (current game, start, update, clear). */\n UseGamePlayResult,\n\n // Board entry hook types\n /** Options for useBoardEntry hook (network client, URL, token). */\n UseBoardEntryOptions,\n /** Result type for useBoardEntry hook (cells, validation, actions). */\n UseBoardEntryReturn,\n /** Validated puzzle data from solver (puzzle + solution strings). */\n ValidatedPuzzle,\n\n // Game session hook types\n /** Options for useGameSession hook (network, auth, userId). */\n UseGameSessionOptions,\n /** Result of starting a game session (sessionStarted, sessionId). */\n GameSessionResult,\n /** Result of finishing a game session (leveledUp, badges, points). */\n GameFinishResult,\n} from './hooks';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\n/** Zustand store for current game state with daily/play slots and localStorage persistence. */\nexport { useGamePlayStore } from './stores/gamePlayStore';\n/** State shape for the game play Zustand store. */\nexport type { GamePlayState } from './stores/gamePlayStore';\n\n// ============================================================================\n// Config\n// ============================================================================\n\n/** Authentication provider configuration types. */\nexport type {\n /** Available auth provider types: 'google' | 'apple' | 'email'. */\n AuthProviderType,\n /** Configuration for which auth providers are enabled. */\n AuthProvidersConfig,\n} from './config';\n\n/** Default auth providers configuration (Google + Email, anonymous fallback). */\nexport { DEFAULT_AUTH_PROVIDERS } from './config';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @sudobility/sudojo_lib - Business logic library for Sudojo app\n *\n * This library provides:\n * - Game state management with useSudoku hook (ported from renderable)\n * - Board scrambling utilities\n * - Game validation (mistakes, completion)\n * - Level, technique, and learning data hooks\n * - Teaching/hint integration with solver\n * - Legacy useGame hook for backward compatibility\n *\n * ## Hook Architecture\n *\n * The hooks form a layered composition pattern:\n *\n * **Data hooks** (fetch and cache server data):\n * - `useLevels` / `useLevel` - Difficulty level data\n * - `useTechniques` / `useTechnique` - Solving technique data\n * - `useLearning` / `useLearningItem` - Learning material data\n *\n * **Game fetching hooks** (handle auth, subscription, and puzzle loading):\n * - `useLevelGame` - Fetch a random board for a specific level\n * - `useDailyGame` - Fetch today's daily puzzle\n *\n * **Game state hooks** (manage board state and user interaction):\n * - `useSudoku` - Primary game state (flat 81-cell array, modern API)\n * - `useGame` - Legacy game state (2D array, deprecated)\n * - `useBoardEntry` - Manual puzzle entry mode\n *\n * **Feature hooks** (provide specific game features):\n * - `useHint` - Solver integration for hints (matches Kotlin HintInteractor)\n * - `useGameTeaching` - Step-by-step teaching with solver\n * - `useGameTimer` - Elapsed time tracking via ref (no re-renders)\n * - `useGamePersistence` / `useAutoSave` - localStorage game save/restore\n * - `useLocalStorage` - Generic typed localStorage hook\n *\n * **Orchestration hooks** (combine multiple hooks for app-level features):\n * - `useGamePlay` - Current game management with Zustand store (daily/play slots)\n * - `useGameSession` - Server-side gamification (start/finish, points, badges)\n *\n * ## Migration Guide\n *\n * Legacy exports (prefixed with \"Legacy\" comments) use the 2D `GameBoard` type\n * from `useGame`. New code should use `useSudoku` with its flat 81-cell\n * `SudokuBoard` type. See `@deprecated` tags on legacy exports.\n */\n\n// ============================================================================\n// Legacy Types (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated Use `SudokuCell` instead. Part of the legacy `useGame` 2D board API.\n */\nexport type {\n CellPosition,\n CellState,\n GameBoard,\n GameHint,\n GameMove,\n GameSettings,\n GameState,\n GameStatus,\n TeachingState,\n} from './types';\n\n/** @deprecated Use `DEFAULT_APP_SETTINGS` / `DEFAULT_PLAY_SETTINGS` instead. */\nexport { DEFAULT_GAME_SETTINGS } from './types';\n\n// ============================================================================\n// Sudoku Types (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Core Sudoku cell and board types using flat 81-cell array representation. */\nexport type {\n /** A single cell in the Sudoku board (indexed 0-80). */\n SudokuCell,\n /** The Sudoku board containing all 81 cells. */\n SudokuBoard,\n /** Current play state including board, settings, and selection. */\n SudokuPlay,\n /** Session settings that can change during play (pencilmarking, auto-pencilmarks). */\n SudokuPlaySettings,\n /** App-level settings persisted across sessions (showErrors, display format). */\n SudokuAppSettings,\n /** Full game state including source, history, and digit mapping. */\n SudokuGameState,\n /** Display modes for Sudoku digits ('NUMERIC' | 'KANJI' | 'COLORS' | 'EMOJIS'). */\n SudokuDisplay,\n /** Source of the puzzle ('DAILY' | 'CHALLENGE' | 'LEVEL' | 'ENTERED'). */\n PlayingSource,\n} from './types';\n\n/** Default settings and cell/board helper functions for the modern Sudoku API. */\nexport {\n /** Default session play settings (pencilmarking off, auto-pencilmarks off). */\n DEFAULT_PLAY_SETTINGS,\n /** Default app settings (showErrors on, animations on, numeric display). */\n DEFAULT_APP_SETTINGS,\n /** Create an empty SudokuCell at the given index. */\n createEmptyCell,\n /** Create an empty 81-cell SudokuBoard. */\n createEmptyBoard,\n /** Check if a cell has an error (input does not match solution). */\n cellHasError,\n /** Get row index (0-8) from cell index (0-80). */\n rowOf,\n /** Get column index (0-8) from cell index (0-80). */\n columnOf,\n /** Get block index (0-8) from cell index (0-80). */\n blockOf,\n /** Get cell index (0-80) from row and column. */\n cellIndex,\n /** Get all cell indices in the same row as the given index. */\n getRowIndices,\n /** Get all cell indices in the same column as the given index. */\n getColumnIndices,\n /** Get all cell indices in the same block as the given index. */\n getBlockIndices,\n /** Get all related cell indices (same row, column, or block) excluding the cell itself. */\n getRelatedIndices,\n} from './types';\n\n// ============================================================================\n// Display types (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Display and hint visualization types matching the Kotlin renderable layer. */\nexport type {\n /** Highlighted area in a hint (row, column, or block). */\n HintArea,\n /** Cell display information in a hint step. */\n HintCell,\n /** Actions to perform on a cell during hint visualization. */\n HintCellActions,\n /** A single hint step with title, text, areas, cells, links, and groups. */\n DisplayHintStep,\n /** Complete display state for a single cell (colors, digit, pencilmarks). */\n CellDisplayState,\n /** Display state for a single pencilmark (digit and color). */\n PencilmarkDisplayState,\n /** UI color palette with system colors for light or dark mode. */\n UIColorPalette,\n /** Link type for chain visualization ('strong' | 'weak'). */\n LinkType,\n /** A link between two cells in a chain (display format). */\n DisplayLink,\n /** A group of cells for pattern visualization (display format). */\n DisplayCellGroup,\n} from './types';\n\n/** Theme and color enums plus predefined light/dark palettes. */\nexport { ThemeColor, SudokuColor, UIColorLight, UIColorDark } from './types';\n\n// ============================================================================\n// Progress Types (for user progress tracking)\n// ============================================================================\n\n/** Types for tracking user puzzle completion and statistics. */\nexport type {\n /** Record of a completed puzzle (id, type, time). */\n CompletedPuzzle,\n /** Computed game statistics (best times, averages). */\n GameStats,\n /** Full user progress data (completed puzzles, streak, stats). */\n UserProgress,\n} from './types';\n\nexport {\n /** Default empty user progress state. */\n DEFAULT_PROGRESS,\n /** localStorage key for progress data ('sudojo-progress'). */\n PROGRESS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Settings Types (for app settings)\n// ============================================================================\n\n/** Types for application settings. */\nexport type {\n /** Digit display format ('numeric' | 'kanji' | 'emojis'). */\n DigitDisplay,\n /** Application settings (showErrors, symmetrical, display). */\n AppSettings,\n} from './types';\n\nexport {\n /** Default application settings. */\n DEFAULT_SETTINGS,\n /** localStorage key for settings ('sudojo-settings'). */\n SETTINGS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Subscription Types (for subscription management)\n// ============================================================================\n\n/** Types for RevenueCat subscription management. */\nexport type {\n /** Subscription product information (price, period, trial). */\n Product,\n /** User subscription status (active, expiration, renewal). */\n Subscription,\n} from './types';\n\n/** Default inactive subscription state. */\nexport { DEFAULT_SUBSCRIPTION } from './types';\n\n// ============================================================================\n// Game Persistence Types (for saving/loading game state)\n// ============================================================================\n\n/** Types for saving and restoring game progress to localStorage. */\nexport type {\n /** Saved game state (input, pencilmarks, mode, timestamp). */\n SavedGameState,\n /** Key identifying a game to persist (type + id). */\n GamePersistenceKey,\n} from './types';\n\nexport {\n /** localStorage key prefix for game saves ('sudojo_game_'). */\n GAME_STORAGE_PREFIX,\n /** Generate a localStorage key from a GamePersistenceKey. */\n getGameStorageKey,\n} from './types';\n\n// ============================================================================\n// Current Game Types (for current game feature)\n// ============================================================================\n\n/** Types for the Zustand-backed current game store. */\nexport type {\n /** Source of the current game ('daily' | 'level' | 'entered'). */\n GameSource,\n /** Navigation metadata for resuming a game (date, level, board info). */\n CurrentGameMeta,\n /** Full current game state stored in Zustand (puzzle, progress, timing). */\n CurrentGame,\n /** Which store slot a game lives in ('daily' | 'play'). */\n GameSlot,\n} from './types';\n\n// ============================================================================\n// Legacy Utilities (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated These utilities work with the legacy 2D `GameBoard` type.\n * For new code, use `useSudoku` with its flat 81-cell board and the\n * scrambler/presenter utilities below.\n */\nexport {\n /** @deprecated Clone a 2D GameBoard. Use useSudoku's immutable state instead. */\n cloneBoard,\n /** @deprecated Count filled cells in a 2D GameBoard. */\n countFilledCells,\n /** @deprecated Create a 2D GameBoard from puzzle/solution strings. */\n createGameBoard,\n /** @deprecated Get cells in a block by block index (2D API). */\n getBlockCells,\n /** @deprecated Get block index from row/col (2D API). Use blockOf() instead. */\n getBlockIndex,\n /** @deprecated Get 2D board state as string. Use cellsToStateString() instead. */\n getBoardStateString,\n /** @deprecated Get cells in a column (2D API). Use getColumnIndices() instead. */\n getColumnCells,\n /** @deprecated Get empty cells from a 2D GameBoard. */\n getEmptyCells,\n /** @deprecated Get pencilmarks string from 2D GameBoard. Use cellsToPencilmarksString() instead. */\n getPencilmarksString,\n /** @deprecated Get related cells (2D API). Use getRelatedIndices() instead. */\n getRelatedCells,\n /** @deprecated Get cells in a row (2D API). Use getRowIndices() instead. */\n getRowCells,\n /** @deprecated Check if placement is valid (2D API). */\n isValidPlacement,\n /** @deprecated Auto-remove pencilmarks (2D API). useSudoku handles this internally. */\n autoRemovePencilmarks,\n /** @deprecated Clear highlights (2D API). useSudoku handles this via presentBoard(). */\n clearHighlights,\n /** @deprecated Count mistakes (2D API). Use useSudoku's errorCount instead. */\n countMistakes,\n /** @deprecated Get incorrect cells (2D API). Use useSudoku's errorCells instead. */\n getIncorrectCells,\n /** @deprecated Get progress percentage (2D API). Use useSudoku's progress instead. */\n getProgressPercentage,\n /** @deprecated Check if board is filled (2D API). */\n isBoardFilled,\n /** @deprecated Check if cell is correct (2D API). Use cellHasError() instead. */\n isCellCorrect,\n /** @deprecated Check if game is complete (2D API). Use useSudoku's isCompleted instead. */\n isGameComplete,\n /** @deprecated Check if value is correct (2D API). */\n isValueCorrect,\n /** @deprecated Update cell errors (2D API). useSudoku handles this automatically. */\n updateCellErrors,\n /** @deprecated Update cell highlights (2D API). Use presentBoard() instead. */\n updateCellHighlights,\n /** @deprecated Validate entire game state (2D API). */\n validateGameState,\n} from './utils';\n\n// ============================================================================\n// Sudoku Utilities (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Types for board scrambling. */\nexport type {\n /** Protocol for board scramblers (Scrambler and NonScrambler implement this). */\n ScramblerProtocol,\n /** Result of scrambling a board (cells + digit mappings). */\n SudokuScrambleResult,\n} from './utils';\n\n/** Board scrambling and puzzle string conversion utilities. */\nexport {\n /** Scrambler that permutes rows, columns, and digits to create unique puzzles. */\n Scrambler,\n /** Identity scrambler that returns the board unchanged. */\n NonScrambler,\n /** Scramble a board using a ScramblerProtocol implementation. */\n scrambleSudokuBoard,\n /** Parse an 81-character puzzle string into SudokuCell array. */\n parsePuzzleString,\n /** Convert SudokuCell array to puzzle string (given values only). */\n cellsToPuzzleString,\n /** Convert SudokuCell array to state string (given + input values). */\n cellsToStateString,\n /** Convert SudokuCell array to input-only string. */\n cellsToInputString,\n /** Convert SudokuCell array to comma-separated pencilmarks string. */\n cellsToPencilmarksString,\n} from './utils';\n\n// ============================================================================\n// Presenter utilities (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Options type for the presentBoard function. */\nexport type {\n /** Options for generating cell display states (cells, selection, errors, hints). */\n PresentBoardOptions,\n} from './utils';\n\n/** Board presentation and color utilities matching the Kotlin renderable layer. */\nexport {\n /** Generate display states for all 81 cells (colors, digits, pencilmarks, hints). */\n presentBoard,\n /** Process hint step areas and cells into a map of cell hints by index. */\n calculateCellHints,\n /** Convert a ThemeColor to an actual CSS color string using a palette. */\n themeColorToCSS,\n /** Get the UIColorPalette for light or dark mode. */\n getColorPalette,\n /** Get indices of cells containing a specific digit (given or input). */\n getCellsWithDigit,\n /** Get the digit to highlight based on the selected cell (given or correct input). */\n getSelectedDigit,\n /** Compute the set of cell indices with the same digit as the selected cell. */\n computeSelectedDigitCells,\n /** Convert a solver link (row/col pairs) to display format (flat indices). */\n convertSolverLink,\n /** Convert a solver cell group to display format with ThemeColor. */\n convertSolverCellGroup,\n /** Convert SudokuColor enum to ThemeColor enum. */\n sudokuColorToTheme,\n} from './utils';\n\n// ============================================================================\n// Time Utilities\n// ============================================================================\n\n/** Time formatting and parsing utilities. */\nexport {\n /** Format seconds into MM:SS or HH:MM:SS string. */\n formatTime,\n /** Parse a MM:SS or HH:MM:SS string back to total seconds. */\n parseTime,\n} from './utils';\n\n// ============================================================================\n// Progress Utilities\n// ============================================================================\n\n/** User progress calculation utilities. */\nexport {\n /** Calculate game statistics (best times, averages) from completed puzzles. */\n calculateStats,\n /** Calculate current daily streak from completion history. */\n calculateStreak,\n /** Check if a specific puzzle (by type and id) has been completed. */\n isPuzzleCompleted,\n /** Get all completed level IDs from completion history. */\n getCompletedLevelIds,\n /** Get all completed daily dates (YYYY-MM-DD) from completion history. */\n getCompletedDailyDates,\n} from './utils';\n\n// ============================================================================\n// Theme Utilities\n// ============================================================================\n\n/** Types for theme preference management. */\nexport type {\n /** Theme preference: 'light' | 'dark' | 'system'. */\n ThemePreference,\n /** Resolved theme without system option: 'light' | 'dark'. */\n ResolvedTheme,\n} from './utils';\n\n/** Theme detection and resolution utilities. */\nexport {\n /** localStorage key for theme preference ('sudojo-theme'). */\n THEME_STORAGE_KEY,\n /** Detect the system color scheme preference (light/dark). */\n getSystemTheme,\n /** Resolve a ThemePreference to an actual theme using the system theme. */\n resolveTheme,\n /** Type guard: check if a value is a valid ThemePreference. */\n isValidThemePreference,\n} from './utils';\n\n// ============================================================================\n// Subscription Utilities\n// ============================================================================\n\n/** RevenueCat subscription conversion and display utilities. */\nexport {\n /** Convert a RevenueCat package to a Product domain model. */\n convertPackageToProduct,\n /** Parse RevenueCat CustomerInfo into a Subscription domain model. */\n parseCustomerInfo,\n /** Get human-readable name for an ISO 8601 subscription period (e.g., 'P1M' -> 'Monthly'). */\n getPeriodDisplayName,\n /** Check if a subscription period is the \"best value\" option (annual plans). */\n isBestValuePlan,\n /** Get a user-friendly error message for a RevenueCat error code. */\n getRevenueCatErrorMessage,\n} from './utils';\n\n// ============================================================================\n// Technique Utilities\n// ============================================================================\n\n/** Technique display utilities. */\nexport {\n /** Get the icon URL for a solving technique by its path slug. */\n getTechniqueIconUrl,\n} from './utils';\n\n// ============================================================================\n// Hint Explanation Utilities\n// ============================================================================\n\n/** Hint explanation generation utilities for teaching users solving techniques. */\nexport {\n /** Generate a detailed explanation for a hint step based on the technique. */\n generateDetailedExplanation,\n /** Get a short action summary for a hint step (e.g., 'Place 5 in R1C3'). */\n getHintActionSummary,\n} from './utils';\n\n// ============================================================================\n// Localized Hint Utilities\n// ============================================================================\n\n/** Types for hint text localization. */\nexport type {\n /** Translation function compatible with i18next's `t` function. */\n TranslateFunction,\n} from './utils';\n\n/** Hint localization utilities. */\nexport {\n /** Get localized text for a hint step using a translation function. */\n getLocalizedHintText,\n} from './utils';\n\n// ============================================================================\n// i18n Key Utilities\n// ============================================================================\n\n/** Internationalization key generation and localization utilities. */\nexport {\n /** Get i18n key for a belt name (e.g., 'belts.1.name'). */\n getBeltKey,\n /** Get localized belt name using a translation function. */\n getLocalizedBeltName,\n /** Get i18n key for a belt label (e.g., 'belts.1.label'). */\n getBeltLabelKey,\n /** Get localized belt label (e.g., 'White Belt'). */\n getLocalizedBeltLabel,\n /** Get i18n key for a level title (e.g., 'levels.3'). */\n getLevelKey,\n /** Get localized level title using a translation function. */\n getLocalizedLevelTitle,\n /** Get i18n key for a technique name (e.g., 'techniques.full-house.title'). */\n getTechniqueKey,\n /** Get localized technique name using a translation function. */\n getLocalizedTechniqueName,\n} from './utils';\n\n// ============================================================================\n// Digit Display Utilities\n// ============================================================================\n\n/** Digit display format conversion. */\nexport {\n /** Convert a digit (1-9) to its display string based on the format (numeric, kanji, emojis). */\n displayDigit,\n} from './utils';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n // Data hooks\n /** Fetch a single difficulty level by number. */\n useLevel,\n /** Fetch all difficulty levels with sorting and filtering utilities. */\n useLevels,\n /** Fetch a single solving technique by number. */\n useTechnique,\n /** Fetch all solving techniques with grouping utilities. */\n useTechniques,\n /** Fetch learning materials with filtering by technique and language. */\n useLearning,\n /** Fetch a single learning item by UUID. */\n useLearningItem,\n\n /**\n * @deprecated Use `useSudoku` instead. `useGame` uses a legacy 2D array board\n * representation, while `useSudoku` uses a flat 81-cell array consistent with\n * the Kotlin renderable layer and the rest of the codebase.\n */\n useGame,\n\n /** Primary game state hook with flat 81-cell board, pencil mode, and scrambling. */\n useSudoku,\n\n /** Teaching/hint integration with the solver API (legacy GameHint format). */\n useGameTeaching,\n\n /** Fetch a random board for a specific level with auth/subscription handling. */\n useLevelGame,\n /** Fetch today's daily puzzle with auth/subscription handling. */\n useDailyGame,\n\n /** Game timer using refs to avoid re-renders every second. */\n useGameTimer,\n\n /** Persist individual game progress to localStorage. */\n useGamePersistence,\n /** Auto-save game state with debouncing. */\n useAutoSave,\n\n /** Generic typed localStorage hook with SSR safety. */\n useLocalStorage,\n\n /** Solver hint integration matching Kotlin HintInteractor behavior. */\n useHint,\n\n /** Current game management with Zustand store (daily/play slots). */\n useGamePlay,\n\n /** Manual puzzle entry mode with solver validation. */\n useBoardEntry,\n\n /** Server-side game session management for gamification (points, badges). */\n useGameSession,\n} from './hooks';\n\nexport type {\n // Data hook types\n /** Options for useLevel hook. */\n UseLevelOptions,\n /** Result type for useLevel hook. */\n UseLevelResult,\n /** Options for useLevels hook. */\n UseLevelsOptions,\n /** Result type for useLevels hook. */\n UseLevelsResult,\n /** Options for useTechnique hook. */\n UseTechniqueOptions,\n /** Result type for useTechnique hook. */\n UseTechniqueResult,\n /** Options for useTechniques hook. */\n UseTechniquesOptions,\n /** Result type for useTechniques hook. */\n UseTechniquesResult,\n /** Options for useLearningItem hook. */\n UseLearningItemOptions,\n /** Result type for useLearningItem hook. */\n UseLearningItemResult,\n /** Options for useLearning hook. */\n UseLearningOptions,\n /** Result type for useLearning hook. */\n UseLearningResult,\n\n // Game hook types (legacy)\n /** @deprecated Options for legacy useGame hook. Use UseSudokuOptions instead. */\n UseGameOptions,\n /** @deprecated Result type for legacy useGame hook. Use UseSudokuResult instead. */\n UseGameResult,\n\n // Sudoku hook types\n /** Options for useSudoku hook (initial app settings). */\n UseSudokuOptions,\n /** Result type for useSudoku hook (state, computed values, actions, utilities). */\n UseSudokuResult,\n\n // Teaching hook types\n /** Options for useGameTeaching hook (network client, URL, token). */\n UseGameTeachingOptions,\n /** Result type for useGameTeaching hook (teaching state, hint actions). */\n UseGameTeachingResult,\n\n // Game fetching hook types\n /** Options for useLevelGame hook (network, auth, level number). */\n UseLevelGameOptions,\n /** Result type for useLevelGame hook (board data, fetch status). */\n UseLevelGameResult,\n /** Options for useDailyGame hook (network, auth). */\n UseDailyGameOptions,\n /** Result type for useDailyGame hook (daily data, fetch status). */\n UseDailyGameResult,\n /** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'entitlement_required' | 'error'. */\n GameFetchStatus,\n\n // Timer hook types\n /** Options for useGameTimer hook (autoStart, initialTime). */\n UseGameTimerOptions,\n /** Result type for useGameTimer hook (elapsedRef, controls). */\n UseGameTimerResult,\n\n // Persistence hook types\n /** Options for useGamePersistence hook (puzzleKey, autoSave). */\n UseGamePersistenceOptions,\n /** Result type for useGamePersistence hook (load, save, clear, hasSaved). */\n UseGamePersistenceResult,\n\n // Hint hook types\n /** Options for useHint hook (network, puzzle state, technique filter). */\n UseHintOptions,\n /** Result type for useHint hook (hint steps, navigation, apply). */\n UseHintResult,\n /** Board data returned when applying a hint (user input, pencilmarks). */\n HintBoardData,\n /** Data passed to onHintReceived callback (hint, board data, technique info). */\n HintReceivedData,\n /** Access denied error info when hint level exceeds subscription tier. */\n HintAccessError,\n\n // Game play hook types\n /** Options for useGamePlay hook (slot selection, auto-save delay). */\n UseGamePlayOptions,\n /** Result type for useGamePlay hook (current game, start, update, clear). */\n UseGamePlayResult,\n\n // Board entry hook types\n /** Options for useBoardEntry hook (network client, URL, token). */\n UseBoardEntryOptions,\n /** Result type for useBoardEntry hook (cells, validation, actions). */\n UseBoardEntryReturn,\n /** Validated puzzle data from solver (puzzle + solution strings). */\n ValidatedPuzzle,\n\n // Game session hook types\n /** Options for useGameSession hook (network, auth, userId). */\n UseGameSessionOptions,\n /** Result of starting a game session (sessionStarted, sessionId). */\n GameSessionResult,\n /** Result of finishing a game session (leveledUp, badges, points). */\n GameFinishResult,\n} from './hooks';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\n/** Zustand store for current game state with daily/play slots and localStorage persistence. */\nexport { useGamePlayStore } from './stores/gamePlayStore';\n/** State shape for the game play Zustand store. */\nexport type { GamePlayState } from './stores/gamePlayStore';\n\n// ============================================================================\n// Config\n// ============================================================================\n\n/** Authentication provider configuration types. */\nexport type {\n /** Available auth provider types: 'google' | 'apple' | 'email'. */\n AuthProviderType,\n /** Configuration for which auth providers are enabled. */\n AuthProvidersConfig,\n} from './config';\n\n/** Default auth providers configuration (Google + Email, anonymous fallback). */\nexport { DEFAULT_AUTH_PROVIDERS } from './config';\n\n// ============================================================================\n// Entitlement Utilities (re-exported from sudojo_types)\n// ============================================================================\n\n/** Parse a comma-delimited entitlement string into an array. */\nexport { parseEntitlements } from '@sudobility/sudojo_types';\n\n/** Check if a user has the required entitlement for a level. */\nexport { hasRequiredEntitlement } from '@sudobility/sudojo_types';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/sudojo_lib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.105",
|
|
4
4
|
"description": "Business logic library for Sudojo app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"license": "BUSL-1.1",
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@sudobility/di": "^1.5.45",
|
|
50
|
-
"@sudobility/sudojo_client": "^0.0.
|
|
51
|
-
"@sudobility/sudojo_types": "^1.2.
|
|
50
|
+
"@sudobility/sudojo_client": "^0.0.87",
|
|
51
|
+
"@sudobility/sudojo_types": "^1.2.38",
|
|
52
52
|
"@sudobility/types": "^1.9.57",
|
|
53
53
|
"@tanstack/react-query": "^5.90.11",
|
|
54
54
|
"@testing-library/dom": "^10.4.1",
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@sudobility/di": "^1.5.45",
|
|
76
|
-
"@sudobility/sudojo_client": "^0.0.
|
|
77
|
-
"@sudobility/sudojo_types": "^1.2.
|
|
76
|
+
"@sudobility/sudojo_client": "^0.0.87",
|
|
77
|
+
"@sudobility/sudojo_types": "^1.2.38",
|
|
78
78
|
"@sudobility/types": "^1.9.57",
|
|
79
79
|
"@tanstack/react-query": ">=5.0.0",
|
|
80
80
|
"react": ">=18.0.0",
|