@sudobility/sudojo_lib 0.0.201 → 0.0.204
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/adminApi.d.ts +34 -0
- package/dist/admin/adminApi.d.ts.map +1 -0
- package/dist/admin/adminApi.js +59 -0
- package/dist/admin/adminApi.js.map +1 -0
- package/dist/admin/boardRules.d.ts +75 -0
- package/dist/admin/boardRules.d.ts.map +1 -0
- package/dist/admin/boardRules.js +127 -0
- package/dist/admin/boardRules.js.map +1 -0
- package/dist/admin/boardStrings.d.ts +55 -0
- package/dist/admin/boardStrings.d.ts.map +1 -0
- package/dist/admin/boardStrings.js +99 -0
- package/dist/admin/boardStrings.js.map +1 -0
- package/dist/admin/examples.d.ts +58 -0
- package/dist/admin/examples.d.ts.map +1 -0
- package/dist/admin/examples.js +104 -0
- package/dist/admin/examples.js.map +1 -0
- package/dist/admin/extraction.d.ts +87 -0
- package/dist/admin/extraction.d.ts.map +1 -0
- package/dist/admin/extraction.js +141 -0
- package/dist/admin/extraction.js.map +1 -0
- package/dist/admin/index.d.ts +32 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +22 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/jobs.d.ts +108 -0
- package/dist/admin/jobs.d.ts.map +1 -0
- package/dist/admin/jobs.js +435 -0
- package/dist/admin/jobs.js.map +1 -0
- package/dist/admin/regenerateHints.d.ts +16 -0
- package/dist/admin/regenerateHints.d.ts.map +1 -0
- package/dist/admin/regenerateHints.js +43 -0
- package/dist/admin/regenerateHints.js.map +1 -0
- package/dist/admin/types.d.ts +42 -0
- package/dist/admin/types.d.ts.map +1 -0
- package/dist/admin/types.js +21 -0
- package/dist/admin/types.js.map +1 -0
- package/dist/admin/useAdminJob.d.ts +28 -0
- package/dist/admin/useAdminJob.d.ts.map +1 -0
- package/dist/admin/useAdminJob.js +99 -0
- package/dist/admin/useAdminJob.js.map +1 -0
- package/dist/admin/useAdminStats.d.ts +46 -0
- package/dist/admin/useAdminStats.d.ts.map +1 -0
- package/dist/admin/useAdminStats.js +91 -0
- package/dist/admin/useAdminStats.js.map +1 -0
- package/dist/admin/useBoardGenerator.d.ts +29 -0
- package/dist/admin/useBoardGenerator.d.ts.map +1 -0
- package/dist/admin/useBoardGenerator.js +38 -0
- package/dist/admin/useBoardGenerator.js.map +1 -0
- package/dist/admin/useBoardTechniquesUpdater.d.ts +14 -0
- package/dist/admin/useBoardTechniquesUpdater.d.ts.map +1 -0
- package/dist/admin/useBoardTechniquesUpdater.js +28 -0
- package/dist/admin/useBoardTechniquesUpdater.js.map +1 -0
- package/dist/admin/useExampleCreator.d.ts +29 -0
- package/dist/admin/useExampleCreator.d.ts.map +1 -0
- package/dist/admin/useExampleCreator.js +58 -0
- package/dist/admin/useExampleCreator.js.map +1 -0
- package/dist/admin/useSingleBoardExtractor.d.ts +18 -0
- package/dist/admin/useSingleBoardExtractor.d.ts.map +1 -0
- package/dist/admin/useSingleBoardExtractor.js +19 -0
- package/dist/admin/useSingleBoardExtractor.js.map +1 -0
- package/dist/admin/useTechniqueExtractor.d.ts +26 -0
- package/dist/admin/useTechniqueExtractor.d.ts.map +1 -0
- package/dist/admin/useTechniqueExtractor.js +37 -0
- package/dist/admin/useTechniqueExtractor.js.map +1 -0
- package/dist/context/SudojoApiContext.d.ts +58 -0
- package/dist/context/SudojoApiContext.d.ts.map +1 -0
- package/dist/context/SudojoApiContext.js +52 -0
- package/dist/context/SudojoApiContext.js.map +1 -0
- package/dist/context/SudojoApiProvider.d.ts +21 -0
- package/dist/context/SudojoApiProvider.d.ts.map +1 -0
- package/dist/context/SudojoApiProvider.js +15 -0
- package/dist/context/SudojoApiProvider.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +2 -0
- package/dist/context/index.js.map +1 -1
- package/dist/hooks/index.d.ts +24 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +22 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useBoardEntry.d.ts +68 -5
- package/dist/hooks/useBoardEntry.d.ts.map +1 -1
- package/dist/hooks/useBoardEntry.js +113 -27
- package/dist/hooks/useBoardEntry.js.map +1 -1
- package/dist/hooks/useBoardScan.d.ts +27 -0
- package/dist/hooks/useBoardScan.d.ts.map +1 -0
- package/dist/hooks/useBoardScan.js +27 -0
- package/dist/hooks/useBoardScan.js.map +1 -0
- package/dist/hooks/useCommunities.d.ts +6 -4
- package/dist/hooks/useCommunities.d.ts.map +1 -1
- package/dist/hooks/useCommunities.js +6 -1
- package/dist/hooks/useCommunities.js.map +1 -1
- package/dist/hooks/useCompletionTrigger.d.ts +23 -0
- package/dist/hooks/useCompletionTrigger.d.ts.map +1 -0
- package/dist/hooks/useCompletionTrigger.js +39 -0
- package/dist/hooks/useCompletionTrigger.js.map +1 -0
- package/dist/hooks/useDailyGame.d.ts +11 -6
- package/dist/hooks/useDailyGame.d.ts.map +1 -1
- package/dist/hooks/useDailyGame.js +20 -61
- package/dist/hooks/useDailyGame.js.map +1 -1
- package/dist/hooks/useDeleteAccount.d.ts +72 -0
- package/dist/hooks/useDeleteAccount.d.ts.map +1 -0
- package/dist/hooks/useDeleteAccount.js +71 -0
- package/dist/hooks/useDeleteAccount.js.map +1 -0
- package/dist/hooks/useEnteredGameSession.d.ts +73 -0
- package/dist/hooks/useEnteredGameSession.d.ts.map +1 -0
- package/dist/hooks/useEnteredGameSession.js +155 -0
- package/dist/hooks/useEnteredGameSession.js.map +1 -0
- package/dist/hooks/useGameSession.d.ts +8 -4
- package/dist/hooks/useGameSession.d.ts.map +1 -1
- package/dist/hooks/useGameSession.js +4 -1
- package/dist/hooks/useGameSession.js.map +1 -1
- package/dist/hooks/useGameTeaching.d.ts.map +1 -1
- package/dist/hooks/useGameTeaching.js +11 -13
- package/dist/hooks/useGameTeaching.js.map +1 -1
- package/dist/hooks/useHint.d.ts +7 -7
- package/dist/hooks/useHint.d.ts.map +1 -1
- package/dist/hooks/useHint.js +18 -9
- package/dist/hooks/useHint.js.map +1 -1
- package/dist/hooks/useIsSiteAdmin.d.ts +39 -0
- package/dist/hooks/useIsSiteAdmin.d.ts.map +1 -0
- package/dist/hooks/useIsSiteAdmin.js +31 -0
- package/dist/hooks/useIsSiteAdmin.js.map +1 -0
- package/dist/hooks/useLearning.d.ts +8 -8
- package/dist/hooks/useLearning.d.ts.map +1 -1
- package/dist/hooks/useLearning.js +5 -2
- package/dist/hooks/useLearning.js.map +1 -1
- package/dist/hooks/useLevelGame.d.ts +7 -7
- package/dist/hooks/useLevelGame.d.ts.map +1 -1
- package/dist/hooks/useLevelGame.js +13 -49
- package/dist/hooks/useLevelGame.js.map +1 -1
- package/dist/hooks/useLevels.d.ts +8 -8
- package/dist/hooks/useLevels.d.ts.map +1 -1
- package/dist/hooks/useLevels.js +7 -3
- package/dist/hooks/useLevels.js.map +1 -1
- package/dist/hooks/usePracticeGame.d.ts +53 -0
- package/dist/hooks/usePracticeGame.d.ts.map +1 -0
- package/dist/hooks/usePracticeGame.js +72 -0
- package/dist/hooks/usePracticeGame.js.map +1 -0
- package/dist/hooks/usePuzzleDistribution.d.ts +2 -0
- package/dist/hooks/usePuzzleDistribution.d.ts.map +1 -1
- package/dist/hooks/usePuzzleDistribution.js +4 -14
- package/dist/hooks/usePuzzleDistribution.js.map +1 -1
- package/dist/hooks/usePuzzleProgress.d.ts +37 -0
- package/dist/hooks/usePuzzleProgress.d.ts.map +1 -0
- package/dist/hooks/usePuzzleProgress.js +48 -0
- package/dist/hooks/usePuzzleProgress.js.map +1 -0
- package/dist/hooks/usePuzzleSession.d.ts +215 -0
- package/dist/hooks/usePuzzleSession.d.ts.map +1 -0
- package/dist/hooks/usePuzzleSession.js +358 -0
- package/dist/hooks/usePuzzleSession.js.map +1 -0
- package/dist/hooks/useResumeGame.d.ts +70 -0
- package/dist/hooks/useResumeGame.d.ts.map +1 -0
- package/dist/hooks/useResumeGame.js +123 -0
- package/dist/hooks/useResumeGame.js.map +1 -0
- package/dist/hooks/useStrategies.d.ts +39 -0
- package/dist/hooks/useStrategies.d.ts.map +1 -0
- package/dist/hooks/useStrategies.js +34 -0
- package/dist/hooks/useStrategies.js.map +1 -0
- package/dist/hooks/useSudoku.d.ts +5 -0
- package/dist/hooks/useSudoku.d.ts.map +1 -1
- package/dist/hooks/useSudoku.js +7 -1
- package/dist/hooks/useSudoku.js.map +1 -1
- package/dist/hooks/useTechniqueByPath.d.ts +46 -0
- package/dist/hooks/useTechniqueByPath.d.ts.map +1 -0
- package/dist/hooks/useTechniqueByPath.js +47 -0
- package/dist/hooks/useTechniqueByPath.js.map +1 -0
- package/dist/hooks/useTechniqueExample.d.ts +60 -0
- package/dist/hooks/useTechniqueExample.d.ts.map +1 -0
- package/dist/hooks/useTechniqueExample.js +63 -0
- package/dist/hooks/useTechniqueExample.js.map +1 -0
- package/dist/hooks/useTechniques.d.ts +8 -8
- package/dist/hooks/useTechniques.d.ts.map +1 -1
- package/dist/hooks/useTechniques.js +9 -21
- package/dist/hooks/useTechniques.js.map +1 -1
- package/dist/index.d.ts +418 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +276 -10
- package/dist/index.js.map +1 -1
- package/dist/types/currentGame.d.ts +9 -1
- package/dist/types/currentGame.d.ts.map +1 -1
- package/dist/types/currentGame.js.map +1 -1
- package/dist/utils/auth.d.ts +6 -0
- package/dist/utils/auth.d.ts.map +1 -1
- package/dist/utils/auth.js +8 -0
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/community.d.ts +64 -0
- package/dist/utils/community.d.ts.map +1 -0
- package/dist/utils/community.js +66 -0
- package/dist/utils/community.js.map +1 -0
- package/dist/utils/date.d.ts +37 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +68 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/entityTranslate.d.ts +120 -0
- package/dist/utils/entityTranslate.d.ts.map +1 -0
- package/dist/utils/entityTranslate.js +146 -0
- package/dist/utils/entityTranslate.js.map +1 -0
- package/dist/utils/gameFetchStatus.d.ts +74 -0
- package/dist/utils/gameFetchStatus.d.ts.map +1 -0
- package/dist/utils/gameFetchStatus.js +118 -0
- package/dist/utils/gameFetchStatus.js.map +1 -0
- package/dist/utils/gamification.d.ts +36 -0
- package/dist/utils/gamification.d.ts.map +1 -0
- package/dist/utils/gamification.js +33 -0
- package/dist/utils/gamification.js.map +1 -0
- package/dist/utils/hintAccess.d.ts +64 -0
- package/dist/utils/hintAccess.d.ts.map +1 -0
- package/dist/utils/hintAccess.js +57 -0
- package/dist/utils/hintAccess.js.map +1 -0
- package/dist/utils/index.d.ts +31 -10
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +20 -9
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/language.d.ts +123 -0
- package/dist/utils/language.d.ts.map +1 -0
- package/dist/utils/language.js +95 -0
- package/dist/utils/language.js.map +1 -0
- package/dist/utils/localizedHint.d.ts +60 -0
- package/dist/utils/localizedHint.d.ts.map +1 -1
- package/dist/utils/localizedHint.js +90 -0
- package/dist/utils/localizedHint.js.map +1 -1
- package/dist/utils/progress.d.ts +10 -1
- package/dist/utils/progress.d.ts.map +1 -1
- package/dist/utils/progress.js +24 -0
- package/dist/utils/progress.js.map +1 -1
- package/dist/utils/scannedBoard.d.ts +88 -0
- package/dist/utils/scannedBoard.d.ts.map +1 -0
- package/dist/utils/scannedBoard.js +101 -0
- package/dist/utils/scannedBoard.js.map +1 -0
- package/dist/utils/shareUrl.d.ts +38 -15
- package/dist/utils/shareUrl.d.ts.map +1 -1
- package/dist/utils/shareUrl.js +75 -26
- package/dist/utils/shareUrl.js.map +1 -1
- package/dist/utils/subscription.d.ts +118 -0
- package/dist/utils/subscription.d.ts.map +1 -1
- package/dist/utils/subscription.js +212 -0
- package/dist/utils/subscription.js.map +1 -1
- package/dist/utils/sudokuPresenter.d.ts +42 -0
- package/dist/utils/sudokuPresenter.d.ts.map +1 -1
- package/dist/utils/sudokuPresenter.js +114 -1
- package/dist/utils/sudokuPresenter.js.map +1 -1
- package/dist/utils/sudokuScrambler.d.ts +8 -0
- package/dist/utils/sudokuScrambler.d.ts.map +1 -1
- package/dist/utils/sudokuScrambler.js +12 -0
- package/dist/utils/sudokuScrambler.js.map +1 -1
- package/dist/utils/technique.d.ts +112 -1
- package/dist/utils/technique.d.ts.map +1 -1
- package/dist/utils/technique.js +293 -1
- package/dist/utils/technique.js.map +1 -1
- package/dist/utils/techniqueBitmask.d.ts +31 -0
- package/dist/utils/techniqueBitmask.d.ts.map +1 -0
- package/dist/utils/techniqueBitmask.js +53 -0
- package/dist/utils/techniqueBitmask.js.map +1 -0
- package/dist/utils/techniqueExample.d.ts +42 -0
- package/dist/utils/techniqueExample.d.ts.map +1 -0
- package/dist/utils/techniqueExample.js +57 -0
- package/dist/utils/techniqueExample.js.map +1 -0
- package/dist/utils/theme.d.ts +2 -0
- package/dist/utils/theme.d.ts.map +1 -1
- package/dist/utils/theme.js +2 -0
- package/dist/utils/theme.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hint access gating (client side).
|
|
3
|
+
*
|
|
4
|
+
* The API serves every hint step to everyone (sudojo_api removed its hint
|
|
5
|
+
* tiers), so gating happens in useHint: without the level's entitlement only
|
|
6
|
+
* the first FREE_HINT_STEP_LIMIT steps are visible and `accessError` is set.
|
|
7
|
+
*/
|
|
8
|
+
import type { HintAccessUserState } from '@sudobility/sudojo_types';
|
|
9
|
+
/** Number of hint steps shown for free before the paywall. */
|
|
10
|
+
export declare const FREE_HINT_STEP_LIMIT = 2;
|
|
11
|
+
/** What the hint-access panel's button does. */
|
|
12
|
+
export type HintAccessAction =
|
|
13
|
+
/** Open sign-in over the game, then dismiss the panel */
|
|
14
|
+
'sign_in'
|
|
15
|
+
/** Go to the subscription screen */
|
|
16
|
+
| 'subscribe'
|
|
17
|
+
/** Nothing to offer: just close the panel */
|
|
18
|
+
| 'dismiss';
|
|
19
|
+
/** Which message the hint-access panel shows. */
|
|
20
|
+
export type HintAccessVariant = 'login' | 'subscription' | 'upgrade' | 'unavailable';
|
|
21
|
+
/** Panel behavior for one access state. */
|
|
22
|
+
export interface HintAccessPresentation {
|
|
23
|
+
action: HintAccessAction;
|
|
24
|
+
variant: HintAccessVariant;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Map a hint access state to the panel's action and message variant, as the
|
|
28
|
+
* web and RN HintAccessPanel do:
|
|
29
|
+
*
|
|
30
|
+
* - `anonymous` → sign in (`login` message)
|
|
31
|
+
* - `no_subscription` → subscribe (`subscription` message)
|
|
32
|
+
* - `insufficient_tier` → subscribe (`upgrade` message)
|
|
33
|
+
* - anything else → dismiss (`unavailable` message)
|
|
34
|
+
*
|
|
35
|
+
* Note: useHint's client-side gate only produces `no_subscription` and
|
|
36
|
+
* `insufficient_tier`. `anonymous` came from the API's 402, which it no
|
|
37
|
+
* longer sends.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getHintAccessAction(state: {
|
|
40
|
+
userState?: HintAccessUserState | string | null;
|
|
41
|
+
} | null | undefined): HintAccessPresentation;
|
|
42
|
+
/**
|
|
43
|
+
* i18n key suffixes for each message variant except `unavailable`, which the
|
|
44
|
+
* apps word differently. Both apps use these suffixes under their own prefix
|
|
45
|
+
* (web `game.hint.access.`, RN `game.hintAccess.`).
|
|
46
|
+
*/
|
|
47
|
+
export declare const HINT_ACCESS_KEY_SUFFIXES: {
|
|
48
|
+
readonly login: {
|
|
49
|
+
readonly title: "loginRequired";
|
|
50
|
+
readonly message: "loginMessage";
|
|
51
|
+
readonly button: "loginButton";
|
|
52
|
+
};
|
|
53
|
+
readonly subscription: {
|
|
54
|
+
readonly title: "subscriptionRequired";
|
|
55
|
+
readonly message: "subscriptionMessage";
|
|
56
|
+
readonly button: "subscribeButton";
|
|
57
|
+
};
|
|
58
|
+
readonly upgrade: {
|
|
59
|
+
readonly title: "upgradeRequired";
|
|
60
|
+
readonly message: "upgradeMessage";
|
|
61
|
+
readonly button: "upgradeButton";
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=hintAccess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hintAccess.d.ts","sourceRoot":"","sources":["../../src/utils/hintAccess.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,8DAA8D;AAC9D,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,gDAAgD;AAChD,MAAM,MAAM,gBAAgB;AAC1B,yDAAyD;AACvD,SAAS;AACX,oCAAoC;GAClC,WAAW;AACb,6CAA6C;GAC3C,SAAS,CAAC;AAEd,iDAAiD;AACjD,MAAM,MAAM,iBAAiB,GACzB,OAAO,GACP,cAAc,GACd,SAAS,GACT,aAAa,CAAC;AAElB,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAC5E,sBAAsB,CAWxB;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;CAgB3B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hint access gating (client side).
|
|
3
|
+
*
|
|
4
|
+
* The API serves every hint step to everyone (sudojo_api removed its hint
|
|
5
|
+
* tiers), so gating happens in useHint: without the level's entitlement only
|
|
6
|
+
* the first FREE_HINT_STEP_LIMIT steps are visible and `accessError` is set.
|
|
7
|
+
*/
|
|
8
|
+
/** Number of hint steps shown for free before the paywall. */
|
|
9
|
+
export const FREE_HINT_STEP_LIMIT = 2;
|
|
10
|
+
/**
|
|
11
|
+
* Map a hint access state to the panel's action and message variant, as the
|
|
12
|
+
* web and RN HintAccessPanel do:
|
|
13
|
+
*
|
|
14
|
+
* - `anonymous` → sign in (`login` message)
|
|
15
|
+
* - `no_subscription` → subscribe (`subscription` message)
|
|
16
|
+
* - `insufficient_tier` → subscribe (`upgrade` message)
|
|
17
|
+
* - anything else → dismiss (`unavailable` message)
|
|
18
|
+
*
|
|
19
|
+
* Note: useHint's client-side gate only produces `no_subscription` and
|
|
20
|
+
* `insufficient_tier`. `anonymous` came from the API's 402, which it no
|
|
21
|
+
* longer sends.
|
|
22
|
+
*/
|
|
23
|
+
export function getHintAccessAction(state) {
|
|
24
|
+
switch (state?.userState) {
|
|
25
|
+
case 'anonymous':
|
|
26
|
+
return { action: 'sign_in', variant: 'login' };
|
|
27
|
+
case 'no_subscription':
|
|
28
|
+
return { action: 'subscribe', variant: 'subscription' };
|
|
29
|
+
case 'insufficient_tier':
|
|
30
|
+
return { action: 'subscribe', variant: 'upgrade' };
|
|
31
|
+
default:
|
|
32
|
+
return { action: 'dismiss', variant: 'unavailable' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* i18n key suffixes for each message variant except `unavailable`, which the
|
|
37
|
+
* apps word differently. Both apps use these suffixes under their own prefix
|
|
38
|
+
* (web `game.hint.access.`, RN `game.hintAccess.`).
|
|
39
|
+
*/
|
|
40
|
+
export const HINT_ACCESS_KEY_SUFFIXES = {
|
|
41
|
+
login: {
|
|
42
|
+
title: 'loginRequired',
|
|
43
|
+
message: 'loginMessage',
|
|
44
|
+
button: 'loginButton',
|
|
45
|
+
},
|
|
46
|
+
subscription: {
|
|
47
|
+
title: 'subscriptionRequired',
|
|
48
|
+
message: 'subscriptionMessage',
|
|
49
|
+
button: 'subscribeButton',
|
|
50
|
+
},
|
|
51
|
+
upgrade: {
|
|
52
|
+
title: 'upgradeRequired',
|
|
53
|
+
message: 'upgradeMessage',
|
|
54
|
+
button: 'upgradeButton',
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=hintAccess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hintAccess.js","sourceRoot":"","sources":["../../src/utils/hintAccess.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAwBtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA6E;IAE7E,QAAQ,KAAK,EAAE,SAAS,EAAE,CAAC;QACzB,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACjD,KAAK,iBAAiB;YACpB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1D,KAAK,mBAAmB;YACtB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QACrD;YACE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,KAAK,EAAE;QACL,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,cAAc;QACvB,MAAM,EAAE,aAAa;KACtB;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,sBAAsB;QAC7B,OAAO,EAAE,qBAAqB;QAC9B,MAAM,EAAE,iBAAiB;KAC1B;IACD,OAAO,EAAE;QACP,KAAK,EAAE,iBAAiB;QACxB,OAAO,EAAE,gBAAgB;QACzB,MAAM,EAAE,eAAe;KACxB;CACO,CAAC","sourcesContent":["/**\n * Hint access gating (client side).\n *\n * The API serves every hint step to everyone (sudojo_api removed its hint\n * tiers), so gating happens in useHint: without the level's entitlement only\n * the first FREE_HINT_STEP_LIMIT steps are visible and `accessError` is set.\n */\n\nimport type { HintAccessUserState } from '@sudobility/sudojo_types';\n\n/** Number of hint steps shown for free before the paywall. */\nexport const FREE_HINT_STEP_LIMIT = 2;\n\n/** What the hint-access panel's button does. */\nexport type HintAccessAction =\n /** Open sign-in over the game, then dismiss the panel */\n | 'sign_in'\n /** Go to the subscription screen */\n | 'subscribe'\n /** Nothing to offer: just close the panel */\n | 'dismiss';\n\n/** Which message the hint-access panel shows. */\nexport type HintAccessVariant =\n | 'login'\n | 'subscription'\n | 'upgrade'\n | 'unavailable';\n\n/** Panel behavior for one access state. */\nexport interface HintAccessPresentation {\n action: HintAccessAction;\n variant: HintAccessVariant;\n}\n\n/**\n * Map a hint access state to the panel's action and message variant, as the\n * web and RN HintAccessPanel do:\n *\n * - `anonymous` → sign in (`login` message)\n * - `no_subscription` → subscribe (`subscription` message)\n * - `insufficient_tier` → subscribe (`upgrade` message)\n * - anything else → dismiss (`unavailable` message)\n *\n * Note: useHint's client-side gate only produces `no_subscription` and\n * `insufficient_tier`. `anonymous` came from the API's 402, which it no\n * longer sends.\n */\nexport function getHintAccessAction(\n state: { userState?: HintAccessUserState | string | null } | null | undefined\n): HintAccessPresentation {\n switch (state?.userState) {\n case 'anonymous':\n return { action: 'sign_in', variant: 'login' };\n case 'no_subscription':\n return { action: 'subscribe', variant: 'subscription' };\n case 'insufficient_tier':\n return { action: 'subscribe', variant: 'upgrade' };\n default:\n return { action: 'dismiss', variant: 'unavailable' };\n }\n}\n\n/**\n * i18n key suffixes for each message variant except `unavailable`, which the\n * apps word differently. Both apps use these suffixes under their own prefix\n * (web `game.hint.access.`, RN `game.hintAccess.`).\n */\nexport const HINT_ACCESS_KEY_SUFFIXES = {\n login: {\n title: 'loginRequired',\n message: 'loginMessage',\n button: 'loginButton',\n },\n subscription: {\n title: 'subscriptionRequired',\n message: 'subscriptionMessage',\n button: 'subscribeButton',\n },\n upgrade: {\n title: 'upgradeRequired',\n message: 'upgradeMessage',\n button: 'upgradeButton',\n },\n} as const;\n"]}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -4,24 +4,45 @@
|
|
|
4
4
|
export { cloneBoard, countFilledCells, createGameBoard, getBlockCells, getBlockIndex, getBoardStateString, getColumnCells, getEmptyCells, getPencilmarksString, getRelatedCells, getRowCells, isValidPlacement, } from './board';
|
|
5
5
|
export { autoRemovePencilmarks, clearHighlights, countMistakes, getIncorrectCells, getProgressPercentage, isBoardFilled, isCellCorrect, isGameComplete, isValueCorrect, updateCellErrors, updateCellHighlights, validateGameState, } from './validation';
|
|
6
6
|
export type { ScramblerProtocol, ScrambleResult as SudokuScrambleResult, } from './sudokuScrambler';
|
|
7
|
-
export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, } from './sudokuScrambler';
|
|
7
|
+
export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, cellsToSolutionString, countClues, } from './sudokuScrambler';
|
|
8
8
|
export type { PresentBoardOptions } from './sudokuPresenter';
|
|
9
|
-
export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, convertSolverLink, convertSolverCellGroup, sudokuColorToTheme, } from './sudokuPresenter';
|
|
9
|
+
export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, convertSolverLink, convertSolverCellGroup, sudokuColorToTheme, solverColorToSudokuColor, parseHintDigits, convertSolverHintStep, isConflictHintStep, } from './sudokuPresenter';
|
|
10
10
|
export { formatTime, parseTime } from './time';
|
|
11
|
-
export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, } from './progress';
|
|
11
|
+
export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, applyPuzzleCompletion, } from './progress';
|
|
12
|
+
export type { PuzzleCompletion } from './progress';
|
|
12
13
|
export type { ThemePreference, ResolvedTheme } from './theme';
|
|
13
|
-
export { THEME_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
|
|
14
|
-
export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, } from './subscription';
|
|
15
|
-
export {
|
|
14
|
+
export { THEME_STORAGE_KEY, FONT_SIZE_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
|
|
15
|
+
export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, getPeriodLabelKey, getPeriodLabel, isBestValueProduct, subscriptionPeriodToMonths, calculateSavingsPercent, isCrossPlatformSubscription, canDeleteAccount, getPuzzleDistribution, selectSavingsBasePlan, getPlanSavingsPercent, } from './subscription';
|
|
16
|
+
export type { PricedPeriod, PaywallPlan, DeleteAccountBlocker, DeleteAccountCheck, } from './subscription';
|
|
17
|
+
export type { TechniqueSlug, StrategySlug, StrategyDifficultyTier, StrategySection, TechniqueContent, } from './technique';
|
|
18
|
+
export { getTechniqueIconUrl, toCanonicalTechniquePath, toApiTechniquePath, isSameTechniquePath, findTechniqueByPath, parseTechniqueDependencies, getTechniqueDependencies, getDependentTechniques, sortTechniquesByLevel, groupTechniquesByLevel, getTechniquesForStrategy, findStrategyByStub, TECHNIQUE_SLUGS, STRATEGY_SLUGS, getStrategyDifficultyTier, getStrategyDifficultyKey, getStrategySections, parseTechniqueContent, } from './technique';
|
|
19
|
+
export { exactTechniqueBitmask, techniqueBitmaskString, techniqueFieldsOf, } from './techniqueBitmask';
|
|
16
20
|
export type { WalkthroughStep } from './techniqueWalkthrough';
|
|
17
21
|
export { parsePencilmarksString, pencilmarksToString, parsePracticeBoard, cloneSudokuBoard, applyHintStep, parseHintData, localizeHintStep, buildWalkthroughSteps, } from './techniqueWalkthrough';
|
|
18
22
|
export { generateDetailedExplanation, getHintActionSummary, } from './hintExplanation';
|
|
19
|
-
export type { TranslateFunction } from './localizedHint';
|
|
20
|
-
export { getLocalizedHintText, getLocalizedHintTitle, localizedField, } from './localizedHint';
|
|
23
|
+
export type { TranslateFunction, HintHeadingTree, LocalizedHintHelpers, } from './localizedHint';
|
|
24
|
+
export { getLocalizedHintText, getLocalizedHintTitle, localizedField, HINT_HEADING_KEY_PREFIX, getStepHeadingLocalization, getLocalizedHintHeading, interpolateHintValues, getStepHeadingFromTree, createLocalizedHintHelpers, } from './localizedHint';
|
|
25
|
+
export type { LevelDisplaySource, TechniqueDisplaySource, StrategyDisplaySource, } from './entityTranslate';
|
|
26
|
+
export { createNamespacedTranslate, getLevelDisplayTitle, getLevelDisplayText, getTechniqueDisplayTitle, getBeltDisplayName, getBeltDisplayLabel, getStrategyDisplayTitle, } from './entityTranslate';
|
|
21
27
|
export { getBeltKey, getLocalizedBeltName, getBeltLabelKey, getLocalizedBeltLabel, getLevelKey, getLocalizedLevelTitle, getTechniqueKey, getLocalizedTechniqueName, } from './i18nKeys';
|
|
22
28
|
export { displayDigit } from './digitDisplay';
|
|
23
|
-
export type {
|
|
29
|
+
export type { ScannedBoard, ScanBoardErrorCode } from './scannedBoard';
|
|
30
|
+
export { MIN_SCAN_CLUES, ScanBoardError, toScannedBoard, hasScannedInput, scannedBoardFromResponse, } from './scannedBoard';
|
|
31
|
+
export type { ShareUrlParams, ParsedShareParams, ShareUrlType, ShareParamsSource, } from './shareUrl';
|
|
24
32
|
export { buildShareUrl, parseShareParams, getWebUrl } from './shareUrl';
|
|
25
33
|
export type { AuthUser } from './auth';
|
|
26
|
-
export { isAuthenticatedUser } from './auth';
|
|
34
|
+
export { isAuthenticatedUser, isRealUser } from './auth';
|
|
35
|
+
export type { SupportedLanguageInfo, SupportedLanguageCode } from './language';
|
|
36
|
+
export { SUPPORTED_LANGUAGES, SUPPORTED_LANGUAGE_CODES, DEFAULT_LANGUAGE, LANGUAGE_STORAGE_KEY, NATIVE_LANGUAGE_STORAGE_KEY, isSupportedLanguage, normalizeLanguageCode, resolveLanguage, toLanguageTag, getLanguageNativeName, } from './language';
|
|
37
|
+
export type { CommunityPlatformInfo } from './community';
|
|
38
|
+
export { COMMUNITY_PLATFORMS, getCommunityPlatform, sortCommunityPlatforms, } from './community';
|
|
39
|
+
export type { BadgeProgress, BadgeDefinitionLike } from './gamification';
|
|
40
|
+
export { LEVEL_MASTERY_BADGE_TYPE, GAMES_PLAYED_BADGE_TYPE, groupBadgeProgress, } from './gamification';
|
|
41
|
+
export type { HintAccessAction, HintAccessVariant, HintAccessPresentation, } from './hintAccess';
|
|
42
|
+
export { FREE_HINT_STEP_LIMIT, getHintAccessAction, HINT_ACCESS_KEY_SUFFIXES, } from './hintAccess';
|
|
43
|
+
export { getUtcDateString, normalizeDailyDate, formatDailyDate, isStaleDaily, } from './date';
|
|
44
|
+
export type { GameFetchResponse, PracticeFetchStatus } from './gameFetchStatus';
|
|
45
|
+
export { isAuthRequiredResponse, isSubscriptionRequiredResponse, getGameFetchStatus, getErrorHttpStatus, getPracticeFetchStatus, } from './gameFetchStatus';
|
|
46
|
+
export type { TechniqueExampleSource, TechniqueWalkthroughTranslations, TechniqueWalkthrough, } from './techniqueExample';
|
|
47
|
+
export { buildTechniqueWalkthrough } from './techniqueExample';
|
|
27
48
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,iBAAiB,EACjB,cAAc,IAAI,oBAAoB,GACvC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,IAAI,mBAAmB,EACpC,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/index.js
CHANGED
|
@@ -5,25 +5,36 @@
|
|
|
5
5
|
export { cloneBoard, countFilledCells, createGameBoard, getBlockCells, getBlockIndex, getBoardStateString, getColumnCells, getEmptyCells, getPencilmarksString, getRelatedCells, getRowCells, isValidPlacement, } from './board';
|
|
6
6
|
// Validation utilities (legacy - for useGame hook)
|
|
7
7
|
export { autoRemovePencilmarks, clearHighlights, countMistakes, getIncorrectCells, getProgressPercentage, isBoardFilled, isCellCorrect, isGameComplete, isValueCorrect, updateCellErrors, updateCellHighlights, validateGameState, } from './validation';
|
|
8
|
-
export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, } from './sudokuScrambler';
|
|
9
|
-
export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, convertSolverLink, convertSolverCellGroup, sudokuColorToTheme, } from './sudokuPresenter';
|
|
8
|
+
export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, cellsToSolutionString, countClues, } from './sudokuScrambler';
|
|
9
|
+
export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, convertSolverLink, convertSolverCellGroup, sudokuColorToTheme, solverColorToSudokuColor, parseHintDigits, convertSolverHintStep, isConflictHintStep, } from './sudokuPresenter';
|
|
10
10
|
// Time utilities
|
|
11
11
|
export { formatTime, parseTime } from './time';
|
|
12
12
|
// Progress utilities
|
|
13
|
-
export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, } from './progress';
|
|
14
|
-
export { THEME_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
|
|
13
|
+
export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, applyPuzzleCompletion, } from './progress';
|
|
14
|
+
export { THEME_STORAGE_KEY, FONT_SIZE_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
|
|
15
15
|
// Subscription utilities
|
|
16
|
-
export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, } from './subscription';
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, getPeriodLabelKey, getPeriodLabel, isBestValueProduct, subscriptionPeriodToMonths, calculateSavingsPercent, isCrossPlatformSubscription, canDeleteAccount, getPuzzleDistribution, selectSavingsBasePlan, getPlanSavingsPercent, } from './subscription';
|
|
17
|
+
export { getTechniqueIconUrl, toCanonicalTechniquePath, toApiTechniquePath, isSameTechniquePath, findTechniqueByPath, parseTechniqueDependencies, getTechniqueDependencies, getDependentTechniques, sortTechniquesByLevel, groupTechniquesByLevel, getTechniquesForStrategy, findStrategyByStub, TECHNIQUE_SLUGS, STRATEGY_SLUGS, getStrategyDifficultyTier, getStrategyDifficultyKey, getStrategySections, parseTechniqueContent, } from './technique';
|
|
18
|
+
// Technique bitmask utilities
|
|
19
|
+
export { exactTechniqueBitmask, techniqueBitmaskString, techniqueFieldsOf, } from './techniqueBitmask';
|
|
19
20
|
export { parsePencilmarksString, pencilmarksToString, parsePracticeBoard, cloneSudokuBoard, applyHintStep, parseHintData, localizeHintStep, buildWalkthroughSteps, } from './techniqueWalkthrough';
|
|
20
21
|
// Hint explanation utilities
|
|
21
22
|
export { generateDetailedExplanation, getHintActionSummary, } from './hintExplanation';
|
|
22
|
-
export { getLocalizedHintText, getLocalizedHintTitle, localizedField, } from './localizedHint';
|
|
23
|
+
export { getLocalizedHintText, getLocalizedHintTitle, localizedField, HINT_HEADING_KEY_PREFIX, getStepHeadingLocalization, getLocalizedHintHeading, interpolateHintValues, getStepHeadingFromTree, createLocalizedHintHelpers, } from './localizedHint';
|
|
24
|
+
export { createNamespacedTranslate, getLevelDisplayTitle, getLevelDisplayText, getTechniqueDisplayTitle, getBeltDisplayName, getBeltDisplayLabel, getStrategyDisplayTitle, } from './entityTranslate';
|
|
23
25
|
// i18n key utilities
|
|
24
26
|
export { getBeltKey, getLocalizedBeltName, getBeltLabelKey, getLocalizedBeltLabel, getLevelKey, getLocalizedLevelTitle, getTechniqueKey, getLocalizedTechniqueName, } from './i18nKeys';
|
|
25
27
|
// Digit display utilities
|
|
26
28
|
export { displayDigit } from './digitDisplay';
|
|
29
|
+
export { MIN_SCAN_CLUES, ScanBoardError, toScannedBoard, hasScannedInput, scannedBoardFromResponse, } from './scannedBoard';
|
|
27
30
|
export { buildShareUrl, parseShareParams, getWebUrl } from './shareUrl';
|
|
28
|
-
export { isAuthenticatedUser } from './auth';
|
|
31
|
+
export { isAuthenticatedUser, isRealUser } from './auth';
|
|
32
|
+
export { SUPPORTED_LANGUAGES, SUPPORTED_LANGUAGE_CODES, DEFAULT_LANGUAGE, LANGUAGE_STORAGE_KEY, NATIVE_LANGUAGE_STORAGE_KEY, isSupportedLanguage, normalizeLanguageCode, resolveLanguage, toLanguageTag, getLanguageNativeName, } from './language';
|
|
33
|
+
export { COMMUNITY_PLATFORMS, getCommunityPlatform, sortCommunityPlatforms, } from './community';
|
|
34
|
+
export { LEVEL_MASTERY_BADGE_TYPE, GAMES_PLAYED_BADGE_TYPE, groupBadgeProgress, } from './gamification';
|
|
35
|
+
export { FREE_HINT_STEP_LIMIT, getHintAccessAction, HINT_ACCESS_KEY_SUFFIXES, } from './hintAccess';
|
|
36
|
+
// Daily date utilities
|
|
37
|
+
export { getUtcDateString, normalizeDailyDate, formatDailyDate, isStaleDaily, } from './date';
|
|
38
|
+
export { isAuthRequiredResponse, isSubscriptionRequiredResponse, getGameFetchStatus, getErrorHttpStatus, getPracticeFetchStatus, } from './gameFetchStatus';
|
|
39
|
+
export { buildTechniqueWalkthrough } from './techniqueExample';
|
|
29
40
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,8CAA8C;AAC9C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,mDAAmD;AACnD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,IAAI,mBAAmB,EACpC,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE/C,qBAAqB;AACrB,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAIpB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAEjB,yBAAyB;AACzB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,sBAAsB;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,6BAA6B;AAC7B,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AAEpB,0BAA0B;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC","sourcesContent":["/**\n * Utility exports for Sudojo library\n */\n\n// Board utilities (legacy - for useGame hook)\nexport {\n cloneBoard,\n countFilledCells,\n createGameBoard,\n getBlockCells,\n getBlockIndex,\n getBoardStateString,\n getColumnCells,\n getEmptyCells,\n getPencilmarksString,\n getRelatedCells,\n getRowCells,\n isValidPlacement,\n} from './board';\n\n// Validation utilities (legacy - for useGame hook)\nexport {\n autoRemovePencilmarks,\n clearHighlights,\n countMistakes,\n getIncorrectCells,\n getProgressPercentage,\n isBoardFilled,\n isCellCorrect,\n isGameComplete,\n isValueCorrect,\n updateCellErrors,\n updateCellHighlights,\n validateGameState,\n} from './validation';\n\n// Sudoku scrambler utilities (for useSudoku hook - ported from renderable)\nexport type {\n ScramblerProtocol,\n ScrambleResult as SudokuScrambleResult,\n} from './sudokuScrambler';\nexport {\n Scrambler,\n NonScrambler,\n scrambleBoard as scrambleSudokuBoard,\n parsePuzzleString,\n cellsToPuzzleString,\n cellsToStateString,\n cellsToInputString,\n cellsToPencilmarksString,\n} from './sudokuScrambler';\n\n// Sudoku presenter (for rendering - matches Kotlin renderable)\nexport type { PresentBoardOptions } from './sudokuPresenter';\nexport {\n presentBoard,\n calculateCellHints,\n themeColorToCSS,\n getColorPalette,\n getCellsWithDigit,\n getSelectedDigit,\n computeSelectedDigitCells,\n convertSolverLink,\n convertSolverCellGroup,\n sudokuColorToTheme,\n} from './sudokuPresenter';\n\n// Time utilities\nexport { formatTime, parseTime } from './time';\n\n// Progress utilities\nexport {\n calculateStats,\n calculateStreak,\n isPuzzleCompleted,\n getCompletedLevelIds,\n getCompletedDailyDates,\n} from './progress';\n\n// Theme utilities\nexport type { ThemePreference, ResolvedTheme } from './theme';\nexport {\n THEME_STORAGE_KEY,\n getSystemTheme,\n resolveTheme,\n isValidThemePreference,\n} from './theme';\n\n// Subscription utilities\nexport {\n convertPackageToProduct,\n parseCustomerInfo,\n getPeriodDisplayName,\n isBestValuePlan,\n getRevenueCatErrorMessage,\n} from './subscription';\n\n// Technique utilities\nexport { getTechniqueIconUrl } from './technique';\n\n// Technique walkthrough utilities\nexport type { WalkthroughStep } from './techniqueWalkthrough';\nexport {\n parsePencilmarksString,\n pencilmarksToString,\n parsePracticeBoard,\n cloneSudokuBoard,\n applyHintStep,\n parseHintData,\n localizeHintStep,\n buildWalkthroughSteps,\n} from './techniqueWalkthrough';\n\n// Hint explanation utilities\nexport {\n generateDetailedExplanation,\n getHintActionSummary,\n} from './hintExplanation';\n\n// Localized hint utilities\nexport type { TranslateFunction } from './localizedHint';\nexport {\n getLocalizedHintText,\n getLocalizedHintTitle,\n localizedField,\n} from './localizedHint';\n\n// i18n key utilities\nexport {\n getBeltKey,\n getLocalizedBeltName,\n getBeltLabelKey,\n getLocalizedBeltLabel,\n getLevelKey,\n getLocalizedLevelTitle,\n getTechniqueKey,\n getLocalizedTechniqueName,\n} from './i18nKeys';\n\n// Digit display utilities\nexport { displayDigit } from './digitDisplay';\n\n// Share URL utilities\nexport type { ShareUrlParams, ParsedShareParams } from './shareUrl';\nexport { buildShareUrl, parseShareParams, getWebUrl } from './shareUrl';\n\n// Auth utilities\nexport type { AuthUser } from './auth';\nexport { isAuthenticatedUser } from './auth';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Utility exports for Sudojo library\n */\n\n// Board utilities (legacy - for useGame hook)\nexport {\n cloneBoard,\n countFilledCells,\n createGameBoard,\n getBlockCells,\n getBlockIndex,\n getBoardStateString,\n getColumnCells,\n getEmptyCells,\n getPencilmarksString,\n getRelatedCells,\n getRowCells,\n isValidPlacement,\n} from './board';\n\n// Validation utilities (legacy - for useGame hook)\nexport {\n autoRemovePencilmarks,\n clearHighlights,\n countMistakes,\n getIncorrectCells,\n getProgressPercentage,\n isBoardFilled,\n isCellCorrect,\n isGameComplete,\n isValueCorrect,\n updateCellErrors,\n updateCellHighlights,\n validateGameState,\n} from './validation';\n\n// Sudoku scrambler utilities (for useSudoku hook - ported from renderable)\nexport type {\n ScramblerProtocol,\n ScrambleResult as SudokuScrambleResult,\n} from './sudokuScrambler';\nexport {\n Scrambler,\n NonScrambler,\n scrambleBoard as scrambleSudokuBoard,\n parsePuzzleString,\n cellsToPuzzleString,\n cellsToStateString,\n cellsToInputString,\n cellsToPencilmarksString,\n cellsToSolutionString,\n countClues,\n} from './sudokuScrambler';\n\n// Sudoku presenter (for rendering - matches Kotlin renderable)\nexport type { PresentBoardOptions } from './sudokuPresenter';\nexport {\n presentBoard,\n calculateCellHints,\n themeColorToCSS,\n getColorPalette,\n getCellsWithDigit,\n getSelectedDigit,\n computeSelectedDigitCells,\n convertSolverLink,\n convertSolverCellGroup,\n sudokuColorToTheme,\n solverColorToSudokuColor,\n parseHintDigits,\n convertSolverHintStep,\n isConflictHintStep,\n} from './sudokuPresenter';\n\n// Time utilities\nexport { formatTime, parseTime } from './time';\n\n// Progress utilities\nexport {\n calculateStats,\n calculateStreak,\n isPuzzleCompleted,\n getCompletedLevelIds,\n getCompletedDailyDates,\n applyPuzzleCompletion,\n} from './progress';\nexport type { PuzzleCompletion } from './progress';\n\n// Theme utilities\nexport type { ThemePreference, ResolvedTheme } from './theme';\nexport {\n THEME_STORAGE_KEY,\n FONT_SIZE_STORAGE_KEY,\n getSystemTheme,\n resolveTheme,\n isValidThemePreference,\n} from './theme';\n\n// Subscription utilities\nexport {\n convertPackageToProduct,\n parseCustomerInfo,\n getPeriodDisplayName,\n isBestValuePlan,\n getRevenueCatErrorMessage,\n getPeriodLabelKey,\n getPeriodLabel,\n isBestValueProduct,\n subscriptionPeriodToMonths,\n calculateSavingsPercent,\n isCrossPlatformSubscription,\n canDeleteAccount,\n getPuzzleDistribution,\n selectSavingsBasePlan,\n getPlanSavingsPercent,\n} from './subscription';\nexport type {\n PricedPeriod,\n PaywallPlan,\n DeleteAccountBlocker,\n DeleteAccountCheck,\n} from './subscription';\n\n// Technique and strategy utilities\nexport type {\n TechniqueSlug,\n StrategySlug,\n StrategyDifficultyTier,\n StrategySection,\n TechniqueContent,\n} from './technique';\nexport {\n getTechniqueIconUrl,\n toCanonicalTechniquePath,\n toApiTechniquePath,\n isSameTechniquePath,\n findTechniqueByPath,\n parseTechniqueDependencies,\n getTechniqueDependencies,\n getDependentTechniques,\n sortTechniquesByLevel,\n groupTechniquesByLevel,\n getTechniquesForStrategy,\n findStrategyByStub,\n TECHNIQUE_SLUGS,\n STRATEGY_SLUGS,\n getStrategyDifficultyTier,\n getStrategyDifficultyKey,\n getStrategySections,\n parseTechniqueContent,\n} from './technique';\n\n// Technique bitmask utilities\nexport {\n exactTechniqueBitmask,\n techniqueBitmaskString,\n techniqueFieldsOf,\n} from './techniqueBitmask';\n\n// Technique walkthrough utilities\nexport type { WalkthroughStep } from './techniqueWalkthrough';\nexport {\n parsePencilmarksString,\n pencilmarksToString,\n parsePracticeBoard,\n cloneSudokuBoard,\n applyHintStep,\n parseHintData,\n localizeHintStep,\n buildWalkthroughSteps,\n} from './techniqueWalkthrough';\n\n// Hint explanation utilities\nexport {\n generateDetailedExplanation,\n getHintActionSummary,\n} from './hintExplanation';\n\n// Localized hint utilities\nexport type {\n TranslateFunction,\n HintHeadingTree,\n LocalizedHintHelpers,\n} from './localizedHint';\nexport {\n getLocalizedHintText,\n getLocalizedHintTitle,\n localizedField,\n HINT_HEADING_KEY_PREFIX,\n getStepHeadingLocalization,\n getLocalizedHintHeading,\n interpolateHintValues,\n getStepHeadingFromTree,\n createLocalizedHintHelpers,\n} from './localizedHint';\n\n// Entity translation utilities\nexport type {\n LevelDisplaySource,\n TechniqueDisplaySource,\n StrategyDisplaySource,\n} from './entityTranslate';\nexport {\n createNamespacedTranslate,\n getLevelDisplayTitle,\n getLevelDisplayText,\n getTechniqueDisplayTitle,\n getBeltDisplayName,\n getBeltDisplayLabel,\n getStrategyDisplayTitle,\n} from './entityTranslate';\n\n// i18n key utilities\nexport {\n getBeltKey,\n getLocalizedBeltName,\n getBeltLabelKey,\n getLocalizedBeltLabel,\n getLevelKey,\n getLocalizedLevelTitle,\n getTechniqueKey,\n getLocalizedTechniqueName,\n} from './i18nKeys';\n\n// Digit display utilities\nexport { displayDigit } from './digitDisplay';\n\n// Scanned board (OCR) utilities\nexport type { ScannedBoard, ScanBoardErrorCode } from './scannedBoard';\nexport {\n MIN_SCAN_CLUES,\n ScanBoardError,\n toScannedBoard,\n hasScannedInput,\n scannedBoardFromResponse,\n} from './scannedBoard';\n\n// Share URL utilities\nexport type {\n ShareUrlParams,\n ParsedShareParams,\n ShareUrlType,\n ShareParamsSource,\n} from './shareUrl';\nexport { buildShareUrl, parseShareParams, getWebUrl } from './shareUrl';\n\n// Auth utilities\nexport type { AuthUser } from './auth';\nexport { isAuthenticatedUser, isRealUser } from './auth';\n\n// Language utilities\nexport type { SupportedLanguageInfo, SupportedLanguageCode } from './language';\nexport {\n SUPPORTED_LANGUAGES,\n SUPPORTED_LANGUAGE_CODES,\n DEFAULT_LANGUAGE,\n LANGUAGE_STORAGE_KEY,\n NATIVE_LANGUAGE_STORAGE_KEY,\n isSupportedLanguage,\n normalizeLanguageCode,\n resolveLanguage,\n toLanguageTag,\n getLanguageNativeName,\n} from './language';\n\n// Community utilities\nexport type { CommunityPlatformInfo } from './community';\nexport {\n COMMUNITY_PLATFORMS,\n getCommunityPlatform,\n sortCommunityPlatforms,\n} from './community';\n\n// Gamification utilities\nexport type { BadgeProgress, BadgeDefinitionLike } from './gamification';\nexport {\n LEVEL_MASTERY_BADGE_TYPE,\n GAMES_PLAYED_BADGE_TYPE,\n groupBadgeProgress,\n} from './gamification';\n\n// Hint access utilities\nexport type {\n HintAccessAction,\n HintAccessVariant,\n HintAccessPresentation,\n} from './hintAccess';\nexport {\n FREE_HINT_STEP_LIMIT,\n getHintAccessAction,\n HINT_ACCESS_KEY_SUFFIXES,\n} from './hintAccess';\n\n// Daily date utilities\nexport {\n getUtcDateString,\n normalizeDailyDate,\n formatDailyDate,\n isStaleDaily,\n} from './date';\n\n// Game fetch status utilities\nexport type { GameFetchResponse, PracticeFetchStatus } from './gameFetchStatus';\nexport {\n isAuthRequiredResponse,\n isSubscriptionRequiredResponse,\n getGameFetchStatus,\n getErrorHttpStatus,\n getPracticeFetchStatus,\n} from './gameFetchStatus';\n\n// Technique example walkthrough\nexport type {\n TechniqueExampleSource,\n TechniqueWalkthroughTranslations,\n TechniqueWalkthrough,\n} from './techniqueExample';\nexport { buildTechniqueWalkthrough } from './techniqueExample';\n"]}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported UI languages and locale-tag resolution.
|
|
3
|
+
*
|
|
4
|
+
* **Code casing.** Language codes here are lowercase (`zh-hant`), which is what
|
|
5
|
+
* the web app uses (i18next `lowerCaseLng`, URL prefixes like `/zh-hant/play`),
|
|
6
|
+
* what the API stores in `Community.language_code`, and how the locale
|
|
7
|
+
* directories are named. The RN app keys its i18next resources as `zh-Hant`;
|
|
8
|
+
* convert with {@link toLanguageTag} there.
|
|
9
|
+
*/
|
|
10
|
+
/** A supported UI language. */
|
|
11
|
+
export interface SupportedLanguageInfo {
|
|
12
|
+
/** Lowercase language code, e.g. `en`, `zh-hant` */
|
|
13
|
+
code: string;
|
|
14
|
+
/** The language's name in itself, e.g. `Deutsch`, `繁體中文` */
|
|
15
|
+
nativeName: string;
|
|
16
|
+
/** Flag emoji shown next to the name in the RN language picker */
|
|
17
|
+
flag: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The 15 supported UI languages, in the web app's order.
|
|
21
|
+
*
|
|
22
|
+
* The two app copies differ only in the Chinese native names: the web says
|
|
23
|
+
* `简体中文` / `繁體中文`, the RN app `中文简体` / `中文繁體`. The web names are used
|
|
24
|
+
* here (the conventional word order).
|
|
25
|
+
*/
|
|
26
|
+
export declare const SUPPORTED_LANGUAGES: readonly [{
|
|
27
|
+
readonly code: "en";
|
|
28
|
+
readonly nativeName: "English";
|
|
29
|
+
readonly flag: "🇺🇸";
|
|
30
|
+
}, {
|
|
31
|
+
readonly code: "de";
|
|
32
|
+
readonly nativeName: "Deutsch";
|
|
33
|
+
readonly flag: "🇩🇪";
|
|
34
|
+
}, {
|
|
35
|
+
readonly code: "es";
|
|
36
|
+
readonly nativeName: "Español";
|
|
37
|
+
readonly flag: "🇪🇸";
|
|
38
|
+
}, {
|
|
39
|
+
readonly code: "fr";
|
|
40
|
+
readonly nativeName: "Français";
|
|
41
|
+
readonly flag: "🇫🇷";
|
|
42
|
+
}, {
|
|
43
|
+
readonly code: "it";
|
|
44
|
+
readonly nativeName: "Italiano";
|
|
45
|
+
readonly flag: "🇮🇹";
|
|
46
|
+
}, {
|
|
47
|
+
readonly code: "ja";
|
|
48
|
+
readonly nativeName: "日本語";
|
|
49
|
+
readonly flag: "🇯🇵";
|
|
50
|
+
}, {
|
|
51
|
+
readonly code: "ko";
|
|
52
|
+
readonly nativeName: "한국어";
|
|
53
|
+
readonly flag: "🇰🇷";
|
|
54
|
+
}, {
|
|
55
|
+
readonly code: "pt";
|
|
56
|
+
readonly nativeName: "Português";
|
|
57
|
+
readonly flag: "🇧🇷";
|
|
58
|
+
}, {
|
|
59
|
+
readonly code: "ru";
|
|
60
|
+
readonly nativeName: "Русский";
|
|
61
|
+
readonly flag: "🇷🇺";
|
|
62
|
+
}, {
|
|
63
|
+
readonly code: "sv";
|
|
64
|
+
readonly nativeName: "Svenska";
|
|
65
|
+
readonly flag: "🇸🇪";
|
|
66
|
+
}, {
|
|
67
|
+
readonly code: "th";
|
|
68
|
+
readonly nativeName: "ไทย";
|
|
69
|
+
readonly flag: "🇹🇭";
|
|
70
|
+
}, {
|
|
71
|
+
readonly code: "uk";
|
|
72
|
+
readonly nativeName: "Українська";
|
|
73
|
+
readonly flag: "🇺🇦";
|
|
74
|
+
}, {
|
|
75
|
+
readonly code: "vi";
|
|
76
|
+
readonly nativeName: "Tiếng Việt";
|
|
77
|
+
readonly flag: "🇻🇳";
|
|
78
|
+
}, {
|
|
79
|
+
readonly code: "zh";
|
|
80
|
+
readonly nativeName: "简体中文";
|
|
81
|
+
readonly flag: "🇨🇳";
|
|
82
|
+
}, {
|
|
83
|
+
readonly code: "zh-hant";
|
|
84
|
+
readonly nativeName: "繁體中文";
|
|
85
|
+
readonly flag: "🇹🇼";
|
|
86
|
+
}];
|
|
87
|
+
/** A supported language code (lowercase). */
|
|
88
|
+
export type SupportedLanguageCode = (typeof SUPPORTED_LANGUAGES)[number]['code'];
|
|
89
|
+
/** All supported language codes, in SUPPORTED_LANGUAGES order. */
|
|
90
|
+
export declare const SUPPORTED_LANGUAGE_CODES: readonly SupportedLanguageCode[];
|
|
91
|
+
/** The language used when nothing else matches. */
|
|
92
|
+
export declare const DEFAULT_LANGUAGE: SupportedLanguageCode;
|
|
93
|
+
/**
|
|
94
|
+
* localStorage key for the web app's language preference (`'language'`, the
|
|
95
|
+
* key i18next-browser-languagedetector and LanguageValidator use).
|
|
96
|
+
*/
|
|
97
|
+
export declare const LANGUAGE_STORAGE_KEY = "language";
|
|
98
|
+
/** AsyncStorage key for the RN app's language preference (`'@sudojo/language'`). */
|
|
99
|
+
export declare const NATIVE_LANGUAGE_STORAGE_KEY = "@sudojo/language";
|
|
100
|
+
/** Whether `code` is a supported language code (exact, lowercase). */
|
|
101
|
+
export declare function isSupportedLanguage(code: string | null | undefined): code is SupportedLanguageCode;
|
|
102
|
+
/**
|
|
103
|
+
* Map a language code or locale tag to a supported language code, or null.
|
|
104
|
+
*
|
|
105
|
+
* Case and `_` / `-` are ignored. Traditional Chinese (`zh-Hant*`, `zh-TW`,
|
|
106
|
+
* `zh-HK`, `zh-MO`) → `zh-hant`; any other `zh*` → `zh`. Otherwise the full
|
|
107
|
+
* tag, then its base language (`pt-BR` → `pt`), must be supported.
|
|
108
|
+
*/
|
|
109
|
+
export declare function normalizeLanguageCode(code: string | null | undefined): SupportedLanguageCode | null;
|
|
110
|
+
/**
|
|
111
|
+
* The supported language for a device/browser locale tag, or
|
|
112
|
+
* {@link DEFAULT_LANGUAGE} when it is not supported.
|
|
113
|
+
* Matches the RN app's device-language detection.
|
|
114
|
+
*/
|
|
115
|
+
export declare function resolveLanguage(localeTag: string | null | undefined): SupportedLanguageCode;
|
|
116
|
+
/**
|
|
117
|
+
* BCP 47 casing of a language code, e.g. `zh-hant` → `zh-Hant` (the RN app's
|
|
118
|
+
* i18next resource key). Other codes are returned unchanged.
|
|
119
|
+
*/
|
|
120
|
+
export declare function toLanguageTag(code: string): string;
|
|
121
|
+
/** Native name of a language, or undefined for an unsupported code. */
|
|
122
|
+
export declare function getLanguageNativeName(code: string | null | undefined): string | undefined;
|
|
123
|
+
//# sourceMappingURL=language.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/utils/language.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,+BAA+B;AAC/B,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBqB,CAAC;AAEtD,6CAA6C;AAC7C,MAAM,MAAM,qBAAqB,GAC/B,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,kEAAkE;AAClE,eAAO,MAAM,wBAAwB,EAAE,SAAS,qBAAqB,EACzB,CAAC;AAE7C,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,EAAE,qBAA4B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C,oFAAoF;AACpF,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAE9D,sEAAsE;AACtE,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,IAAI,IAAI,qBAAqB,CAI/B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,qBAAqB,GAAG,IAAI,CAgB9B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,qBAAqB,CAEvB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,uEAAuE;AACvE,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAGpB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported UI languages and locale-tag resolution.
|
|
3
|
+
*
|
|
4
|
+
* **Code casing.** Language codes here are lowercase (`zh-hant`), which is what
|
|
5
|
+
* the web app uses (i18next `lowerCaseLng`, URL prefixes like `/zh-hant/play`),
|
|
6
|
+
* what the API stores in `Community.language_code`, and how the locale
|
|
7
|
+
* directories are named. The RN app keys its i18next resources as `zh-Hant`;
|
|
8
|
+
* convert with {@link toLanguageTag} there.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The 15 supported UI languages, in the web app's order.
|
|
12
|
+
*
|
|
13
|
+
* The two app copies differ only in the Chinese native names: the web says
|
|
14
|
+
* `简体中文` / `繁體中文`, the RN app `中文简体` / `中文繁體`. The web names are used
|
|
15
|
+
* here (the conventional word order).
|
|
16
|
+
*/
|
|
17
|
+
export const SUPPORTED_LANGUAGES = [
|
|
18
|
+
{ code: 'en', nativeName: 'English', flag: '🇺🇸' },
|
|
19
|
+
{ code: 'de', nativeName: 'Deutsch', flag: '🇩🇪' },
|
|
20
|
+
{ code: 'es', nativeName: 'Español', flag: '🇪🇸' },
|
|
21
|
+
{ code: 'fr', nativeName: 'Français', flag: '🇫🇷' },
|
|
22
|
+
{ code: 'it', nativeName: 'Italiano', flag: '🇮🇹' },
|
|
23
|
+
{ code: 'ja', nativeName: '日本語', flag: '🇯🇵' },
|
|
24
|
+
{ code: 'ko', nativeName: '한국어', flag: '🇰🇷' },
|
|
25
|
+
{ code: 'pt', nativeName: 'Português', flag: '🇧🇷' },
|
|
26
|
+
{ code: 'ru', nativeName: 'Русский', flag: '🇷🇺' },
|
|
27
|
+
{ code: 'sv', nativeName: 'Svenska', flag: '🇸🇪' },
|
|
28
|
+
{ code: 'th', nativeName: 'ไทย', flag: '🇹🇭' },
|
|
29
|
+
{ code: 'uk', nativeName: 'Українська', flag: '🇺🇦' },
|
|
30
|
+
{ code: 'vi', nativeName: 'Tiếng Việt', flag: '🇻🇳' },
|
|
31
|
+
{ code: 'zh', nativeName: '简体中文', flag: '🇨🇳' },
|
|
32
|
+
{ code: 'zh-hant', nativeName: '繁體中文', flag: '🇹🇼' },
|
|
33
|
+
];
|
|
34
|
+
/** All supported language codes, in SUPPORTED_LANGUAGES order. */
|
|
35
|
+
export const SUPPORTED_LANGUAGE_CODES = SUPPORTED_LANGUAGES.map(lang => lang.code);
|
|
36
|
+
/** The language used when nothing else matches. */
|
|
37
|
+
export const DEFAULT_LANGUAGE = 'en';
|
|
38
|
+
/**
|
|
39
|
+
* localStorage key for the web app's language preference (`'language'`, the
|
|
40
|
+
* key i18next-browser-languagedetector and LanguageValidator use).
|
|
41
|
+
*/
|
|
42
|
+
export const LANGUAGE_STORAGE_KEY = 'language';
|
|
43
|
+
/** AsyncStorage key for the RN app's language preference (`'@sudojo/language'`). */
|
|
44
|
+
export const NATIVE_LANGUAGE_STORAGE_KEY = '@sudojo/language';
|
|
45
|
+
/** Whether `code` is a supported language code (exact, lowercase). */
|
|
46
|
+
export function isSupportedLanguage(code) {
|
|
47
|
+
return (!!code && SUPPORTED_LANGUAGE_CODES.includes(code));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Map a language code or locale tag to a supported language code, or null.
|
|
51
|
+
*
|
|
52
|
+
* Case and `_` / `-` are ignored. Traditional Chinese (`zh-Hant*`, `zh-TW`,
|
|
53
|
+
* `zh-HK`, `zh-MO`) → `zh-hant`; any other `zh*` → `zh`. Otherwise the full
|
|
54
|
+
* tag, then its base language (`pt-BR` → `pt`), must be supported.
|
|
55
|
+
*/
|
|
56
|
+
export function normalizeLanguageCode(code) {
|
|
57
|
+
if (!code)
|
|
58
|
+
return null;
|
|
59
|
+
const tag = code.trim().toLowerCase().replace(/_/g, '-');
|
|
60
|
+
if (!tag)
|
|
61
|
+
return null;
|
|
62
|
+
if (tag.startsWith('zh-hant') ||
|
|
63
|
+
tag.startsWith('zh-tw') ||
|
|
64
|
+
tag.startsWith('zh-hk') ||
|
|
65
|
+
tag.startsWith('zh-mo')) {
|
|
66
|
+
return 'zh-hant';
|
|
67
|
+
}
|
|
68
|
+
if (tag === 'zh' || tag.startsWith('zh-'))
|
|
69
|
+
return 'zh';
|
|
70
|
+
if (isSupportedLanguage(tag))
|
|
71
|
+
return tag;
|
|
72
|
+
const base = tag.split('-')[0];
|
|
73
|
+
return isSupportedLanguage(base) ? base : null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The supported language for a device/browser locale tag, or
|
|
77
|
+
* {@link DEFAULT_LANGUAGE} when it is not supported.
|
|
78
|
+
* Matches the RN app's device-language detection.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveLanguage(localeTag) {
|
|
81
|
+
return normalizeLanguageCode(localeTag) ?? DEFAULT_LANGUAGE;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* BCP 47 casing of a language code, e.g. `zh-hant` → `zh-Hant` (the RN app's
|
|
85
|
+
* i18next resource key). Other codes are returned unchanged.
|
|
86
|
+
*/
|
|
87
|
+
export function toLanguageTag(code) {
|
|
88
|
+
return code.toLowerCase() === 'zh-hant' ? 'zh-Hant' : code;
|
|
89
|
+
}
|
|
90
|
+
/** Native name of a language, or undefined for an unsupported code. */
|
|
91
|
+
export function getLanguageNativeName(code) {
|
|
92
|
+
const normalized = normalizeLanguageCode(code);
|
|
93
|
+
return SUPPORTED_LANGUAGES.find(lang => lang.code === normalized)?.nativeName;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/utils/language.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Supported UI languages and locale-tag resolution.\n *\n * **Code casing.** Language codes here are lowercase (`zh-hant`), which is what\n * the web app uses (i18next `lowerCaseLng`, URL prefixes like `/zh-hant/play`),\n * what the API stores in `Community.language_code`, and how the locale\n * directories are named. The RN app keys its i18next resources as `zh-Hant`;\n * convert with {@link toLanguageTag} there.\n */\n\n/** A supported UI language. */\nexport interface SupportedLanguageInfo {\n /** Lowercase language code, e.g. `en`, `zh-hant` */\n code: string;\n /** The language's name in itself, e.g. `Deutsch`, `繁體中文` */\n nativeName: string;\n /** Flag emoji shown next to the name in the RN language picker */\n flag: string;\n}\n\n/**\n * The 15 supported UI languages, in the web app's order.\n *\n * The two app copies differ only in the Chinese native names: the web says\n * `简体中文` / `繁體中文`, the RN app `中文简体` / `中文繁體`. The web names are used\n * here (the conventional word order).\n */\nexport const SUPPORTED_LANGUAGES = [\n { code: 'en', nativeName: 'English', flag: '🇺🇸' },\n { code: 'de', nativeName: 'Deutsch', flag: '🇩🇪' },\n { code: 'es', nativeName: 'Español', flag: '🇪🇸' },\n { code: 'fr', nativeName: 'Français', flag: '🇫🇷' },\n { code: 'it', nativeName: 'Italiano', flag: '🇮🇹' },\n { code: 'ja', nativeName: '日本語', flag: '🇯🇵' },\n { code: 'ko', nativeName: '한국어', flag: '🇰🇷' },\n { code: 'pt', nativeName: 'Português', flag: '🇧🇷' },\n { code: 'ru', nativeName: 'Русский', flag: '🇷🇺' },\n { code: 'sv', nativeName: 'Svenska', flag: '🇸🇪' },\n { code: 'th', nativeName: 'ไทย', flag: '🇹🇭' },\n { code: 'uk', nativeName: 'Українська', flag: '🇺🇦' },\n { code: 'vi', nativeName: 'Tiếng Việt', flag: '🇻🇳' },\n { code: 'zh', nativeName: '简体中文', flag: '🇨🇳' },\n { code: 'zh-hant', nativeName: '繁體中文', flag: '🇹🇼' },\n] as const satisfies readonly SupportedLanguageInfo[];\n\n/** A supported language code (lowercase). */\nexport type SupportedLanguageCode =\n (typeof SUPPORTED_LANGUAGES)[number]['code'];\n\n/** All supported language codes, in SUPPORTED_LANGUAGES order. */\nexport const SUPPORTED_LANGUAGE_CODES: readonly SupportedLanguageCode[] =\n SUPPORTED_LANGUAGES.map(lang => lang.code);\n\n/** The language used when nothing else matches. */\nexport const DEFAULT_LANGUAGE: SupportedLanguageCode = 'en';\n\n/**\n * localStorage key for the web app's language preference (`'language'`, the\n * key i18next-browser-languagedetector and LanguageValidator use).\n */\nexport const LANGUAGE_STORAGE_KEY = 'language';\n\n/** AsyncStorage key for the RN app's language preference (`'@sudojo/language'`). */\nexport const NATIVE_LANGUAGE_STORAGE_KEY = '@sudojo/language';\n\n/** Whether `code` is a supported language code (exact, lowercase). */\nexport function isSupportedLanguage(\n code: string | null | undefined\n): code is SupportedLanguageCode {\n return (\n !!code && (SUPPORTED_LANGUAGE_CODES as readonly string[]).includes(code)\n );\n}\n\n/**\n * Map a language code or locale tag to a supported language code, or null.\n *\n * Case and `_` / `-` are ignored. Traditional Chinese (`zh-Hant*`, `zh-TW`,\n * `zh-HK`, `zh-MO`) → `zh-hant`; any other `zh*` → `zh`. Otherwise the full\n * tag, then its base language (`pt-BR` → `pt`), must be supported.\n */\nexport function normalizeLanguageCode(\n code: string | null | undefined\n): SupportedLanguageCode | null {\n if (!code) return null;\n const tag = code.trim().toLowerCase().replace(/_/g, '-');\n if (!tag) return null;\n if (\n tag.startsWith('zh-hant') ||\n tag.startsWith('zh-tw') ||\n tag.startsWith('zh-hk') ||\n tag.startsWith('zh-mo')\n ) {\n return 'zh-hant';\n }\n if (tag === 'zh' || tag.startsWith('zh-')) return 'zh';\n if (isSupportedLanguage(tag)) return tag;\n const base = tag.split('-')[0];\n return isSupportedLanguage(base) ? base : null;\n}\n\n/**\n * The supported language for a device/browser locale tag, or\n * {@link DEFAULT_LANGUAGE} when it is not supported.\n * Matches the RN app's device-language detection.\n */\nexport function resolveLanguage(\n localeTag: string | null | undefined\n): SupportedLanguageCode {\n return normalizeLanguageCode(localeTag) ?? DEFAULT_LANGUAGE;\n}\n\n/**\n * BCP 47 casing of a language code, e.g. `zh-hant` → `zh-Hant` (the RN app's\n * i18next resource key). Other codes are returned unchanged.\n */\nexport function toLanguageTag(code: string): string {\n return code.toLowerCase() === 'zh-hant' ? 'zh-Hant' : code;\n}\n\n/** Native name of a language, or undefined for an unsupported code. */\nexport function getLanguageNativeName(\n code: string | null | undefined\n): string | undefined {\n const normalized = normalizeLanguageCode(code);\n return SUPPORTED_LANGUAGES.find(lang => lang.code === normalized)?.nativeName;\n}\n"]}
|
|
@@ -35,4 +35,64 @@ export declare function getLocalizedHintText(t: TranslateFunction, step: SolverH
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function localizedField(t: TranslateFunction, loc: LocalizedHint | undefined, fallback: string | null | undefined): string;
|
|
37
37
|
export declare function getLocalizedHintTitle(t: TranslateFunction, step: SolverHintStep, keyPrefix?: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Top-level tree in the apps' `hints.json` that mirrors `hints`, with one
|
|
40
|
+
* heading per step: `hints.hiddenSingle.row.scan` → `headings.hiddenSingle.row.scan`.
|
|
41
|
+
*/
|
|
42
|
+
export declare const HINT_HEADING_KEY_PREFIX = "headings.";
|
|
43
|
+
/**
|
|
44
|
+
* Heading lookup for ONE hint step.
|
|
45
|
+
*
|
|
46
|
+
* Every step key the solver emits (`hints.hiddenSingle.row.scan`) has a heading
|
|
47
|
+
* at the same path under the `headings` tree (`headings.hiddenSingle.row.scan`),
|
|
48
|
+
* interpolated with that step's own values, so `{{valueN}}` means the same in
|
|
49
|
+
* the heading as in the body. Injected `hints.conflict.*` steps get headings too.
|
|
50
|
+
*
|
|
51
|
+
* Accepts the legacy flat localization shape. Returns undefined when the step
|
|
52
|
+
* carries no `hints.*` localization; callers then render no heading.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getStepHeadingLocalization(step: SolverHintStep | null | undefined): LocalizedHint | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Translated heading for one hint step, or '' when it has none (no `hints.*`
|
|
57
|
+
* key, or the heading is missing), so the UI renders nothing instead of a raw key.
|
|
58
|
+
*
|
|
59
|
+
* @param t - Translation function for the `hints` namespace
|
|
60
|
+
*/
|
|
61
|
+
export declare function getLocalizedHintHeading(t: TranslateFunction, step: SolverHintStep | null | undefined): string;
|
|
62
|
+
/** A nested heading tree, e.g. the `headings` object of `hints.json`. */
|
|
63
|
+
export interface HintHeadingTree {
|
|
64
|
+
[key: string]: string | HintHeadingTree;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Fill `{{valueN}}` placeholders from a values array (values[0] → `{{value1}}`).
|
|
68
|
+
* Missing values become ''.
|
|
69
|
+
*/
|
|
70
|
+
export declare function interpolateHintValues(template: string, values: readonly string[]): string;
|
|
71
|
+
/**
|
|
72
|
+
* Heading for one hint step looked up directly in a heading tree, without an
|
|
73
|
+
* i18n library (the Chrome extension bundles the English tree as JSON).
|
|
74
|
+
*
|
|
75
|
+
* The step's `hints.<path>` key maps to `<path>` in the tree and the template
|
|
76
|
+
* is interpolated with the step's values. Returns '' when there is no heading.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getStepHeadingFromTree(tree: HintHeadingTree, step: SolverHintStep | null | undefined): string;
|
|
79
|
+
/** Localized text, title and heading resolvers for hint steps. */
|
|
80
|
+
export interface LocalizedHintHelpers {
|
|
81
|
+
/** Localized body text (falls back to `step.text`). */
|
|
82
|
+
getLocalizedText: (step: SolverHintStep) => string;
|
|
83
|
+
/** Localized technique title (falls back to `step.title`). */
|
|
84
|
+
getLocalizedTitle: (step: SolverHintStep) => string;
|
|
85
|
+
/** Localized per-step heading, or ''. */
|
|
86
|
+
getLocalizedHeading: (step: SolverHintStep | null | undefined) => string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build the hint text/title/heading resolvers the apps' `useLocalizedHint`
|
|
90
|
+
* hooks return. The hooks stay in the apps because they read react-i18next;
|
|
91
|
+
* they should wrap this.
|
|
92
|
+
*
|
|
93
|
+
* @param tHints - Translate function for the `hints` namespace (text + headings)
|
|
94
|
+
* @param tTitle - Entity translate function for titles
|
|
95
|
+
* (`techniques.<path>.title`), e.g. from createNamespacedTranslate
|
|
96
|
+
*/
|
|
97
|
+
export declare function createLocalizedHintHelpers(tHints: TranslateFunction, tTitle: TranslateFunction): LocalizedHintHelpers;
|
|
38
98
|
//# sourceMappingURL=localizedHint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localizedHint.d.ts","sourceRoot":"","sources":["../../src/utils/localizedHint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE9E;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC5B,MAAM,CAAC;AA0DZ;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,EACpB,SAAS,GAAE,MAAW,GACrB,MAAM,CAGR;AAED;;;;;;;GAOG;AACH;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,aAAa,GAAG,SAAS,EAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,MAAM,CAER;AAED,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,EACpB,SAAS,GAAE,MAAW,GACrB,MAAM,CAGR"}
|
|
1
|
+
{"version":3,"file":"localizedHint.d.ts","sourceRoot":"","sources":["../../src/utils/localizedHint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE9E;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC5B,MAAM,CAAC;AA0DZ;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,EACpB,SAAS,GAAE,MAAW,GACrB,MAAM,CAGR;AAED;;;;;;;GAOG;AACH;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,aAAa,GAAG,SAAS,EAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,MAAM,CAER;AAED,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,EACpB,SAAS,GAAE,MAAW,GACrB,MAAM,CAGR;AAQD;;;GAGG;AACH,eAAO,MAAM,uBAAuB,cAAc,CAAC;AAEnD;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GACtC,aAAa,GAAG,SAAS,CAU3B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GACtC,MAAM,CAGR;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB,MAAM,CAKR;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,eAAe,EACrB,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GACtC,MAAM,CAeR;AAED,kEAAkE;AAClE,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,gBAAgB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,CAAC;IACnD,8DAA8D;IAC9D,iBAAiB,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,CAAC;IACpD,yCAAyC;IACzC,mBAAmB,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,KAAK,MAAM,CAAC;CAC1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,iBAAiB,GACxB,oBAAoB,CAMtB"}
|