@fanee/react 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @fanee/react
|
|
2
|
+
|
|
3
|
+
React bindings for Fanee.
|
|
4
|
+
|
|
5
|
+
Provides a Context-based provider and hooks to consume a `FaneeRuntime` from `@fanee/core` inside a React component tree.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @fanee/core @fanee/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { FaneeRuntime } from "@fanee/core";
|
|
17
|
+
import { FaneeProvider, useT, useLocale, useSetLocale } from "@fanee/react";
|
|
18
|
+
|
|
19
|
+
const runtime = new FaneeRuntime().config({
|
|
20
|
+
defaultLocale: "en",
|
|
21
|
+
currentLocale: "en",
|
|
22
|
+
resources: {
|
|
23
|
+
"": {
|
|
24
|
+
en: { hello: "Hello, {name}!" },
|
|
25
|
+
fr: { hello: "Bonjour, {name}!" },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function App() {
|
|
31
|
+
return (
|
|
32
|
+
<FaneeProvider runtime={runtime}>
|
|
33
|
+
<Greeting />
|
|
34
|
+
</FaneeProvider>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Greeting() {
|
|
39
|
+
const t = useT();
|
|
40
|
+
const locale = useLocale();
|
|
41
|
+
const setLocale = useSetLocale();
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<p>{t("hello", { name: "World" })}</p>
|
|
46
|
+
<p>Current locale: {locale}</p>
|
|
47
|
+
<button onClick={() => setLocale(locale === "en" ? "fr" : "en")}>
|
|
48
|
+
Switch locale
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### `FaneeProvider`
|
|
58
|
+
|
|
59
|
+
Wraps your app and exposes a `FaneeRuntime` instance to descendant hooks.
|
|
60
|
+
|
|
61
|
+
### `useT(context?)`
|
|
62
|
+
|
|
63
|
+
Returns a bound translate function. Re-renders when the locale, namespace, or resources change.
|
|
64
|
+
|
|
65
|
+
### `useLocale()`
|
|
66
|
+
|
|
67
|
+
Returns the active locale.
|
|
68
|
+
|
|
69
|
+
### `useSetLocale()`
|
|
70
|
+
|
|
71
|
+
Returns a function to update the active locale.
|
|
72
|
+
|
|
73
|
+
### `useFanee()`
|
|
74
|
+
|
|
75
|
+
Returns `{ runtime, locale }` for direct access to the runtime instance.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { FaneeRuntime, Locale, TranslateContext, TranslateFunction } from "@fanee/core";
|
|
3
|
+
|
|
4
|
+
//#region src/provider.d.ts
|
|
5
|
+
interface FaneeProviderProps {
|
|
6
|
+
/** FaneeRuntime instance to expose to the React tree. */
|
|
7
|
+
runtime: FaneeRuntime;
|
|
8
|
+
/** React children. */
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Provides a FaneeRuntime instance to descendant components.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const runtime = new FaneeRuntime().config({ currentLocale: "en" });
|
|
17
|
+
*
|
|
18
|
+
* <FaneeProvider runtime={runtime}>
|
|
19
|
+
* <App />
|
|
20
|
+
* </FaneeProvider>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function FaneeProvider({
|
|
24
|
+
runtime,
|
|
25
|
+
children
|
|
26
|
+
}: FaneeProviderProps): import("react").JSX.Element;
|
|
27
|
+
/** @internal */
|
|
28
|
+
declare function useRuntime(): FaneeRuntime;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/hooks.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to the Fanee runtime and access it alongside the current locale.
|
|
33
|
+
*
|
|
34
|
+
* @returns An object with the runtime and the active locale.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* const { runtime, locale } = useFanee();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
declare function useFanee(): {
|
|
42
|
+
runtime: ReturnType<typeof useRuntime>;
|
|
43
|
+
locale: Locale;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Return a translation function bound to the current runtime state and
|
|
47
|
+
* an optional namespace/locale context.
|
|
48
|
+
*
|
|
49
|
+
* The returned function is recreated whenever the active locale, namespace,
|
|
50
|
+
* or underlying resources change, so it remains reactive to runtime updates.
|
|
51
|
+
*
|
|
52
|
+
* @param context - Optional locale/namespace overrides.
|
|
53
|
+
* @returns A `(key, vars?) => string` translate function.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```tsx
|
|
57
|
+
* const t = useT({ namespace: "errors" });
|
|
58
|
+
* return <p>{t("not_found")}</p>;
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare function useT(context?: Partial<TranslateContext>): TranslateFunction;
|
|
62
|
+
/**
|
|
63
|
+
* Read the currently active locale from the runtime.
|
|
64
|
+
*
|
|
65
|
+
* @returns The BCP-47 locale tag.
|
|
66
|
+
*/
|
|
67
|
+
declare function useLocale(): Locale;
|
|
68
|
+
/**
|
|
69
|
+
* Return a setter for the runtime locale.
|
|
70
|
+
*
|
|
71
|
+
* @returns A function that updates the active locale.
|
|
72
|
+
*/
|
|
73
|
+
declare function useSetLocale(): (locale: Locale) => void;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { FaneeProvider, type FaneeProviderProps, useFanee, useLocale, useSetLocale, useT };
|
|
76
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/provider.tsx","../src/hooks.ts"],"mappings":";;;;UAKiB,kBAAA;;EAEhB,OAAA,EAAS,YAAA;EAFyB;EAIlC,QAAA,EAAU,SAAS;AAAA;;;;;;AAAA;AAepB;;;;;;iBAAgB,aAAA;EAAgB,OAAA;EAAS;AAAA,GAAY,kBAAA,mBAAkB,GAAA,CAAA,OAAA;;iBAKvD,UAAA,IAAc,YAAY;;;;;AAxB1C;;;;;;;;iBCsBgB,QAAA;EAAc,OAAA,EAAS,UAAA,QAAkB,UAAA;EAAa,MAAA,EAAQ,MAAA;AAAA;;;;;;;;;;;;;;;ADHP;AAKvE;iBCoBgB,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,gBAAA,IAAoB,iBAAA;;;ADpBjB;;;iBCyC1B,SAAA,IAAa,MAAM;AA3CnC;;;;;AAAA,iBAsDgB,YAAA,KAAiB,MAAc,EAAN,MAAM"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createContext as e,useCallback as t,useContext as n,useEffect as r,useMemo as i,useReducer as a}from"react";import{jsx as o}from"react/jsx-runtime";const s=e(null);function c({runtime:e,children:t}){return o(s.Provider,{value:e,children:t})}function l(){let e=n(s);if(!e)throw Error(`[fanee] Fanee hooks must be used within a FaneeProvider`);return e}function u(){let e=l(),[t,n]=a(e=>e+1,0);return r(()=>e.subscribe(()=>{n()}),[e]),t}function d(){let e=l(),t=p();return i(()=>({runtime:e,locale:t}),[e,t])}function f(e){let n=l(),r=u(),i=e?.locale,a=e?.namespace;return t((e,t)=>n.getT({locale:i,namespace:a})(e,t),[n,i,a,r])}function p(){let e=l();return u(),e.getLocale()}function m(){let e=l();return t(t=>e.setLocale(t),[e])}export{c as FaneeProvider,d as useFanee,p as useLocale,m as useSetLocale,f as useT};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\nimport type { FaneeRuntime } from \"@fanee/core\";\n\nconst FaneeContext = createContext<FaneeRuntime | null>(null);\n\nexport interface FaneeProviderProps {\n\t/** FaneeRuntime instance to expose to the React tree. */\n\truntime: FaneeRuntime;\n\t/** React children. */\n\tchildren: ReactNode;\n}\n\n/**\n * Provides a FaneeRuntime instance to descendant components.\n *\n * @example\n * ```tsx\n * const runtime = new FaneeRuntime().config({ currentLocale: \"en\" });\n *\n * <FaneeProvider runtime={runtime}>\n * <App />\n * </FaneeProvider>\n * ```\n */\nexport function FaneeProvider({ runtime, children }: FaneeProviderProps) {\n\treturn <FaneeContext.Provider value={runtime}>{children}</FaneeContext.Provider>;\n}\n\n/** @internal */\nexport function useRuntime(): FaneeRuntime {\n\tconst runtime = useContext(FaneeContext);\n\tif (!runtime) {\n\t\tthrow new Error(\"[fanee] Fanee hooks must be used within a FaneeProvider\");\n\t}\n\treturn runtime;\n}\n","import { useCallback, useEffect, useReducer, useMemo } from \"react\";\nimport type { Locale, MessageKey, TranslateContext, TranslateFunction } from \"@fanee/core\";\nimport { useRuntime } from \"./provider\";\n\nfunction useRuntimeVersion(): number {\n\tconst runtime = useRuntime();\n\tconst [version, bump] = useReducer((v: number) => v + 1, 0);\n\n\tuseEffect(() => {\n\t\treturn runtime.subscribe(() => {\n\t\t\tbump();\n\t\t});\n\t}, [runtime]);\n\n\treturn version;\n}\n\n/**\n * Subscribe to the Fanee runtime and access it alongside the current locale.\n *\n * @returns An object with the runtime and the active locale.\n *\n * @example\n * ```tsx\n * const { runtime, locale } = useFanee();\n * ```\n */\nexport function useFanee(): { runtime: ReturnType<typeof useRuntime>; locale: Locale } {\n\tconst runtime = useRuntime();\n\tconst locale = useLocale();\n\treturn useMemo(() => ({ runtime, locale }), [runtime, locale]);\n}\n\n/**\n * Return a translation function bound to the current runtime state and\n * an optional namespace/locale context.\n *\n * The returned function is recreated whenever the active locale, namespace,\n * or underlying resources change, so it remains reactive to runtime updates.\n *\n * @param context - Optional locale/namespace overrides.\n * @returns A `(key, vars?) => string` translate function.\n *\n * @example\n * ```tsx\n * const t = useT({ namespace: \"errors\" });\n * return <p>{t(\"not_found\")}</p>;\n * ```\n */\nexport function useT(context?: Partial<TranslateContext>): TranslateFunction {\n\tconst runtime = useRuntime();\n\tconst version = useRuntimeVersion();\n\tconst locale = context?.locale;\n\tconst namespace = context?.namespace;\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: version forces update on resource changes\n\treturn useCallback(\n\t\t(key: MessageKey, vars?: Record<string, unknown>) => {\n\t\t\tconst result = runtime.getT({ locale, namespace })(key, vars);\n\t\t\treturn result;\n\t\t},\n\t\t[runtime, locale, namespace, version]\n\t);\n}\n\n/**\n * Read the currently active locale from the runtime.\n *\n * @returns The BCP-47 locale tag.\n */\nexport function useLocale(): Locale {\n\tconst runtime = useRuntime();\n\tuseRuntimeVersion();\n\treturn runtime.getLocale();\n}\n\n/**\n * Return a setter for the runtime locale.\n *\n * @returns A function that updates the active locale.\n */\nexport function useSetLocale(): (locale: Locale) => void {\n\tconst runtime = useRuntime();\n\treturn useCallback((locale: Locale) => runtime.setLocale(locale), [runtime]);\n}\n"],"mappings":"2JAGA,MAAM,EAAe,EAAmC,IAAI,EAqB5D,SAAgB,EAAc,CAAE,UAAS,YAAgC,CACxE,OAAO,EAAC,EAAa,SAAd,CAAuB,MAAO,EAAU,UAAgC,CAAA,CAChF,CAGA,SAAgB,GAA2B,CAC1C,IAAM,EAAU,EAAW,CAAY,EACvC,GAAI,CAAC,EACJ,MAAU,MAAM,yDAAyD,EAE1E,OAAO,CACR,CC/BA,SAAS,GAA4B,CACpC,IAAM,EAAU,EAAW,EACrB,CAAC,EAAS,GAAQ,EAAY,GAAc,EAAI,EAAG,CAAC,EAQ1D,OANA,MACQ,EAAQ,cAAgB,CAC9B,EAAK,CACN,CAAC,EACC,CAAC,CAAO,CAAC,EAEL,CACR,CAYA,SAAgB,GAAuE,CACtF,IAAM,EAAU,EAAW,EACrB,EAAS,EAAU,EACzB,OAAO,OAAe,CAAE,UAAS,QAAO,GAAI,CAAC,EAAS,CAAM,CAAC,CAC9D,CAkBA,SAAgB,EAAK,EAAwD,CAC5E,IAAM,EAAU,EAAW,EACrB,EAAU,EAAkB,EAC5B,EAAS,GAAS,OAClB,EAAY,GAAS,UAG3B,OAAO,GACL,EAAiB,IACF,EAAQ,KAAK,CAAE,SAAQ,WAAU,CAAC,CAAC,CAAC,EAAK,CAC5C,EAEb,CAAC,EAAS,EAAQ,EAAW,CAAO,CACrC,CACD,CAOA,SAAgB,GAAoB,CACnC,IAAM,EAAU,EAAW,EAE3B,OADA,EAAkB,EACX,EAAQ,UAAU,CAC1B,CAOA,SAAgB,GAAyC,CACxD,IAAM,EAAU,EAAW,EAC3B,OAAO,EAAa,GAAmB,EAAQ,UAAU,CAAM,EAAG,CAAC,CAAO,CAAC,CAC5E"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fanee/react",
|
|
3
|
+
"main": "dist/index.js",
|
|
4
|
+
"module": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"version": "0.6.0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"private": false,
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"url": "https://github.com/project-cvsa/fanee"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "bunx --bun tsdown",
|
|
15
|
+
"lint": "bunx --bun biome lint",
|
|
16
|
+
"test": "bun test --preload ./tests/setup.ts",
|
|
17
|
+
"test:coverage": "bun test --preload ./tests/setup.ts --coverage",
|
|
18
|
+
"typecheck": "bunx --bun tsgo --noEmit"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@fanee/core": "workspace:*"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@testing-library/react": "^16.0.0",
|
|
28
|
+
"@types/bun": "latest",
|
|
29
|
+
"@types/react": "^19.2.14",
|
|
30
|
+
"happy-dom": "^17.0.0",
|
|
31
|
+
"react": "^19.2.6",
|
|
32
|
+
"react-dom": "^19.2.7",
|
|
33
|
+
"tsdown": "^0.22.2"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist/"
|
|
37
|
+
]
|
|
38
|
+
}
|